Index: /trunk/include/VBox/vmm/pdmblkcache.h
===================================================================
--- /trunk/include/VBox/vmm/pdmblkcache.h	(revision 38876)
+++ /trunk/include/VBox/vmm/pdmblkcache.h	(revision 38877)
@@ -57,6 +57,8 @@
     /** Write */
     PDMBLKCACHEXFERDIR_WRITE,
-    /** FLush */
-    PDMBLKCACHEXFERDIR_FLUSH
+    /** Flush */
+    PDMBLKCACHEXFERDIR_FLUSH,
+    /** Discard */
+    PDMBLKCACHEXFERDIR_DISCARD
 } PDMBLKCACHEXFERDIR;
 
@@ -87,7 +89,21 @@
 
 /**
+ * Discard enqueue callback for drivers.
+ *
+ * @param   pDrvIns        The driver instance.
+ * @param   paRanges       Ranges to discard.
+ * @param   cRanges        Number of range entries.
+ * @param   hIoXfer        I/O handle to return on completion.
+ */
+typedef DECLCALLBACK(int) FNPDMBLKCACHEXFERENQUEUEDISCARDDRV(PPDMDRVINS pDrvIns,
+                                                             PCRTRANGE paRanges, unsigned cRanges,
+                                                             PPDMBLKCACHEIOXFER hIoXfer);
+/** Pointer to a FNPDMBLKCACHEXFERENQUEUEDISCARDDRV(). */
+typedef FNPDMBLKCACHEXFERENQUEUEDISCARDDRV *PFNPDMBLKCACHEXFERENQUEUEDISCARDDRV;
+
+/**
  * Completion callback for devices.
  *
- * @param   pDrvIns        The driver instance.
+ * @param   pDrvIns        The device instance.
  * @param   pvUser         User argument given during request initiation.
  * @param   rc             The status code of the completed request.
@@ -100,5 +116,5 @@
  * I/O enqueue callback for devices.
  *
- * @param   pDrvIns        The driver instance.
+ * @param   pDevIns        The device instance.
  * @param   pvUser         User argument given during request initiation.
  * @param   rc             The status code of the completed request.
@@ -112,4 +128,18 @@
 
 /**
+ * Discard enqueue callback for devices.
+ *
+ * @param   pDrvIns        The driver instance.
+ * @param   paRanges       Ranges to discard.
+ * @param   cRanges        Number of range entries.
+ * @param   hIoXfer        I/O handle to return on completion.
+ */
+typedef DECLCALLBACK(int) FNPDMBLKCACHEXFERENQUEUEDISCARDDEV(PPDMDEVINS pDevIns,
+                                                             PCRTRANGE paRanges, unsigned cRanges,
+                                                             PPDMBLKCACHEIOXFER hIoXfer);
+/** Pointer to a FNPDMBLKCACHEXFERENQUEUEDISCARDDEV(). */
+typedef FNPDMBLKCACHEXFERENQUEUEDISCARDDEV *PFNPDMBLKCACHEXFERENQUEUEDISCARDDEV;
+
+/**
  * Completion callback for drivers.
  *
@@ -137,4 +167,18 @@
 
 /**
+ * Discard enqueue callback for VMM internal users.
+ *
+ * @param   pDrvIns        The driver instance.
+ * @param   paRanges       Ranges to discard.
+ * @param   cRanges        Number of range entries.
+ * @param   hIoXfer        I/O handle to return on completion.
+ */
+typedef DECLCALLBACK(int) FNPDMBLKCACHEXFERENQUEUEDISCARDINT(void *pvUser,
+                                                             PCRTRANGE paRanges, unsigned cRanges,
+                                                             PPDMBLKCACHEIOXFER hIoXfer);
+/** Pointer to a FNPDMBLKCACHEXFERENQUEUEDISCARDINT(). */
+typedef FNPDMBLKCACHEXFERENQUEUEDISCARDINT *PFNPDMBLKCACHEXFERENQUEUEDISCARDINT;
+
+/**
  * Completion callback for USB.
  *
@@ -162,17 +206,33 @@
 
 /**
+ * Discard enqueue callback for USB devices.
+ *
+ * @param   pUsbIns        The USB device instance.
+ * @param   paRanges       Ranges to discard.
+ * @param   cRanges        Number of range entries.
+ * @param   hIoXfer        I/O handle to return on completion.
+ */
+typedef DECLCALLBACK(int) FNPDMBLKCACHEXFERENQUEUEDISCARDUSB(PPDMUSBINS pUsbIns,
+                                                             PCRTRANGE paRanges, unsigned cRanges,
+                                                             PPDMBLKCACHEIOXFER hIoXfer);
+/** Pointer to a FNPDMBLKCACHEXFERENQUEUEDISCARDUSB(). */
+typedef FNPDMBLKCACHEXFERENQUEUEDISCARDUSB *PFNPDMBLKCACHEXFERENQUEUEDISCARDUSB;
+
+/**
  * Create a block cache user for a driver instance.
  *
  * @returns VBox status code.
- * @param   pVM             Pointer to the shared VM structure.
- * @param   pDrvIns         The driver instance.
- * @param   ppBlkCache      Where to store the handle to the block cache.
- * @param   pfnXferComplete The I/O transfer complete callback.
- * @param   pfnXferEnqueue  The I/O request enqueue callback.
- * @param   pcszId          Unique ID used to identify the user.
+ * @param   pVM                      Pointer to the shared VM structure.
+ * @param   pDrvIns                  The driver instance.
+ * @param   ppBlkCache               Where to store the handle to the block cache.
+ * @param   pfnXferComplete          The I/O transfer complete callback.
+ * @param   pfnXferEnqueue           The I/O request enqueue callback.
+ * @param   pfnXferEnqueueDiscard    The discard request enqueue callback.
+ * @param   pcszId                   Unique ID used to identify the user.
  */
 VMMR3DECL(int) PDMR3BlkCacheRetainDriver(PVM pVM, PPDMDRVINS pDrvIns, PPPDMBLKCACHE ppBlkCache,
                                          PFNPDMBLKCACHEXFERCOMPLETEDRV pfnXferComplete,
                                          PFNPDMBLKCACHEXFERENQUEUEDRV pfnXferEnqueue,
+                                         PFNPDMBLKCACHEXFERENQUEUEDISCARDDRV pfnXferEnqueueDiscard,
                                          const char *pcszId);
 
