Changeset 48297 in vbox for trunk/src/VBox/Main
- Timestamp:
- Sep 5, 2013 9:57:44 AM (11 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 2 added
- 16 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/Makefile.kmk
r48282 r48297 363 363 src-server/StorageControllerImpl.cpp \ 364 364 src-server/SystemPropertiesImpl.cpp \ 365 src-server/TokenImpl.cpp \ 365 366 src-server/USBControllerImpl.cpp \ 366 367 src-server/USBDeviceFiltersImpl.cpp \ -
trunk/src/VBox/Main/idl/VirtualBox.xidl
r48102 r48297 3700 3700 <desc> 3701 3701 Gets called by <link to="IInternalSessionControl::onlineMergeMedium"/>. 3702 </desc> 3703 <param name="mediumAttachment" type="IMediumAttachment" dir="in"> 3704 <desc>The medium attachment which needs to be cleaned up.</desc> 3705 </param> 3706 <param name="source" type="IMedium" dir="in"> 3707 <desc>Merge source medium.</desc> 3708 </param> 3709 <param name="target" type="IMedium" dir="in"> 3710 <desc>Merge target medium.</desc> 3711 </param> 3712 <param name="mergeForward" type="boolean" dir="in"> 3713 <desc>Merge direction.</desc> 3714 </param> 3715 <param name="parentForTarget" type="IMedium" dir="in"> 3716 <desc>For forward merges: new parent for target medium.</desc> 3717 </param> 3718 <param name="childrenToReparent" type="IMedium" safearray="yes" dir="in"> 3719 <desc>For backward merges: list of media which need their parent UUID 3720 updated.</desc> 3721 </param> 3702 All necessary state information is available at the called object. 3703 </desc> 3722 3704 </method> 3723 3705 … … 13612 13594 write operation such as <link to="#cloneTo"/> or <link to="#mergeTo"/>. 13613 13595 13614 The medium locked for reading must be unlocked using the <link13615 to="#unlockRead"/> method. Calls to <link to="#lockRead"/>13616 can be nested and must be followed by the same number of paired13617 <link to="#unlockRead"/> calls.13596 The medium locked for reading must be unlocked by abandoning the 13597 returned token object, see <link to="IToken"/>. Calls to 13598 <link to="#lockRead"/> can be nested and the lock is actually released 13599 when all callers have abandoned the token. 13618 13600 13619 13601 This method sets the medium state (see <link to="#state"/>) to … … 13635 13617 13636 13618 </desc> 13637 <param name="state" type="MediumState" dir="return"> 13638 <desc> 13639 State of the medium after the operation. 13640 </desc> 13641 </param> 13642 </method> 13643 13644 <method name="unlockRead"> 13645 <desc> 13646 Cancels the read lock previously set by <link to="#lockRead"/>. 13647 13648 For both success and failure, this method returns the current state 13649 of the medium <i>after</i> the operation. 13650 13651 See <link to="#lockRead"/> for more details. 13652 13653 <result name="VBOX_E_INVALID_OBJECT_STATE"> 13654 Medium not locked for reading. 13655 </result> 13656 13657 </desc> 13658 <param name="state" type="MediumState" dir="return"> 13659 <desc> 13660 State of the medium after the operation. 13619 <param name="token" type="IToken" dir="return"> 13620 <desc> 13621 Token object, when this is released (reference count reaches 0) then 13622 the lock count is decreased. The lock is released when the lock count 13623 reaches 0. 13661 13624 </desc> 13662 13625 </param> … … 13689 13652 write operation such as <link to="#cloneTo"/> or <link to="#mergeTo"/>. 13690 13653 13691 The medium locked for writing must be unlocked using the <link 13692 to="#unlockWrite"/> method. Write locks <i>cannot</i> be nested. 13654 The medium locked for writing must be unlocked by abandoning the 13655 returned token object, see <link to="IToken"/>. Write locks 13656 <i>cannot</i> be nested. 13693 13657 13694 13658 This method sets the medium state (see <link to="#state"/>) to … … 13701 13665 storage unit. 13702 13666 13703 For both, success and failure, this method returns the current13704 state of the medium <i>before</i> the operation.13705 13706 13667 <result name="VBOX_E_INVALID_OBJECT_STATE"> 13707 13668 Invalid medium state (e.g. not created, locked, inaccessible, … … 13710 13671 13711 13672 </desc> 13712 <param name="state" type="MediumState" dir="return"> 13713 <desc> 13714 State of the medium after the operation. 13715 </desc> 13716 </param> 13717 </method> 13718 13719 <method name="unlockWrite"> 13720 <desc> 13721 Cancels the write lock previously set by <link to="#lockWrite"/>. 13722 13723 For both success and failure, this method returns the current 13724 state of the medium <i>after</i> the operation. 13725 13726 See <link to="#lockWrite"/> for more details. 13727 13728 <result name="VBOX_E_INVALID_OBJECT_STATE"> 13729 Medium not locked for writing. 13730 </result> 13731 13732 </desc> 13733 <param name="state" type="MediumState" dir="return"> 13734 <desc> 13735 State of the medium after the operation. 13673 <param name="token" type="IToken" dir="return"> 13674 <desc> 13675 Token object, when this is released (reference count reaches 0) then 13676 the lock is released. 13736 13677 </desc> 13737 13678 </param> … … 14494 14435 14495 14436 <!-- 14437 // IToken 14438 ///////////////////////////////////////////////////////////////////////// 14439 --> 14440 14441 <interface 14442 name="IToken" extends="$unknown" 14443 uuid="3b1c4797-e289-4d4c-b74c-50c9b86a36f8" 14444 wsmap="managed" 14445 > 14446 <desc> 14447 The IToken interface represents a token passed to an API client, which 14448 triggers cleanup actions when it is explicitly released by calling the 14449 <link to="#abandon"/> method (preferred, as it is accurately defined 14450 when the release happens), or when the object reference count drops 14451 to 0. The latter way is implicitly used when an API client crashes, 14452 however the discovery that there was a crash can take rather long, 14453 depending on the platform (COM needs 6 minutes). So better don't rely 14454 on the crash behavior too much. 14455 </desc> 14456 14457 <method name="abandon" wrap-hint-server="passcaller"> 14458 <desc>Releases this token. Cannot be undone in any way, and makes the 14459 token object unusable (even the <link to="#dummy"/> method will return 14460 an error), ready for releasing. It is a more defined way than just 14461 letting the reference count drop to 0, because the latter (depending 14462 on the platform) can trigger asynchronous cleanup activity. 14463 </desc> 14464 </method> 14465 14466 <method name="dummy"> 14467 <desc>Purely a NOOP. Useful when using proxy type API bindings (e.g. the 14468 webservice) which manage objects on behalf of the actual client, using 14469 an object reference expiration time based garbage collector. 14470 </desc> 14471 </method> 14472 14473 </interface> 14474 14475 14476 <!-- 14496 14477 // IKeyboard 14497 14478 ///////////////////////////////////////////////////////////////////////// … … 14509 14490 Use this interface to send keystrokes or the Ctrl-Alt-Del sequence 14510 14491 to the virtual machine. 14511 14512 14492 </desc> 14493 14513 14494 <method name="putScancode"> 14514 14495 <desc>Sends a scancode to the keyboard. … … 17939 17920 <desc>The index of the target image in the chain. 17940 17921 Redundant, but drastically reduces IPC.</desc> 17941 </param>17942 <param name="source" type="IMedium" dir="in">17943 <desc>Merge source medium.</desc>17944 </param>17945 <param name="target" type="IMedium" dir="in">17946 <desc>Merge target medium.</desc>17947 </param>17948 <param name="mergeForward" type="boolean" dir="in">17949 <desc>Merge direction.</desc>17950 </param>17951 <param name="parentForTarget" type="IMedium" dir="in">17952 <desc>For forward merges: new parent for target medium.</desc>17953 </param>17954 <param name="childrenToReparent" type="IMedium" safearray="yes" dir="in">17955 <desc>For backward merges: list of media which need their parent UUID17956 updated.</desc>17957 17922 </param> 17958 17923 <param name="progress" type="IProgress" dir="in"> -
trunk/src/VBox/Main/include/ConsoleImpl.h
r48054 r48297 230 230 HRESULT onlineMergeMedium(IMediumAttachment *aMediumAttachment, 231 231 ULONG aSourceIdx, ULONG aTargetIdx, 232 IMedium *aSource, IMedium *aTarget,233 BOOL aMergeForward, IMedium *aParentForTarget,234 ComSafeArrayIn(IMedium *, aChildrenToReparent),235 232 IProgress *aProgress); 236 233 VMMDev *getVMMDev() { return m_pVMMDev; } -
trunk/src/VBox/Main/include/MachineImpl.h
r47991 r48297 1070 1070 IN_BSTR aEndID, BOOL fDeleteAllChildren, 1071 1071 MachineState_T *aMachineState, IProgress **aProgress); 1072 STDMETHOD(FinishOnlineMergeMedium)(IMediumAttachment *aMediumAttachment, 1073 IMedium *aSource, IMedium *aTarget, 1074 BOOL fMergeForward, 1075 IMedium *pParentForTarget, 1076 ComSafeArrayIn(IMedium *, aChildrenToReparent)); 1072 STDMETHOD(FinishOnlineMergeMedium)(); 1077 1073 STDMETHOD(RestoreSnapshot)(IConsole *aInitiator, 1078 1074 ISnapshot *aSnapshot, … … 1143 1139 { 1144 1140 ConsoleTaskData() 1145 : mLastState(MachineState_Null) 1141 : mLastState(MachineState_Null), mDeleteSnapshotInfo(NULL) 1146 1142 { } 1147 1143 … … 1151 1147 // used when taking snapshot 1152 1148 ComObjPtr<Snapshot> mSnapshot; 1149 1150 // used when deleting online snapshot 1151 void *mDeleteSnapshotInfo; 1153 1152 1154 1153 // used when saving state (either as part of a snapshot or separate) … … 1185 1184 bool &fMergeForward, 1186 1185 ComObjPtr<Medium> &pParentForTarget, 1187 Medi aList&aChildrenToReparent,1186 MediumLockList * &aChildrenToReparent, 1188 1187 bool &fNeedOnlineMerge, 1189 MediumLockList * &aMediumLockList); 1188 MediumLockList * &aMediumLockList, 1189 ComPtr<IToken> &aHDLockToken); 1190 1190 void cancelDeleteSnapshotMedium(const ComObjPtr<Medium> &aHD, 1191 1191 const ComObjPtr<Medium> &aSource, 1192 const MediaList &aChildrenToReparent,1192 MediumLockList *aChildrenToReparent, 1193 1193 bool fNeedsOnlineMerge, 1194 1194 MediumLockList *aMediumLockList, 1195 const ComPtr<IToken> &aHDLockToken, 1195 1196 const Guid &aMediumId, 1196 1197 const Guid &aSnapshotId); … … 1200 1201 bool fMergeForward, 1201 1202 const ComObjPtr<Medium> &pParentForTarget, 1202 const MediaList &aChildrenToReparent,1203 MediumLockList *aChildrenToReparent, 1203 1204 MediumLockList *aMediumLockList, 1204 1205 ComObjPtr<Progress> &aProgress, -
trunk/src/VBox/Main/include/MediumImpl.h
r44528 r48297 132 132 STDMETHOD(GetSnapshotIds)(IN_BSTR aMachineId, 133 133 ComSafeArrayOut(BSTR, aSnapshotIds)); 134 STDMETHOD(LockRead)(MediumState_T *aState); 135 STDMETHOD(UnlockRead)(MediumState_T *aState); 136 STDMETHOD(LockWrite)(MediumState_T *aState); 137 STDMETHOD(UnlockWrite)(MediumState_T *aState); 134 STDMETHOD(LockRead)(IToken **aToken); 135 STDMETHOD(LockWrite)(IToken **aToken); 138 136 STDMETHOD(Close)(); 139 137 STDMETHOD(GetProperty)(IN_BSTR aName, BSTR *aValue); … … 226 224 227 225 HRESULT close(AutoCaller &autoCaller); 226 HRESULT unlockRead(MediumState_T *aState); 227 HRESULT unlockWrite(MediumState_T *aState); 228 228 HRESULT deleteStorage(ComObjPtr<Progress> *aProgress, bool aWait); 229 229 HRESULT markForDeletion(); … … 241 241 bool &fMergeForward, 242 242 ComObjPtr<Medium> &pParentForTarget, 243 Medi aList&aChildrenToReparent,243 MediumLockList * &aChildrenToReparent, 244 244 MediumLockList * &aMediumLockList); 245 245 HRESULT mergeTo(const ComObjPtr<Medium> &pTarget, 246 246 bool fMergeForward, 247 247 const ComObjPtr<Medium> &pParentForTarget, 248 const MediaList &aChildrenToReparent,248 MediumLockList *aChildrenToReparent, 249 249 MediumLockList *aMediumLockList, 250 250 ComObjPtr<Progress> *aProgress, 251 251 bool aWait); 252 void cancelMergeTo( const MediaList &aChildrenToReparent,252 void cancelMergeTo(MediumLockList *aChildrenToReparent, 253 253 MediumLockList *aMediumLockList); 254 254 255 HRESULT fixParentUuidOfChildren( const MediaList &childrenToReparent);255 HRESULT fixParentUuidOfChildren(MediumLockList *pChildrenToReparent); 256 256 257 257 HRESULT exportFile(const char *aFilename, -
trunk/src/VBox/Main/include/MediumLock.h
r44529 r48297 7 7 8 8 /* 9 * Copyright (C) 2010-201 2Oracle Corporation9 * Copyright (C) 2010-2013 Oracle Corporation 10 10 * 11 11 * This file is part of VirtualBox Open Source Edition (OSE), as … … 90 90 91 91 /** 92 * Check if this medium object has been locked by this MediumLock. 93 */ 94 bool IsLocked() const; 95 96 /** 92 97 * Acquire a medium lock. 93 98 * 94 99 * @return COM status code 95 */ 96 HRESULT Lock(); 100 * @param aIgnoreLockedMedia If set ignore all media which is already 101 * locked in an incompatible way. 102 */ 103 HRESULT Lock(bool aIgnoreLockedMedia = false); 97 104 98 105 /** … … 105 112 private: 106 113 ComObjPtr<Medium> mMedium; 114 ComPtr<IToken> mToken; 107 115 AutoCaller mMediumCaller; 108 116 bool mLockWrite; … … 208 216 * 209 217 * @return COM status code 210 */ 211 HRESULT Lock(); 218 * @param aSkipOverLockedMedia If set ignore all media which is already 219 * locked for reading or writing. For callers 220 * which need to know which medium objects 221 * have been locked by this lock list you 222 * can iterate over the list and check the 223 * MediumLock state. 224 */ 225 HRESULT Lock(bool aSkipOverLockedMedia = false); 212 226 213 227 /** -
trunk/src/VBox/Main/include/SessionImpl.h
r48282 r48297 103 103 STDMETHOD(OnlineMergeMedium)(IMediumAttachment *aMediumAttachment, 104 104 ULONG aSourceIdx, ULONG aTargetIdx, 105 IMedium *aSource, IMedium *aTarget,106 BOOL aMergeForward, IMedium *aParentForTarget,107 ComSafeArrayIn(IMedium *, aChildrenToReparent),108 105 IProgress *aProgress); 109 106 STDMETHOD(EnableVMMStatistics)(BOOL aEnable); -
trunk/src/VBox/Main/include/VirtualBoxImpl.h
r47561 r48297 311 311 AutostartDb* getAutostartDb() const; 312 312 313 RWLockHandle& getMachinesListLockHandle(); 313 314 RWLockHandle& getMediaTreeLockHandle(); 314 315 -
trunk/src/VBox/Main/src-client/ConsoleImpl.cpp
r48054 r48297 5528 5528 HRESULT Console::onlineMergeMedium(IMediumAttachment *aMediumAttachment, 5529 5529 ULONG aSourceIdx, ULONG aTargetIdx, 5530 IMedium *aSource, IMedium *aTarget,5531 BOOL aMergeForward,5532 IMedium *aParentForTarget,5533 ComSafeArrayIn(IMedium *, aChildrenToReparent),5534 5530 IProgress *aProgress) 5535 5531 { … … 5708 5704 5709 5705 /* Update medium chain and state now, so that the VM can continue. */ 5710 rc = mControl->FinishOnlineMergeMedium(aMediumAttachment, aSource, aTarget, 5711 aMergeForward, aParentForTarget, 5712 ComSafeArrayInArg(aChildrenToReparent)); 5706 rc = mControl->FinishOnlineMergeMedium(); 5713 5707 5714 5708 vrc = VMR3ReqCallWaitU(ptrVM.rawUVM(), -
trunk/src/VBox/Main/src-client/SessionImpl.cpp
r48282 r48297 980 980 STDMETHODIMP Session::OnlineMergeMedium(IMediumAttachment *aMediumAttachment, 981 981 ULONG aSourceIdx, ULONG aTargetIdx, 982 IMedium *aSource, IMedium *aTarget,983 BOOL aMergeForward,984 IMedium *aParentForTarget,985 ComSafeArrayIn(IMedium *, aChildrenToReparent),986 982 IProgress *aProgress) 987 983 { … … 997 993 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); 998 994 CheckComArgNotNull(aMediumAttachment); 999 CheckComArgSafeArrayNotNull(aChildrenToReparent); 1000 1001 return mConsole->onlineMergeMedium(aMediumAttachment, aSourceIdx, 1002 aTargetIdx, aSource, aTarget, 1003 aMergeForward, aParentForTarget, 1004 ComSafeArrayInArg(aChildrenToReparent), 995 996 return mConsole->onlineMergeMedium(aMediumAttachment, 997 aSourceIdx, aTargetIdx, 1005 998 aProgress); 1006 999 #else -
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 -
trunk/src/VBox/Main/testcase/tstMediumLock.cpp
r47779 r48297 123 123 { 124 124 RTTestSub(hTest, "Write locks"); 125 126 MediumState_T mediumState = MediumState_NotCreated; 127 TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting state"); 128 if (mediumState != MediumState_Created) 129 RTTestFailed(hTest, "wrong medium state %d", mediumState); 130 131 TEST_COM_SUCCESS(hTest, pMedium->LockWrite(&mediumState), "write lock"); 125 ComPtr<IToken> pToken1, pToken2; 126 127 MediumState_T mediumState = MediumState_NotCreated; 128 TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting state"); 129 if (mediumState != MediumState_Created) 130 RTTestFailed(hTest, "wrong medium state %d", mediumState); 131 132 TEST_COM_SUCCESS(hTest, pMedium->LockWrite(pToken1.asOutParam()), "write lock"); 132 133 133 134 TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting lock write state"); … … 135 136 RTTestFailed(hTest, "wrong lock write medium state %d", mediumState); 136 137 137 TEST_COM_FAILURE(hTest, pMedium->LockWrite(&mediumState), "nested write lock succeeded"); 138 TEST_COM_FAILURE(hTest, pMedium->LockWrite(pToken2.asOutParam()), "nested write lock succeeded"); 139 if (!pToken2.isNull()) 140 RTTestFailed(hTest, "pToken2 is not null"); 138 141 139 142 TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting after nested lock write state"); … … 141 144 RTTestFailed(hTest, "wrong after nested lock write medium state %d", mediumState); 142 145 143 TEST_COM_SUCCESS(hTest, pMedium->UnlockWrite(&mediumState), "write unlock"); 146 if (!pToken1.isNull()) 147 TEST_COM_SUCCESS(hTest, pToken1->Abandon(), "write unlock"); 148 else 149 RTTestFailed(hTest, "pToken1 is null"); 144 150 145 151 TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting unlock write state"); … … 151 157 { 152 158 RTTestSub(hTest, "Read locks"); 153 154 MediumState_T mediumState = MediumState_NotCreated; 155 TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting state"); 156 if (mediumState != MediumState_Created) 157 RTTestFailed(hTest, "wrong medium state %d", mediumState); 158 159 TEST_COM_SUCCESS(hTest, pMedium->LockRead(&mediumState), "read lock"); 159 ComPtr<IToken> pToken1, pToken2; 160 161 MediumState_T mediumState = MediumState_NotCreated; 162 TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting state"); 163 if (mediumState != MediumState_Created) 164 RTTestFailed(hTest, "wrong medium state %d", mediumState); 165 166 TEST_COM_SUCCESS(hTest, pMedium->LockRead(pToken1.asOutParam()), "read lock"); 160 167 161 168 TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting lock read state"); … … 163 170 RTTestFailed(hTest, "wrong lock read medium state %d", mediumState); 164 171 165 TEST_COM_SUCCESS(hTest, pMedium->LockRead( &mediumState), "nested read lock failed");172 TEST_COM_SUCCESS(hTest, pMedium->LockRead(pToken2.asOutParam()), "nested read lock failed"); 166 173 167 174 TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting after nested lock read state"); … … 169 176 RTTestFailed(hTest, "wrong after nested lock read medium state %d", mediumState); 170 177 171 TEST_COM_SUCCESS(hTest, pMedium->UnlockRead(&mediumState), "read nested unlock"); 178 if (!pToken2.isNull()) 179 TEST_COM_SUCCESS(hTest, pToken2->Abandon(), "read nested unlock"); 180 else 181 RTTestFailed(hTest, "pToken2 is null"); 172 182 173 183 TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting after nested lock read state"); … … 175 185 RTTestFailed(hTest, "wrong after nested lock read medium state %d", mediumState); 176 186 177 TEST_COM_SUCCESS(hTest, pMedium->UnlockRead(&mediumState), "read unlock"); 187 if (!pToken1.isNull()) 188 TEST_COM_SUCCESS(hTest, pToken1->Abandon(), "read nested unlock"); 189 else 190 RTTestFailed(hTest, "pToken1 is null"); 178 191 179 192 TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting unlock read state"); … … 185 198 { 186 199 RTTestSub(hTest, "Mixing write and read locks"); 187 188 MediumState_T mediumState = MediumState_NotCreated; 189 TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting state"); 190 if (mediumState != MediumState_Created) 191 RTTestFailed(hTest, "wrong medium state %d", mediumState); 192 193 TEST_COM_SUCCESS(hTest, pMedium->LockWrite(&mediumState), "write lock"); 200 ComPtr<IToken> pToken1, pToken2; 201 202 MediumState_T mediumState = MediumState_NotCreated; 203 TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting state"); 204 if (mediumState != MediumState_Created) 205 RTTestFailed(hTest, "wrong medium state %d", mediumState); 206 207 TEST_COM_SUCCESS(hTest, pMedium->LockWrite(pToken1.asOutParam()), "write lock"); 194 208 195 209 TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting lock write state"); … … 197 211 RTTestFailed(hTest, "wrong lock write medium state %d", mediumState); 198 212 199 TEST_COM_FAILURE(hTest, pMedium->LockRead(&mediumState), "write+read lock succeeded"); 213 TEST_COM_FAILURE(hTest, pMedium->LockRead(pToken2.asOutParam()), "write+read lock succeeded"); 214 if (!pToken2.isNull()) 215 RTTestFailed(hTest, "pToken2 is not null"); 200 216 201 217 TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting after nested lock write state"); … … 203 219 RTTestFailed(hTest, "wrong after nested lock write medium state %d", mediumState); 204 220 205 TEST_COM_SUCCESS(hTest, pMedium->UnlockWrite(&mediumState), "write unlock"); 221 if (!pToken1.isNull()) 222 TEST_COM_SUCCESS(hTest, pToken1->Abandon(), "write unlock"); 223 else 224 RTTestFailed(hTest, "pToken1 is null"); 206 225 207 226 TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting unlock write state"); … … 213 232 { 214 233 RTTestSub(hTest, "Mixing read and write locks"); 215 216 MediumState_T mediumState = MediumState_NotCreated; 217 TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting state"); 218 if (mediumState != MediumState_Created) 219 RTTestFailed(hTest, "wrong medium state %d", mediumState); 220 221 TEST_COM_SUCCESS(hTest, pMedium->LockRead(&mediumState), "read lock"); 234 ComPtr<IToken> pToken1, pToken2; 235 236 MediumState_T mediumState = MediumState_NotCreated; 237 TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting state"); 238 if (mediumState != MediumState_Created) 239 RTTestFailed(hTest, "wrong medium state %d", mediumState); 240 241 TEST_COM_SUCCESS(hTest, pMedium->LockRead(pToken1.asOutParam()), "read lock"); 222 242 223 243 TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting lock read state"); … … 225 245 RTTestFailed(hTest, "wrong lock read medium state %d", mediumState); 226 246 227 TEST_COM_FAILURE(hTest, pMedium->LockWrite(&mediumState), "read+write lock succeeded"); 247 TEST_COM_FAILURE(hTest, pMedium->LockWrite(pToken2.asOutParam()), "read+write lock succeeded"); 248 if (!pToken2.isNull()) 249 RTTestFailed(hTest, "pToken2 is not null"); 228 250 229 251 TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting after nested lock read state"); … … 231 253 RTTestFailed(hTest, "wrong after nested lock read medium state %d", mediumState); 232 254 233 TEST_COM_SUCCESS(hTest, pMedium->UnlockRead(&mediumState), "read unlock"); 234 235 TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting unlock read state"); 236 if (mediumState != MediumState_Created) 237 RTTestFailed(hTest, "wrong unlock read medium state %d", mediumState); 238 } 239 240 if (!RTTestSubErrorCount(hTest)) 241 { 242 RTTestSub(hTest, "Write locks, read unlocks"); 243 244 MediumState_T mediumState = MediumState_NotCreated; 245 TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting state"); 246 if (mediumState != MediumState_Created) 247 RTTestFailed(hTest, "wrong medium state %d", mediumState); 248 249 TEST_COM_SUCCESS(hTest, pMedium->LockWrite(&mediumState), "write lock"); 250 251 TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting lock write state"); 252 if (mediumState != MediumState_LockedWrite) 253 RTTestFailed(hTest, "wrong lock write medium state %d", mediumState); 254 255 TEST_COM_FAILURE(hTest, pMedium->UnlockRead(&mediumState), "read unlocking a write lock succeeded"); 256 257 TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting after read unlock write state"); 258 if (mediumState != MediumState_LockedWrite) 259 RTTestFailed(hTest, "wrong after read lock write medium state %d", mediumState); 260 261 TEST_COM_SUCCESS(hTest, pMedium->UnlockWrite(&mediumState), "write unlock"); 262 263 TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting unlock write state"); 264 if (mediumState != MediumState_Created) 265 RTTestFailed(hTest, "wrong unlock write medium state %d", mediumState); 266 } 267 268 if (!RTTestSubErrorCount(hTest)) 269 { 270 RTTestSub(hTest, "Read locks, write unlocks"); 271 272 MediumState_T mediumState = MediumState_NotCreated; 273 TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting state"); 274 if (mediumState != MediumState_Created) 275 RTTestFailed(hTest, "wrong medium state %d", mediumState); 276 277 TEST_COM_SUCCESS(hTest, pMedium->LockRead(&mediumState), "read lock"); 278 279 TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting lock read state"); 280 if (mediumState != MediumState_LockedRead) 281 RTTestFailed(hTest, "wrong lock write medium state %d", mediumState); 282 283 TEST_COM_FAILURE(hTest, pMedium->UnlockWrite(&mediumState), "write unlocking a read lock succeeded"); 284 285 TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting after write unlock read state"); 286 if (mediumState != MediumState_LockedRead) 287 RTTestFailed(hTest, "wrong after write lock read medium state %d", mediumState); 288 289 TEST_COM_SUCCESS(hTest, pMedium->UnlockRead(&mediumState), "read unlock"); 255 if (!pToken1.isNull()) 256 TEST_COM_SUCCESS(hTest, pToken1->Abandon(), "read unlock"); 257 else 258 RTTestFailed(hTest, "pToken1 is null"); 290 259 291 260 TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting unlock read state");
Note:
See TracChangeset
for help on using the changeset viewer.