VirtualBox

Changeset 86047 in vbox for trunk/src


Ignore:
Timestamp:
Sep 7, 2020 3:37:43 PM (4 years ago)
Author:
vboxsync
Message:

Main: bugref:9623: Implemented DVD multi attachment by ref count.

File:
1 edited

Legend:

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

    r85908 r86047  
    6666////////////////////////////////////////////////////////////////////////////////
    6767
     68struct SnapshotRef
     69{
     70    /** Equality predicate for stdc++. */
     71    struct EqualsTo : public std::unary_function <SnapshotRef, bool>
     72    {
     73        explicit EqualsTo(const Guid &aSnapshotId) : snapshotId(aSnapshotId) {}
     74
     75        bool operator()(const argument_type &aThat) const
     76        {
     77            return aThat.snapshotId == snapshotId;
     78        }
     79
     80        const Guid snapshotId;
     81    };
     82
     83    SnapshotRef(const Guid &aSnapshotId,
     84                const int &aRefCnt = 1)
     85        : snapshotId(aSnapshotId),
     86          iRefCnt(aRefCnt) {}
     87
     88    Guid snapshotId;
     89    /*
     90     * The number of attachments of the medium in the same snapshot.
     91     * Used for MediumType_Readonly. It is always equal to 1 for other types.
     92     * Usual int is used because any changes in the BackRef are guarded by
     93     * AutoWriteLock.
     94     */
     95    int  iRefCnt;
     96};
     97
    6898/** Describes how a machine refers to this medium. */
    6999struct BackRef
     
    85115            const Guid &aSnapshotId = Guid::Empty)
    86116        : machineId(aMachineId),
     117          iRefCnt(1),
    87118          fInCurState(aSnapshotId.isZero())
    88119    {
    89120        if (aSnapshotId.isValid() && !aSnapshotId.isZero())
    90             llSnapshotIds.push_back(aSnapshotId);
     121            llSnapshotIds.push_back(SnapshotRef(aSnapshotId));
    91122    }
    92123
    93124    Guid machineId;
     125    /*
     126     * The number of attachments of the medium in the same machine.
     127     * Used for MediumType_Readonly. It is always equal to 1 for other types.
     128     * Usual int is used because any changes in the BackRef are guarded by
     129     * AutoWriteLock.
     130     */
     131    int iRefCnt;
    94132    bool fInCurState : 1;
    95     GuidList llSnapshotIds;
     133    std::list<SnapshotRef> llSnapshotIds;
    96134};
    97135
     
    14741512
    14751513    AutoWriteLock treeLock(pVirtualBox->i_getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
     1514#if DEBUG
     1515    if (!m->backRefs.empty())
     1516        i_dumpBackRefs();
     1517#endif
     1518    Assert(m->backRefs.empty());
    14761519
    14771520    /* Enclose the state transition Ready->InUninit->NotReady */
     
    21382181                    aSnapshotIds[j++] = it->machineId.toUtf16();
    21392182
    2140                 for(GuidList::const_iterator jt = it->llSnapshotIds.begin(); jt != it->llSnapshotIds.end(); ++jt, ++j)
    2141                     aSnapshotIds[j] = (*jt);
     2183                for(std::list<SnapshotRef>::const_iterator jt = it->llSnapshotIds.begin(); jt != it->llSnapshotIds.end(); ++jt, ++j)
     2184                    aSnapshotIds[j] = jt->snapshotId;
    21422185            }
    21432186
     
    42954338        return S_OK;
    42964339    }
     4340    bool fDvd = false;
     4341    {
     4342        AutoReadLock arlock(this COMMA_LOCKVAL_SRC_POS);
     4343        fDvd = m->type == MediumType_Readonly || m->devType == DeviceType_DVD;
     4344    }
    42974345
    42984346    // if the caller has not supplied a snapshot ID, then we're attaching
     
    43034351    {
    43044352        // Allow MediumType_Readonly mediums and DVD in particular to be attached twice.
    4305         AutoReadLock arlock(this COMMA_LOCKVAL_SRC_POS);
    4306         if (m->type == MediumType_Readonly || m->devType == DeviceType_DVD)
    4307         {
    4308             BackRef ref(aMachineId, aSnapshotId);
    4309             m->backRefs.push_back(ref);
     4353        // (the medium already had been added to back reference)
     4354        if (fDvd)
     4355        {
     4356            it->iRefCnt++;
    43104357            return S_OK;
    43114358        }
     
    43254372    // otherwise: a snapshot medium is being attached
    43264373
    4327     /* sanity: no duplicate attachments except MediumType_Readonly (DVD) */
    4328     for (GuidList::const_iterator jt = it->llSnapshotIds.begin();
     4374    /* sanity: no duplicate attachments */
     4375    for (std::list<SnapshotRef>::iterator jt = it->llSnapshotIds.begin();
    43294376         jt != it->llSnapshotIds.end();
    43304377         ++jt)
    43314378    {
    4332         const Guid &idOldSnapshot = *jt;
    4333 
    4334         if (   idOldSnapshot == aSnapshotId
    4335             && m->type != MediumType_Readonly
    4336             && m->devType != DeviceType_DVD
    4337            )
    4338         {
     4379        const Guid &idOldSnapshot = jt->snapshotId;
     4380
     4381        if (idOldSnapshot == aSnapshotId)
     4382        {
     4383            if (fDvd)
     4384            {
     4385                jt->iRefCnt++;
     4386                return S_OK;
     4387            }
    43394388#ifdef DEBUG
    43404389            i_dumpBackRefs();
     
    43484397    }
    43494398
    4350     it->llSnapshotIds.push_back(aSnapshotId);
     4399    it->llSnapshotIds.push_back(SnapshotRef(aSnapshotId));
    43514400    // Do not touch fInCurState, as the image may be attached to the current
    43524401    // state *and* a snapshot, otherwise we lose the current state association!
     
    43824431    if (aSnapshotId.isZero())
    43834432    {
     4433        it->iRefCnt--;
     4434        if (it->iRefCnt > 0)
     4435            return S_OK;
     4436
    43844437        /* remove the current state attachment */
    43854438        it->fInCurState = false;
     
    43884441    {
    43894442        /* remove the snapshot attachment */
    4390         GuidList::iterator jt = std::find(it->llSnapshotIds.begin(),
    4391                                           it->llSnapshotIds.end(),
    4392                                           aSnapshotId);
     4443        std::list<SnapshotRef>::iterator jt =
     4444                std::find_if(it->llSnapshotIds.begin(),
     4445                             it->llSnapshotIds.end(),
     4446                             SnapshotRef::EqualsTo(aSnapshotId));
    43934447
    43944448        AssertReturn(jt != it->llSnapshotIds.end(), E_FAIL);
     4449
     4450        jt->iRefCnt--;
     4451        if (jt->iRefCnt > 0)
     4452            return S_OK;
     4453
    43954454        it->llSnapshotIds.erase(jt);
    43964455    }
     
    44514510        return NULL;
    44524511
    4453     return &ref.llSnapshotIds.front();
     4512    return &ref.llSnapshotIds.front().snapshotId;
    44544513}
    44554514
     
    44764535    {
    44774536        const BackRef &ref = *it2;
    4478         LogFlowThisFunc(("  Backref from machine {%RTuuid} (fInCurState: %d)\n", ref.machineId.raw(), ref.fInCurState));
    4479 
    4480         for (GuidList::const_iterator jt2 = it2->llSnapshotIds.begin();
     4537        LogFlowThisFunc(("  Backref from machine {%RTuuid} (fInCurState: %d, iRefCnt: %d)\n", ref.machineId.raw(), ref.fInCurState, ref.iRefCnt));
     4538
     4539        for (std::list<SnapshotRef>::const_iterator jt2 = it2->llSnapshotIds.begin();
    44814540             jt2 != it2->llSnapshotIds.end();
    44824541             ++jt2)
    44834542        {
    4484             const Guid &id = *jt2;
    4485             LogFlowThisFunc(("  Backref from snapshot {%RTuuid}\n", id.raw()));
     4543            const Guid &id = jt2->snapshotId;
     4544            LogFlowThisFunc(("  Backref from snapshot {%RTuuid} (iRefCnt = %d)\n", id.raw(), jt2->iRefCnt));
    44864545        }
    44874546    }
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