Changeset 97931 in vbox for trunk/src/VBox/Main/src-server
- Timestamp:
- Dec 31, 2022 9:44:15 PM (2 years ago)
- svn:sync-xref-src-repo-rev:
- 155021
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-server/MediumImpl.cpp
r97865 r97931 497 497 bool fKeepSourceMediumLockList = false, 498 498 bool fKeepTargetMediumLockList = false, 499 bool fNotifyAboutChanges = true) 499 bool fNotifyAboutChanges = true, 500 LONG64 aTargetLogicalSize = 0) 500 501 : Medium::Task(aMedium, aProgress, fNotifyAboutChanges), 501 502 mTarget(aTarget), 502 503 mParent(aParent), 504 mTargetLogicalSize(aTargetLogicalSize), 503 505 mpSourceMediumLockList(aSourceMediumLockList), 504 506 mpTargetMediumLockList(aTargetMediumLockList), … … 510 512 mfKeepSourceMediumLockList(fKeepSourceMediumLockList), 511 513 mfKeepTargetMediumLockList(fKeepTargetMediumLockList) 514 512 515 { 513 516 AssertReturnVoidStmt(aTarget != NULL, mRC = E_FAIL); … … 534 537 const ComObjPtr<Medium> mTarget; 535 538 const ComObjPtr<Medium> mParent; 539 LONG64 mTargetLogicalSize; 536 540 MediumLockList *mpSourceMediumLockList; 537 541 MediumLockList *mpTargetMediumLockList; … … 3020 3024 ComPtr<IProgress> &aProgress) 3021 3025 { 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 */ 3041 HRESULT 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 */ 3025 3048 ComAssertRet(aTarget != this, E_INVALIDARG); 3026 3049 CheckComArgExpr(aLogicalSize, aLogicalSize >= 0); 3050 3051 /* Convert args to usable/needed types */ 3027 3052 IMedium *aT = aTarget; 3028 3053 ComObjPtr<Medium> pTarget = static_cast<Medium*>(aT); … … 3034 3059 } 3035 3060 3061 /* Set up variables. Fetch needed data in lockable blocks */ 3036 3062 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 */ 3037 3081 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 } 3039 3163 3040 3164 try … … 3111 3235 } 3112 3236 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 3125 3237 ULONG mediumVariantFlags = 0; 3126 3238 … … 3139 3251 } 3140 3252 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 3146 3272 rc = pTask->rc(); 3147 3273 AssertComRC(rc); … … 3161 3287 pProgress.queryInterfaceTo(aProgress.asOutParam()); 3162 3288 } 3163 else if (pTask != NULL) 3289 else if (pTask != NULL) { 3164 3290 delete pTask; 3291 throw rc; 3292 } 3165 3293 3166 3294 return rc; … … 9647 9775 (fCreatingTarget) ? targetLocation.c_str() : (char *)NULL, 9648 9776 false /* fMoveByRename */, 9649 0/* cbSize */,9777 (uint64_t) task.mTargetLogicalSize /* cbSize */, 9650 9778 task.mVariant & ~(MediumVariant_NoCreateDir | MediumVariant_Formatted), 9651 9779 targetId.raw(), … … 9663 9791 (fCreatingTarget) ? targetLocation.c_str() : (char *)NULL, 9664 9792 false /* fMoveByRename */, 9665 0/* cbSize */,9793 (uint64_t) task.mTargetLogicalSize /* cbSize */, 9666 9794 task.midxSrcImageSame, 9667 9795 task.midxDstImageSame,
Note:
See TracChangeset
for help on using the changeset viewer.