VirtualBox

Changeset 44252 in vbox for trunk/src/VBox/Storage


Ignore:
Timestamp:
Jan 8, 2013 1:23:54 PM (12 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
83113
Message:

Storage/Backends: async/sync I/O unification, remove separate entries for sync and async I/O callbacks, remove unused code

Location:
trunk/src/VBox/Storage
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Storage/DMG.cpp

    r44233 r44252  
    16601660
    16611661/** @copydoc VBOXHDDBACKEND::pfnRead */
    1662 static int dmgRead(void *pBackendData, uint64_t uOffset, void *pvBuf,
    1663                    size_t cbToRead, size_t *pcbActuallyRead)
    1664 {
    1665     LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n", pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead));
     1662static int dmgRead(void *pBackendData, uint64_t uOffset,  size_t cbToRead,
     1663                   PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
     1664{
     1665    LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n",
     1666                 pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead));
    16661667    PDMGIMAGE pThis = (PDMGIMAGE)pBackendData;
    16671668    PDMGEXTENT pExtent = NULL;
     
    16921693            case DMGEXTENTTYPE_RAW:
    16931694            {
    1694                 rc = vdIfIoIntFileReadSync(pThis->pIfIo, pThis->pStorage,
     1695                rc = vdIfIoIntFileReadUser(pThis->pIfIo, pThis->pStorage,
    16951696                                           pExtent->offFileStart + DMG_BLOCK2BYTE(uExtentRel),
    1696                                            pvBuf, cbToRead);
     1697                                           pIoCtx, cbToRead);
    16971698                break;
    16981699            }
    16991700            case DMGEXTENTTYPE_ZERO:
    17001701            {
    1701                 memset(pvBuf, 0, cbToRead);
     1702                vdIfIoIntIoCtxSet(pThis->pIfIo, pIoCtx, 0, cbToRead);
    17021703                break;
    17031704            }
     
    17291730
    17301731                if (RT_SUCCESS(rc))
    1731                     memcpy(pvBuf, (uint8_t *)pThis->pvDecompExtent + DMG_BLOCK2BYTE(uExtentRel), cbToRead);
     1732                    vdIfIoIntIoCtxCopyTo(pThis->pIfIo, pIoCtx,
     1733                                         (uint8_t *)pThis->pvDecompExtent + DMG_BLOCK2BYTE(uExtentRel),
     1734                                         cbToRead);
    17321735                break;
    17331736            }
     
    17481751
    17491752/** @copydoc VBOXHDDBACKEND::pfnWrite */
    1750 static int dmgWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf,
    1751                     size_t cbToWrite, size_t *pcbWriteProcess,
    1752                     size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite)
    1753 {
    1754     LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n",
    1755                  pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));
     1753static int dmgWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite,
     1754                    PVDIOCTX pIoCtx, size_t *pcbWriteProcess, size_t *pcbPreRead,
     1755                    size_t *pcbPostRead, unsigned fWrite)
     1756{
     1757    LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n",
     1758                 pBackendData, uOffset, pIoCtx, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));
    17561759    PDMGIMAGE pThis = (PDMGIMAGE)pBackendData;
    17571760    int rc = VERR_NOT_IMPLEMENTED;
     
    17751778
    17761779/** @copydoc VBOXHDDBACKEND::pfnFlush */
    1777 static int dmgFlush(void *pBackendData)
     1780static int dmgFlush(void *pBackendData, PVDIOCTX pIoCtx)
    17781781{
    17791782    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     
    22692272    /* pfnFlush */
    22702273    dmgFlush,
     2274    /* pfnDiscard */
     2275    NULL,
    22712276    /* pfnGetVersion */
    22722277    dmgGetVersion,
     
    23212326    /* pfnSetParentFilename */
    23222327    NULL,
    2323     /* pfnAsyncRead */
    2324     NULL,
    2325     /* pfnAsyncWrite */
    2326     NULL,
    2327     /* pfnAsyncFlush */
    2328     NULL,
    23292328    /* pfnComposeLocation */
    23302329    genericFileComposeLocation,
     
    23352334    /* pfnResize */
    23362335    NULL,
    2337     /* pfnDiscard */
    2338     NULL,
    2339     /* pfnAsyncDiscard */
    2340     NULL,
    23412336    /* pfnRepair */
    23422337    NULL
  • trunk/src/VBox/Storage/ISCSI.cpp

    r44242 r44252  
    46044604}
    46054605
    4606 /** @copydoc VBOXHDDBACKEND::pfnRead */
    4607 static int iscsiRead(void *pBackendData, uint64_t uOffset, void *pvBuf,
    4608                      size_t cbToRead, size_t *pcbActuallyRead)
     4606static int iscsiReadSync(void *pBackendData, uint64_t uOffset, void *pvBuf,
     4607                         size_t cbToRead, size_t *pcbActuallyRead)
    46094608{
    46104609    /** @todo reinstate logging of the target everywhere - dropped temporarily */
     
    47064705}
    47074706
    4708 /** @copydoc VBOXHDDBACKEND::pfnWrite */
    4709 static int iscsiWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf,
    4710                      size_t cbToWrite, size_t *pcbWriteProcess,
    4711                      size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite)
     4707static int iscsiWriteSync(void *pBackendData, uint64_t uOffset, const void *pvBuf,
     4708                          size_t cbToWrite, size_t *pcbWriteProcess,
     4709                          size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite)
    47124710{
    47134711     LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n", pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));
     
    48104808}
    48114809
    4812 /** @copydoc VBOXHDDBACKEND::pfnFlush */
    4813 static int iscsiFlush(void *pBackendData)
     4810static int iscsiFlushSync(void *pBackendData)
    48144811{
    48154812    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     
    48534850}
    48544851
    4855 /** @copydoc VBOXHDDBACKEND::pfnGetVersion */
    4856 static unsigned iscsiGetVersion(void *pBackendData)
    4857 {
    4858     LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    4859     PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
    4860 
    4861     Assert(pImage);
    4862     NOREF(pImage);
    4863 
    4864     return 0;
    4865 }
    4866 
    4867 /** @copydoc VBOXHDDBACKEND::pfnGetSize */
    4868 static uint64_t iscsiGetSize(void *pBackendData)
    4869 {
    4870     LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    4871     PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
    4872 
    4873     Assert(pImage);
    4874 
    4875     if (pImage)
    4876         return pImage->cbSize;
    4877     else
    4878         return 0;
    4879 }
    4880 
    4881 /** @copydoc VBOXHDDBACKEND::pfnGetFileSize */
    4882 static uint64_t iscsiGetFileSize(void *pBackendData)
    4883 {
    4884     LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    4885     PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
    4886 
    4887     Assert(pImage);
    4888     NOREF(pImage);
    4889 
    4890     if (pImage)
    4891         return pImage->cbSize;
    4892     else
    4893         return 0;
    4894 }
    4895 
    4896 /** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */
    4897 static int iscsiGetPCHSGeometry(void *pBackendData, PVDGEOMETRY pPCHSGeometry)
    4898 {
    4899     LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry));
    4900     PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
    4901     int rc;
    4902 
    4903     Assert(pImage);
    4904 
    4905     if (pImage)
    4906         rc = VERR_VD_GEOMETRY_NOT_SET;
    4907     else
    4908         rc = VERR_VD_NOT_OPENED;
    4909 
    4910     LogFlowFunc(("returns %Rrc (PCHS=%u/%u/%u)\n", rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
    4911     return rc;
    4912 }
    4913 
    4914 /** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */
    4915 static int iscsiSetPCHSGeometry(void *pBackendData, PCVDGEOMETRY pPCHSGeometry)
    4916 {
    4917     LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
    4918     PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
    4919     int rc;
    4920 
    4921     Assert(pImage);
    4922 
    4923     if (pImage)
    4924     {
    4925         if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    4926         {
    4927             rc = VERR_VD_IMAGE_READ_ONLY;
    4928             goto out;
    4929         }
    4930         rc = VERR_VD_GEOMETRY_NOT_SET;
    4931     }
    4932     else
    4933         rc = VERR_VD_NOT_OPENED;
    4934 
    4935 out:
    4936     LogFlowFunc(("returns %Rrc\n", rc));
    4937     return rc;
    4938 }
    4939 
    4940 /** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */
    4941 static int iscsiGetLCHSGeometry(void *pBackendData, PVDGEOMETRY pLCHSGeometry)
    4942 {
    4943     LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry));
    4944     PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
    4945     int rc;
    4946 
    4947     Assert(pImage);
    4948 
    4949     if (pImage)
    4950         rc = VERR_VD_GEOMETRY_NOT_SET;
    4951     else
    4952         rc = VERR_VD_NOT_OPENED;
    4953 
    4954     LogFlowFunc(("returns %Rrc (LCHS=%u/%u/%u)\n", rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
    4955     return rc;
    4956 }
    4957 
    4958 /** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */
    4959 static int iscsiSetLCHSGeometry(void *pBackendData, PCVDGEOMETRY pLCHSGeometry)
    4960 {
    4961     LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
    4962     PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
    4963     int rc;
    4964 
    4965     Assert(pImage);
    4966 
    4967     if (pImage)
    4968     {
    4969         if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    4970         {
    4971             rc = VERR_VD_IMAGE_READ_ONLY;
    4972             goto out;
    4973         }
    4974         rc = VERR_VD_GEOMETRY_NOT_SET;
    4975     }
    4976     else
    4977         rc = VERR_VD_NOT_OPENED;
    4978 
    4979 out:
    4980     LogFlowFunc(("returns %Rrc\n", rc));
    4981     return rc;
    4982 }
    4983 
    4984 /** @copydoc VBOXHDDBACKEND::pfnGetImageFlags */
    4985 static unsigned iscsiGetImageFlags(void *pBackendData)
    4986 {
    4987     LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    4988     PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
    4989     unsigned uImageFlags;
    4990 
    4991     Assert(pImage);
    4992     NOREF(pImage);
    4993 
    4994     uImageFlags = VD_IMAGE_FLAGS_FIXED;
    4995 
    4996     LogFlowFunc(("returns %#x\n", uImageFlags));
    4997     return uImageFlags;
    4998 }
    4999 
    5000 /** @copydoc VBOXHDDBACKEND::pfnGetOpenFlags */
    5001 static unsigned iscsiGetOpenFlags(void *pBackendData)
    5002 {
    5003     LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    5004     PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
    5005     unsigned uOpenFlags;
    5006 
    5007     Assert(pImage);
    5008 
    5009     if (pImage)
    5010         uOpenFlags = pImage->uOpenFlags;
    5011     else
    5012         uOpenFlags = 0;
    5013 
    5014     LogFlowFunc(("returns %#x\n", uOpenFlags));
    5015     return uOpenFlags;
    5016 }
    5017 
    5018 /** @copydoc VBOXHDDBACKEND::pfnSetOpenFlags */
    5019 static int iscsiSetOpenFlags(void *pBackendData, unsigned uOpenFlags)
    5020 {
    5021     LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags));
    5022     PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
    5023     int rc;
    5024 
    5025     /* Image must be opened and the new flags must be valid. */
    5026     if (!pImage || (uOpenFlags & ~(  VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO
    5027                                    | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE
    5028                                    | VD_OPEN_FLAGS_SEQUENTIAL | VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS)))
    5029     {
    5030         rc = VERR_INVALID_PARAMETER;
    5031         goto out;
    5032     }
    5033 
    5034     /* Implement this operation via reopening the image if we actually need
    5035      * to do something. A read/write -> readonly transition doesn't need a
    5036      * reopen. In the other direction we don't have the necessary information
    5037      * as the "disk is readonly" flag is thrown away. Can be optimized too,
    5038      * but it's not worth the effort at the moment. */
    5039     if (   !(uOpenFlags & VD_OPEN_FLAGS_READONLY)
    5040         && (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    5041     {
    5042         iscsiFreeImage(pImage, false);
    5043         rc = iscsiOpenImage(pImage, uOpenFlags);
    5044     }
    5045     else
    5046     {
    5047         pImage->uOpenFlags = uOpenFlags;
    5048         rc = VINF_SUCCESS;
    5049     }
    5050 out:
    5051     LogFlowFunc(("returns %Rrc\n", rc));
    5052     return rc;
    5053 }
    5054 
    5055 /** @copydoc VBOXHDDBACKEND::pfnGetComment */
    5056 static int iscsiGetComment(void *pBackendData, char *pszComment,
    5057                           size_t cbComment)
    5058 {
    5059     LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment));
    5060     PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
    5061     int rc;
    5062 
    5063     Assert(pImage);
    5064 
    5065     if (pImage)
    5066         rc = VERR_NOT_SUPPORTED;
    5067     else
    5068         rc = VERR_VD_NOT_OPENED;
    5069 
    5070     LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment));
    5071     return rc;
    5072 }
    5073 
    5074 /** @copydoc VBOXHDDBACKEND::pfnSetComment */
    5075 static int iscsiSetComment(void *pBackendData, const char *pszComment)
    5076 {
    5077     LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment));
    5078     PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
    5079     int rc;
    5080 
    5081     Assert(pImage);
    5082 
    5083     if (pImage)
    5084     {
    5085         if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    5086             rc = VERR_NOT_SUPPORTED;
    5087         else
    5088             rc = VERR_VD_IMAGE_READ_ONLY;
    5089     }
    5090     else
    5091         rc = VERR_VD_NOT_OPENED;
    5092 
    5093     LogFlowFunc(("returns %Rrc\n", rc));
    5094     return rc;
    5095 }
    5096 
    5097 /** @copydoc VBOXHDDBACKEND::pfnGetUuid */
    5098 static int iscsiGetUuid(void *pBackendData, PRTUUID pUuid)
    5099 {
    5100     LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
    5101     PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
    5102     int rc;
    5103 
    5104     Assert(pImage);
    5105 
    5106     if (pImage)
    5107         rc = VERR_NOT_SUPPORTED;
    5108     else
    5109         rc = VERR_VD_NOT_OPENED;
    5110 
    5111     LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
    5112     return rc;
    5113 }
    5114 
    5115 /** @copydoc VBOXHDDBACKEND::pfnSetUuid */
    5116 static int iscsiSetUuid(void *pBackendData, PCRTUUID pUuid)
    5117 {
    5118     LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
    5119     PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
    5120     int rc;
    5121 
    5122     LogFlowFunc(("%RTuuid\n", pUuid));
    5123     Assert(pImage);
    5124 
    5125     if (pImage)
    5126     {
    5127         if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    5128             rc = VERR_NOT_SUPPORTED;
    5129         else
    5130             rc = VERR_VD_IMAGE_READ_ONLY;
    5131     }
    5132     else
    5133         rc = VERR_VD_NOT_OPENED;
    5134 
    5135     LogFlowFunc(("returns %Rrc\n", rc));
    5136     return rc;
    5137 }
    5138 
    5139 /** @copydoc VBOXHDDBACKEND::pfnGetModificationUuid */
    5140 static int iscsiGetModificationUuid(void *pBackendData, PRTUUID pUuid)
    5141 {
    5142     LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
    5143     PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
    5144     int rc;
    5145 
    5146     Assert(pImage);
    5147 
    5148     if (pImage)
    5149         rc = VERR_NOT_SUPPORTED;
    5150     else
    5151         rc = VERR_VD_NOT_OPENED;
    5152 
    5153     LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
    5154     return rc;
    5155 }
    5156 
    5157 /** @copydoc VBOXHDDBACKEND::pfnSetModificationUuid */
    5158 static int iscsiSetModificationUuid(void *pBackendData, PCRTUUID pUuid)
    5159 {
    5160     LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
    5161     PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
    5162     int rc;
    5163 
    5164     LogFlowFunc(("%RTuuid\n", pUuid));
    5165     Assert(pImage);
    5166 
    5167     if (pImage)
    5168     {
    5169         if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    5170             rc = VERR_NOT_SUPPORTED;
    5171         else
    5172             rc = VERR_VD_IMAGE_READ_ONLY;
    5173     }
    5174     else
    5175         rc = VERR_VD_NOT_OPENED;
    5176 
    5177     LogFlowFunc(("returns %Rrc\n", rc));
    5178     return rc;
    5179 }
    5180 
    5181 /** @copydoc VBOXHDDBACKEND::pfnGetParentUuid */
    5182 static int iscsiGetParentUuid(void *pBackendData, PRTUUID pUuid)
    5183 {
    5184     LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
    5185     PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
    5186     int rc;
    5187 
    5188     Assert(pImage);
    5189 
    5190     if (pImage)
    5191         rc = VERR_NOT_SUPPORTED;
    5192     else
    5193         rc = VERR_VD_NOT_OPENED;
    5194 
    5195     LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
    5196     return rc;
    5197 }
    5198 
    5199 /** @copydoc VBOXHDDBACKEND::pfnSetParentUuid */
    5200 static int iscsiSetParentUuid(void *pBackendData, PCRTUUID pUuid)
    5201 {
    5202     LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
    5203     PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
    5204     int rc;
    5205 
    5206     LogFlowFunc(("%RTuuid\n", pUuid));
    5207     Assert(pImage);
    5208 
    5209     if (pImage)
    5210     {
    5211         if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    5212             rc = VERR_NOT_SUPPORTED;
    5213         else
    5214             rc = VERR_VD_IMAGE_READ_ONLY;
    5215     }
    5216     else
    5217         rc = VERR_VD_NOT_OPENED;
    5218 
    5219     LogFlowFunc(("returns %Rrc\n", rc));
    5220     return rc;
    5221 }
    5222 
    5223 /** @copydoc VBOXHDDBACKEND::pfnGetParentModificationUuid */
    5224 static int iscsiGetParentModificationUuid(void *pBackendData, PRTUUID pUuid)
    5225 {
    5226     LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
    5227     PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
    5228     int rc;
    5229 
    5230     Assert(pImage);
    5231 
    5232     if (pImage)
    5233         rc = VERR_NOT_SUPPORTED;
    5234     else
    5235         rc = VERR_VD_NOT_OPENED;
    5236 
    5237     LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
    5238     return rc;
    5239 }
    5240 
    5241 /** @copydoc VBOXHDDBACKEND::pfnSetParentModificationUuid */
    5242 static int iscsiSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid)
    5243 {
    5244     LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
    5245     PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
    5246     int rc;
    5247 
    5248     LogFlowFunc(("%RTuuid\n", pUuid));
    5249     Assert(pImage);
    5250 
    5251     if (pImage)
    5252     {
    5253         if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    5254             rc = VERR_NOT_SUPPORTED;
    5255         else
    5256             rc = VERR_VD_IMAGE_READ_ONLY;
    5257     }
    5258     else
    5259         rc = VERR_VD_NOT_OPENED;
    5260 
    5261     LogFlowFunc(("returns %Rrc\n", rc));
    5262     return rc;
    5263 }
    5264 
    5265 /** @copydoc VBOXHDDBACKEND::pfnDump */
    5266 static void iscsiDump(void *pBackendData)
    5267 {
    5268     PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
    5269 
    5270     Assert(pImage);
    5271     if (pImage)
    5272     {
    5273         /** @todo put something useful here */
    5274         vdIfErrorMessage(pImage->pIfError, "Header: cVolume=%u\n", pImage->cVolume);
    5275     }
    5276 }
    5277 
    5278 /** @copydoc VBOXHDDBACKEND::pfnAsyncRead */
    5279 static int iscsiAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbToRead,
    5280                           PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
     4852/** @copydoc VBOXHDDBACKEND::pfnRead */
     4853static int iscsiRead(void *pBackendData, uint64_t uOffset, size_t cbToRead,
     4854                     PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
    52814855{
    52824856    PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
     
    53064880        Assert(cbSegs == cbToRead);
    53074881
    5308         return iscsiRead(pBackendData, uOffset, Segment.pvSeg, cbToRead, pcbActuallyRead);
     4882        return iscsiReadSync(pBackendData, uOffset, Segment.pvSeg, cbToRead, pcbActuallyRead);
    53094883    }
    53104884
     
    54124986
    54134987/** @copydoc VBOXHDDBACKEND::pfnAsyncWrite */
    5414 static int iscsiAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite,
    5415                            PVDIOCTX pIoCtx,
    5416                            size_t *pcbWriteProcess, size_t *pcbPreRead,
    5417                            size_t *pcbPostRead, unsigned fWrite)
     4988static int iscsiWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite,
     4989                      PVDIOCTX pIoCtx, size_t *pcbWriteProcess, size_t *pcbPreRead,
     4990                      size_t *pcbPostRead, unsigned fWrite)
    54184991{
    54194992    LogFlowFunc(("pBackendData=%p uOffset=%llu pIoCtx=%#p cbToWrite=%u pcbWriteProcess=%p pcbPreRead=%p pcbPostRead=%p fWrite=%u\n",
     
    54345007    cbToWrite = RT_MIN(cbToWrite, pImage->cbSendDataLength);
    54355008
    5436     /** @todo: Remove iscsiWrite and integrate properly. */
     5009    /** @todo: Remove iscsiWriteSync and integrate properly. */
    54375010    if (vdIfIoIntIoCtxIsSynchronous(pImage->pIfIo, pIoCtx))
    54385011    {
     
    54455018        Assert(cbSegs == cbToWrite);
    54465019
    5447         return iscsiWrite(pBackendData, uOffset, Segment.pvSeg, cbToWrite,
    5448                           pcbWriteProcess, pcbPreRead, pcbPostRead, fWrite);
     5020        return iscsiWriteSync(pBackendData, uOffset, Segment.pvSeg, cbToWrite,
     5021                              pcbWriteProcess, pcbPreRead, pcbPostRead, fWrite);
    54495022    }
    54505023
     
    55515124}
    55525125
    5553 /** @copydoc VBOXHDDBACKEND::pfnAsyncFlush */
    5554 static int iscsiAsyncFlush(void *pBackendData, PVDIOCTX pIoCtx)
     5126/** @copydoc VBOXHDDBACKEND::pfnFlush */
     5127static int iscsiFlush(void *pBackendData, PVDIOCTX pIoCtx)
    55555128{
    55565129    LogFlowFunc(("pBackendData=%p pIoCtx=%#p\n", pBackendData, pIoCtx));
     
    55585131    int rc = VINF_SUCCESS;
    55595132
    5560     /** @todo: Remove iscsiFlush and integrate properly. */
     5133    /** @todo: Remove iscsiFlushSync and integrate properly. */
    55615134    if (vdIfIoIntIoCtxIsSynchronous(pImage->pIfIo, pIoCtx))
    5562         return iscsiFlush(pBackendData);
     5135        return iscsiFlushSync(pBackendData);
    55635136
    55645137    PSCSIREQASYNC pReqAsync = (PSCSIREQASYNC)RTMemAllocZ(sizeof(SCSIREQASYNC));
     
    56165189    LogFlowFunc(("returns rc=%Rrc\n", rc));
    56175190    return rc;
     5191}
     5192
     5193/** @copydoc VBOXHDDBACKEND::pfnGetVersion */
     5194static unsigned iscsiGetVersion(void *pBackendData)
     5195{
     5196    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     5197    PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
     5198
     5199    Assert(pImage);
     5200    NOREF(pImage);
     5201
     5202    return 0;
     5203}
     5204
     5205/** @copydoc VBOXHDDBACKEND::pfnGetSize */
     5206static uint64_t iscsiGetSize(void *pBackendData)
     5207{
     5208    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     5209    PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
     5210
     5211    Assert(pImage);
     5212
     5213    if (pImage)
     5214        return pImage->cbSize;
     5215    else
     5216        return 0;
     5217}
     5218
     5219/** @copydoc VBOXHDDBACKEND::pfnGetFileSize */
     5220static uint64_t iscsiGetFileSize(void *pBackendData)
     5221{
     5222    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     5223    PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
     5224
     5225    Assert(pImage);
     5226    NOREF(pImage);
     5227
     5228    if (pImage)
     5229        return pImage->cbSize;
     5230    else
     5231        return 0;
     5232}
     5233
     5234/** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */
     5235static int iscsiGetPCHSGeometry(void *pBackendData, PVDGEOMETRY pPCHSGeometry)
     5236{
     5237    LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry));
     5238    PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
     5239    int rc;
     5240
     5241    Assert(pImage);
     5242
     5243    if (pImage)
     5244        rc = VERR_VD_GEOMETRY_NOT_SET;
     5245    else
     5246        rc = VERR_VD_NOT_OPENED;
     5247
     5248    LogFlowFunc(("returns %Rrc (PCHS=%u/%u/%u)\n", rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
     5249    return rc;
     5250}
     5251
     5252/** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */
     5253static int iscsiSetPCHSGeometry(void *pBackendData, PCVDGEOMETRY pPCHSGeometry)
     5254{
     5255    LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
     5256    PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
     5257    int rc;
     5258
     5259    Assert(pImage);
     5260
     5261    if (pImage)
     5262    {
     5263        if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     5264        {
     5265            rc = VERR_VD_IMAGE_READ_ONLY;
     5266            goto out;
     5267        }
     5268        rc = VERR_VD_GEOMETRY_NOT_SET;
     5269    }
     5270    else
     5271        rc = VERR_VD_NOT_OPENED;
     5272
     5273out:
     5274    LogFlowFunc(("returns %Rrc\n", rc));
     5275    return rc;
     5276}
     5277
     5278/** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */
     5279static int iscsiGetLCHSGeometry(void *pBackendData, PVDGEOMETRY pLCHSGeometry)
     5280{
     5281    LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry));
     5282    PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
     5283    int rc;
     5284
     5285    Assert(pImage);
     5286
     5287    if (pImage)
     5288        rc = VERR_VD_GEOMETRY_NOT_SET;
     5289    else
     5290        rc = VERR_VD_NOT_OPENED;
     5291
     5292    LogFlowFunc(("returns %Rrc (LCHS=%u/%u/%u)\n", rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
     5293    return rc;
     5294}
     5295
     5296/** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */
     5297static int iscsiSetLCHSGeometry(void *pBackendData, PCVDGEOMETRY pLCHSGeometry)
     5298{
     5299    LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
     5300    PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
     5301    int rc;
     5302
     5303    Assert(pImage);
     5304
     5305    if (pImage)
     5306    {
     5307        if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     5308        {
     5309            rc = VERR_VD_IMAGE_READ_ONLY;
     5310            goto out;
     5311        }
     5312        rc = VERR_VD_GEOMETRY_NOT_SET;
     5313    }
     5314    else
     5315        rc = VERR_VD_NOT_OPENED;
     5316
     5317out:
     5318    LogFlowFunc(("returns %Rrc\n", rc));
     5319    return rc;
     5320}
     5321
     5322/** @copydoc VBOXHDDBACKEND::pfnGetImageFlags */
     5323static unsigned iscsiGetImageFlags(void *pBackendData)
     5324{
     5325    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     5326    PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
     5327    unsigned uImageFlags;
     5328
     5329    Assert(pImage);
     5330    NOREF(pImage);
     5331
     5332    uImageFlags = VD_IMAGE_FLAGS_FIXED;
     5333
     5334    LogFlowFunc(("returns %#x\n", uImageFlags));
     5335    return uImageFlags;
     5336}
     5337
     5338/** @copydoc VBOXHDDBACKEND::pfnGetOpenFlags */
     5339static unsigned iscsiGetOpenFlags(void *pBackendData)
     5340{
     5341    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     5342    PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
     5343    unsigned uOpenFlags;
     5344
     5345    Assert(pImage);
     5346
     5347    if (pImage)
     5348        uOpenFlags = pImage->uOpenFlags;
     5349    else
     5350        uOpenFlags = 0;
     5351
     5352    LogFlowFunc(("returns %#x\n", uOpenFlags));
     5353    return uOpenFlags;
     5354}
     5355
     5356/** @copydoc VBOXHDDBACKEND::pfnSetOpenFlags */
     5357static int iscsiSetOpenFlags(void *pBackendData, unsigned uOpenFlags)
     5358{
     5359    LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags));
     5360    PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
     5361    int rc;
     5362
     5363    /* Image must be opened and the new flags must be valid. */
     5364    if (!pImage || (uOpenFlags & ~(  VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO
     5365                                   | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE
     5366                                   | VD_OPEN_FLAGS_SEQUENTIAL | VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS)))
     5367    {
     5368        rc = VERR_INVALID_PARAMETER;
     5369        goto out;
     5370    }
     5371
     5372    /* Implement this operation via reopening the image if we actually need
     5373     * to do something. A read/write -> readonly transition doesn't need a
     5374     * reopen. In the other direction we don't have the necessary information
     5375     * as the "disk is readonly" flag is thrown away. Can be optimized too,
     5376     * but it's not worth the effort at the moment. */
     5377    if (   !(uOpenFlags & VD_OPEN_FLAGS_READONLY)
     5378        && (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     5379    {
     5380        iscsiFreeImage(pImage, false);
     5381        rc = iscsiOpenImage(pImage, uOpenFlags);
     5382    }
     5383    else
     5384    {
     5385        pImage->uOpenFlags = uOpenFlags;
     5386        rc = VINF_SUCCESS;
     5387    }
     5388out:
     5389    LogFlowFunc(("returns %Rrc\n", rc));
     5390    return rc;
     5391}
     5392
     5393/** @copydoc VBOXHDDBACKEND::pfnGetComment */
     5394static int iscsiGetComment(void *pBackendData, char *pszComment,
     5395                          size_t cbComment)
     5396{
     5397    LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment));
     5398    PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
     5399    int rc;
     5400
     5401    Assert(pImage);
     5402
     5403    if (pImage)
     5404        rc = VERR_NOT_SUPPORTED;
     5405    else
     5406        rc = VERR_VD_NOT_OPENED;
     5407
     5408    LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment));
     5409    return rc;
     5410}
     5411
     5412/** @copydoc VBOXHDDBACKEND::pfnSetComment */
     5413static int iscsiSetComment(void *pBackendData, const char *pszComment)
     5414{
     5415    LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment));
     5416    PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
     5417    int rc;
     5418
     5419    Assert(pImage);
     5420
     5421    if (pImage)
     5422    {
     5423        if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     5424            rc = VERR_NOT_SUPPORTED;
     5425        else
     5426            rc = VERR_VD_IMAGE_READ_ONLY;
     5427    }
     5428    else
     5429        rc = VERR_VD_NOT_OPENED;
     5430
     5431    LogFlowFunc(("returns %Rrc\n", rc));
     5432    return rc;
     5433}
     5434
     5435/** @copydoc VBOXHDDBACKEND::pfnGetUuid */
     5436static int iscsiGetUuid(void *pBackendData, PRTUUID pUuid)
     5437{
     5438    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
     5439    PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
     5440    int rc;
     5441
     5442    Assert(pImage);
     5443
     5444    if (pImage)
     5445        rc = VERR_NOT_SUPPORTED;
     5446    else
     5447        rc = VERR_VD_NOT_OPENED;
     5448
     5449    LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
     5450    return rc;
     5451}
     5452
     5453/** @copydoc VBOXHDDBACKEND::pfnSetUuid */
     5454static int iscsiSetUuid(void *pBackendData, PCRTUUID pUuid)
     5455{
     5456    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
     5457    PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
     5458    int rc;
     5459
     5460    LogFlowFunc(("%RTuuid\n", pUuid));
     5461    Assert(pImage);
     5462
     5463    if (pImage)
     5464    {
     5465        if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     5466            rc = VERR_NOT_SUPPORTED;
     5467        else
     5468            rc = VERR_VD_IMAGE_READ_ONLY;
     5469    }
     5470    else
     5471        rc = VERR_VD_NOT_OPENED;
     5472
     5473    LogFlowFunc(("returns %Rrc\n", rc));
     5474    return rc;
     5475}
     5476
     5477/** @copydoc VBOXHDDBACKEND::pfnGetModificationUuid */
     5478static int iscsiGetModificationUuid(void *pBackendData, PRTUUID pUuid)
     5479{
     5480    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
     5481    PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
     5482    int rc;
     5483
     5484    Assert(pImage);
     5485
     5486    if (pImage)
     5487        rc = VERR_NOT_SUPPORTED;
     5488    else
     5489        rc = VERR_VD_NOT_OPENED;
     5490
     5491    LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
     5492    return rc;
     5493}
     5494
     5495/** @copydoc VBOXHDDBACKEND::pfnSetModificationUuid */
     5496static int iscsiSetModificationUuid(void *pBackendData, PCRTUUID pUuid)
     5497{
     5498    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
     5499    PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
     5500    int rc;
     5501
     5502    LogFlowFunc(("%RTuuid\n", pUuid));
     5503    Assert(pImage);
     5504
     5505    if (pImage)
     5506    {
     5507        if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     5508            rc = VERR_NOT_SUPPORTED;
     5509        else
     5510            rc = VERR_VD_IMAGE_READ_ONLY;
     5511    }
     5512    else
     5513        rc = VERR_VD_NOT_OPENED;
     5514
     5515    LogFlowFunc(("returns %Rrc\n", rc));
     5516    return rc;
     5517}
     5518
     5519/** @copydoc VBOXHDDBACKEND::pfnGetParentUuid */
     5520static int iscsiGetParentUuid(void *pBackendData, PRTUUID pUuid)
     5521{
     5522    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
     5523    PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
     5524    int rc;
     5525
     5526    Assert(pImage);
     5527
     5528    if (pImage)
     5529        rc = VERR_NOT_SUPPORTED;
     5530    else
     5531        rc = VERR_VD_NOT_OPENED;
     5532
     5533    LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
     5534    return rc;
     5535}
     5536
     5537/** @copydoc VBOXHDDBACKEND::pfnSetParentUuid */
     5538static int iscsiSetParentUuid(void *pBackendData, PCRTUUID pUuid)
     5539{
     5540    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
     5541    PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
     5542    int rc;
     5543
     5544    LogFlowFunc(("%RTuuid\n", pUuid));
     5545    Assert(pImage);
     5546
     5547    if (pImage)
     5548    {
     5549        if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     5550            rc = VERR_NOT_SUPPORTED;
     5551        else
     5552            rc = VERR_VD_IMAGE_READ_ONLY;
     5553    }
     5554    else
     5555        rc = VERR_VD_NOT_OPENED;
     5556
     5557    LogFlowFunc(("returns %Rrc\n", rc));
     5558    return rc;
     5559}
     5560
     5561/** @copydoc VBOXHDDBACKEND::pfnGetParentModificationUuid */
     5562static int iscsiGetParentModificationUuid(void *pBackendData, PRTUUID pUuid)
     5563{
     5564    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
     5565    PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
     5566    int rc;
     5567
     5568    Assert(pImage);
     5569
     5570    if (pImage)
     5571        rc = VERR_NOT_SUPPORTED;
     5572    else
     5573        rc = VERR_VD_NOT_OPENED;
     5574
     5575    LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
     5576    return rc;
     5577}
     5578
     5579/** @copydoc VBOXHDDBACKEND::pfnSetParentModificationUuid */
     5580static int iscsiSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid)
     5581{
     5582    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
     5583    PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
     5584    int rc;
     5585
     5586    LogFlowFunc(("%RTuuid\n", pUuid));
     5587    Assert(pImage);
     5588
     5589    if (pImage)
     5590    {
     5591        if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     5592            rc = VERR_NOT_SUPPORTED;
     5593        else
     5594            rc = VERR_VD_IMAGE_READ_ONLY;
     5595    }
     5596    else
     5597        rc = VERR_VD_NOT_OPENED;
     5598
     5599    LogFlowFunc(("returns %Rrc\n", rc));
     5600    return rc;
     5601}
     5602
     5603/** @copydoc VBOXHDDBACKEND::pfnDump */
     5604static void iscsiDump(void *pBackendData)
     5605{
     5606    PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
     5607
     5608    Assert(pImage);
     5609    if (pImage)
     5610    {
     5611        /** @todo put something useful here */
     5612        vdIfErrorMessage(pImage->pIfError, "Header: cVolume=%u\n", pImage->cVolume);
     5613    }
    56185614}
    56195615
     
    57055701    /* pfnFlush */
    57065702    iscsiFlush,
     5703    /* pfnDiscard */
     5704    NULL,
    57075705    /* pfnGetVersion */
    57085706    iscsiGetVersion,
     
    57575755    /* pfnSetParentFilename */
    57585756    NULL,
    5759     /* pfnAsyncRead */
    5760     iscsiAsyncRead,
    5761     /* pfnAsyncWrite */
    5762     iscsiAsyncWrite,
    5763     /* pfnAsyncFlush */
    5764     iscsiAsyncFlush,
    57655757    /* pfnComposeLocation */
    57665758    iscsiComposeLocation,
     
    57715763    /* pfnResize */
    57725764    NULL,
    5773     /* pfnDiscard */
    5774     NULL,
    5775     /* pfnAsyncDiscard */
    5776     NULL,
    57775765    /* pfnRepair */
    57785766    NULL
  • trunk/src/VBox/Storage/Parallels.cpp

    r44233 r44252  
    602602
    603603/** @copydoc VBOXHDDBACKEND::pfnRead */
    604 static int parallelsRead(void *pBackendData, uint64_t uOffset, void *pvBuf,
    605                          size_t cbToRead, size_t *pcbActuallyRead)
    606 {
    607     LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n",
    608                  pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead));
    609     PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
     604static int parallelsRead(void *pBackendData, uint64_t uOffset, size_t cbToRead,
     605                         PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
     606{
     607    LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n",
     608                 pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead));
    610609    int rc = VINF_SUCCESS;
     610    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
     611    uint64_t uSector;
     612    uint64_t uOffsetInFile;
     613    uint32_t iIndexInAllocationTable;
    611614
    612615    AssertPtr(pImage);
     
    615618
    616619    if (pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED)
    617         rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, uOffset, pvBuf, cbToRead);
    618     else
    619     {
    620         uint64_t uSector;
    621         uint32_t iIndexInAllocationTable;
    622 
    623         /* Calculate offset in the real file. */
    624         uSector = uOffset / 512;
    625 
    626         /* One chunk in the file is always one track big. */
    627         iIndexInAllocationTable = (uint32_t)(uSector / pImage->PCHSGeometry.cSectors);
    628         uSector = uSector % pImage->PCHSGeometry.cSectors;
    629 
    630         Assert(iIndexInAllocationTable < pImage->cAllocationBitmapEntries);
    631 
    632         cbToRead = RT_MIN(cbToRead, (pImage->PCHSGeometry.cSectors - uSector)*512);
    633 
    634         LogFlowFunc(("AllocationBitmap[%u]=%u uSector=%u cbToRead=%zu cAllocationBitmapEntries=%u\n",
    635                      iIndexInAllocationTable, pImage->pAllocationBitmap[iIndexInAllocationTable],
    636                      uSector, cbToRead, pImage->cAllocationBitmapEntries));
    637 
    638         if (pImage->pAllocationBitmap[iIndexInAllocationTable] == 0)
    639             rc = VERR_VD_BLOCK_FREE;
    640         else
    641         {
    642             uint64_t uOffsetInFile = ((uint64_t)pImage->pAllocationBitmap[iIndexInAllocationTable] + uSector) * 512;
    643 
    644             LogFlowFunc(("uOffsetInFile=%llu\n", uOffsetInFile));
    645             rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, uOffsetInFile,
    646                                        pvBuf, cbToRead);
    647         }
    648     }
    649 
    650     if (   (   RT_SUCCESS(rc)
    651             || rc == VERR_VD_BLOCK_FREE)
    652         && pcbActuallyRead)
    653         *pcbActuallyRead = cbToRead;
    654 
    655     LogFlowFunc(("returns %Rrc\n", rc));
    656     return rc;
    657 }
    658 
    659 /** @copydoc VBOXHDDBACKEND::pfnWrite */
    660 static int parallelsWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf,
    661                           size_t cbToWrite, size_t *pcbWriteProcess,
    662                           size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite)
    663 {
    664     LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p\n",
    665                  pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess));
    666     PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    667     int rc = VINF_SUCCESS;
    668 
    669     AssertPtr(pImage);
    670     Assert(uOffset % 512 == 0);
    671     Assert(cbToWrite % 512 == 0);
    672 
    673     if (pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED)
    674         rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, uOffset,
    675                                     pvBuf, cbToWrite);
    676     else
    677     {
    678         uint64_t uSector;
    679         uint64_t uOffsetInFile;
    680         uint32_t iIndexInAllocationTable;
    681 
     620        rc = vdIfIoIntFileReadUser(pImage->pIfIo, pImage->pStorage, uOffset,
     621                                   pIoCtx, cbToRead);
     622    else
     623    {
    682624        /* Calculate offset in the real file. */
    683625        uSector = uOffset / 512;
     
    686628        uSector = uSector % pImage->PCHSGeometry.cSectors;
    687629
    688         Assert(iIndexInAllocationTable < pImage->cAllocationBitmapEntries);
    689 
    690         cbToWrite = RT_MIN(cbToWrite, (pImage->PCHSGeometry.cSectors - uSector)*512);
    691 
    692         LogFlowFunc(("AllocationBitmap[%u]=%u uSector=%u cbToWrite=%zu cAllocationBitmapEntries=%u\n",
    693                      iIndexInAllocationTable, pImage->pAllocationBitmap[iIndexInAllocationTable],
    694                      uSector, cbToWrite, pImage->cAllocationBitmapEntries));
     630        cbToRead = RT_MIN(cbToRead, (pImage->PCHSGeometry.cSectors - uSector)*512);
    695631
    696632        if (pImage->pAllocationBitmap[iIndexInAllocationTable] == 0)
    697         {
    698             if (   cbToWrite == pImage->PCHSGeometry.cSectors * 512
    699                 && !(fWrite & VD_WRITE_NO_ALLOC))
    700             {
    701                 /* Stay on the safe side. Do not run the risk of confusing the higher
    702                  * level, as that can be pretty lethal to image consistency. */
    703                 *pcbPreRead = 0;
    704                 *pcbPostRead = 0;
    705 
    706                 /* Allocate new chunk in the file. */
    707                 AssertMsg(pImage->cbFileCurrent % 512 == 0, ("File size is not a multiple of 512\n"));
    708                 pImage->pAllocationBitmap[iIndexInAllocationTable] = (uint32_t)(pImage->cbFileCurrent / 512);
    709                 pImage->cbFileCurrent += pImage->PCHSGeometry.cSectors * 512;
    710                 pImage->fAllocationBitmapChanged = true;
    711 
    712                 uOffsetInFile = (uint64_t)pImage->pAllocationBitmap[iIndexInAllocationTable] * 512;
    713 
    714                 LogFlowFunc(("uOffsetInFile=%llu\n", uOffsetInFile));
    715 
    716                 /*
    717                  * Write the new block at the current end of the file.
    718                  */
    719                 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage,
    720                                             uOffsetInFile, pvBuf, cbToWrite);
    721             }
    722             else
    723             {
    724                 /* Trying to do a partial write to an unallocated cluster. Don't do
    725                  * anything except letting the upper layer know what to do. */
    726                 *pcbPreRead  = uSector * 512;
    727                 *pcbPostRead = (pImage->PCHSGeometry.cSectors * 512) - cbToWrite - *pcbPreRead;
    728                 rc = VERR_VD_BLOCK_FREE;
    729             }
    730         }
    731         else
    732         {
    733             uOffsetInFile = ((uint64_t)pImage->pAllocationBitmap[iIndexInAllocationTable] + uSector) * 512;
    734 
    735             LogFlowFunc(("uOffsetInFile=%llu\n", uOffsetInFile));
    736             rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, uOffsetInFile,
    737                                         pvBuf, cbToWrite);
    738         }
    739     }
    740 
    741     if (pcbWriteProcess)
    742         *pcbWriteProcess = cbToWrite;
    743 
    744 out:
    745     LogFlowFunc(("returns %Rrc\n", rc));
    746     return rc;
    747 }
    748 
    749 /** @copydoc VBOXHDDBACKEND::pfnFlush */
    750 static int parallelsFlush(void *pBackendData)
    751 {
    752     LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    753     PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    754     int rc;
    755 
    756     AssertPtr(pImage);
    757 
    758     rc = parallelsFlushImage(pImage);
    759 
    760     LogFlowFunc(("returns %Rrc\n", rc));
    761     return rc;
    762 }
    763 
    764 /** @copydoc VBOXHDDBACKEND::pfnGetVersion */
    765 static unsigned parallelsGetVersion(void *pBackendData)
    766 {
    767     LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    768     PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    769 
    770     AssertPtr(pImage);
    771 
    772     if (pImage)
    773         return PARALLELS_DISK_VERSION;
    774     else
    775         return 0;
    776 }
    777 
    778 /** @copydoc VBOXHDDBACKEND::pfnGetSize */
    779 static uint64_t parallelsGetSize(void *pBackendData)
    780 {
    781     LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    782     PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    783     uint64_t cb = 0;
    784 
    785     AssertPtr(pImage);
    786 
    787     if (pImage && pImage->pStorage)
    788         cb = pImage->cbSize;
    789 
    790     LogFlowFunc(("returns %llu\n", cb));
    791     return cb;
    792 }
    793 
    794 /** @copydoc VBOXHDDBACKEND::pfnGetFileSize */
    795 static uint64_t parallelsGetFileSize(void *pBackendData)
    796 {
    797     LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    798     PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    799     uint64_t cb = 0;
    800 
    801     AssertPtr(pImage);
    802 
    803     if (pImage && pImage->pStorage)
    804         cb = pImage->cbFileCurrent;
    805 
    806     LogFlowFunc(("returns %lld\n", cb));
    807     return cb;
    808 }
    809 
    810 /** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */
    811 static int parallelsGetPCHSGeometry(void *pBackendData,
    812                                     PVDGEOMETRY pPCHSGeometry)
    813 {
    814     LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry));
    815     PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    816     int rc;
    817 
    818     AssertPtr(pImage);
    819 
    820     if (pImage)
    821     {
    822         if (pImage->PCHSGeometry.cCylinders)
    823         {
    824             *pPCHSGeometry = pImage->PCHSGeometry;
    825             rc = VINF_SUCCESS;
    826         }
    827         else
    828             rc = VERR_VD_GEOMETRY_NOT_SET;
    829     }
    830     else
    831         rc = VERR_VD_NOT_OPENED;
    832 
    833     LogFlowFunc(("returns %Rrc (PCHS=%u/%u/%u)\n", rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
    834     return rc;
    835 }
    836 
    837 /** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */
    838 static int parallelsSetPCHSGeometry(void *pBackendData,
    839                                     PCVDGEOMETRY pPCHSGeometry)
    840 {
    841     LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
    842     PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    843     int rc;
    844 
    845     AssertPtr(pImage);
    846 
    847     if (pImage)
    848     {
    849         if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    850         {
    851             rc = VERR_VD_IMAGE_READ_ONLY;
    852             goto out;
    853         }
    854 
    855         pImage->PCHSGeometry = *pPCHSGeometry;
    856         rc = VINF_SUCCESS;
    857     }
    858     else
    859         rc = VERR_VD_NOT_OPENED;
    860 
    861 out:
    862     LogFlowFunc(("returns %Rrc\n", rc));
    863     return rc;
    864 }
    865 
    866 /** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */
    867 static int parallelsGetLCHSGeometry(void *pBackendData,
    868                                     PVDGEOMETRY pLCHSGeometry)
    869 {
    870     LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry));
    871     PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    872     int rc;
    873 
    874     AssertPtr(pImage);
    875 
    876     if (pImage)
    877     {
    878         if (pImage->LCHSGeometry.cCylinders)
    879         {
    880             *pLCHSGeometry = pImage->LCHSGeometry;
    881             rc = VINF_SUCCESS;
    882         }
    883         else
    884             rc = VERR_VD_GEOMETRY_NOT_SET;
    885     }
    886     else
    887         rc = VERR_VD_NOT_OPENED;
    888 
    889     LogFlowFunc(("returns %Rrc (LCHS=%u/%u/%u)\n", rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
    890     return rc;
    891 }
    892 
    893 /** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */
    894 static int parallelsSetLCHSGeometry(void *pBackendData,
    895                                     PCVDGEOMETRY pLCHSGeometry)
    896 {
    897     LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
    898     PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    899     int rc;
    900 
    901     AssertPtr(pImage);
    902 
    903     if (pImage)
    904     {
    905         if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    906         {
    907             rc = VERR_VD_IMAGE_READ_ONLY;
    908             goto out;
    909         }
    910 
    911         pImage->LCHSGeometry = *pLCHSGeometry;
    912         rc = VINF_SUCCESS;
    913     }
    914     else
    915         rc = VERR_VD_NOT_OPENED;
    916 
    917 out:
    918     LogFlowFunc(("returns %Rrc\n", rc));
    919     return rc;
    920 }
    921 
    922 /** @copydoc VBOXHDDBACKEND::pfnGetImageFlags */
    923 static unsigned parallelsGetImageFlags(void *pBackendData)
    924 {
    925     LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    926     PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    927     unsigned uImageFlags;
    928 
    929     AssertPtr(pImage);
    930 
    931     if (pImage)
    932         uImageFlags = pImage->uImageFlags;
    933     else
    934         uImageFlags = 0;
    935 
    936     LogFlowFunc(("returns %#x\n", uImageFlags));
    937     return uImageFlags;
    938 }
    939 
    940 /** @copydoc VBOXHDDBACKEND::pfnGetOpenFlags */
    941 static unsigned parallelsGetOpenFlags(void *pBackendData)
    942 {
    943     LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    944     PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    945     unsigned uOpenFlags;
    946 
    947     AssertPtr(pImage);
    948 
    949     if (pImage)
    950         uOpenFlags = pImage->uOpenFlags;
    951     else
    952         uOpenFlags = 0;
    953 
    954     LogFlowFunc(("returns %#x\n", uOpenFlags));
    955     return uOpenFlags;
    956 }
    957 
    958 /** @copydoc VBOXHDDBACKEND::pfnSetOpenFlags */
    959 static int parallelsSetOpenFlags(void *pBackendData, unsigned uOpenFlags)
    960 {
    961     LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags));
    962     PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    963     int rc;
    964 
    965     /* Image must be opened and the new flags must be valid. */
    966     if (!pImage || (uOpenFlags & ~(  VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO
    967                                    | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE
    968                                    | VD_OPEN_FLAGS_SEQUENTIAL | VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS)))
    969     {
    970         rc = VERR_INVALID_PARAMETER;
    971         goto out;
    972     }
    973 
    974     /* Implement this operation via reopening the image. */
    975     parallelsFreeImage(pImage, false);
    976     rc = parallelsOpenImage(pImage, uOpenFlags);
    977 
    978 out:
    979     LogFlowFunc(("returns %Rrc\n", rc));
    980     return rc;
    981 }
    982 
    983 /** @copydoc VBOXHDDBACKEND::pfnGetComment */
    984 static int parallelsGetComment(void *pBackendData, char *pszComment,
    985                                size_t cbComment)
    986 {
    987     LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment));
    988     PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    989     int rc;
    990 
    991     AssertPtr(pImage);
    992 
    993     if (pImage)
    994         rc = VERR_NOT_SUPPORTED;
    995     else
    996         rc = VERR_VD_NOT_OPENED;
    997 
    998     LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment));
    999     return rc;
    1000 }
    1001 
    1002 /** @copydoc VBOXHDDBACKEND::pfnSetComment */
    1003 static int parallelsSetComment(void *pBackendData, const char *pszComment)
    1004 {
    1005     LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment));
    1006     PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    1007     int rc;
    1008 
    1009     AssertPtr(pImage);
    1010 
    1011     if (pImage)
    1012     {
    1013         if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    1014             rc = VERR_VD_IMAGE_READ_ONLY;
    1015         else
    1016             rc = VERR_NOT_SUPPORTED;
    1017     }
    1018     else
    1019         rc = VERR_VD_NOT_OPENED;
    1020 
    1021     LogFlowFunc(("returns %Rrc\n", rc));
    1022     return rc;
    1023 }
    1024 
    1025 /** @copydoc VBOXHDDBACKEND::pfnGetUuid */
    1026 static int parallelsGetUuid(void *pBackendData, PRTUUID pUuid)
    1027 {
    1028     LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
    1029     PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    1030     int rc;
    1031 
    1032     AssertPtr(pImage);
    1033 
    1034     if (pImage)
    1035         rc = VERR_NOT_SUPPORTED;
    1036     else
    1037         rc = VERR_VD_NOT_OPENED;
    1038 
    1039     LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
    1040     return rc;
    1041 }
    1042 
    1043 /** @copydoc VBOXHDDBACKEND::pfnSetUuid */
    1044 static int parallelsSetUuid(void *pBackendData, PCRTUUID pUuid)
    1045 {
    1046     LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
    1047     PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    1048     int rc;
    1049 
    1050     AssertPtr(pImage);
    1051 
    1052     if (pImage)
    1053     {
    1054         if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    1055             rc = VERR_NOT_SUPPORTED;
    1056         else
    1057             rc = VERR_VD_IMAGE_READ_ONLY;
    1058     }
    1059     else
    1060         rc = VERR_VD_NOT_OPENED;
    1061 
    1062     LogFlowFunc(("returns %Rrc\n", rc));
    1063     return rc;
    1064 }
    1065 
    1066 /** @copydoc VBOXHDDBACKEND::pfnGetModificationUuid */
    1067 static int parallelsGetModificationUuid(void *pBackendData, PRTUUID pUuid)
    1068 {
    1069     LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
    1070     PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    1071     int rc;
    1072 
    1073     AssertPtr(pImage);
    1074 
    1075     if (pImage)
    1076         rc = VERR_NOT_SUPPORTED;
    1077     else
    1078         rc = VERR_VD_NOT_OPENED;
    1079 
    1080     LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
    1081     return rc;
    1082 }
    1083 
    1084 /** @copydoc VBOXHDDBACKEND::pfnSetModificationUuid */
    1085 static int parallelsSetModificationUuid(void *pBackendData, PCRTUUID pUuid)
    1086 {
    1087     LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
    1088     PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    1089     int rc;
    1090 
    1091     AssertPtr(pImage);
    1092 
    1093     if (pImage)
    1094     {
    1095         if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    1096             rc = VERR_NOT_SUPPORTED;
    1097         else
    1098             rc = VERR_VD_IMAGE_READ_ONLY;
    1099     }
    1100     else
    1101         rc = VERR_VD_NOT_OPENED;
    1102 
    1103     LogFlowFunc(("returns %Rrc\n", rc));
    1104     return rc;
    1105 }
    1106 
    1107 /** @copydoc VBOXHDDBACKEND::pfnGetParentUuid */
    1108 static int parallelsGetParentUuid(void *pBackendData, PRTUUID pUuid)
    1109 {
    1110     LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
    1111     PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    1112     int rc;
    1113 
    1114     AssertPtr(pImage);
    1115 
    1116     if (pImage)
    1117         rc = VERR_NOT_SUPPORTED;
    1118     else
    1119         rc = VERR_VD_NOT_OPENED;
    1120 
    1121     LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
    1122     return rc;
    1123 }
    1124 
    1125 /** @copydoc VBOXHDDBACKEND::pfnSetParentUuid */
    1126 static int parallelsSetParentUuid(void *pBackendData, PCRTUUID pUuid)
    1127 {
    1128     LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
    1129     PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    1130     int rc;
    1131 
    1132     AssertPtr(pImage);
    1133 
    1134     if (pImage)
    1135     {
    1136         if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    1137             rc = VERR_NOT_SUPPORTED;
    1138         else
    1139             rc = VERR_VD_IMAGE_READ_ONLY;
    1140     }
    1141     else
    1142         rc = VERR_VD_NOT_OPENED;
    1143 
    1144     LogFlowFunc(("returns %Rrc\n", rc));
    1145     return rc;
    1146 }
    1147 
    1148 /** @copydoc VBOXHDDBACKEND::pfnGetParentModificationUuid */
    1149 static int parallelsGetParentModificationUuid(void *pBackendData, PRTUUID pUuid)
    1150 {
    1151     LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
    1152     PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    1153     int rc;
    1154 
    1155     AssertPtr(pImage);
    1156 
    1157     if (pImage)
    1158         rc = VERR_NOT_SUPPORTED;
    1159     else
    1160         rc = VERR_VD_NOT_OPENED;
    1161 
    1162     LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
    1163     return rc;
    1164 }
    1165 
    1166 /** @copydoc VBOXHDDBACKEND::pfnSetParentModificationUuid */
    1167 static int parallelsSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid)
    1168 {
    1169     LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
    1170     PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    1171     int rc;
    1172 
    1173     AssertPtr(pImage);
    1174 
    1175     if (pImage)
    1176     {
    1177         if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    1178             rc = VERR_NOT_SUPPORTED;
    1179         else
    1180             rc = VERR_VD_IMAGE_READ_ONLY;
    1181     }
    1182     else
    1183         rc = VERR_VD_NOT_OPENED;
    1184 
    1185     LogFlowFunc(("returns %Rrc\n", rc));
    1186     return rc;
    1187 }
    1188 
    1189 /** @copydoc VBOXHDDBACKEND::pfnDump */
    1190 static void parallelsDump(void *pBackendData)
    1191 {
    1192     PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    1193 
    1194     AssertPtr(pImage);
    1195     if (pImage)
    1196     {
    1197         vdIfErrorMessage(pImage->pIfError, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u\n",
    1198                          pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors,
    1199                          pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors);
    1200     }
    1201 }
    1202 
    1203 /** @copydoc VBOXHDDBACKEND::pfnAsyncRead */
    1204 static int parallelsAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbToRead,
    1205                               PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
    1206 {
    1207     LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n",
    1208                  pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead));
    1209     int rc = VINF_SUCCESS;
    1210     PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    1211     uint64_t uSector;
    1212     uint64_t uOffsetInFile;
    1213     uint32_t iIndexInAllocationTable;
    1214 
    1215     AssertPtr(pImage);
    1216     Assert(uOffset % 512 == 0);
    1217     Assert(cbToRead % 512 == 0);
    1218 
    1219     if (pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED)
    1220         rc = vdIfIoIntFileReadUser(pImage->pIfIo, pImage->pStorage, uOffset,
    1221                                    pIoCtx, cbToRead);
    1222     else
    1223     {
    1224         /* Calculate offset in the real file. */
    1225         uSector = uOffset / 512;
    1226         /* One chunk in the file is always one track big. */
    1227         iIndexInAllocationTable = (uint32_t)(uSector / pImage->PCHSGeometry.cSectors);
    1228         uSector = uSector % pImage->PCHSGeometry.cSectors;
    1229 
    1230         cbToRead = RT_MIN(cbToRead, (pImage->PCHSGeometry.cSectors - uSector)*512);
    1231 
    1232         if (pImage->pAllocationBitmap[iIndexInAllocationTable] == 0)
    1233         {
    1234633            rc = VERR_VD_BLOCK_FREE;
    1235         }
    1236634        else
    1237635        {
     
    1248646}
    1249647
    1250 /** @copydoc VBOXHDDBACKEND::pfnAsyncWrite */
    1251 static int parallelsAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite,
    1252                                PVDIOCTX pIoCtx,
    1253                                size_t *pcbWriteProcess, size_t *pcbPreRead,
    1254                                size_t *pcbPostRead, unsigned fWrite)
     648/** @copydoc VBOXHDDBACKEND::pfnWrite */
     649static int parallelsWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite,
     650                          PVDIOCTX pIoCtx, size_t *pcbWriteProcess, size_t *pcbPreRead,
     651                          size_t *pcbPostRead, unsigned fWrite)
    1255652{
    1256653    LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p\n",
     
    1333730}
    1334731
    1335 /** @copydoc VBOXHDDBACKEND::pfnAsyncFlush */
    1336 static int parallelsAsyncFlush(void *pBackendData, PVDIOCTX pIoCtx)
     732/** @copydoc VBOXHDDBACKEND::pfnFlush */
     733static int parallelsFlush(void *pBackendData, PVDIOCTX pIoCtx)
    1337734{
    1338735    int rc = VINF_SUCCESS;
     
    1347744    return rc;
    1348745}
     746
     747/** @copydoc VBOXHDDBACKEND::pfnGetVersion */
     748static unsigned parallelsGetVersion(void *pBackendData)
     749{
     750    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     751    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
     752
     753    AssertPtr(pImage);
     754
     755    if (pImage)
     756        return PARALLELS_DISK_VERSION;
     757    else
     758        return 0;
     759}
     760
     761/** @copydoc VBOXHDDBACKEND::pfnGetSize */
     762static uint64_t parallelsGetSize(void *pBackendData)
     763{
     764    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     765    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
     766    uint64_t cb = 0;
     767
     768    AssertPtr(pImage);
     769
     770    if (pImage && pImage->pStorage)
     771        cb = pImage->cbSize;
     772
     773    LogFlowFunc(("returns %llu\n", cb));
     774    return cb;
     775}
     776
     777/** @copydoc VBOXHDDBACKEND::pfnGetFileSize */
     778static uint64_t parallelsGetFileSize(void *pBackendData)
     779{
     780    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     781    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
     782    uint64_t cb = 0;
     783
     784    AssertPtr(pImage);
     785
     786    if (pImage && pImage->pStorage)
     787        cb = pImage->cbFileCurrent;
     788
     789    LogFlowFunc(("returns %lld\n", cb));
     790    return cb;
     791}
     792
     793/** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */
     794static int parallelsGetPCHSGeometry(void *pBackendData,
     795                                    PVDGEOMETRY pPCHSGeometry)
     796{
     797    LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry));
     798    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
     799    int rc;
     800
     801    AssertPtr(pImage);
     802
     803    if (pImage)
     804    {
     805        if (pImage->PCHSGeometry.cCylinders)
     806        {
     807            *pPCHSGeometry = pImage->PCHSGeometry;
     808            rc = VINF_SUCCESS;
     809        }
     810        else
     811            rc = VERR_VD_GEOMETRY_NOT_SET;
     812    }
     813    else
     814        rc = VERR_VD_NOT_OPENED;
     815
     816    LogFlowFunc(("returns %Rrc (PCHS=%u/%u/%u)\n", rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
     817    return rc;
     818}
     819
     820/** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */
     821static int parallelsSetPCHSGeometry(void *pBackendData,
     822                                    PCVDGEOMETRY pPCHSGeometry)
     823{
     824    LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
     825    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
     826    int rc;
     827
     828    AssertPtr(pImage);
     829
     830    if (pImage)
     831    {
     832        if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     833        {
     834            rc = VERR_VD_IMAGE_READ_ONLY;
     835            goto out;
     836        }
     837
     838        pImage->PCHSGeometry = *pPCHSGeometry;
     839        rc = VINF_SUCCESS;
     840    }
     841    else
     842        rc = VERR_VD_NOT_OPENED;
     843
     844out:
     845    LogFlowFunc(("returns %Rrc\n", rc));
     846    return rc;
     847}
     848
     849/** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */
     850static int parallelsGetLCHSGeometry(void *pBackendData,
     851                                    PVDGEOMETRY pLCHSGeometry)
     852{
     853    LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry));
     854    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
     855    int rc;
     856
     857    AssertPtr(pImage);
     858
     859    if (pImage)
     860    {
     861        if (pImage->LCHSGeometry.cCylinders)
     862        {
     863            *pLCHSGeometry = pImage->LCHSGeometry;
     864            rc = VINF_SUCCESS;
     865        }
     866        else
     867            rc = VERR_VD_GEOMETRY_NOT_SET;
     868    }
     869    else
     870        rc = VERR_VD_NOT_OPENED;
     871
     872    LogFlowFunc(("returns %Rrc (LCHS=%u/%u/%u)\n", rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
     873    return rc;
     874}
     875
     876/** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */
     877static int parallelsSetLCHSGeometry(void *pBackendData,
     878                                    PCVDGEOMETRY pLCHSGeometry)
     879{
     880    LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
     881    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
     882    int rc;
     883
     884    AssertPtr(pImage);
     885
     886    if (pImage)
     887    {
     888        if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     889        {
     890            rc = VERR_VD_IMAGE_READ_ONLY;
     891            goto out;
     892        }
     893
     894        pImage->LCHSGeometry = *pLCHSGeometry;
     895        rc = VINF_SUCCESS;
     896    }
     897    else
     898        rc = VERR_VD_NOT_OPENED;
     899
     900out:
     901    LogFlowFunc(("returns %Rrc\n", rc));
     902    return rc;
     903}
     904
     905/** @copydoc VBOXHDDBACKEND::pfnGetImageFlags */
     906static unsigned parallelsGetImageFlags(void *pBackendData)
     907{
     908    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     909    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
     910    unsigned uImageFlags;
     911
     912    AssertPtr(pImage);
     913
     914    if (pImage)
     915        uImageFlags = pImage->uImageFlags;
     916    else
     917        uImageFlags = 0;
     918
     919    LogFlowFunc(("returns %#x\n", uImageFlags));
     920    return uImageFlags;
     921}
     922
     923/** @copydoc VBOXHDDBACKEND::pfnGetOpenFlags */
     924static unsigned parallelsGetOpenFlags(void *pBackendData)
     925{
     926    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     927    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
     928    unsigned uOpenFlags;
     929
     930    AssertPtr(pImage);
     931
     932    if (pImage)
     933        uOpenFlags = pImage->uOpenFlags;
     934    else
     935        uOpenFlags = 0;
     936
     937    LogFlowFunc(("returns %#x\n", uOpenFlags));
     938    return uOpenFlags;
     939}
     940
     941/** @copydoc VBOXHDDBACKEND::pfnSetOpenFlags */
     942static int parallelsSetOpenFlags(void *pBackendData, unsigned uOpenFlags)
     943{
     944    LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags));
     945    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
     946    int rc;
     947
     948    /* Image must be opened and the new flags must be valid. */
     949    if (!pImage || (uOpenFlags & ~(  VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO
     950                                   | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE
     951                                   | VD_OPEN_FLAGS_SEQUENTIAL | VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS)))
     952    {
     953        rc = VERR_INVALID_PARAMETER;
     954        goto out;
     955    }
     956
     957    /* Implement this operation via reopening the image. */
     958    parallelsFreeImage(pImage, false);
     959    rc = parallelsOpenImage(pImage, uOpenFlags);
     960
     961out:
     962    LogFlowFunc(("returns %Rrc\n", rc));
     963    return rc;
     964}
     965
     966/** @copydoc VBOXHDDBACKEND::pfnGetComment */
     967static int parallelsGetComment(void *pBackendData, char *pszComment,
     968                               size_t cbComment)
     969{
     970    LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment));
     971    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
     972    int rc;
     973
     974    AssertPtr(pImage);
     975
     976    if (pImage)
     977        rc = VERR_NOT_SUPPORTED;
     978    else
     979        rc = VERR_VD_NOT_OPENED;
     980
     981    LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment));
     982    return rc;
     983}
     984
     985/** @copydoc VBOXHDDBACKEND::pfnSetComment */
     986static int parallelsSetComment(void *pBackendData, const char *pszComment)
     987{
     988    LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment));
     989    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
     990    int rc;
     991
     992    AssertPtr(pImage);
     993
     994    if (pImage)
     995    {
     996        if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     997            rc = VERR_VD_IMAGE_READ_ONLY;
     998        else
     999            rc = VERR_NOT_SUPPORTED;
     1000    }
     1001    else
     1002        rc = VERR_VD_NOT_OPENED;
     1003
     1004    LogFlowFunc(("returns %Rrc\n", rc));
     1005    return rc;
     1006}
     1007
     1008/** @copydoc VBOXHDDBACKEND::pfnGetUuid */
     1009static int parallelsGetUuid(void *pBackendData, PRTUUID pUuid)
     1010{
     1011    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
     1012    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
     1013    int rc;
     1014
     1015    AssertPtr(pImage);
     1016
     1017    if (pImage)
     1018        rc = VERR_NOT_SUPPORTED;
     1019    else
     1020        rc = VERR_VD_NOT_OPENED;
     1021
     1022    LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
     1023    return rc;
     1024}
     1025
     1026/** @copydoc VBOXHDDBACKEND::pfnSetUuid */
     1027static int parallelsSetUuid(void *pBackendData, PCRTUUID pUuid)
     1028{
     1029    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
     1030    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
     1031    int rc;
     1032
     1033    AssertPtr(pImage);
     1034
     1035    if (pImage)
     1036    {
     1037        if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     1038            rc = VERR_NOT_SUPPORTED;
     1039        else
     1040            rc = VERR_VD_IMAGE_READ_ONLY;
     1041    }
     1042    else
     1043        rc = VERR_VD_NOT_OPENED;
     1044
     1045    LogFlowFunc(("returns %Rrc\n", rc));
     1046    return rc;
     1047}
     1048
     1049/** @copydoc VBOXHDDBACKEND::pfnGetModificationUuid */
     1050static int parallelsGetModificationUuid(void *pBackendData, PRTUUID pUuid)
     1051{
     1052    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
     1053    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
     1054    int rc;
     1055
     1056    AssertPtr(pImage);
     1057
     1058    if (pImage)
     1059        rc = VERR_NOT_SUPPORTED;
     1060    else
     1061        rc = VERR_VD_NOT_OPENED;
     1062
     1063    LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
     1064    return rc;
     1065}
     1066
     1067/** @copydoc VBOXHDDBACKEND::pfnSetModificationUuid */
     1068static int parallelsSetModificationUuid(void *pBackendData, PCRTUUID pUuid)
     1069{
     1070    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
     1071    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
     1072    int rc;
     1073
     1074    AssertPtr(pImage);
     1075
     1076    if (pImage)
     1077    {
     1078        if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     1079            rc = VERR_NOT_SUPPORTED;
     1080        else
     1081            rc = VERR_VD_IMAGE_READ_ONLY;
     1082    }
     1083    else
     1084        rc = VERR_VD_NOT_OPENED;
     1085
     1086    LogFlowFunc(("returns %Rrc\n", rc));
     1087    return rc;
     1088}
     1089
     1090/** @copydoc VBOXHDDBACKEND::pfnGetParentUuid */
     1091static int parallelsGetParentUuid(void *pBackendData, PRTUUID pUuid)
     1092{
     1093    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
     1094    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
     1095    int rc;
     1096
     1097    AssertPtr(pImage);
     1098
     1099    if (pImage)
     1100        rc = VERR_NOT_SUPPORTED;
     1101    else
     1102        rc = VERR_VD_NOT_OPENED;
     1103
     1104    LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
     1105    return rc;
     1106}
     1107
     1108/** @copydoc VBOXHDDBACKEND::pfnSetParentUuid */
     1109static int parallelsSetParentUuid(void *pBackendData, PCRTUUID pUuid)
     1110{
     1111    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
     1112    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
     1113    int rc;
     1114
     1115    AssertPtr(pImage);
     1116
     1117    if (pImage)
     1118    {
     1119        if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     1120            rc = VERR_NOT_SUPPORTED;
     1121        else
     1122            rc = VERR_VD_IMAGE_READ_ONLY;
     1123    }
     1124    else
     1125        rc = VERR_VD_NOT_OPENED;
     1126
     1127    LogFlowFunc(("returns %Rrc\n", rc));
     1128    return rc;
     1129}
     1130
     1131/** @copydoc VBOXHDDBACKEND::pfnGetParentModificationUuid */
     1132static int parallelsGetParentModificationUuid(void *pBackendData, PRTUUID pUuid)
     1133{
     1134    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
     1135    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
     1136    int rc;
     1137
     1138    AssertPtr(pImage);
     1139
     1140    if (pImage)
     1141        rc = VERR_NOT_SUPPORTED;
     1142    else
     1143        rc = VERR_VD_NOT_OPENED;
     1144
     1145    LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
     1146    return rc;
     1147}
     1148
     1149/** @copydoc VBOXHDDBACKEND::pfnSetParentModificationUuid */
     1150static int parallelsSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid)
     1151{
     1152    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
     1153    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
     1154    int rc;
     1155
     1156    AssertPtr(pImage);
     1157
     1158    if (pImage)
     1159    {
     1160        if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     1161            rc = VERR_NOT_SUPPORTED;
     1162        else
     1163            rc = VERR_VD_IMAGE_READ_ONLY;
     1164    }
     1165    else
     1166        rc = VERR_VD_NOT_OPENED;
     1167
     1168    LogFlowFunc(("returns %Rrc\n", rc));
     1169    return rc;
     1170}
     1171
     1172/** @copydoc VBOXHDDBACKEND::pfnDump */
     1173static void parallelsDump(void *pBackendData)
     1174{
     1175    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
     1176
     1177    AssertPtr(pImage);
     1178    if (pImage)
     1179    {
     1180        vdIfErrorMessage(pImage->pIfError, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u\n",
     1181                         pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors,
     1182                         pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors);
     1183    }
     1184}
     1185
    13491186
    13501187
     
    13791216    /* pfnFlush */
    13801217    parallelsFlush,
     1218    /* pfnDiscard */
     1219    NULL,
    13811220    /* pfnGetVersion */
    13821221    parallelsGetVersion,
     
    14311270    /* pfnSetParentFilename */
    14321271    NULL,
    1433     /* pfnAsyncRead */
    1434     parallelsAsyncRead,
    1435     /* pfnAsyncWrite */
    1436     parallelsAsyncWrite,
    1437     /* pfnAsyncFlush */
    1438     parallelsAsyncFlush,
    14391272    /* pfnComposeLocation */
    14401273    genericFileComposeLocation,
     
    14451278    /* pfnResize */
    14461279    NULL,
    1447     /* pfnDiscard */
    1448     NULL,
    1449     /* pfnAsyncDiscard */
    1450     NULL,
    14511280    /* pfnRepair */
    14521281    NULL
  • trunk/src/VBox/Storage/QCOW.cpp

    r44233 r44252  
    684684 * @returns VBox status code.
    685685 * @param   pImage    Image instance data.
    686  * @param   offL2Tbl  The offset of the L2 table in the image.
    687  * @param   ppL2Entry Where to store the L2 table on success.
    688  */
    689 static int qcowL2TblCacheFetch(PQCOWIMAGE pImage, uint64_t offL2Tbl, PQCOWL2CACHEENTRY *ppL2Entry)
    690 {
    691     int rc = VINF_SUCCESS;
    692 
    693     LogFlowFunc(("pImage=%#p offL2Tbl=%llu ppL2Entry=%#p\n", pImage, offL2Tbl, ppL2Entry));
    694 
    695     /* Try to fetch the L2 table from the cache first. */
    696     PQCOWL2CACHEENTRY pL2Entry = qcowL2TblCacheRetain(pImage, offL2Tbl);
    697     if (!pL2Entry)
    698     {
    699         LogFlowFunc(("Reading L2 table from image\n"));
    700         pL2Entry = qcowL2TblCacheEntryAlloc(pImage);
    701 
    702         if (pL2Entry)
    703         {
    704             /* Read from the image. */
    705             pL2Entry->offL2Tbl = offL2Tbl;
    706             rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, offL2Tbl,
    707                                        pL2Entry->paL2Tbl, pImage->cbL2Table);
    708             if (RT_SUCCESS(rc))
    709             {
    710 #if defined(RT_LITTLE_ENDIAN)
    711                 qcowTableConvertToHostEndianess(pL2Entry->paL2Tbl, pImage->cL2TableEntries);
    712 #endif
    713                 qcowL2TblCacheEntryInsert(pImage, pL2Entry);
    714             }
    715             else
    716             {
    717                 qcowL2TblCacheEntryRelease(pL2Entry);
    718                 qcowL2TblCacheEntryFree(pImage, pL2Entry);
    719             }
    720         }
    721         else
    722             rc = VERR_NO_MEMORY;
    723     }
    724 
    725     if (RT_SUCCESS(rc))
    726         *ppL2Entry = pL2Entry;
    727 
    728     LogFlowFunc(("returns rc=%Rrc\n", rc));
    729     return rc;
    730 }
    731 
    732 /**
    733  * Fetches the L2 from the given offset trying the LRU cache first and
    734  * reading it from the image after a cache miss - version for async I/O.
    735  *
    736  * @returns VBox status code.
    737  * @param   pImage    Image instance data.
    738686 * @param   pIoCtx    The I/O context.
    739687 * @param   offL2Tbl  The offset of the L2 table in the image.
    740688 * @param   ppL2Entry Where to store the L2 table on success.
    741689 */
    742 static int qcowL2TblCacheFetchAsync(PQCOWIMAGE pImage, PVDIOCTX pIoCtx,
    743                                     uint64_t offL2Tbl, PQCOWL2CACHEENTRY *ppL2Entry)
     690static int qcowL2TblCacheFetch(PQCOWIMAGE pImage, PVDIOCTX pIoCtx, uint64_t offL2Tbl,
     691                               PQCOWL2CACHEENTRY *ppL2Entry)
    744692{
    745693    int rc = VINF_SUCCESS;
     
    876824 *          VERR_VD_BLOCK_FREE if the cluster is not yet allocated.
    877825 * @param   pImage        The image instance data.
    878  * @param   idxL1         The L1 index.
    879  * @param   idxL2         The L2 index.
    880  * @param   offCluster    Offset inside the cluster.
    881  * @param   poffImage     Where to store the image offset on success;
    882  */
    883 static int qcowConvertToImageOffset(PQCOWIMAGE pImage, uint32_t idxL1, uint32_t idxL2,
    884                                     uint32_t offCluster, uint64_t *poffImage)
    885 {
    886     int rc = VERR_VD_BLOCK_FREE;
    887     LogFlowFunc(("pImage=%#p idxL1=%u idxL2=%u offCluster=%u poffImage=%#p\n",
    888                  pImage, idxL1, idxL2, offCluster, poffImage));
    889 
    890     AssertReturn(idxL1 < pImage->cL1TableEntries, VERR_INVALID_PARAMETER);
    891     AssertReturn(idxL2 < pImage->cL2TableEntries, VERR_INVALID_PARAMETER);
    892 
    893     if (pImage->paL1Table[idxL1])
    894     {
    895         PQCOWL2CACHEENTRY pL2Entry;
    896 
    897         rc = qcowL2TblCacheFetch(pImage, pImage->paL1Table[idxL1], &pL2Entry);
    898         if (RT_SUCCESS(rc))
    899         {
    900             LogFlowFunc(("cluster start offset %llu\n", pL2Entry->paL2Tbl[idxL2]));
    901             /* Get real file offset. */
    902             if (pL2Entry->paL2Tbl[idxL2])
    903             {
    904                 uint64_t off = pL2Entry->paL2Tbl[idxL2];
    905 
    906                 /* Strip flags */
    907                 if (pImage->uVersion == 2)
    908                 {
    909                     if (RT_UNLIKELY(off & QCOW_V2_COMPRESSED_FLAG))
    910                         rc = VERR_NOT_SUPPORTED;
    911                     else
    912                         off &= ~(QCOW_V2_COMPRESSED_FLAG | QCOW_V2_COPIED_FLAG);
    913                 }
    914                 else
    915                 {
    916                     if (RT_UNLIKELY(off & QCOW_V1_COMPRESSED_FLAG))
    917                         rc = VERR_NOT_SUPPORTED;
    918                     else
    919                         off &= ~QCOW_V1_COMPRESSED_FLAG;
    920                 }
    921 
    922                 *poffImage = off + offCluster;
    923             }
    924             else
    925                 rc = VERR_VD_BLOCK_FREE;
    926 
    927             qcowL2TblCacheEntryRelease(pL2Entry);
    928         }
    929     }
    930 
    931     LogFlowFunc(("returns rc=%Rrc\n", rc));
    932     return rc;
    933 }
    934 
    935 /**
    936  * Returns the real image offset for a given cluster or an error if the cluster is not
    937  * yet allocated- version for async I/O.
    938  *
    939  * @returns VBox status code.
    940  *          VERR_VD_BLOCK_FREE if the cluster is not yet allocated.
    941  * @param   pImage        The image instance data.
    942826 * @param   pIoCtx        The I/O context.
    943827 * @param   idxL1         The L1 index.
     
    946830 * @param   poffImage     Where to store the image offset on success;
    947831 */
    948 static int qcowConvertToImageOffsetAsync(PQCOWIMAGE pImage, PVDIOCTX pIoCtx,
    949                                          uint32_t idxL1, uint32_t idxL2,
    950                                          uint32_t offCluster, uint64_t *poffImage)
     832static int qcowConvertToImageOffset(PQCOWIMAGE pImage, PVDIOCTX pIoCtx,
     833                                    uint32_t idxL1, uint32_t idxL2,
     834                                    uint32_t offCluster, uint64_t *poffImage)
    951835{
    952836    int rc = VERR_VD_BLOCK_FREE;
     
    959843        PQCOWL2CACHEENTRY pL2Entry;
    960844
    961         rc = qcowL2TblCacheFetchAsync(pImage, pIoCtx, pImage->paL1Table[idxL1],
    962                                      &pL2Entry);
     845        rc = qcowL2TblCacheFetch(pImage, pIoCtx, pImage->paL1Table[idxL1], &pL2Entry);
    963846        if (RT_SUCCESS(rc))
    964847        {
     
    17871670}
    17881671
    1789 /** @copydoc VBOXHDDBACKEND::pfnRead */
    1790 static int qcowRead(void *pBackendData, uint64_t uOffset, void *pvBuf,
    1791                    size_t cbToRead, size_t *pcbActuallyRead)
    1792 {
    1793     LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n",
    1794                  pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead));
     1672static int qcowRead(void *pBackendData, uint64_t uOffset, size_t cbToRead,
     1673                    PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
     1674{
     1675    LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n",
     1676                 pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead));
    17951677    PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
    17961678    uint32_t offCluster = 0;
     
    18041686    Assert(cbToRead % 512 == 0);
    18051687
     1688    if (!VALID_PTR(pIoCtx) || !cbToRead)
     1689    {
     1690        rc = VERR_INVALID_PARAMETER;
     1691        goto out;
     1692    }
     1693
    18061694    if (   uOffset + cbToRead > pImage->cbSize
    18071695        || cbToRead == 0)
     
    18121700
    18131701    qcowConvertLogicalOffset(pImage, uOffset, &idxL1, &idxL2, &offCluster);
    1814     LogFlowFunc(("idxL1=%u idxL2=%u offCluster=%u\n", idxL1, idxL2, offCluster));
    18151702
    18161703    /* Clip read size to remain in the cluster. */
     
    18181705
    18191706    /* Get offset in image. */
    1820     rc = qcowConvertToImageOffset(pImage, idxL1, idxL2, offCluster, &offFile);
    1821     if (RT_SUCCESS(rc))
    1822     {
    1823         LogFlowFunc(("offFile=%llu\n", offFile));
    1824         rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, offFile,
    1825                                    pvBuf, cbToRead);
    1826     }
    1827 
    1828     if (   (RT_SUCCESS(rc) || rc == VERR_VD_BLOCK_FREE)
    1829         && pcbActuallyRead)
    1830         *pcbActuallyRead = cbToRead;
    1831 
    1832 out:
    1833     LogFlowFunc(("returns %Rrc\n", rc));
    1834     return rc;
    1835 }
    1836 
    1837 /** @copydoc VBOXHDDBACKEND::pfnWrite */
    1838 static int qcowWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf,
    1839                     size_t cbToWrite, size_t *pcbWriteProcess,
    1840                     size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite)
    1841 {
    1842     LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n",
    1843                  pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));
    1844     PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
    1845     uint32_t offCluster = 0;
    1846     uint32_t idxL1      = 0;
    1847     uint32_t idxL2      = 0;
    1848     uint64_t offImage   = 0;
    1849     int rc;
    1850 
    1851     AssertPtr(pImage);
    1852     Assert(uOffset % 512 == 0);
    1853     Assert(cbToWrite % 512 == 0);
    1854 
    1855     if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    1856     {
    1857         rc = VERR_VD_IMAGE_READ_ONLY;
    1858         goto out;
    1859     }
    1860 
    1861     if (   uOffset + cbToWrite > pImage->cbSize
    1862         || cbToWrite == 0)
    1863     {
    1864         rc = VERR_INVALID_PARAMETER;
    1865         goto out;
    1866     }
    1867 
    1868     /* Convert offset to L1, L2 index and cluster offset. */
    1869     qcowConvertLogicalOffset(pImage, uOffset, &idxL1, &idxL2, &offCluster);
    1870 
    1871     /* Clip write size to remain in the cluster. */
    1872     cbToWrite = RT_MIN(cbToWrite, pImage->cbCluster - offCluster);
    1873     Assert(!(cbToWrite % 512));
    1874 
    1875     /* Get offset in image. */
    1876     rc = qcowConvertToImageOffset(pImage, idxL1, idxL2, offCluster, &offImage);
    1877     if (RT_SUCCESS(rc))
    1878         rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, offImage,
    1879                                     pvBuf, cbToWrite);
    1880     else if (rc == VERR_VD_BLOCK_FREE)
    1881     {
    1882         if (   cbToWrite == pImage->cbCluster
    1883             && !(fWrite & VD_WRITE_NO_ALLOC))
    1884         {
    1885             PQCOWL2CACHEENTRY pL2Entry = NULL;
    1886 
    1887             /* Full cluster write to previously unallocated cluster.
    1888              * Allocate cluster and write data. */
    1889             Assert(!offCluster);
    1890 
    1891             do
    1892             {
    1893                 uint64_t idxUpdateLe = 0;
    1894 
    1895                 /* Check if we have to allocate a new cluster for L2 tables. */
    1896                 if (!pImage->paL1Table[idxL1])
    1897                 {
    1898                     uint64_t offL2Tbl = qcowClusterAllocate(pImage, qcowByte2Cluster(pImage, pImage->cbL2Table));
    1899 
    1900                     pL2Entry = qcowL2TblCacheEntryAlloc(pImage);
    1901                     if (!pL2Entry)
    1902                     {
    1903                         rc = VERR_NO_MEMORY;
    1904                         break;
    1905                     }
    1906 
    1907                     pL2Entry->offL2Tbl = offL2Tbl;
    1908                     memset(pL2Entry->paL2Tbl, 0, pImage->cbL2Table);
    1909                     qcowL2TblCacheEntryInsert(pImage, pL2Entry);
    1910 
    1911                     /*
    1912                      * Write the L2 table first and link to the L1 table afterwards.
    1913                      * If something unexpected happens the worst case which can happen
    1914                      * is a leak of some clusters.
    1915                      */
    1916                     rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, offL2Tbl,
    1917                                                 pL2Entry->paL2Tbl, pImage->cbL2Table);
    1918                     if (RT_FAILURE(rc))
    1919                         break;
    1920 
    1921                     /* Write the L1 link now. */
    1922                     pImage->paL1Table[idxL1] = offL2Tbl;
    1923                     idxUpdateLe = RT_H2BE_U64(offL2Tbl);
    1924                     rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage,
    1925                                                 pImage->offL1Table + idxL1*sizeof(uint64_t),
    1926                                                 &idxUpdateLe, sizeof(uint64_t));
    1927                     if (RT_FAILURE(rc))
    1928                         break;
    1929                 }
    1930                 else
    1931                     rc = qcowL2TblCacheFetch(pImage, pImage->paL1Table[idxL1], &pL2Entry);
    1932 
    1933                 if (RT_SUCCESS(rc))
    1934                 {
    1935                     /* Allocate new cluster for the data. */
    1936                     uint64_t offData = qcowClusterAllocate(pImage, 1);
    1937 
    1938                     /* Write data. */
    1939                     rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage,
    1940                                                 offData, pvBuf, cbToWrite);
    1941                     if (RT_FAILURE(rc))
    1942                         break;
    1943 
    1944                     /* Link L2 table and update it. */
    1945                     pL2Entry->paL2Tbl[idxL2] = offData;
    1946                     idxUpdateLe = RT_H2BE_U64(offData);
    1947                     rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage,
    1948                                                 pImage->paL1Table[idxL1] + idxL2*sizeof(uint64_t),
    1949                                                 &idxUpdateLe, sizeof(uint64_t));
    1950                     qcowL2TblCacheEntryRelease(pL2Entry);
    1951                 }
    1952 
    1953             } while (0);
    1954 
    1955             *pcbPreRead = 0;
    1956             *pcbPostRead = 0;
    1957         }
    1958         else
    1959         {
    1960             /* Trying to do a partial write to an unallocated cluster. Don't do
    1961              * anything except letting the upper layer know what to do. */
    1962             *pcbPreRead = offCluster;
    1963             *pcbPostRead = pImage->cbCluster - cbToWrite - *pcbPreRead;
    1964         }
    1965     }
    1966 
    1967     if (pcbWriteProcess)
    1968         *pcbWriteProcess = cbToWrite;
    1969 
    1970 out:
    1971     LogFlowFunc(("returns %Rrc\n", rc));
    1972     return rc;
    1973 }
    1974 
    1975 /** @copydoc VBOXHDDBACKEND::pfnFlush */
    1976 static int qcowFlush(void *pBackendData)
    1977 {
    1978     LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    1979     PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
    1980     int rc;
    1981 
    1982     rc = qcowFlushImage(pImage);
    1983     LogFlowFunc(("returns %Rrc\n", rc));
    1984     return rc;
    1985 }
    1986 
    1987 /** @copydoc VBOXHDDBACKEND::pfnGetVersion */
    1988 static unsigned qcowGetVersion(void *pBackendData)
    1989 {
    1990     LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    1991     PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
    1992 
    1993     AssertPtr(pImage);
    1994 
    1995     if (pImage)
    1996         return pImage->uVersion;
    1997     else
    1998         return 0;
    1999 }
    2000 
    2001 /** @copydoc VBOXHDDBACKEND::pfnGetSize */
    2002 static uint64_t qcowGetSize(void *pBackendData)
    2003 {
    2004     LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    2005     PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
    2006     uint64_t cb = 0;
    2007 
    2008     AssertPtr(pImage);
    2009 
    2010     if (pImage && pImage->pStorage)
    2011         cb = pImage->cbSize;
    2012 
    2013     LogFlowFunc(("returns %llu\n", cb));
    2014     return cb;
    2015 }
    2016 
    2017 /** @copydoc VBOXHDDBACKEND::pfnGetFileSize */
    2018 static uint64_t qcowGetFileSize(void *pBackendData)
    2019 {
    2020     LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    2021     PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
    2022     uint64_t cb = 0;
    2023 
    2024     AssertPtr(pImage);
    2025 
    2026     if (pImage)
    2027     {
    2028         uint64_t cbFile;
    2029         if (pImage->pStorage)
    2030         {
    2031             int rc = vdIfIoIntFileGetSize(pImage->pIfIo, pImage->pStorage, &cbFile);
    2032             if (RT_SUCCESS(rc))
    2033                 cb += cbFile;
    2034         }
    2035     }
    2036 
    2037     LogFlowFunc(("returns %lld\n", cb));
    2038     return cb;
    2039 }
    2040 
    2041 /** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */
    2042 static int qcowGetPCHSGeometry(void *pBackendData,
    2043                               PVDGEOMETRY pPCHSGeometry)
    2044 {
    2045     LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry));
    2046     PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
    2047     int rc;
    2048 
    2049     AssertPtr(pImage);
    2050 
    2051     if (pImage)
    2052     {
    2053         if (pImage->PCHSGeometry.cCylinders)
    2054         {
    2055             *pPCHSGeometry = pImage->PCHSGeometry;
    2056             rc = VINF_SUCCESS;
    2057         }
    2058         else
    2059             rc = VERR_VD_GEOMETRY_NOT_SET;
    2060     }
    2061     else
    2062         rc = VERR_VD_NOT_OPENED;
    2063 
    2064     LogFlowFunc(("returns %Rrc (PCHS=%u/%u/%u)\n", rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
    2065     return rc;
    2066 }
    2067 
    2068 /** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */
    2069 static int qcowSetPCHSGeometry(void *pBackendData,
    2070                               PCVDGEOMETRY pPCHSGeometry)
    2071 {
    2072     LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
    2073     PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
    2074     int rc;
    2075 
    2076     AssertPtr(pImage);
    2077 
    2078     if (pImage)
    2079     {
    2080         if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    2081         {
    2082             rc = VERR_VD_IMAGE_READ_ONLY;
    2083             goto out;
    2084         }
    2085 
    2086         pImage->PCHSGeometry = *pPCHSGeometry;
    2087         rc = VINF_SUCCESS;
    2088     }
    2089     else
    2090         rc = VERR_VD_NOT_OPENED;
    2091 
    2092 out:
    2093     LogFlowFunc(("returns %Rrc\n", rc));
    2094     return rc;
    2095 }
    2096 
    2097 /** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */
    2098 static int qcowGetLCHSGeometry(void *pBackendData,
    2099                               PVDGEOMETRY pLCHSGeometry)
    2100 {
    2101      LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry));
    2102     PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
    2103     int rc;
    2104 
    2105     AssertPtr(pImage);
    2106 
    2107     if (pImage)
    2108     {
    2109         if (pImage->LCHSGeometry.cCylinders)
    2110         {
    2111             *pLCHSGeometry = pImage->LCHSGeometry;
    2112             rc = VINF_SUCCESS;
    2113         }
    2114         else
    2115             rc = VERR_VD_GEOMETRY_NOT_SET;
    2116     }
    2117     else
    2118         rc = VERR_VD_NOT_OPENED;
    2119 
    2120     LogFlowFunc(("returns %Rrc (LCHS=%u/%u/%u)\n", rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
    2121     return rc;
    2122 }
    2123 
    2124 /** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */
    2125 static int qcowSetLCHSGeometry(void *pBackendData,
    2126                                PCVDGEOMETRY pLCHSGeometry)
    2127 {
    2128     LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
    2129     PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
    2130     int rc;
    2131 
    2132     AssertPtr(pImage);
    2133 
    2134     if (pImage)
    2135     {
    2136         if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    2137         {
    2138             rc = VERR_VD_IMAGE_READ_ONLY;
    2139             goto out;
    2140         }
    2141 
    2142         pImage->LCHSGeometry = *pLCHSGeometry;
    2143         rc = VINF_SUCCESS;
    2144     }
    2145     else
    2146         rc = VERR_VD_NOT_OPENED;
    2147 
    2148 out:
    2149     LogFlowFunc(("returns %Rrc\n", rc));
    2150     return rc;
    2151 }
    2152 
    2153 /** @copydoc VBOXHDDBACKEND::pfnGetImageFlags */
    2154 static unsigned qcowGetImageFlags(void *pBackendData)
    2155 {
    2156     LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    2157     PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
    2158     unsigned uImageFlags;
    2159 
    2160     AssertPtr(pImage);
    2161 
    2162     if (pImage)
    2163         uImageFlags = pImage->uImageFlags;
    2164     else
    2165         uImageFlags = 0;
    2166 
    2167     LogFlowFunc(("returns %#x\n", uImageFlags));
    2168     return uImageFlags;
    2169 }
    2170 
    2171 /** @copydoc VBOXHDDBACKEND::pfnGetOpenFlags */
    2172 static unsigned qcowGetOpenFlags(void *pBackendData)
    2173 {
    2174     LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    2175     PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
    2176     unsigned uOpenFlags;
    2177 
    2178     AssertPtr(pImage);
    2179 
    2180     if (pImage)
    2181         uOpenFlags = pImage->uOpenFlags;
    2182     else
    2183         uOpenFlags = 0;
    2184 
    2185     LogFlowFunc(("returns %#x\n", uOpenFlags));
    2186     return uOpenFlags;
    2187 }
    2188 
    2189 /** @copydoc VBOXHDDBACKEND::pfnSetOpenFlags */
    2190 static int qcowSetOpenFlags(void *pBackendData, unsigned uOpenFlags)
    2191 {
    2192     LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags));
    2193     PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
    2194     int rc;
    2195 
    2196     /* Image must be opened and the new flags must be valid. */
    2197     if (!pImage || (uOpenFlags & ~(  VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO
    2198                                    | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS)))
    2199     {
    2200         rc = VERR_INVALID_PARAMETER;
    2201         goto out;
    2202     }
    2203 
    2204     /* Implement this operation via reopening the image. */
    2205     rc = qcowFreeImage(pImage, false);
    2206     if (RT_FAILURE(rc))
    2207         goto out;
    2208     rc = qcowOpenImage(pImage, uOpenFlags);
    2209 
    2210 out:
    2211     LogFlowFunc(("returns %Rrc\n", rc));
    2212     return rc;
    2213 }
    2214 
    2215 /** @copydoc VBOXHDDBACKEND::pfnGetComment */
    2216 static int qcowGetComment(void *pBackendData, char *pszComment,
    2217                           size_t cbComment)
    2218 {
    2219     LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment));
    2220     PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
    2221     int rc;
    2222 
    2223     AssertPtr(pImage);
    2224 
    2225     if (pImage)
    2226         rc = VERR_NOT_SUPPORTED;
    2227     else
    2228         rc = VERR_VD_NOT_OPENED;
    2229 
    2230     LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment));
    2231     return rc;
    2232 }
    2233 
    2234 /** @copydoc VBOXHDDBACKEND::pfnSetComment */
    2235 static int qcowSetComment(void *pBackendData, const char *pszComment)
    2236 {
    2237     LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment));
    2238     PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
    2239     int rc;
    2240 
    2241     AssertPtr(pImage);
    2242 
    2243     if (pImage)
    2244     {
    2245         if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    2246             rc = VERR_VD_IMAGE_READ_ONLY;
    2247         else
    2248             rc = VERR_NOT_SUPPORTED;
    2249     }
    2250     else
    2251         rc = VERR_VD_NOT_OPENED;
    2252 
    2253     LogFlowFunc(("returns %Rrc\n", rc));
    2254     return rc;
    2255 }
    2256 
    2257 /** @copydoc VBOXHDDBACKEND::pfnGetUuid */
    2258 static int qcowGetUuid(void *pBackendData, PRTUUID pUuid)
    2259 {
    2260     LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
    2261     PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
    2262     int rc;
    2263 
    2264     AssertPtr(pImage);
    2265 
    2266     if (pImage)
    2267         rc = VERR_NOT_SUPPORTED;
    2268     else
    2269         rc = VERR_VD_NOT_OPENED;
    2270 
    2271     LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
    2272     return rc;
    2273 }
    2274 
    2275 /** @copydoc VBOXHDDBACKEND::pfnSetUuid */
    2276 static int qcowSetUuid(void *pBackendData, PCRTUUID pUuid)
    2277 {
    2278     LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
    2279     PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
    2280     int rc;
    2281 
    2282     LogFlowFunc(("%RTuuid\n", pUuid));
    2283     AssertPtr(pImage);
    2284 
    2285     if (pImage)
    2286     {
    2287         if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    2288             rc = VERR_NOT_SUPPORTED;
    2289         else
    2290             rc = VERR_VD_IMAGE_READ_ONLY;
    2291     }
    2292     else
    2293         rc = VERR_VD_NOT_OPENED;
    2294 
    2295     LogFlowFunc(("returns %Rrc\n", rc));
    2296     return rc;
    2297 }
    2298 
    2299 /** @copydoc VBOXHDDBACKEND::pfnGetModificationUuid */
    2300 static int qcowGetModificationUuid(void *pBackendData, PRTUUID pUuid)
    2301 {
    2302     LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
    2303     PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
    2304     int rc;
    2305 
    2306     AssertPtr(pImage);
    2307 
    2308     if (pImage)
    2309         rc = VERR_NOT_SUPPORTED;
    2310     else
    2311         rc = VERR_VD_NOT_OPENED;
    2312 
    2313     LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
    2314     return rc;
    2315 }
    2316 
    2317 /** @copydoc VBOXHDDBACKEND::pfnSetModificationUuid */
    2318 static int qcowSetModificationUuid(void *pBackendData, PCRTUUID pUuid)
    2319 {
    2320     LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
    2321     PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
    2322     int rc;
    2323 
    2324     AssertPtr(pImage);
    2325 
    2326     if (pImage)
    2327     {
    2328         if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    2329             rc = VERR_NOT_SUPPORTED;
    2330         else
    2331             rc = VERR_VD_IMAGE_READ_ONLY;
    2332     }
    2333     else
    2334         rc = VERR_VD_NOT_OPENED;
    2335 
    2336     LogFlowFunc(("returns %Rrc\n", rc));
    2337     return rc;
    2338 }
    2339 
    2340 /** @copydoc VBOXHDDBACKEND::pfnGetParentUuid */
    2341 static int qcowGetParentUuid(void *pBackendData, PRTUUID pUuid)
    2342 {
    2343     LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
    2344     PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
    2345     int rc;
    2346 
    2347     AssertPtr(pImage);
    2348 
    2349     if (pImage)
    2350         rc = VERR_NOT_SUPPORTED;
    2351     else
    2352         rc = VERR_VD_NOT_OPENED;
    2353 
    2354     LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
    2355     return rc;
    2356 }
    2357 
    2358 /** @copydoc VBOXHDDBACKEND::pfnSetParentUuid */
    2359 static int qcowSetParentUuid(void *pBackendData, PCRTUUID pUuid)
    2360 {
    2361     LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
    2362     PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
    2363     int rc;
    2364 
    2365     AssertPtr(pImage);
    2366 
    2367     if (pImage)
    2368     {
    2369         if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    2370             rc = VERR_NOT_SUPPORTED;
    2371         else
    2372             rc = VERR_VD_IMAGE_READ_ONLY;
    2373     }
    2374     else
    2375         rc = VERR_VD_NOT_OPENED;
    2376 
    2377     LogFlowFunc(("returns %Rrc\n", rc));
    2378     return rc;
    2379 }
    2380 
    2381 /** @copydoc VBOXHDDBACKEND::pfnGetParentModificationUuid */
    2382 static int qcowGetParentModificationUuid(void *pBackendData, PRTUUID pUuid)
    2383 {
    2384     LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
    2385     PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
    2386     int rc;
    2387 
    2388     AssertPtr(pImage);
    2389 
    2390     if (pImage)
    2391         rc = VERR_NOT_SUPPORTED;
    2392     else
    2393         rc = VERR_VD_NOT_OPENED;
    2394 
    2395     LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
    2396     return rc;
    2397 }
    2398 
    2399 /** @copydoc VBOXHDDBACKEND::pfnSetParentModificationUuid */
    2400 static int qcowSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid)
    2401 {
    2402     LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
    2403     PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
    2404     int rc;
    2405 
    2406     AssertPtr(pImage);
    2407 
    2408     if (pImage)
    2409     {
    2410         if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    2411             rc = VERR_NOT_SUPPORTED;
    2412         else
    2413             rc = VERR_VD_IMAGE_READ_ONLY;
    2414     }
    2415     else
    2416         rc = VERR_VD_NOT_OPENED;
    2417 
    2418     LogFlowFunc(("returns %Rrc\n", rc));
    2419     return rc;
    2420 }
    2421 
    2422 /** @copydoc VBOXHDDBACKEND::pfnDump */
    2423 static void qcowDump(void *pBackendData)
    2424 {
    2425     PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
    2426 
    2427     AssertPtr(pImage);
    2428     if (pImage)
    2429     {
    2430         vdIfErrorMessage(pImage->pIfError, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cSector=%llu\n",
    2431                          pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors,
    2432                          pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors,
    2433                          pImage->cbSize / 512);
    2434     }
    2435 }
    2436 
    2437 /** @copydoc VBOXHDDBACKEND::pfnGetParentFilename */
    2438 static int qcowGetParentFilename(void *pBackendData, char **ppszParentFilename)
    2439 {
    2440     int rc = VINF_SUCCESS;
    2441     PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
    2442 
    2443     AssertPtr(pImage);
    2444     if (pImage)
    2445         if (pImage->pszFilename)
    2446             *ppszParentFilename = RTStrDup(pImage->pszBackingFilename);
    2447         else
    2448             rc = VERR_NOT_SUPPORTED;
    2449     else
    2450         rc = VERR_VD_NOT_OPENED;
    2451 
    2452     LogFlowFunc(("returns %Rrc\n", rc));
    2453     return rc;
    2454 }
    2455 
    2456 /** @copydoc VBOXHDDBACKEND::pfnSetParentFilename */
    2457 static int qcowSetParentFilename(void *pBackendData, const char *pszParentFilename)
    2458 {
    2459     int rc = VINF_SUCCESS;
    2460     PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
    2461 
    2462     AssertPtr(pImage);
    2463     if (pImage)
    2464     {
    2465         if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    2466             rc = VERR_VD_IMAGE_READ_ONLY;
    2467         else if (   pImage->pszBackingFilename
    2468                  && (strlen(pszParentFilename) > pImage->cbBackingFilename))
    2469             rc = VERR_NOT_SUPPORTED; /* The new filename is longer than the old one. */
    2470         else
    2471         {
    2472             if (pImage->pszBackingFilename)
    2473                 RTStrFree(pImage->pszBackingFilename);
    2474             pImage->pszBackingFilename = RTStrDup(pszParentFilename);
    2475             if (!pImage->pszBackingFilename)
    2476                 rc = VERR_NO_MEMORY;
    2477             else
    2478             {
    2479                 if (!pImage->offBackingFilename)
    2480                 {
    2481                     /* Allocate new cluster. */
    2482                     uint64_t offData = qcowClusterAllocate(pImage, 1);
    2483 
    2484                     Assert((offData & UINT32_MAX) == offData);
    2485                     pImage->offBackingFilename = (uint32_t)offData;
    2486                     pImage->cbBackingFilename  = strlen(pszParentFilename);
    2487                     rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage,
    2488                                               offData + pImage->cbCluster);
    2489                 }
    2490 
    2491                 if (RT_SUCCESS(rc))
    2492                     rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage,
    2493                                                 pImage->offBackingFilename,
    2494                                                 pImage->pszBackingFilename,
    2495                                                 strlen(pImage->pszBackingFilename));
    2496             }
    2497         }
    2498     }
    2499     else
    2500         rc = VERR_VD_NOT_OPENED;
    2501 
    2502     LogFlowFunc(("returns %Rrc\n", rc));
    2503     return rc;
    2504 }
    2505 
    2506 static int qcowAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbToRead,
    2507                         PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
    2508 {
    2509     LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n",
    2510                  pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead));
    2511     PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
    2512     uint32_t offCluster = 0;
    2513     uint32_t idxL1      = 0;
    2514     uint32_t idxL2      = 0;
    2515     uint64_t offFile    = 0;
    2516     int rc;
    2517 
    2518     AssertPtr(pImage);
    2519     Assert(uOffset % 512 == 0);
    2520     Assert(cbToRead % 512 == 0);
    2521 
    2522     if (!VALID_PTR(pIoCtx) || !cbToRead)
    2523     {
    2524         rc = VERR_INVALID_PARAMETER;
    2525         goto out;
    2526     }
    2527 
    2528     if (   uOffset + cbToRead > pImage->cbSize
    2529         || cbToRead == 0)
    2530     {
    2531         rc = VERR_INVALID_PARAMETER;
    2532         goto out;
    2533     }
    2534 
    2535     qcowConvertLogicalOffset(pImage, uOffset, &idxL1, &idxL2, &offCluster);
    2536 
    2537     /* Clip read size to remain in the cluster. */
    2538     cbToRead = RT_MIN(cbToRead, pImage->cbCluster - offCluster);
    2539 
    2540     /* Get offset in image. */
    2541     rc = qcowConvertToImageOffsetAsync(pImage, pIoCtx, idxL1, idxL2, offCluster,
    2542                                        &offFile);
     1707    rc = qcowConvertToImageOffset(pImage, pIoCtx, idxL1, idxL2, offCluster, &offFile);
    25431708    if (RT_SUCCESS(rc))
    25441709        rc = vdIfIoIntFileReadUser(pImage->pIfIo, pImage->pStorage, offFile,
     
    25561721}
    25571722
    2558 static int qcowAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite,
    2559                          PVDIOCTX pIoCtx,
    2560                          size_t *pcbWriteProcess, size_t *pcbPreRead,
    2561                          size_t *pcbPostRead, unsigned fWrite)
     1723static int qcowWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite,
     1724                     PVDIOCTX pIoCtx, size_t *pcbWriteProcess, size_t *pcbPreRead,
     1725                     size_t *pcbPostRead, unsigned fWrite)
    25621726{
    25631727    LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n",
     
    26011765
    26021766    /* Get offset in image. */
    2603     rc = qcowConvertToImageOffsetAsync(pImage, pIoCtx, idxL1, idxL2, offCluster,
    2604                                       &offImage);
     1767    rc = qcowConvertToImageOffset(pImage, pIoCtx, idxL1, idxL2, offCluster, &offImage);
    26051768    if (RT_SUCCESS(rc))
    26061769        rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pImage->pStorage,
     
    26761839                else
    26771840                {
    2678                     rc = qcowL2TblCacheFetchAsync(pImage, pIoCtx, pImage->paL1Table[idxL1],
    2679                                                  &pL2Entry);
    2680 
     1841                    rc = qcowL2TblCacheFetch(pImage, pIoCtx, pImage->paL1Table[idxL1],
     1842                                             &pL2Entry);
    26811843                    if (RT_SUCCESS(rc))
    26821844                    {
     
    27411903}
    27421904
    2743 static int qcowAsyncFlush(void *pBackendData, PVDIOCTX pIoCtx)
     1905static int qcowFlush(void *pBackendData, PVDIOCTX pIoCtx)
    27441906{
    27451907    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     
    27571919    return rc;
    27581920}
     1921
     1922/** @copydoc VBOXHDDBACKEND::pfnGetVersion */
     1923static unsigned qcowGetVersion(void *pBackendData)
     1924{
     1925    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     1926    PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
     1927
     1928    AssertPtr(pImage);
     1929
     1930    if (pImage)
     1931        return pImage->uVersion;
     1932    else
     1933        return 0;
     1934}
     1935
     1936/** @copydoc VBOXHDDBACKEND::pfnGetSize */
     1937static uint64_t qcowGetSize(void *pBackendData)
     1938{
     1939    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     1940    PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
     1941    uint64_t cb = 0;
     1942
     1943    AssertPtr(pImage);
     1944
     1945    if (pImage && pImage->pStorage)
     1946        cb = pImage->cbSize;
     1947
     1948    LogFlowFunc(("returns %llu\n", cb));
     1949    return cb;
     1950}
     1951
     1952/** @copydoc VBOXHDDBACKEND::pfnGetFileSize */
     1953static uint64_t qcowGetFileSize(void *pBackendData)
     1954{
     1955    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     1956    PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
     1957    uint64_t cb = 0;
     1958
     1959    AssertPtr(pImage);
     1960
     1961    if (pImage)
     1962    {
     1963        uint64_t cbFile;
     1964        if (pImage->pStorage)
     1965        {
     1966            int rc = vdIfIoIntFileGetSize(pImage->pIfIo, pImage->pStorage, &cbFile);
     1967            if (RT_SUCCESS(rc))
     1968                cb += cbFile;
     1969        }
     1970    }
     1971
     1972    LogFlowFunc(("returns %lld\n", cb));
     1973    return cb;
     1974}
     1975
     1976/** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */
     1977static int qcowGetPCHSGeometry(void *pBackendData,
     1978                              PVDGEOMETRY pPCHSGeometry)
     1979{
     1980    LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry));
     1981    PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
     1982    int rc;
     1983
     1984    AssertPtr(pImage);
     1985
     1986    if (pImage)
     1987    {
     1988        if (pImage->PCHSGeometry.cCylinders)
     1989        {
     1990            *pPCHSGeometry = pImage->PCHSGeometry;
     1991            rc = VINF_SUCCESS;
     1992        }
     1993        else
     1994            rc = VERR_VD_GEOMETRY_NOT_SET;
     1995    }
     1996    else
     1997        rc = VERR_VD_NOT_OPENED;
     1998
     1999    LogFlowFunc(("returns %Rrc (PCHS=%u/%u/%u)\n", rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
     2000    return rc;
     2001}
     2002
     2003/** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */
     2004static int qcowSetPCHSGeometry(void *pBackendData,
     2005                              PCVDGEOMETRY pPCHSGeometry)
     2006{
     2007    LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
     2008    PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
     2009    int rc;
     2010
     2011    AssertPtr(pImage);
     2012
     2013    if (pImage)
     2014    {
     2015        if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     2016        {
     2017            rc = VERR_VD_IMAGE_READ_ONLY;
     2018            goto out;
     2019        }
     2020
     2021        pImage->PCHSGeometry = *pPCHSGeometry;
     2022        rc = VINF_SUCCESS;
     2023    }
     2024    else
     2025        rc = VERR_VD_NOT_OPENED;
     2026
     2027out:
     2028    LogFlowFunc(("returns %Rrc\n", rc));
     2029    return rc;
     2030}
     2031
     2032/** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */
     2033static int qcowGetLCHSGeometry(void *pBackendData,
     2034                              PVDGEOMETRY pLCHSGeometry)
     2035{
     2036     LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry));
     2037    PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
     2038    int rc;
     2039
     2040    AssertPtr(pImage);
     2041
     2042    if (pImage)
     2043    {
     2044        if (pImage->LCHSGeometry.cCylinders)
     2045        {
     2046            *pLCHSGeometry = pImage->LCHSGeometry;
     2047            rc = VINF_SUCCESS;
     2048        }
     2049        else
     2050            rc = VERR_VD_GEOMETRY_NOT_SET;
     2051    }
     2052    else
     2053        rc = VERR_VD_NOT_OPENED;
     2054
     2055    LogFlowFunc(("returns %Rrc (LCHS=%u/%u/%u)\n", rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
     2056    return rc;
     2057}
     2058
     2059/** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */
     2060static int qcowSetLCHSGeometry(void *pBackendData,
     2061                               PCVDGEOMETRY pLCHSGeometry)
     2062{
     2063    LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
     2064    PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
     2065    int rc;
     2066
     2067    AssertPtr(pImage);
     2068
     2069    if (pImage)
     2070    {
     2071        if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     2072        {
     2073            rc = VERR_VD_IMAGE_READ_ONLY;
     2074            goto out;
     2075        }
     2076
     2077        pImage->LCHSGeometry = *pLCHSGeometry;
     2078        rc = VINF_SUCCESS;
     2079    }
     2080    else
     2081        rc = VERR_VD_NOT_OPENED;
     2082
     2083out:
     2084    LogFlowFunc(("returns %Rrc\n", rc));
     2085    return rc;
     2086}
     2087
     2088/** @copydoc VBOXHDDBACKEND::pfnGetImageFlags */
     2089static unsigned qcowGetImageFlags(void *pBackendData)
     2090{
     2091    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     2092    PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
     2093    unsigned uImageFlags;
     2094
     2095    AssertPtr(pImage);
     2096
     2097    if (pImage)
     2098        uImageFlags = pImage->uImageFlags;
     2099    else
     2100        uImageFlags = 0;
     2101
     2102    LogFlowFunc(("returns %#x\n", uImageFlags));
     2103    return uImageFlags;
     2104}
     2105
     2106/** @copydoc VBOXHDDBACKEND::pfnGetOpenFlags */
     2107static unsigned qcowGetOpenFlags(void *pBackendData)
     2108{
     2109    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     2110    PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
     2111    unsigned uOpenFlags;
     2112
     2113    AssertPtr(pImage);
     2114
     2115    if (pImage)
     2116        uOpenFlags = pImage->uOpenFlags;
     2117    else
     2118        uOpenFlags = 0;
     2119
     2120    LogFlowFunc(("returns %#x\n", uOpenFlags));
     2121    return uOpenFlags;
     2122}
     2123
     2124/** @copydoc VBOXHDDBACKEND::pfnSetOpenFlags */
     2125static int qcowSetOpenFlags(void *pBackendData, unsigned uOpenFlags)
     2126{
     2127    LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags));
     2128    PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
     2129    int rc;
     2130
     2131    /* Image must be opened and the new flags must be valid. */
     2132    if (!pImage || (uOpenFlags & ~(  VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO
     2133                                   | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS)))
     2134    {
     2135        rc = VERR_INVALID_PARAMETER;
     2136        goto out;
     2137    }
     2138
     2139    /* Implement this operation via reopening the image. */
     2140    rc = qcowFreeImage(pImage, false);
     2141    if (RT_FAILURE(rc))
     2142        goto out;
     2143    rc = qcowOpenImage(pImage, uOpenFlags);
     2144
     2145out:
     2146    LogFlowFunc(("returns %Rrc\n", rc));
     2147    return rc;
     2148}
     2149
     2150/** @copydoc VBOXHDDBACKEND::pfnGetComment */
     2151static int qcowGetComment(void *pBackendData, char *pszComment,
     2152                          size_t cbComment)
     2153{
     2154    LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment));
     2155    PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
     2156    int rc;
     2157
     2158    AssertPtr(pImage);
     2159
     2160    if (pImage)
     2161        rc = VERR_NOT_SUPPORTED;
     2162    else
     2163        rc = VERR_VD_NOT_OPENED;
     2164
     2165    LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment));
     2166    return rc;
     2167}
     2168
     2169/** @copydoc VBOXHDDBACKEND::pfnSetComment */
     2170static int qcowSetComment(void *pBackendData, const char *pszComment)
     2171{
     2172    LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment));
     2173    PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
     2174    int rc;
     2175
     2176    AssertPtr(pImage);
     2177
     2178    if (pImage)
     2179    {
     2180        if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     2181            rc = VERR_VD_IMAGE_READ_ONLY;
     2182        else
     2183            rc = VERR_NOT_SUPPORTED;
     2184    }
     2185    else
     2186        rc = VERR_VD_NOT_OPENED;
     2187
     2188    LogFlowFunc(("returns %Rrc\n", rc));
     2189    return rc;
     2190}
     2191
     2192/** @copydoc VBOXHDDBACKEND::pfnGetUuid */
     2193static int qcowGetUuid(void *pBackendData, PRTUUID pUuid)
     2194{
     2195    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
     2196    PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
     2197    int rc;
     2198
     2199    AssertPtr(pImage);
     2200
     2201    if (pImage)
     2202        rc = VERR_NOT_SUPPORTED;
     2203    else
     2204        rc = VERR_VD_NOT_OPENED;
     2205
     2206    LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
     2207    return rc;
     2208}
     2209
     2210/** @copydoc VBOXHDDBACKEND::pfnSetUuid */
     2211static int qcowSetUuid(void *pBackendData, PCRTUUID pUuid)
     2212{
     2213    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
     2214    PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
     2215    int rc;
     2216
     2217    LogFlowFunc(("%RTuuid\n", pUuid));
     2218    AssertPtr(pImage);
     2219
     2220    if (pImage)
     2221    {
     2222        if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     2223            rc = VERR_NOT_SUPPORTED;
     2224        else
     2225            rc = VERR_VD_IMAGE_READ_ONLY;
     2226    }
     2227    else
     2228        rc = VERR_VD_NOT_OPENED;
     2229
     2230    LogFlowFunc(("returns %Rrc\n", rc));
     2231    return rc;
     2232}
     2233
     2234/** @copydoc VBOXHDDBACKEND::pfnGetModificationUuid */
     2235static int qcowGetModificationUuid(void *pBackendData, PRTUUID pUuid)
     2236{
     2237    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
     2238    PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
     2239    int rc;
     2240
     2241    AssertPtr(pImage);
     2242
     2243    if (pImage)
     2244        rc = VERR_NOT_SUPPORTED;
     2245    else
     2246        rc = VERR_VD_NOT_OPENED;
     2247
     2248    LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
     2249    return rc;
     2250}
     2251
     2252/** @copydoc VBOXHDDBACKEND::pfnSetModificationUuid */
     2253static int qcowSetModificationUuid(void *pBackendData, PCRTUUID pUuid)
     2254{
     2255    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
     2256    PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
     2257    int rc;
     2258
     2259    AssertPtr(pImage);
     2260
     2261    if (pImage)
     2262    {
     2263        if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     2264            rc = VERR_NOT_SUPPORTED;
     2265        else
     2266            rc = VERR_VD_IMAGE_READ_ONLY;
     2267    }
     2268    else
     2269        rc = VERR_VD_NOT_OPENED;
     2270
     2271    LogFlowFunc(("returns %Rrc\n", rc));
     2272    return rc;
     2273}
     2274
     2275/** @copydoc VBOXHDDBACKEND::pfnGetParentUuid */
     2276static int qcowGetParentUuid(void *pBackendData, PRTUUID pUuid)
     2277{
     2278    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
     2279    PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
     2280    int rc;
     2281
     2282    AssertPtr(pImage);
     2283
     2284    if (pImage)
     2285        rc = VERR_NOT_SUPPORTED;
     2286    else
     2287        rc = VERR_VD_NOT_OPENED;
     2288
     2289    LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
     2290    return rc;
     2291}
     2292
     2293/** @copydoc VBOXHDDBACKEND::pfnSetParentUuid */
     2294static int qcowSetParentUuid(void *pBackendData, PCRTUUID pUuid)
     2295{
     2296    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
     2297    PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
     2298    int rc;
     2299
     2300    AssertPtr(pImage);
     2301
     2302    if (pImage)
     2303    {
     2304        if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     2305            rc = VERR_NOT_SUPPORTED;
     2306        else
     2307            rc = VERR_VD_IMAGE_READ_ONLY;
     2308    }
     2309    else
     2310        rc = VERR_VD_NOT_OPENED;
     2311
     2312    LogFlowFunc(("returns %Rrc\n", rc));
     2313    return rc;
     2314}
     2315
     2316/** @copydoc VBOXHDDBACKEND::pfnGetParentModificationUuid */
     2317static int qcowGetParentModificationUuid(void *pBackendData, PRTUUID pUuid)
     2318{
     2319    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
     2320    PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
     2321    int rc;
     2322
     2323    AssertPtr(pImage);
     2324
     2325    if (pImage)
     2326        rc = VERR_NOT_SUPPORTED;
     2327    else
     2328        rc = VERR_VD_NOT_OPENED;
     2329
     2330    LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
     2331    return rc;
     2332}
     2333
     2334/** @copydoc VBOXHDDBACKEND::pfnSetParentModificationUuid */
     2335static int qcowSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid)
     2336{
     2337    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
     2338    PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
     2339    int rc;
     2340
     2341    AssertPtr(pImage);
     2342
     2343    if (pImage)
     2344    {
     2345        if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     2346            rc = VERR_NOT_SUPPORTED;
     2347        else
     2348            rc = VERR_VD_IMAGE_READ_ONLY;
     2349    }
     2350    else
     2351        rc = VERR_VD_NOT_OPENED;
     2352
     2353    LogFlowFunc(("returns %Rrc\n", rc));
     2354    return rc;
     2355}
     2356
     2357/** @copydoc VBOXHDDBACKEND::pfnDump */
     2358static void qcowDump(void *pBackendData)
     2359{
     2360    PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
     2361
     2362    AssertPtr(pImage);
     2363    if (pImage)
     2364    {
     2365        vdIfErrorMessage(pImage->pIfError, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cSector=%llu\n",
     2366                         pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors,
     2367                         pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors,
     2368                         pImage->cbSize / 512);
     2369    }
     2370}
     2371
     2372/** @copydoc VBOXHDDBACKEND::pfnGetParentFilename */
     2373static int qcowGetParentFilename(void *pBackendData, char **ppszParentFilename)
     2374{
     2375    int rc = VINF_SUCCESS;
     2376    PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
     2377
     2378    AssertPtr(pImage);
     2379    if (pImage)
     2380        if (pImage->pszFilename)
     2381            *ppszParentFilename = RTStrDup(pImage->pszBackingFilename);
     2382        else
     2383            rc = VERR_NOT_SUPPORTED;
     2384    else
     2385        rc = VERR_VD_NOT_OPENED;
     2386
     2387    LogFlowFunc(("returns %Rrc\n", rc));
     2388    return rc;
     2389}
     2390
     2391/** @copydoc VBOXHDDBACKEND::pfnSetParentFilename */
     2392static int qcowSetParentFilename(void *pBackendData, const char *pszParentFilename)
     2393{
     2394    int rc = VINF_SUCCESS;
     2395    PQCOWIMAGE pImage = (PQCOWIMAGE)pBackendData;
     2396
     2397    AssertPtr(pImage);
     2398    if (pImage)
     2399    {
     2400        if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     2401            rc = VERR_VD_IMAGE_READ_ONLY;
     2402        else if (   pImage->pszBackingFilename
     2403                 && (strlen(pszParentFilename) > pImage->cbBackingFilename))
     2404            rc = VERR_NOT_SUPPORTED; /* The new filename is longer than the old one. */
     2405        else
     2406        {
     2407            if (pImage->pszBackingFilename)
     2408                RTStrFree(pImage->pszBackingFilename);
     2409            pImage->pszBackingFilename = RTStrDup(pszParentFilename);
     2410            if (!pImage->pszBackingFilename)
     2411                rc = VERR_NO_MEMORY;
     2412            else
     2413            {
     2414                if (!pImage->offBackingFilename)
     2415                {
     2416                    /* Allocate new cluster. */
     2417                    uint64_t offData = qcowClusterAllocate(pImage, 1);
     2418
     2419                    Assert((offData & UINT32_MAX) == offData);
     2420                    pImage->offBackingFilename = (uint32_t)offData;
     2421                    pImage->cbBackingFilename  = strlen(pszParentFilename);
     2422                    rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage,
     2423                                              offData + pImage->cbCluster);
     2424                }
     2425
     2426                if (RT_SUCCESS(rc))
     2427                    rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage,
     2428                                                pImage->offBackingFilename,
     2429                                                pImage->pszBackingFilename,
     2430                                                strlen(pImage->pszBackingFilename));
     2431            }
     2432        }
     2433    }
     2434    else
     2435        rc = VERR_VD_NOT_OPENED;
     2436
     2437    LogFlowFunc(("returns %Rrc\n", rc));
     2438    return rc;
     2439}
     2440
     2441
    27592442
    27602443VBOXHDDBACKEND g_QCowBackend =
     
    27882471    /* pfnFlush */
    27892472    qcowFlush,
     2473    /* pfnDiscard */
     2474    NULL,
    27902475    /* pfnGetVersion */
    27912476    qcowGetVersion,
     
    28402525    /* pfnSetParentFilename */
    28412526    qcowSetParentFilename,
    2842     /* pfnAsyncRead */
    2843     qcowAsyncRead,
    2844     /* pfnAsyncWrite */
    2845     qcowAsyncWrite,
    2846     /* pfnAsyncFlush */
    2847     qcowAsyncFlush,
    28482527    /* pfnComposeLocation */
    28492528    genericFileComposeLocation,
     
    28542533    /* pfnResize */
    28552534    NULL,
    2856     /* pfnDiscard */
    2857     NULL,
    2858     /* pfnAsyncDiscard */
    2859     NULL,
    28602535    /* pfnRepair */
    28612536    NULL
  • trunk/src/VBox/Storage/QED.cpp

    r44233 r44252  
    772772 *          VERR_VD_BLOCK_FREE if the cluster is not yet allocated.
    773773 * @param   pImage        The image instance data.
    774  * @param   idxL1         The L1 index.
    775  * @param   idxL2         The L2 index.
    776  * @param   offCluster    Offset inside the cluster.
    777  * @param   poffImage     Where to store the image offset on success;
    778  */
    779 static int qedConvertToImageOffset(PQEDIMAGE pImage, uint32_t idxL1, uint32_t idxL2,
    780                                    uint32_t offCluster, uint64_t *poffImage)
    781 {
    782     int rc = VERR_VD_BLOCK_FREE;
    783     LogFlowFunc(("pImage=%#p idxL1=%u idxL2=%u offCluster=%u poffImage=%#p\n",
    784                  pImage, idxL1, idxL2, offCluster, poffImage));
    785 
    786     AssertReturn(idxL1 < pImage->cTableEntries, VERR_INVALID_PARAMETER);
    787     AssertReturn(idxL2 < pImage->cTableEntries, VERR_INVALID_PARAMETER);
    788 
    789     if (pImage->paL1Table[idxL1])
    790     {
    791         PQEDL2CACHEENTRY pL2Entry;
    792 
    793         rc = qedL2TblCacheFetch(pImage, pImage->paL1Table[idxL1], &pL2Entry);
    794         if (RT_SUCCESS(rc))
    795         {
    796             LogFlowFunc(("cluster start offset %llu\n", pL2Entry->paL2Tbl[idxL2]));
    797             /* Get real file offset. */
    798             if (pL2Entry->paL2Tbl[idxL2])
    799                 *poffImage = pL2Entry->paL2Tbl[idxL2] + offCluster;
    800             else
    801                 rc = VERR_VD_BLOCK_FREE;
    802 
    803             qedL2TblCacheEntryRelease(pL2Entry);
    804         }
    805     }
    806 
    807     LogFlowFunc(("returns rc=%Rrc\n", rc));
    808     return rc;
    809 }
    810 
    811 /**
    812  * Returns the real image offset for a given cluster or an error if the cluster is not
    813  * yet allocated- version for async I/O.
    814  *
    815  * @returns VBox status code.
    816  *          VERR_VD_BLOCK_FREE if the cluster is not yet allocated.
    817  * @param   pImage        The image instance data.
    818774 * @param   pIoCtx        The I/O context.
    819775 * @param   idxL1         The L1 index.
     
    822778 * @param   poffImage     Where to store the image offset on success;
    823779 */
    824 static int qedConvertToImageOffsetAsync(PQEDIMAGE pImage, PVDIOCTX pIoCtx,
    825                                         uint32_t idxL1, uint32_t idxL2,
    826                                         uint32_t offCluster, uint64_t *poffImage)
     780static int qedConvertToImageOffset(PQEDIMAGE pImage, PVDIOCTX pIoCtx,
     781                                   uint32_t idxL1, uint32_t idxL2,
     782                                   uint32_t offCluster, uint64_t *poffImage)
    827783{
    828784    int rc = VERR_VD_BLOCK_FREE;
     
    18011757}
    18021758
    1803 /** @copydoc VBOXHDDBACKEND::pfnRead */
    1804 static int qedRead(void *pBackendData, uint64_t uOffset, void *pvBuf,
    1805                    size_t cbToRead, size_t *pcbActuallyRead)
    1806 {
    1807     LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n",
    1808                  pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead));
     1759static int qedRead(void *pBackendData, uint64_t uOffset, size_t cbToRead,
     1760                   PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
     1761{
     1762    LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n",
     1763                 pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead));
    18091764    PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
    18101765    uint32_t offCluster = 0;
     
    18181773    Assert(cbToRead % 512 == 0);
    18191774
     1775    if (!VALID_PTR(pIoCtx) || !cbToRead)
     1776    {
     1777        rc = VERR_INVALID_PARAMETER;
     1778        goto out;
     1779    }
     1780
    18201781    if (   uOffset + cbToRead > pImage->cbSize
    18211782        || cbToRead == 0)
     
    18261787
    18271788    qedConvertLogicalOffset(pImage, uOffset, &idxL1, &idxL2, &offCluster);
    1828     LogFlowFunc(("idxL1=%u idxL2=%u offCluster=%u\n", idxL1, idxL2, offCluster));
    18291789
    18301790    /* Clip read size to remain in the cluster. */
     
    18321792
    18331793    /* Get offset in image. */
    1834     rc = qedConvertToImageOffset(pImage, idxL1, idxL2, offCluster, &offFile);
    1835     if (RT_SUCCESS(rc))
    1836     {
    1837         LogFlowFunc(("offFile=%llu\n", offFile));
    1838         rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, offFile,
    1839                                    pvBuf, cbToRead);
    1840     }
    1841 
    1842     if (   (RT_SUCCESS(rc) || rc == VERR_VD_BLOCK_FREE)
    1843         && pcbActuallyRead)
    1844         *pcbActuallyRead = cbToRead;
    1845 
    1846 out:
    1847     LogFlowFunc(("returns %Rrc\n", rc));
    1848     return rc;
    1849 }
    1850 
    1851 /** @copydoc VBOXHDDBACKEND::pfnWrite */
    1852 static int qedWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf,
    1853                     size_t cbToWrite, size_t *pcbWriteProcess,
    1854                     size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite)
    1855 {
    1856     LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n",
    1857                  pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));
    1858     PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
    1859     uint32_t offCluster = 0;
    1860     uint32_t idxL1      = 0;
    1861     uint32_t idxL2      = 0;
    1862     uint64_t offImage   = 0;
    1863     int rc;
    1864 
    1865     AssertPtr(pImage);
    1866     Assert(uOffset % 512 == 0);
    1867     Assert(cbToWrite % 512 == 0);
    1868 
    1869     if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    1870     {
    1871         rc = VERR_VD_IMAGE_READ_ONLY;
    1872         goto out;
    1873     }
    1874 
    1875     if (   uOffset + cbToWrite > pImage->cbSize
    1876         || cbToWrite == 0)
    1877     {
    1878         rc = VERR_INVALID_PARAMETER;
    1879         goto out;
    1880     }
    1881 
    1882     /* Convert offset to L1, L2 index and cluster offset. */
    1883     qedConvertLogicalOffset(pImage, uOffset, &idxL1, &idxL2, &offCluster);
    1884 
    1885     /* Clip write size to remain in the cluster. */
    1886     cbToWrite = RT_MIN(cbToWrite, pImage->cbCluster - offCluster);
    1887     Assert(!(cbToWrite % 512));
    1888 
    1889     /* Get offset in image. */
    1890     rc = qedConvertToImageOffset(pImage, idxL1, idxL2, offCluster, &offImage);
    1891     if (RT_SUCCESS(rc))
    1892         rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, offImage,
    1893                                     pvBuf, cbToWrite);
    1894     else if (rc == VERR_VD_BLOCK_FREE)
    1895     {
    1896         if (   cbToWrite == pImage->cbCluster
    1897             && !(fWrite & VD_WRITE_NO_ALLOC))
    1898         {
    1899             PQEDL2CACHEENTRY pL2Entry = NULL;
    1900 
    1901             /* Full cluster write to previously unallocated cluster.
    1902              * Allocate cluster and write data. */
    1903             Assert(!offCluster);
    1904 
    1905             do
    1906             {
    1907                 uint64_t idxUpdateLe = 0;
    1908 
    1909                 /* Check if we have to allocate a new cluster for L2 tables. */
    1910                 if (!pImage->paL1Table[idxL1])
    1911                 {
    1912                     uint64_t offL2Tbl = qedClusterAllocate(pImage, qedByte2Cluster(pImage, pImage->cbTable));
    1913 
    1914                     pL2Entry = qedL2TblCacheEntryAlloc(pImage);
    1915                     if (!pL2Entry)
    1916                     {
    1917                         rc = VERR_NO_MEMORY;
    1918                         break;
    1919                     }
    1920 
    1921                     pL2Entry->offL2Tbl = offL2Tbl;
    1922                     memset(pL2Entry->paL2Tbl, 0, pImage->cbTable);
    1923                     qedL2TblCacheEntryInsert(pImage, pL2Entry);
    1924 
    1925                     /*
    1926                      * Write the L2 table first and link to the L1 table afterwards.
    1927                      * If something unexpected happens the worst case which can happen
    1928                      * is a leak of some clusters.
    1929                      */
    1930                     rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, offL2Tbl,
    1931                                                 pL2Entry->paL2Tbl, pImage->cbTable);
    1932                     if (RT_FAILURE(rc))
    1933                         break;
    1934 
    1935                     /* Write the L1 link now. */
    1936                     pImage->paL1Table[idxL1] = offL2Tbl;
    1937                     idxUpdateLe = RT_H2LE_U64(offL2Tbl);
    1938                     rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage,
    1939                                                 pImage->offL1Table + idxL1*sizeof(uint64_t),
    1940                                                 &idxUpdateLe, sizeof(uint64_t));
    1941                     if (RT_FAILURE(rc))
    1942                         break;
    1943                 }
    1944                 else
    1945                     rc = qedL2TblCacheFetch(pImage, pImage->paL1Table[idxL1], &pL2Entry);
    1946 
    1947                 if (RT_SUCCESS(rc))
    1948                 {
    1949                     /* Allocate new cluster for the data. */
    1950                     uint64_t offData = qedClusterAllocate(pImage, 1);
    1951 
    1952                     /* Write data. */
    1953                     rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage,
    1954                                                 offData, pvBuf, cbToWrite);
    1955                     if (RT_FAILURE(rc))
    1956                         break;
    1957 
    1958                     /* Link L2 table and update it. */
    1959                     pL2Entry->paL2Tbl[idxL2] = offData;
    1960                     idxUpdateLe = RT_H2LE_U64(offData);
    1961                     rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage,
    1962                                                 pImage->paL1Table[idxL1] + idxL2*sizeof(uint64_t),
    1963                                                 &idxUpdateLe, sizeof(uint64_t));
    1964                     qedL2TblCacheEntryRelease(pL2Entry);
    1965                 }
    1966 
    1967             } while (0);
    1968 
    1969             *pcbPreRead = 0;
    1970             *pcbPostRead = 0;
    1971         }
    1972         else
    1973         {
    1974             /* Trying to do a partial write to an unallocated cluster. Don't do
    1975              * anything except letting the upper layer know what to do. */
    1976             *pcbPreRead = offCluster;
    1977             *pcbPostRead = pImage->cbCluster - cbToWrite - *pcbPreRead;
    1978         }
    1979     }
    1980 
    1981     if (pcbWriteProcess)
    1982         *pcbWriteProcess = cbToWrite;
    1983 
    1984 out:
    1985     LogFlowFunc(("returns %Rrc\n", rc));
    1986     return rc;
    1987 }
    1988 
    1989 /** @copydoc VBOXHDDBACKEND::pfnFlush */
    1990 static int qedFlush(void *pBackendData)
    1991 {
    1992     LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    1993     PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
    1994     int rc;
    1995 
    1996     rc = qedFlushImage(pImage);
    1997     LogFlowFunc(("returns %Rrc\n", rc));
    1998     return rc;
    1999 }
    2000 
    2001 /** @copydoc VBOXHDDBACKEND::pfnGetVersion */
    2002 static unsigned qedGetVersion(void *pBackendData)
    2003 {
    2004     LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    2005     PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
    2006 
    2007     AssertPtr(pImage);
    2008 
    2009     if (pImage)
    2010         return 1;
    2011     else
    2012         return 0;
    2013 }
    2014 
    2015 /** @copydoc VBOXHDDBACKEND::pfnGetSize */
    2016 static uint64_t qedGetSize(void *pBackendData)
    2017 {
    2018     LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    2019     PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
    2020     uint64_t cb = 0;
    2021 
    2022     AssertPtr(pImage);
    2023 
    2024     if (pImage && pImage->pStorage)
    2025         cb = pImage->cbSize;
    2026 
    2027     LogFlowFunc(("returns %llu\n", cb));
    2028     return cb;
    2029 }
    2030 
    2031 /** @copydoc VBOXHDDBACKEND::pfnGetFileSize */
    2032 static uint64_t qedGetFileSize(void *pBackendData)
    2033 {
    2034     LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    2035     PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
    2036     uint64_t cb = 0;
    2037 
    2038     AssertPtr(pImage);
    2039 
    2040     if (pImage)
    2041     {
    2042         uint64_t cbFile;
    2043         if (pImage->pStorage)
    2044         {
    2045             int rc = vdIfIoIntFileGetSize(pImage->pIfIo, pImage->pStorage, &cbFile);
    2046             if (RT_SUCCESS(rc))
    2047                 cb += cbFile;
    2048         }
    2049     }
    2050 
    2051     LogFlowFunc(("returns %lld\n", cb));
    2052     return cb;
    2053 }
    2054 
    2055 /** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */
    2056 static int qedGetPCHSGeometry(void *pBackendData,
    2057                               PVDGEOMETRY pPCHSGeometry)
    2058 {
    2059     LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry));
    2060     PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
    2061     int rc;
    2062 
    2063     AssertPtr(pImage);
    2064 
    2065     if (pImage)
    2066     {
    2067         if (pImage->PCHSGeometry.cCylinders)
    2068         {
    2069             *pPCHSGeometry = pImage->PCHSGeometry;
    2070             rc = VINF_SUCCESS;
    2071         }
    2072         else
    2073             rc = VERR_VD_GEOMETRY_NOT_SET;
    2074     }
    2075     else
    2076         rc = VERR_VD_NOT_OPENED;
    2077 
    2078     LogFlowFunc(("returns %Rrc (PCHS=%u/%u/%u)\n", rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
    2079     return rc;
    2080 }
    2081 
    2082 /** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */
    2083 static int qedSetPCHSGeometry(void *pBackendData,
    2084                               PCVDGEOMETRY pPCHSGeometry)
    2085 {
    2086     LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
    2087     PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
    2088     int rc;
    2089 
    2090     AssertPtr(pImage);
    2091 
    2092     if (pImage)
    2093     {
    2094         if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    2095         {
    2096             rc = VERR_VD_IMAGE_READ_ONLY;
    2097             goto out;
    2098         }
    2099 
    2100         pImage->PCHSGeometry = *pPCHSGeometry;
    2101         rc = VINF_SUCCESS;
    2102     }
    2103     else
    2104         rc = VERR_VD_NOT_OPENED;
    2105 
    2106 out:
    2107     LogFlowFunc(("returns %Rrc\n", rc));
    2108     return rc;
    2109 }
    2110 
    2111 /** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */
    2112 static int qedGetLCHSGeometry(void *pBackendData,
    2113                               PVDGEOMETRY pLCHSGeometry)
    2114 {
    2115      LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry));
    2116     PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
    2117     int rc;
    2118 
    2119     AssertPtr(pImage);
    2120 
    2121     if (pImage)
    2122     {
    2123         if (pImage->LCHSGeometry.cCylinders)
    2124         {
    2125             *pLCHSGeometry = pImage->LCHSGeometry;
    2126             rc = VINF_SUCCESS;
    2127         }
    2128         else
    2129             rc = VERR_VD_GEOMETRY_NOT_SET;
    2130     }
    2131     else
    2132         rc = VERR_VD_NOT_OPENED;
    2133 
    2134     LogFlowFunc(("returns %Rrc (LCHS=%u/%u/%u)\n", rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
    2135     return rc;
    2136 }
    2137 
    2138 /** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */
    2139 static int qedSetLCHSGeometry(void *pBackendData,
    2140                                PCVDGEOMETRY pLCHSGeometry)
    2141 {
    2142     LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
    2143     PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
    2144     int rc;
    2145 
    2146     AssertPtr(pImage);
    2147 
    2148     if (pImage)
    2149     {
    2150         if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    2151         {
    2152             rc = VERR_VD_IMAGE_READ_ONLY;
    2153             goto out;
    2154         }
    2155 
    2156         pImage->LCHSGeometry = *pLCHSGeometry;
    2157         rc = VINF_SUCCESS;
    2158     }
    2159     else
    2160         rc = VERR_VD_NOT_OPENED;
    2161 
    2162 out:
    2163     LogFlowFunc(("returns %Rrc\n", rc));
    2164     return rc;
    2165 }
    2166 
    2167 /** @copydoc VBOXHDDBACKEND::pfnGetImageFlags */
    2168 static unsigned qedGetImageFlags(void *pBackendData)
    2169 {
    2170     LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    2171     PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
    2172     unsigned uImageFlags;
    2173 
    2174     AssertPtr(pImage);
    2175 
    2176     if (pImage)
    2177         uImageFlags = pImage->uImageFlags;
    2178     else
    2179         uImageFlags = 0;
    2180 
    2181     LogFlowFunc(("returns %#x\n", uImageFlags));
    2182     return uImageFlags;
    2183 }
    2184 
    2185 /** @copydoc VBOXHDDBACKEND::pfnGetOpenFlags */
    2186 static unsigned qedGetOpenFlags(void *pBackendData)
    2187 {
    2188     LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    2189     PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
    2190     unsigned uOpenFlags;
    2191 
    2192     AssertPtr(pImage);
    2193 
    2194     if (pImage)
    2195         uOpenFlags = pImage->uOpenFlags;
    2196     else
    2197         uOpenFlags = 0;
    2198 
    2199     LogFlowFunc(("returns %#x\n", uOpenFlags));
    2200     return uOpenFlags;
    2201 }
    2202 
    2203 /** @copydoc VBOXHDDBACKEND::pfnSetOpenFlags */
    2204 static int qedSetOpenFlags(void *pBackendData, unsigned uOpenFlags)
    2205 {
    2206     LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags));
    2207     PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
    2208     int rc;
    2209 
    2210     /* Image must be opened and the new flags must be valid. */
    2211     if (!pImage || (uOpenFlags & ~(  VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO
    2212                                    | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS)))
    2213     {
    2214         rc = VERR_INVALID_PARAMETER;
    2215         goto out;
    2216     }
    2217 
    2218     /* Implement this operation via reopening the image. */
    2219     rc = qedFreeImage(pImage, false);
    2220     if (RT_FAILURE(rc))
    2221         goto out;
    2222     rc = qedOpenImage(pImage, uOpenFlags);
    2223 
    2224 out:
    2225     LogFlowFunc(("returns %Rrc\n", rc));
    2226     return rc;
    2227 }
    2228 
    2229 /** @copydoc VBOXHDDBACKEND::pfnGetComment */
    2230 static int qedGetComment(void *pBackendData, char *pszComment,
    2231                           size_t cbComment)
    2232 {
    2233     LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment));
    2234     PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
    2235     int rc;
    2236 
    2237     AssertPtr(pImage);
    2238 
    2239     if (pImage)
    2240         rc = VERR_NOT_SUPPORTED;
    2241     else
    2242         rc = VERR_VD_NOT_OPENED;
    2243 
    2244     LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment));
    2245     return rc;
    2246 }
    2247 
    2248 /** @copydoc VBOXHDDBACKEND::pfnSetComment */
    2249 static int qedSetComment(void *pBackendData, const char *pszComment)
    2250 {
    2251     LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment));
    2252     PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
    2253     int rc;
    2254 
    2255     AssertPtr(pImage);
    2256 
    2257     if (pImage)
    2258     {
    2259         if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    2260             rc = VERR_VD_IMAGE_READ_ONLY;
    2261         else
    2262             rc = VERR_NOT_SUPPORTED;
    2263     }
    2264     else
    2265         rc = VERR_VD_NOT_OPENED;
    2266 
    2267     LogFlowFunc(("returns %Rrc\n", rc));
    2268     return rc;
    2269 }
    2270 
    2271 /** @copydoc VBOXHDDBACKEND::pfnGetUuid */
    2272 static int qedGetUuid(void *pBackendData, PRTUUID pUuid)
    2273 {
    2274     LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
    2275     PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
    2276     int rc;
    2277 
    2278     AssertPtr(pImage);
    2279 
    2280     if (pImage)
    2281         rc = VERR_NOT_SUPPORTED;
    2282     else
    2283         rc = VERR_VD_NOT_OPENED;
    2284 
    2285     LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
    2286     return rc;
    2287 }
    2288 
    2289 /** @copydoc VBOXHDDBACKEND::pfnSetUuid */
    2290 static int qedSetUuid(void *pBackendData, PCRTUUID pUuid)
    2291 {
    2292     LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
    2293     PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
    2294     int rc;
    2295 
    2296     LogFlowFunc(("%RTuuid\n", pUuid));
    2297     AssertPtr(pImage);
    2298 
    2299     if (pImage)
    2300     {
    2301         if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    2302             rc = VERR_NOT_SUPPORTED;
    2303         else
    2304             rc = VERR_VD_IMAGE_READ_ONLY;
    2305     }
    2306     else
    2307         rc = VERR_VD_NOT_OPENED;
    2308 
    2309     LogFlowFunc(("returns %Rrc\n", rc));
    2310     return rc;
    2311 }
    2312 
    2313 /** @copydoc VBOXHDDBACKEND::pfnGetModificationUuid */
    2314 static int qedGetModificationUuid(void *pBackendData, PRTUUID pUuid)
    2315 {
    2316     LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
    2317     PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
    2318     int rc;
    2319 
    2320     AssertPtr(pImage);
    2321 
    2322     if (pImage)
    2323         rc = VERR_NOT_SUPPORTED;
    2324     else
    2325         rc = VERR_VD_NOT_OPENED;
    2326 
    2327     LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
    2328     return rc;
    2329 }
    2330 
    2331 /** @copydoc VBOXHDDBACKEND::pfnSetModificationUuid */
    2332 static int qedSetModificationUuid(void *pBackendData, PCRTUUID pUuid)
    2333 {
    2334     LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
    2335     PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
    2336     int rc;
    2337 
    2338     AssertPtr(pImage);
    2339 
    2340     if (pImage)
    2341     {
    2342         if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    2343             rc = VERR_NOT_SUPPORTED;
    2344         else
    2345             rc = VERR_VD_IMAGE_READ_ONLY;
    2346     }
    2347     else
    2348         rc = VERR_VD_NOT_OPENED;
    2349 
    2350     LogFlowFunc(("returns %Rrc\n", rc));
    2351     return rc;
    2352 }
    2353 
    2354 /** @copydoc VBOXHDDBACKEND::pfnGetParentUuid */
    2355 static int qedGetParentUuid(void *pBackendData, PRTUUID pUuid)
    2356 {
    2357     LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
    2358     PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
    2359     int rc;
    2360 
    2361     AssertPtr(pImage);
    2362 
    2363     if (pImage)
    2364         rc = VERR_NOT_SUPPORTED;
    2365     else
    2366         rc = VERR_VD_NOT_OPENED;
    2367 
    2368     LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
    2369     return rc;
    2370 }
    2371 
    2372 /** @copydoc VBOXHDDBACKEND::pfnSetParentUuid */
    2373 static int qedSetParentUuid(void *pBackendData, PCRTUUID pUuid)
    2374 {
    2375     LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
    2376     PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
    2377     int rc;
    2378 
    2379     AssertPtr(pImage);
    2380 
    2381     if (pImage)
    2382     {
    2383         if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    2384             rc = VERR_NOT_SUPPORTED;
    2385         else
    2386             rc = VERR_VD_IMAGE_READ_ONLY;
    2387     }
    2388     else
    2389         rc = VERR_VD_NOT_OPENED;
    2390 
    2391     LogFlowFunc(("returns %Rrc\n", rc));
    2392     return rc;
    2393 }
    2394 
    2395 /** @copydoc VBOXHDDBACKEND::pfnGetParentModificationUuid */
    2396 static int qedGetParentModificationUuid(void *pBackendData, PRTUUID pUuid)
    2397 {
    2398     LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
    2399     PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
    2400     int rc;
    2401 
    2402     AssertPtr(pImage);
    2403 
    2404     if (pImage)
    2405         rc = VERR_NOT_SUPPORTED;
    2406     else
    2407         rc = VERR_VD_NOT_OPENED;
    2408 
    2409     LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
    2410     return rc;
    2411 }
    2412 
    2413 /** @copydoc VBOXHDDBACKEND::pfnSetParentModificationUuid */
    2414 static int qedSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid)
    2415 {
    2416     LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
    2417     PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
    2418     int rc;
    2419 
    2420     AssertPtr(pImage);
    2421 
    2422     if (pImage)
    2423     {
    2424         if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    2425             rc = VERR_NOT_SUPPORTED;
    2426         else
    2427             rc = VERR_VD_IMAGE_READ_ONLY;
    2428     }
    2429     else
    2430         rc = VERR_VD_NOT_OPENED;
    2431 
    2432     LogFlowFunc(("returns %Rrc\n", rc));
    2433     return rc;
    2434 }
    2435 
    2436 /** @copydoc VBOXHDDBACKEND::pfnDump */
    2437 static void qedDump(void *pBackendData)
    2438 {
    2439     PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
    2440 
    2441     AssertPtr(pImage);
    2442     if (pImage)
    2443     {
    2444         vdIfErrorMessage(pImage->pIfError, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n",
    2445                          pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors,
    2446                          pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors,
    2447                          pImage->cbSize / 512);
    2448     }
    2449 }
    2450 
    2451 /** @copydoc VBOXHDDBACKEND::pfnGetParentFilename */
    2452 static int qedGetParentFilename(void *pBackendData, char **ppszParentFilename)
    2453 {
    2454     int rc = VINF_SUCCESS;
    2455     PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
    2456 
    2457     AssertPtr(pImage);
    2458     if (pImage)
    2459         if (pImage->pszFilename)
    2460             *ppszParentFilename = RTStrDup(pImage->pszBackingFilename);
    2461         else
    2462             rc = VERR_NOT_SUPPORTED;
    2463     else
    2464         rc = VERR_VD_NOT_OPENED;
    2465 
    2466     LogFlowFunc(("returns %Rrc\n", rc));
    2467     return rc;
    2468 }
    2469 
    2470 /** @copydoc VBOXHDDBACKEND::pfnSetParentFilename */
    2471 static int qedSetParentFilename(void *pBackendData, const char *pszParentFilename)
    2472 {
    2473     int rc = VINF_SUCCESS;
    2474     PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
    2475 
    2476     AssertPtr(pImage);
    2477     if (pImage)
    2478     {
    2479         if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    2480             rc = VERR_VD_IMAGE_READ_ONLY;
    2481         else if (   pImage->pszBackingFilename
    2482                  && (strlen(pszParentFilename) > pImage->cbBackingFilename))
    2483             rc = VERR_NOT_SUPPORTED; /* The new filename is longer than the old one. */
    2484         else
    2485         {
    2486             if (pImage->pszBackingFilename)
    2487                 RTStrFree(pImage->pszBackingFilename);
    2488             pImage->pszBackingFilename = RTStrDup(pszParentFilename);
    2489             if (!pImage->pszBackingFilename)
    2490                 rc = VERR_NO_MEMORY;
    2491             else
    2492             {
    2493                 if (!pImage->offBackingFilename)
    2494                 {
    2495                     /* Allocate new cluster. */
    2496                     uint64_t offData = qedClusterAllocate(pImage, 1);
    2497 
    2498                     Assert((offData & UINT32_MAX) == offData);
    2499                     pImage->offBackingFilename = (uint32_t)offData;
    2500                     pImage->cbBackingFilename  = strlen(pszParentFilename);
    2501                     rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage,
    2502                                               offData + pImage->cbCluster);
    2503                 }
    2504 
    2505                 if (RT_SUCCESS(rc))
    2506                     rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage,
    2507                                                 pImage->offBackingFilename,
    2508                                                 pImage->pszBackingFilename,
    2509                                                 strlen(pImage->pszBackingFilename));
    2510             }
    2511         }
    2512     }
    2513     else
    2514         rc = VERR_VD_NOT_OPENED;
    2515 
    2516     LogFlowFunc(("returns %Rrc\n", rc));
    2517     return rc;
    2518 }
    2519 
    2520 static int qedAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbToRead,
    2521                         PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
    2522 {
    2523     LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n",
    2524                  pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead));
    2525     PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
    2526     uint32_t offCluster = 0;
    2527     uint32_t idxL1      = 0;
    2528     uint32_t idxL2      = 0;
    2529     uint64_t offFile    = 0;
    2530     int rc;
    2531 
    2532     AssertPtr(pImage);
    2533     Assert(uOffset % 512 == 0);
    2534     Assert(cbToRead % 512 == 0);
    2535 
    2536     if (!VALID_PTR(pIoCtx) || !cbToRead)
    2537     {
    2538         rc = VERR_INVALID_PARAMETER;
    2539         goto out;
    2540     }
    2541 
    2542     if (   uOffset + cbToRead > pImage->cbSize
    2543         || cbToRead == 0)
    2544     {
    2545         rc = VERR_INVALID_PARAMETER;
    2546         goto out;
    2547     }
    2548 
    2549     qedConvertLogicalOffset(pImage, uOffset, &idxL1, &idxL2, &offCluster);
    2550 
    2551     /* Clip read size to remain in the cluster. */
    2552     cbToRead = RT_MIN(cbToRead, pImage->cbCluster - offCluster);
    2553 
    2554     /* Get offset in image. */
    2555     rc = qedConvertToImageOffsetAsync(pImage, pIoCtx, idxL1, idxL2, offCluster,
    2556                                       &offFile);
     1794    rc = qedConvertToImageOffset(pImage, pIoCtx, idxL1, idxL2, offCluster, &offFile);
    25571795    if (RT_SUCCESS(rc))
    25581796        rc = vdIfIoIntFileReadUser(pImage->pIfIo, pImage->pStorage, offFile,
     
    25701808}
    25711809
    2572 static int qedAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite,
    2573                          PVDIOCTX pIoCtx,
    2574                          size_t *pcbWriteProcess, size_t *pcbPreRead,
    2575                          size_t *pcbPostRead, unsigned fWrite)
     1810static int qedWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite,
     1811                    PVDIOCTX pIoCtx, size_t *pcbWriteProcess, size_t *pcbPreRead,
     1812                    size_t *pcbPostRead, unsigned fWrite)
    25761813{
    25771814    LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n",
     
    26151852
    26161853    /* Get offset in image. */
    2617     rc = qedConvertToImageOffsetAsync(pImage, pIoCtx, idxL1, idxL2, offCluster,
    2618                                       &offImage);
     1854    rc = qedConvertToImageOffset(pImage, pIoCtx, idxL1, idxL2, offCluster, &offImage);
    26191855    if (RT_SUCCESS(rc))
    26201856        rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pImage->pStorage,
     
    27551991}
    27561992
    2757 static int qedAsyncFlush(void *pBackendData, PVDIOCTX pIoCtx)
     1993static int qedFlush(void *pBackendData, PVDIOCTX pIoCtx)
    27581994{
    27591995    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     
    27672003    else
    27682004        rc = VERR_INVALID_PARAMETER;
     2005
     2006    LogFlowFunc(("returns %Rrc\n", rc));
     2007    return rc;
     2008}
     2009
     2010/** @copydoc VBOXHDDBACKEND::pfnGetVersion */
     2011static unsigned qedGetVersion(void *pBackendData)
     2012{
     2013    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     2014    PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
     2015
     2016    AssertPtr(pImage);
     2017
     2018    if (pImage)
     2019        return 1;
     2020    else
     2021        return 0;
     2022}
     2023
     2024/** @copydoc VBOXHDDBACKEND::pfnGetSize */
     2025static uint64_t qedGetSize(void *pBackendData)
     2026{
     2027    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     2028    PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
     2029    uint64_t cb = 0;
     2030
     2031    AssertPtr(pImage);
     2032
     2033    if (pImage && pImage->pStorage)
     2034        cb = pImage->cbSize;
     2035
     2036    LogFlowFunc(("returns %llu\n", cb));
     2037    return cb;
     2038}
     2039
     2040/** @copydoc VBOXHDDBACKEND::pfnGetFileSize */
     2041static uint64_t qedGetFileSize(void *pBackendData)
     2042{
     2043    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     2044    PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
     2045    uint64_t cb = 0;
     2046
     2047    AssertPtr(pImage);
     2048
     2049    if (pImage)
     2050    {
     2051        uint64_t cbFile;
     2052        if (pImage->pStorage)
     2053        {
     2054            int rc = vdIfIoIntFileGetSize(pImage->pIfIo, pImage->pStorage, &cbFile);
     2055            if (RT_SUCCESS(rc))
     2056                cb += cbFile;
     2057        }
     2058    }
     2059
     2060    LogFlowFunc(("returns %lld\n", cb));
     2061    return cb;
     2062}
     2063
     2064/** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */
     2065static int qedGetPCHSGeometry(void *pBackendData,
     2066                              PVDGEOMETRY pPCHSGeometry)
     2067{
     2068    LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry));
     2069    PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
     2070    int rc;
     2071
     2072    AssertPtr(pImage);
     2073
     2074    if (pImage)
     2075    {
     2076        if (pImage->PCHSGeometry.cCylinders)
     2077        {
     2078            *pPCHSGeometry = pImage->PCHSGeometry;
     2079            rc = VINF_SUCCESS;
     2080        }
     2081        else
     2082            rc = VERR_VD_GEOMETRY_NOT_SET;
     2083    }
     2084    else
     2085        rc = VERR_VD_NOT_OPENED;
     2086
     2087    LogFlowFunc(("returns %Rrc (PCHS=%u/%u/%u)\n", rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
     2088    return rc;
     2089}
     2090
     2091/** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */
     2092static int qedSetPCHSGeometry(void *pBackendData,
     2093                              PCVDGEOMETRY pPCHSGeometry)
     2094{
     2095    LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
     2096    PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
     2097    int rc;
     2098
     2099    AssertPtr(pImage);
     2100
     2101    if (pImage)
     2102    {
     2103        if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     2104        {
     2105            rc = VERR_VD_IMAGE_READ_ONLY;
     2106            goto out;
     2107        }
     2108
     2109        pImage->PCHSGeometry = *pPCHSGeometry;
     2110        rc = VINF_SUCCESS;
     2111    }
     2112    else
     2113        rc = VERR_VD_NOT_OPENED;
     2114
     2115out:
     2116    LogFlowFunc(("returns %Rrc\n", rc));
     2117    return rc;
     2118}
     2119
     2120/** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */
     2121static int qedGetLCHSGeometry(void *pBackendData,
     2122                              PVDGEOMETRY pLCHSGeometry)
     2123{
     2124     LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry));
     2125    PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
     2126    int rc;
     2127
     2128    AssertPtr(pImage);
     2129
     2130    if (pImage)
     2131    {
     2132        if (pImage->LCHSGeometry.cCylinders)
     2133        {
     2134            *pLCHSGeometry = pImage->LCHSGeometry;
     2135            rc = VINF_SUCCESS;
     2136        }
     2137        else
     2138            rc = VERR_VD_GEOMETRY_NOT_SET;
     2139    }
     2140    else
     2141        rc = VERR_VD_NOT_OPENED;
     2142
     2143    LogFlowFunc(("returns %Rrc (LCHS=%u/%u/%u)\n", rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
     2144    return rc;
     2145}
     2146
     2147/** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */
     2148static int qedSetLCHSGeometry(void *pBackendData,
     2149                               PCVDGEOMETRY pLCHSGeometry)
     2150{
     2151    LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
     2152    PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
     2153    int rc;
     2154
     2155    AssertPtr(pImage);
     2156
     2157    if (pImage)
     2158    {
     2159        if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     2160        {
     2161            rc = VERR_VD_IMAGE_READ_ONLY;
     2162            goto out;
     2163        }
     2164
     2165        pImage->LCHSGeometry = *pLCHSGeometry;
     2166        rc = VINF_SUCCESS;
     2167    }
     2168    else
     2169        rc = VERR_VD_NOT_OPENED;
     2170
     2171out:
     2172    LogFlowFunc(("returns %Rrc\n", rc));
     2173    return rc;
     2174}
     2175
     2176/** @copydoc VBOXHDDBACKEND::pfnGetImageFlags */
     2177static unsigned qedGetImageFlags(void *pBackendData)
     2178{
     2179    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     2180    PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
     2181    unsigned uImageFlags;
     2182
     2183    AssertPtr(pImage);
     2184
     2185    if (pImage)
     2186        uImageFlags = pImage->uImageFlags;
     2187    else
     2188        uImageFlags = 0;
     2189
     2190    LogFlowFunc(("returns %#x\n", uImageFlags));
     2191    return uImageFlags;
     2192}
     2193
     2194/** @copydoc VBOXHDDBACKEND::pfnGetOpenFlags */
     2195static unsigned qedGetOpenFlags(void *pBackendData)
     2196{
     2197    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     2198    PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
     2199    unsigned uOpenFlags;
     2200
     2201    AssertPtr(pImage);
     2202
     2203    if (pImage)
     2204        uOpenFlags = pImage->uOpenFlags;
     2205    else
     2206        uOpenFlags = 0;
     2207
     2208    LogFlowFunc(("returns %#x\n", uOpenFlags));
     2209    return uOpenFlags;
     2210}
     2211
     2212/** @copydoc VBOXHDDBACKEND::pfnSetOpenFlags */
     2213static int qedSetOpenFlags(void *pBackendData, unsigned uOpenFlags)
     2214{
     2215    LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags));
     2216    PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
     2217    int rc;
     2218
     2219    /* Image must be opened and the new flags must be valid. */
     2220    if (!pImage || (uOpenFlags & ~(  VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO
     2221                                   | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS)))
     2222    {
     2223        rc = VERR_INVALID_PARAMETER;
     2224        goto out;
     2225    }
     2226
     2227    /* Implement this operation via reopening the image. */
     2228    rc = qedFreeImage(pImage, false);
     2229    if (RT_FAILURE(rc))
     2230        goto out;
     2231    rc = qedOpenImage(pImage, uOpenFlags);
     2232
     2233out:
     2234    LogFlowFunc(("returns %Rrc\n", rc));
     2235    return rc;
     2236}
     2237
     2238/** @copydoc VBOXHDDBACKEND::pfnGetComment */
     2239static int qedGetComment(void *pBackendData, char *pszComment,
     2240                          size_t cbComment)
     2241{
     2242    LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment));
     2243    PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
     2244    int rc;
     2245
     2246    AssertPtr(pImage);
     2247
     2248    if (pImage)
     2249        rc = VERR_NOT_SUPPORTED;
     2250    else
     2251        rc = VERR_VD_NOT_OPENED;
     2252
     2253    LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment));
     2254    return rc;
     2255}
     2256
     2257/** @copydoc VBOXHDDBACKEND::pfnSetComment */
     2258static int qedSetComment(void *pBackendData, const char *pszComment)
     2259{
     2260    LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment));
     2261    PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
     2262    int rc;
     2263
     2264    AssertPtr(pImage);
     2265
     2266    if (pImage)
     2267    {
     2268        if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     2269            rc = VERR_VD_IMAGE_READ_ONLY;
     2270        else
     2271            rc = VERR_NOT_SUPPORTED;
     2272    }
     2273    else
     2274        rc = VERR_VD_NOT_OPENED;
     2275
     2276    LogFlowFunc(("returns %Rrc\n", rc));
     2277    return rc;
     2278}
     2279
     2280/** @copydoc VBOXHDDBACKEND::pfnGetUuid */
     2281static int qedGetUuid(void *pBackendData, PRTUUID pUuid)
     2282{
     2283    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
     2284    PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
     2285    int rc;
     2286
     2287    AssertPtr(pImage);
     2288
     2289    if (pImage)
     2290        rc = VERR_NOT_SUPPORTED;
     2291    else
     2292        rc = VERR_VD_NOT_OPENED;
     2293
     2294    LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
     2295    return rc;
     2296}
     2297
     2298/** @copydoc VBOXHDDBACKEND::pfnSetUuid */
     2299static int qedSetUuid(void *pBackendData, PCRTUUID pUuid)
     2300{
     2301    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
     2302    PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
     2303    int rc;
     2304
     2305    LogFlowFunc(("%RTuuid\n", pUuid));
     2306    AssertPtr(pImage);
     2307
     2308    if (pImage)
     2309    {
     2310        if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     2311            rc = VERR_NOT_SUPPORTED;
     2312        else
     2313            rc = VERR_VD_IMAGE_READ_ONLY;
     2314    }
     2315    else
     2316        rc = VERR_VD_NOT_OPENED;
     2317
     2318    LogFlowFunc(("returns %Rrc\n", rc));
     2319    return rc;
     2320}
     2321
     2322/** @copydoc VBOXHDDBACKEND::pfnGetModificationUuid */
     2323static int qedGetModificationUuid(void *pBackendData, PRTUUID pUuid)
     2324{
     2325    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
     2326    PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
     2327    int rc;
     2328
     2329    AssertPtr(pImage);
     2330
     2331    if (pImage)
     2332        rc = VERR_NOT_SUPPORTED;
     2333    else
     2334        rc = VERR_VD_NOT_OPENED;
     2335
     2336    LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
     2337    return rc;
     2338}
     2339
     2340/** @copydoc VBOXHDDBACKEND::pfnSetModificationUuid */
     2341static int qedSetModificationUuid(void *pBackendData, PCRTUUID pUuid)
     2342{
     2343    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
     2344    PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
     2345    int rc;
     2346
     2347    AssertPtr(pImage);
     2348
     2349    if (pImage)
     2350    {
     2351        if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     2352            rc = VERR_NOT_SUPPORTED;
     2353        else
     2354            rc = VERR_VD_IMAGE_READ_ONLY;
     2355    }
     2356    else
     2357        rc = VERR_VD_NOT_OPENED;
     2358
     2359    LogFlowFunc(("returns %Rrc\n", rc));
     2360    return rc;
     2361}
     2362
     2363/** @copydoc VBOXHDDBACKEND::pfnGetParentUuid */
     2364static int qedGetParentUuid(void *pBackendData, PRTUUID pUuid)
     2365{
     2366    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
     2367    PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
     2368    int rc;
     2369
     2370    AssertPtr(pImage);
     2371
     2372    if (pImage)
     2373        rc = VERR_NOT_SUPPORTED;
     2374    else
     2375        rc = VERR_VD_NOT_OPENED;
     2376
     2377    LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
     2378    return rc;
     2379}
     2380
     2381/** @copydoc VBOXHDDBACKEND::pfnSetParentUuid */
     2382static int qedSetParentUuid(void *pBackendData, PCRTUUID pUuid)
     2383{
     2384    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
     2385    PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
     2386    int rc;
     2387
     2388    AssertPtr(pImage);
     2389
     2390    if (pImage)
     2391    {
     2392        if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     2393            rc = VERR_NOT_SUPPORTED;
     2394        else
     2395            rc = VERR_VD_IMAGE_READ_ONLY;
     2396    }
     2397    else
     2398        rc = VERR_VD_NOT_OPENED;
     2399
     2400    LogFlowFunc(("returns %Rrc\n", rc));
     2401    return rc;
     2402}
     2403
     2404/** @copydoc VBOXHDDBACKEND::pfnGetParentModificationUuid */
     2405static int qedGetParentModificationUuid(void *pBackendData, PRTUUID pUuid)
     2406{
     2407    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
     2408    PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
     2409    int rc;
     2410
     2411    AssertPtr(pImage);
     2412
     2413    if (pImage)
     2414        rc = VERR_NOT_SUPPORTED;
     2415    else
     2416        rc = VERR_VD_NOT_OPENED;
     2417
     2418    LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
     2419    return rc;
     2420}
     2421
     2422/** @copydoc VBOXHDDBACKEND::pfnSetParentModificationUuid */
     2423static int qedSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid)
     2424{
     2425    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
     2426    PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
     2427    int rc;
     2428
     2429    AssertPtr(pImage);
     2430
     2431    if (pImage)
     2432    {
     2433        if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     2434            rc = VERR_NOT_SUPPORTED;
     2435        else
     2436            rc = VERR_VD_IMAGE_READ_ONLY;
     2437    }
     2438    else
     2439        rc = VERR_VD_NOT_OPENED;
     2440
     2441    LogFlowFunc(("returns %Rrc\n", rc));
     2442    return rc;
     2443}
     2444
     2445/** @copydoc VBOXHDDBACKEND::pfnDump */
     2446static void qedDump(void *pBackendData)
     2447{
     2448    PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
     2449
     2450    AssertPtr(pImage);
     2451    if (pImage)
     2452    {
     2453        vdIfErrorMessage(pImage->pIfError, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n",
     2454                         pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors,
     2455                         pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors,
     2456                         pImage->cbSize / 512);
     2457    }
     2458}
     2459
     2460/** @copydoc VBOXHDDBACKEND::pfnGetParentFilename */
     2461static int qedGetParentFilename(void *pBackendData, char **ppszParentFilename)
     2462{
     2463    int rc = VINF_SUCCESS;
     2464    PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
     2465
     2466    AssertPtr(pImage);
     2467    if (pImage)
     2468        if (pImage->pszFilename)
     2469            *ppszParentFilename = RTStrDup(pImage->pszBackingFilename);
     2470        else
     2471            rc = VERR_NOT_SUPPORTED;
     2472    else
     2473        rc = VERR_VD_NOT_OPENED;
     2474
     2475    LogFlowFunc(("returns %Rrc\n", rc));
     2476    return rc;
     2477}
     2478
     2479/** @copydoc VBOXHDDBACKEND::pfnSetParentFilename */
     2480static int qedSetParentFilename(void *pBackendData, const char *pszParentFilename)
     2481{
     2482    int rc = VINF_SUCCESS;
     2483    PQEDIMAGE pImage = (PQEDIMAGE)pBackendData;
     2484
     2485    AssertPtr(pImage);
     2486    if (pImage)
     2487    {
     2488        if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     2489            rc = VERR_VD_IMAGE_READ_ONLY;
     2490        else if (   pImage->pszBackingFilename
     2491                 && (strlen(pszParentFilename) > pImage->cbBackingFilename))
     2492            rc = VERR_NOT_SUPPORTED; /* The new filename is longer than the old one. */
     2493        else
     2494        {
     2495            if (pImage->pszBackingFilename)
     2496                RTStrFree(pImage->pszBackingFilename);
     2497            pImage->pszBackingFilename = RTStrDup(pszParentFilename);
     2498            if (!pImage->pszBackingFilename)
     2499                rc = VERR_NO_MEMORY;
     2500            else
     2501            {
     2502                if (!pImage->offBackingFilename)
     2503                {
     2504                    /* Allocate new cluster. */
     2505                    uint64_t offData = qedClusterAllocate(pImage, 1);
     2506
     2507                    Assert((offData & UINT32_MAX) == offData);
     2508                    pImage->offBackingFilename = (uint32_t)offData;
     2509                    pImage->cbBackingFilename  = strlen(pszParentFilename);
     2510                    rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage,
     2511                                              offData + pImage->cbCluster);
     2512                }
     2513
     2514                if (RT_SUCCESS(rc))
     2515                    rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage,
     2516                                                pImage->offBackingFilename,
     2517                                                pImage->pszBackingFilename,
     2518                                                strlen(pImage->pszBackingFilename));
     2519            }
     2520        }
     2521    }
     2522    else
     2523        rc = VERR_VD_NOT_OPENED;
    27692524
    27702525    LogFlowFunc(("returns %Rrc\n", rc));
     
    28542609    /* pfnFlush */
    28552610    qedFlush,
     2611    /* pfnDiscard */
     2612    NULL,
    28562613    /* pfnGetVersion */
    28572614    qedGetVersion,
     
    29062663    /* pfnSetParentFilename */
    29072664    qedSetParentFilename,
    2908     /* pfnAsyncRead */
    2909     qedAsyncRead,
    2910     /* pfnAsyncWrite */
    2911     qedAsyncWrite,
    2912     /* pfnAsyncFlush */
    2913     qedAsyncFlush,
    29142665    /* pfnComposeLocation */
    29152666    genericFileComposeLocation,
     
    29202671    /* pfnResize */
    29212672    qedResize,
    2922     /* pfnDiscard */
    2923     NULL,
    2924     /* pfnAsyncDiscard */
    2925     NULL,
    29262673    /* pfnRepair */
    29272674    NULL
  • trunk/src/VBox/Storage/RAW.cpp

    r44233 r44252  
    602602
    603603/** @copydoc VBOXHDDBACKEND::pfnRead */
    604 static int rawRead(void *pBackendData, uint64_t uOffset, void *pvBuf,
    605                    size_t cbToRead, size_t *pcbActuallyRead)
    606 {
    607     LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n", pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead));
    608     PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
    609     int rc;
    610 
    611     AssertPtr(pImage);
    612     Assert(uOffset % 512 == 0);
    613     Assert(cbToRead % 512 == 0);
    614 
    615     if (   uOffset + cbToRead > pImage->cbSize
    616         || cbToRead == 0)
    617     {
    618         rc = VERR_INVALID_PARAMETER;
    619         goto out;
    620     }
    621 
    622     /* For sequential access do not allow to go back. */
    623     if (   pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL
    624         && uOffset < pImage->offAccess)
    625     {
    626         rc = VERR_INVALID_PARAMETER;
    627         goto out;
    628     }
    629 
    630     rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, uOffset, pvBuf,
    631                                cbToRead);
    632     pImage->offAccess = uOffset + cbToRead;
    633     if (pcbActuallyRead)
    634         *pcbActuallyRead = cbToRead;
    635 
    636 out:
    637     LogFlowFunc(("returns %Rrc\n", rc));
     604static int rawRead(void *pBackendData, uint64_t uOffset, size_t cbRead,
     605                   PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
     606{
     607    int rc = VINF_SUCCESS;
     608    PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
     609
     610    rc = vdIfIoIntFileReadUser(pImage->pIfIo, pImage->pStorage, uOffset,
     611                               pIoCtx, cbRead);
     612    if (RT_SUCCESS(rc))
     613        *pcbActuallyRead = cbRead;
     614
    638615    return rc;
    639616}
    640617
    641618/** @copydoc VBOXHDDBACKEND::pfnWrite */
    642 static int rawWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf,
    643                     size_t cbToWrite, size_t *pcbWriteProcess,
    644                     size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite)
    645 {
    646     LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n", pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));
    647     PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
    648     int rc;
    649 
    650     AssertPtr(pImage);
    651     Assert(uOffset % 512 == 0);
    652     Assert(cbToWrite % 512 == 0);
    653 
    654     if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    655     {
    656         rc = VERR_VD_IMAGE_READ_ONLY;
    657         goto out;
    658     }
    659 
    660     if (   uOffset + cbToWrite > pImage->cbSize
    661         || cbToWrite == 0)
    662     {
    663         rc = VERR_INVALID_PARAMETER;
    664         goto out;
    665     }
    666 
    667     /* For sequential access do not allow to go back. */
    668     if (   pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL
    669         && uOffset < pImage->offAccess)
    670     {
    671         rc = VERR_INVALID_PARAMETER;
    672         goto out;
    673     }
    674 
    675     rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, uOffset, pvBuf,
    676                                 cbToWrite);
    677     pImage->offAccess = uOffset + cbToWrite;
    678     if (pcbWriteProcess)
    679         *pcbWriteProcess = cbToWrite;
    680 
    681 out:
    682     LogFlowFunc(("returns %Rrc\n", rc));
     619static int rawWrite(void *pBackendData, uint64_t uOffset, size_t cbWrite,
     620                    PVDIOCTX pIoCtx, size_t *pcbWriteProcess, size_t *pcbPreRead,
     621                    size_t *pcbPostRead, unsigned fWrite)
     622{
     623    int rc = VINF_SUCCESS;
     624    PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
     625
     626    rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pImage->pStorage, uOffset,
     627                                pIoCtx, cbWrite, NULL, NULL);
     628    if (RT_SUCCESS(rc))
     629    {
     630        *pcbWriteProcess = cbWrite;
     631        *pcbPostRead = 0;
     632        *pcbPreRead  = 0;
     633    }
     634
    683635    return rc;
    684636}
    685637
    686638/** @copydoc VBOXHDDBACKEND::pfnFlush */
    687 static int rawFlush(void *pBackendData)
    688 {
    689     LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    690     PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
    691     int rc;
    692 
    693     rc = rawFlushImage(pImage);
    694     LogFlowFunc(("returns %Rrc\n", rc));
     639static int rawFlush(void *pBackendData, PVDIOCTX pIoCtx)
     640{
     641    int rc = VINF_SUCCESS;
     642    PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
     643
     644    if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     645        rc = vdIfIoIntFileFlush(pImage->pIfIo, pImage->pStorage, pIoCtx,
     646                                NULL, NULL);
     647
    695648    return rc;
    696649}
     
    11471100}
    11481101
    1149 /** @copydoc VBOXHDDBACKEND::pfnAsyncRead */
    1150 static int rawAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbRead,
    1151                         PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
    1152 {
    1153     int rc = VINF_SUCCESS;
    1154     PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
    1155 
    1156     rc = vdIfIoIntFileReadUser(pImage->pIfIo, pImage->pStorage, uOffset,
    1157                                pIoCtx, cbRead);
    1158     if (RT_SUCCESS(rc))
    1159         *pcbActuallyRead = cbRead;
    1160 
    1161     return rc;
    1162 }
    1163 
    1164 /** @copydoc VBOXHDDBACKEND::pfnAsyncWrite */
    1165 static int rawAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbWrite,
    1166                          PVDIOCTX pIoCtx,
    1167                          size_t *pcbWriteProcess, size_t *pcbPreRead,
    1168                          size_t *pcbPostRead, unsigned fWrite)
    1169 {
    1170     int rc = VINF_SUCCESS;
    1171     PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
    1172 
    1173     rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pImage->pStorage, uOffset,
    1174                                 pIoCtx, cbWrite, NULL, NULL);
    1175     if (RT_SUCCESS(rc))
    1176     {
    1177         *pcbWriteProcess = cbWrite;
    1178         *pcbPostRead = 0;
    1179         *pcbPreRead  = 0;
    1180     }
    1181 
    1182     return rc;
    1183 }
    1184 
    1185 /** @copydoc VBOXHDDBACKEND::pfnAsyncFlush */
    1186 static int rawAsyncFlush(void *pBackendData, PVDIOCTX pIoCtx)
    1187 {
    1188     int rc = VINF_SUCCESS;
    1189     PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
    1190 
    1191     if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    1192         rc = vdIfIoIntFileFlush(pImage->pIfIo, pImage->pStorage, pIoCtx,
    1193                                 NULL, NULL);
    1194 
    1195     return rc;
    1196 }
    11971102
    11981103
     
    12271132    /* pfnFlush */
    12281133    rawFlush,
     1134    /* pfnDiscard */
     1135    NULL,
    12291136    /* pfnGetVersion */
    12301137    rawGetVersion,
     
    12791186    /* pfnSetParentFilename */
    12801187    NULL,
    1281     /* pfnAsyncRead */
    1282     rawAsyncRead,
    1283     /* pfnAsyncWrite */
    1284     rawAsyncWrite,
    1285     /* pfnAsyncFlush */
    1286     rawAsyncFlush,
    12871188    /* pfnComposeLocation */
    12881189    genericFileComposeLocation,
     
    12931194    /* pfnResize */
    12941195    NULL,
    1295     /* pfnDiscard */
    1296     NULL,
    1297     /* pfnAsyncDiscard */
    1298     NULL,
    12991196    /* pfnRepair */
    13001197    NULL
  • trunk/src/VBox/Storage/VD.cpp

    r44242 r44252  
    913913     * If the block is not allocated read from override chain if present.
    914914     */
    915     rc = pImage->Backend->pfnAsyncRead(pImage->pBackendData,
     915    rc = pImage->Backend->pfnRead(pImage->pBackendData,
    916916                                       uOffset, cbThisRead, &IoCtx,
    917917                                       &cbThisRead);
     
    923923             pCurrImage = pCurrImage->pPrev)
    924924        {
    925             rc = pCurrImage->Backend->pfnAsyncRead(pCurrImage->pBackendData,
     925            rc = pCurrImage->Backend->pfnRead(pCurrImage->pBackendData,
    926926                                                   uOffset, cbThisRead, &IoCtx,
    927927                                                   &cbThisRead);
     
    10131013             * If the block is not allocated read from override chain if present.
    10141014             */
    1015             rc = pImage->Backend->pfnAsyncRead(pImage->pBackendData,
     1015            rc = pImage->Backend->pfnRead(pImage->pBackendData,
    10161016                                               uOffset, cbThisRead, &IoCtx,
    10171017                                               &cbThisRead);
     
    10261026                     pCurrImage = pCurrImage->pPrev)
    10271027                {
    1028                     rc = pCurrImage->Backend->pfnAsyncRead(pCurrImage->pBackendData,
     1028                    rc = pCurrImage->Backend->pfnRead(pCurrImage->pBackendData,
    10291029                                                           uOffset, cbThisRead,
    10301030                                                           &IoCtx, &cbThisRead);
     
    11611161                vdIoCtxInit(&IoCtx, pDisk, VDIOCTXTXDIR_DISCARD, 0, 0, NULL,
    11621162                            NULL, NULL, NULL, VDIOCTX_FLAGS_SYNC);
    1163                 rc = pDisk->pLast->Backend->pfnAsyncDiscard(pDisk->pLast->pBackendData,
     1163                rc = pDisk->pLast->Backend->pfnDiscard(pDisk->pLast->pBackendData,
    11641164                                                            &IoCtx, offStart, cbThis, NULL,
    11651165                                                            NULL, &cbThis, NULL,
     
    12561256            vdIoCtxInit(&IoCtx, pDisk, VDIOCTXTXDIR_DISCARD, 0, 0, NULL,
    12571257                        NULL, NULL, NULL, VDIOCTX_FLAGS_SYNC);
    1258             rc = pDisk->pLast->Backend->pfnAsyncDiscard(pDisk->pLast->pBackendData,
     1258            rc = pDisk->pLast->Backend->pfnDiscard(pDisk->pLast->pBackendData,
    12591259                                                        &IoCtx, offStart,
    12601260                                                        cbThisDiscard, &cbPreAllocated,
     
    13131313                vdIoCtxInit(&IoCtx, pDisk, VDIOCTXTXDIR_DISCARD, 0, 0, NULL,
    13141314                            NULL, NULL, NULL, VDIOCTX_FLAGS_SYNC);
    1315                 rc = pDisk->pLast->Backend->pfnAsyncDiscard(pDisk->pLast->pBackendData,
     1315                rc = pDisk->pLast->Backend->pfnDiscard(pDisk->pLast->pBackendData,
    13161316                                                            &IoCtx, pBlock->Core.Key,
    13171317                                                            pBlock->cbDiscard, &cbPreAllocated,
     
    16501650}
    16511651
    1652 static size_t vdIoCtxCopyTo(PVDIOCTX pIoCtx, uint8_t *pbData, size_t cbData)
     1652static size_t vdIoCtxCopyTo(PVDIOCTX pIoCtx, const uint8_t *pbData, size_t cbData)
     1653{
     1654    return RTSgBufCopyFromBuf(&pIoCtx->Req.Io.SgBuf, pbData, cbData);
     1655}
     1656
     1657static size_t vdIoCtxCopyFrom(PVDIOCTX pIoCtx, uint8_t *pbData, size_t cbData)
    16531658{
    16541659    return RTSgBufCopyToBuf(&pIoCtx->Req.Io.SgBuf, pbData, cbData);
    1655 }
    1656 
    1657 
    1658 static size_t vdIoCtxCopyFrom(PVDIOCTX pIoCtx, uint8_t *pbData, size_t cbData)
    1659 {
    1660     return RTSgBufCopyFromBuf(&pIoCtx->Req.Io.SgBuf, pbData, cbData);
    16611660}
    16621661
     
    20542053         * If the block is not allocated read from override chain if present.
    20552054         */
    2056         rc = pCurrImage->Backend->pfnAsyncRead(pCurrImage->pBackendData,
     2055        rc = pCurrImage->Backend->pfnRead(pCurrImage->pBackendData,
    20572056                                               uOffset, cbThisRead,
    20582057                                               pIoCtx, &cbThisRead);
     
    20642063            {
    20652064                pCurrImage =  pCurrImage->pPrev;
    2066                 rc = pCurrImage->Backend->pfnAsyncRead(pCurrImage->pBackendData,
     2065                rc = pCurrImage->Backend->pfnRead(pCurrImage->pBackendData,
    20672066                                                       uOffset, cbThisRead,
    20682067                                                       pIoCtx, &cbThisRead);
     
    21612160            vdIoCtxInit(&IoCtx, pDisk, VDIOCTXTXDIR_FLUSH, 0, 0, NULL,
    21622161                        NULL, NULL, NULL, VDIOCTX_FLAGS_SYNC);
    2163             pDisk->pLast->Backend->pfnAsyncFlush(pDisk->pLast->pBackendData, &IoCtx);
     2162            pDisk->pLast->Backend->pfnFlush(pDisk->pLast->pBackendData, &IoCtx);
    21642163        }
    21652164    }
     
    22492248    vdIoCtxInit(&IoCtx, pDisk, VDIOCTXTXDIR_WRITE, 0, 0, NULL,
    22502249                &SgBuf, NULL, NULL, VDIOCTX_FLAGS_SYNC);
    2251     rc = pImage->Backend->pfnAsyncWrite(pImage->pBackendData, uOffset - cbPreRead,
     2250    rc = pImage->Backend->pfnWrite(pImage->pBackendData, uOffset - cbPreRead,
    22522251                                        cbPreRead + cbThisWrite + cbPostRead,
    22532252                                        &IoCtx, NULL, &cbPreRead, &cbPostRead, 0);
     
    23392338    vdIoCtxInit(&IoCtx, pDisk, VDIOCTXTXDIR_WRITE, 0, 0, NULL,
    23402339                &SgBuf, NULL, NULL, VDIOCTX_FLAGS_SYNC);
    2341     rc = pImage->Backend->pfnAsyncWrite(pImage->pBackendData, uOffset - cbPreRead,
     2340    rc = pImage->Backend->pfnWrite(pImage->pBackendData, uOffset - cbPreRead,
    23422341                                        cbPreRead + cbThisWrite + cbPostRead,
    23432342                                        &IoCtx, NULL, &cbPreRead, &cbPostRead, 0);
     
    23872386        vdIoCtxInit(&IoCtx, pDisk, VDIOCTXTXDIR_WRITE, 0, 0, NULL,
    23882387                    &SgBuf, NULL, NULL, VDIOCTX_FLAGS_SYNC);
    2389         rc = pImage->Backend->pfnAsyncWrite(pImage->pBackendData, uOffsetCur, cbThisWrite,
     2388        rc = pImage->Backend->pfnWrite(pImage->pBackendData, uOffsetCur, cbThisWrite,
    23902389                                            &IoCtx, &cbThisWrite, &cbPreRead,
    23912390                                            &cbPostRead, fWrite);
     
    25012500
    25022501            /* Read the source data. */
    2503             rc = pImageFrom->Backend->pfnAsyncRead(pImageFrom->pBackendData,
     2502            rc = pImageFrom->Backend->pfnRead(pImageFrom->pBackendData,
    25042503                                                   uOffset, cbThisRead, &IoCtx,
    25052504                                                   &cbThisRead);
     
    25142513                     pCurrImage = pCurrImage->pPrev)
    25152514                {
    2516                     rc = pCurrImage->Backend->pfnAsyncRead(pCurrImage->pBackendData,
     2515                    rc = pCurrImage->Backend->pfnRead(pCurrImage->pBackendData,
    25172516                                                           uOffset, cbThisRead,
    25182517                                                           &IoCtx, &cbThisRead);
     
    26072606    PVDIMAGE pImage = pIoCtx->Req.Io.pImageCur;
    26082607
    2609     rc = pImage->Backend->pfnAsyncFlush(pImage->pBackendData, pIoCtx);
     2608    rc = pImage->Backend->pfnFlush(pImage->pBackendData, pIoCtx);
    26102609    if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
    26112610        rc = VINF_SUCCESS;
     
    27362735        /* Write the full block to the virtual disk. */
    27372736        vdIoCtxChildReset(pIoCtxDst);
    2738         rc = pImage->Backend->pfnAsyncWrite(pImage->pBackendData,
     2737        rc = pImage->Backend->pfnWrite(pImage->pBackendData,
    27392738                                            uOffset - cbPreRead,
    27402739                                            cbPreRead + cbThisWrite + cbPostRead,
     
    27672766
    27682767    LogFlowFunc(("pIoCtx=%#p\n", pIoCtx));
    2769     rc = pImage->Backend->pfnAsyncWrite(pImage->pBackendData,
     2768    rc = pImage->Backend->pfnWrite(pImage->pBackendData,
    27702769                                        pIoCtx->Req.Io.uOffset - cbPreRead,
    27712770                                        cbPreRead + cbThisWrite + cbPostRead,
     
    29732972        fWrite =   (pImage->uOpenFlags & VD_OPEN_FLAGS_HONOR_SAME)
    29742973                 ? 0 : VD_WRITE_NO_ALLOC;
    2975         rc = pImage->Backend->pfnAsyncWrite(pImage->pBackendData, uOffset,
     2974        rc = pImage->Backend->pfnWrite(pImage->pBackendData, uOffset,
    29762975                                            cbThisWrite, pIoCtx,
    29772976                                            &cbThisWrite, &cbPreRead,
     
    31003099    {
    31013100        vdResetModifiedFlag(pDisk);
    3102         rc = pImage->Backend->pfnAsyncFlush(pImage->pBackendData, pIoCtx);
     3101        rc = pImage->Backend->pfnFlush(pImage->pBackendData, pIoCtx);
    31033102        if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
    31043103            rc = VINF_SUCCESS;
     
    31293128    AssertPtr(pBlock);
    31303129
    3131     rc = pDisk->pLast->Backend->pfnAsyncDiscard(pDisk->pLast->pBackendData, pIoCtx,
     3130    rc = pDisk->pLast->Backend->pfnDiscard(pDisk->pLast->pBackendData, pIoCtx,
    31323131                                                pBlock->Core.Key, pBlock->cbDiscard,
    31333132                                                &cbPreAllocated, &cbPostAllocated,
     
    32113210                    cbThis = (idxEnd - idxStart) * 512;
    32123211
    3213                 rc = pDisk->pLast->Backend->pfnAsyncDiscard(pDisk->pLast->pBackendData, pIoCtx,
     3212                rc = pDisk->pLast->Backend->pfnDiscard(pDisk->pLast->pBackendData, pIoCtx,
    32143213                                                            offStart, cbThis, NULL, NULL, &cbThis,
    32153214                                                            NULL, VD_DISCARD_MARK_UNUSED);
     
    32683267
    32693268    /* No block found, try to discard using the backend first. */
    3270     rc = pDisk->pLast->Backend->pfnAsyncDiscard(pDisk->pLast->pBackendData, pIoCtx,
     3269    rc = pDisk->pLast->Backend->pfnDiscard(pDisk->pLast->pBackendData, pIoCtx,
    32713270                                                offStart, cbThisDiscard, &cbPreAllocated,
    32723271                                                &cbPostAllocated, &cbThisDiscard,
     
    47504749
    47514750static size_t vdIOIntIoCtxCopyTo(void *pvUser, PVDIOCTX pIoCtx,
    4752                                  void *pvBuf, size_t cbBuf)
     4751                                 const void *pvBuf, size_t cbBuf)
    47534752{
    47544753    PVDIO    pVDIo = (PVDIO)pvUser;
     
    69586957                fLockWrite = true;
    69596958
    6960                 rc = pImageTo->Backend->pfnAsyncRead(pImageTo->pBackendData,
     6959                rc = pImageTo->Backend->pfnRead(pImageTo->pBackendData,
    69616960                                                     uOffset, cbThisRead,
    69626961                                                     &IoCtx, &cbThisRead);
     
    69716970                         pCurrImage = pCurrImage->pPrev)
    69726971                    {
    6973                         rc = pCurrImage->Backend->pfnAsyncRead(pCurrImage->pBackendData,
     6972                        rc = pCurrImage->Backend->pfnRead(pCurrImage->pBackendData,
    69746973                                                               uOffset, cbThisRead,
    69756974                                                               &IoCtx, &cbThisRead);
     
    70977096                     pCurrImage = pCurrImage->pPrev)
    70987097                {
    7099                     rc = pCurrImage->Backend->pfnAsyncRead(pCurrImage->pBackendData,
     7098                    rc = pCurrImage->Backend->pfnRead(pCurrImage->pBackendData,
    71007099                                                           uOffset, cbThisRead,
    71017100                                                           &IoCtx, &cbThisRead);
     
    82988297        vdIoCtxInit(&IoCtx, pDisk, VDIOCTXTXDIR_FLUSH, 0, 0, NULL,
    82998298                    NULL, NULL, NULL, VDIOCTX_FLAGS_SYNC);
    8300         rc = pImage->Backend->pfnAsyncFlush(pImage->pBackendData, &IoCtx);
     8299        rc = pImage->Backend->pfnFlush(pImage->pBackendData, &IoCtx);
    83018300
    83028301#if 0 /** @todo: Change cache implementation. */
  • trunk/src/VBox/Storage/VDI.cpp

    r44242 r44252  
    10621062 * Internal: Flush the image file to disk - async version.
    10631063 */
    1064 static int vdiFlushImageAsync(PVDIIMAGEDESC pImage, PVDIOCTX pIoCtx)
     1064static int vdiFlushImageIoCtx(PVDIIMAGEDESC pImage, PVDIOCTX pIoCtx)
    10651065{
    10661066    int rc = VINF_SUCCESS;
     
    10781078    }
    10791079
    1080     return rc;
    1081 }
    1082 
    1083 /**
    1084  * Internal: Discard a whole block from the image filling the created hole with
    1085  * data from another block.
    1086  *
    1087  * @returns VBox status code.
    1088  * @param   pImage    VDI image instance data.
    1089  * @param   uBlock    The block to discard.
    1090  * @param   pvBlock   Memory to use for the I/O.
    1091  */
    1092 static int vdiDiscardBlock(PVDIIMAGEDESC pImage, unsigned uBlock, void *pvBlock)
    1093 {
    1094     int rc = VINF_SUCCESS;
    1095     uint64_t cbImage;
    1096     unsigned idxLastBlock = getImageBlocksAllocated(&pImage->Header) - 1;
    1097     unsigned uBlockLast = pImage->paBlocksRev[idxLastBlock];
    1098     VDIIMAGEBLOCKPOINTER ptrBlockDiscard = pImage->paBlocks[uBlock];
    1099 
    1100     LogFlowFunc(("pImage=%#p uBlock=%u pvBlock=%#p\n",
    1101                  pImage, uBlock, pvBlock));
    1102 
    1103     pImage->paBlocksRev[idxLastBlock] = VDI_IMAGE_BLOCK_FREE;
    1104 
    1105     do
    1106     {
    1107         /*
    1108          * The block is empty, remove it.
    1109          * Read the last block of the image first.
    1110          */
    1111         if (idxLastBlock != ptrBlockDiscard)
    1112         {
    1113             uint64_t u64Offset;
    1114 
    1115             LogFlowFunc(("Moving block [%u]=%u into [%u]=%u\n",
    1116                          uBlockLast, idxLastBlock, uBlock, pImage->paBlocks[uBlock]));
    1117 
    1118             u64Offset = (uint64_t)idxLastBlock * pImage->cbTotalBlockData + pImage->offStartData;
    1119             rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, u64Offset,
    1120                                        pvBlock, pImage->cbTotalBlockData);
    1121             if (RT_FAILURE(rc))
    1122                 break;
    1123 
    1124             /* Write to the now unallocated block. */
    1125             u64Offset = (uint64_t)ptrBlockDiscard * pImage->cbTotalBlockData + pImage->offStartData;
    1126             rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, u64Offset,
    1127                                         pvBlock, pImage->cbTotalBlockData);
    1128             if (RT_FAILURE(rc))
    1129                 break;
    1130 
    1131             /* Update block and reverse block tables. */
    1132             pImage->paBlocks[uBlockLast] = ptrBlockDiscard;
    1133             pImage->paBlocksRev[ptrBlockDiscard] = uBlockLast;
    1134             rc = vdiUpdateBlockInfo(pImage, uBlockLast);
    1135             if (RT_FAILURE(rc))
    1136                 break;
    1137         }
    1138         else
    1139             LogFlowFunc(("Discard last block [%u]=%u\n", uBlock, pImage->paBlocks[uBlock]));
    1140 
    1141         pImage->paBlocks[uBlock] = VDI_IMAGE_BLOCK_ZERO;
    1142 
    1143         /* Update the block pointers. */
    1144         setImageBlocksAllocated(&pImage->Header, idxLastBlock);
    1145         rc = vdiUpdateBlockInfo(pImage, uBlock);
    1146         if (RT_FAILURE(rc))
    1147             break;
    1148 
    1149         pImage->cbImage -= pImage->cbTotalBlockData;
    1150         LogFlowFunc(("Set new size %llu\n", pImage->cbImage));
    1151         rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage, pImage->cbImage);
    1152     } while (0);
    1153 
    1154     LogFlowFunc(("returns rc=%Rrc\n", rc));
    11551080    return rc;
    11561081}
     
    13531278 * @param   rcReq           Status code for the completed request.
    13541279 */
    1355 static DECLCALLBACK(int) vdiAsyncBlockAllocUpdate(void *pBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq)
     1280static DECLCALLBACK(int) vdiBlockAllocUpdate(void *pBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq)
    13561281{
    13571282    int rc = VINF_SUCCESS;
     
    16211546}
    16221547
    1623 /** @copydoc VBOXHDDBACKEND::pfnRead */
    1624 static int vdiRead(void *pBackendData, uint64_t uOffset, void *pvBuf,
    1625                    size_t cbToRead, size_t *pcbActuallyRead)
    1626 {
    1627     LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n", pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead));
     1548static int vdiRead(void *pBackendData, uint64_t uOffset, size_t cbToRead,
     1549                   PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
     1550{
     1551    LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n",
     1552                 pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead));
    16281553    PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData;
    16291554    unsigned uBlock;
     
    16361561
    16371562    if (   uOffset + cbToRead > getImageDiskSize(&pImage->Header)
    1638         || !VALID_PTR(pvBuf)
     1563        || !VALID_PTR(pIoCtx)
    16391564        || !cbToRead)
    16401565    {
     
    16551580    else if (pImage->paBlocks[uBlock] == VDI_IMAGE_BLOCK_ZERO)
    16561581    {
    1657         memset(pvBuf, 0, cbToRead);
     1582        size_t cbSet;
     1583
     1584        cbSet = vdIfIoIntIoCtxSet(pImage->pIfIo, pIoCtx, 0, cbToRead);
     1585        Assert(cbSet == cbToRead);
     1586
    16581587        rc = VINF_SUCCESS;
    16591588    }
     
    16651594
    16661595        if (u64Offset + cbToRead <= pImage->cbImage)
    1667             rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, u64Offset,
    1668                                        pvBuf, cbToRead);
     1596            rc = vdIfIoIntFileReadUser(pImage->pIfIo, pImage->pStorage, u64Offset,
     1597                                       pIoCtx, cbToRead);
    16691598        else
    16701599        {
    16711600            LogRel(("VDI: Out of range access (%llu) in image %s, image size %llu\n",
    16721601                    u64Offset, pImage->pszFilename, pImage->cbImage));
    1673             memset(pvBuf, 0, cbToRead);
     1602            vdIfIoIntIoCtxSet(pImage->pIfIo, pIoCtx, 0, cbToRead);
    16741603            rc = VERR_VD_READ_OUT_OF_RANGE;
    16751604        }
     
    16841613}
    16851614
    1686 /**@copydoc VBOXHDDBACKEND::pfnWrite */
    1687 static int vdiWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf,
    1688                     size_t cbToWrite, size_t *pcbWriteProcess,
    1689                     size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite)
    1690 {
    1691     LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n", pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));
     1615static int vdiWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite,
     1616                    PVDIOCTX pIoCtx, size_t *pcbWriteProcess, size_t *pcbPreRead,
     1617                    size_t *pcbPostRead, unsigned fWrite)
     1618{
     1619    LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n",
     1620                 pBackendData, uOffset, pIoCtx, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));
    16921621    PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData;
    16931622    unsigned uBlock;
     
    17051634    }
    17061635
    1707     if (!VALID_PTR(pvBuf) || !cbToWrite)
     1636    if (!VALID_PTR(pIoCtx) || !cbToWrite)
    17081637    {
    17091638        rc = VERR_INVALID_PARAMETER;
     
    17361665                 * (which also means that it's a zero block. Don't need to write
    17371666                 * anything to this block  if the data consists of just zeroes. */
    1738                 Assert(!(cbToWrite % 4));
    1739                 Assert(cbToWrite * 8 <= UINT32_MAX);
    1740                 if (ASMBitFirstSet((volatile void *)pvBuf, (uint32_t)cbToWrite * 8) == -1)
     1667                if (vdIfIoIntIoCtxIsZero(pImage->pIfIo, pIoCtx, cbToWrite, true))
    17411668                {
    17421669                    pImage->paBlocks[uBlock] = VDI_IMAGE_BLOCK_ZERO;
     
    17531680                 * Allocate block and write data. */
    17541681                Assert(!offWrite);
     1682                PVDIASYNCBLOCKALLOC pBlockAlloc = (PVDIASYNCBLOCKALLOC)RTMemAllocZ(sizeof(VDIASYNCBLOCKALLOC));
     1683                if (!pBlockAlloc)
     1684                {
     1685                    rc = VERR_NO_MEMORY;
     1686                    break;
     1687                }
     1688
    17551689                unsigned cBlocksAllocated = getImageBlocksAllocated(&pImage->Header);
    17561690                uint64_t u64Offset = (uint64_t)cBlocksAllocated * pImage->cbTotalBlockData
    17571691                                   + (pImage->offStartData + pImage->offStartBlockData);
    1758                 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage,
    1759                                             u64Offset, pvBuf, cbToWrite);
    1760                 if (RT_FAILURE(rc))
    1761                     goto out;
    1762                 pImage->paBlocks[uBlock] = cBlocksAllocated;
    1763 
    1764                 if (pImage->paBlocksRev)
    1765                     pImage->paBlocksRev[cBlocksAllocated] = uBlock;
    1766 
    1767                 setImageBlocksAllocated(&pImage->Header, cBlocksAllocated + 1);
    1768 
    1769                 rc = vdiUpdateBlockInfo(pImage, uBlock);
    1770                 if (RT_FAILURE(rc))
    1771                     goto out;
    1772 
    1773                 pImage->cbImage += cbToWrite;
     1692
     1693                pBlockAlloc->cBlocksAllocated = cBlocksAllocated;
     1694                pBlockAlloc->uBlock           = uBlock;
     1695
    17741696                *pcbPreRead = 0;
    17751697                *pcbPostRead = 0;
     1698
     1699                rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pImage->pStorage,
     1700                                            u64Offset, pIoCtx, cbToWrite,
     1701                                            vdiBlockAllocUpdate, pBlockAlloc);
     1702                if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
     1703                    break;
     1704                else if (RT_FAILURE(rc))
     1705                {
     1706                    RTMemFree(pBlockAlloc);
     1707                    break;
     1708                }
     1709
     1710                rc = vdiBlockAllocUpdate(pImage, pIoCtx, pBlockAlloc, rc);
    17761711            }
    17771712            else
     
    17891724            uint64_t u64Offset = (uint64_t)pImage->paBlocks[uBlock] * pImage->cbTotalBlockData
    17901725                               + (pImage->offStartData + pImage->offStartBlockData + offWrite);
    1791             rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, u64Offset,
    1792                                         pvBuf, cbToWrite);
     1726            rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pImage->pStorage,
     1727                                        u64Offset, pIoCtx, cbToWrite, NULL, NULL);
    17931728        }
    17941729    } while (0);
     
    18021737}
    18031738
    1804 /** @copydoc VBOXHDDBACKEND::pfnFlush */
    1805 static int vdiFlush(void *pBackendData)
     1739static int vdiFlush(void *pBackendData, PVDIOCTX pIoCtx)
    18061740{
    18071741    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     
    18111745    Assert(pImage);
    18121746
    1813     vdiFlushImage(pImage);
     1747    rc = vdiFlushImageIoCtx(pImage, pIoCtx);
    18141748    LogFlowFunc(("returns %Rrc\n", rc));
    18151749    return rc;
     
    24322366}
    24332367
    2434 static int vdiAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbToRead,
    2435                         PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
    2436 {
    2437     LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n",
    2438                  pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead));
    2439     PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData;
    2440     unsigned uBlock;
    2441     unsigned offRead;
    2442     int rc;
    2443 
    2444     AssertPtr(pImage);
    2445     Assert(!(uOffset % 512));
    2446     Assert(!(cbToRead % 512));
    2447 
    2448     if (   uOffset + cbToRead > getImageDiskSize(&pImage->Header)
    2449         || !VALID_PTR(pIoCtx)
    2450         || !cbToRead)
    2451     {
    2452         rc = VERR_INVALID_PARAMETER;
    2453         goto out;
    2454     }
    2455 
    2456     /* Calculate starting block number and offset inside it. */
    2457     uBlock = (unsigned)(uOffset >> pImage->uShiftOffset2Index);
    2458     offRead = (unsigned)uOffset & pImage->uBlockMask;
    2459 
    2460     /* Clip read range to at most the rest of the block. */
    2461     cbToRead = RT_MIN(cbToRead, getImageBlockSize(&pImage->Header) - offRead);
    2462     Assert(!(cbToRead % 512));
    2463 
    2464     if (pImage->paBlocks[uBlock] == VDI_IMAGE_BLOCK_FREE)
    2465         rc = VERR_VD_BLOCK_FREE;
    2466     else if (pImage->paBlocks[uBlock] == VDI_IMAGE_BLOCK_ZERO)
    2467     {
    2468         size_t cbSet;
    2469 
    2470         cbSet = vdIfIoIntIoCtxSet(pImage->pIfIo, pIoCtx, 0, cbToRead);
    2471         Assert(cbSet == cbToRead);
    2472 
    2473         rc = VINF_SUCCESS;
    2474     }
    2475     else
    2476     {
    2477         /* Block present in image file, read relevant data. */
    2478         uint64_t u64Offset = (uint64_t)pImage->paBlocks[uBlock] * pImage->cbTotalBlockData
    2479                            + (pImage->offStartData + pImage->offStartBlockData + offRead);
    2480 
    2481         if (u64Offset + cbToRead <= pImage->cbImage)
    2482             rc = vdIfIoIntFileReadUser(pImage->pIfIo, pImage->pStorage, u64Offset,
    2483                                        pIoCtx, cbToRead);
    2484         else
    2485         {
    2486             LogRel(("VDI: Out of range access (%llu) in image %s, image size %llu\n",
    2487                     u64Offset, pImage->pszFilename, pImage->cbImage));
    2488             vdIfIoIntIoCtxSet(pImage->pIfIo, pIoCtx, 0, cbToRead);
    2489             rc = VERR_VD_READ_OUT_OF_RANGE;
    2490         }
    2491     }
    2492 
    2493     if (pcbActuallyRead)
    2494         *pcbActuallyRead = cbToRead;
    2495 
    2496 out:
    2497     LogFlowFunc(("returns %Rrc\n", rc));
    2498     return rc;
    2499 }
    2500 
    2501 static int vdiAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite,
    2502                          PVDIOCTX pIoCtx,
    2503                          size_t *pcbWriteProcess, size_t *pcbPreRead,
    2504                          size_t *pcbPostRead, unsigned fWrite)
    2505 {
    2506     LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n",
    2507                  pBackendData, uOffset, pIoCtx, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));
    2508     PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData;
    2509     unsigned uBlock;
    2510     unsigned offWrite;
    2511     int rc = VINF_SUCCESS;
    2512 
    2513     AssertPtr(pImage);
    2514     Assert(!(uOffset % 512));
    2515     Assert(!(cbToWrite % 512));
    2516 
    2517     if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    2518     {
    2519         rc = VERR_VD_IMAGE_READ_ONLY;
    2520         goto out;
    2521     }
    2522 
    2523     if (!VALID_PTR(pIoCtx) || !cbToWrite)
    2524     {
    2525         rc = VERR_INVALID_PARAMETER;
    2526         goto out;
    2527     }
    2528 
    2529     /* No size check here, will do that later.  For dynamic images which are
    2530      * not multiples of the block size in length, this would prevent writing to
    2531      * the last block. */
    2532 
    2533     /* Calculate starting block number and offset inside it. */
    2534     uBlock = (unsigned)(uOffset >> pImage->uShiftOffset2Index);
    2535     offWrite = (unsigned)uOffset & pImage->uBlockMask;
    2536 
    2537     /* Clip write range to at most the rest of the block. */
    2538     cbToWrite = RT_MIN(cbToWrite, getImageBlockSize(&pImage->Header) - offWrite);
    2539     Assert(!(cbToWrite % 512));
    2540 
    2541     do
    2542     {
    2543         if (!IS_VDI_IMAGE_BLOCK_ALLOCATED(pImage->paBlocks[uBlock]))
    2544         {
    2545             /* Block is either free or zero. */
    2546             if (   !(pImage->uOpenFlags & VD_OPEN_FLAGS_HONOR_ZEROES)
    2547                 && (   pImage->paBlocks[uBlock] == VDI_IMAGE_BLOCK_ZERO
    2548                     || cbToWrite == getImageBlockSize(&pImage->Header)))
    2549             {
    2550                 /* If the destination block is unallocated at this point, it's
    2551                  * either a zero block or a block which hasn't been used so far
    2552                  * (which also means that it's a zero block. Don't need to write
    2553                  * anything to this block  if the data consists of just zeroes. */
    2554                 if (vdIfIoIntIoCtxIsZero(pImage->pIfIo, pIoCtx, cbToWrite, true))
    2555                 {
    2556                     pImage->paBlocks[uBlock] = VDI_IMAGE_BLOCK_ZERO;
    2557                     *pcbPreRead = 0;
    2558                     *pcbPostRead = 0;
    2559                     break;
    2560                 }
    2561             }
    2562 
    2563             if (   cbToWrite == getImageBlockSize(&pImage->Header)
    2564                 && !(fWrite & VD_WRITE_NO_ALLOC))
    2565             {
    2566                 /* Full block write to previously unallocated block.
    2567                  * Allocate block and write data. */
    2568                 Assert(!offWrite);
    2569                 PVDIASYNCBLOCKALLOC pBlockAlloc = (PVDIASYNCBLOCKALLOC)RTMemAllocZ(sizeof(VDIASYNCBLOCKALLOC));
    2570                 if (!pBlockAlloc)
    2571                 {
    2572                     rc = VERR_NO_MEMORY;
    2573                     break;
    2574                 }
    2575 
    2576                 unsigned cBlocksAllocated = getImageBlocksAllocated(&pImage->Header);
    2577                 uint64_t u64Offset = (uint64_t)cBlocksAllocated * pImage->cbTotalBlockData
    2578                                    + (pImage->offStartData + pImage->offStartBlockData);
    2579 
    2580                 pBlockAlloc->cBlocksAllocated = cBlocksAllocated;
    2581                 pBlockAlloc->uBlock           = uBlock;
    2582 
    2583                 *pcbPreRead = 0;
    2584                 *pcbPostRead = 0;
    2585 
    2586                 rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pImage->pStorage,
    2587                                             u64Offset, pIoCtx, cbToWrite,
    2588                                             vdiAsyncBlockAllocUpdate, pBlockAlloc);
    2589                 if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
    2590                     break;
    2591                 else if (RT_FAILURE(rc))
    2592                 {
    2593                     RTMemFree(pBlockAlloc);
    2594                     break;
    2595                 }
    2596 
    2597                 rc = vdiAsyncBlockAllocUpdate(pImage, pIoCtx, pBlockAlloc, rc);
    2598             }
    2599             else
    2600             {
    2601                 /* Trying to do a partial write to an unallocated block. Don't do
    2602                  * anything except letting the upper layer know what to do. */
    2603                 *pcbPreRead = offWrite % getImageBlockSize(&pImage->Header);
    2604                 *pcbPostRead = getImageBlockSize(&pImage->Header) - cbToWrite - *pcbPreRead;
    2605                 rc = VERR_VD_BLOCK_FREE;
    2606             }
    2607         }
    2608         else
    2609         {
    2610             /* Block present in image file, write relevant data. */
    2611             uint64_t u64Offset = (uint64_t)pImage->paBlocks[uBlock] * pImage->cbTotalBlockData
    2612                                + (pImage->offStartData + pImage->offStartBlockData + offWrite);
    2613             rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pImage->pStorage,
    2614                                         u64Offset, pIoCtx, cbToWrite, NULL, NULL);
    2615         }
    2616     } while (0);
    2617 
    2618     if (pcbWriteProcess)
    2619         *pcbWriteProcess = cbToWrite;
    2620 
    2621 out:
    2622     LogFlowFunc(("returns %Rrc\n", rc));
    2623     return rc;
    2624 }
    2625 
    2626 static int vdiAsyncFlush(void *pBackendData, PVDIOCTX pIoCtx)
    2627 {
    2628     LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    2629     PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData;
    2630     int rc = VINF_SUCCESS;
    2631 
    2632     Assert(pImage);
    2633 
    2634     rc = vdiFlushImageAsync(pImage, pIoCtx);
    2635     LogFlowFunc(("returns %Rrc\n", rc));
    2636     return rc;
    2637 }
    2638 
    26392368/** @copydoc VBOXHDDBACKEND::pfnCompact */
    26402369static int vdiCompact(void *pBackendData, unsigned uPercentStart,
     
    30882817}
    30892818
    3090 
    30912819/** @copydoc VBOXHDDBACKEND::pfnDiscard */
    3092 static DECLCALLBACK(int) vdiDiscard(void *pBackendData,
    3093                                     uint64_t uOffset, size_t cbDiscard,
    3094                                     size_t *pcbPreAllocated,
    3095                                     size_t *pcbPostAllocated,
    3096                                     size_t *pcbActuallyDiscarded,
    3097                                     void   **ppbmAllocationBitmap,
    3098                                     unsigned fDiscard)
    3099 {
    3100     PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData;
    3101     unsigned uBlock;
    3102     unsigned offDiscard;
    3103     int rc = VINF_SUCCESS;
    3104     void *pvBlock = NULL;
    3105 
    3106     LogFlowFunc(("pBackendData=%#p uOffset=%llu cbDiscard=%zu pcbPreAllocated=%#p pcbPostAllocated=%#p pcbActuallyDiscarded=%#p ppbmAllocationBitmap=%#p fDiscard=%#x\n",
    3107                  pBackendData, uOffset, cbDiscard, pcbPreAllocated, pcbPostAllocated, pcbActuallyDiscarded, ppbmAllocationBitmap, fDiscard));
    3108 
    3109     AssertPtr(pImage);
    3110     Assert(!(uOffset % 512));
    3111     Assert(!(cbDiscard % 512));
    3112 
    3113     AssertMsgReturn(!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY),
    3114                     ("Image is readonly\n"), VERR_VD_IMAGE_READ_ONLY);
    3115     AssertMsgReturn(   uOffset + cbDiscard <= getImageDiskSize(&pImage->Header)
    3116                     && cbDiscard,
    3117                     ("Invalid parameters uOffset=%llu cbDiscard=%zu\n",
    3118                      uOffset, cbDiscard),
    3119                      VERR_INVALID_PARAMETER);
    3120 
    3121     do
    3122     {
    3123         AssertMsgBreakStmt(!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY),
    3124                            ("Image is opened readonly\n"),
    3125                            rc = VERR_VD_IMAGE_READ_ONLY);
    3126 
    3127         AssertMsgBreakStmt(cbDiscard,
    3128                            ("cbDiscard=%u\n", cbDiscard),
    3129                            rc = VERR_INVALID_PARAMETER);
    3130 
    3131         /* Calculate starting block number and offset inside it. */
    3132         uBlock = (unsigned)(uOffset >> pImage->uShiftOffset2Index);
    3133         offDiscard = (unsigned)uOffset & pImage->uBlockMask;
    3134 
    3135         /* Clip range to at most the rest of the block. */
    3136         cbDiscard = RT_MIN(cbDiscard, getImageBlockSize(&pImage->Header) - offDiscard);
    3137         Assert(!(cbDiscard % 512));
    3138 
    3139         if (pcbPreAllocated)
    3140             *pcbPreAllocated = 0;
    3141 
    3142         if (pcbPostAllocated)
    3143             *pcbPostAllocated = 0;
    3144 
    3145         if (IS_VDI_IMAGE_BLOCK_ALLOCATED(pImage->paBlocks[uBlock]))
    3146         {
    3147             uint8_t *pbBlockData;
    3148             size_t cbPreAllocated, cbPostAllocated;
    3149 
    3150             cbPreAllocated = offDiscard % getImageBlockSize(&pImage->Header);
    3151             cbPostAllocated = getImageBlockSize(&pImage->Header) - cbDiscard - cbPreAllocated;
    3152 
    3153             /* Read the block data. */
    3154             pvBlock = RTMemAlloc(pImage->cbTotalBlockData);
    3155             if (!pvBlock)
    3156             {
    3157                 rc = VERR_NO_MEMORY;
    3158                 break;
    3159             }
    3160 
    3161             if (!cbPreAllocated && !cbPostAllocated)
    3162             {
    3163                 /*
    3164                  * Discarding a whole block, don't check for allocated sectors.
    3165                  * It is possible to just remove the whole block which avoids
    3166                  * one read and checking the whole block for data.
    3167                  */
    3168                 rc = vdiDiscardBlock(pImage, uBlock, pvBlock);
    3169             }
    3170             else
    3171             {
    3172                 /* Read data. */
    3173                 pbBlockData = (uint8_t *)pvBlock + pImage->offStartBlockData;
    3174 
    3175                 uint64_t u64Offset = (uint64_t)pImage->paBlocks[uBlock] * pImage->cbTotalBlockData + pImage->offStartData;
    3176                 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, u64Offset,
    3177                                            pvBlock, pImage->cbTotalBlockData);
    3178                 if (RT_FAILURE(rc))
    3179                     break;
    3180 
    3181                 /* Clear data. */
    3182                 memset(pbBlockData + offDiscard , 0, cbDiscard);
    3183 
    3184                 Assert(!(cbDiscard % 4));
    3185                 Assert(cbDiscard * 8 <= UINT32_MAX);
    3186                 if (ASMBitFirstSet((volatile void *)pbBlockData, getImageBlockSize(&pImage->Header) * 8) == -1)
    3187                     rc = vdiDiscardBlock(pImage, uBlock, pvBlock);
    3188                 else if (fDiscard & VD_DISCARD_MARK_UNUSED)
    3189                 {
    3190                     /* Write changed data to the image. */
    3191                     rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, u64Offset + offDiscard,
    3192                                                 pbBlockData + offDiscard, cbDiscard);
    3193                 }
    3194                 else
    3195                 {
    3196                     /* Block has data, create allocation bitmap. */
    3197                     *pcbPreAllocated = cbPreAllocated;
    3198                     *pcbPostAllocated = cbPostAllocated;
    3199                     *ppbmAllocationBitmap = vdiAllocationBitmapCreate(pbBlockData, getImageBlockSize(&pImage->Header));
    3200                     if (RT_UNLIKELY(!*ppbmAllocationBitmap))
    3201                         rc = VERR_NO_MEMORY;
    3202                     else
    3203                         rc = VERR_VD_DISCARD_ALIGNMENT_NOT_MET;
    3204                 }
    3205             } /* if: no complete block discarded */
    3206         } /* if: Block is allocated. */
    3207         /* else: nothing to do. */
    3208     } while (0);
    3209 
    3210     if (pcbActuallyDiscarded)
    3211         *pcbActuallyDiscarded = cbDiscard;
    3212 
    3213     if (pvBlock)
    3214         RTMemFree(pvBlock);
    3215 
    3216     LogFlowFunc(("returns %Rrc\n", rc));
    3217     return rc;
    3218 }
    3219 
    3220 /** @copydoc VBOXHDDBACKEND::pfnDiscard */
    3221 static DECLCALLBACK(int) vdiAsyncDiscard(void *pBackendData, PVDIOCTX pIoCtx,
     2820static DECLCALLBACK(int) vdiDiscard(void *pBackendData, PVDIOCTX pIoCtx,
    32222821                                         uint64_t uOffset, size_t cbDiscard,
    32232822                                         size_t *pcbPreAllocated,
     
    36023201    /* pfnFlush */
    36033202    vdiFlush,
     3203    /* pfnDiscard */
     3204    vdiDiscard,
    36043205    /* pfnGetVersion */
    36053206    vdiGetVersion,
     
    36543255    /* pfnSetParentFilename */
    36553256    NULL,
    3656     /* pfnAsyncRead */
    3657     vdiAsyncRead,
    3658     /* pfnAsyncWrite */
    3659     vdiAsyncWrite,
    3660     /* pfnAsyncFlush */
    3661     vdiAsyncFlush,
    36623257    /* pfnComposeLocation */
    36633258    genericFileComposeLocation,
     
    36683263    /* pfnResize */
    36693264    vdiResize,
    3670     /* pfnDiscard */
    3671     vdiDiscard,
    3672     /* pfnAsyncDiscard */
    3673     vdiAsyncDiscard,
    36743265    /* pfnRepair */
    36753266    vdiRepair
  • trunk/src/VBox/Storage/VHD.cpp

    r44233 r44252  
    14511451
    14521452/** @copydoc VBOXHDDBACKEND::pfnRead */
    1453 static int vhdRead(void *pBackendData, uint64_t uOffset, void *pvBuf,
    1454                    size_t cbBuf, size_t *pcbActuallyRead)
    1455 {
    1456     LogFlowFunc(("pBackendData=%p uOffset=%#llu pvBuf=%p cbBuf=%u pcbActuallyRead=%p\n", pBackendData, uOffset, pvBuf, cbBuf, pcbActuallyRead));
    1457     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1458     int rc = VINF_SUCCESS;
    1459 
    1460     if (uOffset + cbBuf > pImage->cbSize)
    1461     {
    1462         rc = VERR_INVALID_PARAMETER;
    1463         goto out;
    1464     }
    1465 
    1466     /*
    1467      * If we have a dynamic disk image, we need to find the data block and sector to read.
    1468      */
    1469     if (pImage->pBlockAllocationTable)
    1470     {
    1471         /*
    1472          * Get the data block first.
    1473          */
    1474         uint32_t cBlockAllocationTableEntry = (uOffset / VHD_SECTOR_SIZE) / pImage->cSectorsPerDataBlock;
    1475         uint32_t cBATEntryIndex = (uOffset / VHD_SECTOR_SIZE) % pImage->cSectorsPerDataBlock;
    1476         uint64_t uVhdOffset;
    1477 
    1478         LogFlowFunc(("cBlockAllocationTableEntry=%u cBatEntryIndex=%u\n", cBlockAllocationTableEntry, cBATEntryIndex));
    1479         LogFlowFunc(("BlockAllocationEntry=%u\n", pImage->pBlockAllocationTable[cBlockAllocationTableEntry]));
    1480 
    1481         /*
    1482          * Clip read range to remain in this data block.
    1483          */
    1484         cbBuf = RT_MIN(cbBuf, (pImage->cbDataBlock - (cBATEntryIndex * VHD_SECTOR_SIZE)));
    1485 
    1486         /*
    1487          * If the block is not allocated the content of the entry is ~0
    1488          */
    1489         if (pImage->pBlockAllocationTable[cBlockAllocationTableEntry] == ~0U)
    1490             rc = VERR_VD_BLOCK_FREE;
    1491         else
    1492         {
    1493             uVhdOffset = ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry] + pImage->cDataBlockBitmapSectors + cBATEntryIndex) * VHD_SECTOR_SIZE;
    1494             LogFlowFunc(("uVhdOffset=%llu cbBuf=%u\n", uVhdOffset, cbBuf));
    1495 
    1496             /* Read in the block's bitmap. */
    1497             rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage,
    1498                                        ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE,
    1499                                        pImage->pu8Bitmap, pImage->cbDataBlockBitmap);
    1500             if (RT_SUCCESS(rc))
    1501             {
    1502                 uint32_t cSectors = 0;
    1503 
    1504                 if (vhdBlockBitmapSectorContainsData(pImage, cBATEntryIndex))
    1505                 {
    1506                     cBATEntryIndex++;
    1507                     cSectors = 1;
    1508 
    1509                     /*
    1510                      * The first sector being read is marked dirty, read as much as we
    1511                      * can from child. Note that only sectors that are marked dirty
    1512                      * must be read from child.
    1513                      */
    1514                     while (   (cSectors < (cbBuf / VHD_SECTOR_SIZE))
    1515                            && vhdBlockBitmapSectorContainsData(pImage, cBATEntryIndex))
    1516                     {
    1517                         cBATEntryIndex++;
    1518                         cSectors++;
    1519                     }
    1520 
    1521                     cbBuf = cSectors * VHD_SECTOR_SIZE;
    1522 
    1523                     LogFlowFunc(("uVhdOffset=%llu cbBuf=%u\n", uVhdOffset, cbBuf));
    1524                     rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage,
    1525                                                uVhdOffset, pvBuf, cbBuf);
    1526                 }
    1527                 else
    1528                 {
    1529                     /*
    1530                      * The first sector being read is marked clean, so we should read from
    1531                      * our parent instead, but only as much as there are the following
    1532                      * clean sectors, because the block may still contain dirty sectors
    1533                      * further on. We just need to compute the number of clean sectors
    1534                      * and pass it to our caller along with the notification that they
    1535                      * should be read from the parent.
    1536                      */
    1537                     cBATEntryIndex++;
    1538                     cSectors = 1;
    1539 
    1540                     while (   (cSectors < (cbBuf / VHD_SECTOR_SIZE))
    1541                            && !vhdBlockBitmapSectorContainsData(pImage, cBATEntryIndex))
    1542                     {
    1543                         cBATEntryIndex++;
    1544                         cSectors++;
    1545                     }
    1546 
    1547                     cbBuf = cSectors * VHD_SECTOR_SIZE;
    1548                     LogFunc(("Sectors free: uVhdOffset=%llu cbBuf=%u\n", uVhdOffset, cbBuf));
    1549                     rc = VERR_VD_BLOCK_FREE;
    1550                 }
    1551             }
    1552             else
    1553                 AssertMsgFailed(("Reading block bitmap failed rc=%Rrc\n", rc));
    1554         }
    1555     }
    1556     else
    1557         rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, uOffset, pvBuf, cbBuf);
    1558 
    1559     if (   RT_SUCCESS(rc)
    1560         || rc == VERR_VD_BLOCK_FREE)
    1561     {
    1562         if (pcbActuallyRead)
    1563             *pcbActuallyRead = cbBuf;
    1564 
    1565         Log2(("vhdRead: off=%#llx pvBuf=%p cbBuf=%d\n", uOffset, pvBuf, cbBuf));
    1566     }
    1567 
    1568 out:
    1569     LogFlowFunc(("returns %Rrc\n", rc));
    1570     return rc;
    1571 }
    1572 
    1573 /** @copydoc VBOXHDDBACKEND::pfnWrite */
    1574 static int vhdWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf,
    1575                     size_t cbBuf, size_t *pcbWriteProcess,
    1576                     size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite)
    1577 {
    1578     LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbBuf=%zu pcbWriteProcess=%#p\n", pBackendData, uOffset, pvBuf, cbBuf, pcbWriteProcess));
    1579     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1580     int rc = VINF_SUCCESS;
    1581 
    1582     LogFlowFunc(("pBackendData=%p uOffset=%llu pvBuf=%p cbBuf=%u pcbWriteProcess=%p pcbPreRead=%p pcbPostRead=%p fWrite=%u\n",
    1583              pBackendData, uOffset, pvBuf, cbBuf, pcbWriteProcess, pcbPreRead, pcbPostRead, fWrite));
    1584 
    1585     AssertPtr(pImage);
    1586     Assert(uOffset % VHD_SECTOR_SIZE == 0);
    1587     Assert(cbBuf % VHD_SECTOR_SIZE == 0);
    1588 
    1589     if (pImage->pBlockAllocationTable)
    1590     {
    1591         /*
    1592          * Get the data block first.
    1593          */
    1594         uint32_t cSector = uOffset / VHD_SECTOR_SIZE;
    1595         uint32_t cBlockAllocationTableEntry = cSector / pImage->cSectorsPerDataBlock;
    1596         uint32_t cBATEntryIndex = cSector % pImage->cSectorsPerDataBlock;
    1597         uint64_t uVhdOffset;
    1598 
    1599         /*
    1600          * Clip write range.
    1601          */
    1602         cbBuf = RT_MIN(cbBuf, (pImage->cbDataBlock - (cBATEntryIndex * VHD_SECTOR_SIZE)));
    1603 
    1604         /*
    1605          * If the block is not allocated the content of the entry is ~0
    1606          * and we need to allocate a new block. Note that while blocks are
    1607          * allocated with a relatively big granularity, each sector has its
    1608          * own bitmap entry, indicating whether it has been written or not.
    1609          * So that means for the purposes of the higher level that the
    1610          * granularity is invisible. This means there's no need to return
    1611          * VERR_VD_BLOCK_FREE unless the block hasn't been allocated yet.
    1612          */
    1613         if (pImage->pBlockAllocationTable[cBlockAllocationTableEntry] == ~0U)
    1614         {
    1615             /* Check if the block allocation should be suppressed. */
    1616             if (fWrite & VD_WRITE_NO_ALLOC)
    1617             {
    1618                 *pcbPreRead = cBATEntryIndex * VHD_SECTOR_SIZE;
    1619                 *pcbPostRead = pImage->cSectorsPerDataBlock * VHD_SECTOR_SIZE - cbBuf - *pcbPreRead;
    1620 
    1621                 if (pcbWriteProcess)
    1622                     *pcbWriteProcess = cbBuf;
    1623                 rc = VERR_VD_BLOCK_FREE;
    1624                 goto out;
    1625             }
    1626 
    1627             size_t  cbNewBlock = pImage->cbDataBlock + (pImage->cDataBlockBitmapSectors * VHD_SECTOR_SIZE);
    1628             uint8_t *pNewBlock = (uint8_t *)RTMemAllocZ(cbNewBlock);
    1629 
    1630             if (!pNewBlock)
    1631             {
    1632                 rc = VERR_NO_MEMORY;
    1633                 goto out;
    1634             }
    1635 
    1636             /*
    1637              * Write the new block at the current end of the file.
    1638              */
    1639             rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, pImage->uCurrentEndOfFile,
    1640                                         pNewBlock, cbNewBlock);
    1641             AssertRC(rc);
    1642 
    1643             /*
    1644              * Set the new end of the file and link the new block into the BAT.
    1645              */
    1646             pImage->pBlockAllocationTable[cBlockAllocationTableEntry] = pImage->uCurrentEndOfFile / VHD_SECTOR_SIZE;
    1647             pImage->uCurrentEndOfFile += cbNewBlock;
    1648             RTMemFree(pNewBlock);
    1649 
    1650             /* Write the updated BAT and the footer to remain in a consistent state. */
    1651             rc = vhdFlushImage(pImage);
    1652             AssertRC(rc);
    1653         }
    1654 
    1655         /*
    1656          * Calculate the real offset in the file.
    1657          */
    1658         uVhdOffset = ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry] + pImage->cDataBlockBitmapSectors + cBATEntryIndex) * VHD_SECTOR_SIZE;
    1659 
    1660         /* Write data. */
    1661         vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, uVhdOffset,
    1662                                pvBuf, cbBuf);
    1663 
    1664         /* Read in the block's bitmap. */
    1665         rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage,
    1666                                    ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE,
    1667                                    pImage->pu8Bitmap, pImage->cbDataBlockBitmap);
    1668         if (RT_SUCCESS(rc))
    1669         {
    1670             bool fChanged = false;
    1671 
    1672             /* Set the bits for all sectors having been written. */
    1673             for (uint32_t iSector = 0; iSector < (cbBuf / VHD_SECTOR_SIZE); iSector++)
    1674             {
    1675                 fChanged |= vhdBlockBitmapSectorSet(pImage, pImage->pu8Bitmap, cBATEntryIndex);
    1676                 cBATEntryIndex++;
    1677             }
    1678 
    1679             if (fChanged)
    1680             {
    1681                 /* Write the bitmap back. */
    1682                 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage,
    1683                                             ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE,
    1684                                             pImage->pu8Bitmap, pImage->cbDataBlockBitmap);
    1685             }
    1686         }
    1687     }
    1688     else
    1689     {
    1690         rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, uOffset, pvBuf, cbBuf);
    1691     }
    1692 
    1693     if (pcbWriteProcess)
    1694         *pcbWriteProcess = cbBuf;
    1695 
    1696     /* Stay on the safe side. Do not run the risk of confusing the higher
    1697      * level, as that can be pretty lethal to image consistency. */
    1698     *pcbPreRead = 0;
    1699     *pcbPostRead = 0;
    1700 
    1701 out:
    1702     LogFlowFunc(("returns %Rrc\n", rc));
    1703     return rc;
    1704 }
    1705 
    1706 /** @copydoc VBOXHDDBACKEND::pfnFlush */
    1707 static int vhdFlush(void *pBackendData)
    1708 {
    1709     LogFlowFunc(("pBackendData=%#p", pBackendData));
    1710     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1711     int rc;
    1712 
    1713     rc = vhdFlushImage(pImage);
    1714     LogFlowFunc(("returns %Rrc\n", rc));
    1715     return rc;
    1716 }
    1717 
    1718 /** @copydoc VBOXHDDBACKEND::pfnGetVersion */
    1719 static unsigned vhdGetVersion(void *pBackendData)
    1720 {
    1721     LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    1722     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1723     unsigned ver = 0;
    1724 
    1725     AssertPtr(pImage);
    1726 
    1727     if (pImage)
    1728         ver = 1; /**< @todo use correct version */
    1729 
    1730     LogFlowFunc(("returns %u\n", ver));
    1731     return ver;
    1732 }
    1733 
    1734 /** @copydoc VBOXHDDBACKEND::pfnGetSize */
    1735 static uint64_t vhdGetSize(void *pBackendData)
    1736 {
    1737     LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    1738     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1739     uint64_t cb = 0;
    1740 
    1741     AssertPtr(pImage);
    1742 
    1743     if (pImage && pImage->pStorage)
    1744         cb = pImage->cbSize;
    1745 
    1746     LogFlowFunc(("returns %llu\n", cb));
    1747     return cb;
    1748 }
    1749 
    1750 /** @copydoc VBOXHDDBACKEND::pfnGetFileSize */
    1751 static uint64_t vhdGetFileSize(void *pBackendData)
    1752 {
    1753     LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    1754     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1755     uint64_t cb = 0;
    1756 
    1757     AssertPtr(pImage);
    1758 
    1759     if (pImage && pImage->pStorage)
    1760         cb = pImage->uCurrentEndOfFile + sizeof(VHDFooter);
    1761 
    1762     LogFlowFunc(("returns %lld\n", cb));
    1763     return cb;
    1764 }
    1765 
    1766 /** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */
    1767 static int vhdGetPCHSGeometry(void *pBackendData, PVDGEOMETRY pPCHSGeometry)
    1768 {
    1769     LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry));
    1770     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1771     int rc;
    1772 
    1773     AssertPtr(pImage);
    1774 
    1775     if (pImage)
    1776     {
    1777         if (pImage->PCHSGeometry.cCylinders)
    1778         {
    1779             *pPCHSGeometry = pImage->PCHSGeometry;
    1780             rc = VINF_SUCCESS;
    1781         }
    1782         else
    1783             rc = VERR_VD_GEOMETRY_NOT_SET;
    1784     }
    1785     else
    1786         rc = VERR_VD_NOT_OPENED;
    1787 
    1788     LogFlowFunc(("returns %Rrc (CHS=%u/%u/%u)\n", rc, pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors));
    1789     return rc;
    1790 }
    1791 
    1792 /** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */
    1793 static int vhdSetPCHSGeometry(void *pBackendData, PCVDGEOMETRY pPCHSGeometry)
    1794 {
    1795     LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
    1796     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1797     int rc;
    1798 
    1799     AssertPtr(pImage);
    1800 
    1801     if (pImage)
    1802     {
    1803         if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    1804         {
    1805             rc = VERR_VD_IMAGE_READ_ONLY;
    1806             goto out;
    1807         }
    1808 
    1809         pImage->PCHSGeometry = *pPCHSGeometry;
    1810         rc = VINF_SUCCESS;
    1811     }
    1812     else
    1813         rc = VERR_VD_NOT_OPENED;
    1814 
    1815 out:
    1816     LogFlowFunc(("returns %Rrc\n", rc));
    1817     return rc;
    1818 }
    1819 
    1820 /** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */
    1821 static int vhdGetLCHSGeometry(void *pBackendData, PVDGEOMETRY pLCHSGeometry)
    1822 {
    1823 LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry));
    1824     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1825     int rc;
    1826 
    1827     AssertPtr(pImage);
    1828 
    1829     if (pImage)
    1830     {
    1831         if (pImage->LCHSGeometry.cCylinders)
    1832         {
    1833             *pLCHSGeometry = pImage->LCHSGeometry;
    1834             rc = VINF_SUCCESS;
    1835         }
    1836         else
    1837             rc = VERR_VD_GEOMETRY_NOT_SET;
    1838     }
    1839     else
    1840         rc = VERR_VD_NOT_OPENED;
    1841 
    1842     LogFlowFunc(("returns %Rrc (CHS=%u/%u/%u)\n", rc, pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors));
    1843     return rc;
    1844 }
    1845 
    1846 /** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */
    1847 static int vhdSetLCHSGeometry(void *pBackendData, PCVDGEOMETRY pLCHSGeometry)
    1848 {
    1849     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1850     int rc;
    1851 
    1852     AssertPtr(pImage);
    1853 
    1854     if (pImage)
    1855     {
    1856         if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    1857         {
    1858             rc = VERR_VD_IMAGE_READ_ONLY;
    1859             goto out;
    1860         }
    1861 
    1862         pImage->LCHSGeometry = *pLCHSGeometry;
    1863         rc = VINF_SUCCESS;
    1864     }
    1865     else
    1866         rc = VERR_VD_NOT_OPENED;
    1867 
    1868 out:
    1869     LogFlowFunc(("returns %Rrc\n", rc));
    1870     return rc;
    1871 }
    1872 
    1873 /** @copydoc VBOXHDDBACKEND::pfnGetImageFlags */
    1874 static unsigned vhdGetImageFlags(void *pBackendData)
    1875 {
    1876     LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    1877     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1878     unsigned uImageFlags;
    1879 
    1880     AssertPtr(pImage);
    1881 
    1882     if (pImage)
    1883         uImageFlags = pImage->uImageFlags;
    1884     else
    1885         uImageFlags = 0;
    1886 
    1887     LogFlowFunc(("returns %#x\n", uImageFlags));
    1888     return uImageFlags;
    1889 }
    1890 
    1891 /** @copydoc VBOXHDDBACKEND::pfnGetOpenFlags */
    1892 static unsigned vhdGetOpenFlags(void *pBackendData)
    1893 {
    1894     LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    1895     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1896     unsigned uOpenFlags;
    1897 
    1898     AssertPtr(pImage);
    1899 
    1900     if (pImage)
    1901         uOpenFlags = pImage->uOpenFlags;
    1902     else
    1903         uOpenFlags = 0;
    1904 
    1905     LogFlowFunc(("returns %#x\n", uOpenFlags));
    1906     return uOpenFlags;
    1907 }
    1908 
    1909 /** @copydoc VBOXHDDBACKEND::pfnSetOpenFlags */
    1910 static int vhdSetOpenFlags(void *pBackendData, unsigned uOpenFlags)
    1911 {
    1912     LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags));
    1913     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1914     int rc;
    1915 
    1916     /* Image must be opened and the new flags must be valid. */
    1917     if (!pImage || (uOpenFlags & ~(  VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO
    1918                                    | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE
    1919                                    | VD_OPEN_FLAGS_SEQUENTIAL | VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS)))
    1920     {
    1921         rc = VERR_INVALID_PARAMETER;
    1922         goto out;
    1923     }
    1924 
    1925     /* Implement this operation via reopening the image. */
    1926     rc = vhdFreeImage(pImage, false);
    1927     if (RT_FAILURE(rc))
    1928         goto out;
    1929     rc = vhdOpenImage(pImage, uOpenFlags);
    1930 
    1931 out:
    1932     LogFlowFunc(("returns %Rrc\n", rc));
    1933     return rc;
    1934 }
    1935 
    1936 /** @copydoc VBOXHDDBACKEND::pfnGetComment */
    1937 static int vhdGetComment(void *pBackendData, char *pszComment,
    1938                          size_t cbComment)
    1939 {
    1940     LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment));
    1941     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1942     int rc;
    1943 
    1944     AssertPtr(pImage);
    1945 
    1946     if (pImage)
    1947         rc = VERR_NOT_SUPPORTED;
    1948     else
    1949         rc = VERR_VD_NOT_OPENED;
    1950 
    1951     LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment));
    1952     return rc;
    1953 }
    1954 
    1955 /** @copydoc VBOXHDDBACKEND::pfnSetComment */
    1956 static int vhdSetComment(void *pBackendData, const char *pszComment)
    1957 {
    1958     LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment));
    1959     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1960     int rc;
    1961 
    1962     AssertPtr(pImage);
    1963 
    1964     if (pImage)
    1965     {
    1966         if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    1967             rc = VERR_VD_IMAGE_READ_ONLY;
    1968         else
    1969             rc = VERR_NOT_SUPPORTED;
    1970     }
    1971     else
    1972         rc = VERR_VD_NOT_OPENED;
    1973 
    1974     LogFlowFunc(("returns %Rrc\n", rc));
    1975     return rc;
    1976 }
    1977 
    1978 /** @copydoc VBOXHDDBACKEND::pfnGetUuid */
    1979 static int vhdGetUuid(void *pBackendData, PRTUUID pUuid)
    1980 {
    1981     LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
    1982     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1983     int rc;
    1984 
    1985     AssertPtr(pImage);
    1986 
    1987     if (pImage)
    1988     {
    1989         *pUuid = pImage->ImageUuid;
    1990         rc = VINF_SUCCESS;
    1991     }
    1992     else
    1993         rc = VERR_VD_NOT_OPENED;
    1994 
    1995     LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
    1996     return rc;
    1997 }
    1998 
    1999 /** @copydoc VBOXHDDBACKEND::pfnSetUuid */
    2000 static int vhdSetUuid(void *pBackendData, PCRTUUID pUuid)
    2001 {
    2002     LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
    2003     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    2004     int rc;
    2005 
    2006     AssertPtr(pImage);
    2007 
    2008     if (pImage)
    2009     {
    2010         if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    2011         {
    2012             pImage->ImageUuid = *pUuid;
    2013             /* Update the footer copy. It will get written to disk when the image is closed. */
    2014             memcpy(&pImage->vhdFooterCopy.UniqueID, pUuid, 16);
    2015             /* Update checksum. */
    2016             pImage->vhdFooterCopy.Checksum = 0;
    2017             pImage->vhdFooterCopy.Checksum = RT_H2BE_U32(vhdChecksum(&pImage->vhdFooterCopy, sizeof(VHDFooter)));
    2018 
    2019             /* Need to update the dynamic disk header to update the disk footer copy at the beginning. */
    2020             if (!(pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED))
    2021                 pImage->fDynHdrNeedsUpdate = true;
    2022             rc = VINF_SUCCESS;
    2023         }
    2024         else
    2025             rc = VERR_VD_IMAGE_READ_ONLY;
    2026     }
    2027     else
    2028         rc = VERR_VD_NOT_OPENED;
    2029 
    2030     LogFlowFunc(("returns %Rrc\n", rc));
    2031     return rc;
    2032 }
    2033 
    2034 /** @copydoc VBOXHDDBACKEND::pfnGetModificationUuid */
    2035 static int vhdGetModificationUuid(void *pBackendData, PRTUUID pUuid)
    2036 {
    2037     LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
    2038     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    2039     int rc;
    2040 
    2041     AssertPtr(pImage);
    2042 
    2043     if (pImage)
    2044         rc = VERR_NOT_SUPPORTED;
    2045     else
    2046         rc = VERR_VD_NOT_OPENED;
    2047 
    2048     LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
    2049     return rc;
    2050 }
    2051 
    2052 /** @copydoc VBOXHDDBACKEND::pfnSetModificationUuid */
    2053 static int vhdSetModificationUuid(void *pBackendData, PCRTUUID pUuid)
    2054 {
    2055     LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
    2056     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    2057     int rc;
    2058 
    2059     AssertPtr(pImage);
    2060 
    2061     if (pImage)
    2062     {
    2063         if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    2064             rc = VERR_NOT_SUPPORTED;
    2065         else
    2066             rc = VERR_VD_IMAGE_READ_ONLY;
    2067     }
    2068     else
    2069         rc = VERR_VD_NOT_OPENED;
    2070 
    2071     LogFlowFunc(("returns %Rrc\n", rc));
    2072     return rc;
    2073 }
    2074 
    2075 /** @copydoc VBOXHDDBACKEND::pfnGetParentUuid */
    2076 static int vhdGetParentUuid(void *pBackendData, PRTUUID pUuid)
    2077 {
    2078     LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
    2079     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    2080     int rc;
    2081 
    2082     AssertPtr(pImage);
    2083 
    2084     if (pImage)
    2085     {
    2086         *pUuid = pImage->ParentUuid;
    2087         rc = VINF_SUCCESS;
    2088     }
    2089     else
    2090         rc = VERR_VD_NOT_OPENED;
    2091 
    2092     LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
    2093     return rc;
    2094 }
    2095 
    2096 /** @copydoc VBOXHDDBACKEND::pfnSetParentUuid */
    2097 static int vhdSetParentUuid(void *pBackendData, PCRTUUID pUuid)
    2098 {
    2099     LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
    2100     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    2101     int rc = VINF_SUCCESS;
    2102 
    2103     AssertPtr(pImage);
    2104 
    2105     if (pImage && pImage->pStorage)
    2106     {
    2107         if (!(pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED))
    2108         {
    2109             pImage->ParentUuid = *pUuid;
    2110             pImage->fDynHdrNeedsUpdate = true;
    2111         }
    2112         else
    2113             rc = VERR_VD_IMAGE_READ_ONLY;
    2114     }
    2115     else
    2116         rc = VERR_VD_NOT_OPENED;
    2117 
    2118     LogFlowFunc(("returns %Rrc\n", rc));
    2119     return rc;
    2120 }
    2121 
    2122 /** @copydoc VBOXHDDBACKEND::pfnGetParentModificationUuid */
    2123 static int vhdGetParentModificationUuid(void *pBackendData, PRTUUID pUuid)
    2124 {
    2125     LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
    2126     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    2127     int rc;
    2128 
    2129     AssertPtr(pImage);
    2130 
    2131     if (pImage)
    2132         rc = VERR_NOT_SUPPORTED;
    2133     else
    2134         rc = VERR_VD_NOT_OPENED;
    2135 
    2136     LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
    2137     return rc;
    2138 }
    2139 
    2140 /** @copydoc VBOXHDDBACKEND::pfnSetParentModificationUuid */
    2141 static int vhdSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid)
    2142 {
    2143     LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
    2144     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    2145     int rc;
    2146 
    2147     AssertPtr(pImage);
    2148 
    2149     if (pImage)
    2150     {
    2151         if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    2152             rc = VERR_NOT_SUPPORTED;
    2153         else
    2154             rc = VERR_VD_IMAGE_READ_ONLY;
    2155     }
    2156     else
    2157         rc = VERR_VD_NOT_OPENED;
    2158 
    2159     LogFlowFunc(("returns %Rrc\n", rc));
    2160     return rc;
    2161 }
    2162 
    2163 /** @copydoc VBOXHDDBACKEND::pfnDump */
    2164 static void vhdDump(void *pBackendData)
    2165 {
    2166     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    2167 
    2168     AssertPtr(pImage);
    2169     if (pImage)
    2170     {
    2171         vdIfErrorMessage(pImage->pIfError, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%u\n",
    2172                          pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors,
    2173                          pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors,
    2174                          VHD_SECTOR_SIZE);
    2175         vdIfErrorMessage(pImage->pIfError, "Header: uuidCreation={%RTuuid}\n", &pImage->ImageUuid);
    2176         vdIfErrorMessage(pImage->pIfError, "Header: uuidParent={%RTuuid}\n", &pImage->ParentUuid);
    2177     }
    2178 }
    2179 
    2180 /** @copydoc VBOXHDDBACKEND::pfnGetTimestamp */
    2181 static int vhdGetTimeStamp(void *pBackendData, PRTTIMESPEC pTimeStamp)
    2182 {
    2183     int rc = VINF_SUCCESS;
    2184     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    2185 
    2186     AssertPtr(pImage);
    2187 
    2188     if (pImage)
    2189         rc = vdIfIoIntFileGetModificationTime(pImage->pIfIo, pImage->pszFilename, pTimeStamp);
    2190     else
    2191         rc = VERR_VD_NOT_OPENED;
    2192 
    2193     LogFlowFunc(("returns %Rrc\n", rc));
    2194     return rc;
    2195 }
    2196 
    2197 /** @copydoc VBOXHDDBACKEND::pfnGetParentTimeStamp */
    2198 static int vhdGetParentTimeStamp(void *pBackendData, PRTTIMESPEC pTimeStamp)
    2199 {
    2200     int rc = VINF_SUCCESS;
    2201     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    2202 
    2203     AssertPtr(pImage);
    2204 
    2205     if (pImage)
    2206         vhdTime2RtTime(pTimeStamp, pImage->u32ParentTimeStamp);
    2207     else
    2208         rc = VERR_VD_NOT_OPENED;
    2209 
    2210     LogFlowFunc(("returns %Rrc\n", rc));
    2211     return rc;
    2212 }
    2213 
    2214 /** @copydoc VBOXHDDBACKEND::pfnSetParentTimeStamp */
    2215 static int vhdSetParentTimeStamp(void *pBackendData, PCRTTIMESPEC pTimeStamp)
    2216 {
    2217     int rc = VINF_SUCCESS;
    2218     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    2219 
    2220     AssertPtr(pImage);
    2221     if (pImage)
    2222     {
    2223         if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    2224             rc = VERR_VD_IMAGE_READ_ONLY;
    2225         else
    2226         {
    2227             pImage->u32ParentTimeStamp = vhdRtTime2VhdTime(pTimeStamp);
    2228             pImage->fDynHdrNeedsUpdate = true;
    2229         }
    2230     }
    2231     else
    2232         rc = VERR_VD_NOT_OPENED;
    2233 
    2234     LogFlowFunc(("returns %Rrc\n", rc));
    2235     return rc;
    2236 }
    2237 
    2238 /** @copydoc VBOXHDDBACKEND::pfnGetParentFilename */
    2239 static int vhdGetParentFilename(void *pBackendData, char **ppszParentFilename)
    2240 {
    2241     int rc = VINF_SUCCESS;
    2242     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    2243 
    2244     AssertPtr(pImage);
    2245     if (pImage)
    2246         *ppszParentFilename = RTStrDup(pImage->pszParentFilename);
    2247     else
    2248         rc = VERR_VD_NOT_OPENED;
    2249 
    2250     LogFlowFunc(("returns %Rrc\n", rc));
    2251     return rc;
    2252 }
    2253 
    2254 /** @copydoc VBOXHDDBACKEND::pfnSetParentFilename */
    2255 static int vhdSetParentFilename(void *pBackendData, const char *pszParentFilename)
    2256 {
    2257     int rc = VINF_SUCCESS;
    2258     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    2259 
    2260     AssertPtr(pImage);
    2261     if (pImage)
    2262     {
    2263         if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    2264             rc = VERR_VD_IMAGE_READ_ONLY;
    2265         else
    2266         {
    2267             if (pImage->pszParentFilename)
    2268                 RTStrFree(pImage->pszParentFilename);
    2269             pImage->pszParentFilename = RTStrDup(pszParentFilename);
    2270             if (!pImage->pszParentFilename)
    2271                 rc = VERR_NO_MEMORY;
    2272             else
    2273                 pImage->fDynHdrNeedsUpdate = true;
    2274         }
    2275     }
    2276     else
    2277         rc = VERR_VD_NOT_OPENED;
    2278 
    2279     LogFlowFunc(("returns %Rrc\n", rc));
    2280     return rc;
    2281 }
    2282 
    2283 /** @copydoc VBOXHDDBACKEND::pfnAsyncRead */
    2284 static int vhdAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbRead,
    2285                         PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
     1453static int vhdRead(void *pBackendData, uint64_t uOffset, size_t cbRead,
     1454                   PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
    22861455{
    22871456    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     
    23971566}
    23981567
    2399 /** @copydoc VBOXHDDBACKEND::pfnAsyncWrite */
    2400 static int vhdAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbWrite,
    2401                          PVDIOCTX pIoCtx,
    2402                          size_t *pcbWriteProcess, size_t *pcbPreRead,
    2403                          size_t *pcbPostRead, unsigned fWrite)
     1568/** @copydoc VBOXHDDBACKEND::pfnWrite */
     1569static int vhdWrite(void *pBackendData, uint64_t uOffset, size_t cbWrite,
     1570                    PVDIOCTX pIoCtx, size_t *pcbWriteProcess, size_t *pcbPreRead,
     1571                    size_t *pcbPostRead, unsigned fWrite)
    24041572{
    24051573    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     
    26321800}
    26331801
    2634 /** @copydoc VBOXHDDBACKEND::pfnAsyncFlush */
    2635 static int vhdAsyncFlush(void *pBackendData, PVDIOCTX pIoCtx)
     1802/** @copydoc VBOXHDDBACKEND::pfnFlush */
     1803static int vhdFlush(void *pBackendData, PVDIOCTX pIoCtx)
    26361804{
    26371805    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     
    26391807    /* No need to write anything here. Data is always updated on a write. */
    26401808    return vdIfIoIntFileFlush(pImage->pIfIo, pImage->pStorage, pIoCtx, NULL, NULL);
     1809}
     1810
     1811/** @copydoc VBOXHDDBACKEND::pfnGetVersion */
     1812static unsigned vhdGetVersion(void *pBackendData)
     1813{
     1814    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     1815    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     1816    unsigned ver = 0;
     1817
     1818    AssertPtr(pImage);
     1819
     1820    if (pImage)
     1821        ver = 1; /**< @todo use correct version */
     1822
     1823    LogFlowFunc(("returns %u\n", ver));
     1824    return ver;
     1825}
     1826
     1827/** @copydoc VBOXHDDBACKEND::pfnGetSize */
     1828static uint64_t vhdGetSize(void *pBackendData)
     1829{
     1830    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     1831    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     1832    uint64_t cb = 0;
     1833
     1834    AssertPtr(pImage);
     1835
     1836    if (pImage && pImage->pStorage)
     1837        cb = pImage->cbSize;
     1838
     1839    LogFlowFunc(("returns %llu\n", cb));
     1840    return cb;
     1841}
     1842
     1843/** @copydoc VBOXHDDBACKEND::pfnGetFileSize */
     1844static uint64_t vhdGetFileSize(void *pBackendData)
     1845{
     1846    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     1847    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     1848    uint64_t cb = 0;
     1849
     1850    AssertPtr(pImage);
     1851
     1852    if (pImage && pImage->pStorage)
     1853        cb = pImage->uCurrentEndOfFile + sizeof(VHDFooter);
     1854
     1855    LogFlowFunc(("returns %lld\n", cb));
     1856    return cb;
     1857}
     1858
     1859/** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */
     1860static int vhdGetPCHSGeometry(void *pBackendData, PVDGEOMETRY pPCHSGeometry)
     1861{
     1862    LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry));
     1863    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     1864    int rc;
     1865
     1866    AssertPtr(pImage);
     1867
     1868    if (pImage)
     1869    {
     1870        if (pImage->PCHSGeometry.cCylinders)
     1871        {
     1872            *pPCHSGeometry = pImage->PCHSGeometry;
     1873            rc = VINF_SUCCESS;
     1874        }
     1875        else
     1876            rc = VERR_VD_GEOMETRY_NOT_SET;
     1877    }
     1878    else
     1879        rc = VERR_VD_NOT_OPENED;
     1880
     1881    LogFlowFunc(("returns %Rrc (CHS=%u/%u/%u)\n", rc, pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors));
     1882    return rc;
     1883}
     1884
     1885/** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */
     1886static int vhdSetPCHSGeometry(void *pBackendData, PCVDGEOMETRY pPCHSGeometry)
     1887{
     1888    LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
     1889    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     1890    int rc;
     1891
     1892    AssertPtr(pImage);
     1893
     1894    if (pImage)
     1895    {
     1896        if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     1897        {
     1898            rc = VERR_VD_IMAGE_READ_ONLY;
     1899            goto out;
     1900        }
     1901
     1902        pImage->PCHSGeometry = *pPCHSGeometry;
     1903        rc = VINF_SUCCESS;
     1904    }
     1905    else
     1906        rc = VERR_VD_NOT_OPENED;
     1907
     1908out:
     1909    LogFlowFunc(("returns %Rrc\n", rc));
     1910    return rc;
     1911}
     1912
     1913/** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */
     1914static int vhdGetLCHSGeometry(void *pBackendData, PVDGEOMETRY pLCHSGeometry)
     1915{
     1916LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry));
     1917    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     1918    int rc;
     1919
     1920    AssertPtr(pImage);
     1921
     1922    if (pImage)
     1923    {
     1924        if (pImage->LCHSGeometry.cCylinders)
     1925        {
     1926            *pLCHSGeometry = pImage->LCHSGeometry;
     1927            rc = VINF_SUCCESS;
     1928        }
     1929        else
     1930            rc = VERR_VD_GEOMETRY_NOT_SET;
     1931    }
     1932    else
     1933        rc = VERR_VD_NOT_OPENED;
     1934
     1935    LogFlowFunc(("returns %Rrc (CHS=%u/%u/%u)\n", rc, pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors));
     1936    return rc;
     1937}
     1938
     1939/** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */
     1940static int vhdSetLCHSGeometry(void *pBackendData, PCVDGEOMETRY pLCHSGeometry)
     1941{
     1942    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     1943    int rc;
     1944
     1945    AssertPtr(pImage);
     1946
     1947    if (pImage)
     1948    {
     1949        if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     1950        {
     1951            rc = VERR_VD_IMAGE_READ_ONLY;
     1952            goto out;
     1953        }
     1954
     1955        pImage->LCHSGeometry = *pLCHSGeometry;
     1956        rc = VINF_SUCCESS;
     1957    }
     1958    else
     1959        rc = VERR_VD_NOT_OPENED;
     1960
     1961out:
     1962    LogFlowFunc(("returns %Rrc\n", rc));
     1963    return rc;
     1964}
     1965
     1966/** @copydoc VBOXHDDBACKEND::pfnGetImageFlags */
     1967static unsigned vhdGetImageFlags(void *pBackendData)
     1968{
     1969    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     1970    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     1971    unsigned uImageFlags;
     1972
     1973    AssertPtr(pImage);
     1974
     1975    if (pImage)
     1976        uImageFlags = pImage->uImageFlags;
     1977    else
     1978        uImageFlags = 0;
     1979
     1980    LogFlowFunc(("returns %#x\n", uImageFlags));
     1981    return uImageFlags;
     1982}
     1983
     1984/** @copydoc VBOXHDDBACKEND::pfnGetOpenFlags */
     1985static unsigned vhdGetOpenFlags(void *pBackendData)
     1986{
     1987    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     1988    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     1989    unsigned uOpenFlags;
     1990
     1991    AssertPtr(pImage);
     1992
     1993    if (pImage)
     1994        uOpenFlags = pImage->uOpenFlags;
     1995    else
     1996        uOpenFlags = 0;
     1997
     1998    LogFlowFunc(("returns %#x\n", uOpenFlags));
     1999    return uOpenFlags;
     2000}
     2001
     2002/** @copydoc VBOXHDDBACKEND::pfnSetOpenFlags */
     2003static int vhdSetOpenFlags(void *pBackendData, unsigned uOpenFlags)
     2004{
     2005    LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags));
     2006    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2007    int rc;
     2008
     2009    /* Image must be opened and the new flags must be valid. */
     2010    if (!pImage || (uOpenFlags & ~(  VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO
     2011                                   | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE
     2012                                   | VD_OPEN_FLAGS_SEQUENTIAL | VD_OPEN_FLAGS_SKIP_CONSISTENCY_CHECKS)))
     2013    {
     2014        rc = VERR_INVALID_PARAMETER;
     2015        goto out;
     2016    }
     2017
     2018    /* Implement this operation via reopening the image. */
     2019    rc = vhdFreeImage(pImage, false);
     2020    if (RT_FAILURE(rc))
     2021        goto out;
     2022    rc = vhdOpenImage(pImage, uOpenFlags);
     2023
     2024out:
     2025    LogFlowFunc(("returns %Rrc\n", rc));
     2026    return rc;
     2027}
     2028
     2029/** @copydoc VBOXHDDBACKEND::pfnGetComment */
     2030static int vhdGetComment(void *pBackendData, char *pszComment,
     2031                         size_t cbComment)
     2032{
     2033    LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment));
     2034    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2035    int rc;
     2036
     2037    AssertPtr(pImage);
     2038
     2039    if (pImage)
     2040        rc = VERR_NOT_SUPPORTED;
     2041    else
     2042        rc = VERR_VD_NOT_OPENED;
     2043
     2044    LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment));
     2045    return rc;
     2046}
     2047
     2048/** @copydoc VBOXHDDBACKEND::pfnSetComment */
     2049static int vhdSetComment(void *pBackendData, const char *pszComment)
     2050{
     2051    LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment));
     2052    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2053    int rc;
     2054
     2055    AssertPtr(pImage);
     2056
     2057    if (pImage)
     2058    {
     2059        if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     2060            rc = VERR_VD_IMAGE_READ_ONLY;
     2061        else
     2062            rc = VERR_NOT_SUPPORTED;
     2063    }
     2064    else
     2065        rc = VERR_VD_NOT_OPENED;
     2066
     2067    LogFlowFunc(("returns %Rrc\n", rc));
     2068    return rc;
     2069}
     2070
     2071/** @copydoc VBOXHDDBACKEND::pfnGetUuid */
     2072static int vhdGetUuid(void *pBackendData, PRTUUID pUuid)
     2073{
     2074    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
     2075    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2076    int rc;
     2077
     2078    AssertPtr(pImage);
     2079
     2080    if (pImage)
     2081    {
     2082        *pUuid = pImage->ImageUuid;
     2083        rc = VINF_SUCCESS;
     2084    }
     2085    else
     2086        rc = VERR_VD_NOT_OPENED;
     2087
     2088    LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
     2089    return rc;
     2090}
     2091
     2092/** @copydoc VBOXHDDBACKEND::pfnSetUuid */
     2093static int vhdSetUuid(void *pBackendData, PCRTUUID pUuid)
     2094{
     2095    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
     2096    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2097    int rc;
     2098
     2099    AssertPtr(pImage);
     2100
     2101    if (pImage)
     2102    {
     2103        if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     2104        {
     2105            pImage->ImageUuid = *pUuid;
     2106            /* Update the footer copy. It will get written to disk when the image is closed. */
     2107            memcpy(&pImage->vhdFooterCopy.UniqueID, pUuid, 16);
     2108            /* Update checksum. */
     2109            pImage->vhdFooterCopy.Checksum = 0;
     2110            pImage->vhdFooterCopy.Checksum = RT_H2BE_U32(vhdChecksum(&pImage->vhdFooterCopy, sizeof(VHDFooter)));
     2111
     2112            /* Need to update the dynamic disk header to update the disk footer copy at the beginning. */
     2113            if (!(pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED))
     2114                pImage->fDynHdrNeedsUpdate = true;
     2115            rc = VINF_SUCCESS;
     2116        }
     2117        else
     2118            rc = VERR_VD_IMAGE_READ_ONLY;
     2119    }
     2120    else
     2121        rc = VERR_VD_NOT_OPENED;
     2122
     2123    LogFlowFunc(("returns %Rrc\n", rc));
     2124    return rc;
     2125}
     2126
     2127/** @copydoc VBOXHDDBACKEND::pfnGetModificationUuid */
     2128static int vhdGetModificationUuid(void *pBackendData, PRTUUID pUuid)
     2129{
     2130    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
     2131    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2132    int rc;
     2133
     2134    AssertPtr(pImage);
     2135
     2136    if (pImage)
     2137        rc = VERR_NOT_SUPPORTED;
     2138    else
     2139        rc = VERR_VD_NOT_OPENED;
     2140
     2141    LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
     2142    return rc;
     2143}
     2144
     2145/** @copydoc VBOXHDDBACKEND::pfnSetModificationUuid */
     2146static int vhdSetModificationUuid(void *pBackendData, PCRTUUID pUuid)
     2147{
     2148    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
     2149    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2150    int rc;
     2151
     2152    AssertPtr(pImage);
     2153
     2154    if (pImage)
     2155    {
     2156        if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     2157            rc = VERR_NOT_SUPPORTED;
     2158        else
     2159            rc = VERR_VD_IMAGE_READ_ONLY;
     2160    }
     2161    else
     2162        rc = VERR_VD_NOT_OPENED;
     2163
     2164    LogFlowFunc(("returns %Rrc\n", rc));
     2165    return rc;
     2166}
     2167
     2168/** @copydoc VBOXHDDBACKEND::pfnGetParentUuid */
     2169static int vhdGetParentUuid(void *pBackendData, PRTUUID pUuid)
     2170{
     2171    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
     2172    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2173    int rc;
     2174
     2175    AssertPtr(pImage);
     2176
     2177    if (pImage)
     2178    {
     2179        *pUuid = pImage->ParentUuid;
     2180        rc = VINF_SUCCESS;
     2181    }
     2182    else
     2183        rc = VERR_VD_NOT_OPENED;
     2184
     2185    LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
     2186    return rc;
     2187}
     2188
     2189/** @copydoc VBOXHDDBACKEND::pfnSetParentUuid */
     2190static int vhdSetParentUuid(void *pBackendData, PCRTUUID pUuid)
     2191{
     2192    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
     2193    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2194    int rc = VINF_SUCCESS;
     2195
     2196    AssertPtr(pImage);
     2197
     2198    if (pImage && pImage->pStorage)
     2199    {
     2200        if (!(pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED))
     2201        {
     2202            pImage->ParentUuid = *pUuid;
     2203            pImage->fDynHdrNeedsUpdate = true;
     2204        }
     2205        else
     2206            rc = VERR_VD_IMAGE_READ_ONLY;
     2207    }
     2208    else
     2209        rc = VERR_VD_NOT_OPENED;
     2210
     2211    LogFlowFunc(("returns %Rrc\n", rc));
     2212    return rc;
     2213}
     2214
     2215/** @copydoc VBOXHDDBACKEND::pfnGetParentModificationUuid */
     2216static int vhdGetParentModificationUuid(void *pBackendData, PRTUUID pUuid)
     2217{
     2218    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
     2219    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2220    int rc;
     2221
     2222    AssertPtr(pImage);
     2223
     2224    if (pImage)
     2225        rc = VERR_NOT_SUPPORTED;
     2226    else
     2227        rc = VERR_VD_NOT_OPENED;
     2228
     2229    LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
     2230    return rc;
     2231}
     2232
     2233/** @copydoc VBOXHDDBACKEND::pfnSetParentModificationUuid */
     2234static int vhdSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid)
     2235{
     2236    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
     2237    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2238    int rc;
     2239
     2240    AssertPtr(pImage);
     2241
     2242    if (pImage)
     2243    {
     2244        if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     2245            rc = VERR_NOT_SUPPORTED;
     2246        else
     2247            rc = VERR_VD_IMAGE_READ_ONLY;
     2248    }
     2249    else
     2250        rc = VERR_VD_NOT_OPENED;
     2251
     2252    LogFlowFunc(("returns %Rrc\n", rc));
     2253    return rc;
     2254}
     2255
     2256/** @copydoc VBOXHDDBACKEND::pfnDump */
     2257static void vhdDump(void *pBackendData)
     2258{
     2259    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2260
     2261    AssertPtr(pImage);
     2262    if (pImage)
     2263    {
     2264        vdIfErrorMessage(pImage->pIfError, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%u\n",
     2265                         pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors,
     2266                         pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors,
     2267                         VHD_SECTOR_SIZE);
     2268        vdIfErrorMessage(pImage->pIfError, "Header: uuidCreation={%RTuuid}\n", &pImage->ImageUuid);
     2269        vdIfErrorMessage(pImage->pIfError, "Header: uuidParent={%RTuuid}\n", &pImage->ParentUuid);
     2270    }
     2271}
     2272
     2273/** @copydoc VBOXHDDBACKEND::pfnGetTimestamp */
     2274static int vhdGetTimeStamp(void *pBackendData, PRTTIMESPEC pTimeStamp)
     2275{
     2276    int rc = VINF_SUCCESS;
     2277    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2278
     2279    AssertPtr(pImage);
     2280
     2281    if (pImage)
     2282        rc = vdIfIoIntFileGetModificationTime(pImage->pIfIo, pImage->pszFilename, pTimeStamp);
     2283    else
     2284        rc = VERR_VD_NOT_OPENED;
     2285
     2286    LogFlowFunc(("returns %Rrc\n", rc));
     2287    return rc;
     2288}
     2289
     2290/** @copydoc VBOXHDDBACKEND::pfnGetParentTimeStamp */
     2291static int vhdGetParentTimeStamp(void *pBackendData, PRTTIMESPEC pTimeStamp)
     2292{
     2293    int rc = VINF_SUCCESS;
     2294    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2295
     2296    AssertPtr(pImage);
     2297
     2298    if (pImage)
     2299        vhdTime2RtTime(pTimeStamp, pImage->u32ParentTimeStamp);
     2300    else
     2301        rc = VERR_VD_NOT_OPENED;
     2302
     2303    LogFlowFunc(("returns %Rrc\n", rc));
     2304    return rc;
     2305}
     2306
     2307/** @copydoc VBOXHDDBACKEND::pfnSetParentTimeStamp */
     2308static int vhdSetParentTimeStamp(void *pBackendData, PCRTTIMESPEC pTimeStamp)
     2309{
     2310    int rc = VINF_SUCCESS;
     2311    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2312
     2313    AssertPtr(pImage);
     2314    if (pImage)
     2315    {
     2316        if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     2317            rc = VERR_VD_IMAGE_READ_ONLY;
     2318        else
     2319        {
     2320            pImage->u32ParentTimeStamp = vhdRtTime2VhdTime(pTimeStamp);
     2321            pImage->fDynHdrNeedsUpdate = true;
     2322        }
     2323    }
     2324    else
     2325        rc = VERR_VD_NOT_OPENED;
     2326
     2327    LogFlowFunc(("returns %Rrc\n", rc));
     2328    return rc;
     2329}
     2330
     2331/** @copydoc VBOXHDDBACKEND::pfnGetParentFilename */
     2332static int vhdGetParentFilename(void *pBackendData, char **ppszParentFilename)
     2333{
     2334    int rc = VINF_SUCCESS;
     2335    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2336
     2337    AssertPtr(pImage);
     2338    if (pImage)
     2339        *ppszParentFilename = RTStrDup(pImage->pszParentFilename);
     2340    else
     2341        rc = VERR_VD_NOT_OPENED;
     2342
     2343    LogFlowFunc(("returns %Rrc\n", rc));
     2344    return rc;
     2345}
     2346
     2347/** @copydoc VBOXHDDBACKEND::pfnSetParentFilename */
     2348static int vhdSetParentFilename(void *pBackendData, const char *pszParentFilename)
     2349{
     2350    int rc = VINF_SUCCESS;
     2351    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2352
     2353    AssertPtr(pImage);
     2354    if (pImage)
     2355    {
     2356        if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     2357            rc = VERR_VD_IMAGE_READ_ONLY;
     2358        else
     2359        {
     2360            if (pImage->pszParentFilename)
     2361                RTStrFree(pImage->pszParentFilename);
     2362            pImage->pszParentFilename = RTStrDup(pszParentFilename);
     2363            if (!pImage->pszParentFilename)
     2364                rc = VERR_NO_MEMORY;
     2365            else
     2366                pImage->fDynHdrNeedsUpdate = true;
     2367        }
     2368    }
     2369    else
     2370        rc = VERR_VD_NOT_OPENED;
     2371
     2372    LogFlowFunc(("returns %Rrc\n", rc));
     2373    return rc;
    26412374}
    26422375
     
    30562789        /* Update header information in base image file. */
    30572790        pImage->fDynHdrNeedsUpdate = true;
    3058         vhdFlush(pImage);
     2791        vhdFlushImage(pImage);
    30592792    }
    30602793    /* Same size doesn't change the image at all. */
     
    34383171    /* pfnFlush */
    34393172    vhdFlush,
     3173    /* pfnDiscard */
     3174    NULL,
    34403175    /* pfnGetVersion */
    34413176    vhdGetVersion,
     
    34903225    /* pfnSetParentFilename */
    34913226    vhdSetParentFilename,
    3492     /* pfnAsyncRead */
    3493     vhdAsyncRead,
    3494     /* pfnAsyncWrite */
    3495     vhdAsyncWrite,
    3496     /* pfnAsyncFlush */
    3497     vhdAsyncFlush,
    34983227    /* pfnComposeLocation */
    34993228    genericFileComposeLocation,
     
    35043233    /* pfnResize */
    35053234    vhdResize,
    3506     /* pfnDiscard */
    3507     NULL,
    3508     /* pfnAsyncDiscard */
    3509     NULL,
    35103235    /* pfnRepair */
    35113236    vhdRepair
  • trunk/src/VBox/Storage/VHDX.cpp

    r44233 r44252  
    18641864
    18651865/** @copydoc VBOXHDDBACKEND::pfnRead */
    1866 static int vhdxRead(void *pBackendData, uint64_t uOffset, void *pvBuf,
    1867                    size_t cbToRead, size_t *pcbActuallyRead)
    1868 {
    1869     LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n", pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead));
     1866static int vhdxRead(void *pBackendData, uint64_t uOffset, size_t cbToRead,
     1867                    PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
     1868{
     1869    LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n",
     1870                 pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead));
    18701871    PVHDXIMAGE pImage = (PVHDXIMAGE)pBackendData;
    18711872    int rc = VINF_SUCCESS;
     
    18961897            case VHDX_BAT_ENTRY_PAYLOAD_BLOCK_UNMAPPED:
    18971898            {
    1898                 memset(pvBuf, 0, cbToRead);
     1899                vdIfIoIntIoCtxSet(pImage->pIfIo, pIoCtx, 0, cbToRead);
    18991900                break;
    19001901            }
     
    19021903            {
    19031904                uint64_t offFile = VHDX_BAT_ENTRY_GET_FILE_OFFSET(uBatEntry) + offRead;
    1904                 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, offFile,
    1905                                            pvBuf, cbToRead);
     1905                rc = vdIfIoIntFileReadUser(pImage->pIfIo, pImage->pStorage, offFile,
     1906                                           pIoCtx, cbToRead);
    19061907                break;
    19071908            }
     
    19211922
    19221923/** @copydoc VBOXHDDBACKEND::pfnWrite */
    1923 static int vhdxWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf,
    1924                     size_t cbToWrite, size_t *pcbWriteProcess,
    1925                     size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite)
    1926 {
    1927     LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n",
    1928                  pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));
     1924static int vhdxWrite(void *pBackendData, uint64_t uOffset,  size_t cbToWrite,
     1925                     PVDIOCTX pIoCtx, size_t *pcbWriteProcess, size_t *pcbPreRead,
     1926                    size_t *pcbPostRead, unsigned fWrite)
     1927{
     1928    LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n",
     1929                 pBackendData, uOffset, pIoCtx, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));
    19291930    PVHDXIMAGE pImage = (PVHDXIMAGE)pBackendData;
    19301931    int rc;
     
    19471948
    19481949/** @copydoc VBOXHDDBACKEND::pfnFlush */
    1949 static int vhdxFlush(void *pBackendData)
    1950 {
    1951     LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     1950static int vhdxFlush(void *pBackendData, PVDIOCTX pIoCtx)
     1951{
     1952    LogFlowFunc(("pBackendData=%#p pIoCtx=%#p\n", pBackendData, pIoCtx));
    19521953    PVHDXIMAGE pImage = (PVHDXIMAGE)pBackendData;
    19531954    int rc;
     
    24272428    /* pfnFlush */
    24282429    vhdxFlush,
     2430    /* pfnDiscard */
     2431    NULL,
    24292432    /* pfnGetVersion */
    24302433    vhdxGetVersion,
     
    24792482    /* pfnSetParentFilename */
    24802483    NULL,
    2481     /* pfnAsyncRead */
    2482     NULL,
    2483     /* pfnAsyncWrite */
    2484     NULL,
    2485     /* pfnAsyncFlush */
    2486     NULL,
    24872484    /* pfnComposeLocation */
    24882485    genericFileComposeLocation,
     
    24932490    /* pfnResize */
    24942491    NULL,
    2495     /* pfnDiscard */
    2496     NULL,
    2497     /* pfnAsyncDiscard */
    2498     NULL,
    24992492    /* pfnRepair */
    25002493    NULL
  • trunk/src/VBox/Storage/VMDK.cpp

    r44233 r44252  
    233233    /** File open flags for consistency checking. */
    234234    unsigned         fOpen;
    235     /** Flag whether this file has been opened for async I/O. */
    236     bool             fAsyncIO;
    237235    /** Handle for sync/async file abstraction.*/
    238236    PVDIOSTORAGE     pStorage;
     
    530528
    531529static int vmdkCreateExtents(PVMDKIMAGE pImage, unsigned cExtents);
    532 static int vmdkFlushImage(PVMDKIMAGE pImage);
     530static int vmdkFlushImage(PVMDKIMAGE pImage, PVDIOCTX pIoCtx);
    533531static int vmdkSetImageComment(PVMDKIMAGE pImage, const char *pszComment);
    534532static int vmdkFreeImage(PVMDKIMAGE pImage, bool fDelete);
    535533
    536 static int vmdkAllocGrainAsyncComplete(void *pBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq);
     534static int vmdkAllocGrainComplete(void *pBackendData, PVDIOCTX pIoCtx,
     535                                  void *pvUser, int rcReq);
    537536
    538537/**
     
    541540 */
    542541static int vmdkFileOpen(PVMDKIMAGE pImage, PVMDKFILE *ppVmdkFile,
    543                         const char *pszFilename, uint32_t fOpen, bool fAsyncIO)
     542                        const char *pszFilename, uint32_t fOpen)
    544543{
    545544    int rc = VINF_SUCCESS;
     
    577576    }
    578577    pVmdkFile->fOpen = fOpen;
    579     pVmdkFile->fAsyncIO = fAsyncIO;
    580578
    581579    rc = vdIfIoIntFileOpen(pImage->pIfIo, pszFilename, fOpen,
     
    680678                                    uint64_t *puLBA, uint32_t *pcbMarkerData)
    681679{
    682     if (pExtent->pFile->fAsyncIO)
    683     {
    684         AssertMsgFailed(("TODO\n"));
    685         return VERR_NOT_SUPPORTED;
    686     }
    687     else
    688     {
    689         int rc;
    690         PRTZIPDECOMP pZip = NULL;
    691         VMDKMARKER *pMarker = (VMDKMARKER *)pExtent->pvCompGrain;
    692         size_t cbCompSize, cbActuallyRead;
    693 
    694         if (!pcvMarker)
    695         {
    696             rc = vdIfIoIntFileReadSync(pImage->pIfIo, pExtent->pFile->pStorage,
    697                                        uOffset, pMarker, RT_OFFSETOF(VMDKMARKER, uType));
    698             if (RT_FAILURE(rc))
    699                 return rc;
    700         }
    701         else
    702         {
    703             memcpy(pMarker, pcvMarker, RT_OFFSETOF(VMDKMARKER, uType));
    704             /* pcvMarker endianness has already been partially transformed, fix it */
    705             pMarker->uSector = RT_H2LE_U64(pMarker->uSector);
    706             pMarker->cbSize = RT_H2LE_U32(pMarker->cbSize);
    707         }
    708 
    709         cbCompSize = RT_LE2H_U32(pMarker->cbSize);
    710         if (cbCompSize == 0)
    711         {
    712             AssertMsgFailed(("VMDK: corrupted marker\n"));
    713             return VERR_VD_VMDK_INVALID_FORMAT;
    714         }
    715 
    716         /* Sanity check - the expansion ratio should be much less than 2. */
    717         Assert(cbCompSize < 2 * cbToRead);
    718         if (cbCompSize >= 2 * cbToRead)
    719             return VERR_VD_VMDK_INVALID_FORMAT;
    720 
    721         /* Compressed grain marker. Data follows immediately. */
     680    int rc;
     681    PRTZIPDECOMP pZip = NULL;
     682    VMDKMARKER *pMarker = (VMDKMARKER *)pExtent->pvCompGrain;
     683    size_t cbCompSize, cbActuallyRead;
     684
     685    if (!pcvMarker)
     686    {
    722687        rc = vdIfIoIntFileReadSync(pImage->pIfIo, pExtent->pFile->pStorage,
    723                                    uOffset + RT_OFFSETOF(VMDKMARKER, uType),
    724                                     (uint8_t *)pExtent->pvCompGrain
    725                                   + RT_OFFSETOF(VMDKMARKER, uType),
    726                                    RT_ALIGN_Z(  cbCompSize
    727                                               + RT_OFFSETOF(VMDKMARKER, uType),
    728                                               512)
    729                                    - RT_OFFSETOF(VMDKMARKER, uType));
    730 
    731         if (puLBA)
    732             *puLBA = RT_LE2H_U64(pMarker->uSector);
    733         if (pcbMarkerData)
    734             *pcbMarkerData = RT_ALIGN(  cbCompSize
    735                                       + RT_OFFSETOF(VMDKMARKER, uType),
    736                                       512);
    737 
    738         VMDKCOMPRESSIO InflateState;
    739         InflateState.pImage = pImage;
    740         InflateState.iOffset = -1;
    741         InflateState.cbCompGrain = cbCompSize + RT_OFFSETOF(VMDKMARKER, uType);
    742         InflateState.pvCompGrain = pExtent->pvCompGrain;
    743 
    744         rc = RTZipDecompCreate(&pZip, &InflateState, vmdkFileInflateHelper);
     688                                   uOffset, pMarker, RT_OFFSETOF(VMDKMARKER, uType));
    745689        if (RT_FAILURE(rc))
    746690            return rc;
    747         rc = RTZipDecompress(pZip, pvBuf, cbToRead, &cbActuallyRead);
    748         RTZipDecompDestroy(pZip);
    749         if (RT_FAILURE(rc))
    750         {
    751             if (rc == VERR_ZIP_CORRUPTED)
    752                 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: Compressed image is corrupted '%s'"), pExtent->pszFullname);
    753             return rc;
    754         }
    755         if (cbActuallyRead != cbToRead)
    756             rc = VERR_VD_VMDK_INVALID_FORMAT;
     691    }
     692    else
     693    {
     694        memcpy(pMarker, pcvMarker, RT_OFFSETOF(VMDKMARKER, uType));
     695        /* pcvMarker endianness has already been partially transformed, fix it */
     696        pMarker->uSector = RT_H2LE_U64(pMarker->uSector);
     697        pMarker->cbSize = RT_H2LE_U32(pMarker->cbSize);
     698    }
     699
     700    cbCompSize = RT_LE2H_U32(pMarker->cbSize);
     701    if (cbCompSize == 0)
     702    {
     703        AssertMsgFailed(("VMDK: corrupted marker\n"));
     704        return VERR_VD_VMDK_INVALID_FORMAT;
     705    }
     706
     707    /* Sanity check - the expansion ratio should be much less than 2. */
     708    Assert(cbCompSize < 2 * cbToRead);
     709    if (cbCompSize >= 2 * cbToRead)
     710        return VERR_VD_VMDK_INVALID_FORMAT;
     711
     712    /* Compressed grain marker. Data follows immediately. */
     713    rc = vdIfIoIntFileReadSync(pImage->pIfIo, pExtent->pFile->pStorage,
     714                               uOffset + RT_OFFSETOF(VMDKMARKER, uType),
     715                                (uint8_t *)pExtent->pvCompGrain
     716                              + RT_OFFSETOF(VMDKMARKER, uType),
     717                               RT_ALIGN_Z(  cbCompSize
     718                                          + RT_OFFSETOF(VMDKMARKER, uType),
     719                                          512)
     720                               - RT_OFFSETOF(VMDKMARKER, uType));
     721
     722    if (puLBA)
     723        *puLBA = RT_LE2H_U64(pMarker->uSector);
     724    if (pcbMarkerData)
     725        *pcbMarkerData = RT_ALIGN(  cbCompSize
     726                                  + RT_OFFSETOF(VMDKMARKER, uType),
     727                                  512);
     728
     729    VMDKCOMPRESSIO InflateState;
     730    InflateState.pImage = pImage;
     731    InflateState.iOffset = -1;
     732    InflateState.cbCompGrain = cbCompSize + RT_OFFSETOF(VMDKMARKER, uType);
     733    InflateState.pvCompGrain = pExtent->pvCompGrain;
     734
     735    rc = RTZipDecompCreate(&pZip, &InflateState, vmdkFileInflateHelper);
     736    if (RT_FAILURE(rc))
    757737        return rc;
    758     }
     738    rc = RTZipDecompress(pZip, pvBuf, cbToRead, &cbActuallyRead);
     739    RTZipDecompDestroy(pZip);
     740    if (RT_FAILURE(rc))
     741    {
     742        if (rc == VERR_ZIP_CORRUPTED)
     743            rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: Compressed image is corrupted '%s'"), pExtent->pszFullname);
     744        return rc;
     745    }
     746    if (cbActuallyRead != cbToRead)
     747        rc = VERR_VD_VMDK_INVALID_FORMAT;
     748    return rc;
    759749}
    760750
     
    789779                                    uint32_t *pcbMarkerData)
    790780{
    791     if (pExtent->pFile->fAsyncIO)
    792     {
    793         AssertMsgFailed(("TODO\n"));
    794         return VERR_NOT_SUPPORTED;
    795     }
    796     else
    797     {
    798         int rc;
    799         PRTZIPCOMP pZip = NULL;
    800         VMDKCOMPRESSIO DeflateState;
    801 
    802         DeflateState.pImage = pImage;
    803         DeflateState.iOffset = -1;
    804         DeflateState.cbCompGrain = pExtent->cbCompGrain;
    805         DeflateState.pvCompGrain = pExtent->pvCompGrain;
    806 
    807         rc = RTZipCompCreate(&pZip, &DeflateState, vmdkFileDeflateHelper,
    808                              RTZIPTYPE_ZLIB, RTZIPLEVEL_DEFAULT);
     781    int rc;
     782    PRTZIPCOMP pZip = NULL;
     783    VMDKCOMPRESSIO DeflateState;
     784
     785    DeflateState.pImage = pImage;
     786    DeflateState.iOffset = -1;
     787    DeflateState.cbCompGrain = pExtent->cbCompGrain;
     788    DeflateState.pvCompGrain = pExtent->pvCompGrain;
     789
     790    rc = RTZipCompCreate(&pZip, &DeflateState, vmdkFileDeflateHelper,
     791                         RTZIPTYPE_ZLIB, RTZIPLEVEL_DEFAULT);
     792    if (RT_FAILURE(rc))
     793        return rc;
     794    rc = RTZipCompress(pZip, pvBuf, cbToWrite);
     795    if (RT_SUCCESS(rc))
     796        rc = RTZipCompFinish(pZip);
     797    RTZipCompDestroy(pZip);
     798    if (RT_SUCCESS(rc))
     799    {
     800        Assert(   DeflateState.iOffset > 0
     801               && (size_t)DeflateState.iOffset <= DeflateState.cbCompGrain);
     802
     803        /* pad with zeroes to get to a full sector size */
     804        uint32_t uSize = DeflateState.iOffset;
     805        if (uSize % 512)
     806        {
     807            uint32_t uSizeAlign = RT_ALIGN(uSize, 512);
     808            memset((uint8_t *)pExtent->pvCompGrain + uSize, '\0',
     809                   uSizeAlign - uSize);
     810            uSize = uSizeAlign;
     811        }
     812
     813        if (pcbMarkerData)
     814            *pcbMarkerData = uSize;
     815
     816        /* Compressed grain marker. Data follows immediately. */
     817        VMDKMARKER *pMarker = (VMDKMARKER *)pExtent->pvCompGrain;
     818        pMarker->uSector = RT_H2LE_U64(uLBA);
     819        pMarker->cbSize = RT_H2LE_U32(  DeflateState.iOffset
     820                                      - RT_OFFSETOF(VMDKMARKER, uType));
     821        rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,
     822                                    uOffset, pMarker, uSize);
    809823        if (RT_FAILURE(rc))
    810824            return rc;
    811         rc = RTZipCompress(pZip, pvBuf, cbToWrite);
    812         if (RT_SUCCESS(rc))
    813             rc = RTZipCompFinish(pZip);
    814         RTZipCompDestroy(pZip);
    815         if (RT_SUCCESS(rc))
    816         {
    817             Assert(   DeflateState.iOffset > 0
    818                    && (size_t)DeflateState.iOffset <= DeflateState.cbCompGrain);
    819 
    820             /* pad with zeroes to get to a full sector size */
    821             uint32_t uSize = DeflateState.iOffset;
    822             if (uSize % 512)
    823             {
    824                 uint32_t uSizeAlign = RT_ALIGN(uSize, 512);
    825                 memset((uint8_t *)pExtent->pvCompGrain + uSize, '\0',
    826                        uSizeAlign - uSize);
    827                 uSize = uSizeAlign;
    828             }
    829 
    830             if (pcbMarkerData)
    831                 *pcbMarkerData = uSize;
    832 
    833             /* Compressed grain marker. Data follows immediately. */
    834             VMDKMARKER *pMarker = (VMDKMARKER *)pExtent->pvCompGrain;
    835             pMarker->uSector = RT_H2LE_U64(uLBA);
    836             pMarker->cbSize = RT_H2LE_U32(  DeflateState.iOffset
    837                                           - RT_OFFSETOF(VMDKMARKER, uType));
    838             rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,
    839                                         uOffset, pMarker, uSize);
    840             if (RT_FAILURE(rc))
    841                 return rc;
    842         }
    843         return rc;
    844     }
     825    }
     826    return rc;
    845827}
    846828
     
    24302412 * Internal: write/update the descriptor part of the image.
    24312413 */
    2432 static int vmdkWriteDescriptor(PVMDKIMAGE pImage)
     2414static int vmdkWriteDescriptor(PVMDKIMAGE pImage, PVDIOCTX pIoCtx)
    24332415{
    24342416    int rc = VINF_SUCCESS;
     
    24362418    uint64_t uOffset;
    24372419    PVMDKFILE pDescFile;
    2438     void *pvDescriptor;
    2439     size_t cbDescriptor;
    2440 
    2441     if (pImage->pDescData)
    2442     {
    2443         /* Separate descriptor file. */
    2444         uOffset = 0;
    2445         cbLimit = 0;
    2446         pDescFile = pImage->pFile;
    2447     }
    2448     else
    2449     {
    2450         /* Embedded descriptor file. */
    2451         uOffset = VMDK_SECTOR2BYTE(pImage->pExtents[0].uDescriptorSector);
    2452         cbLimit = VMDK_SECTOR2BYTE(pImage->pExtents[0].cDescriptorSectors);
    2453         pDescFile = pImage->pExtents[0].pFile;
    2454     }
    2455     /* Bail out if there is no file to write to. */
    2456     if (pDescFile == NULL)
    2457         return VERR_INVALID_PARAMETER;
    2458 
    2459     rc = vmdkDescriptorPrepare(pImage, cbLimit, &pvDescriptor, &cbDescriptor);
    2460     if (RT_SUCCESS(rc))
    2461     {
    2462         rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pDescFile->pStorage, uOffset,
    2463                                     pvDescriptor, cbLimit ? cbLimit : cbDescriptor);
    2464         if (RT_FAILURE(rc))
    2465             rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error writing descriptor in '%s'"), pImage->pszFilename);
    2466 
    2467         if (RT_SUCCESS(rc) && !cbLimit)
    2468         {
    2469             rc = vdIfIoIntFileSetSize(pImage->pIfIo, pDescFile->pStorage, cbDescriptor);
    2470             if (RT_FAILURE(rc))
    2471                 rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error truncating descriptor in '%s'"), pImage->pszFilename);
    2472         }
    2473 
    2474         if (RT_SUCCESS(rc))
    2475             pImage->Descriptor.fDirty = false;
    2476 
    2477         RTMemFree(pvDescriptor);
    2478     }
    2479 
    2480     return rc;
    2481 }
    2482 
    2483 /**
    2484  * Internal: write/update the descriptor part of the image - async version.
    2485  */
    2486 static int vmdkWriteDescriptorAsync(PVMDKIMAGE pImage, PVDIOCTX pIoCtx)
    2487 {
    2488     int rc = VINF_SUCCESS;
    2489     uint64_t cbLimit;
    2490     uint64_t uOffset;
    2491     PVMDKFILE pDescFile;
    2492     void *pvDescriptor;
     2420    void *pvDescriptor = NULL;
    24932421    size_t cbDescriptor;
    24942422
     
    25332461        pImage->Descriptor.fDirty = false;
    25342462
    2535     RTMemFree(pvDescriptor);
     2463    if (pvDescriptor)
     2464        RTMemFree(pvDescriptor);
    25362465    return rc;
    25372466
     
    27812710 */
    27822711static int vmdkWriteMetaSparseExtent(PVMDKIMAGE pImage, PVMDKEXTENT pExtent,
    2783                                      uint64_t uOffset)
     2712                                     uint64_t uOffset, PVDIOCTX pIoCtx)
    27842713{
    27852714    SparseExtentHeader Header;
     
    28322761    Header.compressAlgorithm = RT_H2LE_U16(pExtent->uCompression);
    28332762
    2834     int rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,
    2835                                     uOffset, &Header, sizeof(Header));
    2836     AssertRC(rc);
    2837     if (RT_FAILURE(rc))
    2838         rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error writing extent header in '%s'"), pExtent->pszFullname);
    2839     return rc;
    2840 }
    2841 
    2842 /**
    2843  * Internal: write/update the metadata for a sparse extent - async version.
    2844  */
    2845 static int vmdkWriteMetaSparseExtentAsync(PVMDKIMAGE pImage, PVMDKEXTENT pExtent,
    2846                                           uint64_t uOffset, PVDIOCTX pIoCtx)
    2847 {
    2848     SparseExtentHeader Header;
    2849 
    2850     memset(&Header, '\0', sizeof(Header));
    2851     Header.magicNumber = RT_H2LE_U32(VMDK_SPARSE_MAGICNUMBER);
    2852     Header.version = RT_H2LE_U32(pExtent->uVersion);
    2853     Header.flags = RT_H2LE_U32(RT_BIT(0));
    2854     if (pExtent->pRGD)
    2855         Header.flags |= RT_H2LE_U32(RT_BIT(1));
    2856     if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
    2857         Header.flags |= RT_H2LE_U32(RT_BIT(16) | RT_BIT(17));
    2858     Header.capacity = RT_H2LE_U64(pExtent->cSectors);
    2859     Header.grainSize = RT_H2LE_U64(pExtent->cSectorsPerGrain);
    2860     Header.descriptorOffset = RT_H2LE_U64(pExtent->uDescriptorSector);
    2861     Header.descriptorSize = RT_H2LE_U64(pExtent->cDescriptorSectors);
    2862     Header.numGTEsPerGT = RT_H2LE_U32(pExtent->cGTEntries);
    2863     if (pExtent->fFooter && uOffset == 0)
    2864     {
    2865         if (pExtent->pRGD)
    2866         {
    2867             Assert(pExtent->uSectorRGD);
    2868             Header.rgdOffset = RT_H2LE_U64(VMDK_GD_AT_END);
    2869             Header.gdOffset = RT_H2LE_U64(VMDK_GD_AT_END);
    2870         }
    2871         else
    2872         {
    2873             Header.gdOffset = RT_H2LE_U64(VMDK_GD_AT_END);
    2874         }
    2875     }
    2876     else
    2877     {
    2878         if (pExtent->pRGD)
    2879         {
    2880             Assert(pExtent->uSectorRGD);
    2881             Header.rgdOffset = RT_H2LE_U64(pExtent->uSectorRGD);
    2882             Header.gdOffset = RT_H2LE_U64(pExtent->uSectorGD);
    2883         }
    2884         else
    2885         {
    2886             Header.gdOffset = RT_H2LE_U64(pExtent->uSectorGD);
    2887         }
    2888     }
    2889     Header.overHead = RT_H2LE_U64(pExtent->cOverheadSectors);
    2890     Header.uncleanShutdown = pExtent->fUncleanShutdown;
    2891     Header.singleEndLineChar = '\n';
    2892     Header.nonEndLineChar = ' ';
    2893     Header.doubleEndLineChar1 = '\r';
    2894     Header.doubleEndLineChar2 = '\n';
    2895     Header.compressAlgorithm = RT_H2LE_U16(pExtent->uCompression);
    2896 
    28972763    int rc = vdIfIoIntFileWriteMeta(pImage->pIfIo, pExtent->pFile->pStorage,
    28982764                                    uOffset, &Header, sizeof(Header),
     
    31162982
    31172983    rc = vmdkFileOpen(pImage, &pFile, pImage->pszFilename,
    3118                       VDOpenFlagsToFileOpenFlags(uOpenFlags, false /* fCreate */),
    3119                       false /* fAsyncIO */);
     2984                      VDOpenFlagsToFileOpenFlags(uOpenFlags, false /* fCreate */));
    31202985    if (RT_FAILURE(rc))
    31212986    {
     
    33573222                    rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname,
    33583223                                      VDOpenFlagsToFileOpenFlags(uOpenFlags,
    3359                                                                  false /* fCreate */),
    3360                                       false /* fAsyncIO */);
     3224                                                                 false /* fCreate */));
    33613225                    if (RT_FAILURE(rc))
    33623226                    {
     
    33853249                    rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname,
    33863250                                      VDOpenFlagsToFileOpenFlags(uOpenFlags,
    3387                                                                  false /* fCreate */),
    3388                                       true /* fAsyncIO */);
     3251                                                                 false /* fCreate */));
    33893252                    if (RT_FAILURE(rc))
    33903253                    {
     
    34233286
    34243287    /* Update the image metadata now in case has changed. */
    3425     rc = vmdkFlushImage(pImage);
     3288    rc = vmdkFlushImage(pImage, NULL);
    34263289    if (RT_FAILURE(rc))
    34273290        goto out;
     
    34883351        rc = vmdkFileOpen(pImage, &pImage->pFile, pImage->pszFilename,
    34893352                          VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags,
    3490                                                      true /* fCreate */),
    3491                           false /* fAsyncIO */);
     3353                                                     true /* fCreate */));
    34923354        if (RT_FAILURE(rc))
    34933355            return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pImage->pszFilename);
     
    35133375        rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname,
    35143376                          VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags & ~VD_OPEN_FLAGS_READONLY,
    3515                                                      false /* fCreate */),
    3516                           false /* fAsyncIO */);
     3377                                                     false /* fCreate */));
    35173378        if (RT_FAILURE(rc))
    35183379            return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not open raw disk file '%s'"), pExtent->pszFullname);
     
    35513412        rc = vmdkFileOpen(pImage, &pImage->pFile, pImage->pszFilename,
    35523413                          VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags,
    3553                                                      true /* fCreate */),
    3554                           false /* fAsyncIO */);
     3414                                                     true /* fCreate */));
    35553415        if (RT_FAILURE(rc))
    35563416            return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pImage->pszFilename);
     
    36233483                rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname,
    36243484                                  VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags,
    3625                                                              true /* fCreate */),
    3626                                   false /* fAsyncIO */);
     3485                                                             true /* fCreate */));
    36273486                if (RT_FAILURE(rc))
    36283487                    return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new partition data file '%s'"), pExtent->pszFullname);
     
    36593518                    rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname,
    36603519                                      VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags & ~VD_OPEN_FLAGS_READONLY,
    3661                                                                  false /* fCreate */),
    3662                                       false /* fAsyncIO */);
     3520                                                                 false /* fCreate */));
    36633521                    if (RT_FAILURE(rc))
    36643522                        return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not open raw partition file '%s'"), pExtent->pszFullname);
     
    37333591        rc = vmdkFileOpen(pImage, &pImage->pFile, pImage->pszFilename,
    37343592                          VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags,
    3735                                                      true /* fCreate */),
    3736                           false /* fAsyncIO */);
     3593                                                     true /* fCreate */));
    37373594        if (RT_FAILURE(rc))
    37383595            return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new sparse descriptor file '%s'"), pImage->pszFilename);
     
    38043661        rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname,
    38053662                          VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags,
    3806                                                      true /* fCreate */),
    3807                           false /* fAsyncIO */);
     3663                                                     true /* fCreate */));
    38083664        if (RT_FAILURE(rc))
    38093665            return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pExtent->pszFullname);
     
    40033859                        VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags,
    40043860                                                   true /* fCreate */)
    4005                       & ~RTFILE_O_READ,
    4006                       false /* fAsyncIO */);
     3861                      & ~RTFILE_O_READ);
    40073862    if (RT_FAILURE(rc))
    40083863        return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pExtent->pszFullname);
     
    42094064        pImage->pExtents[0].cDescriptorSectors = VMDK_BYTE2SECTOR(RT_ALIGN_64(  pImage->Descriptor.aLines[pImage->Descriptor.cLines]
    42104065                                                                              - pImage->Descriptor.aLines[0], 512));
    4211         rc = vmdkWriteMetaSparseExtent(pImage, &pImage->pExtents[0], 0);
     4066        rc = vmdkWriteMetaSparseExtent(pImage, &pImage->pExtents[0], 0, NULL);
    42124067        if (RT_FAILURE(rc))
    42134068        {
     
    42164071        }
    42174072
    4218         rc = vmdkWriteDescriptor(pImage);
     4073        rc = vmdkWriteDescriptor(pImage, NULL);
    42194074        if (RT_FAILURE(rc))
    42204075        {
     
    42244079    }
    42254080    else
    4226         rc = vmdkFlushImage(pImage);
     4081        rc = vmdkFlushImage(pImage, NULL);
    42274082
    42284083out:
     
    44494304
    44504305                uFileOffset += 512;
    4451                 rc = vmdkWriteMetaSparseExtent(pImage, pExtent, uFileOffset);
     4306                rc = vmdkWriteMetaSparseExtent(pImage, pExtent, uFileOffset, NULL);
    44524307                AssertRC(rc);
    44534308
     
    44614316        }
    44624317        else
    4463             vmdkFlushImage(pImage);
     4318            vmdkFlushImage(pImage, NULL);
    44644319
    44654320        if (pImage->pExtents != NULL)
     
    44944349 * Internal. Flush image data (and metadata) to disk.
    44954350 */
    4496 static int vmdkFlushImage(PVMDKIMAGE pImage)
     4351static int vmdkFlushImage(PVMDKIMAGE pImage, PVDIOCTX pIoCtx)
    44974352{
    44984353    PVMDKEXTENT pExtent;
     
    45024357    if (pImage->Descriptor.fDirty)
    45034358    {
    4504         rc = vmdkWriteDescriptor(pImage);
     4359        rc = vmdkWriteDescriptor(pImage, pIoCtx);
    45054360        if (RT_FAILURE(rc))
    45064361            goto out;
     
    45174372                    if (!pExtent->fFooter)
    45184373                    {
    4519                         rc = vmdkWriteMetaSparseExtent(pImage, pExtent, 0);
     4374                        rc = vmdkWriteMetaSparseExtent(pImage, pExtent, 0, pIoCtx);
    45204375                        if (RT_FAILURE(rc))
    45214376                            goto out;
     
    45304385                        uFileOffset = RT_ALIGN_64(uFileOffset, 512);
    45314386                        rc = vmdkWriteMetaSparseExtent(pImage, pExtent,
    4532                                                        uFileOffset);
     4387                                                       uFileOffset, pIoCtx);
    45334388                        if (RT_FAILURE(rc))
    45344389                            goto out;
     
    45634418                    && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    45644419                    && !(pExtent->pszBasename[0] == RTPATH_SLASH))
    4565                     rc = vdIfIoIntFileFlushSync(pImage->pIfIo, pExtent->pFile->pStorage);
     4420                    rc = vdIfIoIntFileFlush(pImage->pIfIo, pExtent->pFile->pStorage, pIoCtx,
     4421                                            NULL, NULL);
    45664422                break;
    45674423            case VMDKETYPE_ZERO:
     
    46214477 * number in the extent.
    46224478 */
    4623 static int vmdkGetSector(PVMDKIMAGE pImage, PVMDKEXTENT pExtent,
    4624                          uint64_t uSector, uint64_t *puExtentSector)
     4479static int vmdkGetSector(PVMDKIMAGE pImage, PVDIOCTX pIoCtx,
     4480                         PVMDKEXTENT pExtent, uint64_t uSector,
     4481                         uint64_t *puExtentSector)
    46254482{
    46264483    PVMDKGTCACHE pCache = pImage->pGTCache;
     
    46424499        return VINF_SUCCESS;
    46434500    }
    4644 
    4645     uGDIndex = uSector / pExtent->cSectorsPerGDE;
    4646     if (uGDIndex >= pExtent->cGDEntries)
    4647         return VERR_OUT_OF_RANGE;
    4648     uGTSector = pExtent->pGD[uGDIndex];
    4649     if (!uGTSector)
    4650     {
    4651         /* There is no grain table referenced by this grain directory
    4652          * entry. So there is absolutely no data in this area. */
    4653         *puExtentSector = 0;
    4654         return VINF_SUCCESS;
    4655     }
    4656 
    4657     uGTBlock = uSector / (pExtent->cSectorsPerGrain * VMDK_GT_CACHELINE_SIZE);
    4658     uGTHash = vmdkGTCacheHash(pCache, uGTBlock, pExtent->uExtent);
    4659     pGTCacheEntry = &pCache->aGTCache[uGTHash];
    4660     if (    pGTCacheEntry->uExtent != pExtent->uExtent
    4661         ||  pGTCacheEntry->uGTBlock != uGTBlock)
    4662     {
    4663         /* Cache miss, fetch data from disk. */
    4664         rc = vdIfIoIntFileReadSync(pImage->pIfIo, pExtent->pFile->pStorage,
    4665                                    VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
    4666                                    aGTDataTmp, sizeof(aGTDataTmp));
    4667         if (RT_FAILURE(rc))
    4668             return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot read grain table entry in '%s'"), pExtent->pszFullname);
    4669         pGTCacheEntry->uExtent = pExtent->uExtent;
    4670         pGTCacheEntry->uGTBlock = uGTBlock;
    4671         for (unsigned i = 0; i < VMDK_GT_CACHELINE_SIZE; i++)
    4672             pGTCacheEntry->aGTData[i] = RT_LE2H_U32(aGTDataTmp[i]);
    4673     }
    4674     uGTBlockIndex = (uSector / pExtent->cSectorsPerGrain) % VMDK_GT_CACHELINE_SIZE;
    4675     uint32_t uGrainSector = pGTCacheEntry->aGTData[uGTBlockIndex];
    4676     if (uGrainSector)
    4677         *puExtentSector = uGrainSector + uSector % pExtent->cSectorsPerGrain;
    4678     else
    4679         *puExtentSector = 0;
    4680     return VINF_SUCCESS;
    4681 }
    4682 
    4683 /**
    4684  * Internal. Get sector number in the extent file from the relative sector
    4685  * number in the extent - version for async access.
    4686  */
    4687 static int vmdkGetSectorAsync(PVMDKIMAGE pImage, PVDIOCTX pIoCtx,
    4688                               PVMDKEXTENT pExtent, uint64_t uSector,
    4689                               uint64_t *puExtentSector)
    4690 {
    4691     PVMDKGTCACHE pCache = pImage->pGTCache;
    4692     uint64_t uGDIndex, uGTSector, uGTBlock;
    4693     uint32_t uGTHash, uGTBlockIndex;
    4694     PVMDKGTCACHEENTRY pGTCacheEntry;
    4695     uint32_t aGTDataTmp[VMDK_GT_CACHELINE_SIZE];
    4696     int rc;
    46974501
    46984502    uGDIndex = uSector / pExtent->cSectorsPerGDE;
     
    47384542
    47394543/**
    4740  * Internal. Allocates a new grain table (if necessary), writes the grain
    4741  * and updates the grain table. The cache is also updated by this operation.
    4742  * This is separate from vmdkGetSector, because that should be as fast as
    4743  * possible. Most code from vmdkGetSector also appears here.
    4744  */
    4745 static int vmdkAllocGrain(PVMDKIMAGE pImage, PVMDKEXTENT pExtent,
    4746                           uint64_t uSector, const void *pvBuf,
    4747                           uint64_t cbWrite)
    4748 {
    4749     PVMDKGTCACHE pCache = pImage->pGTCache;
    4750     uint64_t uGDIndex, uGTSector, uRGTSector, uGTBlock;
    4751     uint64_t uFileOffset;
    4752     uint32_t uGTHash, uGTBlockIndex;
    4753     PVMDKGTCACHEENTRY pGTCacheEntry;
    4754     uint32_t aGTDataTmp[VMDK_GT_CACHELINE_SIZE];
    4755     int rc;
    4756 
    4757     uGDIndex = uSector / pExtent->cSectorsPerGDE;
    4758     if (uGDIndex >= pExtent->cGDEntries)
    4759         return VERR_OUT_OF_RANGE;
    4760     uGTSector = pExtent->pGD[uGDIndex];
    4761     if (pExtent->pRGD)
    4762         uRGTSector = pExtent->pRGD[uGDIndex];
    4763     else
    4764         uRGTSector = 0; /**< avoid compiler warning */
    4765     if (!uGTSector)
    4766     {
    4767         /* There is no grain table referenced by this grain directory
    4768          * entry. So there is absolutely no data in this area. Allocate
    4769          * a new grain table and put the reference to it in the GDs. */
    4770         uFileOffset = pExtent->uAppendPosition;
    4771         if (!uFileOffset)
    4772             return VERR_INTERNAL_ERROR;
    4773         Assert(!(uFileOffset % 512));
    4774         uFileOffset = RT_ALIGN_64(uFileOffset, 512);
    4775         uGTSector = VMDK_BYTE2SECTOR(uFileOffset);
    4776 
    4777         pExtent->uAppendPosition += pExtent->cGTEntries * sizeof(uint32_t);
    4778 
    4779         /* Normally the grain table is preallocated for hosted sparse extents
    4780          * that support more than 32 bit sector numbers. So this shouldn't
    4781          * ever happen on a valid extent. */
    4782         if (uGTSector > UINT32_MAX)
    4783             return VERR_VD_VMDK_INVALID_HEADER;
    4784 
    4785         /* Write grain table by writing the required number of grain table
    4786          * cache chunks. Avoids dynamic memory allocation, but is a bit
    4787          * slower. But as this is a pretty infrequently occurring case it
    4788          * should be acceptable. */
    4789         memset(aGTDataTmp, '\0', sizeof(aGTDataTmp));
    4790         for (unsigned i = 0;
    4791              i < pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE;
    4792              i++)
    4793         {
    4794             rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,
    4795                                         VMDK_SECTOR2BYTE(uGTSector) + i * sizeof(aGTDataTmp),
    4796                                         aGTDataTmp, sizeof(aGTDataTmp));
    4797             if (RT_FAILURE(rc))
    4798                 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write grain table allocation in '%s'"), pExtent->pszFullname);
    4799         }
    4800         pExtent->uAppendPosition = RT_ALIGN_64(  pExtent->uAppendPosition
    4801                                                + pExtent->cGTEntries * sizeof(uint32_t),
    4802                                                512);
    4803 
    4804         if (pExtent->pRGD)
    4805         {
    4806             AssertReturn(!uRGTSector, VERR_VD_VMDK_INVALID_HEADER);
    4807             uFileOffset = pExtent->uAppendPosition;
    4808             if (!uFileOffset)
    4809                 return VERR_INTERNAL_ERROR;
    4810             Assert(!(uFileOffset % 512));
    4811             uRGTSector = VMDK_BYTE2SECTOR(uFileOffset);
    4812 
    4813             pExtent->uAppendPosition += pExtent->cGTEntries * sizeof(uint32_t);
    4814 
    4815             /* Normally the redundant grain table is preallocated for hosted
    4816              * sparse extents that support more than 32 bit sector numbers. So
    4817              * this shouldn't ever happen on a valid extent. */
    4818             if (uRGTSector > UINT32_MAX)
    4819                 return VERR_VD_VMDK_INVALID_HEADER;
    4820 
    4821             /* Write backup grain table by writing the required number of grain
    4822              * table cache chunks. Avoids dynamic memory allocation, but is a
    4823              * bit slower. But as this is a pretty infrequently occurring case
    4824              * it should be acceptable. */
    4825             for (unsigned i = 0;
    4826                  i < pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE;
    4827                  i++)
    4828             {
    4829                 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,
    4830                                             VMDK_SECTOR2BYTE(uRGTSector) + i * sizeof(aGTDataTmp),
    4831                                             aGTDataTmp, sizeof(aGTDataTmp));
    4832                 if (RT_FAILURE(rc))
    4833                     return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain table allocation in '%s'"), pExtent->pszFullname);
    4834             }
    4835 
    4836             pExtent->uAppendPosition =   pExtent->uAppendPosition
    4837                                        + pExtent->cGTEntries * sizeof(uint32_t);
    4838         }
    4839 
    4840         /* Update the grain directory on disk (doing it before writing the
    4841          * grain table will result in a garbled extent if the operation is
    4842          * aborted for some reason. Otherwise the worst that can happen is
    4843          * some unused sectors in the extent. */
    4844         uint32_t uGTSectorLE = RT_H2LE_U64(uGTSector);
    4845         rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,
    4846                                     VMDK_SECTOR2BYTE(pExtent->uSectorGD) + uGDIndex * sizeof(uGTSectorLE),
    4847                                     &uGTSectorLE, sizeof(uGTSectorLE));
    4848         if (RT_FAILURE(rc))
    4849             return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write grain directory entry in '%s'"), pExtent->pszFullname);
    4850         if (pExtent->pRGD)
    4851         {
    4852             uint32_t uRGTSectorLE = RT_H2LE_U64(uRGTSector);
    4853             rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,
    4854                                         VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + uGDIndex * sizeof(uRGTSectorLE),
    4855                                         &uRGTSectorLE, sizeof(uRGTSectorLE));
    4856             if (RT_FAILURE(rc))
    4857                 return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain directory entry in '%s'"), pExtent->pszFullname);
    4858         }
    4859 
    4860         /* As the final step update the in-memory copy of the GDs. */
    4861         pExtent->pGD[uGDIndex] = uGTSector;
    4862         if (pExtent->pRGD)
    4863             pExtent->pRGD[uGDIndex] = uRGTSector;
    4864     }
    4865 
    4866     uFileOffset = pExtent->uAppendPosition;
    4867     if (!uFileOffset)
    4868         return VERR_INTERNAL_ERROR;
    4869     Assert(!(uFileOffset % 512));
    4870 
    4871     /* Write the data. Always a full grain, or we're in big trouble. */
    4872     if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
    4873     {
    4874         if (cbWrite != VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain))
    4875             return vdIfError(pImage->pIfError, VERR_INTERNAL_ERROR, RT_SRC_POS, N_("VMDK: not enough data for a compressed data block in '%s'"), pExtent->pszFullname);
    4876 
    4877         /* Invalidate cache, just in case some code incorrectly allows mixing
    4878          * of reads and writes. Normally shouldn't be needed. */
    4879         pExtent->uGrainSectorAbs = 0;
    4880 
    4881         /* Write compressed data block and the markers. */
    4882         uint32_t cbGrain = 0;
    4883         rc = vmdkFileDeflateSync(pImage, pExtent, uFileOffset,
    4884                                  pvBuf, cbWrite, uSector, &cbGrain);
    4885         if (RT_FAILURE(rc))
    4886         {
    4887             AssertRC(rc);
    4888             return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write allocated compressed data block in '%s'"), pExtent->pszFullname);
    4889         }
    4890         pExtent->uLastGrainAccess = uSector / pExtent->cSectorsPerGrain;
    4891         pExtent->uAppendPosition += cbGrain;
    4892     }
    4893     else
    4894     {
    4895         rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,
    4896                                     uFileOffset, pvBuf, cbWrite);
    4897         if (RT_FAILURE(rc))
    4898             return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write allocated data block in '%s'"), pExtent->pszFullname);
    4899         pExtent->uAppendPosition += cbWrite;
    4900     }
    4901 
    4902     /* Update the grain table (and the cache). */
    4903     uGTBlock = uSector / (pExtent->cSectorsPerGrain * VMDK_GT_CACHELINE_SIZE);
    4904     uGTHash = vmdkGTCacheHash(pCache, uGTBlock, pExtent->uExtent);
    4905     pGTCacheEntry = &pCache->aGTCache[uGTHash];
    4906     if (    pGTCacheEntry->uExtent != pExtent->uExtent
    4907         ||  pGTCacheEntry->uGTBlock != uGTBlock)
    4908     {
    4909         /* Cache miss, fetch data from disk. */
    4910         rc = vdIfIoIntFileReadSync(pImage->pIfIo, pExtent->pFile->pStorage,
    4911                                    VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
    4912                                    aGTDataTmp, sizeof(aGTDataTmp));
    4913         if (RT_FAILURE(rc))
    4914             return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot read allocated grain table entry in '%s'"), pExtent->pszFullname);
    4915         pGTCacheEntry->uExtent = pExtent->uExtent;
    4916         pGTCacheEntry->uGTBlock = uGTBlock;
    4917         for (unsigned i = 0; i < VMDK_GT_CACHELINE_SIZE; i++)
    4918             pGTCacheEntry->aGTData[i] = RT_LE2H_U32(aGTDataTmp[i]);
    4919     }
    4920     else
    4921     {
    4922         /* Cache hit. Convert grain table block back to disk format, otherwise
    4923          * the code below will write garbage for all but the updated entry. */
    4924         for (unsigned i = 0; i < VMDK_GT_CACHELINE_SIZE; i++)
    4925             aGTDataTmp[i] = RT_H2LE_U32(pGTCacheEntry->aGTData[i]);
    4926     }
    4927     uGTBlockIndex = (uSector / pExtent->cSectorsPerGrain) % VMDK_GT_CACHELINE_SIZE;
    4928     aGTDataTmp[uGTBlockIndex] = RT_H2LE_U32(VMDK_BYTE2SECTOR(uFileOffset));
    4929     pGTCacheEntry->aGTData[uGTBlockIndex] = VMDK_BYTE2SECTOR(uFileOffset);
    4930     /* Update grain table on disk. */
    4931     rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,
    4932                                 VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
    4933                                 aGTDataTmp, sizeof(aGTDataTmp));
    4934     if (RT_FAILURE(rc))
    4935         return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write updated grain table in '%s'"), pExtent->pszFullname);
    4936     if (pExtent->pRGD)
    4937     {
    4938         /* Update backup grain table on disk. */
    4939         rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,
    4940                                     VMDK_SECTOR2BYTE(uRGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
    4941                                     aGTDataTmp, sizeof(aGTDataTmp));
    4942         if (RT_FAILURE(rc))
    4943             return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write updated backup grain table in '%s'"), pExtent->pszFullname);
    4944     }
    4945 #ifdef VBOX_WITH_VMDK_ESX
    4946     if (RT_SUCCESS(rc) && pExtent->enmType == VMDKETYPE_ESX_SPARSE)
    4947     {
    4948         pExtent->uFreeSector = uGTSector + VMDK_BYTE2SECTOR(cbWrite);
    4949         pExtent->fMetaDirty = true;
    4950     }
    4951 #endif /* VBOX_WITH_VMDK_ESX */
    4952     return rc;
    4953 }
    4954 
    4955 /**
    49564544 * Internal. Writes the grain and also if necessary the grain tables.
    49574545 * Uses the grain table cache as a true grain table.
    49584546 */
    49594547static int vmdkStreamAllocGrain(PVMDKIMAGE pImage, PVMDKEXTENT pExtent,
    4960                                 uint64_t uSector, const void *pvBuf,
     4548                                uint64_t uSector, PVDIOCTX pIoCtx,
    49614549                                uint64_t cbWrite)
    49624550{
     
    49654553    uint32_t cbGrain = 0;
    49664554    uint32_t uCacheLine, uCacheEntry;
    4967     const void *pData = pvBuf;
     4555    const void *pData;
    49684556    int rc;
    49694557
     
    49964584     * to allocate something, we also need to detect the situation ourself. */
    49974585    if (   !(pImage->uOpenFlags & VD_OPEN_FLAGS_HONOR_ZEROES)
    4998         && ASMBitFirstSet((volatile void *)pvBuf, (uint32_t)cbWrite * 8) == -1)
     4586        && vdIfIoIntIoCtxIsZero(pImage->pIfIo, pIoCtx, cbWrite, true /* fAdvance */))
    49994587        return VINF_SUCCESS;
    50004588
     
    50334621    if (cbWrite != VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain))
    50344622    {
    5035         memcpy(pExtent->pvGrain, pvBuf, cbWrite);
     4623        vdIfIoIntIoCtxCopyFrom(pImage->pIfIo, pIoCtx, pExtent->pvGrain, cbWrite);
    50364624        memset((char *)pExtent->pvGrain + cbWrite, '\0',
    50374625               VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain) - cbWrite);
    50384626        pData = pExtent->pvGrain;
    50394627    }
     4628    else
     4629    {
     4630        RTSGSEG Segment;
     4631        unsigned cSegments = 1;
     4632        size_t cbSeg = 0;
     4633
     4634        cbSeg = vdIfIoIntIoCtxSegArrayCreate(pImage->pIfIo, pIoCtx, &Segment,
     4635                                             &cSegments, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain));
     4636        Assert(cbSeg == VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain));
     4637        pData = Segment.pvSeg;
     4638    }
    50404639    rc = vmdkFileDeflateSync(pImage, pExtent, uFileOffset, pData,
    50414640                             VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain),
     
    50544653
    50554654/**
    5056  * Internal: Updates the grain table during a async grain allocation.
     4655 * Internal: Updates the grain table during grain allocation.
    50574656 */
    5058 static int vmdkAllocGrainAsyncGTUpdate(PVMDKIMAGE pImage, PVMDKEXTENT pExtent,
    5059                                        PVDIOCTX pIoCtx,
    5060                                        PVMDKGRAINALLOCASYNC pGrainAlloc)
     4657static int vmdkAllocGrainGTUpdate(PVMDKIMAGE pImage, PVMDKEXTENT pExtent, PVDIOCTX pIoCtx,
     4658                                  PVMDKGRAINALLOCASYNC pGrainAlloc)
    50614659{
    50624660    int rc = VINF_SUCCESS;
     
    50884686                                   VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
    50894687                                   aGTDataTmp, sizeof(aGTDataTmp), pIoCtx,
    5090                                    &pMetaXfer, vmdkAllocGrainAsyncComplete, pGrainAlloc);
     4688                                   &pMetaXfer, vmdkAllocGrainComplete, pGrainAlloc);
    50914689        if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
    50924690        {
     
    51204718                                VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
    51214719                                aGTDataTmp, sizeof(aGTDataTmp), pIoCtx,
    5122                                 vmdkAllocGrainAsyncComplete, pGrainAlloc);
     4720                                vmdkAllocGrainComplete, pGrainAlloc);
    51234721    if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
    51244722        pGrainAlloc->cIoXfersPending++;
     
    51314729                                    VMDK_SECTOR2BYTE(uRGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
    51324730                                    aGTDataTmp, sizeof(aGTDataTmp), pIoCtx,
    5133                                     vmdkAllocGrainAsyncComplete, pGrainAlloc);
     4731                                    vmdkAllocGrainComplete, pGrainAlloc);
    51344732        if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
    51354733            pGrainAlloc->cIoXfersPending++;
     
    51534751 * Internal - complete the grain allocation by updating disk grain table if required.
    51544752 */
    5155 static int vmdkAllocGrainAsyncComplete(void *pBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq)
     4753static int vmdkAllocGrainComplete(void *pBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq)
    51564754{
    51574755    int rc = VINF_SUCCESS;
     
    51654763    pGrainAlloc->cIoXfersPending--;
    51664764    if (!pGrainAlloc->cIoXfersPending && pGrainAlloc->fGTUpdateNeeded)
    5167         rc = vmdkAllocGrainAsyncGTUpdate(pImage, pGrainAlloc->pExtent,
    5168                                          pIoCtx, pGrainAlloc);
     4765        rc = vmdkAllocGrainGTUpdate(pImage, pGrainAlloc->pExtent, pIoCtx, pGrainAlloc);
    51694766
    51704767    if (!pGrainAlloc->cIoXfersPending)
     
    51794776
    51804777/**
    5181  * Internal. Allocates a new grain table (if necessary) - async version.
     4778 * Internal. Allocates a new grain table (if necessary).
    51824779 */
    5183 static int vmdkAllocGrainAsync(PVMDKIMAGE pImage, PVMDKEXTENT pExtent,
    5184                                PVDIOCTX pIoCtx, uint64_t uSector,
    5185                                uint64_t cbWrite)
     4780static int vmdkAllocGrain(PVMDKIMAGE pImage, PVMDKEXTENT pExtent, PVDIOCTX pIoCtx,
     4781                          uint64_t uSector, uint64_t cbWrite)
    51864782{
    51874783    PVMDKGTCACHE pCache = pImage->pGTCache;
     
    51934789    LogFlowFunc(("pCache=%#p pExtent=%#p pIoCtx=%#p uSector=%llu cbWrite=%llu\n",
    51944790                 pCache, pExtent, pIoCtx, uSector, cbWrite));
    5195 
    5196     AssertReturn(!(pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED), VERR_NOT_SUPPORTED);
    51974791
    51984792    pGrainAlloc = (PVMDKGRAINALLOCASYNC)RTMemAllocZ(sizeof(VMDKGRAINALLOCASYNC));
     
    52484842                                    VMDK_SECTOR2BYTE(uGTSector),
    52494843                                    paGTDataTmp, cbGTDataTmp, pIoCtx,
    5250                                     vmdkAllocGrainAsyncComplete, pGrainAlloc);
     4844                                    vmdkAllocGrainComplete, pGrainAlloc);
    52514845        if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
    52524846            pGrainAlloc->cIoXfersPending++;
     
    52834877                                        VMDK_SECTOR2BYTE(uRGTSector),
    52844878                                        paGTDataTmp, cbGTDataTmp, pIoCtx,
    5285                                         vmdkAllocGrainAsyncComplete, pGrainAlloc);
     4879                                        vmdkAllocGrainComplete, pGrainAlloc);
    52864880            if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
    52874881                pGrainAlloc->cIoXfersPending++;
     
    53054899                                    VMDK_SECTOR2BYTE(pExtent->uSectorGD) + uGDIndex * sizeof(uGTSectorLE),
    53064900                                    &uGTSectorLE, sizeof(uGTSectorLE), pIoCtx,
    5307                                     vmdkAllocGrainAsyncComplete, pGrainAlloc);
     4901                                    vmdkAllocGrainComplete, pGrainAlloc);
    53084902        if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
    53094903            pGrainAlloc->cIoXfersPending++;
     
    53164910                                        VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + uGDIndex * sizeof(uGTSectorLE),
    53174911                                        &uRGTSectorLE, sizeof(uRGTSectorLE), pIoCtx,
    5318                                         vmdkAllocGrainAsyncComplete, pGrainAlloc);
     4912                                        vmdkAllocGrainComplete, pGrainAlloc);
    53194913            if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
    53204914                pGrainAlloc->cIoXfersPending++;
     
    53404934    pGrainAlloc->uGrainOffset = uFileOffset;
    53414935
    5342     /* Write the data. Always a full grain, or we're in big trouble. */
    5343     rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pExtent->pFile->pStorage,
    5344                                 uFileOffset, pIoCtx, cbWrite,
    5345                                 vmdkAllocGrainAsyncComplete, pGrainAlloc);
    5346     if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
    5347         pGrainAlloc->cIoXfersPending++;
    5348     else if (RT_FAILURE(rc))
    5349         return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write allocated data block in '%s'"), pExtent->pszFullname);
    5350 
    5351     pExtent->uAppendPosition += cbWrite;
    5352 
    5353     rc = vmdkAllocGrainAsyncGTUpdate(pImage, pExtent, pIoCtx, pGrainAlloc);
     4936    if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
     4937    {
     4938        AssertMsgReturn(vdIfIoIntIoCtxIsSynchronous(pImage->pIfIo, pIoCtx),
     4939                        ("Accesses to stream optimized images must be synchronous\n"),
     4940                        VERR_INVALID_STATE);
     4941
     4942        if (cbWrite != VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain))
     4943            return vdIfError(pImage->pIfError, VERR_INTERNAL_ERROR, RT_SRC_POS, N_("VMDK: not enough data for a compressed data block in '%s'"), pExtent->pszFullname);
     4944
     4945        /* Invalidate cache, just in case some code incorrectly allows mixing
     4946         * of reads and writes. Normally shouldn't be needed. */
     4947        pExtent->uGrainSectorAbs = 0;
     4948
     4949        /* Write compressed data block and the markers. */
     4950        uint32_t cbGrain = 0;
     4951        size_t cbSeg = 0;
     4952        RTSGSEG Segment;
     4953        unsigned cSegments = 1;
     4954
     4955        cbSeg = vdIfIoIntIoCtxSegArrayCreate(pImage->pIfIo, pIoCtx, &Segment,
     4956                                             &cSegments, cbWrite);
     4957        Assert(cbSeg == cbWrite);
     4958
     4959        rc = vmdkFileDeflateSync(pImage, pExtent, uFileOffset,
     4960                                 Segment.pvSeg, cbWrite, uSector, &cbGrain);
     4961        if (RT_FAILURE(rc))
     4962        {
     4963            AssertRC(rc);
     4964            return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write allocated compressed data block in '%s'"), pExtent->pszFullname);
     4965        }
     4966        pExtent->uLastGrainAccess = uSector / pExtent->cSectorsPerGrain;
     4967        pExtent->uAppendPosition += cbGrain;
     4968    }
     4969    else
     4970    {
     4971        /* Write the data. Always a full grain, or we're in big trouble. */
     4972        rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pExtent->pFile->pStorage,
     4973                                    uFileOffset, pIoCtx, cbWrite,
     4974                                    vmdkAllocGrainComplete, pGrainAlloc);
     4975        if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
     4976            pGrainAlloc->cIoXfersPending++;
     4977        else if (RT_FAILURE(rc))
     4978            return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write allocated data block in '%s'"), pExtent->pszFullname);
     4979
     4980        pExtent->uAppendPosition += cbWrite;
     4981    }
     4982
     4983    rc = vmdkAllocGrainGTUpdate(pImage, pExtent, pIoCtx, pGrainAlloc);
    53544984
    53554985    if (!pGrainAlloc->cIoXfersPending)
     
    53694999 */
    53705000static int vmdkStreamReadSequential(PVMDKIMAGE pImage, PVMDKEXTENT pExtent,
    5371                                     uint64_t uSector, void *pvBuf,
     5001                                    uint64_t uSector, PVDIOCTX pIoCtx,
    53725002                                    uint64_t cbRead)
    53735003{
    53745004    int rc;
    53755005
    5376     LogFlowFunc(("pImage=%#p pExtent=%#p uSector=%llu pvBuf=%#p cbRead=%llu\n",
    5377                  pImage, pExtent, uSector, pvBuf, cbRead));
     5006    LogFlowFunc(("pImage=%#p pExtent=%#p uSector=%llu pIoCtx=%#p cbRead=%llu\n",
     5007                 pImage, pExtent, uSector, pIoCtx, cbRead));
     5008
     5009    AssertMsgReturn(vdIfIoIntIoCtxIsSynchronous(pImage->pIfIo, pIoCtx),
     5010                    ("Async I/O not supported for sequential stream optimized images\n"),
     5011                    VERR_INVALID_STATE);
    53785012
    53795013    /* Do not allow to go back. */
     
    55095143
    55105144    uint32_t uSectorInGrain = uSector % pExtent->cSectorsPerGrain;
    5511     memcpy(pvBuf,
    5512            (uint8_t *)pExtent->pvGrain + VMDK_SECTOR2BYTE(uSectorInGrain),
    5513            cbRead);
     5145    vdIfIoIntIoCtxCopyTo(pImage->pIfIo, pIoCtx,
     5146                         (uint8_t *)pExtent->pvGrain + VMDK_SECTOR2BYTE(uSectorInGrain),
     5147                         cbRead);
    55145148    LogFlowFunc(("returns VINF_SUCCESS\n"));
    55155149    return VINF_SUCCESS;
     
    58715505    pImage->Descriptor.fDirty = true;
    58725506    /* Flush the descriptor now, in case it is embedded. */
    5873     vmdkFlushImage(pImage);
     5507    vmdkFlushImage(pImage, NULL);
    58745508
    58755509    /* Close and rename/move extents. */
     
    59445578        rrc = vmdkFileOpen(pImage, &pFile, pszOldDescName,
    59455579                           VDOpenFlagsToFileOpenFlags(VD_OPEN_FLAGS_NORMAL,
    5946                                                       false /* fCreate */),
    5947                            false /* fAsyncIO */);
     5580                                                      false /* fCreate */));
    59485581        AssertRC(rrc);
    59495582        if (fEmbeddedDesc)
     
    59615594        }
    59625595        pImage->Descriptor = DescriptorCopy;
    5963         vmdkWriteDescriptor(pImage);
     5596        vmdkWriteDescriptor(pImage, NULL);
    59645597        vmdkFileClose(pImage, &pFile, false);
    59655598        /* Get rid of the stuff we implanted. */
     
    60275660
    60285661/** @copydoc VBOXHDDBACKEND::pfnRead */
    6029 static int vmdkRead(void *pBackendData, uint64_t uOffset, void *pvBuf,
    6030                     size_t cbToRead, size_t *pcbActuallyRead)
    6031 {
    6032     LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n", pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead));
     5662static int vmdkRead(void *pBackendData, uint64_t uOffset, size_t cbToRead,
     5663                    PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
     5664{
     5665    LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n",
     5666                 pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead));
    60335667    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    60345668    PVMDKEXTENT pExtent;
     
    60705704        case VMDKETYPE_ESX_SPARSE:
    60715705#endif /* VBOX_WITH_VMDK_ESX */
    6072             rc = vmdkGetSector(pImage, pExtent, uSectorExtentRel,
    6073                                &uSectorExtentAbs);
     5706            rc = vmdkGetSector(pImage, pIoCtx, pExtent, uSectorExtentRel, &uSectorExtentAbs);
    60745707            if (RT_FAILURE(rc))
    60755708                goto out;
     
    60865719                    rc = vmdkStreamReadSequential(pImage, pExtent,
    60875720                                                  uSectorExtentRel,
    6088                                                   pvBuf, cbToRead);
     5721                                                  pIoCtx, cbToRead);
    60895722            }
    60905723            else
     
    60925725                if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
    60935726                {
     5727                    AssertMsg(vdIfIoIntIoCtxIsSynchronous(pImage->pIfIo, pIoCtx),
     5728                              ("Async I/O is not supported for stream optimized VMDK's\n"));
     5729
    60945730                    uint32_t uSectorInGrain = uSectorExtentRel % pExtent->cSectorsPerGrain;
    60955731                    uSectorExtentAbs -= uSectorInGrain;
     
    61125748                        Assert(uLBA == uSectorExtentRel);
    61135749                    }
    6114                     memcpy(pvBuf, (uint8_t *)pExtent->pvGrain + VMDK_SECTOR2BYTE(uSectorInGrain), cbToRead);
     5750                    vdIfIoIntIoCtxCopyTo(pImage->pIfIo, pIoCtx,
     5751                                           (uint8_t *)pExtent->pvGrain
     5752                                         + VMDK_SECTOR2BYTE(uSectorInGrain),
     5753                                         cbToRead);
    61155754                }
    61165755                else
    6117                 {
    6118                     rc = vdIfIoIntFileReadSync(pImage->pIfIo, pExtent->pFile->pStorage,
     5756                    rc = vdIfIoIntFileReadUser(pImage->pIfIo, pExtent->pFile->pStorage,
    61195757                                               VMDK_SECTOR2BYTE(uSectorExtentAbs),
    6120                                                pvBuf, cbToRead);
    6121                 }
     5758                                               pIoCtx, cbToRead);
    61225759            }
    61235760            break;
    61245761        case VMDKETYPE_VMFS:
    61255762        case VMDKETYPE_FLAT:
    6126             rc = vdIfIoIntFileReadSync(pImage->pIfIo, pExtent->pFile->pStorage,
     5763            rc = vdIfIoIntFileReadUser(pImage->pIfIo, pExtent->pFile->pStorage,
    61275764                                       VMDK_SECTOR2BYTE(uSectorExtentRel),
    6128                                        pvBuf, cbToRead);
     5765                                       pIoCtx, cbToRead);
    61295766            break;
    61305767        case VMDKETYPE_ZERO:
    6131             memset(pvBuf, '\0', cbToRead);
     5768            size_t cbSet;
     5769
     5770            cbSet = vdIfIoIntIoCtxSet(pImage->pIfIo, pIoCtx, 0, cbToRead);
     5771            Assert(cbSet == cbToRead);
     5772
     5773            rc = VINF_SUCCESS;
    61325774            break;
    61335775    }
     
    61415783
    61425784/** @copydoc VBOXHDDBACKEND::pfnWrite */
    6143 static int vmdkWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf,
    6144                      size_t cbToWrite, size_t *pcbWriteProcess,
    6145                      size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite)
    6146 {
    6147     LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n", pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));
     5785static int vmdkWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite,
     5786                     PVDIOCTX pIoCtx, size_t *pcbWriteProcess, size_t *pcbPreRead,
     5787                     size_t *pcbPostRead, unsigned fWrite)
     5788{
     5789    LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n",
     5790                 pBackendData, uOffset, pIoCtx, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));
    61485791    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    61495792    PVMDKEXTENT pExtent;
     
    61975840        case VMDKETYPE_ESX_SPARSE:
    61985841#endif /* VBOX_WITH_VMDK_ESX */
    6199             rc = vmdkGetSector(pImage, pExtent, uSectorExtentRel,
    6200                                &uSectorExtentAbs);
     5842            rc = vmdkGetSector(pImage, pIoCtx, pExtent, uSectorExtentRel, &uSectorExtentAbs);
    62015843            if (RT_FAILURE(rc))
    62025844                goto out;
     
    62165858                    {
    62175859                        /* Full block write to a previously unallocated block.
    6218                          * Check if the caller wants feedback. */
     5860                         * Check if the caller wants to avoid the automatic alloc. */
    62195861                        if (!(fWrite & VD_WRITE_NO_ALLOC))
    62205862                        {
    6221                             /* Allocate GT and store the grain. */
    6222                             rc = vmdkAllocGrain(pImage, pExtent,
    6223                                                 uSectorExtentRel,
    6224                                                 pvBuf, cbToWrite);
     5863                            /* Allocate GT and find out where to store the grain. */
     5864                            rc = vmdkAllocGrain(pImage, pExtent, pIoCtx,
     5865                                                uSectorExtentRel, cbToWrite);
    62255866                        }
    62265867                        else
     
    62425883                    rc = vmdkStreamAllocGrain(pImage, pExtent,
    62435884                                              uSectorExtentRel,
    6244                                               pvBuf, cbToWrite);
     5885                                              pIoCtx, cbToWrite);
    62455886                }
    62465887            }
     
    62585899                else
    62595900                {
    6260                     rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,
     5901                    Assert(!(pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED));
     5902                    rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pExtent->pFile->pStorage,
    62615903                                                VMDK_SECTOR2BYTE(uSectorExtentAbs),
    6262                                                 pvBuf, cbToWrite);
     5904                                                pIoCtx, cbToWrite, NULL, NULL);
    62635905                }
    62645906            }
     
    62685910            /* Clip write range to remain in this extent. */
    62695911            cbToWrite = RT_MIN(cbToWrite, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel));
    6270             rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,
     5912            rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pExtent->pFile->pStorage,
    62715913                                        VMDK_SECTOR2BYTE(uSectorExtentRel),
    6272                                         pvBuf, cbToWrite);
     5914                                        pIoCtx, cbToWrite, NULL, NULL);
    62735915            break;
    62745916        case VMDKETYPE_ZERO:
     
    62875929
    62885930/** @copydoc VBOXHDDBACKEND::pfnFlush */
    6289 static int vmdkFlush(void *pBackendData)
    6290 {
    6291     LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     5931static int vmdkFlush(void *pBackendData, PVDIOCTX pIoCtx)
     5932{
    62925933    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    6293     int rc = VINF_SUCCESS;
    6294 
    6295     AssertPtr(pImage);
    6296 
    6297     if (!(pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED))
    6298         rc = vmdkFlushImage(pImage);
    6299 
    6300     LogFlowFunc(("returns %Rrc\n", rc));
    6301     return rc;
     5934
     5935    return vmdkFlushImage(pImage, pIoCtx);
    63025936}
    63035937
     
    68766510}
    68776511
    6878 /** @copydoc VBOXHDDBACKEND::pfnAsyncRead */
    6879 static int vmdkAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbRead,
    6880                          PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
    6881 {
    6882     LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n",
    6883                  pBackendData, uOffset, pIoCtx, cbRead, pcbActuallyRead));
    6884     PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    6885     PVMDKEXTENT pExtent;
    6886     uint64_t uSectorExtentRel;
    6887     uint64_t uSectorExtentAbs;
    6888     int rc;
    6889 
    6890     AssertPtr(pImage);
    6891     Assert(uOffset % 512 == 0);
    6892     Assert(cbRead % 512 == 0);
    6893 
    6894     if (   uOffset + cbRead > pImage->cbSize
    6895         || cbRead == 0)
    6896     {
    6897         rc = VERR_INVALID_PARAMETER;
    6898         goto out;
    6899     }
    6900 
    6901     rc = vmdkFindExtent(pImage, VMDK_BYTE2SECTOR(uOffset),
    6902                         &pExtent, &uSectorExtentRel);
    6903     if (RT_FAILURE(rc))
    6904         goto out;
    6905 
    6906     /* Check access permissions as defined in the extent descriptor. */
    6907     if (pExtent->enmAccess == VMDKACCESS_NOACCESS)
    6908     {
    6909         rc = VERR_VD_VMDK_INVALID_STATE;
    6910         goto out;
    6911     }
    6912 
    6913     /* Clip read range to remain in this extent. */
    6914     cbRead = RT_MIN(cbRead, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel));
    6915 
    6916     /* Handle the read according to the current extent type. */
    6917     switch (pExtent->enmType)
    6918     {
    6919         case VMDKETYPE_HOSTED_SPARSE:
    6920 #ifdef VBOX_WITH_VMDK_ESX
    6921         case VMDKETYPE_ESX_SPARSE:
    6922 #endif /* VBOX_WITH_VMDK_ESX */
    6923             rc = vmdkGetSectorAsync(pImage, pIoCtx, pExtent,
    6924                                     uSectorExtentRel, &uSectorExtentAbs);
    6925             if (RT_FAILURE(rc))
    6926                 goto out;
    6927             /* Clip read range to at most the rest of the grain. */
    6928             cbRead = RT_MIN(cbRead, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain - uSectorExtentRel % pExtent->cSectorsPerGrain));
    6929             Assert(!(cbRead % 512));
    6930             if (uSectorExtentAbs == 0)
    6931                 rc = VERR_VD_BLOCK_FREE;
    6932             else
    6933             {
    6934                 AssertMsg(!(pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED), ("Async I/O is not supported for stream optimized VMDK's\n"));
    6935                 rc = vdIfIoIntFileReadUser(pImage->pIfIo, pExtent->pFile->pStorage,
    6936                                            VMDK_SECTOR2BYTE(uSectorExtentAbs),
    6937                                            pIoCtx, cbRead);
    6938             }
    6939             break;
    6940         case VMDKETYPE_VMFS:
    6941         case VMDKETYPE_FLAT:
    6942             rc = vdIfIoIntFileReadUser(pImage->pIfIo, pExtent->pFile->pStorage,
    6943                                        VMDK_SECTOR2BYTE(uSectorExtentRel),
    6944                                        pIoCtx, cbRead);
    6945             break;
    6946         case VMDKETYPE_ZERO:
    6947             size_t cbSet;
    6948 
    6949             cbSet = vdIfIoIntIoCtxSet(pImage->pIfIo, pIoCtx, 0, cbRead);
    6950             Assert(cbSet == cbRead);
    6951 
    6952             rc = VINF_SUCCESS;
    6953             break;
    6954     }
    6955     if (pcbActuallyRead)
    6956         *pcbActuallyRead = cbRead;
    6957 
    6958 out:
    6959     LogFlowFunc(("returns %Rrc\n", rc));
    6960     return rc;
    6961 }
    6962 
    6963 /** @copydoc VBOXHDDBACKEND::pfnAsyncWrite */
    6964 static int vmdkAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbWrite,
    6965                           PVDIOCTX pIoCtx,
    6966                           size_t *pcbWriteProcess, size_t *pcbPreRead,
    6967                           size_t *pcbPostRead, unsigned fWrite)
    6968 {
    6969     LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n",
    6970                  pBackendData, uOffset, pIoCtx, cbWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));
    6971     PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    6972     PVMDKEXTENT pExtent;
    6973     uint64_t uSectorExtentRel;
    6974     uint64_t uSectorExtentAbs;
    6975     int rc;
    6976 
    6977     AssertPtr(pImage);
    6978     Assert(uOffset % 512 == 0);
    6979     Assert(cbWrite % 512 == 0);
    6980 
    6981     if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    6982     {
    6983         rc = VERR_VD_IMAGE_READ_ONLY;
    6984         goto out;
    6985     }
    6986 
    6987     if (cbWrite == 0)
    6988     {
    6989         rc = VERR_INVALID_PARAMETER;
    6990         goto out;
    6991     }
    6992 
    6993     /* No size check here, will do that later when the extent is located.
    6994      * There are sparse images out there which according to the spec are
    6995      * invalid, because the total size is not a multiple of the grain size.
    6996      * Also for sparse images which are stitched together in odd ways (not at
    6997      * grain boundaries, and with the nominal size not being a multiple of the
    6998      * grain size), this would prevent writing to the last grain. */
    6999 
    7000     rc = vmdkFindExtent(pImage, VMDK_BYTE2SECTOR(uOffset),
    7001                         &pExtent, &uSectorExtentRel);
    7002     if (RT_FAILURE(rc))
    7003         goto out;
    7004 
    7005     /* Check access permissions as defined in the extent descriptor. */
    7006     if (pExtent->enmAccess != VMDKACCESS_READWRITE)
    7007     {
    7008         rc = VERR_VD_VMDK_INVALID_STATE;
    7009         goto out;
    7010     }
    7011 
    7012     /* Handle the write according to the current extent type. */
    7013     switch (pExtent->enmType)
    7014     {
    7015         case VMDKETYPE_HOSTED_SPARSE:
    7016 #ifdef VBOX_WITH_VMDK_ESX
    7017         case VMDKETYPE_ESX_SPARSE:
    7018 #endif /* VBOX_WITH_VMDK_ESX */
    7019             rc = vmdkGetSectorAsync(pImage, pIoCtx, pExtent, uSectorExtentRel,
    7020                                     &uSectorExtentAbs);
    7021             if (RT_FAILURE(rc))
    7022                 goto out;
    7023             /* Clip write range to at most the rest of the grain. */
    7024             cbWrite = RT_MIN(cbWrite, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain - uSectorExtentRel % pExtent->cSectorsPerGrain));
    7025             if (    pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED
    7026                 &&  uSectorExtentRel < (uint64_t)pExtent->uLastGrainAccess * pExtent->cSectorsPerGrain)
    7027             {
    7028                 rc = VERR_VD_VMDK_INVALID_WRITE;
    7029                 goto out;
    7030             }
    7031             if (uSectorExtentAbs == 0)
    7032             {
    7033                 if (cbWrite == VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain))
    7034                 {
    7035                     /* Full block write to a previously unallocated block.
    7036                      * Check if the caller wants to avoid the automatic alloc. */
    7037                     if (!(fWrite & VD_WRITE_NO_ALLOC))
    7038                     {
    7039                         /* Allocate GT and find out where to store the grain. */
    7040                         rc = vmdkAllocGrainAsync(pImage, pExtent, pIoCtx,
    7041                                                  uSectorExtentRel, cbWrite);
    7042                     }
    7043                     else
    7044                         rc = VERR_VD_BLOCK_FREE;
    7045                     *pcbPreRead = 0;
    7046                     *pcbPostRead = 0;
    7047                 }
    7048                 else
    7049                 {
    7050                     /* Clip write range to remain in this extent. */
    7051                     cbWrite = RT_MIN(cbWrite, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel));
    7052                     *pcbPreRead = VMDK_SECTOR2BYTE(uSectorExtentRel % pExtent->cSectorsPerGrain);
    7053                     *pcbPostRead = VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain) - cbWrite - *pcbPreRead;
    7054                     rc = VERR_VD_BLOCK_FREE;
    7055                 }
    7056             }
    7057             else
    7058             {
    7059                 Assert(!(pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED));
    7060                 rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pExtent->pFile->pStorage,
    7061                                             VMDK_SECTOR2BYTE(uSectorExtentAbs),
    7062                                             pIoCtx, cbWrite, NULL, NULL);
    7063             }
    7064             break;
    7065         case VMDKETYPE_VMFS:
    7066         case VMDKETYPE_FLAT:
    7067             /* Clip write range to remain in this extent. */
    7068             cbWrite = RT_MIN(cbWrite, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel));
    7069             rc = vdIfIoIntFileWriteUser(pImage->pIfIo, pExtent->pFile->pStorage,
    7070                                         VMDK_SECTOR2BYTE(uSectorExtentRel),
    7071                                         pIoCtx, cbWrite, NULL, NULL);
    7072             break;
    7073         case VMDKETYPE_ZERO:
    7074             /* Clip write range to remain in this extent. */
    7075             cbWrite = RT_MIN(cbWrite, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel));
    7076             break;
    7077     }
    7078 
    7079     if (pcbWriteProcess)
    7080         *pcbWriteProcess = cbWrite;
    7081 
    7082 out:
    7083     LogFlowFunc(("returns %Rrc\n", rc));
    7084     return rc;
    7085 }
    7086 
    7087 /** @copydoc VBOXHDDBACKEND::pfnAsyncFlush */
    7088 static int vmdkAsyncFlush(void *pBackendData, PVDIOCTX pIoCtx)
    7089 {
    7090     PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    7091     PVMDKEXTENT pExtent;
    7092     int rc = VINF_SUCCESS;
    7093 
    7094     /* Update descriptor if changed. */
    7095     /** @todo: The descriptor is never updated because
    7096      * it remains unchanged during normal operation (only vmdkRename updates it).
    7097      * So this part is actually not tested so far and requires testing as soon
    7098      * as the descriptor might change during async I/O.
    7099      */
    7100     if (pImage->Descriptor.fDirty)
    7101     {
    7102         rc = vmdkWriteDescriptorAsync(pImage, pIoCtx);
    7103         if (   RT_FAILURE(rc)
    7104             && rc != VERR_VD_ASYNC_IO_IN_PROGRESS)
    7105             goto out;
    7106     }
    7107 
    7108     for (unsigned i = 0; i < pImage->cExtents; i++)
    7109     {
    7110         pExtent = &pImage->pExtents[i];
    7111         if (pExtent->pFile != NULL && pExtent->fMetaDirty)
    7112         {
    7113             switch (pExtent->enmType)
    7114             {
    7115                 case VMDKETYPE_HOSTED_SPARSE:
    7116 #ifdef VBOX_WITH_VMDK_ESX
    7117                 case VMDKETYPE_ESX_SPARSE:
    7118 #endif /* VBOX_WITH_VMDK_ESX */
    7119                     rc = vmdkWriteMetaSparseExtentAsync(pImage, pExtent, 0, pIoCtx);
    7120                     if (RT_FAILURE(rc) && (rc != VERR_VD_ASYNC_IO_IN_PROGRESS))
    7121                         goto out;
    7122                     if (pExtent->fFooter)
    7123                     {
    7124                         uint64_t uFileOffset = pExtent->uAppendPosition;
    7125                         if (!uFileOffset)
    7126                         {
    7127                             rc = VERR_INTERNAL_ERROR;
    7128                             goto out;
    7129                         }
    7130                         uFileOffset = RT_ALIGN_64(uFileOffset, 512);
    7131                         rc = vmdkWriteMetaSparseExtent(pImage, pExtent, uFileOffset);
    7132                         if (RT_FAILURE(rc) && (rc != VERR_VD_ASYNC_IO_IN_PROGRESS))
    7133                             goto out;
    7134                     }
    7135                     break;
    7136                 case VMDKETYPE_VMFS:
    7137                 case VMDKETYPE_FLAT:
    7138                     /* Nothing to do. */
    7139                     break;
    7140                 case VMDKETYPE_ZERO:
    7141                 default:
    7142                     AssertMsgFailed(("extent with type %d marked as dirty\n",
    7143                                      pExtent->enmType));
    7144                     break;
    7145             }
    7146         }
    7147         switch (pExtent->enmType)
    7148         {
    7149             case VMDKETYPE_HOSTED_SPARSE:
    7150 #ifdef VBOX_WITH_VMDK_ESX
    7151             case VMDKETYPE_ESX_SPARSE:
    7152 #endif /* VBOX_WITH_VMDK_ESX */
    7153             case VMDKETYPE_VMFS:
    7154             case VMDKETYPE_FLAT:
    7155                 /*
    7156                  * Don't ignore block devices like in the sync case
    7157                  * (they have an absolute path).
    7158                  * We might have unwritten data in the writeback cache and
    7159                  * the async I/O manager will handle these requests properly
    7160                  * even if the block device doesn't support these requests.
    7161                  */
    7162                 if (   pExtent->pFile != NULL
    7163                     && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    7164                     rc = vdIfIoIntFileFlush(pImage->pIfIo, pExtent->pFile->pStorage,
    7165                                             pIoCtx, NULL, NULL);
    7166                 break;
    7167             case VMDKETYPE_ZERO:
    7168                 /* No need to do anything for this extent. */
    7169                 break;
    7170             default:
    7171                 AssertMsgFailed(("unknown extent type %d\n", pExtent->enmType));
    7172                 break;
    7173         }
    7174     }
    7175 
    7176 out:
    7177     return rc;
    7178 }
    71796512
    71806513
     
    72116544    /* pfnFlush */
    72126545    vmdkFlush,
     6546    /* pfnDiscard */
     6547    NULL,
    72136548    /* pfnGetVersion */
    72146549    vmdkGetVersion,
     
    72636598    /* pfnSetParentFilename */
    72646599    NULL,
    7265     /* pfnAsyncRead */
    7266     vmdkAsyncRead,
    7267     /* pfnAsyncWrite */
    7268     vmdkAsyncWrite,
    7269     /* pfnAsyncFlush */
    7270     vmdkAsyncFlush,
    72716600    /* pfnComposeLocation */
    72726601    genericFileComposeLocation,
     
    72776606    /* pfnResize */
    72786607    NULL,
    7279     /* pfnDiscard */
    7280     NULL,
    7281     /* pfnAsyncDiscard */
    7282     NULL,
    72836608    /* pfnRepair */
    72846609    NULL
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette