VirtualBox

Ignore:
Timestamp:
Mar 10, 2009 10:27:08 PM (16 years ago)
Author:
vboxsync
Message:

Main: Reset differencing hard disks for which auto-reset is set to true (#3425).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/MachineImpl.cpp

    r17601 r17651  
    1036810368
    1036910369/**
     10370 * Locks the attached media.
     10371 *
     10372 * All attached hard disks and DVD/floppy are locked for writing. Parents of
     10373 * attached hard disks (if any) are locked for reading.
     10374 *
     10375 * This method also performs accessibility check of all media it locks: if some
     10376 * media is inaccessible, the method will return a failure and a bunch of
     10377 * extended error info objects per each inaccessible medium.
     10378 *
     10379 * Note that this method is atomic: if it returns a success, all media are
     10380 * locked as described above; on failure no media is locked at all (all
     10381 * succeeded individual locks will be undone).
     10382 *
     10383 * This method is intended to be called when the machine is in Starting or
     10384 * Restoring state and asserts otherwise.
     10385 *
     10386 * The locks made by this method must be undone by calling #unlockMedia() when
     10387 * no more needed.
     10388 */
     10389HRESULT SessionMachine::lockMedia()
     10390{
     10391    AutoCaller autoCaller (this);
     10392    AssertComRCReturn (autoCaller.rc(), autoCaller.rc());
     10393
     10394    AutoWriteLock alock (this);
     10395
     10396    AssertReturn (mData->mMachineState == MachineState_Starting ||
     10397                  mData->mMachineState == MachineState_Restoring, E_FAIL);
     10398
     10399    typedef std::list <ComPtr <IMedium> > MediaList;
     10400    MediaList mediaToCheck;
     10401    MediaState_T mediaState;
     10402
     10403    try
     10404    {
     10405        HRESULT rc = S_OK;
     10406
     10407        /* lock hard disks */
     10408        for (HDData::AttachmentList::const_iterator it =
     10409                 mHDData->mAttachments.begin();
     10410             it != mHDData->mAttachments.end(); ++ it)
     10411        {
     10412            ComObjPtr<HardDisk> hd = (*it)->hardDisk();
     10413
     10414            bool first = true;
     10415
     10416            while (!hd.isNull())
     10417            {
     10418                if (first)
     10419                {
     10420                    rc = hd->LockWrite (&mediaState);
     10421                    CheckComRCThrowRC (rc);
     10422
     10423                    mData->mSession.mLockedMedia.push_back (
     10424                        Data::Session::LockedMedia::value_type (
     10425                            ComPtr <IHardDisk> (hd), true));
     10426
     10427                    first = false;
     10428                }
     10429                else
     10430                {
     10431                    rc = hd->LockRead (&mediaState);
     10432                    CheckComRCThrowRC (rc);
     10433
     10434                    mData->mSession.mLockedMedia.push_back (
     10435                        Data::Session::LockedMedia::value_type (
     10436                            ComPtr <IHardDisk> (hd), false));
     10437                }
     10438
     10439                if (mediaState == MediaState_Inaccessible)
     10440                    mediaToCheck.push_back (ComPtr <IHardDisk> (hd));
     10441
     10442                /* no locks or callers here since there should be no way to
     10443                 * change the hard disk parent at this point (as it is still
     10444                 * attached to the machine) */
     10445                hd = hd->parent();
     10446            }
     10447        }
     10448
     10449        /* lock the DVD image for reading if mounted */
     10450        {
     10451            AutoReadLock driveLock (mDVDDrive);
     10452            if (mDVDDrive->data()->state == DriveState_ImageMounted)
     10453            {
     10454                ComObjPtr <DVDImage> image = mDVDDrive->data()->image;
     10455
     10456                rc = image->LockRead (&mediaState);
     10457                CheckComRCThrowRC (rc);
     10458
     10459                mData->mSession.mLockedMedia.push_back (
     10460                    Data::Session::LockedMedia::value_type (
     10461                        ComPtr <IDVDImage> (image), false));
     10462
     10463                if (mediaState == MediaState_Inaccessible)
     10464                    mediaToCheck.push_back (ComPtr <IDVDImage> (image));
     10465            }
     10466        }
     10467
     10468        /* lock the floppy image for reading if mounted */
     10469        {
     10470            AutoReadLock driveLock (mFloppyDrive);
     10471            if (mFloppyDrive->data()->state == DriveState_ImageMounted)
     10472            {
     10473                ComObjPtr <FloppyImage> image = mFloppyDrive->data()->image;
     10474
     10475                rc = image->LockRead (&mediaState);
     10476                CheckComRCThrowRC (rc);
     10477
     10478                mData->mSession.mLockedMedia.push_back (
     10479                    Data::Session::LockedMedia::value_type (
     10480                        ComPtr <IFloppyImage> (image), false));
     10481
     10482                if (mediaState == MediaState_Inaccessible)
     10483                    mediaToCheck.push_back (ComPtr <IFloppyImage> (image));
     10484            }
     10485        }
     10486
     10487        /* SUCCEEDED locking all media, now check accessibility */
     10488
     10489        ErrorInfoKeeper eik (true /* aIsNull */);
     10490        MultiResult mrc (S_OK);
     10491
     10492        /* perform a check of inaccessible media deferred above */
     10493        for (MediaList::const_iterator
     10494             it = mediaToCheck.begin();
     10495             it != mediaToCheck.end(); ++ it)
     10496        {
     10497            MediaState_T mediaState;
     10498            rc = (*it)->COMGETTER(State) (&mediaState);
     10499            CheckComRCThrowRC (rc);
     10500
     10501            Assert (mediaState == MediaState_LockedRead ||
     10502                    mediaState == MediaState_LockedWrite);
     10503
     10504            /* Note that we locked the medium already, so use the error
     10505             * value to see if there was an accessibility failure */
     10506
     10507            Bstr error;
     10508            rc = (*it)->COMGETTER(LastAccessError) (error.asOutParam());
     10509            CheckComRCThrowRC (rc);
     10510
     10511            if (!error.isNull())
     10512            {
     10513                Bstr loc;
     10514                rc = (*it)->COMGETTER(Location) (loc.asOutParam());
     10515                CheckComRCThrowRC (rc);
     10516
     10517                /* collect multiple errors */
     10518                eik.restore();
     10519
     10520                /* be in sync with MediumBase::setStateError() */
     10521                Assert (!error.isEmpty());
     10522                mrc = setError (E_FAIL,
     10523                    tr ("Medium '%ls' is not accessible. %ls"),
     10524                    loc.raw(), error.raw());
     10525
     10526                eik.fetch();
     10527            }
     10528        }
     10529
     10530        eik.restore();
     10531        CheckComRCThrowRC ((HRESULT) mrc);
     10532    }
     10533    catch (HRESULT aRC)
     10534    {
     10535        /* Unlock all locked media on failure */
     10536        unlockMedia();
     10537        return aRC;
     10538    }
     10539
     10540    return S_OK;
     10541}
     10542
     10543/**
     10544 * Undoes the locks made by by #lockMedia().
     10545 */
     10546void SessionMachine::unlockMedia()
     10547{
     10548    AutoCaller autoCaller (this);
     10549    AssertComRCReturnVoid (autoCaller.rc());
     10550
     10551    AutoWriteLock alock (this);
     10552
     10553    /* we may be holding important error info on the current thread;
     10554     * preserve it */
     10555    ErrorInfoKeeper eik;
     10556
     10557    HRESULT rc = S_OK;
     10558
     10559    for (Data::Session::LockedMedia::const_iterator
     10560         it = mData->mSession.mLockedMedia.begin();
     10561         it != mData->mSession.mLockedMedia.end(); ++ it)
     10562    {
     10563        if (it->second)
     10564            rc = it->first->UnlockWrite (NULL);
     10565        else
     10566            rc = it->first->UnlockRead (NULL);
     10567
     10568        AssertComRC (rc);
     10569    }
     10570
     10571    mData->mSession.mLockedMedia.clear();
     10572}
     10573
     10574/**
    1037010575 * Helper to change the machine state (reimplementation).
    1037110576 *
     
    1041710622         mSnapshotData.mLastState >= MachineState_Running))
    1041810623    {
    10419         /* The EMT thread has just stopped, unlock attached media. Note that
    10420          * opposed to locking, we do unlocking here because the VM process may
    10421          * have just aborted before properly unlocking all media it locked. */
    10422 
    10423         for (HDData::AttachmentList::const_iterator it =
    10424                  mHDData->mAttachments.begin();
    10425              it != mHDData->mAttachments.end(); ++ it)
    10426         {
    10427             ComObjPtr<HardDisk> hd = (*it)->hardDisk();
    10428 
    10429             bool first = true;
    10430 
    10431             while (!hd.isNull())
    10432             {
    10433                 if (first)
    10434                 {
    10435                     rc = hd->UnlockWrite (NULL);
    10436                     AssertComRC (rc);
    10437 
    10438                     first = false;
    10439                 }
    10440                 else
    10441                 {
    10442                     rc = hd->UnlockRead (NULL);
    10443                     AssertComRC (rc);
    10444                 }
    10445 
    10446                 /* no locks or callers here since there should be no way to
    10447                  * change the hard disk parent at this point (as it is still
    10448                  * attached to the machine) */
    10449                 hd = hd->parent();
    10450             }
    10451         }
    10452         {
    10453             AutoReadLock driveLock (mDVDDrive);
    10454             if (mDVDDrive->data()->state == DriveState_ImageMounted)
    10455             {
    10456                 rc = mDVDDrive->data()->image->UnlockRead (NULL);
    10457                 AssertComRC (rc);
    10458             }
    10459         }
    10460         {
    10461             AutoReadLock driveLock (mFloppyDrive);
    10462             if (mFloppyDrive->data()->state == DriveState_ImageMounted)
    10463             {
    10464                 rc = mFloppyDrive->data()->image->UnlockRead (NULL);
    10465                 AssertComRC (rc);
    10466             }
    10467         }
     10624        /* The EMT thread has just stopped, unlock attached media. Note that as
     10625         * opposed to locking that is done from Console, we do unlocking here
     10626         * because the VM process may have aborted before having a chance to
     10627         * properly unlock all media it locked. */
     10628
     10629        unlockMedia();
    1046810630    }
    1046910631
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