@@ -181,14 +241,16 @@
  *
  * @returns VBox status code.
- * @param   pVM             Pointer to the shared VM structure.
- * @param   pDevIns         The device instance.
- * @param   ppBlkCache      Where to store the handle to the block cache.
- * @param   pfnXferComplete The I/O transfer complete callback.
- * @param   pfnXferEnqueue  The I/O request enqueue callback.
- * @param   pcszId          Unique ID used to identify the user.
+ * @param   pVM                      Pointer to the shared VM structure.
+ * @param   pDevIns                  The device instance.
+ * @param   ppBlkCache               Where to store the handle to the block cache.
+ * @param   pfnXferComplete          The I/O transfer complete callback.
+ * @param   pfnXferEnqueue           The I/O request enqueue callback.
+ * @param   pfnXferEnqueueDiscard    The discard request enqueue callback.
+ * @param   pcszId                   Unique ID used to identify the user.
  */
 VMMR3DECL(int) PDMR3BlkCacheRetainDevice(PVM pVM, PPDMDEVINS pDevIns, PPPDMBLKCACHE ppBlkCache,
                                          PFNPDMBLKCACHEXFERCOMPLETEDEV pfnXferComplete,
                                          PFNPDMBLKCACHEXFERENQUEUEDEV pfnXferEnqueue,
+                                         PFNPDMBLKCACHEXFERENQUEUEDISCARDDEV pfnXferEnqueueDiscard,
                                          const char *pcszId);
 
@@ -197,14 +259,16 @@
  *
  * @returns VBox status code.
- * @param   pVM             Pointer to the shared VM structure.
- * @param   pUsbIns         The USB device instance.
- * @param   ppBlkCache      Where to store the handle to the block cache.
- * @param   pfnXferComplete The I/O transfer complete callback.
- * @param   pfnXferEnqueue  The I/O request enqueue callback.
- * @param   pcszId          Unique ID used to identify the user.
+ * @param   pVM                      Pointer to the shared VM structure.
+ * @param   pUsbIns                  The USB device instance.
+ * @param   ppBlkCache               Where to store the handle to the block cache.
+ * @param   pfnXferComplete          The I/O transfer complete callback.
+ * @param   pfnXferEnqueue           The I/O request enqueue callback.
+ * @param   pfnXferEnqueueDiscard    The discard request enqueue callback.
+ * @param   pcszId                   Unique ID used to identify the user.
  */
 VMMR3DECL(int) PDMR3BlkCacheRetainUsb(PVM pVM, PPDMUSBINS pUsbIns, PPPDMBLKCACHE ppBlkCache,
                                       PFNPDMBLKCACHEXFERCOMPLETEUSB pfnXferComplete,
                                       PFNPDMBLKCACHEXFERENQUEUEUSB pfnXferEnqueue,
+                                      PFNPDMBLKCACHEXFERENQUEUEDISCARDUSB pfnXferEnqueueDiscard,
                                       const char *pcszId);
 
