Index: /trunk/src/VBox/Devices/Storage/DrvVD.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/DrvVD.cpp	(revision 33744)
+++ /trunk/src/VBox/Devices/Storage/DrvVD.cpp	(revision 33745)
@@ -188,4 +188,9 @@
     /** Bandwidth group the disk is assigned to. */
     char               *pszBwGroup;
+
+    /** I/O interface for a cache image. */
+    VDINTERFACE         VDIIOCache;
+    /** Interface list for the cache image. */
+    PVDINTERFACE        pVDIfsCache;
 } VBOXDISK, *PVBOXDISK;
 
@@ -1931,9 +1936,11 @@
     PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
     int rc = VINF_SUCCESS;
-    char *pszName = NULL;   /**< The path of the disk image file. */
-    char *pszFormat = NULL; /**< The format backed to use for this image. */
-    bool fReadOnly;         /**< True if the media is read-only. */
-    bool fMaybeReadOnly;    /**< True if the media may or may not be read-only. */
-    bool fHonorZeroWrites;  /**< True if zero blocks should be written. */
+    char *pszName = NULL;        /**< The path of the disk image file. */
+    char *pszFormat = NULL;      /**< The format backed to use for this image. */
+    char *pszCachePath = NULL;   /**< The path to the cache image. */
+    char *pszCacheFormat = NULL; /**< The format backend to use for the cache image. */
+    bool fReadOnly;              /**< True if the media is read-only. */
+    bool fMaybeReadOnly;         /**< True if the media may or may not be read-only. */
+    bool fHonorZeroWrites;       /**< True if zero blocks should be written. */
     PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
 
@@ -2018,5 +2025,6 @@
                                           "ReadOnly\0MaybeReadOnly\0TempReadOnly\0Shareable\0HonorZeroWrites\0"
                                           "HostIPStack\0UseNewIo\0BootAcceleration\0BootAccelerationBuffer\0"
-                                          "SetupMerge\0MergeSource\0MergeTarget\0BwGroup\0Type\0");
+                                          "SetupMerge\0MergeSource\0MergeTarget\0BwGroup\0Type\0"
+                                          "CachePath\0CacheFormat\0");
         }
         else
@@ -2155,4 +2163,25 @@
             }
             MMR3HeapFree(psz); psz = NULL;
+
+            rc = CFGMR3QueryStringAlloc(pCurNode, "CachePath", &pszCachePath);
+            if (RT_FAILURE(rc) && rc != VERR_CFGM_VALUE_NOT_FOUND)
+            {
+                rc = PDMDRV_SET_ERROR(pDrvIns, rc,
+                                      N_("DrvVD: Configuration error: Querying \"CachePath\" as string failed"));
+                break;
+            }
+            else
+                rc = VINF_SUCCESS;
+
+            if (pszCachePath)
+            {
+                rc = CFGMR3QueryStringAlloc(pCurNode, "CacheFormat", &pszCacheFormat);
+                if (RT_FAILURE(rc))
+                {
+                    rc = PDMDRV_SET_ERROR(pDrvIns, rc,
+                                          N_("DrvVD: Configuration error: Querying \"CacheFormat\" as string failed"));
+                    break;
+                }
+            }
         }
 
@@ -2456,4 +2485,29 @@
         pCurNode = CFGMR3GetParent(pCurNode);
     }
+
+    /* Open the cache image if set. */
+    if (   RT_SUCCESS(rc)
+        && VALID_PTR(pszCachePath))
+    {
+        /* Insert the custom I/O interface only if we're told to use new IO.
+         * Since the I/O interface is per image we could make this more
+         * flexible in the future if we want to. */
+        if (fUseNewIo)
+        {
+            rc = VDInterfaceAdd(&pThis->VDIIOCache, "DrvVD_IO", VDINTERFACETYPE_IO,
+                                &pThis->VDIIOCallbacks, pThis,
+                                &pThis->pVDIfsCache);
+            AssertRC(rc);
+        }
+
+        rc = VDCacheOpen(pThis->pDisk, pszCacheFormat, pszCachePath, VD_OPEN_FLAGS_NORMAL, pThis->pVDIfsCache);
+        if (RT_FAILURE(rc))
+            rc = PDMDRV_SET_ERROR(pDrvIns, rc, N_("DrvVD: Could not open cache image"));
+    }
+
+    if (VALID_PTR(pszCachePath))
+        MMR3HeapFree(pszCachePath);
+    if (VALID_PTR(pszCacheFormat))
+        MMR3HeapFree(pszCacheFormat);
 
     if (   RT_SUCCESS(rc)
Index: /trunk/src/VBox/Storage/VCICache.cpp
===================================================================
--- /trunk/src/VBox/Storage/VCICache.cpp	(revision 33744)
+++ /trunk/src/VBox/Storage/VCICache.cpp	(revision 33745)
@@ -82,5 +82,5 @@
 
 /** VCI signature to identify a valid image. */
-#define VCI_HDR_SIGNATURE          UINT32_C(0x56434900) /* VCI\0 */
+#define VCI_HDR_SIGNATURE          UINT32_C(0x00494356) /* \0ICV */
 /** Current version we support. */
 #define VCI_HDR_VERSION            UINT32_C(0x00000001)
@@ -193,5 +193,5 @@
 
 /** The magic which identifies a block map. */
-#define VCI_BLKMAP_MAGIC   UINT32_C(0x56424c4b) /* VBLK */
+#define VCI_BLKMAP_MAGIC   UINT32_C(0x4b4c4256) /* KLBV */
 /** Current version. */
 #define VCI_BLKMAP_VERSION UINT32_C(0x00000001)
@@ -466,6 +466,6 @@
 {
     return pCache->pInterfaceIOCallbacks->pfnWriteSync(pCache->pInterfaceIO->pvUser,
-                                                       pCache->pStorage, uOffset,
-                                                       pvBuffer, cbBuffer, NULL);
+                                                       pCache->pStorage, VCI_BLOCK2BYTE(uOffset),
+                                                       pvBuffer, VCI_BLOCK2BYTE(cbBuffer), NULL);
 }
 
@@ -474,6 +474,6 @@
 {
     return pCache->pInterfaceIOCallbacks->pfnReadSync(pCache->pInterfaceIO->pvUser,
-                                                      pCache->pStorage, uOffset,
-                                                      pvBuffer, cbBuffer, NULL);
+                                                      pCache->pStorage, VCI_BLOCK2BYTE(uOffset),
+                                                      pvBuffer, VCI_BLOCK2BYTE(cbBuffer), NULL);
 }
 
@@ -596,7 +596,7 @@
         pBlkMap->pRangesTail = pFree;
 
-        Assert(!((cbBlkMap + sizeof(VciBlkMap) % VCI_BLOCK_SIZE)));
+        Assert(!((cbBlkMap + sizeof(VciBlkMap)) % VCI_BLOCK_SIZE));
         *ppBlkMap = pBlkMap;
