VirtualBox

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


Ignore:
Timestamp:
Mar 16, 2010 11:02:33 AM (15 years ago)
Author:
vboxsync
Message:

Snapshots: Fix corruption during merge of snapshots

File:
1 edited

Legend:

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

    r27279 r27392  
    404404            AutoWriteLock alock(*it COMMA_LOCKVAL_SRC_POS);
    405405            Assert((*it)->m->state == MediumState_LockedWrite ||
     406                   (*it)->m->state == MediumState_LockedRead ||
    406407                   (*it)->m->state == MediumState_Deleting);
    407408            if ((*it)->m->state == MediumState_LockedWrite)
    408409                (*it)->UnlockWrite(NULL);
     410            else if ((*it)->m->state == MediumState_LockedRead)
     411                (*it)->UnlockRead(NULL);
    409412            else
    410413                (*it)->m->state = MediumState_Created;
     
    461464
    462465                mParent = aMedium->m->pParent;
     466            }
     467
     468            /* Include all images from base to source. */
     469            ComObjPtr<Medium> pParent = aMedium->m->pParent;
     470            while (!pParent.isNull())
     471            {
     472                rc = pParent->addCaller();
     473                if (FAILED(rc)) return rc;
     474
     475                rc = pParent->LockRead(NULL);
     476                if (FAILED(rc)) return rc;
     477
     478                push_front(pParent);
     479                pParent = pParent->m->pParent;
    463480            }
    464481        }
     
    485502        }
    486503
     504        mSource = aMedium;
     505
    487506        return S_OK;
    488507    }
     
    515534        push_front(aMedium);
    516535
     536        mTarget = aMedium;
     537
    517538        return S_OK;
    518539    }
     
    548569    }
    549570
     571    int targetIdx()
     572    {
     573        Assert(!mTarget.isNull());
     574        int idx = 0;
     575
     576        for (MediaList::const_iterator it = begin(); it != end(); ++it)
     577        {
     578            ComObjPtr<Medium> pMedium = *it;
     579
     580            /* Do we have the target? */
     581            if (pMedium == mTarget)
     582                break;
     583
     584            idx++;
     585        }
     586
     587        return idx;
     588    }
     589
     590    int sourceIdx()
     591    {
     592        Assert(!mSource.isNull());
     593        int idx = 0;
     594
     595        for (MediaList::const_iterator it = begin(); it != end(); ++it)
     596        {
     597            ComObjPtr<Medium> pMedium = *it;
     598
     599            /* Do we have the source? */
     600            if (pMedium == mSource)
     601                break;
     602
     603            idx++;
     604        }
     605
     606        return idx;
     607    }
     608
    550609    bool isForward() const { return mForward; }
    551610    Medium *parent() const { return mParent; }
     
    553612
    554613    Medium *source() const
    555     { AssertReturn(size() > 0, NULL); return mForward ? front() : back(); }
     614    { AssertReturn(size() > 0, NULL); return mSource; }
    556615
    557616    Medium *target() const
    558     { AssertReturn(size() > 0, NULL); return mForward ? back() : front(); }
     617    { AssertReturn(size() > 0, NULL); return mTarget; }
    559618
    560619protected:
     
    622681    /** Children of the source when backward merge (if any) */
    623682    MediaList mChildren;
     683    /** Source image */
     684    ComObjPtr <Medium> mSource;
     685    /** Target image */
     686    ComObjPtr <Medium> mTarget;
    624687};
    625688
     
    52355298                 ++it)
    52365299            {
    5237                 /* complex sanity (sane complexity) */
    5238                 Assert((chain->isForward() &&
    5239                         ((*it != chain->back() &&
    5240                             (*it)->m->state == MediumState_Deleting) ||
    5241                             (*it == chain->back() &&
    5242                             (*it)->m->state == MediumState_LockedWrite))) ||
    5243                         (!chain->isForward() &&
    5244                         ((*it != chain->front() &&
    5245                             (*it)->m->state == MediumState_Deleting) ||
    5246                             (*it == chain->front() &&
    5247                             (*it)->m->state == MediumState_LockedWrite))));
    5248 
    5249                 Assert(*it == chain->target() ||
    5250                         (*it)->m->backRefs.size() == 0);
    5251 
    5252                 /* open the first image with VDOPEN_FLAGS_INFO because
    5253                  * it's not necessarily the base one */
     5300                /*
     5301                 * complex sanity (sane complexity)
     5302                 *
     5303                 * The current image must be in the Deleting (image is merged)
     5304                 * or LockedRead (parent image) state if it is not the target.
     5305                 * If it is the target it must be in the LockedWrite state.
     5306                 */
     5307                Assert(   (   *it != chain->target()
     5308                           && (   (*it)->m->state == MediumState_Deleting
     5309                               || (*it)->m->state == MediumState_LockedRead))
     5310                       || (   *it == chain->target()
     5311                           && (*it)->m->state == MediumState_LockedWrite));
     5312
     5313                /*
     5314                 * Image must be the target, in the LockedRead state
     5315                 * or Deleting state where it is not allowed to be attached
     5316                 * to a virtual machine.
     5317                 */
     5318                Assert(   *it == chain->target()
     5319                       || (*it)->m->state == MediumState_LockedRead
     5320                       || (   (*it)->m->backRefs.size() == 0
     5321                           && (*it)->m->state == MediumState_Deleting)
     5322                      );
     5323
     5324                unsigned uOpenFlags = 0;
     5325
     5326                if (   (*it)->m->state == MediumState_LockedRead
     5327                    || (*it)->m->state == MediumState_Deleting)
     5328                    uOpenFlags = VD_OPEN_FLAGS_READONLY;
     5329
     5330                /* Open the image */
    52545331                vrc = VDOpen(hdd,
    52555332                             (*it)->m->strFormat.c_str(),
    52565333                             (*it)->m->strLocationFull.c_str(),
    5257                              it == chain->begin() ? VD_OPEN_FLAGS_INFO : 0,
     5334                             uOpenFlags,
    52585335                             (*it)->m->vdDiskIfaces);
    52595336                if (RT_FAILURE(vrc))
     
    52615338            }
    52625339
    5263             unsigned start = chain->isForward() ?
    5264                 0 : (unsigned)chain->size() - 1;
    5265             unsigned end = chain->isForward() ?
    5266                 (unsigned)chain->size() - 1 : 0;
    5267 
    5268             vrc = VDMerge(hdd, start, end, vdOperationIfaces);
     5340            vrc = VDMerge(hdd, chain->sourceIdx(), chain->targetIdx(), vdOperationIfaces);
    52695341            if (RT_FAILURE(vrc))
    52705342                throw vrc;
    52715343
    52725344            /* update parent UUIDs */
    5273             /// @todo VDMerge should be taught to do so, including the
     5345            /// @todo VDMerge should handle the
    52745346            /// multiple children case
    5275             if (chain->isForward())
    5276             {
    5277                 /* target's UUID needs to be updated (note that target
    5278                  * is the only image in the container on success) */
    5279                 vrc = VDSetParentUuid(hdd, 0, chain->parent()->m->id);
    5280                 if (RT_FAILURE(vrc))
    5281                     throw vrc;
    5282             }
    5283             else
     5347            if (!chain->isForward())
    52845348            {
    52855349                /* we need to update UUIDs of all source's children
     
    53965460            )
    53975461        {
    5398             if (*it == chain->target())
     5462            /* The target and all images not merged (readonly) are skipped */
     5463            if (   *it == chain->target()
     5464                || (*it)->m->state == MediumState_LockedRead)
    53995465            {
    54005466                ++it;
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