@@ -213,14 +277,16 @@
  *
  * @returns VBox status code.
- * @param   pVM             Pointer to the shared VM structure.
- * @param   pvUser          Opaque user data.
- * @param   ppBlkCache      Where to store the handle to the block cache.
- * @param   pfnXferComplete The I/O transfer complete callback.
- * @param   pfnXferEnqueue  The I/O request enqueue callback.
- * @param   pcszId          Unique ID used to identify the user.
+ * @param   pVM                      Pointer to the shared VM structure.
+ * @param   pvUser                   Opaque user data.
+ * @param   ppBlkCache               Where to store the handle to the block cache.
+ * @param   pfnXferComplete          The I/O transfer complete callback.
+ * @param   pfnXferEnqueue           The I/O request enqueue callback.
+ * @param   pfnXferEnqueueDiscard    The discard request enqueue callback.
+ * @param   pcszId                   Unique ID used to identify the user.
  */
 VMMR3DECL(int) PDMR3BlkCacheRetainInt(PVM pVM, void *pvUser, PPPDMBLKCACHE ppBlkCache,
                                       PFNPDMBLKCACHEXFERCOMPLETEINT pfnXferComplete,
                                       PFNPDMBLKCACHEXFERENQUEUEINT pfnXferEnqueue,
+                                      PFNPDMBLKCACHEXFERENQUEUEDISCARDINT pfnXferEnqueueDiscard,
                                       const char *pcszId);
 
@@ -297,7 +363,18 @@
  * @param   pvUser          Opaque user data returned in the completion callback
  *                          upon completion of the task.
- * @param   ppTask          Where to store the task handle on success.
  */
 VMMR3DECL(int) PDMR3BlkCacheFlush(PPDMBLKCACHE pBlkCache, void *pvUser);
