VirtualBox

Changeset 23956 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
Oct 21, 2009 10:18:40 PM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
53775
Message:

PDMAsyncCompletion: Migrate endpoints to a failsafe manager if a request fails

Location:
trunk/src/VBox/VMM
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/PDMAsyncCompletionFile.cpp

    r23952 r23956  
    2525*******************************************************************************/
    2626#define LOG_GROUP LOG_GROUP_PDM_ASYNC_COMPLETION
     27#define RT_STRICT
    2728#include "PDMInternal.h"
    2829#include <VBox/pdm.h>
     
    381382 * @param   pEpClass    Pointer to the endpoint class data.
    382383 * @param   ppAioMgr    Where to store the pointer to the new async I/O manager on success.
     384 * @param   fFailsafe   Flag to force a failsafe manager even if the global flag is not set.
    383385 */
    384 int pdmacFileAioMgrCreate(PPDMASYNCCOMPLETIONEPCLASSFILE pEpClass, PPPDMACEPFILEMGR ppAioMgr)
     386int pdmacFileAioMgrCreate(PPDMASYNCCOMPLETIONEPCLASSFILE pEpClass, PPPDMACEPFILEMGR ppAioMgr, bool fFailsafe)
    385387{
    386388    int rc = VINF_SUCCESS;
     
    392394    if (RT_SUCCESS(rc))
    393395    {
    394         pAioMgrNew->fFailsafe = pEpClass->fFailsafe;
     396        pAioMgrNew->fFailsafe = fFailsafe ? true : pEpClass->fFailsafe;
    395397
    396398        rc = RTSemEventCreate(&pAioMgrNew->EventSem);
     
    637639                {
    638640                    /* Safe mode. Every file has its own async I/O manager. */
    639                     rc = pdmacFileAioMgrCreate(pEpClassFile, &pAioMgr);
     641                    rc = pdmacFileAioMgrCreate(pEpClassFile, &pAioMgr, false);
    640642                    AssertRC(rc);
    641643                }
     
    656658                    if (!pEpClassFile->pAioMgrHead)
    657659                    {
    658                         rc = pdmacFileAioMgrCreate(pEpClassFile, &pAioMgr);
     660                        rc = pdmacFileAioMgrCreate(pEpClassFile, &pAioMgr, false);
    659661                        AssertRC(rc);
    660662                    }
  • trunk/src/VBox/VMM/PDMAsyncCompletionFileFailsafe.cpp

    r22979 r23956  
    2121 */
    2222#define LOG_GROUP LOG_GROUP_PDM_ASYNC_COMPLETION
     23#define RT_STRICT
    2324#include <iprt/types.h>
     25#include <iprt/assert.h>
    2426#include <VBox/log.h>
    2527
    2628#include "PDMAsyncCompletionFileInternal.h"
    2729
    28 static int pdmacFileAioMgrFailsafeProcessEndpoint(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint)
     30static int pdmacFileAioMgrFailsafeProcessEndpointTaskList(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint,
     31                                                          PPDMACTASKFILE pTasks)
    2932{
    3033    int rc = VINF_SUCCESS;
    31     PPDMACTASKFILE pTasks = pdmacFileEpGetNewTasks(pEndpoint);
    3234
    3335    while (pTasks)
     
    8385}
    8486
     87static int pdmacFileAioMgrFailsafeProcessEndpoint(PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint)
     88{
     89    int rc = VINF_SUCCESS;
     90    PPDMACTASKFILE pTasks = pEndpoint->AioMgr.pReqsPendingHead;
     91
     92    pEndpoint->AioMgr.pReqsPendingHead = NULL;
     93    pEndpoint->AioMgr.pReqsPendingTail = NULL;
     94
     95    /* Process the request pending list first in case the endpoint was migrated due to an error. */
     96    if (pTasks)
     97        rc = pdmacFileAioMgrFailsafeProcessEndpointTaskList(pEndpoint, pTasks);
     98
     99    if (RT_SUCCESS(rc))
     100    {
     101        pTasks = pdmacFileEpGetNewTasks(pEndpoint);
     102
     103        if (pTasks);
     104            rc = pdmacFileAioMgrFailsafeProcessEndpointTaskList(pEndpoint, pTasks);
     105    }
     106
     107    return rc;
     108}
     109
    85110/**
    86111 * A fallback method in case something goes wrong with the normal
  • trunk/src/VBox/VMM/PDMAsyncCompletionFileInternal.h

    r23404 r23956  
    528528void pdmacFileAioMgrNormalDestroy(PPDMACEPFILEMGR pAioMgr);
    529529
    530 int pdmacFileAioMgrCreate(PPDMASYNCCOMPLETIONEPCLASSFILE pEpClass, PPPDMACEPFILEMGR ppAioMgr);
     530int pdmacFileAioMgrCreate(PPDMASYNCCOMPLETIONEPCLASSFILE pEpClass, PPPDMACEPFILEMGR ppAioMgr, bool fFailsafe);
    531531
    532532int pdmacFileAioMgrAddEndpoint(PPDMACEPFILEMGR pAioMgr, PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint);
  • trunk/src/VBox/VMM/PDMAsyncCompletionFileNormal.cpp

    r23812 r23956  
    2121 */
    2222#define LOG_GROUP LOG_GROUP_PDM_ASYNC_COMPLETION
     23#define RT_STRICT
    2324#include <iprt/types.h>
    2425#include <iprt/asm.h>
     
    2627#include <iprt/mem.h>
    2728#include <iprt/string.h>
     29#include <iprt/assert.h>
    2830#include <VBox/log.h>
    2931
     
    206208    {
    207209        rc = pdmacFileAioMgrCreate((PPDMASYNCCOMPLETIONEPCLASSFILE)pAioMgr->pEndpointsHead->Core.pEpClass,
    208                                    &pAioMgrNew);
     210                                   &pAioMgrNew, false);
    209211        if (RT_SUCCESS(rc))
    210212        {
     
    850852                    pEndpoint = pTask->pEndpoint;
    851853
    852                     AssertMsg(   RT_SUCCESS(rcReq)
    853                               && (   (cbTransfered == pTask->DataSeg.cbSeg)
    854                                   || (pTask->fBounceBuffer)),
    855                               ("Task didn't completed successfully (rc=%Rrc) or was incomplete (cbTransfered=%u)\n", rcReq, cbTransfered));
    856 
    857                     if (pTask->fPrefetch)
     854                    /*
     855                     * It is possible that the request failed on Linux with kernels < 2.6.23
     856                     * if the passed buffer was allocated with remap_pfn_range or if the file
     857                     * is on an NFS endpoint which does not support async and direct I/O at the same time.
     858                     * The endpoint will be migrated to a failsafe manager in case a request fails.
     859                     */
     860                    if (RT_FAILURE(rcReq))
    858861                    {
    859                         Assert(pTask->enmTransferType == PDMACTASKFILETRANSFER_WRITE);
    860                         Assert(pTask->fBounceBuffer);
    861 
    862                         memcpy(((uint8_t *)pTask->pvBounceBuffer) + pTask->uBounceBufOffset,
    863                                 pTask->DataSeg.pvSeg,
    864                                 pTask->DataSeg.cbSeg);
    865 
    866                         /* Write it now. */
    867                         pTask->fPrefetch = false;
    868                         size_t cbToTransfer = RT_ALIGN_Z(pTask->DataSeg.cbSeg, 512);
    869                         RTFOFF offStart = pTask->Off & ~(RTFOFF)(512-1);
    870 
    871                         /* Grow the file if needed. */
    872                         if (RT_UNLIKELY((uint64_t)(pTask->Off + pTask->DataSeg.cbSeg) > pEndpoint->cbFile))
     862                        /* Free bounce buffers and the IPRT request. */
     863                        pAioMgr->pahReqsFree[pAioMgr->iFreeEntryNext] = apReqs[i];
     864                        pAioMgr->iFreeEntryNext = (pAioMgr->iFreeEntryNext + 1) % pAioMgr->cReqEntries;
     865
     866                        pAioMgr->cRequestsActive--;
     867                        pEndpoint->AioMgr.cRequestsActive--;
     868                        pEndpoint->AioMgr.cReqsProcessed++;
     869
     870                        if (pTask->fBounceBuffer)
     871                            RTMemFree(pTask->pvBounceBuffer);
     872
     873                        /* Queue the request on the pending list. */
     874                        pTask->pNext = pEndpoint->AioMgr.pReqsPendingHead;
     875                        pEndpoint->AioMgr.pReqsPendingHead = pTask;
     876
     877                        /* Create a new failsafe manager if neccessary. */
     878                        if (!pEndpoint->AioMgr.fMoving)
    873879                        {
    874                             ASMAtomicWriteU64(&pEndpoint->cbFile, pTask->Off + pTask->DataSeg.cbSeg);
    875                             RTFileSetSize(pEndpoint->File, pTask->Off + pTask->DataSeg.cbSeg);
     880                            PPDMACEPFILEMGR pAioMgrFailsafe;
     881
     882                            pEndpoint->AioMgr.fMoving = true;
     883
     884                            rc = pdmacFileAioMgrCreate((PPDMASYNCCOMPLETIONEPCLASSFILE)pEndpoint->Core.pEpClass,
     885                                                       &pAioMgrFailsafe, true);
     886                            AssertRC(rc);
     887
     888                            pEndpoint->AioMgr.pAioMgrDst = pAioMgrFailsafe;
    876889                        }
    877890
    878                         rc = RTFileAioReqPrepareWrite(apReqs[i], pEndpoint->File,
    879                                                       offStart, pTask->pvBounceBuffer, cbToTransfer, pTask);
    880                         AssertRC(rc);
    881                         rc = RTFileAioCtxSubmit(pAioMgr->hAioCtx, &apReqs[i], 1);
    882                         AssertRC(rc);
     891                        /* If this was the last request for the endpoint migrate it to the new manager. */
     892                        if (!pEndpoint->AioMgr.cRequestsActive)
     893                        {
     894                            bool fReqsPending = pdmacFileAioMgrNormalRemoveEndpoint(pEndpoint);
     895                            Assert(!fReqsPending);
     896
     897                            rc = pdmacFileAioMgrAddEndpoint(pEndpoint->AioMgr.pAioMgrDst, pEndpoint);
     898                            AssertRC(rc);
     899                        }
    883900                    }
    884901                    else
    885902                    {
    886                         if (pTask->fBounceBuffer)
     903                        AssertMsg((   (cbTransfered == pTask->DataSeg.cbSeg)
     904                                   || (pTask->fBounceBuffer && (cbTransfered >= pTask->DataSeg.cbSeg))),
     905                                  ("Task didn't completed successfully (rc=%Rrc) or was incomplete (cbTransfered=%u)\n", rcReq, cbTransfered));
     906
     907                        if (pTask->fPrefetch)
    887908                        {
    888                             if (pTask->enmTransferType == PDMACTASKFILETRANSFER_READ)
    889                                 memcpy(pTask->DataSeg.pvSeg,
    890                                        ((uint8_t *)pTask->pvBounceBuffer) + pTask->uBounceBufOffset,
    891                                        pTask->DataSeg.cbSeg);
    892 
    893                             RTMemPageFree(pTask->pvBounceBuffer);
     909                            Assert(pTask->enmTransferType == PDMACTASKFILETRANSFER_WRITE);
     910                            Assert(pTask->fBounceBuffer);
     911
     912                            memcpy(((uint8_t *)pTask->pvBounceBuffer) + pTask->uBounceBufOffset,
     913                                    pTask->DataSeg.pvSeg,
     914                                    pTask->DataSeg.cbSeg);
     915
     916                            /* Write it now. */
     917                            pTask->fPrefetch = false;
     918                            size_t cbToTransfer = RT_ALIGN_Z(pTask->DataSeg.cbSeg, 512);
     919                            RTFOFF offStart = pTask->Off & ~(RTFOFF)(512-1);
     920
     921                            /* Grow the file if needed. */
     922                            if (RT_UNLIKELY((uint64_t)(pTask->Off + pTask->DataSeg.cbSeg) > pEndpoint->cbFile))
     923                            {
     924                                ASMAtomicWriteU64(&pEndpoint->cbFile, pTask->Off + pTask->DataSeg.cbSeg);
     925                                RTFileSetSize(pEndpoint->File, pTask->Off + pTask->DataSeg.cbSeg);
     926                            }
     927
     928                            rc = RTFileAioReqPrepareWrite(apReqs[i], pEndpoint->File,
     929                                                          offStart, pTask->pvBounceBuffer, cbToTransfer, pTask);
     930                            AssertRC(rc);
     931                            rc = RTFileAioCtxSubmit(pAioMgr->hAioCtx, &apReqs[i], 1);
     932                            AssertRC(rc);
    894933                        }
    895 
    896                         /* Put the entry on the free array */
    897                         pAioMgr->pahReqsFree[pAioMgr->iFreeEntryNext] = apReqs[i];
    898                         pAioMgr->iFreeEntryNext = (pAioMgr->iFreeEntryNext + 1) % pAioMgr->cReqEntries;
    899 
    900                         pAioMgr->cRequestsActive--;
    901                         pEndpoint->AioMgr.cRequestsActive--;
    902                         pEndpoint->AioMgr.cReqsProcessed++;
    903 
    904                         /* Call completion callback */
    905                         pTask->pfnCompleted(pTask, pTask->pvUser);
    906                         pdmacFileTaskFree(pEndpoint, pTask);
    907 
    908                         /*
    909                          * If there is no request left on the endpoint but a flush request is set
    910                          * it completed now and we notify the owner.
    911                          * Furthermore we look for new requests and continue.
    912                          */
    913                         if (!pEndpoint->AioMgr.cRequestsActive && pEndpoint->pFlushReq)
     934                        else
    914935                        {
     936                            if (pTask->fBounceBuffer)
     937                            {
     938                                if (pTask->enmTransferType == PDMACTASKFILETRANSFER_READ)
     939                                    memcpy(pTask->DataSeg.pvSeg,
     940                                           ((uint8_t *)pTask->pvBounceBuffer) + pTask->uBounceBufOffset,
     941                                           pTask->DataSeg.cbSeg);
     942
     943                                RTMemPageFree(pTask->pvBounceBuffer);
     944                            }
     945
     946                            /* Put the entry on the free array */
     947                            pAioMgr->pahReqsFree[pAioMgr->iFreeEntryNext] = apReqs[i];
     948                            pAioMgr->iFreeEntryNext = (pAioMgr->iFreeEntryNext + 1) % pAioMgr->cReqEntries;
     949
     950                            pAioMgr->cRequestsActive--;
     951                            pEndpoint->AioMgr.cRequestsActive--;
     952                            pEndpoint->AioMgr.cReqsProcessed++;
     953
    915954                            /* Call completion callback */
    916                             pTask = pEndpoint->pFlushReq;
    917                             pEndpoint->pFlushReq = NULL;
    918 
    919                             AssertMsg(pTask->pEndpoint == pEndpoint, ("Endpoint of the flush request does not match assigned one\n"));
    920 
    921955                            pTask->pfnCompleted(pTask, pTask->pvUser);
    922956                            pdmacFileTaskFree(pEndpoint, pTask);
     957
     958                            /*
     959                             * If there is no request left on the endpoint but a flush request is set
     960                             * it completed now and we notify the owner.
     961                             * Furthermore we look for new requests and continue.
     962                             */
     963                            if (!pEndpoint->AioMgr.cRequestsActive && pEndpoint->pFlushReq)
     964                            {
     965                                /* Call completion callback */
     966                                pTask = pEndpoint->pFlushReq;
     967                                pEndpoint->pFlushReq = NULL;
     968
     969                                AssertMsg(pTask->pEndpoint == pEndpoint, ("Endpoint of the flush request does not match assigned one\n"));
     970
     971                                pTask->pfnCompleted(pTask, pTask->pvUser);
     972                                pdmacFileTaskFree(pEndpoint, pTask);
     973                            }
     974                            else if (RT_UNLIKELY(!pEndpoint->AioMgr.cRequestsActive && pEndpoint->AioMgr.fMoving))
     975                            {
     976                                /* If we the endpoint is about to be migrated do it now. */
     977                                bool fReqsPending = pdmacFileAioMgrNormalRemoveEndpoint(pEndpoint);
     978                                Assert(!fReqsPending);
     979
     980                                rc = pdmacFileAioMgrAddEndpoint(pEndpoint->AioMgr.pAioMgrDst, pEndpoint);
     981                                AssertRC(rc);
     982                            }
    923983                        }
    924                     }
    925                 }
     984                    } /* request completed successfully */
     985                } /* for every completed request */
    926986
    927987                /* Check for an external blocking event before we go to sleep again. */
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette