- Timestamp:
- Mar 4, 2015 2:35:32 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Storage/VD.cpp
r54591 r54624 8651 8651 } 8652 8652 8653 VBOXDDU_DECL(int) VDPrepareWithFilters(PVBOXHDD pDisk, PVDINTERFACE pVDIfsOperation) 8654 { 8655 int rc = VINF_SUCCESS; 8656 int rc2; 8657 bool fLockRead = false, fLockWrite = false; 8658 8659 LogFlowFunc(("pDisk=%#p pVDIfsOperation=%#p\n", pDisk, pVDIfsOperation)); 8660 8661 PVDINTERFACEPROGRESS pIfProgress = VDIfProgressGet(pVDIfsOperation); 8662 8663 do { 8664 /* Check arguments. */ 8665 AssertMsgBreakStmt(VALID_PTR(pDisk), ("pDisk=%#p\n", pDisk), 8666 rc = VERR_INVALID_PARAMETER); 8667 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, 8668 ("u32Signature=%08x\n", pDisk->u32Signature)); 8669 8670 rc2 = vdThreadStartRead(pDisk); 8671 AssertRC(rc2); 8672 fLockRead = true; 8673 8674 /* Must have at least one image in the chain. */ 8675 AssertMsgBreakStmt(pDisk->cImages >= 1, ("cImages=%u\n", pDisk->cImages), 8676 rc = VERR_VD_NOT_OPENED); 8677 8678 unsigned uOpenFlags = pDisk->pLast->Backend->pfnGetOpenFlags(pDisk->pLast->pBackendData); 8679 AssertMsgBreakStmt(!(uOpenFlags & VD_OPEN_FLAGS_READONLY), 8680 ("Last image should be read write"), 8681 rc = VERR_VD_IMAGE_READ_ONLY); 8682 8683 rc2 = vdThreadFinishRead(pDisk); 8684 AssertRC(rc2); 8685 fLockRead = false; 8686 8687 rc2 = vdThreadStartWrite(pDisk); 8688 AssertRC(rc2); 8689 fLockWrite = true; 8690 8691 /* 8692 * Open all images in the chain in read write mode first to avoid running 8693 * into an error in the middle of the process. 8694 */ 8695 PVDIMAGE pImage = pDisk->pBase; 8696 8697 while (pImage) 8698 { 8699 uOpenFlags = pImage->Backend->pfnGetOpenFlags(pImage->pBackendData); 8700 if (uOpenFlags & VD_OPEN_FLAGS_READONLY) 8701 { 8702 /* 8703 * Clear skip consistency checks because the image is made writable now and 8704 * skipping consistency checks is only possible for readonly images. 8705 */ 8706 uOpenFlags &= ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS); 8707 rc = pImage->Backend->pfnSetOpenFlags(pImage->pBackendData, uOpenFlags); 8708 if (RT_FAILURE(rc)) 8709 break; 8710 } 8711 pImage = pImage->pNext; 8712 } 8713 8714 if (RT_SUCCESS(rc)) 8715 { 8716 unsigned cImgCur = 0; 8717 unsigned uPercentStart = 0; 8718 unsigned uPercentSpan = 100 / pDisk->cImages - 1; 8719 8720 /* Allocate tmp buffer. */ 8721 void *pvBuf = RTMemTmpAlloc(VD_MERGE_BUFFER_SIZE); 8722 if (!pvBuf) 8723 { 8724 rc = VERR_NO_MEMORY; 8725 break; 8726 } 8727 8728 pImage = pDisk->pBase; 8729 pDisk->fLocked = true; 8730 8731 while ( pImage 8732 && RT_SUCCESS(rc)) 8733 { 8734 /* Get size of image. */ 8735 uint64_t cbSize = pImage->Backend->pfnGetSize(pImage->pBackendData); 8736 uint64_t uOffset = 0; 8737 uint64_t cbRemaining = cbSize; 8738 8739 do 8740 { 8741 size_t cbThisRead = RT_MIN(VD_MERGE_BUFFER_SIZE, cbRemaining); 8742 RTSGSEG SegmentBuf; 8743 RTSGBUF SgBuf; 8744 VDIOCTX IoCtx; 8745 8746 SegmentBuf.pvSeg = pvBuf; 8747 SegmentBuf.cbSeg = VD_MERGE_BUFFER_SIZE; 8748 RTSgBufInit(&SgBuf, &SegmentBuf, 1); 8749 vdIoCtxInit(&IoCtx, pDisk, VDIOCTXTXDIR_READ, 0, 0, NULL, 8750 &SgBuf, NULL, NULL, VDIOCTX_FLAGS_SYNC); 8751 8752 rc = pImage->Backend->pfnRead(pImage->pBackendData, uOffset, 8753 cbThisRead, &IoCtx, &cbThisRead); 8754 if (rc != VERR_VD_BLOCK_FREE) 8755 { 8756 if (RT_FAILURE(rc)) 8757 break; 8758 8759 /* Apply filter chains. */ 8760 rc = vdFilterChainApplyRead(pDisk, uOffset, cbThisRead, &IoCtx); 8761 if (RT_FAILURE(rc)) 8762 break; 8763 8764 rc = vdFilterChainApplyWrite(pDisk, uOffset, cbThisRead, &IoCtx); 8765 if (RT_FAILURE(rc)) 8766 break; 8767 8768 RTSgBufReset(&SgBuf); 8769 size_t cbThisWrite = 0; 8770 size_t cbPreRead = 0; 8771 size_t cbPostRead = 0; 8772 rc = pImage->Backend->pfnWrite(pImage->pBackendData, uOffset, 8773 cbThisRead, &IoCtx, &cbThisWrite, 8774 &cbPreRead, &cbPostRead, VD_WRITE_NO_ALLOC); 8775 if (RT_FAILURE(rc)) 8776 break; 8777 Assert(cbThisWrite == cbThisRead); 8778 } 8779 else 8780 rc = VINF_SUCCESS; 8781 8782 uOffset += cbThisRead; 8783 cbRemaining -= cbThisRead; 8784 8785 if (pIfProgress && pIfProgress->pfnProgress) 8786 { 8787 rc2 = pIfProgress->pfnProgress(pIfProgress->Core.pvUser, 8788 uPercentStart + uOffset * uPercentSpan / cbSize); 8789 AssertRC(rc2); /* Cancelling this operation without leaving an inconsistent state is not possible. */ 8790 } 8791 } while (uOffset < cbSize); 8792 8793 pImage = pImage->pNext; 8794 cImgCur++; 8795 uPercentStart += uPercentSpan; 8796 } 8797 8798 pDisk->fLocked = false; 8799 if (pvBuf) 8800 RTMemTmpFree(pvBuf); 8801 } 8802 8803 /* Change images except last one back to readonly. */ 8804 pImage = pDisk->pBase; 8805 while ( pImage != pDisk->pLast 8806 && pImage) 8807 { 8808 uOpenFlags = pImage->Backend->pfnGetOpenFlags(pImage->pBackendData); 8809 uOpenFlags |= VD_OPEN_FLAGS_READONLY; 8810 rc2 = pImage->Backend->pfnSetOpenFlags(pImage->pBackendData, uOpenFlags); 8811 if (RT_FAILURE(rc2)) 8812 { 8813 if (RT_SUCCESS(rc)) 8814 rc = rc2; 8815 break; 8816 } 8817 pImage = pImage->pNext; 8818 } 8819 } while (0); 8820 8821 if (RT_UNLIKELY(fLockWrite)) 8822 { 8823 rc2 = vdThreadFinishWrite(pDisk); 8824 AssertRC(rc2); 8825 } 8826 else if (RT_UNLIKELY(fLockRead)) 8827 { 8828 rc2 = vdThreadFinishRead(pDisk); 8829 AssertRC(rc2); 8830 } 8831 8832 if ( RT_SUCCESS(rc) 8833 && pIfProgress 8834 && pIfProgress->pfnProgress) 8835 pIfProgress->pfnProgress(pIfProgress->Core.pvUser, 100); 8836 8837 LogFlowFunc(("returns %Rrc\n", rc)); 8838 return rc; 8839 } 8840 8653 8841 /** 8654 8842 * Closes the last opened image file in HDD container. … … 8846 9034 if (fFlags & VD_FILTER_FLAGS_READ) 8847 9035 { 8848 Assert PtrBreakStmt(!RTListIsEmpty(&pDisk->ListFilterChainRead), rc = VERR_VD_NOT_OPENED);9036 AssertBreakStmt(!RTListIsEmpty(&pDisk->ListFilterChainRead), rc = VERR_VD_NOT_OPENED); 8849 9037 pFilter = RTListGetLast(&pDisk->ListFilterChainRead, VDFILTER, ListNodeChainRead); 8850 9038 AssertPtr(pFilter);
Note:
See TracChangeset
for help on using the changeset viewer.