+
+/**
+ * Discards the given ranges from the cache.
+ *
+ * @returns VBox status code.
+ * @param   pEndpoint       The file endpoint to flush.
+ * @param   paRanges        Array of ranges to discard.
+ * @param   cRanges         Number of ranges in the array.
+ * @param   pvUser          Opaque user data returned in the completion callback
+ *                          upon completion of the task.
+ */
+VMMR3DECL(int) PDMR3BlkCacheDiscard(PPDMBLKCACHE pBlkCache, PCRTRANGE paRanges, unsigned cRanges, void *pvUser);
 
 /**
Index: /trunk/src/VBox/VMM/VMMR3/PDMBlkCache.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/PDMBlkCache.cpp	(revision 38876)
+++ /trunk/src/VBox/VMM/VMMR3/PDMBlkCache.cpp	(revision 38877)
@@ -1271,4 +1271,5 @@
                                          PFNPDMBLKCACHEXFERCOMPLETEDRV pfnXferComplete,
                                          PFNPDMBLKCACHEXFERENQUEUEDRV pfnXferEnqueue,
+                                         PFNPDMBLKCACHEXFERENQUEUEDISCARDDRV pfnXferEnqueueDiscard,
                                          const char *pcszId)
 {
@@ -1279,8 +1280,9 @@
     if (RT_SUCCESS(rc))
     {
-        pBlkCache->enmType = PDMBLKCACHETYPE_DRV;
-        pBlkCache->u.Drv.pfnXferComplete = pfnXferComplete;
-        pBlkCache->u.Drv.pfnXferEnqueue  = pfnXferEnqueue;
-        pBlkCache->u.Drv.pDrvIns         = pDrvIns;
+        pBlkCache->enmType                      = PDMBLKCACHETYPE_DRV;
+        pBlkCache->u.Drv.pfnXferComplete        = pfnXferComplete;
+        pBlkCache->u.Drv.pfnXferEnqueue         = pfnXferEnqueue;
+        pBlkCache->u.Drv.pfnXferEnqueueDiscard  = pfnXferEnqueueDiscard;
+        pBlkCache->u.Drv.pDrvIns                = pDrvIns;
         *ppBlkCache = pBlkCache;
     }
@@ -1293,4 +1295,5 @@
                                          PFNPDMBLKCACHEXFERCOMPLETEDEV pfnXferComplete,
                                          PFNPDMBLKCACHEXFERENQUEUEDEV pfnXferEnqueue,
+                                         PFNPDMBLKCACHEXFERENQUEUEDISCARDDEV pfnXferEnqueueDiscard,
                                          const char *pcszId)
 {
@@ -1301,8 +1304,9 @@
     if (RT_SUCCESS(rc))
     {
-        pBlkCache->enmType = PDMBLKCACHETYPE_DEV;
-        pBlkCache->u.Dev.pfnXferComplete = pfnXferComplete;
-        pBlkCache->u.Dev.pfnXferEnqueue  = pfnXferEnqueue;
-        pBlkCache->u.Dev.pDevIns         = pDevIns;
+        pBlkCache->enmType                      = PDMBLKCACHETYPE_DEV;
+        pBlkCache->u.Dev.pfnXferComplete        = pfnXferComplete;
+        pBlkCache->u.Dev.pfnXferEnqueue         = pfnXferEnqueue;
+        pBlkCache->u.Dev.pfnXferEnqueueDiscard  = pfnXferEnqueueDiscard;
+        pBlkCache->u.Dev.pDevIns                = pDevIns;
         *ppBlkCache = pBlkCache;
     }
@@ -1316,4 +1320,5 @@
                                       PFNPDMBLKCACHEXFERCOMPLETEUSB pfnXferComplete,
                                       PFNPDMBLKCACHEXFERENQUEUEUSB pfnXferEnqueue,
+                                      PFNPDMBLKCACHEXFERENQUEUEDISCARDUSB pfnXferEnqueueDiscard,
                                       const char *pcszId)
 {
@@ -1324,8 +1329,9 @@
     if (RT_SUCCESS(rc))
     {
-        pBlkCache->enmType = PDMBLKCACHETYPE_USB;
-        pBlkCache->u.Usb.pfnXferComplete = pfnXferComplete;
-        pBlkCache->u.Usb.pfnXferEnqueue  = pfnXferEnqueue;
-        pBlkCache->u.Usb.pUsbIns         = pUsbIns;
+        pBlkCache->enmType                      = PDMBLKCACHETYPE_USB;
+        pBlkCache->u.Usb.pfnXferComplete        = pfnXferComplete;
+        pBlkCache->u.Usb.pfnXferEnqueue         = pfnXferEnqueue;
+        pBlkCache->u.Usb.pfnXferEnqueueDiscard  = pfnXferEnqueueDiscard;
+        pBlkCache->u.Usb.pUsbIns                = pUsbIns;
         *ppBlkCache = pBlkCache;
     }
@@ -1339,4 +1345,5 @@
                                       PFNPDMBLKCACHEXFERCOMPLETEINT pfnXferComplete,
                                       PFNPDMBLKCACHEXFERENQUEUEINT pfnXferEnqueue,
+                                      PFNPDMBLKCACHEXFERENQUEUEDISCARDINT pfnXferEnqueueDiscard,
                                       const char *pcszId)
 {
@@ -1347,8 +1354,9 @@
     if (RT_SUCCESS(rc))
     {
-        pBlkCache->enmType = PDMBLKCACHETYPE_INTERNAL;
-        pBlkCache->u.Int.pfnXferComplete = pfnXferComplete;
-        pBlkCache->u.Int.pfnXferEnqueue  = pfnXferEnqueue;
-        pBlkCache->u.Int.pvUser          = pvUser;
+        pBlkCache->enmType                      = PDMBLKCACHETYPE_INTERNAL;
+        pBlkCache->u.Int.pfnXferComplete        = pfnXferComplete;
+        pBlkCache->u.Int.pfnXferEnqueue         = pfnXferEnqueue;
+        pBlkCache->u.Int.pfnXferEnqueueDiscard  = pfnXferEnqueueDiscard;
+        pBlkCache->u.Int.pvUser                 = pvUser;
         *ppBlkCache = pBlkCache;
     }
@@ -2408,4 +2416,154 @@
 }
 
+VMMR3DECL(int) PDMR3BlkCacheDiscard(PPDMBLKCACHE pBlkCache, PCRTRANGE paRanges,
+                                    unsigned cRanges, void *pvUser)
+{
+    int rc = VINF_SUCCESS;
+    PPDMBLKCACHEGLOBAL pCache = pBlkCache->pCache;
+    PPDMBLKCACHEENTRY pEntry;
+    PPDMBLKCACHEREQ pReq;
+
+    LogFlowFunc((": pBlkCache=%#p{%s} paRanges=%#p cRanges=%u pvUser=%#p\n",
+                 pBlkCache, pBlkCache->pszId, paRanges, cRanges, pvUser));
+
+    AssertPtrReturn(pBlkCache, VERR_INVALID_POINTER);
+    AssertReturn(!pBlkCache->fSuspended, VERR_INVALID_STATE);
+
+    /* Allocate new request structure. */
+    pReq = pdmBlkCacheReqAlloc(pvUser);
+    if (RT_UNLIKELY(!pReq))
+        return VERR_NO_MEMORY;
+
+    /* Increment data transfer counter to keep the request valid while we access it. */
+    ASMAtomicIncU32(&pReq->cXfersPending);
+
+    for (unsigned i = 0; i < cRanges; i++)
+    {
+        uint64_t offCur = paRanges[i].offStart;
+        size_t cbLeft = paRanges[i].cbRange;
+
+        while (cbLeft)
+        {
+            size_t cbThisDiscard;
+
+            pEntry = pdmBlkCacheGetCacheEntryByOffset(pBlkCache, offCur);
+
+            if (pEntry)
+            {
+                /* Write the data into the entry and mark it as dirty */
+                AssertPtr(pEntry->pList);
+
+                uint64_t offDiff = offCur - pEntry->Core.Key;
+
+                AssertMsg(offCur >= pEntry->Core.Key,
+                          ("Overflow in calculation offCur=%llu OffsetAligned=%llu\n",
+                          offCur, pEntry->Core.Key));
+
+                cbThisDiscard = RT_MIN(pEntry->cbData - offDiff, cbLeft);
+
+                /* Ghost lists contain no data. */
+                if (   (pEntry->pList == &pCache->LruRecentlyUsedIn)
+                    || (pEntry->pList == &pCache->LruFrequentlyUsed))
+                {
+                    /* Check if the entry is dirty. */
+                    if (pdmBlkCacheEntryFlagIsSetClearAcquireLock(pBlkCache, pEntry,
+                                                                  PDMBLKCACHE_ENTRY_IS_DIRTY,
+                                                                  0))
+                    {
+                        /* If it is dirty but not yet in progress remove it. */
+                        if (!(pEntry->fFlags & PDMBLKCACHE_ENTRY_IO_IN_PROGRESS))
+                        {
+                            pdmBlkCacheLockEnter(pCache);
+                            pdmBlkCacheEntryRemoveFromList(pEntry); 
+
+                            STAM_PROFILE_ADV_START(&pCache->StatTreeRemove, Cache);
+                            RTAvlrU64Remove(pBlkCache->pTree, pEntry->Core.Key);
+                            STAM_PROFILE_ADV_STOP(&pCache->StatTreeRemove, Cache);
+
+                            pdmBlkCacheLockLeave(pCache);
+
+                            RTMemFree(pEntry);
+                        }
+                        else
+                        {
+#if 0
+                            /* The data isn't written to the file yet */
+                            pdmBlkCacheEntryWaitersAdd(pEntry, pReq,
+                                                       &SgBuf, offDiff, cbToWrite,
+                                                       true /* fWrite */);
+                            STAM_COUNTER_INC(&pBlkCache->StatWriteDeferred);
+#endif
+                        }
+
+                        RTSemRWReleaseWrite(pBlkCache->SemRWEntries);
+                        pdmBlkCacheEntryRelease(pEntry);
+                    }
+                    else /* Dirty bit not set */
+                    {
+                        /*
+                         * Check if a read is in progress for this entry.
+                         * We have to defer processing in that case.
+                         */
+                        if(pdmBlkCacheEntryFlagIsSetClearAcquireLock(pBlkCache, pEntry,
+                                                                     PDMBLKCACHE_ENTRY_IO_IN_PROGRESS,
+                                                                     0))
+                        {
+#if 0
+                            pdmBlkCacheEntryWaitersAdd(pEntry, pReq,
+                                                       &SgBuf, offDiff, cbToWrite,
+                                                       true /* fWrite */);
+#endif
+                            STAM_COUNTER_INC(&pBlkCache->StatWriteDeferred);
+                            RTSemRWReleaseWrite(pBlkCache->SemRWEntries);
+                            pdmBlkCacheEntryRelease(pEntry);
+                        }
+                        else /* I/O in progress flag not set */
+                        {
+                            pdmBlkCacheLockEnter(pCache);
+                            pdmBlkCacheEntryRemoveFromList(pEntry); 
+
+                            RTSemRWRequestWrite(pBlkCache->SemRWEntries, RT_INDEFINITE_WAIT);
+                            STAM_PROFILE_ADV_START(&pCache->StatTreeRemove, Cache);
+                            RTAvlrU64Remove(pBlkCache->pTree, pEntry->Core.Key);
+                            STAM_PROFILE_ADV_STOP(&pCache->StatTreeRemove, Cache);
+                            RTSemRWReleaseWrite(pBlkCache->SemRWEntries);
+
+                            pdmBlkCacheLockLeave(pCache);
+
+                            RTMemFree(pEntry);
+                        }
+                    } /* Dirty bit not set */
+                }
+                else /* Entry is on the ghost list just remove cache entry. */
+                {
+                    pdmBlkCacheLockEnter(pCache);
+                    pdmBlkCacheEntryRemoveFromList(pEntry); 
+
+                    RTSemRWRequestWrite(pBlkCache->SemRWEntries, RT_INDEFINITE_WAIT);
+                    STAM_PROFILE_ADV_START(&pCache->StatTreeRemove, Cache);
+                    RTAvlrU64Remove(pBlkCache->pTree, pEntry->Core.Key);
+                    STAM_PROFILE_ADV_STOP(&pCache->StatTreeRemove, Cache);
+                    RTSemRWReleaseWrite(pBlkCache->SemRWEntries);
+
+                    pdmBlkCacheLockLeave(pCache);
+
+                    RTMemFree(pEntry);
+                }
+            }
+            /* else: no entry found. */
+
+            offCur += cbThisDiscard;
+            cbLeft -= cbThisDiscard;
+        }
+    }
+
+    if (!pdmBlkCacheReqUpdate(pBlkCache, pReq, rc, false))
+        rc = VINF_AIO_TASK_PENDING;
+
+    LogFlowFunc((": Leave rc=%Rrc\n", rc));
+
+    return rc;
+}
+
 /**
  * Completes a task segment freeing all resources and completes the task handle
Index: /trunk/src/VBox/VMM/include/PDMBlkCacheInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/PDMBlkCacheInternal.h	(revision 38876)
+++ /trunk/src/VBox/VMM/include/PDMBlkCacheInternal.h	(revision 38877)
@@ -204,9 +204,11 @@
         {
             /** Pointer to the device instance owning the block cache. */