-        *pcBlkMap = (cbBlkMap + sizeof(VciBlkMap)) / VCI_BLOCK_SIZE;
+        *pcBlkMap = VCI_BYTE2BLOCK(cbBlkMap + sizeof(VciBlkMap));
     }
     else
@@ -662,5 +662,5 @@
         cBlkMap -= VCI_BYTE2BLOCK(sizeof(VciBlkMap));
 
-        rc = vciFileReadSync(pStorage, VCI_BLOCK2BYTE(offBlkMap), &BlkMap, VCI_BYTE2BLOCK(sizeof(VciBlkMap)));
+        rc = vciFileReadSync(pStorage, offBlkMap, &BlkMap, VCI_BYTE2BLOCK(sizeof(VciBlkMap)));
         if (RT_SUCCESS(rc))
         {
@@ -677,5 +677,5 @@
                 && BlkMap.u32Version == VCI_BLKMAP_VERSION
                 && BlkMap.cBlocks == BlkMap.cBlocksFree + BlkMap.cBlocksAllocMeta + BlkMap.cBlocksAllocData
-                && BlkMap.cBlocks / 8 == cBlkMap)
+                && VCI_BYTE2BLOCK(BlkMap.cBlocks / 8) == cBlkMap)
             {
                 PVCIBLKMAP pBlkMap = (PVCIBLKMAP)RTMemAllocZ(sizeof(VCIBLKMAP));
@@ -696,10 +696,9 @@
                         uint8_t abBitmapBuffer[16 * _1K];
                         uint32_t cBlocksRead = 0;
-                        int iBit = 0;
-                        uint64_t cBlocksLeft = pBlkMap->cBlocks;
+                        uint64_t cBlocksLeft = VCI_BYTE2BLOCK(pBlkMap->cBlocks / 8);
 
                         cBlocksRead = RT_MIN(VCI_BYTE2BLOCK(sizeof(abBitmapBuffer)), cBlocksLeft);
-                        rc = vciFileReadSync(pStorage, VCI_BLOCK2BYTE(offBlkMap), abBitmapBuffer,
-                                             VCI_BLOCK2BYTE(cBlocksRead));
+                        rc = vciFileReadSync(pStorage, offBlkMap, abBitmapBuffer,
+                                             cBlocksRead);
 
                         if (RT_SUCCESS(rc))
@@ -717,14 +716,19 @@
                                && cBlocksLeft)
                         {
-#if 0
-                            while (cBlocksRead)
+                            int iBit = 0;
+                            uint32_t cBits = VCI_BLOCK2BYTE(cBlocksRead) * 8;
+                            uint32_t iBitPrev = 0xffffffff;
+
+                            while (cBits)
                             {
                                 if (pRangeCur->fFree)
                                 {
                                     /* Check for the first set bit. */
+                                    iBit = ASMBitNextSet(abBitmapBuffer, cBits, iBitPrev);
                                 }
                                 else
                                 {
                                     /* Check for the first free bit. */
+                                    iBit = ASMBitNextClear(abBitmapBuffer, cBits, iBitPrev);
                                 }
 
@@ -732,19 +736,41 @@
                                 {
                                     /* No change. */
-                                    pRangeCur->cBlocks += cBlocksRead;
-                                    cBlocksRead = 0;
+                                    pRangeCur->cBlocks += cBits;
+                                    cBits = 0;
                                 }
                                 else
                                 {
+                                    Assert((uint32_t)iBit < cBits);
+                                    pRangeCur->cBlocks += iBit;
+
                                     /* Create a new range descriptor. */
+                                    PVCIBLKRANGEDESC pRangeNew = (PVCIBLKRANGEDESC)RTMemAllocZ(sizeof(VCIBLKRANGEDESC));
+                                    if (!pRangeNew)
+                                    {
+                                        rc = VERR_NO_MEMORY;
+                                        break;
+                                    }
+
+                                    pRangeNew->fFree = !pRangeCur->fFree;
+                                    pRangeNew->offAddrStart = pRangeCur->offAddrStart + pRangeCur->cBlocks;
+                                    pRangeNew->cBlocks = 0;
+                                    pRangeNew->pPrev = pRangeCur;
+                                    pRangeCur->pNext = pRangeNew;
+                                    pBlkMap->pRangesTail = pRangeNew;
+                                    pRangeCur = pRangeNew;
+                                    cBits -= iBit;
+                                    iBitPrev = iBit;
                                 }
                             }
-#endif
+
                             cBlocksLeft -= cBlocksRead;
                             offBlkMap   += cBlocksRead;
 
-                            if (cBlocksLeft)
+                            if (   RT_SUCCESS(rc)
+                                && cBlocksLeft)
                             {
                                 /* Read next chunk. */
+                                cBlocksRead = RT_MIN(VCI_BYTE2BLOCK(sizeof(abBitmapBuffer)), cBlocksLeft);
+                                rc = vciFileReadSync(pStorage, offBlkMap, abBitmapBuffer, cBlocksRead);
                             }
                         }
@@ -797,5 +823,5 @@
 
     /* Make sure the number of blocks allocated for us match our expectations. */
-    if ((pBlkMap->cBlocks / 8) + VCI_BYTE2BLOCK(sizeof(VciBlkMap)) == cBlkMap)
+    if (VCI_BYTE2BLOCK(pBlkMap->cBlocks / 8) + VCI_BYTE2BLOCK(sizeof(VciBlkMap)) == cBlkMap)
     {
         /* Setup the header */
@@ -809,5 +835,5 @@
         BlkMap.cBlocksAllocData = RT_H2LE_U32(pBlkMap->cBlocksAllocData);
 
-        rc = vciFileWriteSync(pStorage, VCI_BLOCK2BYTE(offBlkMap), &BlkMap, VCI_BYTE2BLOCK(sizeof(VciBlkMap)));
+        rc = vciFileWriteSync(pStorage, offBlkMap, &BlkMap, VCI_BYTE2BLOCK(sizeof(VciBlkMap)));
         if (RT_SUCCESS(rc))
         {
@@ -838,5 +864,5 @@
                     {
                         /* Buffer is full, write to file and reset. */
-                        rc = vciFileWriteSync(pStorage, offBlkMap, abBitmapBuffer, sizeof(abBitmapBuffer));
+                        rc = vciFileWriteSync(pStorage, offBlkMap, abBitmapBuffer, VCI_BYTE2BLOCK(sizeof(abBitmapBuffer)));
                         if (RT_FAILURE(rc))
                             break;
@@ -853,5 +879,5 @@
 
             if (RT_SUCCESS(rc) && iBit)
-                rc = vciFileWriteSync(pStorage, offBlkMap, abBitmapBuffer, iBit / 8);
+                rc = vciFileWriteSync(pStorage, offBlkMap, abBitmapBuffer, VCI_BYTE2BLOCK(iBit / 8));
         }
     }
@@ -932,4 +958,5 @@
                 pFree->fFree = true;
                 pFree->cBlocks = pBestFit->cBlocks - cBlocks;
+                pBestFit->cBlocks -= pFree->cBlocks;
                 pFree->offAddrStart = pBestFit->offAddrStart + cBlocks;
 
@@ -1280,5 +1307,5 @@
     }
 
