Changeset 48297 in vbox for trunk/src/VBox/Main/src-server/SnapshotImpl.cpp
- Timestamp:
- Sep 5, 2013 9:57:44 AM (12 years ago)
- svn:sync-xref-src-repo-rev:
- 88714
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-server/SnapshotImpl.cpp
r47401 r48297 2104 2104 2105 2105 /** 2106 * Implementation for IInternalMachineControl:: deleteSnapshot().2106 * Implementation for IInternalMachineControl::DeleteSnapshot(). 2107 2107 * 2108 2108 * Gets called from Console::DeleteSnapshot(), and that's basically the … … 2294 2294 bool fMergeForward, 2295 2295 const ComObjPtr<Medium> &aParentForTarget, 2296 const MediaList &aChildrenToReparent,2296 MediumLockList *aChildrenToReparent, 2297 2297 bool fNeedsOnlineMerge, 2298 MediumLockList *aMediumLockList) 2298 MediumLockList *aMediumLockList, 2299 const ComPtr<IToken> &aHDLockToken) 2299 2300 : mpHD(aHd), 2300 2301 mpSource(aSource), … … 2303 2304 mfMergeForward(fMergeForward), 2304 2305 mpParentForTarget(aParentForTarget), 2305 m ChildrenToReparent(aChildrenToReparent),2306 mpChildrenToReparent(aChildrenToReparent), 2306 2307 mfNeedsOnlineMerge(fNeedsOnlineMerge), 2307 mpMediumLockList(aMediumLockList) 2308 mpMediumLockList(aMediumLockList), 2309 mpHDLockToken(aHDLockToken) 2308 2310 {} 2309 2311 … … 2314 2316 bool fMergeForward, 2315 2317 const ComObjPtr<Medium> &aParentForTarget, 2316 const MediaList &aChildrenToReparent,2318 MediumLockList *aChildrenToReparent, 2317 2319 bool fNeedsOnlineMerge, 2318 2320 MediumLockList *aMediumLockList, 2321 const ComPtr<IToken> &aHDLockToken, 2319 2322 const Guid &aMachineId, 2320 2323 const Guid &aSnapshotId) … … 2325 2328 mfMergeForward(fMergeForward), 2326 2329 mpParentForTarget(aParentForTarget), 2327 m ChildrenToReparent(aChildrenToReparent),2330 mpChildrenToReparent(aChildrenToReparent), 2328 2331 mfNeedsOnlineMerge(fNeedsOnlineMerge), 2329 2332 mpMediumLockList(aMediumLockList), 2333 mpHDLockToken(aHDLockToken), 2330 2334 mMachineId(aMachineId), 2331 2335 mSnapshotId(aSnapshotId) … … 2338 2342 bool mfMergeForward; 2339 2343 ComObjPtr<Medium> mpParentForTarget; 2340 Medi aList mChildrenToReparent;2344 MediumLockList *mpChildrenToReparent; 2341 2345 bool mfNeedsOnlineMerge; 2342 2346 MediumLockList *mpMediumLockList; 2347 /** optional lock token, used only in case mpHD is not merged/deleted */ 2348 ComPtr<IToken> mpHDLockToken; 2343 2349 /* these are for reattaching the hard disk in case of a failure: */ 2344 2350 Guid mMachineId; … … 2450 2456 bool fMergeForward = false; 2451 2457 ComObjPtr<Medium> pParentForTarget; 2452 Medi aList childrenToReparent;2458 MediumLockList *pChildrenToReparent = NULL; 2453 2459 bool fNeedsOnlineMerge = false; 2454 2460 bool fOnlineMergePossible = aTask.m_fDeleteOnline; 2455 2461 MediumLockList *pMediumLockList = NULL; 2456 2462 MediumLockList *pVMMALockList = NULL; 2463 ComPtr<IToken> pHDLockToken; 2457 2464 ComObjPtr<MediumAttachment> pOnlineMediumAttachment; 2458 2465 if (fOnlineMergePossible) … … 2487 2494 pVMMALockList, pSource, pTarget, 2488 2495 fMergeForward, pParentForTarget, 2489 childrenToReparent,2496 pChildrenToReparent, 2490 2497 fNeedsOnlineMerge, 2491 pMediumLockList); 2498 pMediumLockList, 2499 pHDLockToken); 2492 2500 treeLock.acquire(); 2493 2501 if (FAILED(rc)) … … 2545 2553 fMergeForward, 2546 2554 pParentForTarget, 2547 childrenToReparent,2555 pChildrenToReparent, 2548 2556 fNeedsOnlineMerge, 2549 2557 pMediumLockList, 2558 pHDLockToken, 2550 2559 replaceMachineId, 2551 2560 replaceSnapshotId)); … … 2556 2565 fMergeForward, 2557 2566 pParentForTarget, 2558 childrenToReparent,2567 pChildrenToReparent, 2559 2568 fNeedsOnlineMerge, 2560 pMediumLockList)); 2569 pMediumLockList, 2570 pHDLockToken)); 2561 2571 } 2562 2572 … … 2756 2766 if (it->mfNeedsOnlineMerge) 2757 2767 { 2768 // Put the medium merge information (MediumDeleteRec) where 2769 // SessionMachine::FinishOnlineMergeMedium can get at it. 2770 // This callback will arrive while onlineMergeMedium is 2771 // still executing, and there can't be two tasks. 2772 mConsoleTaskData.mDeleteSnapshotInfo = (void *)&(*it); 2758 2773 // online medium merge, in the direction decided earlier 2759 2774 rc = onlineMergeMedium(it->mpOnlineMediumAttachment, … … 2762 2777 it->mfMergeForward, 2763 2778 it->mpParentForTarget, 2764 it->m ChildrenToReparent,2779 it->mpChildrenToReparent, 2765 2780 it->mpMediumLockList, 2766 2781 aTask.pProgress, 2767 2782 &fNeedsSave); 2783 mConsoleTaskData.mDeleteSnapshotInfo = NULL; 2768 2784 } 2769 2785 else … … 2773 2789 it->mfMergeForward, 2774 2790 it->mpParentForTarget, 2775 it->m ChildrenToReparent,2791 it->mpChildrenToReparent, 2776 2792 it->mpMediumLockList, 2777 2793 &aTask.pProgress, … … 2912 2928 { 2913 2929 cancelDeleteSnapshotMedium(it->mpHD, it->mpSource, 2914 it->m ChildrenToReparent,2930 it->mpChildrenToReparent, 2915 2931 it->mfNeedsOnlineMerge, 2916 it->mpMediumLockList, it->m MachineId,2917 it->m SnapshotId);2932 it->mpMediumLockList, it->mpHDLockToken, 2933 it->mMachineId, it->mSnapshotId); 2918 2934 } 2919 2935 } … … 2966 2982 * @param aMergeForward Merge direction decision (out). 2967 2983 * @param aParentForTarget New parent if target needs to be reparented (out). 2968 * @param aChildrenToReparent Children which have to be reparented to the2969 * target (out).2984 * @param aChildrenToReparent MediumLockList with children which have to be 2985 * reparented to the target (out). 2970 2986 * @param fNeedsOnlineMerge Whether this merge needs to be done online (out). 2971 2987 * If this is set to @a true then the @a aVMMALockList … … 2974 2990 * @param aMediumLockList Where to store the created medium lock list (may 2975 2991 * return NULL if no real merge is necessary). 2992 * @param aHDLockToken Where to store the write lock token for aHD, in case 2993 * it is not merged or deleted (out). 2976 2994 * 2977 2995 * @note Caller must hold media tree lock for writing. This locks this object … … 2987 3005 bool &aMergeForward, 2988 3006 ComObjPtr<Medium> &aParentForTarget, 2989 Medi aList&aChildrenToReparent,3007 MediumLockList * &aChildrenToReparent, 2990 3008 bool &fNeedsOnlineMerge, 2991 MediumLockList * &aMediumLockList) 3009 MediumLockList * &aMediumLockList, 3010 ComPtr<IToken> &aHDLockToken) 2992 3011 { 2993 3012 Assert(!mParent->getMediaTreeLockHandle().isWriteLockOnCurrentThread()); … … 3002 3021 && type != MediumType_Readonly, E_FAIL); 3003 3022 3023 aChildrenToReparent = NULL; 3004 3024 aMediumLockList = NULL; 3005 3025 fNeedsOnlineMerge = false; … … 3018 3038 * is completed */ 3019 3039 alock.release(); 3020 return aHD->LockWrite( NULL);3040 return aHD->LockWrite(aHDLockToken.asOutParam()); 3021 3041 } 3022 3042 … … 3049 3069 childLock.release(); 3050 3070 alock.release(); 3051 return aHD->LockWrite( NULL);3071 return aHD->LockWrite(aHDLockToken.asOutParam()); 3052 3072 } 3053 3073 … … 3146 3166 { 3147 3167 /* we will lock the children of the source for reparenting */ 3148 for (MediaList::const_iterator it = aChildrenToReparent.begin(); 3149 it != aChildrenToReparent.end(); 3150 ++it) 3168 if (aChildrenToReparent && !aChildrenToReparent->IsEmpty()) 3151 3169 { 3152 ComObjPtr<Medium> pMedium = *it; 3153 AutoReadLock mediumLock(pMedium COMMA_LOCKVAL_SRC_POS); 3154 if (pMedium->getState() == MediumState_Created) 3170 /* Cannot just call aChildrenToReparent->Lock(), as one of 3171 * the children is the one under which the current state of 3172 * the VM is located, and this means it is already locked 3173 * (for reading). Note that no special unlocking is needed, 3174 * because cancelMergeTo will unlock everything locked in 3175 * its context (using the unlock on destruction), and both 3176 * cancelDeleteSnapshotMedium (in case something fails) and 3177 * FinishOnlineMergeMedium re-define the read/write lock 3178 * state of everything which the VM need, search for the 3179 * UpdateLock method calls. */ 3180 childLock.release(); 3181 alock.release(); 3182 rc = aChildrenToReparent->Lock(true /* fSkipOverLockedMedia */); 3183 alock.acquire(); 3184 childLock.acquire(); 3185 MediumLockList::Base::iterator childrenToReparentBegin = aChildrenToReparent->GetBegin(); 3186 MediumLockList::Base::iterator childrenToReparentEnd = aChildrenToReparent->GetEnd(); 3187 for (MediumLockList::Base::iterator it = childrenToReparentBegin; 3188 it != childrenToReparentEnd; 3189 ++it) 3155 3190 { 3156 mediumLock.release(); 3157 childLock.release(); 3158 alock.release(); 3159 rc = pMedium->LockWrite(NULL); 3160 alock.acquire(); 3161 childLock.acquire(); 3162 mediumLock.acquire(); 3163 if (FAILED(rc)) 3164 throw rc; 3165 } 3166 else 3167 { 3168 mediumLock.release(); 3169 childLock.release(); 3170 alock.release(); 3171 rc = aVMMALockList->Update(pMedium, true); 3172 alock.acquire(); 3173 childLock.acquire(); 3174 mediumLock.acquire(); 3175 if (FAILED(rc)) 3191 ComObjPtr<Medium> pMedium = it->GetMedium(); 3192 AutoReadLock mediumLock(pMedium COMMA_LOCKVAL_SRC_POS); 3193 if (!it->IsLocked()) 3176 3194 { 3177 3195 mediumLock.release(); 3178 3196 childLock.release(); 3179 3197 alock.release(); 3180 rc = pMedium->LockWrite(NULL);3198 rc = aVMMALockList->Update(pMedium, true); 3181 3199 alock.acquire(); 3182 3200 childLock.acquire(); … … 3265 3283 * @param fNeedsOnlineMerge Whether this merge needs to be done online. 3266 3284 * @param aMediumLockList Medium locks to cancel. 3285 * @param aHDLockToken Optional write lock token for aHD. 3267 3286 * @param aMachineId Machine id to attach the medium to. 3268 3287 * @param aSnapshotId Snapshot id to attach the medium to. … … 3272 3291 void SessionMachine::cancelDeleteSnapshotMedium(const ComObjPtr<Medium> &aHD, 3273 3292 const ComObjPtr<Medium> &aSource, 3274 const MediaList &aChildrenToReparent,3293 MediumLockList *aChildrenToReparent, 3275 3294 bool fNeedsOnlineMerge, 3276 3295 MediumLockList *aMediumLockList, 3296 const ComPtr<IToken> &aHDLockToken, 3277 3297 const Guid &aMachineId, 3278 3298 const Guid &aSnapshotId) … … 3286 3306 if (aHD->getParent().isNull()) 3287 3307 { 3288 HRESULT rc = aHD->UnlockWrite(NULL); 3289 AssertComRC(rc); 3308 Assert(!aHDLockToken.isNull()); 3309 if (!aHDLockToken.isNull()) 3310 { 3311 HRESULT rc = aHDLockToken->Abandon(); 3312 AssertComRC(rc); 3313 } 3290 3314 } 3291 3315 else … … 3354 3378 * @param aMergeForward Merge direction. 3355 3379 * @param aParentForTarget New parent if target needs to be reparented. 3356 * @param aChildrenToReparent Children which have to be reparented to the3357 * target.3380 * @param aChildrenToReparent Medium lock list with children which have to be 3381 * reparented to the target. 3358 3382 * @param aMediumLockList Where to store the created medium lock list (may 3359 3383 * return NULL if no real merge is necessary). … … 3366 3390 bool fMergeForward, 3367 3391 const ComObjPtr<Medium> &aParentForTarget, 3368 const MediaList &aChildrenToReparent,3392 MediumLockList *aChildrenToReparent, 3369 3393 MediumLockList *aMediumLockList, 3370 3394 ComObjPtr<Progress> &aProgress, … … 3415 3439 && uTargetIdx != (unsigned)-1, E_FAIL); 3416 3440 3417 // For forward merges, tell the VM what images need to have their3418 // parent UUID updated. This cannot be done in VBoxSVC, as opening3419 // the required parent images is not safe while the VM is running.3420 // For backward merges this will be simply an array of size 0.3421 com::SafeIfaceArray<IMedium> childrenToReparent(aChildrenToReparent);3422 3423 3441 ComPtr<IInternalSessionControl> directControl; 3424 3442 { … … 3436 3454 rc = directControl->OnlineMergeMedium(aMediumAttachment, 3437 3455 uSourceIdx, uTargetIdx, 3438 aSource, aTarget,3439 fMergeForward, aParentForTarget,3440 ComSafeArrayAsInParam(childrenToReparent),3441 3456 aProgress); 3442 3457 if (FAILED(rc)) … … 3454 3469 3455 3470 /** 3456 * Implementation for IInternalMachineControl:: finishOnlineMergeMedium().3471 * Implementation for IInternalMachineControl::FinishOnlineMergeMedium(). 3457 3472 * 3458 3473 * Gets called after the successful completion of an online merge from … … 3463 3478 * can continue with the updated state of the medium chain. 3464 3479 */ 3465 STDMETHODIMP SessionMachine::FinishOnlineMergeMedium(IMediumAttachment *aMediumAttachment, 3466 IMedium *aSource, 3467 IMedium *aTarget, 3468 BOOL aMergeForward, 3469 IMedium *aParentForTarget, 3470 ComSafeArrayIn(IMedium *, aChildrenToReparent)) 3480 STDMETHODIMP SessionMachine::FinishOnlineMergeMedium() 3471 3481 { 3472 3482 HRESULT rc = S_OK; 3473 ComObjPtr<Medium> pSource(static_cast<Medium *>(aSource)); 3474 ComObjPtr<Medium> pTarget(static_cast<Medium *>(aTarget)); 3475 ComObjPtr<Medium> pParentForTarget(static_cast<Medium *>(aParentForTarget)); 3483 MediumDeleteRec *pDeleteRec = (MediumDeleteRec *)mConsoleTaskData.mDeleteSnapshotInfo; 3484 AssertReturn(pDeleteRec, E_FAIL); 3476 3485 bool fSourceHasChildren = false; 3477 3486 … … 3486 3495 ComObjPtr<Medium> targetChild; 3487 3496 3488 if ( aMergeForward)3497 if (pDeleteRec->mfMergeForward) 3489 3498 { 3490 3499 // first, unregister the target since it may become a base 3491 3500 // hard disk which needs re-registration 3492 rc = mParent->unregisterMedium(p Target);3501 rc = mParent->unregisterMedium(pDeleteRec->mpTarget); 3493 3502 AssertComRC(rc); 3494 3503 3495 3504 // then, reparent it and disconnect the deleted branch at 3496 3505 // both ends (chain->parent() is source's parent) 3497 p Target->deparent();3498 p Target->setParent(pParentForTarget);3499 if (p ParentForTarget)3500 p Source->deparent();3506 pDeleteRec->mpTarget->deparent(); 3507 pDeleteRec->mpTarget->setParent(pDeleteRec->mpParentForTarget); 3508 if (pDeleteRec->mpParentForTarget) 3509 pDeleteRec->mpSource->deparent(); 3501 3510 3502 3511 // then, register again 3503 rc = mParent->registerMedium(p Target, &pTarget, DeviceType_HardDisk);3512 rc = mParent->registerMedium(pDeleteRec->mpTarget, &pDeleteRec->mpTarget, DeviceType_HardDisk); 3504 3513 AssertComRC(rc); 3505 3514 } 3506 3515 else 3507 3516 { 3508 Assert(p Target->getChildren().size() == 1);3509 targetChild = p Target->getChildren().front();3517 Assert(pDeleteRec->mpTarget->getChildren().size() == 1); 3518 targetChild = pDeleteRec->mpTarget->getChildren().front(); 3510 3519 3511 3520 // disconnect the deleted branch at the elder end … … 3514 3523 // Update parent UUIDs of the source's children, reparent them and 3515 3524 // disconnect the deleted branch at the younger end 3516 com::SafeIfaceArray<IMedium> childrenToReparent(ComSafeArrayInArg(aChildrenToReparent)); 3517 if (childrenToReparent.size() > 0) 3525 if (pDeleteRec->mpChildrenToReparent && !pDeleteRec->mpChildrenToReparent->IsEmpty()) 3518 3526 { 3519 3527 fSourceHasChildren = true; … … 3523 3531 // we must continue. The worst possible result is that the images 3524 3532 // need manual fixing via VBoxManage to adjust the parent UUID. 3525 MediaList toReparent; 3526 for (size_t i = 0; i < childrenToReparent.size(); i++) 3533 treeLock.release(); 3534 pDeleteRec->mpTarget->fixParentUuidOfChildren(pDeleteRec->mpChildrenToReparent); 3535 // The childen are still write locked, unlock them now and don't 3536 // rely on the destructor doing it very late. 3537 pDeleteRec->mpChildrenToReparent->Unlock(); 3538 treeLock.acquire(); 3539 3540 // obey {parent,child} lock order 3541 AutoWriteLock sourceLock(pDeleteRec->mpSource COMMA_LOCKVAL_SRC_POS); 3542 3543 MediumLockList::Base::iterator childrenBegin = pDeleteRec->mpChildrenToReparent->GetBegin(); 3544 MediumLockList::Base::iterator childrenEnd = pDeleteRec->mpChildrenToReparent->GetEnd(); 3545 for (MediumLockList::Base::iterator it = childrenBegin; 3546 it != childrenEnd; 3547 ++it) 3527 3548 { 3528 Medium *pMedium = static_cast<Medium *>(childrenToReparent[i]); 3529 toReparent.push_back(pMedium); 3530 } 3531 treeLock.release(); 3532 pTarget->fixParentUuidOfChildren(toReparent); 3533 treeLock.acquire(); 3534 3535 // obey {parent,child} lock order 3536 AutoWriteLock sourceLock(pSource COMMA_LOCKVAL_SRC_POS); 3537 3538 for (size_t i = 0; i < childrenToReparent.size(); i++) 3539 { 3540 Medium *pMedium = static_cast<Medium *>(childrenToReparent[i]); 3549 Medium *pMedium = it->GetMedium(); 3541 3550 AutoWriteLock childLock(pMedium COMMA_LOCKVAL_SRC_POS); 3542 3551 3543 3552 pMedium->deparent(); // removes pMedium from source 3544 pMedium->setParent(p Target);3553 pMedium->setParent(pDeleteRec->mpTarget); 3545 3554 } 3546 3555 } … … 3549 3558 /* unregister and uninitialize all hard disks removed by the merge */ 3550 3559 MediumLockList *pMediumLockList = NULL; 3551 MediumAttachment *pMediumAttachment = static_cast<MediumAttachment *>(aMediumAttachment); 3552 rc = mData->mSession.mLockedMedia.Get(pMediumAttachment, pMediumLockList); 3553 const ComObjPtr<Medium> &pLast = aMergeForward ? pTarget : pSource; 3560 rc = mData->mSession.mLockedMedia.Get(pDeleteRec->mpOnlineMediumAttachment, pMediumLockList); 3561 const ComObjPtr<Medium> &pLast = pDeleteRec->mfMergeForward ? pDeleteRec->mpTarget : pDeleteRec->mpSource; 3554 3562 AssertReturn(SUCCEEDED(rc) && pMediumLockList, E_FAIL); 3555 3563 MediumLockList::Base::iterator lockListBegin = … … 3567 3575 3568 3576 /* The target and all images not merged (readonly) are skipped */ 3569 if ( pMedium == p Target3577 if ( pMedium == pDeleteRec->mpTarget 3570 3578 || pMedium->getState() == MediumState_LockedRead) 3571 3579 { … … 3589 3597 * and therefore we cannot uninit() it (it's therefore 3590 3598 * the caller's responsibility) */ 3591 if (pMedium == aSource)3599 if (pMedium == pDeleteRec->mpSource) 3592 3600 { 3593 Assert(p Source->getChildren().size() == 0);3594 Assert(p Source->getFirstMachineBackrefId() == NULL);3601 Assert(pDeleteRec->mpSource->getChildren().size() == 0); 3602 Assert(pDeleteRec->mpSource->getFirstMachineBackrefId() == NULL); 3595 3603 } 3596 3604 … … 3628 3636 * attachment, as the previously associated one (source) is now deleted. 3629 3637 * Without the immediate update the VM could not continue running. */ 3630 if (! aMergeForward && !fSourceHasChildren)3631 { 3632 AutoWriteLock attLock(p MediumAttachment COMMA_LOCKVAL_SRC_POS);3633 p MediumAttachment->updateMedium(pTarget);3638 if (!pDeleteRec->mfMergeForward && !fSourceHasChildren) 3639 { 3640 AutoWriteLock attLock(pDeleteRec->mpOnlineMediumAttachment COMMA_LOCKVAL_SRC_POS); 3641 pDeleteRec->mpOnlineMediumAttachment->updateMedium(pDeleteRec->mpTarget); 3634 3642 } 3635 3643
Note:
See TracChangeset
for help on using the changeset viewer.