-            R3PTRTYPE(PPDMDEVINS)                     pDevIns;
+            R3PTRTYPE(PPDMDEVINS)                            pDevIns;
             /** Complete callback to the user. */
-            R3PTRTYPE(PFNPDMBLKCACHEXFERCOMPLETEDEV)  pfnXferComplete;
+            R3PTRTYPE(PFNPDMBLKCACHEXFERCOMPLETEDEV)         pfnXferComplete;
             /** I/O enqueue callback. */
-            R3PTRTYPE(PFNPDMBLKCACHEXFERENQUEUEDEV)   pfnXferEnqueue;
+            R3PTRTYPE(PFNPDMBLKCACHEXFERENQUEUEDEV)          pfnXferEnqueue;
+            /** Discard enqueue callback. */
+            R3PTRTYPE(PFNPDMBLKCACHEXFERENQUEUEDISCARDDEV)   pfnXferEnqueueDiscard;
         } Dev;
         /** PDMASYNCCOMPLETIONTEMPLATETYPE_DRV */
@@ -214,9 +216,11 @@
         {
             /** Pointer to the driver instance owning the block cache. */
-            R3PTRTYPE(PPDMDRVINS)                     pDrvIns;
+            R3PTRTYPE(PPDMDRVINS)                            pDrvIns;
             /** Complete callback to the user. */
-            R3PTRTYPE(PFNPDMBLKCACHEXFERCOMPLETEDRV)  pfnXferComplete;
+            R3PTRTYPE(PFNPDMBLKCACHEXFERCOMPLETEDRV)         pfnXferComplete;
             /** I/O enqueue callback. */
-            R3PTRTYPE(PFNPDMBLKCACHEXFERENQUEUEDRV)   pfnXferEnqueue;
+            R3PTRTYPE(PFNPDMBLKCACHEXFERENQUEUEDRV)          pfnXferEnqueue;
+            /** Discard enqueue callback. */
+            R3PTRTYPE(PFNPDMBLKCACHEXFERENQUEUEDISCARDDRV)   pfnXferEnqueueDiscard;
         } Drv;
         /** PDMASYNCCOMPLETIONTEMPLATETYPE_INTERNAL */