-    rc = vciFileReadSync(pCache, 0, &Hdr, sizeof(Hdr));
+    rc = vciFileReadSync(pCache, 0, &Hdr, VCI_BYTE2BLOCK(sizeof(Hdr)));
     if (RT_FAILURE(rc))
     {
@@ -1302,5 +1329,5 @@
 
         /* Load the block map. */
-        rc = vciBlkMapLoad(pCache, VCI_BLOCK2BYTE(pCache->offBlksBitmap), Hdr.cBlkMap, &pCache->pBlkMap);
+        rc = vciBlkMapLoad(pCache, pCache->offBlksBitmap, Hdr.cBlkMap, &pCache->pBlkMap);
         if (RT_SUCCESS(rc))
         {
@@ -1308,5 +1335,5 @@
             VciTreeNode RootNode;
 
-            rc = vciFileReadSync(pCache, VCI_BLOCK2BYTE(pCache->offTreeRoot), &RootNode, sizeof(VciTreeNode));
+            rc = vciFileReadSync(pCache, pCache->offTreeRoot, &RootNode, VCI_BYTE2BLOCK(sizeof(VciTreeNode)));
             if (RT_SUCCESS(rc))
             {
@@ -1742,4 +1769,5 @@
     Assert(cbToWrite % 512 == 0);
 
+    *pcbWriteProcess = cbToWrite; /** @todo: Implement. */
 out:
     LogFlowFunc(("returns %Rrc\n", rc));
Index: /trunk/src/VBox/Storage/VD.cpp
===================================================================
--- /trunk/src/VBox/Storage/VD.cpp	(revision 33744)
+++ /trunk/src/VBox/Storage/VD.cpp	(revision 33745)
@@ -66,4 +66,27 @@
 
 /**
+ * Structure containing everything I/O related
+ * for the image and cache descriptors.
+ */
+typedef struct VDIO
+{
+    /** I/O interface to the upper layer. */
+    PVDINTERFACE        pInterfaceIO;
+    /** I/O interface callback table. */
+    PVDINTERFACEIO      pInterfaceIOCallbacks;
+
+    /** Per image internal I/O interface. */
+    VDINTERFACE         VDIIOInt;
+
+    /** Fallback I/O interface, only used if the caller doesn't provide it. */
+    VDINTERFACE         VDIIO;
+
+    /** Opaque backend data. */
+    void               *pBackendData;
+    /** Disk this image is part of */
+    PVBOXHDD            pDisk;
+} VDIO, *PVDIO;
+
+/**
  * VBox HDD Container image descriptor.
  */
@@ -86,21 +109,8 @@
     /** Function pointers for the various backend methods. */
     PCVBOXHDDBACKEND    Backend;
-
     /** Pointer to list of VD interfaces, per-image. */
     PVDINTERFACE        pVDIfsImage;
-
-    /** I/O interface to the upper layer. */
-    PVDINTERFACE        pInterfaceIO;
-    /** I/O interface callback table. */
-    PVDINTERFACEIO      pInterfaceIOCallbacks;
-
-    /** Per image internal I/O interface. */
-    VDINTERFACE         VDIIOInt;
-
-    /** Fallback I/O interface, only used if the caller doesn't provide it. */
-    VDINTERFACE         VDIIO;
-
-    /** Disk this image is part of */
-    PVBOXHDD            pDisk;
+    /** I/O related things. */
+    VDIO                VDIo;
 } VDIMAGE, *PVDIMAGE;
 
@@ -133,18 +143,6 @@
     /** Pointer to list of VD interfaces, per-cache. */
     PVDINTERFACE        pVDIfsCache;
-
-    /** I/O interface to the upper layer. */
-    PVDINTERFACE        pInterfaceIO;
-    /** I/O interface callback table. */
-    PVDINTERFACEIO      pInterfaceIOCallbacks;
-
-    /** Per image internal I/O interface. */
-    VDINTERFACE         VDIIOInt;
-
-    /** Fallback I/O interface, only used if the caller doesn't provide it. */
-    VDINTERFACE         VDIIO;
-
-    /** Disk this image is part of */
-    PVBOXHDD            pDisk;
+    /** I/O related things. */
+    VDIO                VDIo;
 } VDCACHE, *PVDCACHE;
 
@@ -392,6 +390,6 @@
 typedef struct VDIOSTORAGE
 {
-    /** Image this storage handle belongs to. */
-    PVDIMAGE                     pImage;
+    /** Image I/O state this storage handle belongs to. */
+    PVDIO                        pVDIo;
     /** AVL tree for pending async metadata transfers. */
     PAVLRFOFFTREE                pTreeMetaXfers;
@@ -799,5 +797,5 @@
     }
 
-    if (RT_SUCCESS(rc))
+    if (RT_SUCCESS(rc) || rc == VERR_VD_BLOCK_FREE)
         *pcbThisRead = cbThisRead;
 
@@ -991,5 +989,5 @@
     PVDIOTASK pIoTask = NULL;
 
-    pIoTask = (PVDIOTASK)RTMemCacheAlloc(pIoStorage->pImage->pDisk->hMemCacheIoTask);
+    pIoTask = (PVDIOTASK)RTMemCacheAlloc(pIoStorage->pVDIo->pDisk->hMemCacheIoTask);
     if (pIoTask)
     {
@@ -1009,5 +1007,5 @@
     PVDIOTASK pIoTask = NULL;
 
-    pIoTask = (PVDIOTASK)RTMemCacheAlloc(pIoStorage->pImage->pDisk->hMemCacheIoTask);
+    pIoTask = (PVDIOTASK)RTMemCacheAlloc(pIoStorage->pVDIo->pDisk->hMemCacheIoTask);
     if (pIoTask)
     {
@@ -1047,5 +1045,5 @@
 }
 
-DECLINLINE(PVDMETAXFER) vdMetaXferAlloc(PVDIMAGE pImage, PVDIOSTORAGE pIoStorage, uint64_t uOffset, size_t cb)
+DECLINLINE(PVDMETAXFER) vdMetaXferAlloc(PVDIOSTORAGE pIoStorage, uint64_t uOffset, size_t cb)
 {
     PVDMETAXFER pMetaXfer = (PVDMETAXFER)RTMemAlloc(RT_OFFSETOF(VDMETAXFER, abData[cb]));
@@ -2603,5 +2601,5 @@
     {
         RTCritSectEnter(&pDisk->CritSect);
-        rc = pfnComplete(pIoStorage->pImage->pBackendData, pIoCtx, pvUser, rcReq);
+        rc = pfnComplete(pIoStorage->pVDIo->pBackendData, pIoCtx, pvUser, rcReq);
         RTCritSectLeave(&pDisk->CritSect);
     }
@@ -2621,5 +2619,5 @@
                                PVDMETAXFER pMetaXfer, int rcReq)
 {
-    PVBOXHDD pDisk = pIoStorage->pImage->pDisk;
+    PVBOXHDD pDisk = pIoStorage->pVDIo->pDisk;
     RTLISTNODE ListIoCtxWaiting;
     bool fFlush;
@@ -2669,5 +2667,5 @@
         {
             RTCritSectEnter(&pDisk->CritSect);
-            rc = pfnComplete(pIoStorage->pImage->pBackendData, pIoCtx, pvUser, rcReq);
+            rc = pfnComplete(pIoStorage->pVDIo->pBackendData, pIoCtx, pvUser, rcReq);
             RTCritSectLeave(&pDisk->CritSect);
         }
@@ -2721,5 +2719,5 @@
                                  pIoTask->Type.Meta.pMetaXfer, rcReq);
 
-    vdIoTaskFree(pIoStorage->pImage->pDisk, pIoTask);
+    vdIoTaskFree(pIoStorage->pVDIo->pDisk, pIoTask);
 
     return rc;
@@ -2733,11 +2731,9 @@
 {
     int rc = VINF_SUCCESS;
-    PVDIMAGE pImage         = (PVDIMAGE)pvUser;
+    PVDIO pVDIo             = (PVDIO)pvUser;
     PVDIOSTORAGE pIoStorage = (PVDIOSTORAGE)RTMemAllocZ(sizeof(VDIOSTORAGE));
 
     if (!pIoStorage)
         return VERR_NO_MEMORY;
-
-    pIoStorage->pImage = pImage;
 
     /* Create the AVl tree. */
@@ -2745,10 +2741,11 @@
     if (pIoStorage->pTreeMetaXfers)
     {
-        rc = pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser,
-                                                    pszLocation, uOpenFlags,
-                                                    vdIOIntReqCompleted,
-                                                    &pIoStorage->pStorage);
+        rc = pVDIo->pInterfaceIOCallbacks->pfnOpen(pVDIo->pInterfaceIO->pvUser,
+                                                   pszLocation, uOpenFlags,
+                                                   vdIOIntReqCompleted,
+                                                   &pIoStorage->pStorage);
         if (RT_SUCCESS(rc))
         {
+            pIoStorage->pVDIo = pVDIo;
             *ppIoStorage = pIoStorage;
             return VINF_SUCCESS;
@@ -2772,8 +2769,8 @@
 static int vdIOIntClose(void *pvUser, PVDIOSTORAGE pIoStorage)
 {
-    PVDIMAGE pImage = (PVDIMAGE)pvUser;
-
-    int rc = pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser,
-                                                     pIoStorage->pStorage);
+    PVDIO pVDIo             = (PVDIO)pvUser;
+
+    int rc = pVDIo->pInterfaceIOCallbacks->pfnClose(pVDIo->pInterfaceIO->pvUser,
+                                                    pIoStorage->pStorage);
     AssertRC(rc);
 
@@ -2786,7 +2783,7 @@
 static int vdIOIntDelete(void *pvUser, const char *pcszFilename)
 {
-    PVDIMAGE pImage = (PVDIMAGE)pvUser;
-    return pImage->pInterfaceIOCallbacks->pfnDelete(pImage->pInterfaceIO->pvUser,
-                                                    pcszFilename);
+    PVDIO pVDIo = (PVDIO)pvUser;
+    return pVDIo->pInterfaceIOCallbacks->pfnDelete(pVDIo->pInterfaceIO->pvUser,
+                                                   pcszFilename);
 }
 
@@ -2794,7 +2791,7 @@
                        unsigned fMove)
 {
-    PVDIMAGE pImage = (PVDIMAGE)pvUser;
-    return pImage->pInterfaceIOCallbacks->pfnMove(pImage->pInterfaceIO->pvUser,
-                                                  pcszSrc, pcszDst, fMove);
+    PVDIO pVDIo = (PVDIO)pvUser;
+    return pVDIo->pInterfaceIOCallbacks->pfnMove(pVDIo->pInterfaceIO->pvUser,
+                                                 pcszSrc, pcszDst, fMove);
 }
 
@@ -2802,8 +2799,8 @@
                                int64_t *pcbFreeSpace)
 {
-    PVDIMAGE pImage = (PVDIMAGE)pvUser;
-    return pImage->pInterfaceIOCallbacks->pfnGetFreeSpace(pImage->pInterfaceIO->pvUser,
-                                                          pcszFilename,
-                                                          pcbFreeSpace);
+    PVDIO pVDIo = (PVDIO)pvUser;
+    return pVDIo->pInterfaceIOCallbacks->pfnGetFreeSpace(pVDIo->pInterfaceIO->pvUser,
+                                                         pcszFilename,
+                                                         pcbFreeSpace);
 }
 
@@ -2811,8 +2808,8 @@
                                       PRTTIMESPEC pModificationTime)
 {
-    PVDIMAGE pImage = (PVDIMAGE)pvUser;
-    return pImage->pInterfaceIOCallbacks->pfnGetModificationTime(pImage->pInterfaceIO->pvUser,
-                                                                 pcszFilename,
-                                                                 pModificationTime);
+    PVDIO pVDIo = (PVDIO)pvUser;
+    return pVDIo->pInterfaceIOCallbacks->pfnGetModificationTime(pVDIo->pInterfaceIO->pvUser,
+                                                                pcszFilename,
+                                                                pModificationTime);
 }
 
@@ -2820,7 +2817,6 @@
                           uint64_t *pcbSize)
 {
-    PVDIMAGE pImage = (PVDIMAGE)pvUser;
-
-    return pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser,
+    PVDIO pVDIo = (PVDIO)pvUser;
+    return pVDIo->pInterfaceIOCallbacks->pfnGetSize(pVDIo->pInterfaceIO->pvUser,
                                                     pIoStorage->pStorage,
                                                     pcbSize);
@@ -2830,9 +2826,9 @@
                           uint64_t cbSize)
 {
-    PVDIMAGE pImage = (PVDIMAGE)pvUser;
-
-    return pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser,
-                                                     pIoStorage->pStorage,
-                                                     cbSize);
+    PVDIO pVDIo = (PVDIO)pvUser;
+
+    return pVDIo->pInterfaceIOCallbacks->pfnSetSize(pVDIo->pInterfaceIO->pvUser,
+                                                    pIoStorage->pStorage,
+                                                    cbSize);
 }
 
