VirtualBox

Changeset 48297 in vbox for trunk/src/VBox/Main


Ignore:
Timestamp:
Sep 5, 2013 9:57:44 AM (11 years ago)
Author:
vboxsync
Message:

Main/Medium: redesign API level medium locking, needed conversions from MediaList to MediumLockLists in several places, forced cleanups elsewhere, too
Main/Token: introduced token objects for controlling the unlocking, will be used as a general concept in the future
Main/Snapshot: snapshot deletion needed significant cleanups as it was still using many shortcuts, directly calling the API to lock media instead of using lock lists. Now much better, and the online snapshot deletion is also a lot cleaner as it no longer passes unnecessary parameters around which are already known in the machine/snapshot code
Main/MediumLock: small improvements, now has a mode which skips locking already locked media, needed by the Snapshot code where we have overlapping lock lists and have to update the original one instead
Main/Console+Session+Machine: follow-up changes for the online snapshot merging parameter passing simplification, plus an unrelated lock order violation fix in Machine which happens only for inaccessible machines
Main/testcase: update correspondingly
doc: update SDK reference

Location:
trunk/src/VBox/Main
Files:
2 added
16 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/Makefile.kmk

    r48282 r48297  
    363363        src-server/StorageControllerImpl.cpp \
    364364        src-server/SystemPropertiesImpl.cpp \
     365        src-server/TokenImpl.cpp \
    365366        src-server/USBControllerImpl.cpp \
    366367        src-server/USBDeviceFiltersImpl.cpp \
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r48102 r48297  
    37003700      <desc>
    37013701        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>
    37223704    </method>
    37233705
     
    1361213594        write operation such as <link to="#cloneTo"/> or <link to="#mergeTo"/>.
    1361313595
    13614         The medium locked for reading must be unlocked using the <link
    13615         to="#unlockRead"/> method. Calls to <link to="#lockRead"/>
    13616         can be nested and must be followed by the same number of paired
    13617         <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.
    1361813600
    1361913601        This method sets the medium state (see <link to="#state"/>) to
     
    1363513617
    1363613618      </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.
    1366113624        </desc>
    1366213625      </param>
     
    1368913652        write operation such as <link to="#cloneTo"/> or <link to="#mergeTo"/>.
    1369013653
    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.
    1369313657
    1369413658        This method sets the medium state (see <link to="#state"/>) to
     
    1370113665        storage unit.
    1370213666
    13703         For both, success and failure, this method returns the current
    13704         state of the medium <i>before</i> the operation.
    13705 
    1370613667        <result name="VBOX_E_INVALID_OBJECT_STATE">
    1370713668          Invalid medium state (e.g. not created, locked, inaccessible,
     
    1371013671
    1371113672      </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.
    1373613677        </desc>
    1373713678      </param>
     
    1449414435
    1449514436  <!--
     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  <!--
    1449614477  // IKeyboard
    1449714478  /////////////////////////////////////////////////////////////////////////
     
    1450914490      Use this interface to send keystrokes or the Ctrl-Alt-Del sequence
    1451014491      to the virtual machine.
    14511 
    1451214492    </desc>
     14493
    1451314494    <method name="putScancode">
    1451414495      <desc>Sends a scancode to the keyboard.
     
    1793917920        <desc>The index of the target image in the chain.
    1794017921        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 UUID
    17956         updated.</desc>
    1795717922      </param>
    1795817923      <param name="progress" type="IProgress" dir="in">
  • trunk/src/VBox/Main/include/ConsoleImpl.h

    r48054 r48297  
    230230    HRESULT onlineMergeMedium(IMediumAttachment *aMediumAttachment,
    231231                              ULONG aSourceIdx, ULONG aTargetIdx,
    232                               IMedium *aSource, IMedium *aTarget,
    233                               BOOL aMergeForward, IMedium *aParentForTarget,
    234                               ComSafeArrayIn(IMedium *, aChildrenToReparent),
    235232                              IProgress *aProgress);
    236233    VMMDev *getVMMDev() { return m_pVMMDev; }
  • trunk/src/VBox/Main/include/MachineImpl.h

    r47991 r48297  
    10701070                              IN_BSTR aEndID, BOOL fDeleteAllChildren,
    10711071                              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)();
    10771073    STDMETHOD(RestoreSnapshot)(IConsole *aInitiator,
    10781074                               ISnapshot *aSnapshot,
     
    11431139    {
    11441140        ConsoleTaskData()
    1145             : mLastState(MachineState_Null)
     1141            : mLastState(MachineState_Null), mDeleteSnapshotInfo(NULL)
    11461142        { }
    11471143
     
    11511147        // used when taking snapshot
    11521148        ComObjPtr<Snapshot> mSnapshot;
     1149
     1150        // used when deleting online snapshot
     1151        void *mDeleteSnapshotInfo;
    11531152
    11541153        // used when saving state (either as part of a snapshot or separate)
     
    11851184                                        bool &fMergeForward,
    11861185                                        ComObjPtr<Medium> &pParentForTarget,
    1187                                         MediaList &aChildrenToReparent,
     1186                                        MediumLockList * &aChildrenToReparent,
    11881187                                        bool &fNeedOnlineMerge,
    1189                                         MediumLockList * &aMediumLockList);
     1188                                        MediumLockList * &aMediumLockList,
     1189                                        ComPtr<IToken> &aHDLockToken);
    11901190    void cancelDeleteSnapshotMedium(const ComObjPtr<Medium> &aHD,
    11911191                                    const ComObjPtr<Medium> &aSource,
    1192                                     const MediaList &aChildrenToReparent,
     1192                                    MediumLockList *aChildrenToReparent,
    11931193                                    bool fNeedsOnlineMerge,
    11941194                                    MediumLockList *aMediumLockList,
     1195                                    const ComPtr<IToken> &aHDLockToken,
    11951196                                    const Guid &aMediumId,
    11961197                                    const Guid &aSnapshotId);
     
    12001201                              bool fMergeForward,
    12011202                              const ComObjPtr<Medium> &pParentForTarget,
    1202                               const MediaList &aChildrenToReparent,
     1203                              MediumLockList *aChildrenToReparent,
    12031204                              MediumLockList *aMediumLockList,
    12041205                              ComObjPtr<Progress> &aProgress,
  • trunk/src/VBox/Main/include/MediumImpl.h

    r44528 r48297  
    132132    STDMETHOD(GetSnapshotIds)(IN_BSTR aMachineId,
    133133                              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);
    138136    STDMETHOD(Close)();
    139137    STDMETHOD(GetProperty)(IN_BSTR aName, BSTR *aValue);
     
    226224
    227225    HRESULT close(AutoCaller &autoCaller);
     226    HRESULT unlockRead(MediumState_T *aState);
     227    HRESULT unlockWrite(MediumState_T *aState);
    228228    HRESULT deleteStorage(ComObjPtr<Progress> *aProgress, bool aWait);
    229229    HRESULT markForDeletion();
     
    241241                           bool &fMergeForward,
    242242                           ComObjPtr<Medium> &pParentForTarget,
    243                            MediaList &aChildrenToReparent,
     243                           MediumLockList * &aChildrenToReparent,
    244244                           MediumLockList * &aMediumLockList);
    245245    HRESULT mergeTo(const ComObjPtr<Medium> &pTarget,
    246246                    bool fMergeForward,
    247247                    const ComObjPtr<Medium> &pParentForTarget,
    248                     const MediaList &aChildrenToReparent,
     248                    MediumLockList *aChildrenToReparent,
    249249                    MediumLockList *aMediumLockList,
    250250                    ComObjPtr<Progress> *aProgress,
    251251                    bool aWait);
    252     void cancelMergeTo(const MediaList &aChildrenToReparent,
     252    void cancelMergeTo(MediumLockList *aChildrenToReparent,
    253253                       MediumLockList *aMediumLockList);
    254254
    255     HRESULT fixParentUuidOfChildren(const MediaList &childrenToReparent);
     255    HRESULT fixParentUuidOfChildren(MediumLockList *pChildrenToReparent);
    256256
    257257    HRESULT exportFile(const char *aFilename,
  • trunk/src/VBox/Main/include/MediumLock.h

    r44529 r48297  
    77
    88/*
    9  * Copyright (C) 2010-2012 Oracle Corporation
     9 * Copyright (C) 2010-2013 Oracle Corporation
    1010 *
    1111 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    9090
    9191    /**
     92     * Check if this medium object has been locked by this MediumLock.
     93     */
     94    bool IsLocked() const;
     95
     96    /**
    9297     * Acquire a medium lock.
    9398     *
    9499     * @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);
    97104
    98105    /**
     
    105112private:
    106113    ComObjPtr<Medium> mMedium;
     114    ComPtr<IToken> mToken;
    107115    AutoCaller mMediumCaller;
    108116    bool mLockWrite;
     
    208216     *
    209217     * @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);
    212226
    213227    /**
  • trunk/src/VBox/Main/include/SessionImpl.h

    r48282 r48297  
    103103    STDMETHOD(OnlineMergeMedium)(IMediumAttachment *aMediumAttachment,
    104104                                 ULONG aSourceIdx, ULONG aTargetIdx,
    105                                  IMedium *aSource, IMedium *aTarget,
    106                                  BOOL aMergeForward, IMedium *aParentForTarget,
    107                                  ComSafeArrayIn(IMedium *, aChildrenToReparent),
    108105                                 IProgress *aProgress);
    109106    STDMETHOD(EnableVMMStatistics)(BOOL aEnable);
  • trunk/src/VBox/Main/include/VirtualBoxImpl.h

    r47561 r48297  
    311311    AutostartDb* getAutostartDb() const;
    312312
     313    RWLockHandle& getMachinesListLockHandle();
    313314    RWLockHandle& getMediaTreeLockHandle();
    314315
  • trunk/src/VBox/Main/src-client/ConsoleImpl.cpp

    r48054 r48297  
    55285528HRESULT Console::onlineMergeMedium(IMediumAttachment *aMediumAttachment,
    55295529                                   ULONG aSourceIdx, ULONG aTargetIdx,
    5530                                    IMedium *aSource, IMedium *aTarget,
    5531                                    BOOL aMergeForward,
    5532                                    IMedium *aParentForTarget,
    5533                                    ComSafeArrayIn(IMedium *, aChildrenToReparent),
    55345530                                   IProgress *aProgress)
    55355531{
     
    57085704
    57095705    /* 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();
    57135707
    57145708    vrc = VMR3ReqCallWaitU(ptrVM.rawUVM(),
  • trunk/src/VBox/Main/src-client/SessionImpl.cpp

    r48282 r48297  
    980980STDMETHODIMP Session::OnlineMergeMedium(IMediumAttachment *aMediumAttachment,
    981981                                        ULONG aSourceIdx, ULONG aTargetIdx,
    982                                         IMedium *aSource, IMedium *aTarget,
    983                                         BOOL aMergeForward,
    984                                         IMedium *aParentForTarget,
    985                                         ComSafeArrayIn(IMedium *, aChildrenToReparent),
    986982                                        IProgress *aProgress)
    987983{
     
    997993    AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
    998994    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,
    1005998                                       aProgress);
    1006999#else
  • trunk/src/VBox/Main/src-server/MachineImpl.cpp

    r48295 r48297  
    903903    LogFlowThisFunc(("ENTER\n"));
    904904
     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);
    905909    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    906910
  • trunk/src/VBox/Main/src-server/MediumImpl.cpp

    r47920 r48297  
    1717
    1818#include "MediumImpl.h"
     19#include "TokenImpl.h"
    1920#include "ProgressImpl.h"
    2021#include "SystemPropertiesImpl.h"
     
    515516              bool fMergeForward,
    516517              Medium *aParentForTarget,
    517               const MediaList &aChildrenToReparent,
     518              MediumLockList *aChildrenToReparent,
    518519              Progress *aProgress,
    519520              MediumLockList *aMediumLockList,
     
    523524          mfMergeForward(fMergeForward),
    524525          mParentForTarget(aParentForTarget),
    525           mChildrenToReparent(aChildrenToReparent),
     526          mpChildrenToReparent(aChildrenToReparent),
    526527          mpMediumLockList(aMediumLockList),
    527528          mTargetCaller(aTarget),
    528529          mParentForTargetCaller(aParentForTarget),
    529           mfChildrenCaller(false),
    530530          mfKeepMediumLockList(fKeepMediumLockList)
    531531    {
    532532        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;
    551533    }
    552534
     
    555537        if (!mfKeepMediumLockList && mpMediumLockList)
    556538            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;
    566541    }
    567542
    568543    const ComObjPtr<Medium> mTarget;
    569544    bool mfMergeForward;
    570     /* When mChildrenToReparent 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. */
    572547    const ComObjPtr<Medium> mParentForTarget;
    573     MediaList mChildrenToReparent;
     548    MediumLockList *mpChildrenToReparent;
    574549    MediumLockList *mpMediumLockList;
    575550
     
    579554    AutoCaller mTargetCaller;
    580555    AutoCaller mParentForTargetCaller;
    581     bool mfChildrenCaller;
    582556    bool mfKeepMediumLockList;
    583557};
     
    21232097}
    21242098
    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 {
     2099STDMETHODIMP Medium::LockRead(IToken **aToken)
     2100{
     2101    CheckComArgNotNull(aToken);
     2102
    21312103    AutoCaller autoCaller(this);
    21322104    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     
    21522124    }
    21532125
    2154     /* return the current state before */
    2155     if (aState)
    2156         *aState = m->state;
    2157 
    21582126    HRESULT rc = S_OK;
    21592127
     
    21752143            m->state = MediumState_LockedRead;
    21762144
     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);
    21772158            break;
    21782159        }
     
    21922173 *       in-process calls).
    21932174 */
    2194 STDMETHODIMP Medium::UnlockRead(MediumState_T *aState)
     2175HRESULT Medium::unlockRead(MediumState_T *aState)
    21952176{
    21962177    AutoCaller autoCaller(this);
     
    22392220}
    22402221
    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 {
     2222STDMETHODIMP Medium::LockWrite(IToken **aToken)
     2223{
     2224    CheckComArgNotNull(aToken);
     2225
    22472226    AutoCaller autoCaller(this);
    22482227    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     
    22682247    }
    22692248
    2270     /* return the current state before */
    2271     if (aState)
    2272         *aState = m->state;
    2273 
    22742249    HRESULT rc = S_OK;
    22752250
     
    22832258            LogFlowThisFunc(("Okay - prev state=%d locationFull=%s\n", m->state, getLocationFull().c_str()));
    22842259            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);
    22852272            break;
    22862273        }
     
    23002287 *       in-process calls).
    23012288 */
    2302 STDMETHODIMP Medium::UnlockWrite(MediumState_T *aState)
     2289HRESULT Medium::unlockWrite(MediumState_T *aState)
    23032290{
    23042291    AutoCaller autoCaller(this);
     
    25382525
    25392526    HRESULT rc = S_OK;
    2540     ComObjPtr <Progress> pProgress;
     2527    ComObjPtr<Progress> pProgress;
    25412528    Medium::Task *pTask = NULL;
    25422529
     
    26942681    alock.release();
    26952682
    2696     ComObjPtr <Progress> pProgress;
     2683    ComObjPtr<Progress> pProgress;
    26972684
    26982685    ULONG mediumVariantFlags = 0;
     
    27282715    bool fMergeForward = false;
    27292716    ComObjPtr<Medium> pParentForTarget;
    2730     MediaList childrenToReparent;
     2717    MediumLockList *pChildrenToReparent = NULL;
    27312718    MediumLockList *pMediumLockList = NULL;
    27322719
     
    27342721
    27352722    rc = prepareMergeTo(pTarget, NULL, NULL, true, fMergeForward,
    2736                         pParentForTarget, childrenToReparent, pMediumLockList);
     2723                        pParentForTarget, pChildrenToReparent, pMediumLockList);
    27372724    if (FAILED(rc)) return rc;
    27382725
    2739     ComObjPtr <Progress> pProgress;
    2740 
    2741     rc = mergeTo(pTarget, fMergeForward, pParentForTarget, childrenToReparent,
     2726    ComObjPtr<Progress> pProgress;
     2727
     2728    rc = mergeTo(pTarget, fMergeForward, pParentForTarget, pChildrenToReparent,
    27422729                 pMediumLockList, &pProgress, false /* aWait */);
    27432730    if (FAILED(rc))
    2744         cancelMergeTo(childrenToReparent, pMediumLockList);
     2731        cancelMergeTo(pChildrenToReparent, pMediumLockList);
    27452732    else
    27462733        pProgress.queryInterfaceTo(aProgress);
     
    29152902
    29162903    HRESULT rc = S_OK;
    2917     ComObjPtr <Progress> pProgress;
     2904    ComObjPtr<Progress> pProgress;
    29182905    Medium::Task *pTask = NULL;
    29192906
     
    29882975
    29892976    HRESULT rc = S_OK;
    2990     ComObjPtr <Progress> pProgress;
     2977    ComObjPtr<Progress> pProgress;
    29912978    Medium::Task *pTask = NULL;
    29922979
     
    30613048
    30623049    HRESULT rc = S_OK;
    3063     ComObjPtr <Progress> pProgress;
     3050    ComObjPtr<Progress> pProgress;
    30643051    Medium::Task *pTask = NULL;
    30653052
     
    46654652 * @param fMergeForward Resulting merge direction (out).
    46664653 * @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).
    46694657 * @param aMediumLockList Medium locking information (out).
    46704658 *
     
    46784666                               bool &fMergeForward,
    46794667                               ComObjPtr<Medium> &pParentForTarget,
    4680                                MediaList &aChildrenToReparent,
     4668                               MediumLockList * &aChildrenToReparent,
    46814669                               MediumLockList * &aMediumLockList)
    46824670{
     
    46934681    fMergeForward = false;
    46944682    pParentForTarget.setNull();
    4695     aChildrenToReparent.clear();
     4683    Assert(aChildrenToReparent == NULL);
     4684    aChildrenToReparent = NULL;
    46964685    Assert(aMediumLockList == NULL);
    46974686    aMediumLockList = NULL;
     
    48764865        {
    48774866            /* we will need to reparent children of the source */
     4867            aChildrenToReparent = new MediumLockList();
    48784868            for (MediaList::const_iterator it = getChildren().begin();
    48794869                 it != getChildren().end();
     
    48814871            {
    48824872                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;
    48914882            }
    48924883        }
     
    49474938    if (FAILED(rc))
    49484939    {
    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        }
    49514950    }
    49524951
     
    50335032                        bool fMergeForward,
    50345033                        const ComObjPtr<Medium> &pParentForTarget,
    5035                         const MediaList &aChildrenToReparent,
     5034                        MediumLockList *aChildrenToReparent,
    50365035                        MediumLockList *aMediumLockList,
    5037                         ComObjPtr <Progress> *aProgress,
     5036                        ComObjPtr<Progress> *aProgress,
    50385037                        bool aWait)
    50395038{
     
    50505049
    50515050    HRESULT rc = S_OK;
    5052     ComObjPtr <Progress> pProgress;
     5051    ComObjPtr<Progress> pProgress;
    50535052    Medium::Task *pTask = NULL;
    50545053
     
    51225121 * @note Locks the media from the chain for writing.
    51235122 */
    5124 void Medium::cancelMergeTo(const MediaList &aChildrenToReparent,
     5123void Medium::cancelMergeTo(MediumLockList *aChildrenToReparent,
    51255124                           MediumLockList *aMediumLockList)
    51265125{
     
    51545153    delete aMediumLockList;
    51555154
    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;
    51665159}
    51675160
     
    51705163 * parent.
    51715164 */
    5172 HRESULT Medium::fixParentUuidOfChildren(const MediaList &childrenToReparent)
     5165HRESULT Medium::fixParentUuidOfChildren(MediumLockList *pChildrenToReparent)
    51735166{
    51745167    Assert(!isWriteLockOnCurrentThread());
     
    52115204            }
    52125205
    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;
    52155210                 ++it)
    52165211            {
     5212                Medium *pMedium = it->GetMedium();
    52175213                /* VD_OPEN_FLAGS_INFO since UUID is wrong yet */
    52185214                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(),
    52215217                             VD_OPEN_FLAGS_INFO | m->uOpenFlagsDef,
    5222                              (*it)->m->vdImageIfaces);
     5218                             pMedium->m->vdImageIfaces);
    52235219                if (RT_FAILURE(vrc))
    52245220                    throw vrc;
     
    52315227                if (RT_FAILURE(vrc))
    52325228                    throw vrc;
    5233 
    5234                 (*it)->UnlockWrite(NULL);
    52355229            }
    52365230        }
     
    56485642    /* Lock the medium, which makes the behavior much more consistent */
    56495643    alock.release();
     5644    ComPtr<IToken> pToken;
    56505645    if (uOpenFlags & (VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_SHAREABLE))
    5651         rc = LockRead(NULL);
     5646        rc = LockRead(pToken.asOutParam());
    56525647    else
    5653         rc = LockWrite(NULL);
     5648        rc = LockWrite(pToken.asOutParam());
    56545649    if (FAILED(rc)) return rc;
    56555650    alock.acquire();
     
    59895984        m->preLockState = MediumState_Inaccessible;
    59905985
    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   
    59985989    if (FAILED(rc)) return rc;
    59995990
     
    60065997    if (fRepairImageZeroParentUuid)
    60075998    {
    6008         rc = LockWrite(NULL);
     5999        rc = LockWrite(pToken.asOutParam());
    60096000        if (FAILED(rc)) return rc;
    60106001
     
    60446035        }
    60456036
    6046         rc = UnlockWrite(NULL);
    6047         if (SUCCEEDED(rc) && FAILED(rc2))
    6048             rc = rc2;
     6037        pToken->Abandon();
     6038        pToken.setNull();
    60496039        if (FAILED(rc)) return rc;
    60506040    }
     
    72147204                 * which cannot be part of the container at once so
    72157205                 * add each one in there individually */
    7216                 if (task.mChildrenToReparent.size() > 0)
     7206                if (task.mpChildrenToReparent)
    72177207                {
    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;
    72207212                         ++it)
    72217213                    {
     7214                        Medium *pMedium = it->GetMedium();
    72227215                        /* VD_OPEN_FLAGS_INFO since UUID is wrong yet */
    72237216                        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(),
    72267219                                     VD_OPEN_FLAGS_INFO | m->uOpenFlagsDef,
    7227                                      (*it)->m->vdImageIfaces);
     7220                                     pMedium->m->vdImageIfaces);
    72287221                        if (RT_FAILURE(vrc))
    72297222                            throw vrc;
     
    72377230                        if (RT_FAILURE(vrc))
    72387231                            throw vrc;
    7239 
    7240                         (*it)->UnlockWrite(NULL);
    72417232                    }
    72427233                }
     
    73017292            /* reparent source's children and disconnect the deleted
    73027293             * branch at the younger end */
    7303             if (task.mChildrenToReparent.size() > 0)
     7294            if (task.mpChildrenToReparent)
    73047295            {
    73057296                /* obey {parent,child} lock order */
    73067297                AutoWriteLock sourceLock(this COMMA_LOCKVAL_SRC_POS);
    73077298
    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)
    73117304                {
    7312                     Medium *pMedium = *it;
     7305                    Medium *pMedium = it->GetMedium();
    73137306                    AutoWriteLock childLock(pMedium COMMA_LOCKVAL_SRC_POS);
    73147307
     
    73967389         * don't own the merge chain, so release it in this case. */
    73977390        if (task.isAsync())
    7398         {
    7399             Assert(task.mChildrenToReparent.size() == 0);
    7400             cancelMergeTo(task.mChildrenToReparent, task.mpMediumLockList);
    7401         }
     7391            cancelMergeTo(task.mpChildrenToReparent, task.mpMediumLockList);
    74027392    }
    74037393
  • trunk/src/VBox/Main/src-server/MediumLock.cpp

    r45595 r48297  
    55
    66/*
    7  * Copyright (C) 2010 Oracle Corporation
     7 * Copyright (C) 2010-2013 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    7575}
    7676
    77 HRESULT MediumLock::Lock()
     77bool MediumLock::IsLocked() const
     78{
     79    return mIsLocked;
     80}
     81
     82HRESULT MediumLock::Lock(bool aIgnoreLockedMedia)
    7883{
    7984    if (mIsLocked)
     
    102107        default:
    103108            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            }
    105116            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            }
    107123    }
    108124    if (SUCCEEDED(rc))
     
    121137{
    122138    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();
    129143    }
    130144    mMediumCaller.attach(NULL);
     
    202216}
    203217
    204 HRESULT MediumLockList::Lock()
     218HRESULT MediumLockList::Lock(bool fSkipOverLockedMedia /* = false */)
    205219{
    206220    if (mIsLocked)
     
    211225         it++)
    212226    {
    213         rc = it->Lock();
     227        rc = it->Lock(fSkipOverLockedMedia);
    214228        if (FAILED(rc))
    215229        {
  • trunk/src/VBox/Main/src-server/SnapshotImpl.cpp

    r47401 r48297  
    21042104
    21052105/**
    2106  * Implementation for IInternalMachineControl::deleteSnapshot().
     2106 * Implementation for IInternalMachineControl::DeleteSnapshot().
    21072107 *
    21082108 * Gets called from Console::DeleteSnapshot(), and that's basically the
     
    22942294                    bool fMergeForward,
    22952295                    const ComObjPtr<Medium> &aParentForTarget,
    2296                     const MediaList &aChildrenToReparent,
     2296                    MediumLockList *aChildrenToReparent,
    22972297                    bool fNeedsOnlineMerge,
    2298                     MediumLockList *aMediumLockList)
     2298                    MediumLockList *aMediumLockList,
     2299                    const ComPtr<IToken> &aHDLockToken)
    22992300        : mpHD(aHd),
    23002301          mpSource(aSource),
     
    23032304          mfMergeForward(fMergeForward),
    23042305          mpParentForTarget(aParentForTarget),
    2305           mChildrenToReparent(aChildrenToReparent),
     2306          mpChildrenToReparent(aChildrenToReparent),
    23062307          mfNeedsOnlineMerge(fNeedsOnlineMerge),
    2307           mpMediumLockList(aMediumLockList)
     2308          mpMediumLockList(aMediumLockList),
     2309          mpHDLockToken(aHDLockToken)
    23082310    {}
    23092311
     
    23142316                    bool fMergeForward,
    23152317                    const ComObjPtr<Medium> &aParentForTarget,
    2316                     const MediaList &aChildrenToReparent,
     2318                    MediumLockList *aChildrenToReparent,
    23172319                    bool fNeedsOnlineMerge,
    23182320                    MediumLockList *aMediumLockList,
     2321                    const ComPtr<IToken> &aHDLockToken,
    23192322                    const Guid &aMachineId,
    23202323                    const Guid &aSnapshotId)
     
    23252328          mfMergeForward(fMergeForward),
    23262329          mpParentForTarget(aParentForTarget),
    2327           mChildrenToReparent(aChildrenToReparent),
     2330          mpChildrenToReparent(aChildrenToReparent),
    23282331          mfNeedsOnlineMerge(fNeedsOnlineMerge),
    23292332          mpMediumLockList(aMediumLockList),
     2333          mpHDLockToken(aHDLockToken),
    23302334          mMachineId(aMachineId),
    23312335          mSnapshotId(aSnapshotId)
     
    23382342    bool mfMergeForward;
    23392343    ComObjPtr<Medium> mpParentForTarget;
    2340     MediaList mChildrenToReparent;
     2344    MediumLockList *mpChildrenToReparent;
    23412345    bool mfNeedsOnlineMerge;
    23422346    MediumLockList *mpMediumLockList;
     2347    /** optional lock token, used only in case mpHD is not merged/deleted */
     2348    ComPtr<IToken> mpHDLockToken;
    23432349    /* these are for reattaching the hard disk in case of a failure: */
    23442350    Guid mMachineId;
     
    24502456            bool fMergeForward = false;
    24512457            ComObjPtr<Medium> pParentForTarget;
    2452             MediaList childrenToReparent;
     2458            MediumLockList *pChildrenToReparent = NULL;
    24532459            bool fNeedsOnlineMerge = false;
    24542460            bool fOnlineMergePossible = aTask.m_fDeleteOnline;
    24552461            MediumLockList *pMediumLockList = NULL;
    24562462            MediumLockList *pVMMALockList = NULL;
     2463            ComPtr<IToken> pHDLockToken;
    24572464            ComObjPtr<MediumAttachment> pOnlineMediumAttachment;
    24582465            if (fOnlineMergePossible)
     
    24872494                                             pVMMALockList, pSource, pTarget,
    24882495                                             fMergeForward, pParentForTarget,
    2489                                              childrenToReparent,
     2496                                             pChildrenToReparent,
    24902497                                             fNeedsOnlineMerge,
    2491                                              pMediumLockList);
     2498                                             pMediumLockList,
     2499                                             pHDLockToken);
    24922500            treeLock.acquire();
    24932501            if (FAILED(rc))
     
    25452553                                                   fMergeForward,
    25462554                                                   pParentForTarget,
    2547                                                    childrenToReparent,
     2555                                                   pChildrenToReparent,
    25482556                                                   fNeedsOnlineMerge,
    25492557                                                   pMediumLockList,
     2558                                                   pHDLockToken,
    25502559                                                   replaceMachineId,
    25512560                                                   replaceSnapshotId));
     
    25562565                                                   fMergeForward,
    25572566                                                   pParentForTarget,
    2558                                                    childrenToReparent,
     2567                                                   pChildrenToReparent,
    25592568                                                   fNeedsOnlineMerge,
    2560                                                    pMediumLockList));
     2569                                                   pMediumLockList,
     2570                                                   pHDLockToken));
    25612571        }
    25622572
     
    27562766                if (it->mfNeedsOnlineMerge)
    27572767                {
     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);
    27582773                    // online medium merge, in the direction decided earlier
    27592774                    rc = onlineMergeMedium(it->mpOnlineMediumAttachment,
     
    27622777                                           it->mfMergeForward,
    27632778                                           it->mpParentForTarget,
    2764                                            it->mChildrenToReparent,
     2779                                           it->mpChildrenToReparent,
    27652780                                           it->mpMediumLockList,
    27662781                                           aTask.pProgress,
    27672782                                           &fNeedsSave);
     2783                    mConsoleTaskData.mDeleteSnapshotInfo = NULL;
    27682784                }
    27692785                else
     
    27732789                                               it->mfMergeForward,
    27742790                                               it->mpParentForTarget,
    2775                                                it->mChildrenToReparent,
     2791                                               it->mpChildrenToReparent,
    27762792                                               it->mpMediumLockList,
    27772793                                               &aTask.pProgress,
     
    29122928        {
    29132929            cancelDeleteSnapshotMedium(it->mpHD, it->mpSource,
    2914                                        it->mChildrenToReparent,
     2930                                       it->mpChildrenToReparent,
    29152931                                       it->mfNeedsOnlineMerge,
    2916                                        it->mpMediumLockList, it->mMachineId,
    2917                                        it->mSnapshotId);
     2932                                       it->mpMediumLockList, it->mpHDLockToken,
     2933                                       it->mMachineId, it->mSnapshotId);
    29182934        }
    29192935    }
     
    29662982 * @param aMergeForward Merge direction decision (out).
    29672983 * @param aParentForTarget New parent if target needs to be reparented (out).
    2968  * @param aChildrenToReparent Children which have to be reparented to the
    2969  *                      target (out).
     2984 * @param aChildrenToReparent MediumLockList with children which have to be
     2985 *                      reparented to the target (out).
    29702986 * @param fNeedsOnlineMerge Whether this merge needs to be done online (out).
    29712987 *                      If this is set to @a true then the @a aVMMALockList
     
    29742990 * @param aMediumLockList Where to store the created medium lock list (may
    29752991 *                      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).
    29762994 *
    29772995 * @note Caller must hold media tree lock for writing. This locks this object
     
    29873005                                                    bool &aMergeForward,
    29883006                                                    ComObjPtr<Medium> &aParentForTarget,
    2989                                                     MediaList &aChildrenToReparent,
     3007                                                    MediumLockList * &aChildrenToReparent,
    29903008                                                    bool &fNeedsOnlineMerge,
    2991                                                     MediumLockList * &aMediumLockList)
     3009                                                    MediumLockList * &aMediumLockList,
     3010                                                    ComPtr<IToken> &aHDLockToken)
    29923011{
    29933012    Assert(!mParent->getMediaTreeLockHandle().isWriteLockOnCurrentThread());
     
    30023021                 && type != MediumType_Readonly, E_FAIL);
    30033022
     3023    aChildrenToReparent = NULL;
    30043024    aMediumLockList = NULL;
    30053025    fNeedsOnlineMerge = false;
     
    30183038             * is completed */
    30193039            alock.release();
    3020             return aHD->LockWrite(NULL);
     3040            return aHD->LockWrite(aHDLockToken.asOutParam());
    30213041        }
    30223042
     
    30493069            childLock.release();
    30503070            alock.release();
    3051             return aHD->LockWrite(NULL);
     3071            return aHD->LockWrite(aHDLockToken.asOutParam());
    30523072        }
    30533073
     
    31463166            {
    31473167                /* 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())
    31513169                {
    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)
    31553190                    {
    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())
    31763194                        {
    31773195                            mediumLock.release();
    31783196                            childLock.release();
    31793197                            alock.release();
    3180                             rc = pMedium->LockWrite(NULL);
     3198                            rc = aVMMALockList->Update(pMedium, true);
    31813199                            alock.acquire();
    31823200                            childLock.acquire();
     
    32653283 * @param fNeedsOnlineMerge Whether this merge needs to be done online.
    32663284 * @param aMediumLockList Medium locks to cancel.
     3285 * @param aHDLockToken  Optional write lock token for aHD.
    32673286 * @param aMachineId    Machine id to attach the medium to.
    32683287 * @param aSnapshotId   Snapshot id to attach the medium to.
     
    32723291void SessionMachine::cancelDeleteSnapshotMedium(const ComObjPtr<Medium> &aHD,
    32733292                                                const ComObjPtr<Medium> &aSource,
    3274                                                 const MediaList &aChildrenToReparent,
     3293                                                MediumLockList *aChildrenToReparent,
    32753294                                                bool fNeedsOnlineMerge,
    32763295                                                MediumLockList *aMediumLockList,
     3296                                                const ComPtr<IToken> &aHDLockToken,
    32773297                                                const Guid &aMachineId,
    32783298                                                const Guid &aSnapshotId)
     
    32863306        if (aHD->getParent().isNull())
    32873307        {
    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            }
    32903314        }
    32913315        else
     
    33543378 * @param aMergeForward Merge direction.
    33553379 * @param aParentForTarget New parent if target needs to be reparented.
    3356  * @param aChildrenToReparent Children which have to be reparented to the
    3357  *                      target.
     3380 * @param aChildrenToReparent Medium lock list with children which have to be
     3381 *                      reparented to the target.
    33583382 * @param aMediumLockList Where to store the created medium lock list (may
    33593383 *                      return NULL if no real merge is necessary).
     
    33663390                                          bool fMergeForward,
    33673391                                          const ComObjPtr<Medium> &aParentForTarget,
    3368                                           const MediaList &aChildrenToReparent,
     3392                                          MediumLockList *aChildrenToReparent,
    33693393                                          MediumLockList *aMediumLockList,
    33703394                                          ComObjPtr<Progress> &aProgress,
     
    34153439                       && uTargetIdx != (unsigned)-1, E_FAIL);
    34163440
    3417         // For forward merges, tell the VM what images need to have their
    3418         // parent UUID updated. This cannot be done in VBoxSVC, as opening
    3419         // 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 
    34233441        ComPtr<IInternalSessionControl> directControl;
    34243442        {
     
    34363454        rc = directControl->OnlineMergeMedium(aMediumAttachment,
    34373455                                              uSourceIdx, uTargetIdx,
    3438                                               aSource, aTarget,
    3439                                               fMergeForward, aParentForTarget,
    3440                                               ComSafeArrayAsInParam(childrenToReparent),
    34413456                                              aProgress);
    34423457        if (FAILED(rc))
     
    34543469
    34553470/**
    3456  * Implementation for IInternalMachineControl::finishOnlineMergeMedium().
     3471 * Implementation for IInternalMachineControl::FinishOnlineMergeMedium().
    34573472 *
    34583473 * Gets called after the successful completion of an online merge from
     
    34633478 * can continue with the updated state of the medium chain.
    34643479 */
    3465 STDMETHODIMP SessionMachine::FinishOnlineMergeMedium(IMediumAttachment *aMediumAttachment,
    3466                                                      IMedium *aSource,
    3467                                                      IMedium *aTarget,
    3468                                                      BOOL aMergeForward,
    3469                                                      IMedium *aParentForTarget,
    3470                                                      ComSafeArrayIn(IMedium *, aChildrenToReparent))
     3480STDMETHODIMP SessionMachine::FinishOnlineMergeMedium()
    34713481{
    34723482    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);
    34763485    bool fSourceHasChildren = false;
    34773486
     
    34863495    ComObjPtr<Medium> targetChild;
    34873496
    3488     if (aMergeForward)
     3497    if (pDeleteRec->mfMergeForward)
    34893498    {
    34903499        // first, unregister the target since it may become a base
    34913500        // hard disk which needs re-registration
    3492         rc = mParent->unregisterMedium(pTarget);
     3501        rc = mParent->unregisterMedium(pDeleteRec->mpTarget);
    34933502        AssertComRC(rc);
    34943503
    34953504        // then, reparent it and disconnect the deleted branch at
    34963505        // both ends (chain->parent() is source's parent)
    3497         pTarget->deparent();
    3498         pTarget->setParent(pParentForTarget);
    3499         if (pParentForTarget)
    3500             pSource->deparent();
     3506        pDeleteRec->mpTarget->deparent();
     3507        pDeleteRec->mpTarget->setParent(pDeleteRec->mpParentForTarget);
     3508        if (pDeleteRec->mpParentForTarget)
     3509            pDeleteRec->mpSource->deparent();
    35013510
    35023511        // then, register again
    3503         rc = mParent->registerMedium(pTarget, &pTarget, DeviceType_HardDisk);
     3512        rc = mParent->registerMedium(pDeleteRec->mpTarget, &pDeleteRec->mpTarget, DeviceType_HardDisk);
    35043513        AssertComRC(rc);
    35053514    }
    35063515    else
    35073516    {
    3508         Assert(pTarget->getChildren().size() == 1);
    3509         targetChild = pTarget->getChildren().front();
     3517        Assert(pDeleteRec->mpTarget->getChildren().size() == 1);
     3518        targetChild = pDeleteRec->mpTarget->getChildren().front();
    35103519
    35113520        // disconnect the deleted branch at the elder end
     
    35143523        // Update parent UUIDs of the source's children, reparent them and
    35153524        // 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())
    35183526        {
    35193527            fSourceHasChildren = true;
     
    35233531            // we must continue. The worst possible result is that the images
    35243532            // 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)
    35273548            {
    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();
    35413550                AutoWriteLock childLock(pMedium COMMA_LOCKVAL_SRC_POS);
    35423551
    35433552                pMedium->deparent();  // removes pMedium from source
    3544                 pMedium->setParent(pTarget);
     3553                pMedium->setParent(pDeleteRec->mpTarget);
    35453554            }
    35463555        }
     
    35493558    /* unregister and uninitialize all hard disks removed by the merge */
    35503559    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;
    35543562    AssertReturn(SUCCEEDED(rc) && pMediumLockList, E_FAIL);
    35553563    MediumLockList::Base::iterator lockListBegin =
     
    35673575
    35683576        /* The target and all images not merged (readonly) are skipped */
    3569         if (   pMedium == pTarget
     3577        if (   pMedium == pDeleteRec->mpTarget
    35703578            || pMedium->getState() == MediumState_LockedRead)
    35713579        {
     
    35893597             * and therefore we cannot uninit() it (it's therefore
    35903598             * the caller's responsibility) */
    3591             if (pMedium == aSource)
     3599            if (pMedium == pDeleteRec->mpSource)
    35923600            {
    3593                 Assert(pSource->getChildren().size() == 0);
    3594                 Assert(pSource->getFirstMachineBackrefId() == NULL);
     3601                Assert(pDeleteRec->mpSource->getChildren().size() == 0);
     3602                Assert(pDeleteRec->mpSource->getFirstMachineBackrefId() == NULL);
    35953603            }
    35963604
     
    36283636     * attachment, as the previously associated one (source) is now deleted.
    36293637     * Without the immediate update the VM could not continue running. */
    3630     if (!aMergeForward && !fSourceHasChildren)
    3631     {
    3632         AutoWriteLock attLock(pMediumAttachment COMMA_LOCKVAL_SRC_POS);
    3633         pMediumAttachment->updateMedium(pTarget);
     3638    if (!pDeleteRec->mfMergeForward && !fSourceHasChildren)
     3639    {
     3640        AutoWriteLock attLock(pDeleteRec->mpOnlineMediumAttachment COMMA_LOCKVAL_SRC_POS);
     3641        pDeleteRec->mpOnlineMediumAttachment->updateMedium(pDeleteRec->mpTarget);
    36343642    }
    36353643
  • trunk/src/VBox/Main/src-server/VirtualBoxImpl.cpp

    r47597 r48297  
    47324732
    47334733/**
     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 */
     4740RWLockHandle& VirtualBox::getMachinesListLockHandle()
     4741{
     4742    return m->lockMachines;
     4743}
     4744
     4745/**
    47344746 * Returns the lock handle which protects the media trees (hard disks,
    47354747 * DVDs, floppies). As opposed to version 3.1 and earlier, these lists
  • trunk/src/VBox/Main/testcase/tstMediumLock.cpp

    r47779 r48297  
    123123    {
    124124        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");
    132133
    133134        TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting lock write state");
     
    135136            RTTestFailed(hTest, "wrong lock write medium state %d", mediumState);
    136137
    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");
    138141
    139142        TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting after nested lock write state");
     
    141144            RTTestFailed(hTest, "wrong after nested lock write medium state %d", mediumState);
    142145
    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");
    144150
    145151        TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting unlock write state");
     
    151157    {
    152158        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");
    160167
    161168        TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting lock read state");
     
    163170            RTTestFailed(hTest, "wrong lock read medium state %d", mediumState);
    164171
    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");
    166173
    167174        TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting after nested lock read state");
     
    169176            RTTestFailed(hTest, "wrong after nested lock read medium state %d", mediumState);
    170177
    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");
    172182
    173183        TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting after nested lock read state");
     
    175185            RTTestFailed(hTest, "wrong after nested lock read medium state %d", mediumState);
    176186
    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");
    178191
    179192        TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting unlock read state");
     
    185198    {
    186199        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");
    194208
    195209        TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting lock write state");
     
    197211            RTTestFailed(hTest, "wrong lock write medium state %d", mediumState);
    198212
    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");
    200216
    201217        TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting after nested lock write state");
     
    203219            RTTestFailed(hTest, "wrong after nested lock write medium state %d", mediumState);
    204220
    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");
    206225
    207226        TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting unlock write state");
     
    213232    {
    214233        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");
    222242
    223243        TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting lock read state");
     
    225245            RTTestFailed(hTest, "wrong lock read medium state %d", mediumState);
    226246
    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");
    228250
    229251        TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting after nested lock read state");
     
    231253            RTTestFailed(hTest, "wrong after nested lock read medium state %d", mediumState);
    232254
    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");
    290259
    291260        TEST_COM_SUCCESS(hTest, pMedium->COMGETTER(State)(&mediumState), "getting unlock read state");
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette