diff options
author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2014-03-26 19:21:20 +0000 |
---|---|---|
committer | <> | 2014-05-08 15:03:54 +0000 |
commit | fb123f93f9f5ce42c8e5785d2f8e0edaf951740e (patch) | |
tree | c2103d76aec5f1f10892cd1d3a38e24f665ae5db /src/VBox/Storage/VDI.cpp | |
parent | 58ed4748338f9466599adfc8a9171280ed99e23f (diff) | |
download | VirtualBox-master.tar.gz |
Imported from /home/lorry/working-area/delta_VirtualBox/VirtualBox-4.3.10.tar.bz2.HEADVirtualBox-4.3.10master
Diffstat (limited to 'src/VBox/Storage/VDI.cpp')
-rw-r--r-- | src/VBox/Storage/VDI.cpp | 742 |
1 files changed, 183 insertions, 559 deletions
diff --git a/src/VBox/Storage/VDI.cpp b/src/VBox/Storage/VDI.cpp index f20f1874..7cd47c24 100644 --- a/src/VBox/Storage/VDI.cpp +++ b/src/VBox/Storage/VDI.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2011 Oracle Corporation + * Copyright (C) 2006-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -102,6 +102,7 @@ static void vdiConvGeometryEndianess(VDIECONV enmConv, PVDIDISKGEOMETRY pDiskGeo static void vdiConvHeaderEndianessV0(VDIECONV enmConv, PVDIHEADER0 pHdrConv, PVDIHEADER0 pHdr) { + memmove(pHdrConv->szComment, pHdr->szComment, sizeof(pHdr->szComment)); pHdrConv->u32Type = SET_ENDIAN_U32(enmConv, pHdr->u32Type); pHdrConv->fFlags = SET_ENDIAN_U32(enmConv, pHdr->fFlags); vdiConvGeometryEndianess(enmConv, &pHdrConv->LegacyGeometry, &pHdr->LegacyGeometry); @@ -124,6 +125,7 @@ static void vdiConvHeaderEndianessV0(VDIECONV enmConv, PVDIHEADER0 pHdrConv, static void vdiConvHeaderEndianessV1(VDIECONV enmConv, PVDIHEADER1 pHdrConv, PVDIHEADER1 pHdr) { + memmove(pHdrConv->szComment, pHdr->szComment, sizeof(pHdr->szComment)); pHdrConv->cbHeader = SET_ENDIAN_U32(enmConv, pHdr->cbHeader); pHdrConv->u32Type = SET_ENDIAN_U32(enmConv, pHdr->u32Type); pHdrConv->fFlags = SET_ENDIAN_U32(enmConv, pHdr->fFlags); @@ -152,6 +154,7 @@ static void vdiConvHeaderEndianessV1(VDIECONV enmConv, PVDIHEADER1 pHdrConv, static void vdiConvHeaderEndianessV1p(VDIECONV enmConv, PVDIHEADER1PLUS pHdrConv, PVDIHEADER1PLUS pHdr) { + memmove(pHdrConv->szComment, pHdr->szComment, sizeof(pHdr->szComment)); pHdrConv->cbHeader = SET_ENDIAN_U32(enmConv, pHdr->cbHeader); pHdrConv->u32Type = SET_ENDIAN_U32(enmConv, pHdr->u32Type); pHdrConv->fFlags = SET_ENDIAN_U32(enmConv, pHdr->fFlags); @@ -221,7 +224,7 @@ static int vdiFreeImage(PVDIIMAGEDESC pImage, bool fDelete) if (!fDelete) vdiFlushImage(pImage); - vdIfIoIntFileClose(pImage->pIfIo, pImage->pStorage); + rc = vdIfIoIntFileClose(pImage->pIfIo, pImage->pStorage); pImage->pStorage = NULL; } @@ -325,7 +328,8 @@ static unsigned vdiTranslateVDI2ImageFlags(VDIIMAGETYPE enmType) */ static void vdiInitHeader(PVDIHEADER pHeader, uint32_t uImageFlags, const char *pszComment, uint64_t cbDisk, - uint32_t cbBlock, uint32_t cbBlockExtra) + uint32_t cbBlock, uint32_t cbBlockExtra, + uint32_t cbDataAlign) { pHeader->uVersion = VDI_IMAGE_VERSION; pHeader->u.v1plus.cbHeader = sizeof(VDIHEADER1PLUS); @@ -359,8 +363,8 @@ static void vdiInitHeader(PVDIHEADER pHeader, uint32_t uImageFlags, pHeader->u.v1plus.cBlocksAllocated = 0; /* Init offsets. */ - pHeader->u.v1plus.offBlocks = RT_ALIGN_32(sizeof(VDIPREHEADER) + sizeof(VDIHEADER1PLUS), VDI_DATA_ALIGN); - pHeader->u.v1plus.offData = RT_ALIGN_32(pHeader->u.v1plus.offBlocks + (pHeader->u.v1plus.cBlocks * sizeof(VDIIMAGEBLOCKPOINTER)), VDI_DATA_ALIGN); + pHeader->u.v1plus.offBlocks = RT_ALIGN_32(sizeof(VDIPREHEADER) + sizeof(VDIHEADER1PLUS), cbDataAlign); + pHeader->u.v1plus.offData = RT_ALIGN_32(pHeader->u.v1plus.offBlocks + (pHeader->u.v1plus.cBlocks * sizeof(VDIIMAGEBLOCKPOINTER)), cbDataAlign); /* Init uuids. */ RTUuidCreate(&pHeader->u.v1plus.uuidCreate); @@ -520,12 +524,13 @@ static int vdiCreateImage(PVDIIMAGEDESC pImage, uint64_t cbSize, PCVDGEOMETRY pLCHSGeometry, PCRTUUID pUuid, unsigned uOpenFlags, PFNVDPROGRESS pfnProgress, void *pvUser, unsigned uPercentStart, - unsigned uPercentSpan) + unsigned uPercentSpan, PVDINTERFACECONFIG pIfCfg) { int rc; uint64_t cbTotal; uint64_t cbFill; uint64_t uOff; + uint32_t cbDataAlign = VDI_DATA_ALIGN; AssertPtr(pPCHSGeometry); AssertPtr(pLCHSGeometry); @@ -543,8 +548,20 @@ static int vdiCreateImage(PVDIIMAGEDESC pImage, uint64_t cbSize, goto out; } + if (pIfCfg) + { + rc = VDCFGQueryU32Def(pIfCfg, "DataAlignment", &cbDataAlign, VDI_DATA_ALIGN); + if (RT_FAILURE(rc)) + { + rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, + N_("VDI: Getting data alignment for '%s' failed (%Rrc)"), pImage->pszFilename); + goto out; + } + } + vdiInitPreHeader(&pImage->PreHeader); - vdiInitHeader(&pImage->Header, uImageFlags, pszComment, cbSize, VDI_IMAGE_DEFAULT_BLOCK_SIZE, 0); + vdiInitHeader(&pImage->Header, uImageFlags, pszComment, cbSize, VDI_IMAGE_DEFAULT_BLOCK_SIZE, 0, + cbDataAlign); /* Save PCHS geometry. Not much work, and makes the flow of information * quite a bit clearer - relying on the higher level isn't obvious. */ pImage->PCHSGeometry = *pPCHSGeometry; @@ -639,7 +656,7 @@ static int vdiCreateImage(PVDIIMAGEDESC pImage, uint64_t cbSize, VDIPREHEADER PreHeader; vdiConvPreHeaderEndianess(VDIECONV_H2F, &PreHeader, &pImage->PreHeader); rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, 0, - &PreHeader, sizeof(PreHeader), NULL); + &PreHeader, sizeof(PreHeader)); if (RT_FAILURE(rc)) { rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VDI: writing pre-header failed for '%s'"), @@ -651,7 +668,7 @@ static int vdiCreateImage(PVDIIMAGEDESC pImage, uint64_t cbSize, VDIHEADER1PLUS Hdr; vdiConvHeaderEndianessV1p(VDIECONV_H2F, &Hdr, &pImage->Header.u.v1plus); rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, sizeof(pImage->PreHeader), - &Hdr, sizeof(Hdr), NULL); + &Hdr, sizeof(Hdr)); if (RT_FAILURE(rc)) { rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VDI: writing header failed for '%s'"), @@ -661,8 +678,7 @@ static int vdiCreateImage(PVDIIMAGEDESC pImage, uint64_t cbSize, vdiConvBlocksEndianess(VDIECONV_H2F, pImage->paBlocks, getImageBlocks(&pImage->Header)); rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, pImage->offStartBlocks, pImage->paBlocks, - getImageBlocks(&pImage->Header) * sizeof(VDIIMAGEBLOCKPOINTER), - NULL); + getImageBlocks(&pImage->Header) * sizeof(VDIIMAGEBLOCKPOINTER)); vdiConvBlocksEndianess(VDIECONV_F2H, pImage->paBlocks, getImageBlocks(&pImage->Header)); if (RT_FAILURE(rc)) { @@ -697,7 +713,7 @@ static int vdiCreateImage(PVDIIMAGEDESC pImage, uint64_t cbSize, unsigned cbChunk = (unsigned)RT_MIN(cbFill, cbBuf); rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, pImage->offStartData + uOff, - pvBuf, cbChunk, NULL); + pvBuf, cbChunk); if (RT_FAILURE(rc)) { rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VDI: writing block failed for '%s'"), pImage->pszFilename); @@ -766,7 +782,7 @@ static int vdiOpenImage(PVDIIMAGEDESC pImage, unsigned uOpenFlags) /* Read pre-header. */ VDIPREHEADER PreHeader; rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, 0, - &PreHeader, sizeof(PreHeader), NULL); + &PreHeader, sizeof(PreHeader)); if (RT_FAILURE(rc)) { vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VDI: error reading pre-header in '%s'"), pImage->pszFilename); @@ -787,8 +803,7 @@ static int vdiOpenImage(PVDIIMAGEDESC pImage, unsigned uOpenFlags) { case 0: rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, sizeof(pImage->PreHeader), - &pImage->Header.u.v0, sizeof(pImage->Header.u.v0), - NULL); + &pImage->Header.u.v0, sizeof(pImage->Header.u.v0)); if (RT_FAILURE(rc)) { rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VDI: error reading v0 header in '%s'"), pImage->pszFilename); @@ -798,8 +813,7 @@ static int vdiOpenImage(PVDIIMAGEDESC pImage, unsigned uOpenFlags) break; case 1: rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, sizeof(pImage->PreHeader), - &pImage->Header.u.v1, sizeof(pImage->Header.u.v1), - NULL); + &pImage->Header.u.v1, sizeof(pImage->Header.u.v1)); if (RT_FAILURE(rc)) { rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VDI: error reading v1 header in '%s'"), pImage->pszFilename); @@ -825,7 +839,7 @@ static int vdiOpenImage(PVDIIMAGEDESC pImage, unsigned uOpenFlags) /* Read the actual VDI 1.1+ header completely. */ rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, sizeof(pImage->PreHeader), &pImage->Header.u.v1plus, - sizeof(pImage->Header.u.v1plus), NULL); + sizeof(pImage->Header.u.v1plus)); if (RT_FAILURE(rc)) { rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VDI: error reading v1.1+ header in '%s'"), pImage->pszFilename); @@ -859,8 +873,7 @@ static int vdiOpenImage(PVDIIMAGEDESC pImage, unsigned uOpenFlags) /* Read blocks array. */ rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, pImage->offStartBlocks, pImage->paBlocks, - getImageBlocks(&pImage->Header) * sizeof(VDIIMAGEBLOCKPOINTER), - NULL); + getImageBlocks(&pImage->Header) * sizeof(VDIIMAGEBLOCKPOINTER)); if (RT_FAILURE(rc)) { rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VDI: Error reading the block table in '%s'"), pImage->pszFilename); @@ -930,7 +943,7 @@ static int vdiUpdateHeader(PVDIIMAGEDESC pImage) VDIHEADER0 Hdr; vdiConvHeaderEndianessV0(VDIECONV_H2F, &Hdr, &pImage->Header.u.v0); rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, sizeof(VDIPREHEADER), - &Hdr, sizeof(Hdr), NULL); + &Hdr, sizeof(Hdr)); break; } case 1: @@ -939,14 +952,14 @@ static int vdiUpdateHeader(PVDIIMAGEDESC pImage) VDIHEADER1 Hdr; vdiConvHeaderEndianessV1(VDIECONV_H2F, &Hdr, &pImage->Header.u.v1); rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, sizeof(VDIPREHEADER), - &Hdr, sizeof(Hdr), NULL); + &Hdr, sizeof(Hdr)); } else { VDIHEADER1PLUS Hdr; vdiConvHeaderEndianessV1p(VDIECONV_H2F, &Hdr, &pImage->Header.u.v1plus); rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, sizeof(VDIPREHEADER), - &Hdr, sizeof(Hdr), NULL); + &Hdr, sizeof(Hdr)); } break; default: @@ -969,9 +982,9 @@ static int vdiUpdateHeaderAsync(PVDIIMAGEDESC pImage, PVDIOCTX pIoCtx) { VDIHEADER0 Hdr; vdiConvHeaderEndianessV0(VDIECONV_H2F, &Hdr, &pImage->Header.u.v0); - rc = vdIfIoIntFileWriteMetaAsync(pImage->pIfIo, pImage->pStorage, - sizeof(VDIPREHEADER), &Hdr, sizeof(Hdr), - pIoCtx, NULL, NULL); + rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pImage->pStorage, + sizeof(VDIPREHEADER), &Hdr, sizeof(Hdr), + pIoCtx, NULL, NULL); break; } case 1: @@ -979,17 +992,17 @@ static int vdiUpdateHeaderAsync(PVDIIMAGEDESC pImage, PVDIOCTX pIoCtx) { VDIHEADER1 Hdr; vdiConvHeaderEndianessV1(VDIECONV_H2F, &Hdr, &pImage->Header.u.v1); - rc = vdIfIoIntFileWriteMetaAsync(pImage->pIfIo, pImage->pStorage, - sizeof(VDIPREHEADER), &Hdr, sizeof(Hdr), - pIoCtx, NULL, NULL); + rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pImage->pStorage, + sizeof(VDIPREHEADER), &Hdr, sizeof(Hdr), + pIoCtx, NULL, NULL); } else { VDIHEADER1PLUS Hdr; vdiConvHeaderEndianessV1p(VDIECONV_H2F, &Hdr, &pImage->Header.u.v1plus); - rc = vdIfIoIntFileWriteMetaAsync(pImage->pIfIo, pImage->pStorage, - sizeof(VDIPREHEADER), &Hdr, sizeof(Hdr), - pIoCtx, NULL, NULL); + rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pImage->pStorage, + sizeof(VDIPREHEADER), &Hdr, sizeof(Hdr), + pIoCtx, NULL, NULL); } break; default: @@ -1014,8 +1027,7 @@ static int vdiUpdateBlockInfo(PVDIIMAGEDESC pImage, unsigned uBlock) VDIIMAGEBLOCKPOINTER ptrBlock = RT_H2LE_U32(pImage->paBlocks[uBlock]); rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, pImage->offStartBlocks + uBlock * sizeof(VDIIMAGEBLOCKPOINTER), - &ptrBlock, sizeof(VDIIMAGEBLOCKPOINTER), - NULL); + &ptrBlock, sizeof(VDIIMAGEBLOCKPOINTER)); AssertMsgRC(rc, ("vdiUpdateBlockInfo failed to update block=%u, filename=\"%s\", rc=%Rrc\n", uBlock, pImage->pszFilename, rc)); } @@ -1038,10 +1050,10 @@ static int vdiUpdateBlockInfoAsync(PVDIIMAGEDESC pImage, unsigned uBlock, { /* write only one block pointer. */ VDIIMAGEBLOCKPOINTER ptrBlock = RT_H2LE_U32(pImage->paBlocks[uBlock]); - rc = vdIfIoIntFileWriteMetaAsync(pImage->pIfIo, pImage->pStorage, - pImage->offStartBlocks + uBlock * sizeof(VDIIMAGEBLOCKPOINTER), - &ptrBlock, sizeof(VDIIMAGEBLOCKPOINTER), - pIoCtx, NULL, NULL); + rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pImage->pStorage, + pImage->offStartBlocks + uBlock * sizeof(VDIIMAGEBLOCKPOINTER), + &ptrBlock, sizeof(VDIIMAGEBLOCKPOINTER), + pIoCtx, NULL, NULL); AssertMsg(RT_SUCCESS(rc) || rc == VERR_VD_ASYNC_IO_IN_PROGRESS, ("vdiUpdateBlockInfo failed to update block=%u, filename=\"%s\", rc=%Rrc\n", uBlock, pImage->pszFilename, rc)); @@ -1052,7 +1064,7 @@ static int vdiUpdateBlockInfoAsync(PVDIIMAGEDESC pImage, unsigned uBlock, /** * Internal: Flush the image file to disk - async version. */ -static int vdiFlushImageAsync(PVDIIMAGEDESC pImage, PVDIOCTX pIoCtx) +static int vdiFlushImageIoCtx(PVDIIMAGEDESC pImage, PVDIOCTX pIoCtx) { int rc = VINF_SUCCESS; @@ -1063,7 +1075,7 @@ static int vdiFlushImageAsync(PVDIIMAGEDESC pImage, PVDIOCTX pIoCtx) AssertMsg(RT_SUCCESS(rc) || rc == VERR_VD_ASYNC_IO_IN_PROGRESS, ("vdiUpdateHeaderAsync() failed, filename=\"%s\", rc=%Rrc\n", pImage->pszFilename, rc)); - rc = vdIfIoIntFileFlushAsync(pImage->pIfIo, pImage->pStorage, pIoCtx, NULL, NULL); + rc = vdIfIoIntFileFlush(pImage->pIfIo, pImage->pStorage, pIoCtx, NULL, NULL); AssertMsg(RT_SUCCESS(rc) || rc == VERR_VD_ASYNC_IO_IN_PROGRESS, ("Flushing data to disk failed rc=%Rrc\n", rc)); } @@ -1072,81 +1084,6 @@ static int vdiFlushImageAsync(PVDIIMAGEDESC pImage, PVDIOCTX pIoCtx) } /** - * Internal: Discard a whole block from the image filling the created hole with - * data from another block. - * - * @returns VBox status code. - * @param pImage VDI image instance data. - * @param uBlock The block to discard. - * @param pvBlock Memory to use for the I/O. - */ -static int vdiDiscardBlock(PVDIIMAGEDESC pImage, unsigned uBlock, void *pvBlock) -{ - int rc = VINF_SUCCESS; - uint64_t cbImage; - unsigned idxLastBlock = getImageBlocksAllocated(&pImage->Header) - 1; - unsigned uBlockLast = pImage->paBlocksRev[idxLastBlock]; - VDIIMAGEBLOCKPOINTER ptrBlockDiscard = pImage->paBlocks[uBlock]; - - LogFlowFunc(("pImage=%#p uBlock=%u pvBlock=%#p\n", - pImage, uBlock, pvBlock)); - - pImage->paBlocksRev[idxLastBlock] = VDI_IMAGE_BLOCK_FREE; - - do - { - /* - * The block is empty, remove it. - * Read the last block of the image first. - */ - if (idxLastBlock != ptrBlockDiscard) - { - uint64_t u64Offset; - - LogFlowFunc(("Moving block [%u]=%u into [%u]=%u\n", - uBlockLast, idxLastBlock, uBlock, pImage->paBlocks[uBlock])); - - u64Offset = (uint64_t)idxLastBlock * pImage->cbTotalBlockData + pImage->offStartData; - rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, u64Offset, - pvBlock, pImage->cbTotalBlockData, NULL); - if (RT_FAILURE(rc)) - break; - - /* Write to the now unallocated block. */ - u64Offset = (uint64_t)ptrBlockDiscard * pImage->cbTotalBlockData + pImage->offStartData; - rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, u64Offset, - pvBlock, pImage->cbTotalBlockData, NULL); - if (RT_FAILURE(rc)) - break; - - /* Update block and reverse block tables. */ - pImage->paBlocks[uBlockLast] = ptrBlockDiscard; - pImage->paBlocksRev[ptrBlockDiscard] = uBlockLast; - rc = vdiUpdateBlockInfo(pImage, uBlockLast); - if (RT_FAILURE(rc)) - break; - } - else - LogFlowFunc(("Discard last block [%u]=%u\n", uBlock, pImage->paBlocks[uBlock])); - - pImage->paBlocks[uBlock] = VDI_IMAGE_BLOCK_ZERO; - - /* Update the block pointers. */ - setImageBlocksAllocated(&pImage->Header, idxLastBlock); - rc = vdiUpdateBlockInfo(pImage, uBlock); - if (RT_FAILURE(rc)) - break; - - pImage->cbImage -= pImage->cbTotalBlockData; - LogFlowFunc(("Set new size %llu\n", pImage->cbImage)); - rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage, pImage->cbImage); - } while (0); - - LogFlowFunc(("returns rc=%Rrc\n", rc)); - return rc; -} - -/** * Completion callback for meta/userdata reads or writes. * * @return VBox status code. @@ -1169,9 +1106,9 @@ static DECLCALLBACK(int) vdiDiscardBlockAsyncUpdate(void *pBackendData, PVDIOCTX { PVDMETAXFER pMetaXfer; uint64_t u64Offset = (uint64_t)pDiscardAsync->idxLastBlock * pImage->cbTotalBlockData + pImage->offStartData; - rc = vdIfIoIntFileReadMetaAsync(pImage->pIfIo, pImage->pStorage, u64Offset, - pDiscardAsync->pvBlock, pImage->cbTotalBlockData, pIoCtx, - &pMetaXfer, vdiDiscardBlockAsyncUpdate, pDiscardAsync); + rc = vdIfIoIntFileReadMeta(pImage->pIfIo, pImage->pStorage, u64Offset, + pDiscardAsync->pvBlock, pImage->cbTotalBlockData, pIoCtx, + &pMetaXfer, vdiDiscardBlockAsyncUpdate, pDiscardAsync); if (RT_FAILURE(rc)) break; @@ -1183,9 +1120,9 @@ static DECLCALLBACK(int) vdiDiscardBlockAsyncUpdate(void *pBackendData, PVDIOCTX { /* Block read complete. Write to the new location (discarded block). */ uint64_t u64Offset = (uint64_t)pDiscardAsync->ptrBlockDiscard * pImage->cbTotalBlockData + pImage->offStartData; - rc = vdIfIoIntFileWriteMetaAsync(pImage->pIfIo, pImage->pStorage, u64Offset, - pDiscardAsync->pvBlock, pImage->cbTotalBlockData, pIoCtx, - vdiDiscardBlockAsyncUpdate, pDiscardAsync); + rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pImage->pStorage, u64Offset, + pDiscardAsync->pvBlock, pImage->cbTotalBlockData, pIoCtx, + vdiDiscardBlockAsyncUpdate, pDiscardAsync); pDiscardAsync->enmState = VDIBLOCKDISCARDSTATE_UPDATE_METADATA; if (RT_FAILURE(rc)) @@ -1194,7 +1131,6 @@ static DECLCALLBACK(int) vdiDiscardBlockAsyncUpdate(void *pBackendData, PVDIOCTX case VDIBLOCKDISCARDSTATE_UPDATE_METADATA: { int rc2; - uint64_t cbImage; /* Block write complete. Update metadata. */ pImage->paBlocksRev[pDiscardAsync->idxLastBlock] = VDI_IMAGE_BLOCK_FREE; @@ -1303,8 +1239,9 @@ static int vdiDiscardBlockAsync(PVDIIMAGEDESC pImage, PVDIOCTX pIoCtx, */ static void *vdiAllocationBitmapCreate(void *pvData, size_t cbData) { - unsigned cSectors = cbData / 512; - unsigned uSectorCur = 0; + Assert(cbData <= UINT32_MAX / 8); + uint32_t cSectors = (uint32_t)(cbData / 512); + uint32_t uSectorCur = 0; void *pbmAllocationBitmap = NULL; Assert(!(cbData % 512)); @@ -1316,7 +1253,7 @@ static void *vdiAllocationBitmapCreate(void *pvData, size_t cbData) while (uSectorCur < cSectors) { - int idxSet = ASMBitFirstSet((uint8_t *)pvData + uSectorCur * 512, cbData * 8); + int idxSet = ASMBitFirstSet((uint8_t *)pvData + uSectorCur * 512, (uint32_t)cbData * 8); if (idxSet != -1) { @@ -1343,7 +1280,7 @@ static void *vdiAllocationBitmapCreate(void *pvData, size_t cbData) * @param pvUser Opaque user data passed during a read/write request. * @param rcReq Status code for the completed request. */ -static DECLCALLBACK(int) vdiAsyncBlockAllocUpdate(void *pBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq) +static DECLCALLBACK(int) vdiBlockAllocUpdate(void *pBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq) { int rc = VINF_SUCCESS; PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData; @@ -1475,6 +1412,8 @@ static int vdiCreate(const char *pszFilename, uint64_t cbSize, pvUser = pIfProgress->Core.pvUser; } + PVDINTERFACECONFIG pIfCfg = VDIfConfigGet(pVDIfsOperation); + /* Check the image flags. */ if ((uImageFlags & ~VD_VDI_IMAGE_FLAGS_MASK) != 0) { @@ -1491,7 +1430,6 @@ static int vdiCreate(const char *pszFilename, uint64_t cbSize, /* Check size. Maximum 4PB-3M. No tricks with adjusting the 1M block size * so far, which would extend the size. */ - cbSize = RT_ALIGN_64(cbSize, _1M); if ( !cbSize || cbSize >= _1P * 4 - _1M * 3) { @@ -1524,7 +1462,8 @@ static int vdiCreate(const char *pszFilename, uint64_t cbSize, rc = vdiCreateImage(pImage, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags, - pfnProgress, pvUser, uPercentStart, uPercentSpan); + pfnProgress, pvUser, uPercentStart, uPercentSpan, + pIfCfg); if (RT_SUCCESS(rc)) { /* So far the image is opened in read/write mode. Make sure the @@ -1567,27 +1506,29 @@ static int vdiRename(void *pBackendData, const char *pszFilename) } /* Close the image. */ - vdiFreeImage(pImage, false); - - /* Rename the file. */ - rc = vdIfIoIntFileMove(pImage->pIfIo, pImage->pszFilename, pszFilename, 0); - if (RT_FAILURE(rc)) + rc = vdiFreeImage(pImage, false); + if (RT_SUCCESS(rc)) { - /* The move failed, try to reopen the original image. */ - int rc2 = vdiOpenImage(pImage, pImage->uOpenFlags); - if (RT_FAILURE(rc2)) - rc = rc2; + /* Rename the file. */ + rc = vdIfIoIntFileMove(pImage->pIfIo, pImage->pszFilename, pszFilename, 0); + if (RT_FAILURE(rc)) + { + /* The move failed, try to reopen the original image. */ + int rc2 = vdiOpenImage(pImage, pImage->uOpenFlags); + if (RT_FAILURE(rc2)) + rc = rc2; - goto out; - } + goto out; + } - /* Update pImage with the new information. */ - pImage->pszFilename = pszFilename; + /* Update pImage with the new information. */ + pImage->pszFilename = pszFilename; - /* Open the new image. */ - rc = vdiOpenImage(pImage, pImage->uOpenFlags); - if (RT_FAILURE(rc)) - goto out; + /* Open the new image. */ + rc = vdiOpenImage(pImage, pImage->uOpenFlags); + if (RT_FAILURE(rc)) + goto out; + } out: LogFlowFunc(("returns %Rrc\n", rc)); @@ -1608,11 +1549,11 @@ static int vdiClose(void *pBackendData, bool fDelete) return rc; } -/** @copydoc VBOXHDDBACKEND::pfnRead */ -static int vdiRead(void *pBackendData, uint64_t uOffset, void *pvBuf, - size_t cbToRead, size_t *pcbActuallyRead) +static int vdiRead(void *pBackendData, uint64_t uOffset, size_t cbToRead, + PVDIOCTX pIoCtx, size_t *pcbActuallyRead) { - LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n", pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead)); + LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n", + pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead)); PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData; unsigned uBlock; unsigned offRead; @@ -1623,7 +1564,7 @@ static int vdiRead(void *pBackendData, uint64_t uOffset, void *pvBuf, Assert(!(cbToRead % 512)); if ( uOffset + cbToRead > getImageDiskSize(&pImage->Header) - || !VALID_PTR(pvBuf) + || !VALID_PTR(pIoCtx) || !cbToRead) { rc = VERR_INVALID_PARAMETER; @@ -1642,7 +1583,11 @@ static int vdiRead(void *pBackendData, uint64_t uOffset, void *pvBuf, rc = VERR_VD_BLOCK_FREE; else if (pImage->paBlocks[uBlock] == VDI_IMAGE_BLOCK_ZERO) { - memset(pvBuf, 0, cbToRead); + size_t cbSet; + + cbSet = vdIfIoIntIoCtxSet(pImage->pIfIo, pIoCtx, 0, cbToRead); + Assert(cbSet == cbToRead); + rc = VINF_SUCCESS; } else @@ -1652,13 +1597,13 @@ static int vdiRead(void *pBackendData, uint64_t uOffset, void *pvBuf, + (pImage->offStartData + pImage->offStartBlockData + offRead); if (u64Offset + cbToRead <= pImage->cbImage) - rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, u64Offset, - pvBuf, cbToRead, NULL); + rc = vdIfIoIntFileReadUser(pImage->pIfIo, pImage->pStorage, u64Offset, + pIoCtx, cbToRead); else { LogRel(("VDI: Out of range access (%llu) in image %s, image size %llu\n", u64Offset, pImage->pszFilename, pImage->cbImage)); - memset(pvBuf, 0, cbToRead); + vdIfIoIntIoCtxSet(pImage->pIfIo, pIoCtx, 0, cbToRead); rc = VERR_VD_READ_OUT_OF_RANGE; } } @@ -1671,12 +1616,12 @@ out: return rc; } -/**@copydoc VBOXHDDBACKEND::pfnWrite */ -static int vdiWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf, - size_t cbToWrite, size_t *pcbWriteProcess, - size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite) +static int vdiWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite, + PVDIOCTX pIoCtx, size_t *pcbWriteProcess, size_t *pcbPreRead, + size_t *pcbPostRead, unsigned fWrite) { - LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n", pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead)); + LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n", + pBackendData, uOffset, pIoCtx, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead)); PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData; unsigned uBlock; unsigned offWrite; @@ -1692,7 +1637,7 @@ static int vdiWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf, goto out; } - if (!VALID_PTR(pvBuf) || !cbToWrite) + if (!VALID_PTR(pIoCtx) || !cbToWrite) { rc = VERR_INVALID_PARAMETER; goto out; @@ -1723,9 +1668,7 @@ static int vdiWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf, * either a zero block or a block which hasn't been used so far * (which also means that it's a zero block. Don't need to write * anything to this block if the data consists of just zeroes. */ - Assert(!(cbToWrite % 4)); - Assert(cbToWrite * 8 <= UINT32_MAX); - if (ASMBitFirstSet((volatile void *)pvBuf, (uint32_t)cbToWrite * 8) == -1) + if (vdIfIoIntIoCtxIsZero(pImage->pIfIo, pIoCtx, cbToWrite, true)) { pImage->paBlocks[uBlock] = VDI_IMAGE_BLOCK_ZERO; *pcbPreRead = 0; @@ -1740,27 +1683,35 @@ static int vdiWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf, /* Full block write to previously unallocated block. * Allocate block and write data. */ Assert(!offWrite); + PVDIASYNCBLOCKALLOC pBlockAlloc = (PVDIASYNCBLOCKALLOC)RTMemAllocZ(sizeof(VDIASYNCBLOCKALLOC)); + if (!pBlockAlloc) + { + rc = VERR_NO_MEMORY; + break; + } + unsigned cBlocksAllocated = getImageBlocksAllocated(&pImage->Header); uint64_t u64Offset = (uint64_t)cBlocksAllocated * pImage->cbTotalBlockData + (pImage->offStartData + pImage->offStartBlockData); - rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, - u64Offset, pvBuf, cbToWrite, NULL); - if (RT_FAILURE(rc)) - goto out; - pImage->paBlocks[uBlock] = cBlocksAllocated; - - if (pImage->paBlocksRev) - pImage->paBlocksRev[cBlocksAllocated] = uBlock; - setImageBlocksAllocated(&pImage->Header, cBlocksAllocated + 1); - - rc = vdiUpdateBlockInfo(pImage, uBlock); - if (RT_FAILURE(rc)) - goto out; + pBlockAlloc->cBlocksAllocated = cBlocksAllocated; + pBlockAlloc->uBlock = uBlock; - pImage->cbImage += cbToWrite; *pcbPreRead = 0; *pcbPostRead = 0; + + rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pImage->pStorage, + u64Offset, pIoCtx, cbToWrite, + vdiBlockAllocUpdate, pBlockAlloc); + if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) + break; + else if (RT_FAILURE(rc)) + { + RTMemFree(pBlockAlloc); + break; + } + + rc = vdiBlockAllocUpdate(pImage, pIoCtx, pBlockAlloc, rc); } else { @@ -1776,8 +1727,8 @@ static int vdiWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf, /* Block present in image file, write relevant data. */ uint64_t u64Offset = (uint64_t)pImage->paBlocks[uBlock] * pImage->cbTotalBlockData + (pImage->offStartData + pImage->offStartBlockData + offWrite); - rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, u64Offset, - pvBuf, cbToWrite, NULL); + rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pImage->pStorage, + u64Offset, pIoCtx, cbToWrite, NULL, NULL); } } while (0); @@ -1789,8 +1740,7 @@ out: return rc; } -/** @copydoc VBOXHDDBACKEND::pfnFlush */ -static int vdiFlush(void *pBackendData) +static int vdiFlush(void *pBackendData, PVDIOCTX pIoCtx) { LogFlowFunc(("pBackendData=%#p\n", pBackendData)); PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData; @@ -1798,7 +1748,7 @@ static int vdiFlush(void *pBackendData) Assert(pImage); - vdiFlushImage(pImage); + rc = vdiFlushImageIoCtx(pImage, pIoCtx); LogFlowFunc(("returns %Rrc\n", rc)); return rc; } @@ -1821,6 +1771,22 @@ static unsigned vdiGetVersion(void *pBackendData) return uVersion; } +/** @copydoc VBOXHDDBACKEND::pfnGetSectorSize */ +static uint32_t vdiGetSectorSize(void *pBackendData) +{ + LogFlowFunc(("pBackendData=%#p\n", pBackendData)); + PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData; + uint64_t cbSector = 0; + + AssertPtr(pImage); + + if (pImage && pImage->pStorage) + cbSector = 512; + + LogFlowFunc(("returns %zu\n", cbSector)); + return cbSector; +} + /** @copydoc VBOXHDDBACKEND::pfnGetSize */ static uint64_t vdiGetSize(void *pBackendData) { @@ -2036,7 +2002,10 @@ static int vdiSetOpenFlags(void *pBackendData, unsigned uOpenFlags) const char *pszFilename; /* Image must be opened and the new flags must be valid. */ - if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE | VD_OPEN_FLAGS_SEQUENTIAL | VD_OPEN_FLAGS_DISCARD))) + if (!pImage || (uOpenFlags & ~( VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO + | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE + | VD_OPEN_FLAGS_SEQUENTIAL | VD_OPEN_FLAGS_DISCARD + | VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS))) { rc = VERR_INVALID_PARAMETER; goto out; @@ -2416,213 +2385,6 @@ static void vdiDump(void *pBackendData) } } -static int vdiAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbToRead, - PVDIOCTX pIoCtx, size_t *pcbActuallyRead) -{ - LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n", - pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead)); - PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData; - unsigned uBlock; - unsigned offRead; - int rc; - - AssertPtr(pImage); - Assert(!(uOffset % 512)); - Assert(!(cbToRead % 512)); - - if ( uOffset + cbToRead > getImageDiskSize(&pImage->Header) - || !VALID_PTR(pIoCtx) - || !cbToRead) - { - rc = VERR_INVALID_PARAMETER; - goto out; - } - - /* Calculate starting block number and offset inside it. */ - uBlock = (unsigned)(uOffset >> pImage->uShiftOffset2Index); - offRead = (unsigned)uOffset & pImage->uBlockMask; - - /* Clip read range to at most the rest of the block. */ - cbToRead = RT_MIN(cbToRead, getImageBlockSize(&pImage->Header) - offRead); - Assert(!(cbToRead % 512)); - - if (pImage->paBlocks[uBlock] == VDI_IMAGE_BLOCK_FREE) - rc = VERR_VD_BLOCK_FREE; - else if (pImage->paBlocks[uBlock] == VDI_IMAGE_BLOCK_ZERO) - { - size_t cbSet; - - cbSet = vdIfIoIntIoCtxSet(pImage->pIfIo, pIoCtx, 0, cbToRead); - Assert(cbSet == cbToRead); - - rc = VINF_SUCCESS; - } - else - { - /* Block present in image file, read relevant data. */ - uint64_t u64Offset = (uint64_t)pImage->paBlocks[uBlock] * pImage->cbTotalBlockData - + (pImage->offStartData + pImage->offStartBlockData + offRead); - - if (u64Offset + cbToRead <= pImage->cbImage) - rc = vdIfIoIntFileReadUserAsync(pImage->pIfIo, pImage->pStorage, u64Offset, - pIoCtx, cbToRead); - else - { - LogRel(("VDI: Out of range access (%llu) in image %s, image size %llu\n", - u64Offset, pImage->pszFilename, pImage->cbImage)); - vdIfIoIntIoCtxSet(pImage->pIfIo, pIoCtx, 0, cbToRead); - rc = VERR_VD_READ_OUT_OF_RANGE; - } - } - - if (pcbActuallyRead) - *pcbActuallyRead = cbToRead; - -out: - LogFlowFunc(("returns %Rrc\n", rc)); - return rc; -} - -static int vdiAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite, - PVDIOCTX pIoCtx, - size_t *pcbWriteProcess, size_t *pcbPreRead, - size_t *pcbPostRead, unsigned fWrite) -{ - LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n", - pBackendData, uOffset, pIoCtx, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead)); - PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData; - unsigned uBlock; - unsigned offWrite; - int rc = VINF_SUCCESS; - - AssertPtr(pImage); - Assert(!(uOffset % 512)); - Assert(!(cbToWrite % 512)); - - if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) - { - rc = VERR_VD_IMAGE_READ_ONLY; - goto out; - } - - if (!VALID_PTR(pIoCtx) || !cbToWrite) - { - rc = VERR_INVALID_PARAMETER; - goto out; - } - - /* No size check here, will do that later. For dynamic images which are - * not multiples of the block size in length, this would prevent writing to - * the last block. */ - - /* Calculate starting block number and offset inside it. */ - uBlock = (unsigned)(uOffset >> pImage->uShiftOffset2Index); - offWrite = (unsigned)uOffset & pImage->uBlockMask; - - /* Clip write range to at most the rest of the block. */ - cbToWrite = RT_MIN(cbToWrite, getImageBlockSize(&pImage->Header) - offWrite); - Assert(!(cbToWrite % 512)); - - do - { - if (!IS_VDI_IMAGE_BLOCK_ALLOCATED(pImage->paBlocks[uBlock])) - { - /* Block is either free or zero. */ - if ( !(pImage->uOpenFlags & VD_OPEN_FLAGS_HONOR_ZEROES) - && ( pImage->paBlocks[uBlock] == VDI_IMAGE_BLOCK_ZERO - || cbToWrite == getImageBlockSize(&pImage->Header))) - { -#if 0 /** @todo Provide interface to check an I/O context for a specific value */ - /* If the destination block is unallocated at this point, it's - * either a zero block or a block which hasn't been used so far - * (which also means that it's a zero block. Don't need to write - * anything to this block if the data consists of just zeroes. */ - Assert(!(cbToWrite % 4)); - Assert(cbToWrite * 8 <= UINT32_MAX); - if (ASMBitFirstSet((volatile void *)pvBuf, (uint32_t)cbToWrite * 8) == -1) - { - pImage->paBlocks[uBlock] = VDI_IMAGE_BLOCK_ZERO; - break; - } -#endif - } - - if ( cbToWrite == getImageBlockSize(&pImage->Header) - && !(fWrite & VD_WRITE_NO_ALLOC)) - { - /* Full block write to previously unallocated block. - * Allocate block and write data. */ - Assert(!offWrite); - PVDIASYNCBLOCKALLOC pBlockAlloc = (PVDIASYNCBLOCKALLOC)RTMemAllocZ(sizeof(VDIASYNCBLOCKALLOC)); - if (!pBlockAlloc) - { - rc = VERR_NO_MEMORY; - break; - } - - unsigned cBlocksAllocated = getImageBlocksAllocated(&pImage->Header); - uint64_t u64Offset = (uint64_t)cBlocksAllocated * pImage->cbTotalBlockData - + (pImage->offStartData + pImage->offStartBlockData); - - pBlockAlloc->cBlocksAllocated = cBlocksAllocated; - pBlockAlloc->uBlock = uBlock; - - *pcbPreRead = 0; - *pcbPostRead = 0; - - rc = vdIfIoIntFileWriteUserAsync(pImage->pIfIo, pImage->pStorage, - u64Offset, pIoCtx, cbToWrite, - vdiAsyncBlockAllocUpdate, pBlockAlloc); - if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) - break; - else if (RT_FAILURE(rc)) - { - RTMemFree(pBlockAlloc); - break; - } - - rc = vdiAsyncBlockAllocUpdate(pImage, pIoCtx, pBlockAlloc, rc); - } - else - { - /* Trying to do a partial write to an unallocated block. Don't do - * anything except letting the upper layer know what to do. */ - *pcbPreRead = offWrite % getImageBlockSize(&pImage->Header); - *pcbPostRead = getImageBlockSize(&pImage->Header) - cbToWrite - *pcbPreRead; - rc = VERR_VD_BLOCK_FREE; - } - } - else - { - /* Block present in image file, write relevant data. */ - uint64_t u64Offset = (uint64_t)pImage->paBlocks[uBlock] * pImage->cbTotalBlockData - + (pImage->offStartData + pImage->offStartBlockData + offWrite); - rc = vdIfIoIntFileWriteUserAsync(pImage->pIfIo, pImage->pStorage, - u64Offset, pIoCtx, cbToWrite, NULL, NULL); - } - } while (0); - - if (pcbWriteProcess) - *pcbWriteProcess = cbToWrite; - -out: - LogFlowFunc(("returns %Rrc\n", rc)); - return rc; -} - -static int vdiAsyncFlush(void *pBackendData, PVDIOCTX pIoCtx) -{ - LogFlowFunc(("pBackendData=%#p\n", pBackendData)); - PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData; - int rc = VINF_SUCCESS; - - Assert(pImage); - - rc = vdiFlushImageAsync(pImage, pIoCtx); - LogFlowFunc(("returns %Rrc\n", rc)); - return rc; -} - /** @copydoc VBOXHDDBACKEND::pfnCompact */ static int vdiCompact(void *pBackendData, unsigned uPercentStart, unsigned uPercentSpan, PVDINTERFACE pVDIfsDisk, @@ -2731,7 +2493,7 @@ static int vdiCompact(void *pBackendData, unsigned uPercentStart, /* Block present in image file, read relevant data. */ uint64_t u64Offset = (uint64_t)ptrBlock * pImage->cbTotalBlockData + (pImage->offStartData + pImage->offStartBlockData); - rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, u64Offset, pvTmp, cbBlock, NULL); + rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, u64Offset, pvTmp, cbBlock); if (RT_FAILURE(rc)) break; @@ -2816,11 +2578,11 @@ static int vdiCompact(void *pBackendData, unsigned uPercentStart, uint64_t u64Offset = (uint64_t)uBlockUsedPos * pImage->cbTotalBlockData + (pImage->offStartData + pImage->offStartBlockData); rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, u64Offset, - pvTmp, cbBlock, NULL); + pvTmp, cbBlock); u64Offset = (uint64_t)i * pImage->cbTotalBlockData + (pImage->offStartData + pImage->offStartBlockData); rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, u64Offset, - pvTmp, cbBlock, NULL); + pvTmp, cbBlock); pImage->paBlocks[uBlockData] = i; setImageBlocksAllocated(&pImage->Header, cBlocksAllocated - cBlocksMoved); rc = vdiUpdateBlockInfo(pImage, uBlockData); @@ -2931,8 +2693,6 @@ static int vdiResize(void *pBackendData, uint64_t cbSize, void *pvBuf = NULL, *pvZero = NULL; do { - VDIIMAGEBLOCKPOINTER uBlock = 0; - /* Allocate data buffer. */ pvBuf = RTMemAllocZ(pImage->cbTotalBlockData); if (!pvBuf) @@ -2954,12 +2714,12 @@ static int vdiResize(void *pBackendData, uint64_t cbSize, /* Search the index in the block table. */ for (unsigned idxBlock = 0; idxBlock < cBlocksOld; idxBlock++) { - if (pImage->paBlocks[idxBlock] == uBlock) + if (!pImage->paBlocks[idxBlock]) { /* Read data and append to the end of the image. */ rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, offStartDataNew, pvBuf, - pImage->cbTotalBlockData, NULL); + pImage->cbTotalBlockData); if (RT_FAILURE(rc)) break; @@ -2970,14 +2730,14 @@ static int vdiResize(void *pBackendData, uint64_t cbSize, rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, offBlockAppend, pvBuf, - pImage->cbTotalBlockData, NULL); + pImage->cbTotalBlockData); if (RT_FAILURE(rc)) break; /* Zero out the old block area. */ rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, offStartDataNew, pvZero, - pImage->cbTotalBlockData, NULL); + pImage->cbTotalBlockData); if (RT_FAILURE(rc)) break; @@ -3006,7 +2766,6 @@ static int vdiResize(void *pBackendData, uint64_t cbSize, if (RT_FAILURE(rc)) break; - uBlock++; offStartDataNew += pImage->cbTotalBlockData; } } while (0); @@ -3045,7 +2804,7 @@ static int vdiResize(void *pBackendData, uint64_t cbSize, /* Write the block array before updating the rest. */ vdiConvBlocksEndianess(VDIECONV_H2F, pImage->paBlocks, cBlocksNew); rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, pImage->offStartBlocks, - pImage->paBlocks, cbBlockspaceNew, NULL); + pImage->paBlocks, cbBlockspaceNew); vdiConvBlocksEndianess(VDIECONV_F2H, pImage->paBlocks, cBlocksNew); if (RT_SUCCESS(rc)) @@ -3055,6 +2814,7 @@ static int vdiResize(void *pBackendData, uint64_t cbSize, setImageBlocks(&pImage->Header, cBlocksNew); /* Update geometry. */ pImage->PCHSGeometry = *pPCHSGeometry; + pImage->cbImage = cbSize; PVDIDISKGEOMETRY pGeometry = getImageLCHSGeometry(&pImage->Header); if (pGeometry) @@ -3076,138 +2836,8 @@ static int vdiResize(void *pBackendData, uint64_t cbSize, return rc; } - /** @copydoc VBOXHDDBACKEND::pfnDiscard */ -static DECLCALLBACK(int) vdiDiscard(void *pBackendData, - uint64_t uOffset, size_t cbDiscard, - size_t *pcbPreAllocated, - size_t *pcbPostAllocated, - size_t *pcbActuallyDiscarded, - void **ppbmAllocationBitmap, - unsigned fDiscard) -{ - PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData; - unsigned uBlock; - unsigned offDiscard; - int rc = VINF_SUCCESS; - void *pvBlock = NULL; - - LogFlowFunc(("pBackendData=%#p uOffset=%llu cbDiscard=%zu pcbPreAllocated=%#p pcbPostAllocated=%#p pcbActuallyDiscarded=%#p ppbmAllocationBitmap=%#p fDiscard=%#x\n", - pBackendData, uOffset, cbDiscard, pcbPreAllocated, pcbPostAllocated, pcbActuallyDiscarded, ppbmAllocationBitmap, fDiscard)); - - AssertPtr(pImage); - Assert(!(uOffset % 512)); - Assert(!(cbDiscard % 512)); - - AssertMsgReturn(!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY), - ("Image is readonly\n"), VERR_VD_IMAGE_READ_ONLY); - AssertMsgReturn( uOffset + cbDiscard <= getImageDiskSize(&pImage->Header) - && cbDiscard, - ("Invalid parameters uOffset=%llu cbDiscard=%zu\n", - uOffset, cbDiscard), - VERR_INVALID_PARAMETER); - - do - { - AssertMsgBreakStmt(!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY), - ("Image is opened readonly\n"), - rc = VERR_VD_IMAGE_READ_ONLY); - - AssertMsgBreakStmt(cbDiscard, - ("cbDiscard=%u\n", cbDiscard), - rc = VERR_INVALID_PARAMETER); - - /* Calculate starting block number and offset inside it. */ - uBlock = (unsigned)(uOffset >> pImage->uShiftOffset2Index); - offDiscard = (unsigned)uOffset & pImage->uBlockMask; - - /* Clip range to at most the rest of the block. */ - cbDiscard = RT_MIN(cbDiscard, getImageBlockSize(&pImage->Header) - offDiscard); - Assert(!(cbDiscard % 512)); - - if (pcbPreAllocated) - *pcbPreAllocated = 0; - - if (pcbPostAllocated) - *pcbPostAllocated = 0; - - if (IS_VDI_IMAGE_BLOCK_ALLOCATED(pImage->paBlocks[uBlock])) - { - uint8_t *pbBlockData; - size_t cbPreAllocated, cbPostAllocated; - - cbPreAllocated = offDiscard % getImageBlockSize(&pImage->Header); - cbPostAllocated = getImageBlockSize(&pImage->Header) - cbDiscard - cbPreAllocated; - - /* Read the block data. */ - pvBlock = RTMemAlloc(pImage->cbTotalBlockData); - if (!pvBlock) - { - rc = VERR_NO_MEMORY; - break; - } - - if (!cbPreAllocated && !cbPostAllocated) - { - /* - * Discarding a whole block, don't check for allocated sectors. - * It is possible to just remove the whole block which avoids - * one read and checking the whole block for data. - */ - rc = vdiDiscardBlock(pImage, uBlock, pvBlock); - } - else - { - /* Read data. */ - pbBlockData = (uint8_t *)pvBlock + pImage->offStartBlockData; - - uint64_t u64Offset = (uint64_t)pImage->paBlocks[uBlock] * pImage->cbTotalBlockData + pImage->offStartData; - rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, u64Offset, - pvBlock, pImage->cbTotalBlockData, NULL); - if (RT_FAILURE(rc)) - break; - - /* Clear data. */ - memset(pbBlockData + offDiscard , 0, cbDiscard); - - Assert(!(cbDiscard % 4)); - Assert(cbDiscard * 8 <= UINT32_MAX); - if (ASMBitFirstSet((volatile void *)pbBlockData, getImageBlockSize(&pImage->Header) * 8) == -1) - rc = vdiDiscardBlock(pImage, uBlock, pvBlock); - else if (fDiscard & VD_DISCARD_MARK_UNUSED) - { - /* Write changed data to the image. */ - rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, u64Offset + offDiscard, - pbBlockData + offDiscard, cbDiscard, NULL); - } - else - { - /* Block has data, create allocation bitmap. */ - *pcbPreAllocated = cbPreAllocated; - *pcbPostAllocated = cbPostAllocated; - *ppbmAllocationBitmap = vdiAllocationBitmapCreate(pbBlockData, getImageBlockSize(&pImage->Header)); - if (RT_UNLIKELY(!*ppbmAllocationBitmap)) - rc = VERR_NO_MEMORY; - else - rc = VERR_VD_DISCARD_ALIGNMENT_NOT_MET; - } - } /* if: no complete block discarded */ - } /* if: Block is allocated. */ - /* else: nothing to do. */ - } while (0); - - if (pcbActuallyDiscarded) - *pcbActuallyDiscarded = cbDiscard; - - if (pvBlock) - RTMemFree(pvBlock); - - LogFlowFunc(("returns %Rrc\n", rc)); - return rc; -} - -/** @copydoc VBOXHDDBACKEND::pfnDiscard */ -static DECLCALLBACK(int) vdiAsyncDiscard(void *pBackendData, PVDIOCTX pIoCtx, +static DECLCALLBACK(int) vdiDiscard(void *pBackendData, PVDIOCTX pIoCtx, uint64_t uOffset, size_t cbDiscard, size_t *pcbPreAllocated, size_t *pcbPostAllocated, @@ -3291,9 +2921,9 @@ static DECLCALLBACK(int) vdiAsyncDiscard(void *pBackendData, PVDIOCTX pIoCtx, memset(pvBlock, 0, cbDiscard); uint64_t u64Offset = (uint64_t)pImage->paBlocks[uBlock] * pImage->cbTotalBlockData + pImage->offStartData + offDiscard; - rc = vdIfIoIntFileWriteMetaAsync(pImage->pIfIo, pImage->pStorage, - u64Offset, pvBlock, cbDiscard, pIoCtx, - NULL, NULL); + rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pImage->pStorage, + u64Offset, pvBlock, cbDiscard, pIoCtx, + NULL, NULL); RTMemFree(pvBlock); } else @@ -3306,9 +2936,9 @@ static DECLCALLBACK(int) vdiAsyncDiscard(void *pBackendData, PVDIOCTX pIoCtx, pbBlockData = (uint8_t *)pvBlock + pImage->offStartBlockData; uint64_t u64Offset = (uint64_t)pImage->paBlocks[uBlock] * pImage->cbTotalBlockData + pImage->offStartData; - rc = vdIfIoIntFileReadMetaAsync(pImage->pIfIo, pImage->pStorage, u64Offset, - pbBlockData, pImage->cbTotalBlockData, - pIoCtx, &pMetaXfer, NULL, NULL); + rc = vdIfIoIntFileReadMeta(pImage->pIfIo, pImage->pStorage, u64Offset, + pbBlockData, pImage->cbTotalBlockData, + pIoCtx, &pMetaXfer, NULL, NULL); if (RT_FAILURE(rc)) { RTMemFree(pvBlock); @@ -3394,7 +3024,7 @@ static DECLCALLBACK(int) vdiRepair(const char *pszFilename, PVDINTERFACE pVDIfsD } /* Read pre-header. */ - rc = vdIfIoIntFileReadSync(pIfIo, pStorage, 0, &PreHdr, sizeof(PreHdr), NULL); + rc = vdIfIoIntFileReadSync(pIfIo, pStorage, 0, &PreHdr, sizeof(PreHdr)); if (RT_FAILURE(rc)) { rc = vdIfError(pIfError, rc, RT_SRC_POS, N_("VDI: Error reading pre-header in '%s'"), pszFilename); @@ -3415,8 +3045,7 @@ static DECLCALLBACK(int) vdiRepair(const char *pszFilename, PVDINTERFACE pVDIfsD { case 0: rc = vdIfIoIntFileReadSync(pIfIo, pStorage, sizeof(PreHdr), - &Hdr.u.v0, sizeof(Hdr.u.v0), - NULL); + &Hdr.u.v0, sizeof(Hdr.u.v0)); if (RT_FAILURE(rc)) rc = vdIfError(pIfError, rc, RT_SRC_POS, N_("VDI: error reading v0 header in '%s'"), pszFilename); @@ -3424,7 +3053,7 @@ static DECLCALLBACK(int) vdiRepair(const char *pszFilename, PVDINTERFACE pVDIfsD break; case 1: rc = vdIfIoIntFileReadSync(pIfIo, pStorage, sizeof(PreHdr), - &Hdr.u.v1, sizeof(Hdr.u.v1), NULL); + &Hdr.u.v1, sizeof(Hdr.u.v1)); if (RT_FAILURE(rc)) { rc = vdIfError(pIfError, rc, RT_SRC_POS, N_("VDI: error reading v1 header in '%s'"), @@ -3435,8 +3064,7 @@ static DECLCALLBACK(int) vdiRepair(const char *pszFilename, PVDINTERFACE pVDIfsD { /* Read the VDI 1.1+ header completely. */ rc = vdIfIoIntFileReadSync(pIfIo, pStorage, sizeof(PreHdr), - &Hdr.u.v1plus, sizeof(Hdr.u.v1plus), - NULL); + &Hdr.u.v1plus, sizeof(Hdr.u.v1plus)); if (RT_FAILURE(rc)) rc = vdIfError(pIfError, rc, RT_SRC_POS, N_("VDI: error reading v1.1+ header in '%s'"), pszFilename); @@ -3480,8 +3108,7 @@ static DECLCALLBACK(int) vdiRepair(const char *pszFilename, PVDINTERFACE pVDIfsD /* Read blocks array. */ rc = vdIfIoIntFileReadSync(pIfIo, pStorage, offStartBlocks, paBlocks, - getImageBlocks(&Hdr) * sizeof(VDIIMAGEBLOCKPOINTER), - NULL); + getImageBlocks(&Hdr) * sizeof(VDIIMAGEBLOCKPOINTER)); if (RT_FAILURE(rc)) { rc = vdIfError(pIfError, VERR_VD_IMAGE_REPAIR_IMPOSSIBLE, RT_SRC_POS, @@ -3536,8 +3163,7 @@ static DECLCALLBACK(int) vdiRepair(const char *pszFilename, PVDINTERFACE pVDIfsD vdiConvBlocksEndianess(VDIECONV_H2F, paBlocks, getImageBlocks(&Hdr)); rc = vdIfIoIntFileWriteSync(pIfIo, pStorage, offStartBlocks, paBlocks, - getImageBlocks(&Hdr) * sizeof(VDIIMAGEBLOCKPOINTER), - NULL); + getImageBlocks(&Hdr) * sizeof(VDIIMAGEBLOCKPOINTER)); if (RT_FAILURE(rc)) { rc = vdIfError(pIfError, VERR_VD_IMAGE_REPAIR_IMPOSSIBLE, RT_SRC_POS, @@ -3557,7 +3183,11 @@ static DECLCALLBACK(int) vdiRepair(const char *pszFilename, PVDINTERFACE pVDIfsD RTMemFree(pu32BlockBitmap); if (pStorage) - vdIfIoIntFileClose(pIfIo, pStorage); + { + int rc2 = vdIfIoIntFileClose(pIfIo, pStorage); + if (RT_SUCCESS(rc)) + rc = rc2; /* Propagate error code only if repairing was successful. */ + } LogFlowFunc(("returns %Rrc\n", rc)); return rc; @@ -3594,8 +3224,12 @@ VBOXHDDBACKEND g_VDIBackend = vdiWrite, /* pfnFlush */ vdiFlush, + /* pfnDiscard */ + vdiDiscard, /* pfnGetVersion */ vdiGetVersion, + /* pfnGetSectorSize */ + vdiGetSectorSize, /* pfnGetSize */ vdiGetSize, /* pfnGetFileSize */ @@ -3646,12 +3280,6 @@ VBOXHDDBACKEND g_VDIBackend = NULL, /* pfnSetParentFilename */ NULL, - /* pfnAsyncRead */ - vdiAsyncRead, - /* pfnAsyncWrite */ - vdiAsyncWrite, - /* pfnAsyncFlush */ - vdiAsyncFlush, /* pfnComposeLocation */ genericFileComposeLocation, /* pfnComposeName */ @@ -3660,10 +3288,6 @@ VBOXHDDBACKEND g_VDIBackend = vdiCompact, /* pfnResize */ vdiResize, - /* pfnDiscard */ - vdiDiscard, - /* pfnAsyncDiscard */ - vdiAsyncDiscard, /* pfnRepair */ vdiRepair }; |