Changeset 25936 in vbox for trunk/src/VBox
- Timestamp:
- Jan 20, 2010 2:51:25 PM (15 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/MachineImpl.cpp
r25930 r25936 5792 5792 if (mData->mFirstSnapshot) 5793 5793 { 5794 // snapshots tree is protected by media write lock; strictly 5795 // this isn't necessary here since we're deleting the entire 5796 // machine, but otherwise we assert in Snapshot::uninit() 5797 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 5794 5798 mData->mFirstSnapshot->uninit(); 5795 5799 mData->mFirstSnapshot.setNull(); -
trunk/src/VBox/Main/SnapshotImpl.cpp
r25930 r25936 84 84 {} 85 85 86 Guiduuid;86 const Guid uuid; 87 87 Utf8Str strName; 88 88 Utf8Str strDescription; … … 149 149 m->pParent = aParent; 150 150 151 m->uuid= aId;151 unconst(m->uuid) = aId; 152 152 m->strName = aName; 153 153 m->strDescription = aDescription; … … 168 168 * Called either from FinalRelease(), by the parent when it gets destroyed, 169 169 * or by a third party when it decides this object is no more valid. 170 * 171 * Since this manipulates the snapshots tree, the caller must hold the 172 * machine lock in write mode (which protects the snapshots tree)! 170 173 */ 171 174 void Snapshot::uninit() … … 177 180 if (autoUninitSpan.uninitDone()) 178 181 return; 182 183 Assert(m->pMachine->isWriteLockOnCurrentThread()); 179 184 180 185 // uninit all children … … 211 216 * the number of callers to become 0 (it is 1 because of the AutoCaller in here). 212 217 * 213 * NOTE: this does NOT lock the snapshot, it is assumed that the caller has 214 * locked a) the machine and b) the snapshots tree in write mode! 218 * NOTE: this does NOT lock the snapshot, it is assumed that the machine state 219 * (and the snapshots tree) is protected by the caller having requested the machine 220 * lock in write mode AND the machine state must be DeletingSnapshot. 215 221 */ 216 222 void Snapshot::beginDiscard() … … 220 226 return; 221 227 222 /* for now, the snapshot must have only one child when discarded, 223 * or no children at all */ 228 // caller must have acquired the machine's write lock 229 Assert(m->pMachine->mData->mMachineState == MachineState_DeletingSnapshot); 230 Assert(m->pMachine->isWriteLockOnCurrentThread()); 231 232 // the snapshot must have only one child when discarded or no children at all 224 233 AssertReturnVoid(m->llChildren.size() <= 1); 225 234 … … 259 268 { 260 269 ComObjPtr<Snapshot> child = *it; 261 AutoWriteLock childLock(child COMMA_LOCKVAL_SRC_POS); 262 270 // no need to lock, snapshots tree is protected by machine lock 263 271 child->m->pParent = m->pParent; 264 272 if (m->pParent) … … 274 282 * parent. Used in uninit() and other places when reparenting is necessary. 275 283 * 276 * The caller must hold the snapshots tree lock!284 * The caller must hold the machine lock in write mode (which protects the snapshots tree)! 277 285 */ 278 286 void Snapshot::deparent() 279 287 { 288 Assert(m->pMachine->isWriteLockOnCurrentThread()); 289 280 290 SnapshotsList &llParent = m->pParent->m->llChildren; 281 291 for (SnapshotsList::iterator it = llParent.begin(); … … 577 587 * Searches for a snapshot with the given ID among children, grand-children, 578 588 * etc. of this snapshot. This snapshot itself is also included in the search. 579 * Caller must hold the snapshots tree lock! 589 * 590 * Caller must hold the machine lock (which protects the snapshots tree!) 580 591 */ 581 592 ComObjPtr<Snapshot> Snapshot::findChildOrSelf(IN_GUID aId) … … 586 597 AssertComRC(autoCaller.rc()); 587 598 588 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 589 599 // no need to lock, uuid is const 590 600 if (m->uuid == aId) 591 601 child = this; 592 602 else 593 603 { 594 alock.release();595 604 for (SnapshotsList::const_iterator it = m->llChildren.begin(); 596 605 it != m->llChildren.end(); … … 609 618 * grand-children, etc. of this snapshot. This snapshot itself is also included 610 619 * in the search. 611 * Caller must hold the snapshots tree lock! 620 * 621 * Caller must hold the machine lock (which protects the snapshots tree!) 612 622 */ 613 623 ComObjPtr<Snapshot> Snapshot::findChildOrSelf(const Utf8Str &aName) … … 678 688 * @param aNewPath new path (full) 679 689 * 680 * @note Locks th is object + children for writing.690 * @note Locks the machine (for the snapshots tree) + this object + children for writing. 681 691 */ 682 692 void Snapshot::updateSavedStatePaths(const char *aOldPath, const char *aNewPath) … … 2036 2046 } 2037 2047 2038 /* set the proper machine state (note: after creating a Task instance) */ 2048 // the task might start running but will block on acquiring the machine's write lock 2049 // which we acquired above; once this function leaves, the task will be unblocked; 2050 // set the proper machine state here now (note: after creating a Task instance) 2039 2051 setMachineState(MachineState_DeletingSnapshot); 2040 2052 … … 2095 2107 * SessionMachine::DeleteSnapshot, through which progress and results are reported. 2096 2108 * 2097 * @note Locks mParent + this + child objects for writing! 2109 * SessionMachine::DeleteSnapshot() has set the machne state to MachineState_DeletingSnapshot 2110 * right after creating this task. Since we block on the machine write lock at the beginning, 2111 * once that has been acquired, we can assume that the machine state is indeed that. 2112 * 2113 * @note Locks the machine + the snapshot + the media tree for writing! 2098 2114 * 2099 2115 * @param aTask Task data. … … 2118 2134 } 2119 2135 2120 /* Locking order: */ 2121 AutoMultiWriteLock3 alock(this->lockHandle(), 2122 aTask.pSnapshot->lockHandle(), 2123 &mParent->getMediaTreeLockHandle() 2124 COMMA_LOCKVAL_SRC_POS); 2125 2126 ComObjPtr<SnapshotMachine> pSnapMachine = aTask.pSnapshot->getSnapshotMachine(); 2127 /* no need to lock the snapshot machine since it is const by definiton */ 2136 MediumDiscardRecList toDiscard; 2128 2137 2129 2138 HRESULT rc = S_OK; 2130 2131 /* save the snapshot ID (for callbacks) */2132 Guid snapshotId1 = aTask.pSnapshot->getId();2133 2134 MediumDiscardRecList toDiscard;2135 2139 2136 2140 bool fMachineSettingsChanged = false; // Machine 2137 2141 bool fNeedsSaveSettings = false; // VirtualBox.xml 2138 2142 2143 Guid snapshotId1; 2144 2139 2145 try 2140 2146 { 2141 /* first pass: */ 2147 /* Locking order: */ 2148 AutoMultiWriteLock3 multiLock(this->lockHandle(), // machine 2149 aTask.pSnapshot->lockHandle(), // snapshot 2150 &mParent->getMediaTreeLockHandle() // media tree 2151 COMMA_LOCKVAL_SRC_POS); 2152 // once we have this lock, we know that SessionMachine::DeleteSnapshot() 2153 // has exited after setting the machine state to MachineState_DeletingSnapshot 2154 2155 ComObjPtr<SnapshotMachine> pSnapMachine = aTask.pSnapshot->getSnapshotMachine(); 2156 // no need to lock the snapshot machine since it is const by definiton 2157 2158 // save the snapshot ID (for callbacks) 2159 snapshotId1 = aTask.pSnapshot->getId(); 2160 2161 // first pass: 2142 2162 LogFlowThisFunc(("1: Checking hard disk merge prerequisites...\n")); 2143 2163 … … 2148 2168 // diff image holding the changes written after the snapshot was taken) 2149 2169 for (MediaData::AttachmentList::iterator it = pSnapMachine->mMediaData->mAttachments.begin(); 2150 it != pSnapMachine->mMediaData->mAttachments.end();2151 ++it)2170 it != pSnapMachine->mMediaData->mAttachments.end(); 2171 ++it) 2152 2172 { 2153 2173 ComObjPtr<MediumAttachment> &pAttach = *it; … … 2251 2271 } 2252 2272 2273 // we can release the lock now since the machine state is MachineState_DeletingSnapshot 2274 multiLock.release(); 2275 2253 2276 /* Now we checked that we can successfully merge all normal hard disks 2254 2277 * (unless a runtime error like end-of-disc happens). Prior to … … 2262 2285 2263 2286 { 2287 // saveAllSnapshots() needs a machine lock, and the snapshots 2288 // tree is protected by the machine lock as well 2289 AutoWriteLock machineLock(this COMMA_LOCKVAL_SRC_POS); 2290 2264 2291 ComObjPtr<Snapshot> parentSnapshot = aTask.pSnapshot->getParent(); 2265 2292 Utf8Str stateFilePath = aTask.pSnapshot->stateFilePath(); 2266 2293 2267 / *Note that discarding the snapshot will deassociate it from the2268 * hard disks which will allow the merge+delete operation for them*/2294 // Note that discarding the snapshot will deassociate it from the 2295 // hard disks which will allow the merge+delete operation for them 2269 2296 aTask.pSnapshot->beginDiscard(); 2270 2297 aTask.pSnapshot->uninit(); 2298 // this requests the machine lock in turn when deleting all the children 2299 // in the snapshot machine 2271 2300 2272 2301 rc = saveAllSnapshots(); 2302 machineLock.release(); 2273 2303 if (FAILED(rc)) throw rc; 2274 2304 2275 /// @todo (dmik)2276 // if we implement some warning mechanism later, we'll have2277 // to return a warning if the state file path cannot be deleted2278 2305 if (!stateFilePath.isEmpty()) 2279 2306 { … … 2302 2329 LogFlowThisFunc(("3: Performing actual hard disk merging...\n")); 2303 2330 2304 /* leave the locks before the potentially lengthy operation */2305 alock.leave();2306 2307 2331 /// @todo NEWMEDIA turn the following errors into warnings because the 2308 2332 /// snapshot itself has been already deleted (and interpret these 2309 2333 /// warnings properly on the GUI side) 2310 2311 2334 for (MediumDiscardRecList::iterator it = toDiscard.begin(); 2312 2335 it != toDiscard.end();) … … 2321 2344 it = toDiscard.erase(it); 2322 2345 } 2323 2324 LogFlowThisFunc(("Entering locks again...\n"));2325 alock.enter();2326 LogFlowThisFunc(("Entered locks OK\n"));2327 2346 } 2328 2347 catch (HRESULT aRC) { rc = aRC; } … … 2332 2351 HRESULT rc2 = S_OK; 2333 2352 2334 /* un-prepare the remaining hard disks */ 2353 AutoMultiWriteLock2 multiLock(this->lockHandle(), // machine 2354 &mParent->getMediaTreeLockHandle() // media tree 2355 COMMA_LOCKVAL_SRC_POS); 2356 2357 // un-prepare the remaining hard disks 2335 2358 for (MediumDiscardRecList::const_iterator it = toDiscard.begin(); 2336 it != toDiscard.end(); ++it) 2359 it != toDiscard.end(); 2360 ++it) 2337 2361 { 2338 it->hd->cancelDiscard 2362 it->hd->cancelDiscard(it->chain); 2339 2363 2340 2364 if (!it->replaceHd.isNull()) 2341 2365 { 2342 /* undo hard disk replacement */2343 2344 2366 rc2 = it->replaceHd->attachTo(mData->mUuid, it->snapshotId); 2345 2367 AssertComRC(rc2); 2346 2368 2347 rc2 = it->hd->detachFrom 2369 rc2 = it->hd->detachFrom(mData->mUuid, it->snapshotId); 2348 2370 AssertComRC(rc2); 2349 2371 … … 2353 2375 } 2354 2376 } 2355 2356 alock.release();2357 2377 2358 2378 // whether we were successful or not, we need to set the machine … … 2376 2396 if (fMachineSettingsChanged) 2377 2397 { 2378 alock.acquire();2398 AutoWriteLock machineLock(this COMMA_LOCKVAL_SRC_POS); 2379 2399 saveSettings(SaveS_InformCallbacksAnyway); 2380 2400 }
Note:
See TracChangeset
for help on using the changeset viewer.