summaryrefslogtreecommitdiff
path: root/src/VBox/Storage/VDI.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2014-03-26 19:21:20 +0000
committer <>2014-05-08 15:03:54 +0000
commitfb123f93f9f5ce42c8e5785d2f8e0edaf951740e (patch)
treec2103d76aec5f1f10892cd1d3a38e24f665ae5db /src/VBox/Storage/VDI.cpp
parent58ed4748338f9466599adfc8a9171280ed99e23f (diff)
downloadVirtualBox-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.cpp742
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
};