@@ -2841,10 +2837,10 @@
                             size_t cbWrite, size_t *pcbWritten)
 {
-    PVDIMAGE pImage = (PVDIMAGE)pvUser;
-
-    return pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser,
-                                                       pIoStorage->pStorage,
-                                                       uOffset, pvBuf, cbWrite,
-                                                       pcbWritten);
+    PVDIO pVDIo = (PVDIO)pvUser;
+
+    return pVDIo->pInterfaceIOCallbacks->pfnWriteSync(pVDIo->pInterfaceIO->pvUser,
+                                                      pIoStorage->pStorage,
+                                                      uOffset, pvBuf, cbWrite,
+                                                      pcbWritten);
 }
 
@@ -2853,18 +2849,16 @@
                            size_t *pcbRead)
 {
-    PVDIMAGE pImage = (PVDIMAGE)pvUser;
-
-    return pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser,
-                                                      pIoStorage->pStorage,
-                                                      uOffset, pvBuf, cbRead,
-                                                      pcbRead);
+    PVDIO pVDIo = (PVDIO)pvUser;
+    return pVDIo->pInterfaceIOCallbacks->pfnReadSync(pVDIo->pInterfaceIO->pvUser,
+                                                     pIoStorage->pStorage,
+                                                     uOffset, pvBuf, cbRead,
+                                                     pcbRead);
 }
 
 static int vdIOIntFlushSync(void *pvUser, PVDIOSTORAGE pIoStorage)
 {
-    PVDIMAGE pImage = (PVDIMAGE)pvUser;
-
-    return pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser,
-                                                       pIoStorage->pStorage);
+    PVDIO pVDIo = (PVDIO)pvUser;
+    return pVDIo->pInterfaceIOCallbacks->pfnFlushSync(pVDIo->pInterfaceIO->pvUser,
+                                                      pIoStorage->pStorage);
 }
 
