VirtualBox

Ignore:
Timestamp:
Nov 19, 2012 7:07:10 PM (12 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
82197
Message:

Main/Machine+Snapshot+Medium: fix cancelling snapshots, used to trigger both backref inconsistency and incorrect lock list/map updates which could cause runtime misbehavior, the config file was already made consistent with the previous changes

File:
1 edited

Legend:

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

    r43908 r43915  
    17031703
    17041704    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    1705     if(strFile.isEmpty())
     1705    if (strFile.isEmpty())
    17061706       strFile = "VideoCap.webm";
    17071707    mHWData->mVideoCaptureFile = strFile;
     
    80188018    }
    80198019
    8020     /* Deassociate hard disks (only when a real Machine or a SnapshotMachine
     8020    /* Deassociate media (only when a real Machine or a SnapshotMachine
    80218021     * instance is uninitialized; SessionMachine instances refer to real
    8022      * Machine hard disks). This is necessary for a clean re-initialization of
     8022     * Machine media). This is necessary for a clean re-initialization of
    80238023     * the VM after successfully re-checking the accessibility state. Note
    80248024     * that in case of normal Machine or SnapshotMachine uninitialization (as
    8025      * a result of unregistering or deleting the snapshot), outdated hard
    8026      * disk attachments will already be uninitialized and deleted, so this
     8025     * a result of unregistering or deleting the snapshot), outdated media
     8026     * attachments will already be uninitialized and deleted, so this
    80278027     * code will not affect them. */
    80288028    if (    !!mMediaData
     
    80348034             ++it)
    80358035        {
    8036             ComObjPtr<Medium> hd = (*it)->getMedium();
    8037             if (hd.isNull())
     8036            ComObjPtr<Medium> pMedium = (*it)->getMedium();
     8037            if (pMedium.isNull())
    80388038                continue;
    8039             HRESULT rc = hd->removeBackReference(mData->mUuid, getSnapshotId());
     8039            HRESULT rc = pMedium->removeBackReference(mData->mUuid, getSnapshotId());
    80408040            AssertComRC(rc);
    80418041        }
     
    1013010130 *       on failure. This is a responsibility of the caller.
    1013110131 *
    10132  * @note Locks this object for writing.
     10132 * @note Locks this object and the media tree for writing.
    1013310133 */
    1013410134HRESULT Machine::createImplicitDiffs(IProgress *aProgress,
     
    1015310153    HRESULT rc = S_OK;
    1015410154
     10155    // use appropriate locked media map (online or offline)
    1015510156    MediumLockListMap lockedMediaOffline;
    1015610157    MediumLockListMap *lockedMediaMap;
     
    1024210243                    else
    1024310244                        aProgress->SetNextOperation(BstrFmt(tr("Skipping medium '%s'"),
    10244                                                     pMedium->getBase()->getName().c_str()).raw(),
     10245                                                            pMedium->getBase()->getName().c_str()).raw(),
    1024510246                                                    aWeight);        // weight
    1024610247                }
     
    1028410285            {
    1028510286                alock.release();
     10287                /* The currently attached medium will be read-only, change
     10288                 * the lock type to read. */
    1028610289                rc = pMediumLockList->Update(pMedium, false);
    1028710290                alock.acquire();
    1028810291                AssertComRCThrowRC(rc);
    1028910292            }
    10290             rc = lockedMediaMap->Get(pAtt, pMediumLockList);
    10291             AssertComRCThrowRC(rc);
    1029210293
    1029310294            /* release the locks before the potentially lengthy operation */
     
    1033810339    catch (HRESULT aRC) { rc = aRC; }
    1033910340
    10340 
    10341     /* unlock all hard disks we locked */
     10341    /* unlock all hard disks we locked when there is no VM */
    1034210342    if (!aOnline)
    1034310343    {
     
    1034710347        AssertComRC(rc1);
    1034810348    }
    10349 
    10350 
    10351     if (FAILED(rc))
    10352     {
    10353         MultiResult mrc = rc;
    10354 
    10355         alock.release();
    10356         mrc = deleteImplicitDiffs(aOnline);
    10357     }
    10358 
    10359     if (aOnline)
    10360         mData->mSession.mLockedMedia =  *lockedMediaMap;
    10361     else
    10362         lockedMediaOffline = *lockedMediaMap;
    1036310349
    1036410350    return rc;
     
    1037210358 * called from #fixupMedia() when the changes are rolled back.
    1037310359 *
    10374  * @note Locks this object for writing.
     10360 * @note Locks this object and the media tree for writing.
    1037510361 */
    10376 // Tod - deal withh offline atts .....
    10377 HRESULT Machine::deleteImplicitDiffs(bool      aOnline)
     10362HRESULT Machine::deleteImplicitDiffs(bool aOnline)
    1037810363{
    1037910364    LogFlowThisFunc(("aOnline=%d\n", aOnline));
     
    1038210367    AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
    1038310368
    10384     AutoWriteLock alock(this  COMMA_LOCKVAL_SRC_POS);
    10385     AutoMultiWriteLock2 alock2(this->lockHandle(),
     10369    AutoMultiWriteLock2 alock(this->lockHandle(),
    1038610370                              &mParent->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
    1038710371
    10388     /* Don't want backed up state. */
     10372    /* We absolutely must have backed up state. */
    1038910373    AssertReturn(mMediaData.isBackedUp(), E_FAIL);
    1039010374
     
    1039210376    MachineState_T oldState = mData->mMachineState;
    1039310377
    10394     MediaData::AttachmentList implicitAtts;
    10395     const MediaData::AttachmentList &oldAtts = mMediaData.backedUpData()->mAttachments;
    10396 
    10397     // Locked Media Map.
     10378    /* will release the lock before the potentially lengthy operation,
     10379     * so protect with the special state (unless already protected) */
     10380    if (   oldState != MachineState_Saving
     10381        && oldState != MachineState_LiveSnapshotting
     10382        && oldState != MachineState_RestoringSnapshot
     10383        && oldState != MachineState_DeletingSnapshot
     10384        && oldState != MachineState_DeletingSnapshotOnline
     10385        && oldState != MachineState_DeletingSnapshotPaused
     10386       )
     10387        setMachineState(MachineState_SettingUp);
     10388
     10389    // use appropriate locked media map (online or offline)
    1039810390    MediumLockListMap lockedMediaOffline;
    1039910391    MediumLockListMap *lockedMediaMap;
     
    1040510397    try
    1040610398    {
    10407         // create Medium lock lists for offline atts as per createImplicitAtts.
    1040810399        if (!aOnline)
    1040910400        {
     
    1044110432
    1044210433            if (FAILED(rc))
    10443                 throw(rc);
    10444 
     10434                throw rc;
    1044510435        } // end of offline
    1044610436
    10447 
    10448         /* Start from scratch */
    10449 
    10450         /* Go through remembered attachments and create diffs for normal hard
    10451          * disks and attach them */
     10437        /* Lock lists are now up to date and include implicitly created media */
     10438
     10439        /* Go through remembered attachments and delete all implicitly created
     10440         * diffs and fix up the attachment information */
     10441        const MediaData::AttachmentList &oldAtts = mMediaData.backedUpData()->mAttachments;
     10442        MediaData::AttachmentList implicitAtts;
    1045210443        for (MediaData::AttachmentList::const_iterator it = mMediaData->mAttachments.begin();
    1045310444             it != mMediaData->mAttachments.end();
    1045410445             ++it)
    1045510446        {
    10456             MediumAttachment* pAtt = *it;
    10457 
    10458             //  Ensure we get a hard disk.
    10459             ComObjPtr<Medium> hd = pAtt->getMedium();
    10460 
    10461             if (hd.isNull())
     10447            ComObjPtr<MediumAttachment> pAtt = *it;
     10448            ComObjPtr<Medium> pMedium = pAtt->getMedium();
     10449            if (pMedium.isNull())
    1046210450                continue;
    1046310451
    10464             // DeviceType_T devType = pAtt->getType();
    10465 
    10466             // Implicit atts go on the list of implicit atts for deletion and back reference gets removed.
     10452            // Implicit attachments go on the list for deletion and back references are removed.
    1046710453            if (pAtt->isImplicit())
    1046810454            {
    1046910455                /* Deassociate and mark for deletion */
    1047010456                LogFlowThisFunc(("Detaching '%s', pending deletion\n", pAtt->getLogName()));
    10471                 rc = hd->removeBackReference(mData->mUuid);
     10457                rc = pMedium->removeBackReference(mData->mUuid);
    1047210458                if (FAILED(rc))
    10473                    throw(rc);
     10459                   throw rc;
    1047410460                implicitAtts.push_back(pAtt);
    1047510461                continue;
    1047610462            }
    1047710463
    10478             /* Was this hard disk attached before? */
    10479             if (!findAttachment(oldAtts, hd))
     10464            /* Was this medium attached before? */
     10465            if (!findAttachment(oldAtts, pMedium))
    1048010466            {
    1048110467                /* no: de-associate */
    1048210468                LogFlowThisFunc(("Detaching '%s', no deletion\n", pAtt->getLogName()));
    10483                 rc = hd->removeBackReference(mData->mUuid);
     10469                rc = pMedium->removeBackReference(mData->mUuid);
    1048410470                if (FAILED(rc))
    10485                     throw setError(rc);
     10471                    throw rc;
    1048610472                continue;
    1048710473            }
     
    1048910475        }
    1049010476
     10477        /* If there are implicit attachments to delete, throw away the lock
     10478         * map contents (which will unlock all media) since the medium
     10479         * attachments will be rolled back. Below we need to completely
     10480         * recreate the lock map anyway since it is infinitely complex to
     10481         * do this incrementally (would need reconstructing each attachment
     10482         * change, which would be extremely hairy). */
     10483        if (implicitAtts.size() != 0)
     10484        {
     10485            ErrorInfoKeeper eik;
     10486
     10487            HRESULT rc1 = lockedMediaMap->Clear();
     10488            AssertComRC(rc1);
     10489        }
     10490
    1049110491        /* rollback hard disk changes */
    1049210492        mMediaData.rollback();
     
    1049510495
    1049610496        // Delete unused implicit diffs.
    10497         if(implicitAtts.size() != 0)
    10498         {
    10499             if (    oldState != MachineState_Saving
    10500                     && oldState != MachineState_LiveSnapshotting
    10501                     && oldState != MachineState_RestoringSnapshot
    10502                     && oldState != MachineState_DeletingSnapshot
    10503                     && oldState != MachineState_DeletingSnapshotOnline
    10504                     && oldState != MachineState_DeletingSnapshotPaused
    10505                )
    10506                    setMachineState(MachineState_SettingUp);
    10507 
     10497        if (implicitAtts.size() != 0)
     10498        {
    1050810499            alock.release();
    1050910500
    10510             // Loop round implicitatts
    10511             // a) Remove medum lock list.
    10512             // b) Delete HD storage from media list.
    10513             // c) Remove medium lock list.
    10514             MediaData::AttachmentList::const_iterator ittodelete;
    1051510501            for (MediaData::AttachmentList::const_iterator it = implicitAtts.begin();
    1051610502                 it != implicitAtts.end();
    1051710503                 ++it)
    1051810504            {
    10519                 // Remove attachment.
    10520                 MediumAttachment* pAtt = *it;
     10505                // Remove medium associated with this attachment.
     10506                ComObjPtr<MediumAttachment> pAtt = *it;
    1052110507                Assert(pAtt);
    10522                 LogFlowThisFunc(("Deleting '%s'\n", (pAtt)->getLogName()));
    10523                 ComObjPtr<Medium> hd = pAtt->getMedium();
    10524                 Assert(hd);
    10525                 mMediaData->mAttachments.remove(pAtt);
    10526                 rc = lockedMediaMap->Unlock();
    10527 
    10528                 if (FAILED(rc))
    10529                     throw(rc);
    10530 
    10531                 // Remove from locked media map.
    10532                 MediumLockList *pMediumLockList;
    10533                 rc = lockedMediaMap->Get(pAtt, pMediumLockList);
    10534 
    10535                 if (FAILED(rc))
    10536                     throw(rc);
    10537                 rc = lockedMediaMap->Remove(pAtt);
    10538                 if (FAILED(rc))
    10539                     throw(rc);
    10540                 rc = lockedMediaMap->Lock();
    10541                 alock2.release();
    10542                 rc = hd->deleteStorage(NULL /*aProgress*/, true /*aWait*/);
    10543 
    10544                 if (FAILED(rc))
    10545                     throw(rc);
    10546                 AssertMsg(SUCCEEDED(rc), ("rc=%Rhrc it=%s hd=%s\n", rc, pAtt->getLogName(), hd->getLocationFull().c_str() ));
    10547 
    10548                 // Only way to delete lock list entry is
    10549                 // by iterator so find the iterator with this lock list entry.
    10550                 // Remove from Media Lock List.
    10551                 MediumLockList::Base::iterator lockListBegin = pMediumLockList->GetBegin();
    10552                 MediumLockList::Base::iterator lockListEnd   = pMediumLockList->GetEnd();
    10553                 for (MediumLockList::Base::iterator it2 = lockListBegin; it2 != lockListEnd; ++it2 )
     10508                LogFlowThisFunc(("Deleting '%s'\n", pAtt->getLogName()));
     10509                ComObjPtr<Medium> pMedium = pAtt->getMedium();
     10510                Assert(pMedium);
     10511
     10512                rc = pMedium->deleteStorage(NULL /*aProgress*/, true /*aWait*/);
     10513                // continue on delete failure, just collect error messages
     10514                AssertMsg(SUCCEEDED(rc), ("rc=%Rhrc it=%s hd=%s\n", rc, pAtt->getLogName(), pMedium->getLocationFull().c_str() ));
     10515                mrc = rc;
     10516            }
     10517
     10518            alock.acquire();
     10519
     10520            /* if there is a VM recreate media lock map as mentioned above,
     10521             * otherwise it is a waste of time and we leave things unlocked */
     10522            if (aOnline)
     10523            {
     10524                const ComObjPtr<SessionMachine> pMachine = mData->mSession.mMachine;
     10525                /* must never be NULL, but better safe than sorry */
     10526                if (!pMachine.isNull())
    1055410527                {
    10555                     MediumLock &mediumLock = *it2;
    10556                     const ComObjPtr<Medium> pMedium = mediumLock.GetMedium();
    10557 
    10558                     if (pMedium == hd)
    10559                     {
    10560                         rc = pMediumLockList->RemoveByIterator(it2);
    10561                         if (FAILED(rc))
    10562                             throw(rc);
    10563                         break;
    10564                     }
     10528                    alock.release();
     10529                    rc = mData->mSession.mMachine->lockMedia();
     10530                    alock.acquire();
     10531                    if (FAILED(rc))
     10532                        throw rc;
    1056510533                }
    1056610534            }
    1056710535        }
    10568         if (mData->mMachineState == MachineState_SettingUp)
    10569             setMachineState(oldState);
    10570     }
    10571 
     10536    }
    1057210537    catch (HRESULT aRC) {rc = aRC;}
    1057310538
    10574     // Unlock all hard disks that we locked if offline).
     10539    if (mData->mMachineState == MachineState_SettingUp)
     10540        setMachineState(oldState);
     10541
     10542    /* unlock all hard disks we locked when there is no VM */
    1057510543    if (!aOnline)
    1057610544    {
    1057710545        ErrorInfoKeeper eik;
    10578         rc = lockedMediaMap->Clear();
    10579         if (FAILED(rc))
    10580             throw (rc);
    10581     }
    10582 
    10583 
    10584     if (aOnline)
    10585         mData->mSession.mLockedMedia = *lockedMediaMap;
    10586     else
    10587         lockedMediaOffline = *lockedMediaMap;
     10546
     10547        HRESULT rc1 = lockedMediaMap->Clear();
     10548        AssertComRC(rc1);
     10549    }
    1058810550
    1058910551    return rc;
     
    1101810980{
    1101910981    AutoCaller autoCaller(this);
    11020     AssertComRCReturnVoid (autoCaller.rc());
     10982    AssertComRCReturnVoid(autoCaller.rc());
    1102110983
    1102210984    // AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    11023     LogFlowThisFunc(("Entering rollbackmedia\n"));
     10985    LogFlowThisFunc(("Entering rollbackMedia\n"));
    1102410986
    1102510987    HRESULT rc = S_OK;
     
    1106311025    /** @todo convert all this Machine-based voodoo to MediumAttachment
    1106411026     * based rollback logic. */
    11065     deleteImplicitDiffs(true);
     11027    deleteImplicitDiffs(Global::IsOnline(mData->mMachineState));
    1106611028
    1106711029    return;
     
    1288812850}
    1288912851
     12852STDMETHODIMP SessionMachine::LockMedia()
     12853{
     12854    AutoCaller autoCaller(this);
     12855    AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
     12856
     12857    AutoMultiWriteLock2 alock(this->lockHandle(),
     12858                              &mParent->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
     12859
     12860    AssertReturn(   mData->mMachineState == MachineState_Starting
     12861                 || mData->mMachineState == MachineState_Restoring
     12862                 || mData->mMachineState == MachineState_TeleportingIn, E_FAIL);
     12863
     12864    clearError();
     12865    alock.release();
     12866    return lockMedia();
     12867}
     12868
     12869STDMETHODIMP SessionMachine::UnlockMedia()
     12870{
     12871    unlockMedia();
     12872    return S_OK;
     12873}
     12874
    1289012875STDMETHODIMP SessionMachine::EjectMedium(IMediumAttachment *aAttachment,
    1289112876                                         IMediumAttachment **aNewAttachment)
     
    1320713192
    1320813193    AutoCaller autoCaller(this);
    13209     AssertComRCReturn (autoCaller.rc(), autoCaller.rc());
     13194    AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
    1321013195
    1321113196    ComPtr<IInternalSessionControl> directControl;
     
    1322713212
    1322813213    AutoCaller autoCaller(this);
    13229     AssertComRCReturn (autoCaller.rc(), autoCaller.rc());
     13214    AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
    1323013215
    1323113216    ComPtr<IInternalSessionControl> directControl;
     
    1336513350
    1336613351    AutoCaller autoCaller(this);
    13367     AssertComRCReturn (autoCaller.rc(), autoCaller.rc());
     13352    AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
    1336813353
    1336913354    ComPtr<IInternalSessionControl> directControl;
     
    1361113596 * succeeded individual locks will be undone).
    1361213597 *
    13613  * This method is intended to be called when the machine is in Starting or
    13614  * Restoring state and asserts otherwise.
     13598 * The caller is responsible for doing the necessary state sanity checks.
    1361513599 *
    1361613600 * The locks made by this method must be undone by calling #unlockMedia() when
     
    1362513609                              &mParent->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
    1362613610
    13627     AssertReturn(   mData->mMachineState == MachineState_Starting
    13628                  || mData->mMachineState == MachineState_Restoring
    13629                  || mData->mMachineState == MachineState_TeleportingIn, E_FAIL);
    1363013611    /* bail out if trying to lock things with already set up locking */
    1363113612    AssertReturn(mData->mSession.mLockedMedia.IsEmpty(), E_FAIL);
    1363213613
    13633     clearError();
    1363413614    MultiResult mrc(S_OK);
    1363513615
Note: See TracChangeset for help on using the changeset viewer.

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