VirtualBox

Changeset 35903 in vbox


Ignore:
Timestamp:
Feb 8, 2011 4:46:25 PM (14 years ago)
Author:
vboxsync
Message:

Main: before unregistering a machine, move media shared with another machine to that machine's media registry to prevent that machine from becoming inaccessible

Location:
trunk/src/VBox/Main
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r35893 r35903  
    52305230    <method name="unregister">
    52315231      <desc>
    5232         Unregisters the machine, which must have been previously registered using
    5233         <link to="IVirtualBox::registerMachine"/>, and optionally do additional
     5232        Unregisters a machine previously registered with
     5233        <link to="IVirtualBox::registerMachine"/> and optionally do additional
    52345234        cleanup before the machine is unregistered.
    52355235
     
    52465246          <li>With "UnregisterOnly", the machine will only be unregistered, but no additional
    52475247            cleanup will be performed. The call will fail if the machine is in "Saved" state
    5248             or has any snapshots or any media attached (see <link to="IMediumAttachment" />.
     5248            or has any snapshots or any media attached (see <link to="IMediumAttachment" />).
    52495249            It is the responsibility of the caller to delete all such configuration in this mode.
    52505250            In this mode, the API behaves like the former @c IVirtualBox::unregisterMachine() API
     
    52525252          <li>With "DetachAllReturnNone", the call will succeed even if the machine is in "Saved"
    52535253            state or if it has snapshots or media attached. All media attached to the current machine
    5254             state or in snapshots will be detached. No medium objects will be returned; all of the
    5255             machine's media will remain open.</li>
     5254            state or in snapshots will be detached. For machines created with VirtualBox 4.0 or
     5255            later, media which are registered in this machine's media registry which are still
     5256            attached to another machine besides this machine will be moved a another machine's
     5257            registry. No medium objects will be returned; all of the machine's media will remain open.</li>
    52565258          <li>With "DetachAllReturnHardDisksOnly", the call will behave like with "DetachAllReturnNone",
    52575259            except that all the hard disk medium objects which were detached from the machine will
  • trunk/src/VBox/Main/include/MediumImpl.h

    r35836 r35903  
    176176
    177177    bool addRegistry(const Guid& id);
     178    bool removeRegistry(const Guid& id);
    178179    bool isInRegistry(const Guid& id);
    179180    bool getFirstRegistryMachineId(Guid &uuid) const;
  • trunk/src/VBox/Main/include/VirtualBoxImpl.h

    r35638 r35903  
    275275    HRESULT saveSettings();
    276276
    277     void addGuidToListUniquely(GuidList &llRegistriesThatNeedSaving, Guid uuid);
     277    void addGuidToListUniquely(GuidList &llRegistriesThatNeedSaving, const Guid &uuid);
    278278    HRESULT saveRegistries(const GuidList &llRegistriesThatNeedSaving);
    279279
  • trunk/src/VBox/Main/src-server/MachineImpl.cpp

    r35885 r35903  
    43164316                           mUserData->s.strName.c_str(), cSnapshots);
    43174317
    4318     // this list collects the medium objects from all medium attachments
    4319     // which got detached from the machine and its snapshots, in the following
    4320     // order:
    4321     // 1) media from machine attachments (these have the "leaf" attachments with snapshots
    4322     //    and must be closed first, or closing the parents will fail because they will
    4323     //    children);
     4318    // This list collects the medium objects from all medium attachments
     4319    // which we will detach from the machine and its snapshots, in a specific
     4320    // order which allows for closing all media without getting "media in use"
     4321    // errors, simply by going through the list from the front to the back:
     4322    // 1) first media from machine attachments (these have the "leaf" attachments with snapshots
     4323    //    and must be closed before the parent media from the snapshots, or closing the parents
     4324    //    will fail because they still have children);
    43244325    // 2) media from the youngest snapshots followed by those from the parent snapshots until
    4325     //    the root ("first") snapshot of the machine
    4326     // This order allows for closing the media on this list from the beginning to the end
    4327     // without getting "media in use" errors.
     4326    //    the root ("first") snapshot of the machine.
    43284327    MediaList llMedia;
    43294328
     
    77497748        if (!medium.isNull())
    77507749        {
     7750            AutoCaller medCaller(medium);
     7751            if (FAILED(medCaller.rc())) return medCaller.rc();
     7752            AutoWriteLock mlock(medium COMMA_LOCKVAL_SRC_POS);
     7753
    77517754            if (isSnapshotMachine())
    77527755                rc = medium->addBackReference(mData->mUuid, *puuidSnapshot);
     
    87778780        uuid = mParent->getGlobalRegistryId(); // VirtualBox global registry UUID
    87788781
     8782    AutoCaller autoCaller(pMedium);
     8783    if (FAILED(autoCaller.rc())) return;
     8784    AutoWriteLock alock(pMedium COMMA_LOCKVAL_SRC_POS);
     8785
    87798786    if (pMedium->addRegistry(uuid))
    87808787        // registry actually changed:
     
    90349041 * called from #fixupMedia() when the changes are rolled back.
    90359042 *
    9036  * @param pfNeedsSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
    9037  *                by this function if the caller should invoke VirtualBox::saveSettings() because the global settings have changed.
     9043 * @param pllRegistriesThatNeedSaving Optional pointer to a list of UUIDs to receive the registry IDs that need saving
    90389044 *
    90399045 * @note Locks this object for writing.
     
    92209226 * @param writeLock Machine write lock which the caller must have locked once. This may be released temporarily in here.
    92219227 * @param pSnapshot If NULL, then the detachment is for the current machine. Otherwise this is for a SnapshotMachine, and this must be its snapshot.
    9222  * @param pfNeedsSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
    9223  *                by this function if the caller should invoke VirtualBox::saveSettings() because the global settings have changed.
     9228 * @param pllRegistriesThatNeedSaving Optional pointer to a list of UUIDs to receive the registry IDs that need saving
    92249229 * @return
    92259230 */
     
    92519256        writeLock.release();
    92529257
    9253         HRESULT rc = oldmedium->deleteStorage(NULL /*aProgress*/, true /*aWait*/,
     9258        HRESULT rc = oldmedium->deleteStorage(NULL /*aProgress*/,
     9259                                              true /*aWait*/,
    92549260                                              pllRegistriesThatNeedSaving);
    92559261
     
    92839289
    92849290/**
    9285  * Goes thru all medium attachments of the list and calls detachDevice() on each
    9286  * of them and attaches all Medium objects found in the process to the given list,
    9287  * depending on cleanupMode.
     9291 * Goes thru all media of the given list and
     9292 *
     9293 * 1) calls detachDevice() on each of them for this machine and
     9294 * 2) adds all Medium objects found in the process to the given list,
     9295 *    depending on cleanupMode.
     9296 *
     9297 * If cleanupMode is CleanupMode_DetachAllReturnHardDisksOnly, this only
     9298 * adds hard disks to the list. If it is CleanupMode_Full, this adds all
     9299 * media to the list.
    92889300 *
    92899301 * This gets called from Machine::Unregister, both for the actual Machine and
    92909302 * the SnapshotMachine objects that might be found in the snapshots.
    92919303 *
    9292  * Requires caller and locking.
     9304 * Requires caller and locking. The machine lock must be passed in because it
     9305 * will be passed on to detachDevice which needs it for temporary unlocking.
    92939306 *
    92949307 * @param writeLock Machine lock from top-level caller; this gets passed to detachDevice.
     
    93169329         ++it)
    93179330    {
    9318         ComObjPtr<MediumAttachment> pAttach = *it;
     9331        ComObjPtr<MediumAttachment> &pAttach = *it;
    93199332        ComObjPtr<Medium> pMedium = pAttach->getMedium();
    93209333
  • trunk/src/VBox/Main/src-server/MediumImpl.cpp

    r35836 r35903  
    16261626
    16271627    // we access mParent and members
    1628     AutoMultiWriteLock2 mlock(&m->pVirtualBox->getMediaTreeLockHandle(), this->lockHandle() COMMA_LOCKVAL_SRC_POS);
     1628    AutoMultiWriteLock2 mlock(&m->pVirtualBox->getMediaTreeLockHandle(),
     1629                              this->lockHandle() COMMA_LOCKVAL_SRC_POS);
    16291630
    16301631    switch (m->state)
     
    30763077 * See getFirstRegistryMachineId() for details.
    30773078 *
     3079 * Must have caller + locking!
     3080 *
    30783081 * @param id
    30793082 * @return true if the registry was added; false if the given id was already on the list.
     
    30813084bool Medium::addRegistry(const Guid& id)
    30823085{
    3083     AutoCaller autoCaller(this);
    3084     if (FAILED(autoCaller.rc())) return false;
    3085 
    3086     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    3087 
     3086    // hard disks cannot be in more than one registry
    30883087    if (    m->devType == DeviceType_HardDisk
    30893088         && m->llRegistryIDs.size() > 0
     
    31053104
    31063105/**
     3106 * Removes the given UUID from the list of media registry UUIDs. Returns true
     3107 * if found or false if not.
     3108 *
     3109 * Must have caller + locking!
     3110 *
     3111 * @param id
     3112 * @return
     3113 */
     3114bool Medium::removeRegistry(const Guid& id)
     3115{
     3116    for (GuidList::iterator it = m->llRegistryIDs.begin();
     3117         it != m->llRegistryIDs.end();
     3118         ++it)
     3119    {
     3120        if ((*it) == id)
     3121        {
     3122            m->llRegistryIDs.erase(it);
     3123            return true;
     3124        }
     3125    }
     3126
     3127    return false;
     3128}
     3129
     3130/**
    31073131 * Returns true if id is in the list of media registries for this medium.
     3132 *
     3133 * Must have caller + locking!
     3134 *
    31083135 * @param id
    31093136 * @return
  • trunk/src/VBox/Main/src-server/SnapshotImpl.cpp

    r35638 r35903  
    812812 * cannot be closed if they have children.
    813813 *
    814  * This calls uninit() on itself, so the snapshots tree becomes invalid after this.
     814 * This calls uninit() on itself, so the snapshots tree (beginning with a machine's pFirstSnapshot) becomes invalid after this.
    815815 * It does not alter the main machine's snapshot pointers (pFirstSnapshot, pCurrentSnapshot).
    816816 *
     
    898898
    899899    uninit();
    900  
     900
    901901    BaseFinalRelease();
    902902}
  • trunk/src/VBox/Main/src-server/VirtualBoxImpl.cpp

    r35812 r35903  
    345345
    346346    HRESULT rc = init();
    347    
     347
    348348    BaseFinalConstruct();
    349349
     
    31923192    }
    31933193
     3194    struct {
     3195        MediaOList &llSource;
     3196        settings::MediaList &llTarget;
     3197    } s[] =
     3198    {
     3199        // hard disks
     3200        { m->allHardDisks, mediaRegistry.llHardDisks },
     3201        // CD/DVD images
     3202        { m->allDVDImages, mediaRegistry.llDvdImages },
     3203        // floppy images
     3204        { m->allFloppyImages, mediaRegistry.llFloppyImages }
     3205    };
     3206
    31943207    HRESULT rc;
    3195     // hard disks
    3196     mediaRegistry.llHardDisks.clear();
    3197     for (MediaList::const_iterator it = m->allHardDisks.begin();
    3198          it != m->allHardDisks.end();
    3199          ++it)
    3200     {
    3201         Medium *pMedium = *it;
    3202         if (pMedium->isInRegistry(uuidRegistry))
    3203         {
    3204             settings::Medium med;
    3205             rc = pMedium->saveSettings(med, strMachineFolder);     // this recurses into its children
    3206             if (FAILED(rc)) throw rc;
    3207             mediaRegistry.llHardDisks.push_back(med);
    3208         }
    3209     }
    3210 
    3211     // CD/DVD images
    3212     mediaRegistry.llDvdImages.clear();
    3213     for (MediaList::const_iterator it = m->allDVDImages.begin();
    3214          it != m->allDVDImages.end();
    3215          ++it)
    3216     {
    3217         Medium *pMedium = *it;
    3218         if (pMedium->isInRegistry(uuidRegistry))
    3219         {
    3220             settings::Medium med;
    3221             rc = pMedium->saveSettings(med, strMachineFolder);
    3222             if (FAILED(rc)) throw rc;
    3223             mediaRegistry.llDvdImages.push_back(med);
    3224         }
    3225     }
    3226 
    3227     // floppy images
    3228     mediaRegistry.llFloppyImages.clear();
    3229     for (MediaList::const_iterator it = m->allFloppyImages.begin();
    3230          it != m->allFloppyImages.end();
    3231          ++it)
    3232     {
    3233         Medium *pMedium = *it;
    3234         if (pMedium->isInRegistry(uuidRegistry))
    3235         {
    3236             settings::Medium med;
    3237             rc = pMedium->saveSettings(med, strMachineFolder);
    3238             if (FAILED(rc)) throw rc;
    3239             mediaRegistry.llFloppyImages.push_back(med);
     3208
     3209    for (size_t i = 0; i < RT_ELEMENTS(s); ++i)
     3210    {
     3211        MediaOList &llSource = s[i].llSource;
     3212        settings::MediaList &llTarget = s[i].llTarget;
     3213        llTarget.clear();
     3214        for (MediaList::const_iterator it = llSource.begin();
     3215             it != llSource.end();
     3216             ++it)
     3217        {
     3218            Medium *pMedium = *it;
     3219            AutoCaller autoCaller(pMedium);
     3220            if (FAILED(autoCaller.rc())) throw autoCaller.rc();
     3221            AutoReadLock mlock(pMedium COMMA_LOCKVAL_SRC_POS);
     3222
     3223            if (pMedium->isInRegistry(uuidRegistry))
     3224            {
     3225                settings::Medium med;
     3226                rc = pMedium->saveSettings(med, strMachineFolder);     // this recurses into child hard disks
     3227                if (FAILED(rc)) throw rc;
     3228                llTarget.push_back(med);
     3229            }
    32403230        }
    32413231    }
     
    36643654
    36653655    {
    3666         AutoWriteLock mlock(getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
     3656        AutoWriteLock tlock(getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
     3657
    36673658        for (MediaOList::iterator it = m->allHardDisks.getList().begin();
    36683659             it != m->allHardDisks.getList().end();
     
    36703661        {
    36713662            ComObjPtr<Medium> pMedium = *it;
     3663            AutoCaller medCaller(pMedium);
     3664            if (FAILED(medCaller.rc())) return medCaller.rc();
     3665            AutoReadLock medlock(pMedium COMMA_LOCKVAL_SRC_POS);
    36723666
    36733667            if (pMedium->isInRegistry(uuidMachine))
     
    37023696                                      const Guid &id)
    37033697{
     3698    // remove from the collection of registered machines
    37043699    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    3705 
    3706     // remove from the collection of registered machines
    37073700    m->allMachines.removeChild(pMachine);
    3708 
    37093701    // save the global registry
    37103702    HRESULT rc = saveSettings();
    3711 
    37123703    alock.release();
     3704
     3705    /*
     3706     * Now go over all known media and checks if they were registered in the
     3707     * media registry of the given machine. Each such medium is then moved to
     3708     * a different media registry to make sure it doesn't get lost since its
     3709     * media registry is about to go away.
     3710     *
     3711     * This fixes the following use case: Image A.vdi of machine A is also used
     3712     * by machine B, but registered in the media registry of machine A. If machine
     3713     * A is deleted, A.vdi must be moved to the registry of B, or else B will
     3714     * become inaccessible.
     3715     */
     3716    GuidList llRegistriesThatNeedSaving;
     3717    {
     3718        AutoWriteLock tlock(getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
     3719        for (MediaOList::iterator it = m->allHardDisks.getList().begin();
     3720             it != m->allHardDisks.getList().end();
     3721             ++it)
     3722        {
     3723            ComObjPtr<Medium> &pMedium = *it;
     3724            AutoCaller medCaller(pMedium);
     3725            if (FAILED(medCaller.rc())) return medCaller.rc();
     3726            AutoWriteLock mlock(pMedium COMMA_LOCKVAL_SRC_POS);
     3727
     3728            if (pMedium->removeRegistry(id))
     3729            {
     3730                // ID was found in medium's registry list:
     3731                // add a new one then
     3732                const Guid *puuidBetter = pMedium->getFirstMachineBackrefId();
     3733                if (puuidBetter)
     3734                {
     3735                    pMedium->addRegistry(*puuidBetter);
     3736                    addGuidToListUniquely(llRegistriesThatNeedSaving, *puuidBetter);
     3737                }
     3738            }
     3739        }
     3740    }
     3741
     3742    saveRegistries(llRegistriesThatNeedSaving);
    37133743
    37143744    /* fire an event */
     
    37273757 */
    37283758void VirtualBox::addGuidToListUniquely(GuidList &llRegistriesThatNeedSaving,
    3729                                        Guid uuid)
     3759                                       const Guid &uuid)
    37303760{
    37313761    for (GuidList::const_iterator it = llRegistriesThatNeedSaving.begin();
     
    43924422
    43934423    AssertReturn(pvUser, VERR_INVALID_POINTER);
    4394    
     4424
    43954425    com::Initialize();
    43964426
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