Index: /trunk/src/VBox/VMM/PDMAsyncCompletionFile.cpp
===================================================================
--- /trunk/src/VBox/VMM/PDMAsyncCompletionFile.cpp	(revision 23955)
+++ /trunk/src/VBox/VMM/PDMAsyncCompletionFile.cpp	(revision 23956)
@@ -25,4 +25,5 @@
 *******************************************************************************/
 #define LOG_GROUP LOG_GROUP_PDM_ASYNC_COMPLETION
+#define RT_STRICT
 #include "PDMInternal.h"
 #include <VBox/pdm.h>
@@ -381,6 +382,7 @@
  * @param   pEpClass    Pointer to the endpoint class data.
  * @param   ppAioMgr    Where to store the pointer to the new async I/O manager on success.
+ * @param   fFailsafe   Flag to force a failsafe manager even if the global flag is not set.
  */
-int pdmacFileAioMgrCreate(PPDMASYNCCOMPLETIONEPCLASSFILE pEpClass, PPPDMACEPFILEMGR ppAioMgr)
+int pdmacFileAioMgrCreate(PPDMASYNCCOMPLETIONEPCLASSFILE pEpClass, PPPDMACEPFILEMGR ppAioMgr, bool fFailsafe)
 {
     int rc = VINF_SUCCESS;
@@ -392,5 +394,5 @@
     if (RT_SUCCESS(rc))
     {
-        pAioMgrNew->fFailsafe = pEpClass->fFailsafe;
+        pAioMgrNew->fFailsafe = fFailsafe ? true : pEpClass->fFailsafe;
 
         rc = RTSemEventCreate(&pAioMgrNew->EventSem);
@@ -637,5 +639,5 @@
                 {
                     /* Safe mode. Every file has its own async I/O manager. */
-                    rc = pdmacFileAioMgrCreate(pEpClassFile, &pAioMgr);
+                    rc = pdmacFileAioMgrCreate(pEpClassFile, &pAioMgr, false);
                     AssertRC(rc);
                 }
@@ -656,5 +658,5 @@
                     if (!pEpClassFile->pAioMgrHead)
                     {
-                        rc = pdmacFileAioMgrCreate(pEpClassFile, &pAioMgr);
+                        rc = pdmacFileAioMgrCreate(pEpClassFile, &pAioMgr, false);
                         AssertRC(rc);
                     }
Index: /trunk/src/VBox/VMM/PDMAsyncCompletionFileFailsafe.cpp
===================================================================
--- /trunk/src/VBox/VMM/PDMAsyncCompletionFileFailsafe.cpp	(revision 23955)
+++ /trunk/src/VBox/VMM/PDMAsyncCompletionFileFailsafe.cpp	(revision 23956)
@@ -21,13 +21,15 @@
  */
 #define LOG_GROUP LOG_GROUP_PDM_ASYNC_COMPLETION
+#define RT_STRICT
 #include <iprt/types.h>
+#include <iprt/assert.h>
 #include <VBox/log.h>
 
 #include "PDMAsyncCompletionFileInternal.h"
 
-static int pdmacFileAioMgrFailsafeProcessEndpoint(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint)
+static int pdmacFileAioMgrFailsafeProcessEndpointTaskList(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint,
+                                                          PPDMACTASKFILE pTasks)
 {
     int rc = VINF_SUCCESS;
-    PPDMACTASKFILE pTasks = pdmacFileEpGetNewTasks(pEndpoint);
 
     while (pTasks)
@@ -83,4 +85,27 @@
 }
 
+static int pdmacFileAioMgrFailsafeProcessEndpoint(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint)
+{
+    int rc = VINF_SUCCESS;
+    PPDMACTASKFILE pTasks = pEndpoint->AioMgr.pReqsPendingHead;
+
+    pEndpoint->AioMgr.pReqsPendingHead = NULL;
+    pEndpoint->AioMgr.pReqsPendingTail = NULL;
+
+    /* Process the request pending list first in case the endpoint was migrated due to an error. */
+    if (pTasks)
+        rc = pdmacFileAioMgrFailsafeProcessEndpointTaskList(pEndpoint, pTasks);
+
+    if (RT_SUCCESS(rc))
+    {
+        pTasks = pdmacFileEpGetNewTasks(pEndpoint);
+
+        if (pTasks);
+            rc = pdmacFileAioMgrFailsafeProcessEndpointTaskList(pEndpoint, pTasks);
+    }
+
+    return rc;
+}
+
 /**
  * A fallback method in case something goes wrong with the normal
Index: /trunk/src/VBox/VMM/PDMAsyncCompletionFileInternal.h
===================================================================
--- /trunk/src/VBox/VMM/PDMAsyncCompletionFileInternal.h	(revision 23955)
+++ /trunk/src/VBox/VMM/PDMAsyncCompletionFileInternal.h	(revision 23956)
@@ -528,5 +528,5 @@
 void pdmacFileAioMgrNormalDestroy(PPDMACEPFILEMGR pAioMgr);
 
-int pdmacFileAioMgrCreate(PPDMASYNCCOMPLETIONEPCLASSFILE pEpClass, PPPDMACEPFILEMGR ppAioMgr);
+int pdmacFileAioMgrCreate(PPDMASYNCCOMPLETIONEPCLASSFILE pEpClass, PPPDMACEPFILEMGR ppAioMgr, bool fFailsafe);
 
 int pdmacFileAioMgrAddEndpoint(PPDMACEPFILEMGR pAioMgr, PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint);
Index: /trunk/src/VBox/VMM/PDMAsyncCompletionFileNormal.cpp
===================================================================
--- /trunk/src/VBox/VMM/PDMAsyncCompletionFileNormal.cpp	(revision 23955)
+++ /trunk/src/VBox/VMM/PDMAsyncCompletionFileNormal.cpp	(revision 23956)
@@ -21,4 +21,5 @@
  */
 #define LOG_GROUP LOG_GROUP_PDM_ASYNC_COMPLETION
+#define RT_STRICT
 #include <iprt/types.h>
 #include <iprt/asm.h>
@@ -26,4 +27,5 @@
 #include <iprt/mem.h>
 #include <iprt/string.h>
+#include <iprt/assert.h>
 #include <VBox/log.h>
 
@@ -206,5 +208,5 @@
     {
         rc = pdmacFileAioMgrCreate((PPDMASYNCCOMPLETIONEPCLASSFILE)pAioMgr->pEndpointsHead->Core.pEpClass,
-                                   &pAioMgrNew);
+                                   &pAioMgrNew, false);
         if (RT_SUCCESS(rc))
         {
@@ -850,78 +852,136 @@
                     pEndpoint = pTask->pEndpoint;
 
-                    AssertMsg(   RT_SUCCESS(rcReq)
-                              && (   (cbTransfered == pTask->DataSeg.cbSeg)
-                                  || (pTask->fBounceBuffer)),
-                              ("Task didn't completed successfully (rc=%Rrc) or was incomplete (cbTransfered=%u)\n", rcReq, cbTransfered));
-
-                    if (pTask->fPrefetch)
+                    /*
+                     * It is possible that the request failed on Linux with kernels < 2.6.23
+                     * if the passed buffer was allocated with remap_pfn_range or if the file
+                     * is on an NFS endpoint which does not support async and direct I/O at the same time.
+                     * The endpoint will be migrated to a failsafe manager in case a request fails.
+                     */
+                    if (RT_FAILURE(rcReq))
                     {
-                        Assert(pTask->enmTransferType == PDMACTASKFILETRANSFER_WRITE);
-                        Assert(pTask->fBounceBuffer);
-
-                        memcpy(((uint8_t *)pTask->pvBounceBuffer) + pTask->uBounceBufOffset,
-                                pTask->DataSeg.pvSeg,
-                                pTask->DataSeg.cbSeg);
-
-                        /* Write it now. */
-                        pTask->fPrefetch = false;
-                        size_t cbToTransfer = RT_ALIGN_Z(pTask->DataSeg.cbSeg, 512);
-                        RTFOFF offStart = pTask->Off & ~(RTFOFF)(512-1);
-
-                        /* Grow the file if needed. */
-                        if (RT_UNLIKELY((uint64_t)(pTask->Off + pTask->DataSeg.cbSeg) > pEndpoint->cbFile))
+                        /* Free bounce buffers and the IPRT request. */
+                        pAioMgr->pahReqsFree[pAioMgr->iFreeEntryNext] = apReqs[i];
+                        pAioMgr->iFreeEntryNext = (pAioMgr->iFreeEntryNext + 1) % pAioMgr->cReqEntries;
+
+                        pAioMgr->cRequestsActive--;
+                        pEndpoint->AioMgr.cRequestsActive--;
+                        pEndpoint->AioMgr.cReqsProcessed++;
+
+                        if (pTask->fBounceBuffer)
+                            RTMemFree(pTask->pvBounceBuffer);
+
+                        /* Queue the request on the pending list. */
+                        pTask->pNext = pEndpoint->AioMgr.pReqsPendingHead;
+                        pEndpoint->AioMgr.pReqsPendingHead = pTask;
+
+                        /* Create a new failsafe manager if neccessary. */
+                        if (!pEndpoint->AioMgr.fMoving)
                         {
-                            ASMAtomicWriteU64(&pEndpoint->cbFile, pTask->Off + pTask->DataSeg.cbSeg);
-                            RTFileSetSize(pEndpoint->File, pTask->Off + pTask->DataSeg.cbSeg);
+                            PPDMACEPFILEMGR pAioMgrFailsafe;
+
+                            pEndpoint->AioMgr.fMoving = true;
+
+                            rc = pdmacFileAioMgrCreate((PPDMASYNCCOMPLETIONEPCLASSFILE)pEndpoint->Core.pEpClass,
+                                                       &pAioMgrFailsafe, true);
+                            AssertRC(rc);
+
+                            pEndpoint->AioMgr.pAioMgrDst = pAioMgrFailsafe;
                         }
 
-                        rc = RTFileAioReqPrepareWrite(apReqs[i], pEndpoint->File,
-                                                      offStart, pTask->pvBounceBuffer, cbToTransfer, pTask);
-                        AssertRC(rc);
-                        rc = RTFileAioCtxSubmit(pAioMgr->hAioCtx, &apReqs[i], 1);
-                        AssertRC(rc);
+                        /* If this was the last request for the endpoint migrate it to the new manager. */
+                        if (!pEndpoint->AioMgr.cRequestsActive)
+                        {
+                            bool fReqsPending = pdmacFileAioMgrNormalRemoveEndpoint(pEndpoint);
+                            Assert(!fReqsPending);
+
+                            rc = pdmacFileAioMgrAddEndpoint(pEndpoint->AioMgr.pAioMgrDst, pEndpoint);
+                            AssertRC(rc);
+                        }
                     }
                     else
                     {
-                        if (pTask->fBounceBuffer)
+                        AssertMsg((   (cbTransfered == pTask->DataSeg.cbSeg)
+                                   || (pTask->fBounceBuffer && (cbTransfered >= pTask->DataSeg.cbSeg))),
+                                  ("Task didn't completed successfully (rc=%Rrc) or was incomplete (cbTransfered=%u)\n", rcReq, cbTransfered));
+
+                        if (pTask->fPrefetch)
                         {
-                            if (pTask->enmTransferType == PDMACTASKFILETRANSFER_READ)
-                                memcpy(pTask->DataSeg.pvSeg,
-                                       ((uint8_t *)pTask->pvBounceBuffer) + pTask->uBounceBufOffset,
-                                       pTask->DataSeg.cbSeg);
-
-                            RTMemPageFree(pTask->pvBounceBuffer);
+                            Assert(pTask->enmTransferType == PDMACTASKFILETRANSFER_WRITE);
+                            Assert(pTask->fBounceBuffer);
+
+                            memcpy(((uint8_t *)pTask->pvBounceBuffer) + pTask->uBounceBufOffset,
+                                    pTask->DataSeg.pvSeg,
+                                    pTask->DataSeg.cbSeg);
+
+                            /* Write it now. */
+                            pTask->fPrefetch = false;
+                            size_t cbToTransfer = RT_ALIGN_Z(pTask->DataSeg.cbSeg, 512);
+                            RTFOFF offStart = pTask->Off & ~(RTFOFF)(512-1);
+
+                            /* Grow the file if needed. */
+                            if (RT_UNLIKELY((uint64_t)(pTask->Off + pTask->DataSeg.cbSeg) > pEndpoint->cbFile))
+                            {
+                                ASMAtomicWriteU64(&pEndpoint->cbFile, pTask->Off + pTask->DataSeg.cbSeg);
+                                RTFileSetSize(pEndpoint->File, pTask->Off + pTask->DataSeg.cbSeg);
+                            }
+
+                            rc = RTFileAioReqPrepareWrite(apReqs[i], pEndpoint->File,
+                                                          offStart, pTask->pvBounceBuffer, cbToTransfer, pTask);
+                            AssertRC(rc);
+                            rc = RTFileAioCtxSubmit(pAioMgr->hAioCtx, &apReqs[i], 1);
+                            AssertRC(rc);
                         }
-
-                        /* Put the entry on the free array */
-                        pAioMgr->pahReqsFree[pAioMgr->iFreeEntryNext] = apReqs[i];
-                        pAioMgr->iFreeEntryNext = (pAioMgr->iFreeEntryNext + 1) % pAioMgr->cReqEntries;
-
-                        pAioMgr->cRequestsActive--;
-                        pEndpoint->AioMgr.cRequestsActive--;
-                        pEndpoint->AioMgr.cReqsProcessed++;
-
-                        /* Call completion callback */
-                        pTask->pfnCompleted(pTask, pTask->pvUser);
-                        pdmacFileTaskFree(pEndpoint, pTask);
-
-                        /*
-                         * If there is no request left on the endpoint but a flush request is set
-                         * it completed now and we notify the owner.
-                         * Furthermore we look for new requests and continue.
-                         */
-                        if (!pEndpoint->AioMgr.cRequestsActive && pEndpoint->pFlushReq)
+                        else
                         {
+                            if (pTask->fBounceBuffer)
+                            {
+                                if (pTask->enmTransferType == PDMACTASKFILETRANSFER_READ)
+                                    memcpy(pTask->DataSeg.pvSeg,
+                                           ((uint8_t *)pTask->pvBounceBuffer) + pTask->uBounceBufOffset,
+                                           pTask->DataSeg.cbSeg);
+
+                                RTMemPageFree(pTask->pvBounceBuffer);
+                            }
+
+                            /* Put the entry on the free array */
+                            pAioMgr->pahReqsFree[pAioMgr->iFreeEntryNext] = apReqs[i];
+                            pAioMgr->iFreeEntryNext = (pAioMgr->iFreeEntryNext + 1) % pAioMgr->cReqEntries;
+
+                            pAioMgr->cRequestsActive--;
+                            pEndpoint->AioMgr.cRequestsActive--;
+                            pEndpoint->AioMgr.cReqsProcessed++;
+
                             /* Call completion callback */
-                            pTask = pEndpoint->pFlushReq;
-                            pEndpoint->pFlushReq = NULL;
-
-                            AssertMsg(pTask->pEndpoint == pEndpoint, ("Endpoint of the flush request does not match assigned one\n"));
-
                             pTask->pfnCompleted(pTask, pTask->pvUser);
                             pdmacFileTaskFree(pEndpoint, pTask);
+
+                            /*
+                             * If there is no request left on the endpoint but a flush request is set
+                             * it completed now and we notify the owner.
+                             * Furthermore we look for new requests and continue.
+                             */
+                            if (!pEndpoint->AioMgr.cRequestsActive && pEndpoint->pFlushReq)
+                            {
+                                /* Call completion callback */
+                                pTask = pEndpoint->pFlushReq;
+                                pEndpoint->pFlushReq = NULL;
+
+                                AssertMsg(pTask->pEndpoint == pEndpoint, ("Endpoint of the flush request does not match assigned one\n"));
+
+                                pTask->pfnCompleted(pTask, pTask->pvUser);
+                                pdmacFileTaskFree(pEndpoint, pTask);
+                            }
+                            else if (RT_UNLIKELY(!pEndpoint->AioMgr.cRequestsActive && pEndpoint->AioMgr.fMoving))
+                            {
+                                /* If we the endpoint is about to be migrated do it now. */
+                                bool fReqsPending = pdmacFileAioMgrNormalRemoveEndpoint(pEndpoint);
+                                Assert(!fReqsPending);
+
+                                rc = pdmacFileAioMgrAddEndpoint(pEndpoint->AioMgr.pAioMgrDst, pEndpoint);
+                                AssertRC(rc);
+                            }
                         }
-                    }
-                }
+                    } /* request completed successfully */
+                } /* for every completed request */
 
                 /* Check for an external blocking event before we go to sleep again. */
