Index: trunk/src/VBox/VMM/PDMAsyncCompletionFile.cpp
===================================================================
--- trunk/src/VBox/VMM/PDMAsyncCompletionFile.cpp	(revision 25146)
+++ trunk/src/VBox/VMM/PDMAsyncCompletionFile.cpp	(revision 25147)
@@ -850,4 +850,5 @@
                             PPDMASYNCCOMPLETIONENDPOINT pEndpoint)
 {
+    int rc = VINF_SUCCESS;
     PPDMASYNCCOMPLETIONENDPOINTFILE pEpFile = (PPDMASYNCCOMPLETIONENDPOINTFILE)pEndpoint;
     PPDMASYNCCOMPLETIONTASKFILE pTaskFile = (PPDMASYNCCOMPLETIONTASKFILE)pTask;
@@ -858,14 +859,19 @@
     pTaskFile->cbTransferLeft = 0;
 
-    PPDMACTASKFILE pIoTask = pdmacFileTaskAlloc(pEpFile);
-    AssertPtr(pIoTask);
-
-    pIoTask->pEndpoint       = pEpFile;
-    pIoTask->enmTransferType = PDMACTASKFILETRANSFER_FLUSH;
-    pIoTask->pvUser          = pTaskFile;
-    pIoTask->pfnCompleted    = pdmacFileEpTaskCompleted;
-    pdmacFileEpAddTask(pEpFile, pIoTask);
-
-    return VINF_SUCCESS;
+    if (pEpFile->fCaching)
+        rc = pdmacFileEpCacheFlush(pEpFile, pTaskFile);
+    else
+    {
+        PPDMACTASKFILE pIoTask = pdmacFileTaskAlloc(pEpFile);
+        AssertPtr(pIoTask);
+
+        pIoTask->pEndpoint       = pEpFile;
+        pIoTask->enmTransferType = PDMACTASKFILETRANSFER_FLUSH;
+        pIoTask->pvUser          = pTaskFile;
+        pIoTask->pfnCompleted    = pdmacFileEpTaskCompleted;
+        pdmacFileEpAddTask(pEpFile, pIoTask);
+    }
+
+    return rc;
 }
 
Index: trunk/src/VBox/VMM/PDMAsyncCompletionFileCache.cpp
===================================================================
--- trunk/src/VBox/VMM/PDMAsyncCompletionFileCache.cpp	(revision 25146)
+++ trunk/src/VBox/VMM/PDMAsyncCompletionFileCache.cpp	(revision 25147)
@@ -563,4 +563,39 @@
 
 /**
+ * Completes a task segment freeing all ressources and completes the task handle
+ * if everything was transfered.
+ *
+ * @returns Next task segment handle.
+ * @param   pEndpointCache    The endpoint cache.
+ * @param   pTaskSeg          Task segment to complete.
+ */
+static PPDMACFILETASKSEG pdmacFileCacheTaskComplete(PPDMACFILEENDPOINTCACHE pEndpointCache, PPDMACFILETASKSEG pTaskSeg)
+{
+    PPDMACFILETASKSEG pNext = pTaskSeg->pNext;
+
+    uint32_t uOld = ASMAtomicSubU32(&pTaskSeg->pTask->cbTransferLeft, pTaskSeg->cbTransfer);
+    AssertMsg(uOld >= pTaskSeg->cbTransfer, ("New value would overflow\n"));
+    if (!(uOld - pTaskSeg->cbTransfer)
+        && !ASMAtomicXchgBool(&pTaskSeg->pTask->fCompleted, true))
+    {
+        pdmR3AsyncCompletionCompleteTask(&pTaskSeg->pTask->Core);
+
+        if (pTaskSeg->fWrite)
+        {
+            /* Complete a pending flush if all writes have completed */
+            uint32_t cWritesOutstanding = ASMAtomicDecU32(&pEndpointCache->cWritesOutstanding);
+            PPDMASYNCCOMPLETIONTASKFILE pTaskFlush = (PPDMASYNCCOMPLETIONTASKFILE)ASMAtomicXchgPtr((void * volatile *)&pEndpointCache->pTaskFlush, NULL);
+
+            if (!cWritesOutstanding && pTaskFlush)
+                pdmR3AsyncCompletionCompleteTask(&pTaskFlush->Core);
+        }
+    }
+
+    RTMemFree(pTaskSeg);
+
+    return pNext;
+}
+
+/**
  * Completion callback for I/O tasks.
  *
@@ -613,14 +648,5 @@
                 pEntry->fFlags |= PDMACFILECACHE_ENTRY_IS_DIRTY;
 
-                uint32_t uOld = ASMAtomicSubU32(&pCurr->pTask->cbTransferLeft, pCurr->cbTransfer);
-                AssertMsg(uOld >= pCurr->cbTransfer, ("New value would overflow\n"));
-                if (!(uOld - pCurr->cbTransfer)
-                    && !ASMAtomicXchgBool(&pCurr->pTask->fCompleted, true))
-                    pdmR3AsyncCompletionCompleteTask(&pCurr->pTask->Core);
-
-                PPDMACFILETASKSEG pFree = pCurr;
-                pCurr = pCurr->pNext;
-
-                RTMemFree(pFree);
+                pCurr = pdmacFileCacheTaskComplete(pEndpointCache, pCurr);
             }
         }
@@ -641,14 +667,5 @@
                 memcpy(pCurr->pvBuf, pEntry->pbData + pCurr->uBufOffset, pCurr->cbTransfer);
 
-            uint32_t uOld = ASMAtomicSubU32(&pCurr->pTask->cbTransferLeft, pCurr->cbTransfer);
-            AssertMsg(uOld >= pCurr->cbTransfer, ("New value would overflow\n"));
-            if (!(uOld - pCurr->cbTransfer)
-                && !ASMAtomicXchgBool(&pCurr->pTask->fCompleted, true))
-                pdmR3AsyncCompletionCompleteTask(&pCurr->pTask->Core);
-
-            PPDMACFILETASKSEG pFree = pCurr;
-            pCurr = pCurr->pNext;
-
-            RTMemFree(pFree);
+            pCurr = pdmacFileCacheTaskComplete(pEndpointCache, pCurr);
         }
     }
@@ -1508,4 +1525,5 @@
     /* Set to completed to make sure that the task is valid while we access it. */
     ASMAtomicWriteBool(&pTask->fCompleted, true);
