Changeset 33259 in vbox
- Timestamp:
- Oct 20, 2010 12:49:55 PM (14 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/VBoxHDD.cpp
r33094 r33259 166 166 * The same as pBase if only one image is used. */ 167 167 PVDIMAGE pLast; 168 169 /** If a merge to one of the parents is running this may be non-NULL 170 * to indicate to what image the writes should be additionally relayed. */ 171 PVDIMAGE pImageRelay; 168 172 169 173 /** Flags representing the modification state. */ … … 1565 1569 * write optimizations. 1566 1570 */ 1567 static int vdWriteHelper(PVBOXHDD pDisk, PVDIMAGE pImage, PVDIMAGE pImageParentOverride, 1568 uint64_t uOffset, const void *pvBuf, size_t cbWrite, 1571 static int vdWriteHelper(PVBOXHDD pDisk, PVDIMAGE pImage, 1572 PVDIMAGE pImageParentOverride, uint64_t uOffset, 1573 const void *pvBuf, size_t cbWrite, 1569 1574 bool fUpdateCache) 1570 1575 { … … 5290 5295 { 5291 5296 /* 5292 * We may need to update the parent uuid of the child coming after the5293 * last image to be merged. We have to reopen it read/write.5297 * We may need to update the parent uuid of the child coming after 5298 * the last image to be merged. We have to reopen it read/write. 5294 5299 * 5295 * This is done before we do the actual merge to prevent an incosistent5296 * chain if the mode change fails for some reason.5300 * This is done before we do the actual merge to prevent an 5301 * inconsistent chain if the mode change fails for some reason. 5297 5302 */ 5298 5303 if (pImageFrom->pNext) … … 5316 5321 break; 5317 5322 } 5323 5324 rc2 = vdThreadFinishWrite(pDisk); 5325 AssertRC(rc2); 5326 fLockWrite = false; 5327 } 5328 5329 /* If the merge is from the last image we have to relay all writes 5330 * to the merge destination as well, so that concurrent writes 5331 * (in case of a live merge) are handled correctly. */ 5332 if (!pImageFrom->pNext) 5333 { 5334 /* Take the write lock. */ 5335 rc2 = vdThreadStartWrite(pDisk); 5336 AssertRC(rc2); 5337 fLockWrite = true; 5338 5339 pDisk->pImageRelay = pImageTo; 5318 5340 5319 5341 rc2 = vdThreadFinishWrite(pDisk); … … 5380 5402 } 5381 5403 } while (uOffset < cbSize); 5404 5405 /* In case we set up a "write proxy" image above we must clear 5406 * this again now to prevent stray writes. Failure or not. */ 5407 if (!pImageFrom->pNext) 5408 { 5409 /* Take the write lock. */ 5410 rc2 = vdThreadStartWrite(pDisk); 5411 AssertRC(rc2); 5412 fLockWrite = true; 5413 5414 pDisk->pImageRelay = NULL; 5415 5416 rc2 = vdThreadFinishWrite(pDisk); 5417 AssertRC(rc2); 5418 fLockWrite = false; 5419 } 5382 5420 } 5383 5421 … … 6475 6513 rc = vdWriteHelper(pDisk, pImage, NULL, uOffset, pvBuf, cbWrite, 6476 6514 true /* fUpdateCache */); 6515 if (RT_FAILURE(rc)) 6516 break; 6517 6518 /* If there is a merge (in the direction towards a parent) running 6519 * concurrently then we have to also "relay" the write to this parent, 6520 * as the merge position might be already past the position where 6521 * this write is going. The "context" of the write can come from the 6522 * natural chain, since merging either already did or will take care 6523 * of the "other" content which is might be needed to fill the block 6524 * to a full allocation size. The cache doesn't need to be touched 6525 * as this write is covered by the previous one. */ 6526 if (RT_UNLIKELY(pDisk->pImageRelay)) 6527 rc = vdWriteHelper(pDisk, pDisk->pImageRelay, NULL, uOffset, 6528 pvBuf, cbWrite, false /* fUpdateCache */); 6477 6529 } while (0); 6478 6530 -
trunk/src/VBox/Main/SnapshotImpl.cpp
r33078 r33259 2579 2579 if (it->mfNeedsOnlineMerge) 2580 2580 { 2581 /// @todo VBoxHDD cannot handle backward merges where source==active disk yet2582 if (!it->mfMergeForward && it->mChildrenToReparent.size() == 0)2583 throw setError(E_NOTIMPL,2584 tr("Snapshot '%s' of the machine '%ls' cannot be deleted while a VM is running, as this case is not implemented yet. You can delete the snapshot when the VM is powered off"),2585 aTask.pSnapshot->getName().c_str(),2586 mUserData->s.strName.c_str());2587 2588 2581 // online medium merge, in the direction decided earlier 2589 2582 rc = onlineMergeMedium(it->mpOnlineMediumAttachment, … … 2682 2675 childSnapshotId = pChildSnapshot->getId(); 2683 2676 } 2684 pAtt = findAttachment(pMachine->mMediaData->mAttachments, it->mpSource);2685 // If no attachment is found do not change anything. The source2686 // medium might not have been attached to the snapshot.2687 if ( pAtt)2677 // If this is an online deletion the attachment was updated 2678 // already as it is required to continue execution immediately. 2679 // Needs a bit of special treatment due to this difference. 2680 if (it->mfNeedsOnlineMerge) 2688 2681 { 2689 AutoWriteLock attLock(pAtt COMMA_LOCKVAL_SRC_POS);2690 pAtt->updateMedium(it->mpTarget);2691 2682 it->mpTarget->addBackReference(pMachine->mData->mUuid, childSnapshotId); 2683 } 2684 else 2685 { 2686 pAtt = findAttachment(pMachine->mMediaData->mAttachments, it->mpSource); 2687 // If no attachment is found do not change anything. Maybe 2688 // the source medium was not attached to the snapshot. 2689 if (pAtt) 2690 { 2691 AutoWriteLock attLock(pAtt COMMA_LOCKVAL_SRC_POS); 2692 pAtt->updateMedium(it->mpTarget); 2693 it->mpTarget->addBackReference(pMachine->mData->mUuid, childSnapshotId); 2694 } 2692 2695 } 2693 2696 } … … 3260 3263 AutoWriteLock treeLock(mParent->getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS); 3261 3264 3265 // Declare this here to make sure the object does not get uninitialized 3266 // before this method completes. Would normally happen as halfway through 3267 // we delete the last reference to the no longer existing medium object. 3268 ComObjPtr<Medium> targetChild; 3269 3262 3270 if (aMergeForward) 3263 3271 { … … 3281 3289 { 3282 3290 Assert(pTarget->getChildren().size() == 1); 3283 Medium *targetChild = pTarget->getChildren().front();3291 targetChild = pTarget->getChildren().front(); 3284 3292 3285 3293 // disconnect the deleted branch at the elder end … … 3320 3328 /* unregister and uninitialize all hard disks removed by the merge */ 3321 3329 MediumLockList *pMediumLockList = NULL; 3322 rc = mData->mSession.mLockedMedia.Get(static_cast<MediumAttachment *>(aMediumAttachment),3323 3330 MediumAttachment *pMediumAttachment = static_cast<MediumAttachment *>(aMediumAttachment); 3331 rc = mData->mSession.mLockedMedia.Get(pMediumAttachment, pMediumLockList); 3324 3332 const ComObjPtr<Medium> &pLast = aMergeForward ? pTarget : pSource; 3325 3333 AssertReturn(SUCCEEDED(rc) && pMediumLockList, E_FAIL); … … 3396 3404 } 3397 3405 3406 /* If this is a backwards merge update the medium associated with the 3407 * attachment, as the previously associated one is now deleted. */ 3408 if (!aMergeForward) 3409 { 3410 AutoWriteLock attLock(pMediumAttachment COMMA_LOCKVAL_SRC_POS); 3411 pMediumAttachment->updateMedium(pTarget); 3412 } 3398 3413 3399 3414 return S_OK;
Note:
See TracChangeset
for help on using the changeset viewer.