VirtualBox

Changeset 97931 in vbox for trunk/src/VBox/Main/src-server


Ignore:
Timestamp:
Dec 31, 2022 9:44:15 PM (2 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
155021
Message:

Main: Added resizeAndCloneTo(). Modified cloneTo(), bugref:10090

File:
1 edited

Legend:

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

    r97865 r97931  
    497497              bool fKeepSourceMediumLockList = false,
    498498              bool fKeepTargetMediumLockList = false,
    499               bool fNotifyAboutChanges = true)
     499              bool fNotifyAboutChanges = true,
     500              LONG64 aTargetLogicalSize = 0)
    500501        : Medium::Task(aMedium, aProgress, fNotifyAboutChanges),
    501502          mTarget(aTarget),
    502503          mParent(aParent),
     504          mTargetLogicalSize(aTargetLogicalSize),
    503505          mpSourceMediumLockList(aSourceMediumLockList),
    504506          mpTargetMediumLockList(aTargetMediumLockList),
     
    510512          mfKeepSourceMediumLockList(fKeepSourceMediumLockList),
    511513          mfKeepTargetMediumLockList(fKeepTargetMediumLockList)
     514
    512515    {
    513516        AssertReturnVoidStmt(aTarget != NULL, mRC = E_FAIL);
     
    534537    const ComObjPtr<Medium> mTarget;
    535538    const ComObjPtr<Medium> mParent;
     539    LONG64 mTargetLogicalSize;
    536540    MediumLockList *mpSourceMediumLockList;
    537541    MediumLockList *mpTargetMediumLockList;
     
    30203024                        ComPtr<IProgress> &aProgress)
    30213025{
    3022     /** @todo r=klaus The code below needs to be double checked with regard
    3023      * to lock order violations, it probably causes lock order issues related
    3024      * to the AutoCaller usage. */
     3026    return resizeAndCloneTo(aTarget, 0, aVariant, aParent, aProgress);
     3027}
     3028
     3029/**
     3030 * This is a helper function that combines the functionality of
     3031 * Medium::cloneTo() and Medium::resize(). The target medium will take the
     3032 * contents of the calling medium.
     3033 *
     3034 * @param aTarget           Medium to resize and clone to
     3035 * @param aLogicalSize      Desired size for targer medium
     3036 * @param aVariant
     3037 * @param aParent
     3038 * @param aProgress
     3039 * @return HRESULT
     3040 */
     3041HRESULT Medium::resizeAndCloneTo(const ComPtr<IMedium> &aTarget,
     3042                                 LONG64 aLogicalSize,
     3043                                 const std::vector<MediumVariant_T> &aVariant,
     3044                                 const ComPtr<IMedium> &aParent,
     3045                                 ComPtr<IProgress> &aProgress)
     3046{
     3047    /* Check for valid args */
    30253048    ComAssertRet(aTarget != this, E_INVALIDARG);
    3026 
     3049    CheckComArgExpr(aLogicalSize, aLogicalSize >= 0);
     3050
     3051    /* Convert args to usable/needed types */
    30273052    IMedium *aT = aTarget;
    30283053    ComObjPtr<Medium> pTarget = static_cast<Medium*>(aT);
     
    30343059    }
    30353060
     3061    /* Set up variables. Fetch needed data in lockable blocks */
    30363062    HRESULT rc = S_OK;
     3063    ComObjPtr<Progress> pTmpProgress;
     3064    Medium::Task *pTask = NULL;
     3065
     3066    Utf8Str strSourceName;
     3067    {
     3068        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     3069        strSourceName = i_getName();
     3070    }
     3071
     3072    uint64_t uTargetExistingSize = 0;
     3073    Utf8Str strTargetName;
     3074    {
     3075        AutoReadLock alock(pTarget COMMA_LOCKVAL_SRC_POS);
     3076        uTargetExistingSize = pTarget->i_getLogicalSize();
     3077        strTargetName = pTarget->i_getName();
     3078    }
     3079
     3080    /* Set up internal multi-subprocess progress object */
    30373081    ComObjPtr<Progress> pProgress;
    3038     Medium::Task *pTask = NULL;
     3082    pProgress.createObject();
     3083    rc = pProgress->init(m->pVirtualBox,
     3084                static_cast<IMedium*>(this),
     3085                BstrFmt(tr("Resizing medium and cloning into it")).raw(),
     3086                TRUE, /* aCancelable */
     3087                2, /* Number of opearations */
     3088                BstrFmt(tr("Resizing medium before clone")).raw()
     3089                );
     3090
     3091    if (FAILED(rc))
     3092        throw rc;
     3093
     3094    /* If target does not exist, handle resize. */
     3095    if (pTarget->m->state != MediumState_NotCreated && aLogicalSize > 0)
     3096    {
     3097        if ((LONG64)uTargetExistingSize != aLogicalSize) {
     3098            if (!i_isMediumFormatFile())
     3099            {
     3100                AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     3101                rc = setError(VBOX_E_NOT_SUPPORTED,
     3102                              tr("Sizes of '%s' and '%s' are different and \
     3103                                 medium format does not support resing"),
     3104                              strSourceName.c_str(), strTargetName.c_str());
     3105                throw rc;
     3106            }
     3107
     3108            /**
     3109             * Need to lock the target medium as i_resize does do so
     3110             * automatically.
     3111             */
     3112
     3113            ComPtr<IToken> pToken;
     3114            rc = pTarget->LockWrite(pToken.asOutParam());
     3115
     3116            if (FAILED(rc)) throw rc;
     3117
     3118            /**
     3119             * Have to make own lock list, because "resize" method resizes only
     3120             * last image in the lock chain.
     3121             */
     3122
     3123            MediumLockList* pMediumLockListForResize = new MediumLockList();
     3124            pMediumLockListForResize->Append(pTarget, pTarget->m->state == MediumState_LockedWrite);
     3125
     3126            rc = pMediumLockListForResize->Lock(true /* fSkipOverLockedMedia */);
     3127
     3128            if (FAILED(rc))
     3129            {
     3130                AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     3131                rc = setError(rc,
     3132                                tr("Failed to lock the medium '%s' to resize before merge"),
     3133                                strTargetName.c_str());
     3134                delete pMediumLockListForResize;
     3135                throw rc;
     3136            }
     3137
     3138
     3139            rc = pTarget->i_resize((uint64_t)aLogicalSize, pMediumLockListForResize, &pProgress, true, false);
     3140
     3141            if (FAILED(rc))
     3142            {
     3143                /* No need to setError becasue i_resize and i_taskResizeHandler handle this automatically. */
     3144                AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     3145                delete pMediumLockListForResize;
     3146                throw rc;
     3147            }
     3148
     3149            delete pMediumLockListForResize;
     3150
     3151            pTarget->m->logicalSize = (uint64_t)aLogicalSize;
     3152
     3153            pToken->Abandon();
     3154            pToken.setNull();
     3155        }
     3156    }
     3157
     3158    /* Report progress to supplied progress argument */
     3159    if (SUCCEEDED(rc))
     3160    {
     3161        pProgress.queryInterfaceTo(aProgress.asOutParam());
     3162    }
    30393163
    30403164    try
     
    31113235        }
    31123236
    3113         pProgress.createObject();
    3114         rc = pProgress->init(m->pVirtualBox,
    3115                              static_cast <IMedium *>(this),
    3116                              BstrFmt(tr("Creating clone medium '%s'"), pTarget->m->strLocationFull.c_str()).raw(),
    3117                              TRUE /* aCancelable */);
    3118         if (FAILED(rc))
    3119         {
    3120             delete pSourceMediumLockList;
    3121             delete pTargetMediumLockList;
    3122             throw rc;
    3123         }
    3124 
    31253237        ULONG mediumVariantFlags = 0;
    31263238
     
    31393251        }
    31403252
    3141         /* setup task object to carry out the operation asynchronously */
    3142         pTask = new Medium::CloneTask(this, pProgress, pTarget,
    3143                                       (MediumVariant_T)mediumVariantFlags,
    3144                                       pParent, UINT32_MAX, UINT32_MAX,
    3145                                       pSourceMediumLockList, pTargetMediumLockList);
     3253        if (pTarget->m->state != MediumState_NotCreated || aLogicalSize == 0)
     3254        {
     3255            /* setup task object to carry out the operation asynchronously */
     3256            pTask = new Medium::CloneTask(this, pProgress, pTarget,
     3257                                          (MediumVariant_T)mediumVariantFlags,
     3258                                          pParent, UINT32_MAX, UINT32_MAX,
     3259                                          pSourceMediumLockList, pTargetMediumLockList,
     3260                                          false, false, true, 0);
     3261        }
     3262        else
     3263        {
     3264            /* setup task object to carry out the operation asynchronously */
     3265            pTask = new Medium::CloneTask(this, pProgress, pTarget,
     3266                                          (MediumVariant_T)mediumVariantFlags,
     3267                                          pParent, UINT32_MAX, UINT32_MAX,
     3268                                          pSourceMediumLockList, pTargetMediumLockList,
     3269                                          false, false, true, aLogicalSize);
     3270        }
     3271
    31463272        rc = pTask->rc();
    31473273        AssertComRC(rc);
     
    31613287            pProgress.queryInterfaceTo(aProgress.asOutParam());
    31623288    }
    3163     else if (pTask != NULL)
     3289    else if (pTask != NULL) {
    31643290        delete pTask;
     3291        throw rc;
     3292    }
    31653293
    31663294    return rc;
     
    96479775                                 (fCreatingTarget) ? targetLocation.c_str() : (char *)NULL,
    96489776                                 false /* fMoveByRename */,
    9649                                  0 /* cbSize */,
     9777                                 (uint64_t) task.mTargetLogicalSize /* cbSize */,
    96509778                                 task.mVariant & ~(MediumVariant_NoCreateDir | MediumVariant_Formatted),
    96519779                                 targetId.raw(),
     
    96639791                                   (fCreatingTarget) ? targetLocation.c_str() : (char *)NULL,
    96649792                                   false /* fMoveByRename */,
    9665                                    0 /* cbSize */,
     9793                                   (uint64_t) task.mTargetLogicalSize /* cbSize */,
    96669794                                   task.midxSrcImageSame,
    96679795                                   task.midxDstImageSame,
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