VirtualBox

Changeset 19562 in vbox for trunk/src/VBox/Runtime/r3/linux


Ignore:
Timestamp:
May 10, 2009 9:44:16 PM (16 years ago)
Author:
vboxsync
Message:

Runtime/Aio: Change API again

  • pcReqs in RTFileAioCtxSubmit is useless because it does not specify which request fails. Removed it again and made it possible to get the state of a request through RTFileAioReqGetRC()
  • Introduce request states for the first point and to catch more errors using the API before a system dependent call is made to return the same error codes one every system for the same cause.
  • Add RTFileAioGetLimits to get global limits and indication for AIO support.
  • General cleanups and fixes
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/linux/fileaio-linux.cpp

    r19371 r19562  
    190190     *  the structure! (see notes below) */
    191191    LNXKAIOIOCB           AioCB;
     192    /** Current state the request is in. */
     193    RTFILEAIOREQSTATE     enmState;
    192194    /** The I/O context this request is associated with. */
    193195    aio_context_t         AioContext;
    194196    /** Return code the request completed with. */
    195197    int                   Rc;
    196     /** Flag whether the request is in process or not. */
    197     bool                  fFinished;
    198198    /** Number of bytes actually trasnfered. */
    199199    size_t                cbTransfered;
     
    241241 * Submits an array of I/O requests to the kernel.
    242242 */
    243 DECLINLINE(int) rtFileAsyncIoLinuxSubmit(aio_context_t AioContext, long cReqs, LNXKAIOIOCB **ppIoCB)
     243DECLINLINE(int) rtFileAsyncIoLinuxSubmit(aio_context_t AioContext, long cReqs, LNXKAIOIOCB **ppIoCB, int *pcSubmitted)
    244244{
    245245    int rc = syscall(__NR_io_submit, AioContext, cReqs, ppIoCB);
     
    247247        return RTErrConvertFromErrno(errno);
    248248
     249    *pcSubmitted = rc;
     250
    249251    return VINF_SUCCESS;
    250252}
     
    276278}
    277279
     280RTR3DECL(int) RTFileAioGetLimits(PRTFILEAIOLIMITS pAioLimits)
     281{
     282    int rc = VINF_SUCCESS;
     283    AssertPtrReturn(pAioLimits, VERR_INVALID_POINTER);
     284
     285    /*
     286     * Check if the API is implemented by creating a
     287     * completion port.
     288     */
     289    aio_context_t AioContext = 0;
     290    rc = rtFileAsyncIoLinuxCreate(1, &AioContext);
     291    if (RT_FAILURE(rc))
     292        return rc;
     293
     294    rc = rtFileAsyncIoLinuxDestroy(AioContext);
     295    if (RT_FAILURE(rc))
     296        return rc;
     297
     298    /* Supported - fill in the limits. The alignment is the only restriction. */
     299    pAioLimits->cReqsOutstandingMax = RTFILEAIO_UNLIMITED_REQS;
     300    pAioLimits->cbBufferAlignment   = 512;
     301
     302    return VINF_SUCCESS;
     303}
     304
     305
    278306RTR3DECL(int) RTFileAioReqCreate(PRTFILEAIOREQ phReq)
    279307{
     
    287315        return VERR_NO_MEMORY;
    288316
    289     pReqInt->fFinished = false;
    290317    pReqInt->pCtxInt   = NULL;
    291318    pReqInt->u32Magic  = RTFILEAIOREQ_MAGIC;
     319    RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
    292320
    293321    *phReq = (RTFILEAIOREQ)pReqInt;
     
    296324
    297325
    298 RTDECL(void) RTFileAioReqDestroy(RTFILEAIOREQ hReq)
     326RTDECL(int) RTFileAioReqDestroy(RTFILEAIOREQ hReq)
    299327{
    300328    /*
     
    302330     */
    303331    if (hReq == NIL_RTFILEAIOREQ)
    304         return;
     332        return VINF_SUCCESS;
    305333    PRTFILEAIOREQINTERNAL pReqInt = hReq;
    306     RTFILEAIOREQ_VALID_RETURN_VOID(pReqInt);
     334    RTFILEAIOREQ_VALID_RETURN(pReqInt);
     335    RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS);
    307336
    308337    /*
     
    311340    ASMAtomicUoWriteU32(&pReqInt->u32Magic, ~RTFILEAIOREQ_MAGIC);
    312341    RTMemFree(pReqInt);
     342    return VINF_SUCCESS;
    313343}
    314344
     
    327357    PRTFILEAIOREQINTERNAL pReqInt = hReq;
    328358    RTFILEAIOREQ_VALID_RETURN(pReqInt);
     359    RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS);
    329360    Assert(hFile != NIL_RTFILE);
    330361    AssertPtr(pvBuf);
     
    342373    pReqInt->AioCB.pvUser      = pvUser;
    343374
    344     pReqInt->fFinished         = false;
    345375    pReqInt->pCtxInt           = NULL;
     376    RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED);
    346377
    347378    return VINF_SUCCESS;
     
    370401    RTFILEAIOREQ_VALID_RETURN(pReqInt);
    371402    AssertReturn(hFile != NIL_RTFILE, VERR_INVALID_HANDLE);
     403    RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS);
    372404
    373405    /** @todo: Flushing is not neccessary on Linux because O_DIRECT is mandatory
     
    397429    PRTFILEAIOREQINTERNAL pReqInt = hReq;
    398430    RTFILEAIOREQ_VALID_RETURN(pReqInt);
     431    RTFILEAIOREQ_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_NOT_SUBMITTED);
    399432
    400433    LNXKAIOIOEVENT AioEvent;
     
    410443
    411444        ASMAtomicDecS32(&pReqInt->pCtxInt->cRequests);
     445        pReqInt->Rc = VERR_FILE_AIO_CANCELED;
     446        RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
    412447        return VINF_SUCCESS;
    413448    }
     
    423458    RTFILEAIOREQ_VALID_RETURN(pReqInt);
    424459    AssertPtrNull(pcbTransfered);
    425 
    426     if (!pReqInt->fFinished)
    427         return VERR_FILE_AIO_IN_PROGRESS;
     460    RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, SUBMITTED, VERR_FILE_AIO_IN_PROGRESS);
     461    RTFILEAIOREQ_NOT_STATE_RETURN_RC(pReqInt, PREPARED, VERR_FILE_AIO_NOT_SUBMITTED);
    428462
    429463    if (    pcbTransfered
     
    509543}
    510544
    511 RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs, size_t *pcReqs)
    512 {
     545RTDECL(int) RTFileAioCtxSubmit(RTFILEAIOCTX hAioCtx, PRTFILEAIOREQ pahReqs, size_t cReqs)
     546{
     547    int rc = VINF_SUCCESS;
     548
    513549    /*
    514550     * Parameter validation.
    515551     */
    516     AssertPtrReturn(pcReqs, VERR_INVALID_POINTER);
    517     *pcReqs = 0;
    518552    PRTFILEAIOCTXINTERNAL pCtxInt = hAioCtx;
    519553    RTFILEAIOCTX_VALID_RETURN(pCtxInt);
     
    521555    AssertPtrReturn(pahReqs, VERR_INVALID_POINTER);
    522556    uint32_t i = cReqs;
     557    PRTFILEAIOREQINTERNAL pReqInt = NULL;
    523558
    524559    /*
     
    527562    while (i-- > 0)
    528563    {
    529         PRTFILEAIOREQINTERNAL pReqInt = pahReqs[i];
    530         RTFILEAIOREQ_VALID_RETURN(pReqInt);
     564        pReqInt = pahReqs[i];
     565        if (RTFILEAIOREQ_IS_NOT_VALID(pReqInt))
     566        {
     567            /* Undo everything and stop submitting. */
     568            size_t iUndo = cReqs;
     569            while (iUndo-- > i)
     570            {
     571                pReqInt = pahReqs[iUndo];
     572                RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED);
     573                pReqInt->pCtxInt = NULL;
     574            }
     575            return VERR_INVALID_HANDLE;
     576        }
    531577
    532578        pReqInt->AioContext = pCtxInt->AioContext;
    533579        pReqInt->pCtxInt    = pCtxInt;
     580        RTFILEAIOREQ_SET_STATE(pReqInt, SUBMITTED);
    534581    }
    535582
    536     /*
    537      * Add the submitted requests to the counter
    538      * to prevent destroying the context while
    539      * it is still used.
    540      */
    541     ASMAtomicAddS32(&pCtxInt->cRequests, cReqs);
    542 
    543     /*
    544      * We cast phReqs to the Linux iocb structure to avoid copying the requests
    545      * into a temporary array. This is possible because the iocb structure is
    546      * the first element in the request structure (see PRTFILEAIOCTXINTERNAL).
    547      */
    548     int rc = rtFileAsyncIoLinuxSubmit(pCtxInt->AioContext, cReqs, (PLNXKAIOIOCB *)pahReqs);
    549     if (RT_FAILURE(rc))
    550         ASMAtomicSubS32(&pCtxInt->cRequests, cReqs);
    551     else
    552         *pcReqs = cReqs;
     583    do
     584    {
     585        /*
     586         * We cast pahReqs to the Linux iocb structure to avoid copying the requests
     587         * into a temporary array. This is possible because the iocb structure is
     588         * the first element in the request structure (see PRTFILEAIOCTXINTERNAL).
     589         */
     590        int cReqsSubmitted = 0;
     591        rc = rtFileAsyncIoLinuxSubmit(pCtxInt->AioContext, cReqs,
     592                                      (PLNXKAIOIOCB *)pahReqs,
     593                                      &cReqsSubmitted);
     594        if (RT_FAILURE(rc))
     595        {
     596            /*
     597             * We encountered an error.
     598             * This means that the first IoCB
     599             * is not correctly initialized
     600             * (invalid buffer alignment or bad file descriptor).
     601             * Revert every request into the prepared state except
     602             * the first one which will switch to completed.
     603             * Another reason could be insuffidient ressources.
     604             */
     605            i = cReqs;
     606            while (i-- > 0)
     607            {
     608                /* Already validated. */
     609                pReqInt = pahReqs[i];
     610                pReqInt->pCtxInt    = NULL;
     611                pReqInt->AioContext = 0;
     612                RTFILEAIOREQ_SET_STATE(pReqInt, PREPARED);
     613            }
     614
     615            if (rc == VERR_TRY_AGAIN)
     616                return VERR_FILE_AIO_INSUFFICIENT_RESSOURCES;
     617            else
     618            {
     619                /* The first request failed. */
     620                pReqInt = pahReqs[0];
     621                RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
     622                pReqInt->Rc = rc;
     623                pReqInt->cbTransfered = 0;
     624                return rc;
     625            }
     626        }
     627
     628        /* Advance. */
     629        cReqs   -= cReqsSubmitted;
     630        pahReqs += cReqsSubmitted;
     631        ASMAtomicAddS32(&pCtxInt->cRequests, cReqsSubmitted);
     632
     633    } while (cReqs);
    553634
    554635    return rc;
     
    643724
    644725            /* Mark the request as finished. */
    645             pReqInt->fFinished = true;
     726            RTFILEAIOREQ_SET_STATE(pReqInt, COMPLETED);
    646727
    647728            pahReqs[cRequestsCompleted++] = (RTFILEAIOREQ)pReqInt;
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