@@ -224,9 +228,11 @@
         {
             /** Pointer to user data. */
-            R3PTRTYPE(void *)                         pvUser;
+            R3PTRTYPE(void *)                                pvUser;
             /** Complete callback to the user. */
-            R3PTRTYPE(PFNPDMBLKCACHEXFERCOMPLETEINT)  pfnXferComplete;
+            R3PTRTYPE(PFNPDMBLKCACHEXFERCOMPLETEINT)         pfnXferComplete;
             /** I/O enqueue callback. */
-            R3PTRTYPE(PFNPDMBLKCACHEXFERENQUEUEINT)   pfnXferEnqueue;
+            R3PTRTYPE(PFNPDMBLKCACHEXFERENQUEUEINT)          pfnXferEnqueue;
+            /** Discard enqueue callback. */
+            R3PTRTYPE(PFNPDMBLKCACHEXFERENQUEUEDISCARDINT)   pfnXferEnqueueDiscard;
         } Int;
         /** PDMASYNCCOMPLETIONTEMPLATETYPE_USB */
@@ -234,16 +240,18 @@
         {
             /** Pointer to the usb instance owning the template. */
-            R3PTRTYPE(PPDMUSBINS)                     pUsbIns;
+            R3PTRTYPE(PPDMUSBINS)                            pUsbIns;
             /** Complete callback to the user. */
-            R3PTRTYPE(PFNPDMBLKCACHEXFERCOMPLETEUSB)  pfnXferComplete;
+            R3PTRTYPE(PFNPDMBLKCACHEXFERCOMPLETEUSB)         pfnXferComplete;
             /** I/O enqueue callback. */
-            R3PTRTYPE(PFNPDMBLKCACHEXFERENQUEUEUSB)   pfnXferEnqueue;
+            R3PTRTYPE(PFNPDMBLKCACHEXFERENQUEUEUSB)          pfnXferEnqueue;
+            /** Discard enqueue callback. */
+            R3PTRTYPE(PFNPDMBLKCACHEXFERENQUEUEDISCARDUSB)   pfnXferEnqueueDiscard;
         } Usb;
     } u;
 
 #ifdef VBOX_WITH_STATISTICS
