Changeset 48297 in vbox for trunk/src/VBox/Main/src-server
- Timestamp:
- Sep 5, 2013 9:57:44 AM (12 years ago)
- svn:sync-xref-src-repo-rev:
- 88714
- Location:
- trunk/src/VBox/Main/src-server
- Files:
-
- 1 added
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-server/MachineImpl.cpp
r48295 r48297 903 903 LogFlowThisFunc(("ENTER\n")); 904 904 905 /* In some cases (medium registry related), it is necessary to be able to 906 * go through the list of all machines. Happens when an inaccessible VM 907 * has a sensible medium registry. */ 908 AutoReadLock mllock(mParent->getMachinesListLockHandle() COMMA_LOCKVAL_SRC_POS); 905 909 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 906 910 -
trunk/src/VBox/Main/src-server/MediumImpl.cpp
r47920 r48297 17 17 18 18 #include "MediumImpl.h" 19 #include "TokenImpl.h" 19 20 #include "ProgressImpl.h" 20 21 #include "SystemPropertiesImpl.h" … … 515 516 bool fMergeForward, 516 517 Medium *aParentForTarget, 517 const MediaList &aChildrenToReparent,518 MediumLockList *aChildrenToReparent, 518 519 Progress *aProgress, 519 520 MediumLockList *aMediumLockList, … … 523 524 mfMergeForward(fMergeForward), 524 525 mParentForTarget(aParentForTarget), 525 m ChildrenToReparent(aChildrenToReparent),526 mpChildrenToReparent(aChildrenToReparent), 526 527 mpMediumLockList(aMediumLockList), 527 528 mTargetCaller(aTarget), 528 529 mParentForTargetCaller(aParentForTarget), 529 mfChildrenCaller(false),530 530 mfKeepMediumLockList(fKeepMediumLockList) 531 531 { 532 532 AssertReturnVoidStmt(aMediumLockList != NULL, mRC = E_FAIL); 533 for (MediaList::const_iterator it = mChildrenToReparent.begin();534 it != mChildrenToReparent.end();535 ++it)536 {537 HRESULT rc2 = (*it)->addCaller();538 if (FAILED(rc2))539 {540 mRC = E_FAIL;541 for (MediaList::const_iterator it2 = mChildrenToReparent.begin();542 it2 != it;543 --it2)544 {545 (*it2)->releaseCaller();546 }547 return;548 }549 }550 mfChildrenCaller = true;551 533 } 552 534 … … 555 537 if (!mfKeepMediumLockList && mpMediumLockList) 556 538 delete mpMediumLockList; 557 if (mfChildrenCaller) 558 { 559 for (MediaList::const_iterator it = mChildrenToReparent.begin(); 560 it != mChildrenToReparent.end(); 561 ++it) 562 { 563 (*it)->releaseCaller(); 564 } 565 } 539 if (mpChildrenToReparent) 540 delete mpChildrenToReparent; 566 541 } 567 542 568 543 const ComObjPtr<Medium> mTarget; 569 544 bool mfMergeForward; 570 /* When m ChildrenToReparent is empty then mParentForTarget is non-null.571 * In other words: they are used in different cases. */545 /* When mpChildrenToReparent is null then mParentForTarget is non-null and 546 * vice versa. In other words: they are used in different cases. */ 572 547 const ComObjPtr<Medium> mParentForTarget; 573 Medi aList mChildrenToReparent;548 MediumLockList *mpChildrenToReparent; 574 549 MediumLockList *mpMediumLockList; 575 550 … … 579 554 AutoCaller mTargetCaller; 580 555 AutoCaller mParentForTargetCaller; 581 bool mfChildrenCaller;582 556 bool mfKeepMediumLockList; 583 557 }; … … 2123 2097 } 2124 2098 2125 /** 2126 * @note @a aState may be NULL if the state value is not needed (only for 2127 * in-process calls). 2128 */ 2129 STDMETHODIMP Medium::LockRead(MediumState_T *aState) 2130 { 2099 STDMETHODIMP Medium::LockRead(IToken **aToken) 2100 { 2101 CheckComArgNotNull(aToken); 2102 2131 2103 AutoCaller autoCaller(this); 2132 2104 if (FAILED(autoCaller.rc())) return autoCaller.rc(); … … 2152 2124 } 2153 2125 2154 /* return the current state before */2155 if (aState)2156 *aState = m->state;2157 2158 2126 HRESULT rc = S_OK; 2159 2127 … … 2175 2143 m->state = MediumState_LockedRead; 2176 2144 2145 ComObjPtr<MediumLockToken> pToken; 2146 rc = pToken.createObject(); 2147 if (SUCCEEDED(rc)) 2148 rc = pToken->init(this, false /* fWrite */); 2149 if (FAILED(rc)) 2150 { 2151 --m->readers; 2152 if (m->readers == 0) 2153 m->state = m->preLockState; 2154 return rc; 2155 } 2156 2157 pToken.queryInterfaceTo(aToken); 2177 2158 break; 2178 2159 } … … 2192 2173 * in-process calls). 2193 2174 */ 2194 STDMETHODIMP Medium::UnlockRead(MediumState_T *aState)2175 HRESULT Medium::unlockRead(MediumState_T *aState) 2195 2176 { 2196 2177 AutoCaller autoCaller(this); … … 2239 2220 } 2240 2221 2241 /** 2242 * @note @a aState may be NULL if the state value is not needed (only for 2243 * in-process calls). 2244 */ 2245 STDMETHODIMP Medium::LockWrite(MediumState_T *aState) 2246 { 2222 STDMETHODIMP Medium::LockWrite(IToken **aToken) 2223 { 2224 CheckComArgNotNull(aToken); 2225 2247 2226 AutoCaller autoCaller(this); 2248 2227 if (FAILED(autoCaller.rc())) return autoCaller.rc(); … … 2268 2247 } 2269 2248 2270 /* return the current state before */2271 if (aState)2272 *aState = m->state;2273 2274 2249 HRESULT rc = S_OK; 2275 2250 … … 2283 2258 LogFlowThisFunc(("Okay - prev state=%d locationFull=%s\n", m->state, getLocationFull().c_str())); 2284 2259 m->state = MediumState_LockedWrite; 2260 2261 ComObjPtr<MediumLockToken> pToken; 2262 rc = pToken.createObject(); 2263 if (SUCCEEDED(rc)) 2264 rc = pToken->init(this, true /* fWrite */); 2265 if (FAILED(rc)) 2266 { 2267 m->state = m->preLockState; 2268 return rc; 2269 } 2270 2271 pToken.queryInterfaceTo(aToken); 2285 2272 break; 2286 2273 } … … 2300 2287 * in-process calls). 2301 2288 */ 2302 STDMETHODIMP Medium::UnlockWrite(MediumState_T *aState)2289 HRESULT Medium::unlockWrite(MediumState_T *aState) 2303 2290 { 2304 2291 AutoCaller autoCaller(this); … … 2538 2525 2539 2526 HRESULT rc = S_OK; 2540 ComObjPtr 2527 ComObjPtr<Progress> pProgress; 2541 2528 Medium::Task *pTask = NULL; 2542 2529 … … 2694 2681 alock.release(); 2695 2682 2696 ComObjPtr 2683 ComObjPtr<Progress> pProgress; 2697 2684 2698 2685 ULONG mediumVariantFlags = 0; … … 2728 2715 bool fMergeForward = false; 2729 2716 ComObjPtr<Medium> pParentForTarget; 2730 Medi aList childrenToReparent;2717 MediumLockList *pChildrenToReparent = NULL; 2731 2718 MediumLockList *pMediumLockList = NULL; 2732 2719 … … 2734 2721 2735 2722 rc = prepareMergeTo(pTarget, NULL, NULL, true, fMergeForward, 2736 pParentForTarget, childrenToReparent, pMediumLockList);2723 pParentForTarget, pChildrenToReparent, pMediumLockList); 2737 2724 if (FAILED(rc)) return rc; 2738 2725 2739 ComObjPtr 2740 2741 rc = mergeTo(pTarget, fMergeForward, pParentForTarget, childrenToReparent,2726 ComObjPtr<Progress> pProgress; 2727 2728 rc = mergeTo(pTarget, fMergeForward, pParentForTarget, pChildrenToReparent, 2742 2729 pMediumLockList, &pProgress, false /* aWait */); 2743 2730 if (FAILED(rc)) 2744 cancelMergeTo( childrenToReparent, pMediumLockList);2731 cancelMergeTo(pChildrenToReparent, pMediumLockList); 2745 2732 else 2746 2733 pProgress.queryInterfaceTo(aProgress); … … 2915 2902 2916 2903 HRESULT rc = S_OK; 2917 ComObjPtr 2904 ComObjPtr<Progress> pProgress; 2918 2905 Medium::Task *pTask = NULL; 2919 2906 … … 2988 2975 2989 2976 HRESULT rc = S_OK; 2990 ComObjPtr 2977 ComObjPtr<Progress> pProgress; 2991 2978 Medium::Task *pTask = NULL; 2992 2979 … … 3061 3048 3062 3049 HRESULT rc = S_OK; 3063 ComObjPtr 3050 ComObjPtr<Progress> pProgress; 3064 3051 Medium::Task *pTask = NULL; 3065 3052 … … 4665 4652 * @param fMergeForward Resulting merge direction (out). 4666 4653 * @param pParentForTarget New parent for target medium after merge (out). 4667 * @param aChildrenToReparent List of children of the source which will have 4668 * to be reparented to the target after merge (out). 4654 * @param aChildrenToReparent Medium lock list containing all children of the 4655 * source which will have to be reparented to the target 4656 * after merge (out). 4669 4657 * @param aMediumLockList Medium locking information (out). 4670 4658 * … … 4678 4666 bool &fMergeForward, 4679 4667 ComObjPtr<Medium> &pParentForTarget, 4680 Medi aList&aChildrenToReparent,4668 MediumLockList * &aChildrenToReparent, 4681 4669 MediumLockList * &aMediumLockList) 4682 4670 { … … 4693 4681 fMergeForward = false; 4694 4682 pParentForTarget.setNull(); 4695 aChildrenToReparent.clear(); 4683 Assert(aChildrenToReparent == NULL); 4684 aChildrenToReparent = NULL; 4696 4685 Assert(aMediumLockList == NULL); 4697 4686 aMediumLockList = NULL; … … 4876 4865 { 4877 4866 /* we will need to reparent children of the source */ 4867 aChildrenToReparent = new MediumLockList(); 4878 4868 for (MediaList::const_iterator it = getChildren().begin(); 4879 4869 it != getChildren().end(); … … 4881 4871 { 4882 4872 pMedium = *it; 4883 if (fLockMedia) 4884 { 4885 rc = pMedium->LockWrite(NULL); 4886 if (FAILED(rc)) 4887 throw rc; 4888 } 4889 4890 aChildrenToReparent.push_back(pMedium); 4873 aChildrenToReparent->Append(pMedium, true /* fLockWrite */); 4874 } 4875 if (fLockMedia && aChildrenToReparent) 4876 { 4877 treeLock.release(); 4878 rc = aChildrenToReparent->Lock(); 4879 treeLock.acquire(); 4880 if (FAILED(rc)) 4881 throw rc; 4891 4882 } 4892 4883 } … … 4947 4938 if (FAILED(rc)) 4948 4939 { 4949 delete aMediumLockList; 4950 aMediumLockList = NULL; 4940 if (aMediumLockList) 4941 { 4942 delete aMediumLockList; 4943 aMediumLockList = NULL; 4944 } 4945 if (aChildrenToReparent) 4946 { 4947 delete aChildrenToReparent; 4948 aChildrenToReparent = NULL; 4949 } 4951 4950 } 4952 4951 … … 5033 5032 bool fMergeForward, 5034 5033 const ComObjPtr<Medium> &pParentForTarget, 5035 const MediaList &aChildrenToReparent,5034 MediumLockList *aChildrenToReparent, 5036 5035 MediumLockList *aMediumLockList, 5037 ComObjPtr 5036 ComObjPtr<Progress> *aProgress, 5038 5037 bool aWait) 5039 5038 { … … 5050 5049 5051 5050 HRESULT rc = S_OK; 5052 ComObjPtr 5051 ComObjPtr<Progress> pProgress; 5053 5052 Medium::Task *pTask = NULL; 5054 5053 … … 5122 5121 * @note Locks the media from the chain for writing. 5123 5122 */ 5124 void Medium::cancelMergeTo( const MediaList &aChildrenToReparent,5123 void Medium::cancelMergeTo(MediumLockList *aChildrenToReparent, 5125 5124 MediumLockList *aMediumLockList) 5126 5125 { … … 5154 5153 delete aMediumLockList; 5155 5154 5156 /* unlock the children which had to be reparented */ 5157 for (MediaList::const_iterator it = aChildrenToReparent.begin(); 5158 it != aChildrenToReparent.end(); 5159 ++it) 5160 { 5161 const ComObjPtr<Medium> &pMedium = *it; 5162 5163 AutoWriteLock alock(pMedium COMMA_LOCKVAL_SRC_POS); 5164 pMedium->UnlockWrite(NULL); 5165 } 5155 /* unlock the children which had to be reparented, the destructor will do 5156 * the work */ 5157 if (aChildrenToReparent) 5158 delete aChildrenToReparent; 5166 5159 } 5167 5160 … … 5170 5163 * parent. 5171 5164 */ 5172 HRESULT Medium::fixParentUuidOfChildren( const MediaList &childrenToReparent)5165 HRESULT Medium::fixParentUuidOfChildren(MediumLockList *pChildrenToReparent) 5173 5166 { 5174 5167 Assert(!isWriteLockOnCurrentThread()); … … 5211 5204 } 5212 5205 5213 for (MediaList::const_iterator it = childrenToReparent.begin(); 5214 it != childrenToReparent.end(); 5206 MediumLockList::Base::iterator childrenBegin = pChildrenToReparent->GetBegin(); 5207 MediumLockList::Base::iterator childrenEnd = pChildrenToReparent->GetEnd(); 5208 for (MediumLockList::Base::iterator it = childrenBegin; 5209 it != childrenEnd; 5215 5210 ++it) 5216 5211 { 5212 Medium *pMedium = it->GetMedium(); 5217 5213 /* VD_OPEN_FLAGS_INFO since UUID is wrong yet */ 5218 5214 vrc = VDOpen(hdd, 5219 (*it)->m->strFormat.c_str(),5220 (*it)->m->strLocationFull.c_str(),5215 pMedium->m->strFormat.c_str(), 5216 pMedium->m->strLocationFull.c_str(), 5221 5217 VD_OPEN_FLAGS_INFO | m->uOpenFlagsDef, 5222 (*it)->m->vdImageIfaces);5218 pMedium->m->vdImageIfaces); 5223 5219 if (RT_FAILURE(vrc)) 5224 5220 throw vrc; … … 5231 5227 if (RT_FAILURE(vrc)) 5232 5228 throw vrc; 5233 5234 (*it)->UnlockWrite(NULL);5235 5229 } 5236 5230 } … … 5648 5642 /* Lock the medium, which makes the behavior much more consistent */ 5649 5643 alock.release(); 5644 ComPtr<IToken> pToken; 5650 5645 if (uOpenFlags & (VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_SHAREABLE)) 5651 rc = LockRead( NULL);5646 rc = LockRead(pToken.asOutParam()); 5652 5647 else 5653 rc = LockWrite( NULL);5648 rc = LockWrite(pToken.asOutParam()); 5654 5649 if (FAILED(rc)) return rc; 5655 5650 alock.acquire(); … … 5989 5984 m->preLockState = MediumState_Inaccessible; 5990 5985 5991 HRESULT rc2; 5992 if (uOpenFlags & (VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_SHAREABLE)) 5993 rc2 = UnlockRead(NULL); 5994 else 5995 rc2 = UnlockWrite(NULL); 5996 if (SUCCEEDED(rc) && FAILED(rc2)) 5997 rc = rc2; 5986 pToken->Abandon(); 5987 pToken.setNull(); 5988 5998 5989 if (FAILED(rc)) return rc; 5999 5990 … … 6006 5997 if (fRepairImageZeroParentUuid) 6007 5998 { 6008 rc = LockWrite( NULL);5999 rc = LockWrite(pToken.asOutParam()); 6009 6000 if (FAILED(rc)) return rc; 6010 6001 … … 6044 6035 } 6045 6036 6046 rc = UnlockWrite(NULL); 6047 if (SUCCEEDED(rc) && FAILED(rc2)) 6048 rc = rc2; 6037 pToken->Abandon(); 6038 pToken.setNull(); 6049 6039 if (FAILED(rc)) return rc; 6050 6040 } … … 7214 7204 * which cannot be part of the container at once so 7215 7205 * add each one in there individually */ 7216 if (task.m ChildrenToReparent.size() > 0)7206 if (task.mpChildrenToReparent) 7217 7207 { 7218 for (MediaList::const_iterator it = task.mChildrenToReparent.begin(); 7219 it != task.mChildrenToReparent.end(); 7208 MediumLockList::Base::iterator childrenBegin = task.mpChildrenToReparent->GetBegin(); 7209 MediumLockList::Base::iterator childrenEnd = task.mpChildrenToReparent->GetEnd(); 7210 for (MediumLockList::Base::iterator it = childrenBegin; 7211 it != childrenEnd; 7220 7212 ++it) 7221 7213 { 7214 Medium *pMedium = it->GetMedium(); 7222 7215 /* VD_OPEN_FLAGS_INFO since UUID is wrong yet */ 7223 7216 vrc = VDOpen(hdd, 7224 (*it)->m->strFormat.c_str(),7225 (*it)->m->strLocationFull.c_str(),7217 pMedium->m->strFormat.c_str(), 7218 pMedium->m->strLocationFull.c_str(), 7226 7219 VD_OPEN_FLAGS_INFO | m->uOpenFlagsDef, 7227 (*it)->m->vdImageIfaces);7220 pMedium->m->vdImageIfaces); 7228 7221 if (RT_FAILURE(vrc)) 7229 7222 throw vrc; … … 7237 7230 if (RT_FAILURE(vrc)) 7238 7231 throw vrc; 7239 7240 (*it)->UnlockWrite(NULL);7241 7232 } 7242 7233 } … … 7301 7292 /* reparent source's children and disconnect the deleted 7302 7293 * branch at the younger end */ 7303 if (task.m ChildrenToReparent.size() > 0)7294 if (task.mpChildrenToReparent) 7304 7295 { 7305 7296 /* obey {parent,child} lock order */ 7306 7297 AutoWriteLock sourceLock(this COMMA_LOCKVAL_SRC_POS); 7307 7298 7308 for (MediaList::const_iterator it = task.mChildrenToReparent.begin(); 7309 it != task.mChildrenToReparent.end(); 7310 it++) 7299 MediumLockList::Base::iterator childrenBegin = task.mpChildrenToReparent->GetBegin(); 7300 MediumLockList::Base::iterator childrenEnd = task.mpChildrenToReparent->GetEnd(); 7301 for (MediumLockList::Base::iterator it = childrenBegin; 7302 it != childrenEnd; 7303 ++it) 7311 7304 { 7312 Medium *pMedium = *it;7305 Medium *pMedium = it->GetMedium(); 7313 7306 AutoWriteLock childLock(pMedium COMMA_LOCKVAL_SRC_POS); 7314 7307 … … 7396 7389 * don't own the merge chain, so release it in this case. */ 7397 7390 if (task.isAsync()) 7398 { 7399 Assert(task.mChildrenToReparent.size() == 0); 7400 cancelMergeTo(task.mChildrenToReparent, task.mpMediumLockList); 7401 } 7391 cancelMergeTo(task.mpChildrenToReparent, task.mpMediumLockList); 7402 7392 } 7403 7393 -
trunk/src/VBox/Main/src-server/MediumLock.cpp
r45595 r48297 5 5 6 6 /* 7 * Copyright (C) 2010 Oracle Corporation7 * Copyright (C) 2010-2013 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 75 75 } 76 76 77 HRESULT MediumLock::Lock() 77 bool MediumLock::IsLocked() const 78 { 79 return mIsLocked; 80 } 81 82 HRESULT MediumLock::Lock(bool aIgnoreLockedMedia) 78 83 { 79 84 if (mIsLocked) … … 102 107 default: 103 108 if (mLockWrite) 104 rc = mMedium->LockWrite(NULL); 109 { 110 if (aIgnoreLockedMedia && ( state == MediumState_LockedRead 111 || state == MediumState_LockedWrite)) 112 return S_OK; 113 else 114 rc = mMedium->LockWrite(mToken.asOutParam()); 115 } 105 116 else 106 rc = mMedium->LockRead(NULL); 117 { 118 if (aIgnoreLockedMedia && state == MediumState_LockedWrite) 119 return S_OK; 120 else 121 rc = mMedium->LockRead(mToken.asOutParam()); 122 } 107 123 } 108 124 if (SUCCEEDED(rc)) … … 121 137 { 122 138 HRESULT rc = S_OK; 123 if (mIsLocked && !mLockSkipped) 124 { 125 if (mLockWrite) 126 rc = mMedium->UnlockWrite(NULL); 127 else 128 rc = mMedium->UnlockRead(NULL); 139 if (mIsLocked && !mLockSkipped && mToken) 140 { 141 mToken->Abandon(); 142 mToken.setNull(); 129 143 } 130 144 mMediumCaller.attach(NULL); … … 202 216 } 203 217 204 HRESULT MediumLockList::Lock( )218 HRESULT MediumLockList::Lock(bool fSkipOverLockedMedia /* = false */) 205 219 { 206 220 if (mIsLocked) … … 211 225 it++) 212 226 { 213 rc = it->Lock( );227 rc = it->Lock(fSkipOverLockedMedia); 214 228 if (FAILED(rc)) 215 229 { -
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 -
trunk/src/VBox/Main/src-server/VirtualBoxImpl.cpp
r47597 r48297 4732 4732 4733 4733 /** 4734 * Returns the lock handle which protects the machines list. As opposed 4735 * to version 3.1 and earlier, these lists are no longer protected by the 4736 * VirtualBox lock, but by this more specialized lock. Mind the locking 4737 * order: always request this lock after the VirtualBox object lock but 4738 * before the locks of any machine object. See AutoLock.h. 4739 */ 4740 RWLockHandle& VirtualBox::getMachinesListLockHandle() 4741 { 4742 return m->lockMachines; 4743 } 4744 4745 /** 4734 4746 * Returns the lock handle which protects the media trees (hard disks, 4735 4747 * DVDs, floppies). As opposed to version 3.1 and earlier, these lists
Note:
See TracChangeset
for help on using the changeset viewer.