Changeset 106832 in vbox for trunk/src/VBox
- Timestamp:
- Nov 5, 2024 11:35:04 AM (3 months ago)
- Location:
- trunk/src/VBox/Main/src-server
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-server/MachineImpl.cpp
r106061 r106832 10582 10582 AssertComRCReturn(autoCaller.hrc(), autoCaller.hrc()); 10583 10583 10584 AutoMultiWriteLock2 alock(this->lockHandle(), 10585 &mParent->i_getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS); 10584 /* We can't use AutoMultiWriteLock2 here as some error code paths acquire 10585 * the media tree lock which means we need to be able to drop the media 10586 * tree lock individually in those cases. */ 10587 AutoWriteLock aMachineLock(this->lockHandle() COMMA_LOCKVAL_SRC_POS); 10588 AutoWriteLock aTreeLock(&mParent->i_getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS); 10586 10589 10587 10590 /* must be in a protective state because we release the lock below */ … … 10621 10624 10622 10625 MediumLockList *pMediumLockList(new MediumLockList()); 10623 alock.release(); 10626 aTreeLock.release(); 10627 aMachineLock.release(); 10624 10628 hrc = pMedium->i_createMediumLockList(true /* fFailIfInaccessible */, 10625 10629 NULL /* pToLockWrite */, … … 10627 10631 NULL, 10628 10632 *pMediumLockList); 10629 alock.acquire(); 10633 aMachineLock.acquire(); 10634 aTreeLock.acquire(); 10630 10635 if (FAILED(hrc)) 10631 10636 { … … 10640 10645 10641 10646 /* Now lock all media. If this fails, nothing is locked. */ 10642 alock.release(); 10647 aTreeLock.release(); 10648 aMachineLock.release(); 10643 10649 hrc = lockedMediaMap->Lock(); 10644 alock.acquire(); 10650 aMachineLock.acquire(); 10651 aTreeLock.acquire(); 10645 10652 if (FAILED(hrc)) 10646 10653 throw setError(hrc, tr("Locking of attached media failed")); … … 10711 10718 uuidRegistryParent, 10712 10719 DeviceType_HardDisk); 10713 if (FAILED(hrc)) throw hrc; 10720 if (FAILED(hrc)) 10721 { 10722 /* Throwing an exception here causes the 'diff' object to go out of scope 10723 * which triggers its destructor (ComObjPtr<Medium>::~ComObjPtr) which will 10724 * ultimately call Medium::uninit() which acquires the media tree lock 10725 * (VirtualBox::i_getMediaTreeLockHandle()) so drop the media tree lock here. */ 10726 aTreeLock.release(); 10727 throw hrc; 10728 } 10714 10729 10715 10730 /** @todo r=bird: How is the locking and diff image cleaned up if we fail before … … 10724 10739 if (aOnline) 10725 10740 { 10726 alock.release(); 10741 aTreeLock.release(); 10742 aMachineLock.release(); 10727 10743 /* The currently attached medium will be read-only, change 10728 10744 * the lock type to read. */ 10729 10745 hrc = pMediumLockList->Update(pMedium, false); 10730 alock.acquire(); 10746 aMachineLock.acquire(); 10747 aTreeLock.acquire(); 10731 10748 AssertComRCThrowRC(hrc); 10732 10749 } 10733 10750 10734 10751 /* release the locks before the potentially lengthy operation */ 10735 alock.release(); 10752 aTreeLock.release(); 10753 aMachineLock.release(); 10736 10754 hrc = pMedium->i_createDiffStorage(diff, 10737 10755 pMedium->i_getPreferredDiffVariant(), … … 10740 10758 true /* aWait */, 10741 10759 false /* aNotify */); 10742 alock.acquire(); 10743 if (FAILED(hrc)) throw hrc; 10760 aMachineLock.acquire(); 10761 aTreeLock.acquire(); 10762 if (FAILED(hrc)) 10763 { 10764 /* As above, 'diff' will go out of scope via the 'throw' here resulting in 10765 * Medium::uninit() being called which acquires the media tree lock. */ 10766 aTreeLock.release(); 10767 throw hrc; 10768 } 10744 10769 10745 10770 /* actual lock list update is done in Machine::i_commitMedia */ … … 10764 10789 pAtt->i_getHotPluggable(), 10765 10790 pAtt->i_getBandwidthGroup()); 10766 if (FAILED(hrc)) throw hrc; 10791 if (FAILED(hrc)) { 10792 /* As above, 'diff' will go out of scope via the 'throw' here resulting in 10793 * Medium::uninit() being called which acquires the media tree lock. */ 10794 aTreeLock.release(); 10795 throw hrc; 10796 } 10767 10797 10768 10798 hrc = lockedMediaMap->ReplaceKey(pAtt, attachment); … … 12646 12676 #endif /* VBOX_WITH_USB */ 12647 12677 12648 // we need to lock this object in uninit() because the lock is shared 12649 // with mPeer (as well as data we modify below). mParent lock is needed 12650 // by several calls to it. 12651 AutoMultiWriteLock2 multilock(mParent, this COMMA_LOCKVAL_SRC_POS); 12678 /* We need to lock this object in uninit() because the lock is shared 12679 * with mPeer (as well as data we modify below). mParent lock is needed 12680 * by several calls to it. 12681 * We can't use AutoMultiWriteLock2 here as some error code paths 12682 * acquire the machine lock so we need to be able to drop the machine 12683 * lock individually in those cases. */ 12684 AutoWriteLock aVBoxLock(mParent COMMA_LOCKVAL_SRC_POS); 12685 AutoWriteLock aMachineLock(this COMMA_LOCKVAL_SRC_POS); 12652 12686 12653 12687 #ifdef VBOX_WITH_RESOURCE_USAGE_API … … 12690 12724 { 12691 12725 Log1WarningThisFunc(("Discarding unsaved settings changes!\n")); 12692 i_rollback(false /* aNotify */); 12726 aMachineLock.release(); 12727 discardSettings(); 12728 mParent->i_unmarkRegistryModified(i_getId()); 12729 aMachineLock.acquire(); 12693 12730 } 12694 12731 … … 12718 12755 ComPtr<IInternalSessionControl> pControl = *it; 12719 12756 mData->mSession.mRemoteControls.erase(it); 12720 multilock.release(); 12757 aMachineLock.release(); 12758 aVBoxLock.release(); 12721 12759 LogFlowThisFunc((" Calling remoteControl->Uninitialize()...\n")); 12722 12760 HRESULT hrc = pControl->Uninitialize(); … … 12724 12762 if (FAILED(hrc)) 12725 12763 Log1WarningThisFunc(("Forgot to close the remote session?\n")); 12726 multilock.acquire(); 12764 aVBoxLock.acquire(); 12765 aMachineLock.acquire(); 12727 12766 } 12728 12767 mData->mSession.mRemoteControls.clear(); … … 12750 12789 if (SUCCEEDED(hrc)) 12751 12790 { 12752 multilock.release(); 12791 aMachineLock.release(); 12792 aVBoxLock.release(); 12753 12793 Utf8Str strName(name); 12754 12794 LogRel(("VM '%s' stops using NAT network '%s'\n", 12755 12795 mUserData->s.strName.c_str(), strName.c_str())); 12756 12796 mParent->i_natNetworkRefDec(strName); 12757 multilock.acquire(); 12797 aVBoxLock.acquire(); 12798 aMachineLock.acquire(); 12758 12799 } 12759 12800 } … … 12834 12875 mData.free(); 12835 12876 12836 /* release the exclusive lock before setting the below two to NULL */ 12837 multilock.release(); 12877 /* release the exclusive locks before setting the below two to NULL */ 12878 aMachineLock.release(); 12879 aVBoxLock.release(); 12838 12880 12839 12881 unconst(mParent) = NULL; -
trunk/src/VBox/Main/src-server/MediumImpl.cpp
r106077 r106832 4617 4617 AssertReturn(aMachineId.isValid(), E_FAIL); 4618 4618 4619 LogFlowThisFunc(("ENTER, aMachineId: {%RTuuid}, aSnapshotId: {%RTuuid}\n", aMachineId.raw(), aSnapshotId.raw()));4620 4621 4619 AutoCaller autoCaller(this); 4622 4620 AssertComRCReturnRC(autoCaller.hrc()); 4623 4621 4624 4622 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 4623 4624 LogFlowThisFunc(("ENTER: medium: '%s' aMachineId: {%RTuuid}, aSnapshotId: {%RTuuid}\n", 4625 i_getLocationFull().c_str(), aMachineId.raw(), aSnapshotId.raw())); 4625 4626 4626 4627 switch (m->state) … … 4744 4745 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 4745 4746 4747 LogFlowThisFunc(("ENTER: medium: '%s' aMachineId: {%RTuuid}, aSnapshotId: {%RTuuid}\n", 4748 i_getLocationFull().c_str(), aMachineId.raw(), aSnapshotId.raw())); 4749 4746 4750 BackRefList::iterator it = 4747 4751 std::find_if(m->backRefs.begin(), m->backRefs.end(), … … 4749 4753 AssertReturn(it != m->backRefs.end(), E_FAIL); 4750 4754 4755 bool fDvd = false; 4756 { 4757 AutoReadLock arlock(this COMMA_LOCKVAL_SRC_POS); 4758 /* 4759 * Check the medium is DVD and readonly. It's for the case if DVD 4760 * will be able to be writable sometime in the future. 4761 */ 4762 fDvd = m->type == MediumType_Readonly && m->devType == DeviceType_DVD; 4763 } 4764 4751 4765 if (aSnapshotId.isZero()) 4752 4766 { 4767 /* Attached removable media which are part of a snapshot can be added to a 4768 * back reference more than once (as described above in i_addBackReference()) 4769 * so we need to balance out the reference counting for DVDs here. */ 4770 if (fDvd && it->iRefCnt > 1) 4771 it->iRefCnt--; 4753 4772 it->iRefCnt--; 4754 4773 if (it->iRefCnt > 0) 4755 4774 return S_OK; 4756 4775 4757 /* remove the current state attachment */ 4776 /* Mark the medium as no longer in use by the current machine although it 4777 * may still be included in one or more snapshots (it->llSnapshotIds). */ 4758 4778 it->fInCurState = false; 4759 4779 } … … 4773 4793 4774 4794 it->llSnapshotIds.erase(jt); 4795 4796 /* The BackRef() constructor in i_addBackReference() creates back references 4797 * for attached hard disk mediums associated with a snapshot with the reference 4798 * count set to '1' and fInCurState=false before adding the snapshot to 4799 * it->llSnapshotIds. When removing that snapshot reference here we need to 4800 * decrement the reference count since there won't be a separate 4801 * i_removeBackReference() call with aSnapshotId.isZero() since this hard disk 4802 * medium is only associated with this snapshot. Removable media like DVDs 4803 * associated with a snapshot on the other hand can be attached twice, once for 4804 * the snapshot and once for the machine (aSnapshotId.isZero()=true) and their 4805 * reference counting is balanced out in the machine case above. */ 4806 if (!fDvd && it->fInCurState == false && it->iRefCnt == 1 && it->llSnapshotIds.size() == 0) 4807 it->iRefCnt--; 4775 4808 } 4776 4809 4777 4810 /* if the backref becomes empty, remove it */ 4778 if (it->fInCurState == false && it-> llSnapshotIds.size() == 0)4811 if (it->fInCurState == false && it->iRefCnt == 0 && it->llSnapshotIds.size() == 0) 4779 4812 m->backRefs.erase(it); 4780 4813 … … 4868 4901 { 4869 4902 const BackRef &ref = *it2; 4870 LogFlowThisFunc((" Backref from machine {%RTuuid} (fInCurState: %d, iRefCnt:%d)\n", ref.machineId.raw(), ref.fInCurState, ref.iRefCnt));4903 LogFlowThisFunc((" Backref from machine={%RTuuid} (fInCurState=%d, iRefCnt=%d)\n", ref.machineId.raw(), ref.fInCurState, ref.iRefCnt)); 4871 4904 4872 4905 for (std::list<SnapshotRef>::const_iterator jt2 = it2->llSnapshotIds.begin(); … … 4875 4908 { 4876 4909 const Guid &id = jt2->snapshotId; 4877 LogFlowThisFunc((" Backref from snapshot {%RTuuid} (iRefCnt =%d)\n", id.raw(), jt2->iRefCnt));4910 LogFlowThisFunc((" Backref from snapshot={%RTuuid} (iRefCnt=%d)\n", id.raw(), jt2->iRefCnt)); 4878 4911 } 4879 4912 } -
trunk/src/VBox/Main/src-server/SnapshotImpl.cpp
r106061 r106832 1859 1859 mMediumAttachments.backup(); 1860 1860 1861 /* We need to set fBeganTakingSnapshot=true here to handle not only the 1862 * scenario of i_createImplicitDiffs() succeeding but also the failure case 1863 * since differencing hard disks can still be created which then need to be 1864 * cleaned up and deleted via i_finishTakingSnapshot() below. */ 1865 fBeganTakingSnapshot = true; 1866 1861 1867 alock.release(); 1862 1868 /* create new differencing hard disks and attach them to this machine */ … … 1864 1870 1, // operation weight; must be the same as in Machine::TakeSnapshot() 1865 1871 task.m_fTakingSnapshotOnline); 1872 /* If i_createImplicitDiffs() fails the 'catch' block below calls 1873 * Snapshot::uninit() which requires the machine to be write locked 1874 * so reacquire alock here before testing for failure. */ 1875 alock.acquire(); 1866 1876 if (FAILED(hrc)) 1867 1877 throw hrc; 1868 alock.acquire();1869 1878 1870 1879 // MUST NOT save the settings or the media registry here, because 1871 1880 // this causes trouble with rolling back settings if the user cancels 1872 1881 // taking the snapshot after the diff images have been created. 1873 1874 fBeganTakingSnapshot = true;1875 1882 1876 1883 // STEP 3: save the VM state (if online) … … 2608 2615 ErrorInfoKeeper eik; 2609 2616 2617 /* If any MediumAttachments have been modified then Machine::i_rollback() will 2618 * go through Machine::i_rollbackMedia() -> Machine::i_deleteImplicitDiffs() -> 2619 * Medium::i_deleteStorage() -> Medium::i_markRegistriesModified() -> 2620 * VirtualBox::i_markRegistryModified() -> VirtualBox::i_findMachine() which 2621 * attempts to acquire the Machine object lock for 'VirtualBox::allMachines' but 2622 * the locking order when accessing the MachinesOList type (aka ObjectsList<Machine>) 2623 * requires that the machines lock list (LOCKCLASS_LISTOFMACHINES) be 2624 * acquired first and then the Machine object lock (LOCKCLASS_MACHINEOBJECT). 2625 */ 2626 AutoReadLock alockMachines(mParent->i_getMachinesListLockHandle() COMMA_LOCKVAL_SRC_POS); 2627 2610 2628 /* undo all changes on failure */ 2611 2629 i_rollback(false /* aNotify */); 2612 2613 2630 } 2614 2631
Note:
See TracChangeset
for help on using the changeset viewer.