VirtualBox

Changeset 27299 in vbox


Ignore:
Timestamp:
Mar 11, 2010 7:19:59 PM (15 years ago)
Author:
vboxsync
Message:

AsyncCompletion: More configuration options

  • There are two manager types which can be selected with CFGM with the "IoMgr" key:

-- Async - I/O is done asynchronously using the capabilities on the host (Default)
-- Simple - Used as a fallback if "Async" doesn't work. Normally selected automatically

if the async type encounters an error

  • Two types for a file backend selected by the "FileBackend" CFGM key. (The I/O cache of VirtualBox is unaffected by this setting):

-- Buffered - The I/O goes through the host cache (Default on all hosts except Linux)
-- NonBuffered - The host cache is disabled

  • The following combinations of the two options are supported:

-- Async/NonBuffered
-- Simple/Buffered
-- Async/Buffered (not supported on Linux because of kernel limitations)

  • The Async/Buffered combination is optimized now (no need to align the transfer to sector boundaries)
Location:
trunk/src/VBox/VMM
Files:
4 edited

Legend:

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

    r26812 r27299  
    387387 * @param   pEpClass    Pointer to the endpoint class data.
    388388 * @param   ppAioMgr    Where to store the pointer to the new async I/O manager on success.
    389  * @param   fFailsafe   Flag to force a failsafe manager even if the global flag is not set.
     389 * @param   enmMgrType  Wanted manager type - can be overwritten by the global override.
    390390 */
    391 int pdmacFileAioMgrCreate(PPDMASYNCCOMPLETIONEPCLASSFILE pEpClass, PPPDMACEPFILEMGR ppAioMgr, bool fFailsafe)
     391int pdmacFileAioMgrCreate(PPDMASYNCCOMPLETIONEPCLASSFILE pEpClass, PPPDMACEPFILEMGR ppAioMgr,
     392                          PDMACEPFILEMGRTYPE enmMgrType)
    392393{
    393394    int rc = VINF_SUCCESS;
     
    399400    if (RT_SUCCESS(rc))
    400401    {
    401         pAioMgrNew->fFailsafe = fFailsafe || pEpClass->fFailsafe;
     402        if (enmMgrType < pEpClass->enmMgrTypeOverride)
     403            pAioMgrNew->enmMgrType = enmMgrType;
     404        else
     405            pAioMgrNew->enmMgrType = pEpClass->enmMgrTypeOverride;
    402406
    403407        rc = RTSemEventCreate(&pAioMgrNew->EventSem);
     
    411415                {
    412416                    /* Init the rest of the manager. */
    413                     if (!pAioMgrNew->fFailsafe)
     417                    if (pAioMgrNew->enmMgrType != PDMACEPFILEMGRTYPE_SIMPLE)
    414418                        rc = pdmacFileAioMgrNormalInit(pAioMgrNew);
    415419
     
    419423
    420424                        rc = RTThreadCreateF(&pAioMgrNew->Thread,
    421                                              pAioMgrNew->fFailsafe
     425                                             pAioMgrNew->enmMgrType == PDMACEPFILEMGRTYPE_SIMPLE
    422426                                             ? pdmacFileAioMgrFailsafe
    423427                                             : pdmacFileAioMgrNormal,
     
    427431                                             0,
    428432                                             "AioMgr%d-%s", pEpClass->cAioMgrs,
    429                                              pAioMgrNew->fFailsafe
     433                                             pAioMgrNew->enmMgrType == PDMACEPFILEMGRTYPE_SIMPLE
    430434                                             ? "F"
    431435                                             : "N");
     
    495499    RTCritSectDelete(&pAioMgr->CritSectBlockingEvent);
    496500    RTSemEventDestroy(pAioMgr->EventSem);
    497     if (!pAioMgr->fFailsafe)
     501    if (pAioMgr->enmMgrType != PDMACEPFILEMGRTYPE_SIMPLE)
    498502        pdmacFileAioMgrNormalDestroy(pAioMgr);
    499503
     
    515519        rc = CFGMR3QueryU32Def(pCfgNode, "VMTransferPerSecMax", &pBwMgr->cbVMTransferPerSecMax, UINT32_MAX);
    516520        AssertLogRelRCReturn(rc, rc);
    517         rc = CFGMR3QueryU32Def(pCfgNode, "VMTransferPerSecStart", &pBwMgr->cbVMTransferPerSecStart, _1M);
     521        rc = CFGMR3QueryU32Def(pCfgNode, "VMTransferPerSecStart", &pBwMgr->cbVMTransferPerSecStart, 5 * _1M);
    518522        AssertLogRelRCReturn(rc, rc);
    519523        rc = CFGMR3QueryU32Def(pCfgNode, "VMTransferPerSecStep", &pBwMgr->cbVMTransferPerSecStep, _1M);
     
    585589}
    586590
     591static int pdmacFileMgrTypeFromName(const char *pszVal, PPDMACEPFILEMGRTYPE penmMgrType)
     592{
     593    int rc = VINF_SUCCESS;
     594
     595    if (!RTStrCmp(pszVal, "Simple"))
     596        *penmMgrType = PDMACEPFILEMGRTYPE_SIMPLE;
     597    else if (!RTStrCmp(pszVal, "Async"))
     598        *penmMgrType = PDMACEPFILEMGRTYPE_ASYNC;
     599    else
     600        rc = VERR_CFGM_CONFIG_UNKNOWN_VALUE;
     601
     602    return rc;
     603}
     604
     605static const char *pdmacFileMgrTypeToName(PDMACEPFILEMGRTYPE enmMgrType)
     606{
     607    if (enmMgrType == PDMACEPFILEMGRTYPE_SIMPLE)
     608        return "Simple";
     609    if (enmMgrType == PDMACEPFILEMGRTYPE_ASYNC)
     610        return "Async";
     611
     612    return NULL;
     613}
     614
     615static int pdmacFileBackendTypeFromName(const char *pszVal, PPDMACFILEEPBACKEND penmBackendType)
     616{
     617    int rc = VINF_SUCCESS;
     618
     619    if (!RTStrCmp(pszVal, "Buffered"))
     620        *penmBackendType = PDMACFILEEPBACKEND_BUFFERED;
     621    else if (!RTStrCmp(pszVal, "NonBuffered"))
     622        *penmBackendType = PDMACFILEEPBACKEND_NON_BUFFERED;
     623    else
     624        rc = VERR_CFGM_CONFIG_UNKNOWN_VALUE;
     625
     626    return rc;
     627}
     628
     629static const char *pdmacFileBackendTypeToName(PDMACFILEEPBACKEND enmBackendType)
     630{
     631    if (enmBackendType == PDMACFILEEPBACKEND_BUFFERED)
     632        return "Buffered";
     633    if (enmBackendType == PDMACFILEEPBACKEND_NON_BUFFERED)
     634        return "NonBuffered";
     635
     636    return NULL;
     637}
     638
    587639static int pdmacFileInitialize(PPDMASYNCCOMPLETIONEPCLASS pClassGlobals, PCFGMNODE pCfgNode)
    588640{
     
    599651    if (RT_FAILURE(rc))
    600652    {
    601         LogRel(("AIO: Async I/O manager not supported (rc=%Rrc). Falling back to failsafe manager\n",
     653        LogRel(("AIO: Async I/O manager not supported (rc=%Rrc). Falling back to simple manager\n",
    602654                rc));
    603         pEpClassFile->fFailsafe = true;
     655        pEpClassFile->enmMgrTypeOverride = PDMACEPFILEMGRTYPE_SIMPLE;
     656        pEpClassFile->enmEpBackendDefault = PDMACFILEEPBACKEND_BUFFERED;
    604657    }
    605658    else
     
    608661        pEpClassFile->cReqsOutstandingMax = AioLimits.cReqsOutstandingMax;
    609662
    610         /* The user can force the failsafe manager. */
    611         rc = CFGMR3QueryBoolDef(pCfgNode, "UseFailsafeIo", &pEpClassFile->fFailsafe, false);
    612         AssertLogRelRCReturn(rc, rc);
    613 
    614         if (pEpClassFile->fFailsafe)
    615             LogRel(("AIOMgr: Failsafe I/O was requested by user\n"));
     663        if (pCfgNode)
     664        {
     665            /* Query the default manager type */
     666            char *pszVal = NULL;
     667            rc = CFGMR3QueryStringAllocDef(pCfgNode, "IoMgr", &pszVal, "Async");
     668            AssertLogRelRCReturn(rc, rc);
     669
     670            rc = pdmacFileMgrTypeFromName(pszVal, &pEpClassFile->enmMgrTypeOverride);
     671            MMR3HeapFree(pszVal);
     672            if (RT_FAILURE(rc))
     673                return rc;
     674
     675            LogRel(("AIOMgr: Default manager type is \"%s\"\n", pdmacFileMgrTypeToName(pEpClassFile->enmMgrTypeOverride)));
     676
     677            /* Query default backend type */
     678#ifndef RT_OS_LINUX
     679            rc = CFGMR3QueryStringAllocDef(pCfgNode, "FileBackend", &pszVal, "Buffered");
     680#else /* Linux can't use buffered with async */
     681            rc = CFGMR3QueryStringAllocDef(pCfgNode, "FileBackend", &pszVal, "NonBuffered");
     682#endif
     683            AssertLogRelRCReturn(rc, rc);
     684
     685            rc = pdmacFileBackendTypeFromName(pszVal, &pEpClassFile->enmEpBackendDefault);
     686            MMR3HeapFree(pszVal);
     687            if (RT_FAILURE(rc))
     688                return rc;
     689
     690            LogRel(("AIOMgr: Default file backend is \"%s\"\n", pdmacFileBackendTypeToName(pEpClassFile->enmEpBackendDefault)));
     691
     692#ifdef RT_OS_LINUX
     693            if (   pEpClassFile->enmMgrTypeOverride == PDMACEPFILEMGRTYPE_ASYNC
     694                && pEpClassFile->enmEpBackendDefault == PDMACFILEEPBACKEND_BUFFERED)
     695            {
     696                LogRel(("AIOMgr: Linux does not support buffered async I/O, changing to non buffered\n"));
     697                pEpClassFile->enmEpBackendDefault = PDMACFILEEPBACKEND_NON_BUFFERED;
     698            }
     699#endif
     700        }
     701        else
     702        {
     703            /* No configuration supplied, set defaults */
     704            pEpClassFile->enmMgrTypeOverride = PDMACEPFILEMGRTYPE_ASYNC;
     705#ifdef RT_OS_LINUX
     706            pEpClassFile->enmEpBackendDefault = PDMACFILEEPBACKEND_NON_BUFFERED;
     707#else
     708            pEpClassFile->enmEpBackendDefault = PDMACFILEEPBACKEND_BUFFERED;
     709#endif
     710        }
    616711    }
    617712
     
    620715    if (RT_SUCCESS(rc))
    621716    {
    622         /* Check if the host cache should be used too. */
    623 #ifndef RT_OS_LINUX
    624         rc = CFGMR3QueryBoolDef(pCfgNode, "HostCacheEnabled", &pEpClassFile->fHostCacheEnabled, false);
    625         AssertLogRelRCReturn(rc, rc);
    626 #else
    627         /*
    628          * Host cache + async I/O is not supported on Linux. Check if the user enabled the cache,
    629          * leave a warning and disable it always.
    630          */
    631         bool fDummy;
    632         rc = CFGMR3QueryBool(pCfgNode, "HostCacheEnabled", &fDummy);
    633         if (RT_SUCCESS(rc))
    634             LogRel(("AIOMgr: The host cache is not supported with async I/O on Linux\n"));
    635 
    636         pEpClassFile->fHostCacheEnabled = false;
    637 #endif
    638 
    639717        /* Check if the cache was disabled by the user. */
    640718        rc = CFGMR3QueryBoolDef(pCfgNode, "CacheEnabled", &pEpClassFile->fCacheEnabled, true);
     
    687765    PPDMASYNCCOMPLETIONENDPOINTFILE pEpFile = (PPDMASYNCCOMPLETIONENDPOINTFILE)pEndpoint;
    688766    PPDMASYNCCOMPLETIONEPCLASSFILE pEpClassFile = (PPDMASYNCCOMPLETIONEPCLASSFILE)pEndpoint->pEpClass;
    689     bool fUseFailsafeManager = pEpClassFile->fFailsafe;
     767    PDMACEPFILEMGRTYPE enmMgrType = pEpClassFile->enmMgrTypeOverride;
     768    PDMACFILEEPBACKEND enmEpBackend = pEpClassFile->enmEpBackendDefault;
    690769
    691770    AssertMsgReturn((fFlags & ~(PDMACEP_FILE_FLAGS_READ_ONLY | PDMACEP_FILE_FLAGS_CACHING)) == 0,
     
    696775                         : RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE;
    697776
    698     if (!pEpClassFile->fFailsafe)
    699     {
    700         fFileFlags |= (RTFILE_O_ASYNC_IO | RTFILE_O_WRITE_THROUGH);
    701 
     777    if (enmEpBackend == PDMACFILEEPBACKEND_NON_BUFFERED)
     778    {
    702779        /*
    703780         * We only disable the cache if the size of the file is a multiple of 512.
     
    717794            rc = RTFileGetSize(File, &cbSize);
    718795            if (RT_SUCCESS(rc) && ((cbSize % 512) == 0))
     796                fFileFlags |= RTFILE_O_NO_CACHE;
     797            else
    719798            {
    720                 fFileFlags &= ~RTFILE_O_WRITE_THROUGH;
    721 
    722 #if defined(RT_OS_LINUX)
    723                 AssertMsg(!pEpClassFile->fHostCacheEnabled, ("Host cache + async I/O is not supported on Linux\n"));
    724                 fFileFlags |= RTFILE_O_NO_CACHE;
    725 #else
    726                 if (!pEpClassFile->fHostCacheEnabled)
    727                     fFileFlags |= RTFILE_O_NO_CACHE;
    728 #endif
     799                /* Downgrade to the buffered backend */
     800                enmEpBackend = PDMACFILEEPBACKEND_BUFFERED;
    729801            }
    730 
    731             pEpFile->cbFile = cbSize;
    732 
    733802            RTFileClose(File);
    734803        }
     
    753822         */
    754823        fFileFlags &= ~RTFILE_O_NO_CACHE;
     824        enmEpBackend = PDMACFILEEPBACKEND_BUFFERED;
    755825
    756826#ifdef RT_OS_LINUX
    757827        fFileFlags &= ~RTFILE_O_ASYNC_IO;
    758         fUseFailsafeManager = true;
     828        enmMgrType   = PDMACEPFILEMGRTYPE_SIMPLE;
    759829#endif
    760830
     
    793863                pEpFile->cTasksCached   = 0;
    794864                pEpFile->pBwMgr         = pEpClassFile->pBwMgr;
     865                pEpFile->enmBackendType = enmEpBackend;
    795866                pdmacFileBwRef(pEpFile->pBwMgr);
    796867
    797                 if (fUseFailsafeManager)
     868                if (enmMgrType == PDMACEPFILEMGRTYPE_SIMPLE)
    798869                {
    799                     /* Safe mode. Every file has its own async I/O manager. */
    800                     rc = pdmacFileAioMgrCreate(pEpClassFile, &pAioMgr, true);
     870                    /* Simple mode. Every file has its own async I/O manager. */
     871                    rc = pdmacFileAioMgrCreate(pEpClassFile, &pAioMgr, PDMACEPFILEMGRTYPE_SIMPLE);
    801872                    AssertRC(rc);
    802873                }
     
    817888                    pAioMgr = pEpClassFile->pAioMgrHead;
    818889
    819                     /* Check for an idling not failsafe one or create new if not found */
    820                     while (pAioMgr && pAioMgr->fFailsafe)
     890                    /* Check for an idling manager of the same type */
     891                    while (pAioMgr)
     892                    {
     893                        if (pAioMgr->enmMgrType == enmMgrType)
     894                            break;
    821895                        pAioMgr = pAioMgr->pNext;
     896                    }
    822897
    823898                    if (!pAioMgr)
    824899                    {
    825                         rc = pdmacFileAioMgrCreate(pEpClassFile, &pAioMgr, false);
     900                        rc = pdmacFileAioMgrCreate(pEpClassFile, &pAioMgr, enmMgrType);
    826901                        AssertRC(rc);
    827902                    }
     
    888963     * he processes and thus can be destroyed now.
    889964     */
    890     if (pEpFile->pAioMgr->fFailsafe)
     965    if (pEpFile->pAioMgr->enmMgrType == PDMACEPFILEMGRTYPE_SIMPLE)
    891966        pdmacFileAioMgrDestroy(pEpClassFile, pEpFile->pAioMgr);
    892967
  • trunk/src/VBox/VMM/PDMAsyncCompletionFileFailsafe.cpp

    r26147 r27299  
    22/** @file
    33 * PDM Async I/O - Transport data asynchronous in R3 using EMT.
    4  * Failsafe File I/O manager.
     4 * Simple File I/O manager.
    55 */
    66
  • trunk/src/VBox/VMM/PDMAsyncCompletionFileInternal.h

    r27280 r27299  
    8787    PDMACEPFILEAIOMGRBLOCKINGEVENT_32BIT_HACK = 0x7fffffff
    8888} PDMACEPFILEAIOMGRBLOCKINGEVENT;
     89
     90/**
     91 * I/O manager type.
     92 */
     93typedef enum PDMACEPFILEMGRTYPE
     94{
     95    /** Simple aka failsafe */
     96    PDMACEPFILEMGRTYPE_SIMPLE = 0,
     97    /** Async I/O with host cache enabled. */
     98    PDMACEPFILEMGRTYPE_ASYNC,
     99    /** 32bit hack */
     100    PDMACEPFILEMGRTYPE_32BIT_HACK = 0x7fffffff
     101} PDMACEPFILEMGRTYPE;
     102/** Pointer to a I/O manager type */
     103typedef PDMACEPFILEMGRTYPE *PPDMACEPFILEMGRTYPE;
    89104
    90105/**
     
    124139    /** Previous Aio manager in the list. */
    125140    R3PTRTYPE(struct PDMACEPFILEMGR *)     pPrev;
     141    /** Manager type */
     142    PDMACEPFILEMGRTYPE                     enmMgrType;
    126143    /** Current state of the manager. */
    127144    PDMACEPFILEMGRSTATE                    enmState;
     
    130147    /** Flag whether the thread waits in the event semaphore. */
    131148    volatile bool                          fWaitingEventSem;
    132    /** Flag whether this manager uses the failsafe method. */
    133     bool                                   fFailsafe;
    134149    /** Thread data */
    135150    RTTHREAD                               Thread;
     
    402417
    403418/**
     419 * Backend type for the endpoint.
     420 */
     421typedef enum PDMACFILEEPBACKEND
     422{
     423    /** Non buffered. */
     424    PDMACFILEEPBACKEND_NON_BUFFERED = 0,
     425    /** Buffered (i.e host cache enabled) */
     426    PDMACFILEEPBACKEND_BUFFERED,
     427    /** 32bit hack */
     428    PDMACFILEEPBACKEND_32BIT_HACK = 0x7fffffff
     429} PDMACFILEEPBACKEND;
     430/** Pointer to a backend type. */
     431typedef PDMACFILEEPBACKEND *PPDMACFILEEPBACKEND;
     432
     433/**
    404434 * Global data for the file endpoint class.
    405435 */
     
    408438    /** Common data. */
    409439    PDMASYNCCOMPLETIONEPCLASS           Core;
    410     /** Flag whether we use the failsafe method. */
    411     bool                                fFailsafe;
     440    /** Override I/O manager type - set to SIMPLE after failure. */
     441    PDMACEPFILEMGRTYPE                  enmMgrTypeOverride;
     442    /** Default backend type for the endpoint. */
     443    PDMACFILEEPBACKEND                  enmEpBackendDefault;
    412444    /** Flag whether the file data cache is enabled. */
    413445    bool                                fCacheEnabled;
    414     /** Flag whether the host cache should be used too. */
    415     bool                                fHostCacheEnabled;
    416446    /** Critical section protecting the list of async I/O managers. */
    417447    RTCRITSECT                          CritSect;
     
    480510    /** Current state of the endpoint. */
    481511    PDMASYNCCOMPLETIONENDPOINTFILESTATE    enmState;
     512    /** The backend to use for this endpoint. */
     513    PDMACFILEEPBACKEND                     enmBackendType;
    482514    /** async I/O manager this endpoint is assigned to. */
    483515    R3PTRTYPE(volatile PPDMACEPFILEMGR)    pAioMgr;
     
    644676void pdmacFileAioMgrNormalDestroy(PPDMACEPFILEMGR pAioMgr);
    645677
    646 int pdmacFileAioMgrCreate(PPDMASYNCCOMPLETIONEPCLASSFILE pEpClass, PPPDMACEPFILEMGR ppAioMgr, bool fFailsafe);
     678int pdmacFileAioMgrCreate(PPDMASYNCCOMPLETIONEPCLASSFILE pEpClass, PPPDMACEPFILEMGR ppAioMgr, PDMACEPFILEMGRTYPE enmMgrType);
    647679
    648680int pdmacFileAioMgrAddEndpoint(PPDMACEPFILEMGR pAioMgr, PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint);
  • trunk/src/VBox/VMM/PDMAsyncCompletionFileNormal.cpp

    r27280 r27299  
    248248    if (pdmacFileAioMgrNormalIsBalancePossible(pAioMgr))
    249249    {
    250         rc = pdmacFileAioMgrCreate((PPDMASYNCCOMPLETIONEPCLASSFILE)pAioMgr->pEndpointsHead->Core.pEpClass,
    251                                    &pAioMgrNew, false);
     250        PPDMASYNCCOMPLETIONEPCLASSFILE pEpClassFile = (PPDMASYNCCOMPLETIONEPCLASSFILE)pAioMgr->pEndpointsHead->Core.pEpClass;
     251
     252        rc = pdmacFileAioMgrCreate(pEpClassFile, &pAioMgrNew, PDMACEPFILEMGRTYPE_ASYNC);
    252253        if (RT_SUCCESS(rc))
    253254        {
     
    326327
    327328    pAioMgr->enmState = PDMACEPFILEMGRSTATE_FAULT;
    328     ASMAtomicWriteBool(&pEpClassFile->fFailsafe, true);
     329    ASMAtomicWriteU32((volatile uint32_t *)&pEpClassFile->enmMgrTypeOverride, PDMACEPFILEMGRTYPE_SIMPLE);
    329330
    330331    AssertMsgFailed(("Implement\n"));
     
    562563}
    563564
    564 static int pdmacFileAioMgrNormalTaskPrepare(PPDMACEPFILEMGR pAioMgr,
    565                                             PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint,
    566                                             PPDMACTASKFILE pTask, PRTFILEAIOREQ phReq)
     565static int pdmacFileAioMgrNormalTaskPrepareBuffered(PPDMACEPFILEMGR pAioMgr,
     566                                                    PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint,
     567                                                    PPDMACTASKFILE pTask, PRTFILEAIOREQ phReq)
    567568{
    568569    int rc = VINF_SUCCESS;
     
    571572    void *pvBuf = pTask->DataSeg.pvSeg;
    572573
    573     /* Get a request handle. */
    574     hReq = pdmacFileAioMgrNormalRequestAlloc(pAioMgr);
    575     AssertMsg(hReq != NIL_RTFILEAIOREQ, ("Out of request handles\n"));
     574    AssertMsg(   pTask->enmTransferType == PDMACTASKFILETRANSFER_WRITE
     575                || (uint64_t)(pTask->Off + pTask->DataSeg.cbSeg) <= pEndpoint->cbFile,
     576                ("Read exceeds file size offStart=%RTfoff cbToTransfer=%d cbFile=%llu\n",
     577                pTask->Off, pTask->DataSeg.cbSeg, pEndpoint->cbFile));
     578
     579    pTask->fPrefetch = false;
     580    pTask->fBounceBuffer = false;
     581
     582    /*
     583     * Before we start to setup the request we have to check whether there is a task
     584     * already active which range intersects with ours. We have to defer execution
     585     * of this task in two cases:
     586     *     - The pending task is a write and the current is either read or write
     587     *     - The pending task is a read and the current task is a write task.
     588     *
     589     * To check whether a range is currently "locked" we use the AVL tree where every pending task
     590     * is stored by its file offset range. The current task will be added to the active task
     591     * and will be executed when the active one completes. (The method below
     592     * which checks whether a range is already used will add the task)
     593     *
     594     * This is neccessary because of the requirement to align all requests to a 512 boundary
     595     * which is enforced by the host OS (Linux and Windows atm). It is possible that
     596     * we have to process unaligned tasks and need to align them using bounce buffers.
     597     * While the data is fetched from the file another request might arrive writing to
     598     * the same range. This will result in data corruption if both are executed concurrently.
     599     */
     600    bool fLocked = pdmacFileAioMgrNormalIsRangeLocked(pEndpoint, pTask->Off, pTask->DataSeg.cbSeg, pTask);
     601
     602    if (!fLocked)
     603    {
     604        /* Get a request handle. */
     605        hReq = pdmacFileAioMgrNormalRequestAlloc(pAioMgr);
     606        AssertMsg(hReq != NIL_RTFILEAIOREQ, ("Out of request handles\n"));
     607
     608        if (pTask->enmTransferType == PDMACTASKFILETRANSFER_WRITE)
     609        {
     610            /* Grow the file if needed. */
     611            if (RT_UNLIKELY((uint64_t)(pTask->Off + pTask->DataSeg.cbSeg) > pEndpoint->cbFile))
     612            {
     613                ASMAtomicWriteU64(&pEndpoint->cbFile, pTask->Off + pTask->DataSeg.cbSeg);
     614                RTFileSetSize(pEndpoint->File, pTask->Off + pTask->DataSeg.cbSeg);
     615            }
     616
     617            rc = RTFileAioReqPrepareWrite(hReq, pEndpoint->File,
     618                                          pTask->Off, pTask->DataSeg.pvSeg,
     619                                          pTask->DataSeg.cbSeg, pTask);
     620        }
     621        else
     622            rc = RTFileAioReqPrepareRead(hReq, pEndpoint->File,
     623                                         pTask->Off, pTask->DataSeg.pvSeg,
     624                                         pTask->DataSeg.cbSeg, pTask);
     625        AssertRC(rc);
     626
     627        rc = pdmacFileAioMgrNormalRangeLock(pAioMgr, pEndpoint, pTask->Off,
     628                                            pTask->DataSeg.cbSeg,
     629                                            pTask);
     630
     631        if (RT_SUCCESS(rc))
     632            *phReq = hReq;
     633    }
     634    else
     635        LogFlow(("Task %#p was deferred because the access range is locked\n", pTask));
     636
     637    return rc;
     638}
     639
     640static int pdmacFileAioMgrNormalTaskPrepareNonBuffered(PPDMACEPFILEMGR pAioMgr,
     641                                                       PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint,
     642                                                       PPDMACTASKFILE pTask, PRTFILEAIOREQ phReq)
     643{
     644    int rc = VINF_SUCCESS;
     645    RTFILEAIOREQ hReq = NIL_RTFILEAIOREQ;
     646    PPDMASYNCCOMPLETIONEPCLASSFILE pEpClassFile = (PPDMASYNCCOMPLETIONEPCLASSFILE)pEndpoint->Core.pEpClass;
     647    void *pvBuf = pTask->DataSeg.pvSeg;
    576648
    577649    /*
     
    585657
    586658    AssertMsg(   pTask->enmTransferType == PDMACTASKFILETRANSFER_WRITE
    587               || (uint64_t)(offStart + cbToTransfer) <= pEndpoint->cbFile,
    588               ("Read exceeds file size offStart=%RTfoff cbToTransfer=%d cbFile=%llu\n",
    589                offStart, cbToTransfer, pEndpoint->cbFile));
     659                || (uint64_t)(offStart + cbToTransfer) <= pEndpoint->cbFile,
     660                ("Read exceeds file size offStart=%RTfoff cbToTransfer=%d cbFile=%llu\n",
     661                offStart, cbToTransfer, pEndpoint->cbFile));
    590662
    591663    pTask->fPrefetch = false;
     
    613685    if (!fLocked)
    614686    {
     687        /* Get a request handle. */
     688        hReq = pdmacFileAioMgrNormalRequestAlloc(pAioMgr);
     689        AssertMsg(hReq != NIL_RTFILEAIOREQ, ("Out of request handles\n"));
     690
    615691        if (   RT_UNLIKELY(cbToTransfer != pTask->DataSeg.cbSeg)
    616692            || RT_UNLIKELY(offStart != pTask->Off)
     
    692768    }
    693769    else
    694     {
    695770        LogFlow(("Task %#p was deferred because the access range is locked\n", pTask));
    696         rc = VINF_SUCCESS;
    697     }
    698771
    699772    return rc;
     
    755828                RTFILEAIOREQ hReq = NIL_RTFILEAIOREQ;
    756829
    757                 rc = pdmacFileAioMgrNormalTaskPrepare(pAioMgr, pEndpoint, pCurr, &hReq);
     830                if (pEndpoint->enmBackendType == PDMACFILEEPBACKEND_BUFFERED)
     831                    rc = pdmacFileAioMgrNormalTaskPrepareBuffered(pAioMgr, pEndpoint, pCurr, &hReq);
     832                else if (pEndpoint->enmBackendType == PDMACFILEEPBACKEND_NON_BUFFERED)
     833                    rc = pdmacFileAioMgrNormalTaskPrepareNonBuffered(pAioMgr, pEndpoint, pCurr, &hReq);
     834                else
     835                    AssertMsgFailed(("Invalid backend type %d\n", pEndpoint->enmBackendType));
     836
    758837                AssertRC(rc);
    759838
     
    10591138
    10601139            rc = pdmacFileAioMgrCreate((PPDMASYNCCOMPLETIONEPCLASSFILE)pEndpoint->Core.pEpClass,
    1061                                         &pAioMgrFailsafe, true);
     1140                                        &pAioMgrFailsafe, PDMACEPFILEMGRTYPE_SIMPLE);
    10621141            AssertRC(rc);
    10631142
Note: See TracChangeset for help on using the changeset viewer.

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