@@ -2874,6 +2868,6 @@
 {
     int rc = VINF_SUCCESS;
-    PVDIMAGE pImage = (PVDIMAGE)pvUser;
-    PVBOXHDD pDisk  = pImage->pDisk;
+    PVDIO    pVDIo = (PVDIO)pvUser;
+    PVBOXHDD pDisk = pVDIo->pDisk;
 
     LogFlowFunc(("pvUser=%#p pIoStorage=%#p uOffset=%llu pIoCtx=%#p cbRead=%u\n",
@@ -2909,9 +2903,9 @@
 
         void *pvTask;
-        rc = pImage->pInterfaceIOCallbacks->pfnReadAsync(pImage->pInterfaceIO->pvUser,
-                                                         pIoStorage->pStorage,
-                                                         uOffset, aSeg, cSegments,
-                                                         cbTaskRead, pIoTask,
-                                                         &pvTask);
+        rc = pVDIo->pInterfaceIOCallbacks->pfnReadAsync(pVDIo->pInterfaceIO->pvUser,
+                                                        pIoStorage->pStorage,
+                                                        uOffset, aSeg, cSegments,
+                                                        cbTaskRead, pIoTask,
+                                                        &pvTask);
         if (RT_SUCCESS(rc))
         {
@@ -2942,6 +2936,6 @@
 {
     int rc = VINF_SUCCESS;
-    PVDIMAGE pImage = (PVDIMAGE)pvUser;
-    PVBOXHDD pDisk  = pImage->pDisk;
+    PVDIO    pVDIo = (PVDIO)pvUser;
+    PVBOXHDD pDisk = pVDIo->pDisk;
 
     LogFlowFunc(("pvUser=%#p pIoStorage=%#p uOffset=%llu pIoCtx=%#p cbWrite=%u\n",
@@ -2977,9 +2971,9 @@
 
         void *pvTask;
-        rc = pImage->pInterfaceIOCallbacks->pfnWriteAsync(pImage->pInterfaceIO->pvUser,
-                                                          pIoStorage->pStorage,
-                                                          uOffset, aSeg, cSegments,
-                                                          cbTaskWrite, pIoTask,
-                                                          &pvTask);
+        rc = pVDIo->pInterfaceIOCallbacks->pfnWriteAsync(pVDIo->pInterfaceIO->pvUser,
+                                                         pIoStorage->pStorage,
+                                                         uOffset, aSeg, cSegments,
+                                                         cbTaskWrite, pIoTask,
+                                                         &pvTask);
         if (RT_SUCCESS(rc))
         {
@@ -3009,6 +3003,6 @@
                                 void *pvCompleteUser)
 {
-    PVDIMAGE pImage = (PVDIMAGE)pvUser;
-    PVBOXHDD pDisk  = pImage->pDisk;
+    PVDIO pVDIo     = (PVDIO)pvUser;
+    PVBOXHDD pDisk  = pVDIo->pDisk;
     int rc = VINF_SUCCESS;
     RTSGSEG Seg;
@@ -3032,5 +3026,5 @@
 
         /* Allocate a new meta transfer. */
-        pMetaXfer = vdMetaXferAlloc(pImage, pIoStorage, uOffset, cbRead);
+        pMetaXfer = vdMetaXferAlloc(pIoStorage, uOffset, cbRead);
         if (!pMetaXfer)
             return VERR_NO_MEMORY;
@@ -3047,9 +3041,9 @@
 
         VDMETAXFER_TXDIR_SET(pMetaXfer->fFlags, VDMETAXFER_TXDIR_READ);
-        rc = pImage->pInterfaceIOCallbacks->pfnReadAsync(pImage->pInterfaceIO->pvUser,
-                                                         pIoStorage->pStorage,
-                                                         uOffset, &Seg, 1,
-                                                         cbRead, pIoTask,
-                                                         &pvTask);
+        rc = pVDIo->pInterfaceIOCallbacks->pfnReadAsync(pVDIo->pInterfaceIO->pvUser,
+                                                        pIoStorage->pStorage,
+                                                        uOffset, &Seg, 1,
+                                                        cbRead, pIoTask,
+                                                        &pvTask);
 
         if (RT_SUCCESS(rc) || rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
@@ -3107,6 +3101,6 @@
                                  void *pvCompleteUser)
 {
-    PVDIMAGE pImage = (PVDIMAGE)pvUser;
-    PVBOXHDD pDisk  = pImage->pDisk;
+    PVDIO    pVDIo = (PVDIO)pvUser;
+    PVBOXHDD pDisk = pVDIo->pDisk;
     int rc = VINF_SUCCESS;
     RTSGSEG Seg;
@@ -3125,5 +3119,5 @@
     {
         /* Allocate a new meta transfer. */
-        pMetaXfer = vdMetaXferAlloc(pImage, pIoStorage, uOffset, cbWrite);
+        pMetaXfer = vdMetaXferAlloc(pIoStorage, uOffset, cbWrite);
         if (!pMetaXfer)
             return VERR_NO_MEMORY;
@@ -3152,9 +3146,9 @@
 
     VDMETAXFER_TXDIR_SET(pMetaXfer->fFlags, VDMETAXFER_TXDIR_WRITE);
-    rc = pImage->pInterfaceIOCallbacks->pfnWriteAsync(pImage->pInterfaceIO->pvUser,
-                                                      pIoStorage->pStorage,
-                                                      uOffset, &Seg, 1,
-                                                      cbWrite, pIoTask,
-                                                      &pvTask);
+    rc = pVDIo->pInterfaceIOCallbacks->pfnWriteAsync(pVDIo->pInterfaceIO->pvUser,
+                                                     pIoStorage->pStorage,
+                                                     uOffset, &Seg, 1,
+                                                     cbWrite, pIoTask,
+                                                     &pvTask);
     if (RT_SUCCESS(rc))
     {
@@ -3198,6 +3192,6 @@
 static void vdIOIntMetaXferRelease(void *pvUser, PVDMETAXFER pMetaXfer)
 {
-    PVDIMAGE pImage = (PVDIMAGE)pvUser;
-    PVBOXHDD pDisk  = pImage->pDisk;
+    PVDIO    pVDIo = (PVDIO)pvUser;
+    PVBOXHDD pDisk = pVDIo->pDisk;
     PVDIOSTORAGE pIoStorage = pMetaXfer->pIoStorage;
 
@@ -3226,6 +3220,6 @@
                              void *pvCompleteUser)
 {
-    PVDIMAGE pImage = (PVDIMAGE)pvUser;
-    PVBOXHDD pDisk  = pImage->pDisk;
+    PVDIO    pVDIo = (PVDIO)pvUser;
+    PVBOXHDD pDisk = pVDIo->pDisk;
     int rc = VINF_SUCCESS;
     PVDIOTASK pIoTask;
@@ -3239,5 +3233,5 @@
 
     /* Allocate a new meta transfer. */
-    pMetaXfer = vdMetaXferAlloc(pImage, pIoStorage, 0, 0);
+    pMetaXfer = vdMetaXferAlloc(pIoStorage, 0, 0);
     if (!pMetaXfer)
         return VERR_NO_MEMORY;
@@ -3260,7 +3254,7 @@
     RTListAppend(&pMetaXfer->ListIoCtxWaiting, &pDeferred->NodeDeferred);
     VDMETAXFER_TXDIR_SET(pMetaXfer->fFlags, VDMETAXFER_TXDIR_FLUSH);
-    rc = pImage->pInterfaceIOCallbacks->pfnFlushAsync(pImage->pInterfaceIO->pvUser,
-                                                      pIoStorage->pStorage,
-                                                      pIoTask, &pvTask);
+    rc = pVDIo->pInterfaceIOCallbacks->pfnFlushAsync(pVDIo->pInterfaceIO->pvUser,
+                                                     pIoStorage->pStorage,
+                                                     pIoTask, &pvTask);
     if (RT_SUCCESS(rc))
     {
@@ -3280,6 +3274,6 @@
                                  void *pvBuf, size_t cbBuf)
 {
-    PVDIMAGE pImage = (PVDIMAGE)pvUser;
-    PVBOXHDD pDisk  = pImage->pDisk;
+    PVDIO    pVDIo = (PVDIO)pvUser;
+    PVBOXHDD pDisk = pVDIo->pDisk;
     size_t cbCopied = 0;
 
@@ -3297,6 +3291,6 @@
                                    void *pvBuf, size_t cbBuf)
 {
-    PVDIMAGE pImage = (PVDIMAGE)pvUser;
-    PVBOXHDD pDisk  = pImage->pDisk;
+    PVDIO    pVDIo = (PVDIO)pvUser;
+    PVBOXHDD pDisk = pVDIo->pDisk;
     size_t cbCopied = 0;
 
@@ -3313,6 +3307,6 @@
 static size_t vdIOIntIoCtxSet(void *pvUser, PVDIOCTX pIoCtx, int ch, size_t cb)
 {
-    PVDIMAGE pImage = (PVDIMAGE)pvUser;
-    PVBOXHDD pDisk  = pImage->pDisk;
+    PVDIO    pVDIo = (PVDIO)pvUser;
+    PVBOXHDD pDisk = pVDIo->pDisk;
     size_t cbSet = 0;
 
@@ -3331,6 +3325,6 @@
                                          size_t cbData)
 {
-    PVDIMAGE pImage = (PVDIMAGE)pvUser;
-    PVBOXHDD pDisk  = pImage->pDisk;
+    PVDIO    pVDIo = (PVDIO)pvUser;
+    PVBOXHDD pDisk = pVDIo->pDisk;
     size_t cbCreated = 0;
 
@@ -4011,5 +4005,5 @@
         }
 
-        pImage->pDisk       = pDisk;
+        pImage->VDIo.pDisk  = pDisk;
         pImage->pVDIfsImage = pVDIfsImage;
 
@@ -4025,13 +4019,13 @@
 
         /* Set up the I/O interface. */
-        pImage->pInterfaceIO = VDInterfaceGet(pVDIfsImage, VDINTERFACETYPE_IO);
-        if (pImage->pInterfaceIO)
-            pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO);
+        pImage->VDIo.pInterfaceIO = VDInterfaceGet(pVDIfsImage, VDINTERFACETYPE_IO);
+        if (pImage->VDIo.pInterfaceIO)
+            pImage->VDIo.pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->VDIo.pInterfaceIO);
         else
         {
-            rc = VDInterfaceAdd(&pImage->VDIIO, "VD_IO", VDINTERFACETYPE_IO,
+            rc = VDInterfaceAdd(&pImage->VDIo.VDIIO, "VD_IO", VDINTERFACETYPE_IO,
                                 &pDisk->VDIIOCallbacks, pDisk, &pVDIfsImage);
-            pImage->pInterfaceIO = &pImage->VDIIO;
-            pImage->pInterfaceIOCallbacks = &pDisk->VDIIOCallbacks;
+            pImage->VDIo.pInterfaceIO = &pImage->VDIo.VDIIO;
+            pImage->VDIo.pInterfaceIOCallbacks = &pDisk->VDIIOCallbacks;
         }
 
@@ -4039,6 +4033,6 @@
         AssertBreakStmt(!VDInterfaceGet(pVDIfsImage, VDINTERFACETYPE_IOINT),
                         rc = VERR_INVALID_PARAMETER);
-        rc = VDInterfaceAdd(&pImage->VDIIOInt, "VD_IOINT", VDINTERFACETYPE_IOINT,
-                            &pDisk->VDIIOIntCallbacks, pImage, &pImage->pVDIfsImage);
+        rc = VDInterfaceAdd(&pImage->VDIo.VDIIOInt, "VD_IOINT", VDINTERFACETYPE_IOINT,
+                            &pDisk->VDIIOIntCallbacks, &pImage->VDIo, &pImage->pVDIfsImage);
         AssertRC(rc);
 
@@ -4079,4 +4073,6 @@
         fLockWrite = true;
 
+        pImage->VDIo.pBackendData = pImage->pBackendData;
+
         /* Check image type. As the image itself has only partial knowledge
          * whether it's a base image or not, this info is derived here. The
@@ -4264,5 +4260,5 @@
         }
 
-        pCache->pDisk       = pDisk;
+        pCache->VDIo.pDisk  = pDisk;
         pCache->pVDIfsCache = pVDIfsCache;
 
@@ -4278,13 +4274,13 @@
 
         /* Set up the I/O interface. */
-        pCache->pInterfaceIO = VDInterfaceGet(pVDIfsCache, VDINTERFACETYPE_IO);
-        if (pCache->pInterfaceIO)
-            pCache->pInterfaceIOCallbacks = VDGetInterfaceIO(pCache->pInterfaceIO);
+        pCache->VDIo.pInterfaceIO = VDInterfaceGet(pVDIfsCache, VDINTERFACETYPE_IO);
+        if (pCache->VDIo.pInterfaceIO)
+            pCache->VDIo.pInterfaceIOCallbacks = VDGetInterfaceIO(pCache->VDIo.pInterfaceIO);
         else
         {
-            rc = VDInterfaceAdd(&pCache->VDIIO, "VD_IO", VDINTERFACETYPE_IO,
+            rc = VDInterfaceAdd(&pCache->VDIo.VDIIO, "VD_IO", VDINTERFACETYPE_IO,
                                 &pDisk->VDIIOCallbacks, pDisk, &pVDIfsCache);
-            pCache->pInterfaceIO = &pCache->VDIIO;
-            pCache->pInterfaceIOCallbacks = &pDisk->VDIIOCallbacks;
+            pCache->VDIo.pInterfaceIO = &pCache->VDIo.VDIIO;
+            pCache->VDIo.pInterfaceIOCallbacks = &pDisk->VDIIOCallbacks;
         }
 
@@ -4292,6 +4288,6 @@
         AssertBreakStmt(!VDInterfaceGet(pVDIfsCache, VDINTERFACETYPE_IOINT),
                         rc = VERR_INVALID_PARAMETER);
-        rc = VDInterfaceAdd(&pCache->VDIIOInt, "VD_IOINT", VDINTERFACETYPE_IOINT,
-                            &pDisk->VDIIOIntCallbacks, pCache, &pCache->pVDIfsCache);
+        rc = VDInterfaceAdd(&pCache->VDIo.VDIIOInt, "VD_IOINT", VDINTERFACETYPE_IOINT,
+                            &pDisk->VDIIOIntCallbacks, &pCache->VDIo, &pCache->pVDIfsCache);
         AssertRC(rc);
 
@@ -4509,17 +4505,17 @@
             break;
         }
-        pImage->pDisk       = pDisk;
+        pImage->VDIo.pDisk  = pDisk;
         pImage->pVDIfsImage = pVDIfsImage;
 
         /* Set up the I/O interface. */
-        pImage->pInterfaceIO = VDInterfaceGet(pVDIfsImage, VDINTERFACETYPE_IO);
-        if (pImage->pInterfaceIO)
-            pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO);
+        pImage->VDIo.pInterfaceIO = VDInterfaceGet(pVDIfsImage, VDINTERFACETYPE_IO);
+        if (pImage->VDIo.pInterfaceIO)
+            pImage->VDIo.pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->VDIo.pInterfaceIO);
         else
         {
-            rc = VDInterfaceAdd(&pImage->VDIIO, "VD_IO", VDINTERFACETYPE_IO,
+            rc = VDInterfaceAdd(&pImage->VDIo.VDIIO, "VD_IO", VDINTERFACETYPE_IO,
                                 &pDisk->VDIIOCallbacks, pDisk, &pVDIfsImage);
-            pImage->pInterfaceIO = &pImage->VDIIO;
-            pImage->pInterfaceIOCallbacks = &pDisk->VDIIOCallbacks;
+            pImage->VDIo.pInterfaceIO = &pImage->VDIo.VDIIO;
+            pImage->VDIo.pInterfaceIOCallbacks = &pDisk->VDIIOCallbacks;
         }
 
@@ -4527,6 +4523,6 @@
         AssertBreakStmt(!VDInterfaceGet(pVDIfsImage, VDINTERFACETYPE_IOINT),
                         rc = VERR_INVALID_PARAMETER);
-        rc = VDInterfaceAdd(&pImage->VDIIOInt, "VD_IOINT", VDINTERFACETYPE_IOINT,
-                            &pDisk->VDIIOIntCallbacks, pImage, &pImage->pVDIfsImage);
+        rc = VDInterfaceAdd(&pImage->VDIo.VDIIOInt, "VD_IOINT", VDINTERFACETYPE_IOINT,
+                            &pDisk->VDIIOIntCallbacks, &pImage->VDIo, &pImage->pVDIfsImage);
         AssertRC(rc);
 
@@ -4576,4 +4572,5 @@
         if (RT_SUCCESS(rc))
         {
+            pImage->VDIo.pBackendData = pImage->pBackendData;
             pImage->uImageFlags = uImageFlags;
 
@@ -4791,17 +4788,17 @@
         }
 
-        pImage->pDisk       = pDisk;
+        pImage->VDIo.pDisk  = pDisk;
         pImage->pVDIfsImage = pVDIfsImage;
 
         /* Set up the I/O interface. */
-        pImage->pInterfaceIO = VDInterfaceGet(pVDIfsImage, VDINTERFACETYPE_IO);
-        if (pImage->pInterfaceIO)
-            pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO);
+        pImage->VDIo.pInterfaceIO = VDInterfaceGet(pVDIfsImage, VDINTERFACETYPE_IO);
+        if (pImage->VDIo.pInterfaceIO)
+            pImage->VDIo.pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->VDIo.pInterfaceIO);
         else
         {
-            rc = VDInterfaceAdd(&pImage->VDIIO, "VD_IO", VDINTERFACETYPE_IO,
+            rc = VDInterfaceAdd(&pImage->VDIo.VDIIO, "VD_IO", VDINTERFACETYPE_IO,
                                 &pDisk->VDIIOCallbacks, pDisk, &pVDIfsImage);
-            pImage->pInterfaceIO = &pImage->VDIIO;
-            pImage->pInterfaceIOCallbacks = &pDisk->VDIIOCallbacks;
+            pImage->VDIo.pInterfaceIO = &pImage->VDIo.VDIIO;
+            pImage->VDIo.pInterfaceIOCallbacks = &pDisk->VDIIOCallbacks;
         }
 
@@ -4809,6 +4806,6 @@
         AssertBreakStmt(!VDInterfaceGet(pVDIfsImage, VDINTERFACETYPE_IOINT),
                         rc = VERR_INVALID_PARAMETER);
-        rc = VDInterfaceAdd(&pImage->VDIIOInt, "VD_IOINT", VDINTERFACETYPE_IOINT,
-                            &pDisk->VDIIOIntCallbacks, pImage, &pImage->pVDIfsImage);
+        rc = VDInterfaceAdd(&pImage->VDIo.VDIIOInt, "VD_IOINT", VDINTERFACETYPE_IOINT,
+                            &pDisk->VDIIOIntCallbacks, &pImage->VDIo, &pImage->pVDIfsImage);
         AssertRC(rc);
 
@@ -4842,4 +4839,5 @@
         if (RT_SUCCESS(rc))
         {
+            pImage->VDIo.pBackendData = pImage->pBackendData;
             pImage->uImageFlags = uImageFlags;
 
@@ -5013,7 +5011,4 @@
         AssertRC(rc2);
         fLockRead = true;
-        AssertMsgBreakStmt(pDisk->cImages != 0,
-                           ("Create diff image cannot be done without other images open\n"),
-                           rc = VERR_VD_INVALID_STATE);
         AssertMsgBreakStmt(!pDisk->pCache,
                            ("Create cache image cannot be done with a cache already attached\n"),
@@ -5047,17 +5042,17 @@
         }
 
-        pCache->pDisk       = pDisk;
-        pCache->pVDIfsCache = pVDIfsCache;
+        pCache->VDIo.pDisk        = pDisk;
+        pCache->pVDIfsCache       = pVDIfsCache;
 
         /* Set up the I/O interface. */
-        pCache->pInterfaceIO = VDInterfaceGet(pVDIfsCache, VDINTERFACETYPE_IO);
-        if (pCache->pInterfaceIO)
-            pCache->pInterfaceIOCallbacks = VDGetInterfaceIO(pCache->pInterfaceIO);
+        pCache->VDIo.pInterfaceIO = VDInterfaceGet(pVDIfsCache, VDINTERFACETYPE_IO);
+        if (pCache->VDIo.pInterfaceIO)
+            pCache->VDIo.pInterfaceIOCallbacks = VDGetInterfaceIO(pCache->VDIo.pInterfaceIO);
         else
         {
-            rc = VDInterfaceAdd(&pCache->VDIIO, "VD_IO", VDINTERFACETYPE_IO,
+            rc = VDInterfaceAdd(&pCache->VDIo.VDIIO, "VD_IO", VDINTERFACETYPE_IO,
                                 &pDisk->VDIIOCallbacks, pDisk, &pVDIfsCache);
-            pCache->pInterfaceIO = &pCache->VDIIO;
-            pCache->pInterfaceIOCallbacks = &pDisk->VDIIOCallbacks;
+            pCache->VDIo.pInterfaceIO = &pCache->VDIo.VDIIO;
+            pCache->VDIo.pInterfaceIOCallbacks = &pDisk->VDIIOCallbacks;
         }
 
@@ -5065,6 +5060,6 @@
         AssertBreakStmt(!VDInterfaceGet(pVDIfsCache, VDINTERFACETYPE_IOINT),
                         rc = VERR_INVALID_PARAMETER);
-        rc = VDInterfaceAdd(&pCache->VDIIOInt, "VD_IOINT", VDINTERFACETYPE_IOINT,
-                            &pDisk->VDIIOIntCallbacks, pCache, &pCache->pVDIfsCache);
+        rc = VDInterfaceAdd(&pCache->VDIo.VDIIOInt, "VD_IOINT", VDINTERFACETYPE_IOINT,
+                            &pDisk->VDIIOIntCallbacks, &pCache->VDIo, &pCache->pVDIfsCache);
         AssertRC(rc);
 
@@ -5101,4 +5096,6 @@
             fLockWrite = true;
 
+            pCache->VDIo.pBackendData = pCache->pBackendData;
+
             /* Re-check state, as the lock wasn't held and another image
              * creation call could have been done by another thread. */
@@ -5108,5 +5105,6 @@
         }
 
-        if (RT_SUCCESS(rc))
+        if (   RT_SUCCESS(rc)
+            && pDisk->pLast)
         {
             RTUUID UuidModification;
Index: /trunk/src/VBox/Storage/testcase/vbox-img.cpp
===================================================================
--- /trunk/src/VBox/Storage/testcase/vbox-img.cpp	(revision 33744)
+++ /trunk/src/VBox/Storage/testcase/vbox-img.cpp	(revision 33745)
@@ -52,5 +52,7 @@
                  "   info         --filename <filename>\n"
                  "\n"
-                 "   compact      --filename <filename>\n",
+                 "   compact      --filename <filename>\n"
+                 "   createcache  --filename <filename>\n"
+                 "                --size <cache size>\n",
                  g_pszProgName);
 }
@@ -969,4 +971,63 @@
 
 
+int handleCreateCache(HandlerArg *a)
+{
+    int rc = VINF_SUCCESS;
+    PVBOXHDD pDisk = NULL;
+    const char *pszFilename = NULL;
+    uint64_t cbSize = 0;
+
+    /* Parse the command line. */
+    static const RTGETOPTDEF s_aOptions[] =
+    {
+        { "--filename", 'f', RTGETOPT_REQ_STRING },
+        { "--size",     's', RTGETOPT_REQ_UINT64 }
+    };
+    int ch;
+    RTGETOPTUNION ValueUnion;
+    RTGETOPTSTATE GetState;
+    RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0 /* fFlags */);
+    while ((ch = RTGetOpt(&GetState, &ValueUnion)))
+    {
+        switch (ch)
+        {
+            case 'f':   // --filename
+                pszFilename = ValueUnion.psz;
+                break;
+
+            case 's':   // --size
+                cbSize = ValueUnion.u64;
+                break;
+
+            default:
+                ch = RTGetOptPrintError(ch, &ValueUnion);
+                printUsage(g_pStdErr);
+                return ch;
+        }
+    }
+
+    /* Check for mandatory parameters. */
+    if (!pszFilename)
+        return errorSyntax("Mandatory --filename option missing\n");
+
+    if (!cbSize)
+        return errorSyntax("Mandatory --size option missing\n");
+
+    /* just try it */
+    rc = VDCreate(pVDIfs, VDTYPE_HDD, &pDisk);
+    if (RT_FAILURE(rc))
+        return errorRuntime("Error while creating the virtual disk container: %Rrc\n", rc);
+
+    rc = VDCreateCache(pDisk, "VCI", pszFilename, cbSize, VD_IMAGE_FLAGS_DEFAULT,
+                       NULL, NULL, VD_OPEN_FLAGS_NORMAL, NULL, NULL);
+    if (RT_FAILURE(rc))
+        return errorRuntime("Error while creating the virtual disk cache: %Rrc\n", rc);
+
+    VDCloseAll(pDisk);
+
+    return rc;
+}
+
+
 int main(int argc, char *argv[])
 {
@@ -1052,9 +1113,10 @@
     } s_commandHandlers[] =
     {
-        { "setuuid", handleSetUUID },
-        { "convert", handleConvert },
-        { "info",    handleInfo    },
-        { "compact", handleCompact },
-        { NULL,               NULL }
+        { "setuuid",     handleSetUUID     },
+        { "convert",     handleConvert     },
+        { "info",        handleInfo        },
+        { "compact",     handleCompact     },
+        { "createcache", handleCreateCache },
+        { NULL,                       NULL }
     };
 