+    ASMAtomicIncU32(&pEndpointCache->cWritesOutstanding);
 
     int iSegCurr       = 0;
@@ -1909,6 +1927,15 @@
     if (ASMAtomicReadS32(&pTask->cbTransferLeft) == 0
         && !ASMAtomicXchgBool(&pTask->fCompleted, true))
+    {
         pdmR3AsyncCompletionCompleteTask(&pTask->Core);
 
+        /* Complete a pending flush if all writes have completed */
+        uint32_t cWritesOutstanding = ASMAtomicDecU32(&pEndpointCache->cWritesOutstanding);
+        PPDMASYNCCOMPLETIONTASKFILE pTaskFlush = (PPDMASYNCCOMPLETIONTASKFILE)ASMAtomicXchgPtr((void * volatile *)&pEndpointCache->pTaskFlush, NULL);
+
+        if (!cWritesOutstanding && pTaskFlush)
+            pdmR3AsyncCompletionCompleteTask(&pTaskFlush->Core);
+    }
+
     return VINF_SUCCESS;
 }
@@ -1916,2 +1943,19 @@
 #undef ADVANCE_SEGMENT_BUFFER
 
+int pdmacFileEpCacheFlush(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint, PPDMASYNCCOMPLETIONTASKFILE pTask)
+{
+    int rc = VINF_SUCCESS;
+
+    if (ASMAtomicReadPtr((void * volatile *)&pEndpoint->DataCache.pTaskFlush))
+        rc = VERR_RESOURCE_BUSY;
+    else
+    {
+        if (ASMAtomicReadU32(&pEndpoint->DataCache.cWritesOutstanding) > 0)
+            ASMAtomicWritePtr((void * volatile *)&pEndpoint->DataCache.pTaskFlush, pTask);
+        else
+            pdmR3AsyncCompletionCompleteTask(&pTask->Core);
+    }
+
+    return rc;
+}
+
Index: trunk/src/VBox/VMM/PDMAsyncCompletionFileInternal.h
===================================================================
--- trunk/src/VBox/VMM/PDMAsyncCompletionFileInternal.h	(revision 25146)
+++ trunk/src/VBox/VMM/PDMAsyncCompletionFileInternal.h	(revision 25147)
@@ -324,13 +324,16 @@
 {
     /** AVL tree managing cache entries. */
-    PAVLRFOFFTREE         pTree;
+    PAVLRFOFFTREE                        pTree;
     /** R/W semaphore protecting cached entries for this endpoint. */
-    RTSEMRW               SemRWEntries;
+    RTSEMRW                              SemRWEntries;
     /** Pointer to the gobal cache data */
-    PPDMACFILECACHEGLOBAL pCache;
-
+    PPDMACFILECACHEGLOBAL                pCache;
+    /** Number of writes outstanding. */
+    volatile uint32_t                    cWritesOutstanding;
+    /** Handle of the flush request if one is active */
+    volatile PPDMASYNCCOMPLETIONTASKFILE pTaskFlush;
 #ifdef VBOX_WITH_STATISTICS
     /** Number of times a write was deferred because the cache entry was still in progress */
-    STAMCOUNTER           StatWriteDeferred;
+    STAMCOUNTER                          StatWriteDeferred;
 #endif
 } PDMACFILEENDPOINTCACHE, *PPDMACFILEENDPOINTCACHE;
@@ -592,4 +595,5 @@
                           RTFOFF off, PCPDMDATASEG paSegments, size_t cSegments,
                           size_t cbWrite);
+int pdmacFileEpCacheFlush(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint, PPDMASYNCCOMPLETIONTASKFILE pTask);
 
 RT_C_DECLS_END
