Index: /trunk/src/VBox/Devices/Storage/DevAHCI.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/DevAHCI.cpp	(revision 56657)
+++ /trunk/src/VBox/Devices/Storage/DevAHCI.cpp	(revision 56658)
@@ -5716,28 +5716,31 @@
     for (unsigned i = 0; i < RT_ELEMENTS(pAhciPort->aActiveTasks); i++)
     {
-        PAHCIREQ pAhciReq = (PAHCIREQ)ASMAtomicXchgPtr((void * volatile *)&pAhciPort->aActiveTasks[i], NULL);
-
-        if (   VALID_PTR(pAhciReq)
-            && pAhciReq != pAhciReqExcept)
-        {
-            bool fXchg = ASMAtomicCmpXchgU32((volatile uint32_t *)&pAhciReq->enmTxState, AHCITXSTATE_CANCELED, AHCITXSTATE_ACTIVE);
-            if (fXchg)
+        PAHCIREQ pAhciReq = ASMAtomicReadPtrT(&pAhciPort->aActiveTasks[i], PAHCIREQ);
+        if (pAhciReq != pAhciReqExcept)
+        {
+            pAhciReq = (PAHCIREQ)ASMAtomicXchgPtr((void * volatile *)&pAhciPort->aActiveTasks[i], NULL);
+
+            if (VALID_PTR(pAhciReq))
             {
-                /* Task is active and was canceled. */
-                AssertReleaseMsg(ASMAtomicReadU32(&pAhciPort->cTasksActive) > 0,
-                                 ("Task was canceled but none is active\n"));
-                ASMAtomicDecU32(&pAhciPort->cTasksActive);
-
-                /*
-                 * Clear the pointer in the cached array. The controller will allocate a
-                 * a new task structure for this tag.
-                 */
-                ASMAtomicWriteNullPtr(&pAhciPort->aActiveTasks[i]);
-                LogRel(("AHCI#%uP%u: Cancelled task %u\n", pAhciPort->CTX_SUFF(pDevIns)->iInstance,
-                        pAhciPort->iLUN, pAhciReq->uTag));
+                bool fXchg = ASMAtomicCmpXchgU32((volatile uint32_t *)&pAhciReq->enmTxState, AHCITXSTATE_CANCELED, AHCITXSTATE_ACTIVE);
+                if (fXchg)
+                {
+                    /* Task is active and was canceled. */
+                    AssertReleaseMsg(ASMAtomicReadU32(&pAhciPort->cTasksActive) > 0,
+                                     ("Task was canceled but none is active\n"));
+                    ASMAtomicDecU32(&pAhciPort->cTasksActive);
+
+                    /*
+                     * Clear the pointer in the cached array. The controller will allocate a
+                     * a new task structure for this tag.
+                     */
+                    ASMAtomicWriteNullPtr(&pAhciPort->aActiveTasks[i]);
+                    LogRel(("AHCI#%uP%u: Cancelled task %u\n", pAhciPort->CTX_SUFF(pDevIns)->iInstance,
+                            pAhciPort->iLUN, pAhciReq->uTag));
+                }
+                else
+                    AssertMsg(pAhciReq->enmTxState == AHCITXSTATE_FREE,
+                              ("Invalid task state, must be free!\n"));
             }
-            else
-                AssertMsg(pAhciReq->enmTxState == AHCITXSTATE_FREE,
-                          ("Invalid task state, must be free!\n"));
         }
     }
@@ -5960,5 +5963,8 @@
     pAhciReq = RTListGetFirst(pAhciPort->pListReqsFree, AHCIREQ, NodeList);
     if (pAhciReq)
+    {
+        AssertMsg(pAhciReq->enmTxState == AHCITXSTATE_FREE, ("Should be free!\n"));
         RTListNodeRemove(&pAhciReq->NodeList);
+    }
     RTCritSectLeave(&pAhciPort->CritSectReqsFree);
 
@@ -5978,4 +5984,5 @@
 static void ahciR3ReqFree(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
 {
+    AssertMsg(pAhciReq->enmTxState != AHCITXSTATE_FREE, ("Double free!\n"));
     pAhciReq->enmTxState = AHCITXSTATE_FREE;
 
@@ -6017,4 +6024,5 @@
     bool fPortReset = ASMAtomicReadBool(&pAhciPort->fPortReset);
     bool fXchg = ASMAtomicCmpXchgPtr(&pAhciPort->aActiveTasks[pAhciReq->uTag], NULL, pAhciReq);
+    bool fReqErrSaved = false;
 
     /*
@@ -6095,5 +6103,5 @@
                 pAhciReq->uATARegError    = ID_ERR;
                 pAhciReq->uATARegStatus   = ATA_STAT_READY | ATA_STAT_ERR;
-                ASMAtomicCmpXchgPtr(&pAhciPort->pTaskErr, pAhciReq, NULL);
+                fReqErrSaved = ASMAtomicCmpXchgPtr(&pAhciPort->pTaskErr, pAhciReq, NULL);
             }
             else
@@ -6207,5 +6215,8 @@
         PDMDevHlpAsyncNotificationCompleted(pAhciPort->pDevInsR3);
 
-    if (pAhciReq && !(pAhciReq->fFlags & AHCI_REQ_IS_ON_STACK))
+    /* Don't free the request yet when it is saved for the error log page. */
+    if (   pAhciReq
+        && !(pAhciReq->fFlags & AHCI_REQ_IS_ON_STACK)
+        && !fReqErrSaved)
         ahciR3ReqFree(pAhciPort, pAhciReq);
     return fCanceled;
@@ -6471,5 +6482,5 @@
                                 ahciTrimRangesDestroy(pTaskErr);
                             else if (pTaskErr->enmTxDir != AHCITXDIR_FLUSH)
-                                ahciIoBufFree(pAhciPort, pTaskErr, false /* fCopyToGuest */);
+                                ahciReqMemFree(pAhciPort, pTaskErr, true /* fForceFree */);
 
                             /* Finally free the error task state structure because it is completely unused now. */