-    uint32_t    u32Alignment;
+    uint32_t                      u32Alignment;
     /** Number of times a write was deferred because the cache entry was still in progress */
-    STAMCOUNTER StatWriteDeferred;
+    STAMCOUNTER                   StatWriteDeferred;
 #endif
 
@@ -274,6 +282,6 @@
 typedef struct PDMBLKCACHEIOXFER
 {
-    /** Flag whether the I/O xfer updates a cache entry or updates the request directl. */
-    bool fIoCache;
+    /** Flag whether the I/O xfer updates a cache entry or updates the request directly. */
+    bool                  fIoCache;
     /** Type dependent data. */
     union
@@ -281,13 +289,13 @@
         /** Pointer to the entry the transfer updates. */
         PPDMBLKCACHEENTRY pEntry;
-        /** Pointer to the request the ztransfer updates. */
+        /** Pointer to the request the transfer updates. */
         PPDMBLKCACHEREQ   pReq;
     };
+    /** Transfer direction. */
+    PDMBLKCACHEXFERDIR    enmXferDir;
     /** Segment used if a cache entry is updated. */
-    RTSGSEG SgSeg;
+    RTSGSEG               SgSeg;
     /** S/G buffer. */
-    RTSGBUF SgBuf;
-    /** Transfer direction. */
-    PDMBLKCACHEXFERDIR enmXferDir;
+    RTSGBUF               SgBuf;
 } PDMBLKCACHEIOXFER;
 
