summaryrefslogtreecommitdiff
path: root/src/VBox/Storage/QED.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Storage/QED.cpp')
-rw-r--r--src/VBox/Storage/QED.cpp598
1 files changed, 183 insertions, 415 deletions
diff --git a/src/VBox/Storage/QED.cpp b/src/VBox/Storage/QED.cpp
index f27957d0..681a8a56 100644
--- a/src/VBox/Storage/QED.cpp
+++ b/src/VBox/Storage/QED.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-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;
@@ -580,7 +580,7 @@ static int qedL2TblCacheFetch(PQEDIMAGE pImage, uint64_t offL2Tbl, PQEDL2CACHEEN
/* Read from the image. */
pL2Entry->offL2Tbl = offL2Tbl;
rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, offL2Tbl,
- pL2Entry->paL2Tbl, pImage->cbTable, NULL);
+ pL2Entry->paL2Tbl, pImage->cbTable);
if (RT_SUCCESS(rc))
{
#if defined(RT_BIG_ENDIAN)
@@ -632,10 +632,10 @@ static int qedL2TblCacheFetchAsync(PQEDIMAGE pImage, PVDIOCTX pIoCtx,
PVDMETAXFER pMetaXfer;
pL2Entry->offL2Tbl = offL2Tbl;
- rc = vdIfIoIntFileReadMetaAsync(pImage->pIfIo, pImage->pStorage,
- offL2Tbl, pL2Entry->paL2Tbl,
- pImage->cbTable, pIoCtx,
- &pMetaXfer, NULL, NULL);
+ rc = vdIfIoIntFileReadMeta(pImage->pIfIo, pImage->pStorage,
+ offL2Tbl, pL2Entry->paL2Tbl,
+ pImage->cbTable, pIoCtx,
+ &pMetaXfer, NULL, NULL);
if (RT_SUCCESS(rc))
{
vdIfIoIntMetaXferRelease(pImage->pIfIo, pMetaXfer);
@@ -702,7 +702,7 @@ static void qedTableMasksInit(PQEDIMAGE pImage)
}
/**
- * Converts a given logical offset into the
+ * Converts a given logical offset into the
*
* @returns nothing.
* @param pImage The image instance data.
@@ -771,59 +771,15 @@ DECLINLINE(uint64_t) qedClusterAllocate(PQEDIMAGE pImage, uint32_t cClusters)
* @returns VBox status code.
* VERR_VD_BLOCK_FREE if the cluster is not yet allocated.
* @param pImage The image instance data.
- * @param idxL1 The L1 index.
- * @param idxL2 The L2 index.
- * @param offCluster Offset inside the cluster.
- * @param poffImage Where to store the image offset on success;
- */
-static int qedConvertToImageOffset(PQEDIMAGE pImage, uint32_t idxL1, uint32_t idxL2,
- uint32_t offCluster, uint64_t *poffImage)
-{
- int rc = VERR_VD_BLOCK_FREE;
- LogFlowFunc(("pImage=%#p idxL1=%u idxL2=%u offCluster=%u poffImage=%#p\n",
- pImage, idxL1, idxL2, offCluster, poffImage));
-
- AssertReturn(idxL1 < pImage->cTableEntries, VERR_INVALID_PARAMETER);
- AssertReturn(idxL2 < pImage->cTableEntries, VERR_INVALID_PARAMETER);
-
- if (pImage->paL1Table[idxL1])
- {
- PQEDL2CACHEENTRY pL2Entry;
-
- rc = qedL2TblCacheFetch(pImage, pImage->paL1Table[idxL1], &pL2Entry);
- if (RT_SUCCESS(rc))
- {
- LogFlowFunc(("cluster start offset %llu\n", pL2Entry->paL2Tbl[idxL2]));
- /* Get real file offset. */
- if (pL2Entry->paL2Tbl[idxL2])
- *poffImage = pL2Entry->paL2Tbl[idxL2] + offCluster;
- else
- rc = VERR_VD_BLOCK_FREE;
-
- qedL2TblCacheEntryRelease(pL2Entry);
- }
- }
-
- LogFlowFunc(("returns rc=%Rrc\n", rc));
- return rc;
-}
-
-/**
- * Returns the real image offset for a given cluster or an error if the cluster is not
- * yet allocated- version for async I/O.
- *
- * @returns VBox status code.
- * VERR_VD_BLOCK_FREE if the cluster is not yet allocated.
- * @param pImage The image instance data.
* @param pIoCtx The I/O context.
* @param idxL1 The L1 index.
* @param idxL2 The L2 index.
* @param offCluster Offset inside the cluster.
* @param poffImage Where to store the image offset on success;
*/
-static int qedConvertToImageOffsetAsync(PQEDIMAGE pImage, PVDIOCTX pIoCtx,
- uint32_t idxL1, uint32_t idxL2,
- uint32_t offCluster, uint64_t *poffImage)
+static int qedConvertToImageOffset(PQEDIMAGE pImage, PVDIOCTX pIoCtx,
+ uint32_t idxL1, uint32_t idxL2,
+ uint32_t offCluster, uint64_t *poffImage)
{
int rc = VERR_VD_BLOCK_FREE;
@@ -881,14 +837,14 @@ static int qedFlushImage(PQEDIMAGE pImage)
#else
/* Write L1 table directly. */
rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, pImage->offL1Table,
- pImage->paL1Table, pImage->cbTable, NULL);
+ pImage->paL1Table, pImage->cbTable);
#endif
if (RT_SUCCESS(rc))
{
/* Write header. */
qedHdrConvertFromHostEndianess(pImage, &Header);
rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, 0, &Header,
- sizeof(Header), NULL);
+ sizeof(Header));
if (RT_SUCCESS(rc))
rc = vdIfIoIntFileFlushSync(pImage->pIfIo, pImage->pStorage);
}
@@ -920,29 +876,29 @@ static int qedFlushImageAsync(PQEDIMAGE pImage, PVDIOCTX pIoCtx)
{
qedTableConvertFromHostEndianess(paL1TblImg, pImage->paL1Table,
pImage->cTableEntries);
- rc = vdIfIoIntFileWriteMetaAsync(pImage->pIfIo, pImage->pStorage,
- pImage->offL1Table, paL1TblImg,
- pImage->cbTable, pIoCtx, NULL, NULL);
+ rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pImage->pStorage,
+ pImage->offL1Table, paL1TblImg,
+ pImage->cbTable, pIoCtx, NULL, NULL);
RTMemFree(paL1TblImg);
}
else
rc = VERR_NO_MEMORY;
#else
/* Write L1 table directly. */
- rc = vdIfIoIntFileWriteMetaAsync(pImage->pIfIo, pImage->pStorage,
- pImage->offL1Table, pImage->paL1Table,
- pImage->cbTable, pIoCtx, NULL, NULL);
+ rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pImage->pStorage,
+ pImage->offL1Table, pImage->paL1Table,
+ pImage->cbTable, pIoCtx, NULL, NULL);
#endif
if (RT_SUCCESS(rc) || rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
{
/* Write header. */
qedHdrConvertFromHostEndianess(pImage, &Header);
- rc = vdIfIoIntFileWriteMetaAsync(pImage->pIfIo, pImage->pStorage,
- 0, &Header, sizeof(Header),
- pIoCtx, NULL, NULL);
+ rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pImage->pStorage,
+ 0, &Header, sizeof(Header),
+ pIoCtx, NULL, NULL);
if (RT_SUCCESS(rc) || rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
- rc = vdIfIoIntFileFlushAsync(pImage->pIfIo, pImage->pStorage,
- pIoCtx, NULL, NULL);
+ rc = vdIfIoIntFileFlush(pImage->pIfIo, pImage->pStorage,
+ pIoCtx, NULL, NULL);
}
}
@@ -1076,7 +1032,7 @@ static int qedCheckImage(PQEDIMAGE pImage, PQedHeader pHeader)
/* Read L1 table. */
rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage,
- pHeader->u64OffL1Table, paL1Tbl, cbTable, NULL);
+ pHeader->u64OffL1Table, paL1Tbl, cbTable);
if (RT_FAILURE(rc))
{
rc = vdIfError(pImage->pIfError, VERR_VD_GEN_INVALID_HEADER, RT_SRC_POS,
@@ -1120,7 +1076,7 @@ static int qedCheckImage(PQEDIMAGE pImage, PQedHeader pHeader)
/* Read the linked L2 table and check it. */
rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage,
- paL1Tbl[iL1], paL2Tbl, cbTable, NULL);
+ paL1Tbl[iL1], paL2Tbl, cbTable);
if (RT_FAILURE(rc))
{
rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS,
@@ -1185,7 +1141,7 @@ static int qedFreeImage(PQEDIMAGE pImage, bool fDelete)
if (!fDelete)
qedFlushImage(pImage);
- vdIfIoIntFileClose(pImage->pIfIo, pImage->pStorage);
+ rc = vdIfIoIntFileClose(pImage->pIfIo, pImage->pStorage);
pImage->pStorage = NULL;
}
@@ -1193,7 +1149,10 @@ static int qedFreeImage(PQEDIMAGE pImage, bool fDelete)
RTMemFree(pImage->paL1Table);
if (pImage->pszBackingFilename)
+ {
RTMemFree(pImage->pszBackingFilename);
+ pImage->pszBackingFilename = NULL;
+ }
qedL2TblCacheDestroy(pImage);
@@ -1239,7 +1198,7 @@ static int qedOpenImage(PQEDIMAGE pImage, unsigned uOpenFlags)
goto out;
if (cbFile > sizeof(Header))
{
- rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, 0, &Header, sizeof(Header), NULL);
+ rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, 0, &Header, sizeof(Header));
if ( RT_SUCCESS(rc)
&& qedHdrConvertToHostEndianess(&Header))
{
@@ -1261,14 +1220,14 @@ static int qedOpenImage(PQEDIMAGE pImage, unsigned uOpenFlags)
&& (Header.u64FeatureFlags & QED_FEATURE_BACKING_FILE))
{
/* Load backing filename from image. */
- pImage->pszFilename = (char *)RTMemAllocZ(Header.u32BackingFilenameSize + 1); /* +1 for \0 terminator. */
- if (pImage->pszFilename)
+ pImage->pszBackingFilename = (char *)RTMemAllocZ(Header.u32BackingFilenameSize + 1); /* +1 for \0 terminator. */
+ if (pImage->pszBackingFilename)
{
pImage->cbBackingFilename = Header.u32BackingFilenameSize;
pImage->offBackingFilename = Header.u32OffBackingFilename;
rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage,
Header.u32OffBackingFilename, pImage->pszBackingFilename,
- Header.u32BackingFilenameSize, NULL);
+ Header.u32BackingFilenameSize);
}
else
rc = VERR_NO_MEMORY;
@@ -1291,7 +1250,7 @@ static int qedOpenImage(PQEDIMAGE pImage, unsigned uOpenFlags)
/* Read from the image. */
rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage,
pImage->offL1Table, pImage->paL1Table,
- pImage->cbTable, NULL);
+ pImage->cbTable);
if (RT_SUCCESS(rc))
{
qedTableConvertToHostEndianess(pImage->paL1Table, pImage->cTableEntries);
@@ -1482,10 +1441,10 @@ static DECLCALLBACK(int) qedAsyncClusterAllocUpdate(void *pBackendData, PVDIOCTX
/* Update the link in the on disk L1 table now. */
pClusterAlloc->enmAllocState = QEDCLUSTERASYNCALLOCSTATE_L2_LINK;
- rc = vdIfIoIntFileWriteMetaAsync(pImage->pIfIo, pImage->pStorage,
- pImage->offL1Table + pClusterAlloc->idxL1*sizeof(uint64_t),
- &offUpdateLe, sizeof(uint64_t), pIoCtx,
- qedAsyncClusterAllocUpdate, pClusterAlloc);
+ rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pImage->pStorage,
+ pImage->offL1Table + pClusterAlloc->idxL1*sizeof(uint64_t),
+ &offUpdateLe, sizeof(uint64_t), pIoCtx,
+ qedAsyncClusterAllocUpdate, pClusterAlloc);
if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
break;
else if (RT_FAILURE(rc))
@@ -1510,9 +1469,9 @@ static DECLCALLBACK(int) qedAsyncClusterAllocUpdate(void *pBackendData, PVDIOCTX
pClusterAlloc->offClusterNew = offData;
/* Write data. */
- rc = vdIfIoIntFileWriteUserAsync(pImage->pIfIo, pImage->pStorage,
- offData, pIoCtx, pClusterAlloc->cbToWrite,
- qedAsyncClusterAllocUpdate, pClusterAlloc);
+ rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pImage->pStorage,
+ offData, pIoCtx, pClusterAlloc->cbToWrite,
+ qedAsyncClusterAllocUpdate, pClusterAlloc);
if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
break;
else if (RT_FAILURE(rc))
@@ -1529,10 +1488,10 @@ static DECLCALLBACK(int) qedAsyncClusterAllocUpdate(void *pBackendData, PVDIOCTX
pClusterAlloc->enmAllocState = QEDCLUSTERASYNCALLOCSTATE_USER_LINK;
/* Link L2 table and update it. */
- rc = vdIfIoIntFileWriteMetaAsync(pImage->pIfIo, pImage->pStorage,
- pImage->paL1Table[pClusterAlloc->idxL1] + pClusterAlloc->idxL2*sizeof(uint64_t),
- &offUpdateLe, sizeof(uint64_t), pIoCtx,
- qedAsyncClusterAllocUpdate, pClusterAlloc);
+ rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pImage->pStorage,
+ pImage->paL1Table[pClusterAlloc->idxL1] + pClusterAlloc->idxL2*sizeof(uint64_t),
+ &offUpdateLe, sizeof(uint64_t), pIoCtx,
+ qedAsyncClusterAllocUpdate, pClusterAlloc);
if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
break;
else if (RT_FAILURE(rc))
@@ -1594,7 +1553,7 @@ static int qedCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk,
{
QedHeader Header;
- rc = vdIfIoIntFileReadSync(pIfIo, pStorage, 0, &Header, sizeof(Header), NULL);
+ rc = vdIfIoIntFileReadSync(pIfIo, pStorage, 0, &Header, sizeof(Header));
if ( RT_SUCCESS(rc)
&& qedHdrConvertToHostEndianess(&Header))
{
@@ -1800,12 +1759,11 @@ static int qedClose(void *pBackendData, bool fDelete)
return rc;
}
-/** @copydoc VBOXHDDBACKEND::pfnRead */
-static int qedRead(void *pBackendData, uint64_t uOffset, void *pvBuf,
- size_t cbToRead, size_t *pcbActuallyRead)
+static int qedRead(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));
PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
uint32_t offCluster = 0;
uint32_t idxL1 = 0;
@@ -1817,6 +1775,12 @@ static int qedRead(void *pBackendData, uint64_t uOffset, void *pvBuf,
Assert(uOffset % 512 == 0);
Assert(cbToRead % 512 == 0);
+ if (!VALID_PTR(pIoCtx) || !cbToRead)
+ {
+ rc = VERR_INVALID_PARAMETER;
+ goto out;
+ }
+
if ( uOffset + cbToRead > pImage->cbSize
|| cbToRead == 0)
{
@@ -1825,21 +1789,19 @@ static int qedRead(void *pBackendData, uint64_t uOffset, void *pvBuf,
}
qedConvertLogicalOffset(pImage, uOffset, &idxL1, &idxL2, &offCluster);
- LogFlowFunc(("idxL1=%u idxL2=%u offCluster=%u\n", idxL1, idxL2, offCluster));
/* Clip read size to remain in the cluster. */
cbToRead = RT_MIN(cbToRead, pImage->cbCluster - offCluster);
/* Get offset in image. */
- rc = qedConvertToImageOffset(pImage, idxL1, idxL2, offCluster, &offFile);
+ rc = qedConvertToImageOffset(pImage, pIoCtx, idxL1, idxL2, offCluster, &offFile);
if (RT_SUCCESS(rc))
- {
- LogFlowFunc(("offFile=%llu\n", offFile));
- rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, offFile,
- pvBuf, cbToRead, NULL);
- }
+ rc = vdIfIoIntFileReadUser(pImage->pIfIo, pImage->pStorage, offFile,
+ pIoCtx, cbToRead);
- if ( (RT_SUCCESS(rc) || rc == VERR_VD_BLOCK_FREE)
+ if ( ( RT_SUCCESS(rc)
+ || rc == VERR_VD_BLOCK_FREE
+ || rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
&& pcbActuallyRead)
*pcbActuallyRead = cbToRead;
@@ -1848,23 +1810,22 @@ out:
return rc;
}
-/** @copydoc VBOXHDDBACKEND::pfnWrite */
-static int qedWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf,
- size_t cbToWrite, size_t *pcbWriteProcess,
- size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite)
+static int qedWrite(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));
PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
uint32_t offCluster = 0;
uint32_t idxL1 = 0;
uint32_t idxL2 = 0;
uint64_t offImage = 0;
- int rc;
+ int rc = VINF_SUCCESS;
AssertPtr(pImage);
- Assert(uOffset % 512 == 0);
- Assert(cbToWrite % 512 == 0);
+ Assert(!(uOffset % 512));
+ Assert(!(cbToWrite % 512));
if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
{
@@ -1872,6 +1833,12 @@ static int qedWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf,
goto out;
}
+ if (!VALID_PTR(pIoCtx) || !cbToWrite)
+ {
+ rc = VERR_INVALID_PARAMETER;
+ goto out;
+ }
+
if ( uOffset + cbToWrite > pImage->cbSize
|| cbToWrite == 0)
{
@@ -1887,10 +1854,10 @@ static int qedWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf,
Assert(!(cbToWrite % 512));
/* Get offset in image. */
- rc = qedConvertToImageOffset(pImage, idxL1, idxL2, offCluster, &offImage);
+ rc = qedConvertToImageOffset(pImage, pIoCtx, idxL1, idxL2, offCluster, &offImage);
if (RT_SUCCESS(rc))
- rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, offImage,
- pvBuf, cbToWrite, NULL);
+ rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pImage->pStorage,
+ offImage, pIoCtx, cbToWrite, NULL, NULL);
else if (rc == VERR_VD_BLOCK_FREE)
{
if ( cbToWrite == pImage->cbCluster
@@ -1909,59 +1876,98 @@ static int qedWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf,
/* Check if we have to allocate a new cluster for L2 tables. */
if (!pImage->paL1Table[idxL1])
{
- uint64_t offL2Tbl = qedClusterAllocate(pImage, qedByte2Cluster(pImage, pImage->cbTable));
+ uint64_t offL2Tbl;
+ PQEDCLUSTERASYNCALLOC pL2ClusterAlloc = NULL;
+
+ /* Allocate new async cluster allocation state. */
+ pL2ClusterAlloc = (PQEDCLUSTERASYNCALLOC)RTMemAllocZ(sizeof(QEDCLUSTERASYNCALLOC));
+ if (RT_UNLIKELY(!pL2ClusterAlloc))
+ {
+ rc = VERR_NO_MEMORY;
+ break;
+ }
pL2Entry = qedL2TblCacheEntryAlloc(pImage);
if (!pL2Entry)
{
rc = VERR_NO_MEMORY;
+ RTMemFree(pL2ClusterAlloc);
break;
}
+ offL2Tbl = qedClusterAllocate(pImage, qedByte2Cluster(pImage, pImage->cbTable));
pL2Entry->offL2Tbl = offL2Tbl;
memset(pL2Entry->paL2Tbl, 0, pImage->cbTable);
- qedL2TblCacheEntryInsert(pImage, pL2Entry);
+
+ pL2ClusterAlloc->enmAllocState = QEDCLUSTERASYNCALLOCSTATE_L2_ALLOC;
+ pL2ClusterAlloc->cbImageOld = offL2Tbl;
+ pL2ClusterAlloc->offClusterNew = offL2Tbl;
+ pL2ClusterAlloc->idxL1 = idxL1;
+ pL2ClusterAlloc->idxL2 = idxL2;
+ pL2ClusterAlloc->cbToWrite = cbToWrite;
+ pL2ClusterAlloc->pL2Entry = pL2Entry;
/*
* Write the L2 table first and link to the L1 table afterwards.
* If something unexpected happens the worst case which can happen
* is a leak of some clusters.
*/
- rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, offL2Tbl,
- pL2Entry->paL2Tbl, pImage->cbTable, NULL);
- if (RT_FAILURE(rc))
+ rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pImage->pStorage,
+ offL2Tbl, pL2Entry->paL2Tbl, pImage->cbTable, pIoCtx,
+ qedAsyncClusterAllocUpdate, pL2ClusterAlloc);
+ if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
break;
-
- /* Write the L1 link now. */
- pImage->paL1Table[idxL1] = offL2Tbl;
- idxUpdateLe = RT_H2LE_U64(offL2Tbl);
- rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage,
- pImage->offL1Table + idxL1*sizeof(uint64_t),
- &idxUpdateLe, sizeof(uint64_t), NULL);
- if (RT_FAILURE(rc))
+ else if (RT_FAILURE(rc))
+ {
+ RTMemFree(pL2ClusterAlloc);
+ qedL2TblCacheEntryFree(pImage, pL2Entry);
break;
+ }
+
+ rc = qedAsyncClusterAllocUpdate(pImage, pIoCtx, pL2ClusterAlloc, rc);
}
else
- rc = qedL2TblCacheFetch(pImage, pImage->paL1Table[idxL1], &pL2Entry);
-
- if (RT_SUCCESS(rc))
{
- /* Allocate new cluster for the data. */
- uint64_t offData = qedClusterAllocate(pImage, 1);
+ rc = qedL2TblCacheFetchAsync(pImage, pIoCtx, pImage->paL1Table[idxL1],
+ &pL2Entry);
- /* Write data. */
- rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage,
- offData, pvBuf, cbToWrite, NULL);
- if (RT_FAILURE(rc))
- break;
+ if (RT_SUCCESS(rc))
+ {
+ PQEDCLUSTERASYNCALLOC pDataClusterAlloc = NULL;
- /* Link L2 table and update it. */
- pL2Entry->paL2Tbl[idxL2] = offData;
- idxUpdateLe = RT_H2LE_U64(offData);
- rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage,
- pImage->paL1Table[idxL1] + idxL2*sizeof(uint64_t),
- &idxUpdateLe, sizeof(uint64_t), NULL);
- qedL2TblCacheEntryRelease(pL2Entry);
+ /* Allocate new async cluster allocation state. */
+ pDataClusterAlloc = (PQEDCLUSTERASYNCALLOC)RTMemAllocZ(sizeof(QEDCLUSTERASYNCALLOC));
+ if (RT_UNLIKELY(!pDataClusterAlloc))
+ {
+ rc = VERR_NO_MEMORY;
+ break;
+ }
+
+ /* Allocate new cluster for the data. */
+ uint64_t offData = qedClusterAllocate(pImage, 1);
+
+ pDataClusterAlloc->enmAllocState = QEDCLUSTERASYNCALLOCSTATE_USER_ALLOC;
+ pDataClusterAlloc->cbImageOld = offData;
+ pDataClusterAlloc->offClusterNew = offData;
+ pDataClusterAlloc->idxL1 = idxL1;
+ pDataClusterAlloc->idxL2 = idxL2;
+ pDataClusterAlloc->cbToWrite = cbToWrite;
+ pDataClusterAlloc->pL2Entry = pL2Entry;
+
+ /* Write data. */
+ rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pImage->pStorage,
+ offData, pIoCtx, cbToWrite,
+ qedAsyncClusterAllocUpdate, pDataClusterAlloc);
+ if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
+ break;
+ else if (RT_FAILURE(rc))
+ {
+ RTMemFree(pDataClusterAlloc);
+ break;
+ }
+
+ rc = qedAsyncClusterAllocUpdate(pImage, pIoCtx, pDataClusterAlloc, rc);
+ }
}
} while (0);
@@ -1981,19 +1987,25 @@ static int qedWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf,
if (pcbWriteProcess)
*pcbWriteProcess = cbToWrite;
+
out:
LogFlowFunc(("returns %Rrc\n", rc));
return rc;
}
-/** @copydoc VBOXHDDBACKEND::pfnFlush */
-static int qedFlush(void *pBackendData)
+static int qedFlush(void *pBackendData, PVDIOCTX pIoCtx)
{
LogFlowFunc(("pBackendData=%#p\n", pBackendData));
PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
- int rc;
+ int rc = VINF_SUCCESS;
+
+ Assert(pImage);
+
+ if (VALID_PTR(pIoCtx))
+ rc = qedFlushImageAsync(pImage, pIoCtx);
+ else
+ rc = VERR_INVALID_PARAMETER;
- rc = qedFlushImage(pImage);
LogFlowFunc(("returns %Rrc\n", rc));
return rc;
}
@@ -2012,6 +2024,22 @@ static unsigned qedGetVersion(void *pBackendData)
return 0;
}
+/** @copydoc VBOXHDDBACKEND::pfnGetSectorSize */
+static uint32_t qedGetSectorSize(void *pBackendData)
+{
+ LogFlowFunc(("pBackendData=%#p\n", pBackendData));
+ PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
+ uint32_t cb = 0;
+
+ AssertPtr(pImage);
+
+ if (pImage && pImage->pStorage)
+ cb = 512;
+
+ LogFlowFunc(("returns %u\n", cb));
+ return cb;
+}
+
/** @copydoc VBOXHDDBACKEND::pfnGetSize */
static uint64_t qedGetSize(void *pBackendData)
{
@@ -2208,7 +2236,8 @@ static int qedSetOpenFlags(void *pBackendData, unsigned uOpenFlags)
int rc;
/* 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)))
+ if (!pImage || (uOpenFlags & ~( VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO
+ | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS)))
{
rc = VERR_INVALID_PARAMETER;
goto out;
@@ -2455,7 +2484,7 @@ static int qedGetParentFilename(void *pBackendData, char **ppszParentFilename)
AssertPtr(pImage);
if (pImage)
- if (pImage->pszFilename)
+ if (pImage->pszBackingFilename)
*ppszParentFilename = RTStrDup(pImage->pszBackingFilename);
else
rc = VERR_NOT_SUPPORTED;
@@ -2496,7 +2525,7 @@ static int qedSetParentFilename(void *pBackendData, const char *pszParentFilenam
Assert((offData & UINT32_MAX) == offData);
pImage->offBackingFilename = (uint32_t)offData;
- pImage->cbBackingFilename = strlen(pszParentFilename);
+ pImage->cbBackingFilename = (uint32_t)strlen(pszParentFilename);
rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage,
offData + pImage->cbCluster);
}
@@ -2505,8 +2534,7 @@ static int qedSetParentFilename(void *pBackendData, const char *pszParentFilenam
rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage,
pImage->offBackingFilename,
pImage->pszBackingFilename,
- strlen(pImage->pszBackingFilename),
- NULL);
+ strlen(pImage->pszBackingFilename));
}
}
}
@@ -2517,260 +2545,6 @@ static int qedSetParentFilename(void *pBackendData, const char *pszParentFilenam
return rc;
}
-static int qedAsyncRead(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));
- PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
- uint32_t offCluster = 0;
- uint32_t idxL1 = 0;
- uint32_t idxL2 = 0;
- uint64_t offFile = 0;
- int rc;
-
- AssertPtr(pImage);
- Assert(uOffset % 512 == 0);
- Assert(cbToRead % 512 == 0);
-
- if (!VALID_PTR(pIoCtx) || !cbToRead)
- {
- rc = VERR_INVALID_PARAMETER;
- goto out;
- }
-
- if ( uOffset + cbToRead > pImage->cbSize
- || cbToRead == 0)
- {
- rc = VERR_INVALID_PARAMETER;
- goto out;
- }
-
- qedConvertLogicalOffset(pImage, uOffset, &idxL1, &idxL2, &offCluster);
-
- /* Clip read size to remain in the cluster. */
- cbToRead = RT_MIN(cbToRead, pImage->cbCluster - offCluster);
-
- /* Get offset in image. */
- rc = qedConvertToImageOffsetAsync(pImage, pIoCtx, idxL1, idxL2, offCluster,
- &offFile);
- if (RT_SUCCESS(rc))
- rc = vdIfIoIntFileReadUserAsync(pImage->pIfIo, pImage->pStorage, offFile,
- pIoCtx, cbToRead);
-
- if ( ( RT_SUCCESS(rc)
- || rc == VERR_VD_BLOCK_FREE
- || rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
- && pcbActuallyRead)
- *pcbActuallyRead = cbToRead;
-
-out:
- LogFlowFunc(("returns %Rrc\n", rc));
- return rc;
-}
-
-static int qedAsyncWrite(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));
- PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
- uint32_t offCluster = 0;
- uint32_t idxL1 = 0;
- uint32_t idxL2 = 0;
- uint64_t offImage = 0;
- 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;
- }
-
- if ( uOffset + cbToWrite > pImage->cbSize
- || cbToWrite == 0)
- {
- rc = VERR_INVALID_PARAMETER;
- goto out;
- }
-
- /* Convert offset to L1, L2 index and cluster offset. */
- qedConvertLogicalOffset(pImage, uOffset, &idxL1, &idxL2, &offCluster);
-
- /* Clip write size to remain in the cluster. */
- cbToWrite = RT_MIN(cbToWrite, pImage->cbCluster - offCluster);
- Assert(!(cbToWrite % 512));
-
- /* Get offset in image. */
- rc = qedConvertToImageOffsetAsync(pImage, pIoCtx, idxL1, idxL2, offCluster,
- &offImage);
- if (RT_SUCCESS(rc))
- rc = vdIfIoIntFileWriteUserAsync(pImage->pIfIo, pImage->pStorage,
- offImage, pIoCtx, cbToWrite, NULL, NULL);
- else if (rc == VERR_VD_BLOCK_FREE)
- {
- if ( cbToWrite == pImage->cbCluster
- && !(fWrite & VD_WRITE_NO_ALLOC))
- {
- PQEDL2CACHEENTRY pL2Entry = NULL;
-
- /* Full cluster write to previously unallocated cluster.
- * Allocate cluster and write data. */
- Assert(!offCluster);
-
- do
- {
- uint64_t idxUpdateLe = 0;
-
- /* Check if we have to allocate a new cluster for L2 tables. */
- if (!pImage->paL1Table[idxL1])
- {
- uint64_t offL2Tbl;
- PQEDCLUSTERASYNCALLOC pL2ClusterAlloc = NULL;
-
- /* Allocate new async cluster allocation state. */
- pL2ClusterAlloc = (PQEDCLUSTERASYNCALLOC)RTMemAllocZ(sizeof(QEDCLUSTERASYNCALLOC));
- if (RT_UNLIKELY(!pL2ClusterAlloc))
- {
- rc = VERR_NO_MEMORY;
- break;
- }
-
- pL2Entry = qedL2TblCacheEntryAlloc(pImage);
- if (!pL2Entry)
- {
- rc = VERR_NO_MEMORY;
- RTMemFree(pL2ClusterAlloc);
- break;
- }
-
- offL2Tbl = qedClusterAllocate(pImage, qedByte2Cluster(pImage, pImage->cbTable));
- pL2Entry->offL2Tbl = offL2Tbl;
- memset(pL2Entry->paL2Tbl, 0, pImage->cbTable);
-
- pL2ClusterAlloc->enmAllocState = QEDCLUSTERASYNCALLOCSTATE_L2_ALLOC;
- pL2ClusterAlloc->cbImageOld = offL2Tbl;
- pL2ClusterAlloc->offClusterNew = offL2Tbl;
- pL2ClusterAlloc->idxL1 = idxL1;
- pL2ClusterAlloc->idxL2 = idxL2;
- pL2ClusterAlloc->cbToWrite = cbToWrite;
- pL2ClusterAlloc->pL2Entry = pL2Entry;
-
- /*
- * Write the L2 table first and link to the L1 table afterwards.
- * If something unexpected happens the worst case which can happen
- * is a leak of some clusters.
- */
- rc = vdIfIoIntFileWriteMetaAsync(pImage->pIfIo, pImage->pStorage,
- offL2Tbl, pL2Entry->paL2Tbl, pImage->cbTable, pIoCtx,
- qedAsyncClusterAllocUpdate, pL2ClusterAlloc);
- if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
- break;
- else if (RT_FAILURE(rc))
- {
- RTMemFree(pL2ClusterAlloc);
- qedL2TblCacheEntryFree(pImage, pL2Entry);
- break;
- }
-
- rc = qedAsyncClusterAllocUpdate(pImage, pIoCtx, pL2ClusterAlloc, rc);
- }
- else
- {
- rc = qedL2TblCacheFetchAsync(pImage, pIoCtx, pImage->paL1Table[idxL1],
- &pL2Entry);
-
- if (RT_SUCCESS(rc))
- {
- PQEDCLUSTERASYNCALLOC pDataClusterAlloc = NULL;
-
- /* Allocate new async cluster allocation state. */
- pDataClusterAlloc = (PQEDCLUSTERASYNCALLOC)RTMemAllocZ(sizeof(QEDCLUSTERASYNCALLOC));
- if (RT_UNLIKELY(!pDataClusterAlloc))
- {
- rc = VERR_NO_MEMORY;
- break;
- }
-
- /* Allocate new cluster for the data. */
- uint64_t offData = qedClusterAllocate(pImage, 1);
-
- pDataClusterAlloc->enmAllocState = QEDCLUSTERASYNCALLOCSTATE_USER_ALLOC;
- pDataClusterAlloc->cbImageOld = offData;
- pDataClusterAlloc->offClusterNew = offData;
- pDataClusterAlloc->idxL1 = idxL1;
- pDataClusterAlloc->idxL2 = idxL2;
- pDataClusterAlloc->cbToWrite = cbToWrite;
- pDataClusterAlloc->pL2Entry = pL2Entry;
-
- /* Write data. */
- rc = vdIfIoIntFileWriteUserAsync(pImage->pIfIo, pImage->pStorage,
- offData, pIoCtx, cbToWrite,
- qedAsyncClusterAllocUpdate, pDataClusterAlloc);
- if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
- break;
- else if (RT_FAILURE(rc))
- {
- RTMemFree(pDataClusterAlloc);
- break;
- }
-
- rc = qedAsyncClusterAllocUpdate(pImage, pIoCtx, pDataClusterAlloc, rc);
- }
- }
-
- } while (0);
-
- *pcbPreRead = 0;
- *pcbPostRead = 0;
- }
- else
- {
- /* Trying to do a partial write to an unallocated cluster. Don't do
- * anything except letting the upper layer know what to do. */
- *pcbPreRead = offCluster;
- *pcbPostRead = pImage->cbCluster - cbToWrite - *pcbPreRead;
- }
- }
-
- if (pcbWriteProcess)
- *pcbWriteProcess = cbToWrite;
-
-
-out:
- LogFlowFunc(("returns %Rrc\n", rc));
- return rc;
-}
-
-static int qedAsyncFlush(void *pBackendData, PVDIOCTX pIoCtx)
-{
- LogFlowFunc(("pBackendData=%#p\n", pBackendData));
- PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
- int rc = VINF_SUCCESS;
-
- Assert(pImage);
-
- if (VALID_PTR(pIoCtx))
- rc = qedFlushImageAsync(pImage, pIoCtx);
- else
- rc = VERR_INVALID_PARAMETER;
-
- LogFlowFunc(("returns %Rrc\n", rc));
- return rc;
-}
-
/** @copydoc VBOXHDDBACKEND::pfnResize */
static int qedResize(void *pBackendData, uint64_t cbSize,
PCVDGEOMETRY pPCHSGeometry, PCVDGEOMETRY pLCHSGeometry,
@@ -2853,8 +2627,12 @@ VBOXHDDBACKEND g_QedBackend =
qedWrite,
/* pfnFlush */
qedFlush,
+ /* pfnDiscard */
+ NULL,
/* pfnGetVersion */
qedGetVersion,
+ /* pfnGetSectorSize */
+ qedGetSectorSize,
/* pfnGetSize */
qedGetSize,
/* pfnGetFileSize */
@@ -2905,12 +2683,6 @@ VBOXHDDBACKEND g_QedBackend =
qedGetParentFilename,
/* pfnSetParentFilename */
qedSetParentFilename,
- /* pfnAsyncRead */
- qedAsyncRead,
- /* pfnAsyncWrite */
- qedAsyncWrite,
- /* pfnAsyncFlush */
- qedAsyncFlush,
/* pfnComposeLocation */
genericFileComposeLocation,
/* pfnComposeName */
@@ -2919,10 +2691,6 @@ VBOXHDDBACKEND g_QedBackend =
NULL,
/* pfnResize */
qedResize,
- /* pfnDiscard */
- NULL,
- /* pfnAsyncDiscard */
- NULL,
/* pfnRepair */
NULL
};