VirtualBox

Changeset 24433 in vbox


Ignore:
Timestamp:
Nov 6, 2009 11:58:54 AM (15 years ago)
Author:
vboxsync
Message:

Main: fix crash when deleting the only snapshot

File:
1 edited

Legend:

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

    r24354 r24433  
    21012101        LogFlowThisFunc(("1: Checking hard disk merge prerequisites...\n"));
    21022102
     2103        // go thru the attachments of the snapshot machine
     2104        // (the media in here point to the disk states _before_ the snapshot
     2105        // was taken, i.e. the state we're restoring to; for each such
     2106        // medium, we will need to merge it with its one and only child (the
     2107        // diff image holding the changes written after the snapshot was taken)
    21032108        for (MediaData::AttachmentList::iterator it = pSnapMachine->mMediaData->mAttachments.begin();
    21042109            it != pSnapMachine->mMediaData->mAttachments.end();
     
    21112116                Assert(pAttach->medium());
    21122117                ComObjPtr<Medium> pHD = pAttach->medium();
    2113                 // do not lock, prepareDiscared() has a write lock which will hang otherwise
     2118                        // do not lock, prepareDiscared() has a write lock which will hang otherwise
    21142119
    21152120                Medium::MergeChain *chain = NULL;
    21162121
    2117                 /* needs to be discarded (merged with the child if any), check
    2118                 * prerequisites */
     2122                // needs to be discarded (merged with the child if any), check prerequisites
    21192123                rc = pHD->prepareDiscard(chain);
    21202124                CheckComRCThrowRC(rc);
    21212125
    2122                 if (pHD->parent().isNull() && chain != NULL)
     2126                // for simplicity, we merge pHd onto its child (forward merge), not the
     2127                // other way round, because that saves us from updating the attachments
     2128                // for the machine that follows the snapshot (next snapshot or real machine),
     2129                // unless it's a base image:
     2130
     2131                if (    pHD->parent().isNull()
     2132                     && chain != NULL
     2133                   )
    21232134                {
    2124                     /* it's a base hard disk so it will be a backward merge of its
    2125                     * only child to it (prepareDiscard() does necessary checks). We
    2126                     * need then to update the attachment that refers to the child
    2127                     * to refer to the parent instead. Don't forget to detach the
    2128                     * child (otherwise mergeTo() called by discard() will assert
    2129                     * because it will be going to delete the child) */
     2135                    // parent is null -> this disk is a base hard disk: we will
     2136                    // then do a backward merge, i.e. merge its only child onto
     2137                    // the base disk; prepareDiscard() does necessary checks.
     2138                    // So here we need then to update the attachment that refers
     2139                    // to the child and have it point to the parent instead
    21302140
    21312141                    /* The below assert would be nice but I don't want to move
    2132                     * Medium::MergeChain to the header just for that
    2133                     * Assert (!chain->isForward()); */
    2134 
     2142                     * Medium::MergeChain to the header just for that
     2143                     * Assert (!chain->isForward()); */
     2144
     2145                    // prepareDiscard() should have raised an error already
     2146                    // if there was more than one child
    21352147                    Assert(pHD->children().size() == 1);
    21362148
    2137                     ComObjPtr<Medium> replaceHd = pHD->children().front();
    2138 
    2139                     const Guid *pReplaceMachineId = replaceHd->getFirstMachineBackrefId();
    2140                     Assert(pReplaceMachineId  && *pReplaceMachineId == mData->mUuid);
     2149                    ComObjPtr<Medium> pReplaceHD = pHD->children().front();
     2150
     2151                    const Guid *pReplaceMachineId = pReplaceHD->getFirstMachineBackrefId();
     2152                    Assert(pReplaceMachineId);
     2153                    Assert(*pReplaceMachineId == mData->mUuid);
    21412154
    21422155                    Guid snapshotId;
    2143                     const Guid *pSnapshotId = replaceHd->getFirstMachineBackrefSnapshotId();
     2156                    const Guid *pSnapshotId = pReplaceHD->getFirstMachineBackrefSnapshotId();
    21442157                    if (pSnapshotId)
    21452158                        snapshotId = *pSnapshotId;
     
    21472160                    HRESULT rc2 = S_OK;
    21482161
    2149                     /* adjust back references */
    2150                     rc2 = replaceHd->detachFrom(mData->mUuid, snapshotId);
     2162                    attachLock.unlock();
     2163
     2164                    // First we must detach the child (otherwise mergeTo() called
     2165                    // by discard() will assert because it will be going to delete
     2166                    // the child), so adjust the backreferences:
     2167                    // 1) detach the first child hard disk
     2168                    rc2 = pReplaceHD->detachFrom(mData->mUuid, snapshotId);
    21512169                    AssertComRC(rc2);
    2152 
     2170                    // 2) attach to machine and snapshot
    21532171                    rc2 = pHD->attachTo(mData->mUuid, snapshotId);
    21542172                    AssertComRC(rc2);
     
    21582176                    {
    21592177                        /* in current state */
    2160                         AssertBreak(pAttach = findAttachment(mMediaData->mAttachments, replaceHd));
     2178                        AssertBreak(pAttach = findAttachment(mMediaData->mAttachments, pReplaceHD));
    21612179                    }
    21622180                    else
     
    21692187                        /* don't lock the snapshot; cannot be modified outside */
    21702188                        MediaData::AttachmentList &snapAtts = snapshot->getSnapshotMachine()->mMediaData->mAttachments;
    2171                         AssertBreak(pAttach = findAttachment(snapAtts, replaceHd));
     2189                        AssertBreak(pAttach = findAttachment(snapAtts, pReplaceHD));
    21722190                    }
    21732191
    2174                     attachLock.unlock();
    21752192                    AutoWriteLock attLock(pAttach);
    21762193                    pAttach->updateMedium(pHD, false /* aImplicit */);
     
    21782195                    toDiscard.push_back(MediumDiscardRec(pHD,
    21792196                                                         chain,
    2180                                                          replaceHd,
     2197                                                         pReplaceHD,
    21812198                                                         pAttach,
    21822199                                                         snapshotId));
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