VirtualBox

Changeset 59290 in vbox for trunk/src/VBox/Devices/Storage


Ignore:
Timestamp:
Jan 8, 2016 6:15:30 PM (9 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
104944
Message:

Storage/DrvVD.cpp: First simple implementation for the PDMIMEDIAEX interface, work in progress

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Storage/DrvVD.cpp

    r59284 r59290  
    4040#include <iprt/memsafer.h>
    4141#include <iprt/memcache.h>
     42#include <iprt/list.h>
    4243
    4344#ifdef VBOX_WITH_INIP
     
    9798#define PDMIMEDIAASYNC_2_VBOXDISK(pInterface) \
    9899    ( (PVBOXDISK)((uintptr_t)pInterface - RT_OFFSETOF(VBOXDISK, IMediaAsync)) )
     100
     101/** Forward declaration for the dis kcontainer. */
     102typedef struct VBOXDISK *PVBOXDISK;
    99103
    100104/**
     
    161165    /** The request is not in use and resides on the free list. */
    162166    VDIOREQSTATE_FREE,
     167    /** The request was just allocated and is not active. */
     168    VDIOREQSTATE_ALLOCATED,
    163169    /** The request was allocated and is in use. */
    164170    VDIOREQSTATE_ACTIVE,
     171    /** The request is in the last step of completion and syncs memory. */
     172    VDIOREQSTATE_COMPLETING,
     173    /** The request completed. */
     174    VDIOREQSTATE_COMPLETED,
    165175    /** The request was aborted but wasn't returned as complete from the storage
    166176     * layer below us. */
    167     VDIOREQSTATE_ABORTED,
     177    VDIOREQSTATE_CANCELED,
    168178    /** 32bit hack. */
    169179    VDIOREQSTATE_32BIT_HACK = 0x7fffffff
     
    173183 * VD I/O Request.
    174184 */
    175 typedef struct VDIOREQ
    176 {
     185typedef struct PDMMEDIAEXIOREQINT
     186{
     187    /** List node for the list of allocated requests. */
     188    RTLISTNODE                    NdAllocatedList;
    177189    /** I/O request type. */
    178190    VDIOREQTYPE                   enmType;
    179191    /** Request state. */
    180192    volatile VDIOREQSTATE         enmState;
     193    /** I/O request ID. */
     194    PDMMEDIAEXIOREQID             uIoReqId;
     195    /** Flags. */
     196    uint32_t                      fFlags;
     197    /** Pointer to the disk container. */
     198    PVBOXDISK                     pDisk;
     199    /** I/O memory buffer. */
     200    RTSGSEG                       DataSeg;
     201    /** S/G buffer for this request. */
     202    RTSGBUF                       SgBuf;
    181203    /** Allocator specific memory - variable size. */
    182204    uint8_t                       abAlloc[1];
    183 } VDIOREQ;
     205} PDMMEDIAEXIOREQINT;
    184206/** Pointer to a VD I/O request. */
    185 typedef VDIOREQ *PVDIOREQ;
     207typedef PDMMEDIAEXIOREQINT *PPDMMEDIAEXIOREQINT;
     208
     209/**
     210 * Structure for holding a list of allocated requests.
     211 */
     212typedef struct VDLSTIOREQALLOC
     213{
     214    /** Mutex protecting the table of allocated requests. */
     215    RTSEMFASTMUTEX           hMtxLstIoReqAlloc;
     216    /** List anchor. */
     217    RTLISTANCHOR             LstIoReqAlloc;
     218} VDLSTIOREQALLOC;
     219typedef VDLSTIOREQALLOC *PVDLSTIOREQALLOC;
     220
     221/** Number of bins for allocated requests. */
     222#define DRVVD_VDIOREQ_ALLOC_BINS    8
    186223
    187224/**
     
    322359    /** Memory cache for the I/O requests. */
    323360    RTMEMCACHE               hIoReqCache;
     361    /** Active request counter. */
     362    volatile uint32_t        cIoReqsActive;
     363    /** Bins for allocated requests. */
     364    VDLSTIOREQALLOC          aIoReqAllocBins[DRVVD_VDIOREQ_ALLOC_BINS];
    324365    /** @} */
    325 } VBOXDISK, *PVBOXDISK;
     366} VBOXDISK;
    326367
    327368
     
    24032444*********************************************************************************************************************************/
    24042445
    2405 static void drvvdAsyncReqComplete(void *pvUser1, void *pvUser2, int rcReq)
     2446static DECLCALLBACK(void) drvvdAsyncReqComplete(void *pvUser1, void *pvUser2, int rcReq)
    24062447{
    24072448    PVBOXDISK pThis = (PVBOXDISK)pvUser1;
     
    26392680
    26402681/**
     2682 * Syncs the memory buffers between the I/O request allocator and the internal buffer.
     2683 *
     2684 * @returns VBox status code.
     2685 * @param   pThis     VBox disk container instance data.
     2686 * @param   pIoReq    I/O request to sync.
     2687 * @param   fToIoBuf  Flag indicating the sync direction.
     2688 *                    true to copy data from the allocators buffer to our internal buffer.
     2689 *                    false for the other direction.
     2690 */
     2691DECLINLINE(int) drvvdMediaExIoReqBufSync(PVBOXDISK pThis, PPDMMEDIAEXIOREQINT pIoReq, bool fToIoBuf)
     2692{
     2693    if (fToIoBuf)
     2694        return pThis->pDrvMediaExPort->pfnIoReqCopyToBuf(pThis->pDrvMediaExPort, pIoReq, &pIoReq->abAlloc[0],
     2695                                                         0, pIoReq->DataSeg.pvSeg, pIoReq->DataSeg.cbSeg);
     2696    else
     2697        return pThis->pDrvMediaExPort->pfnIoReqCopyFromBuf(pThis->pDrvMediaExPort, pIoReq, &pIoReq->abAlloc[0],
     2698                                                           0, pIoReq->DataSeg.pvSeg, pIoReq->DataSeg.cbSeg);
     2699}
     2700
     2701/**
     2702 * Hashes the I/O request ID to an index for the allocated I/O request bin.
     2703 */
     2704DECLINLINE(unsigned) drvvdMediaExIoReqIdHash(PDMMEDIAEXIOREQID uIoReqId)
     2705{
     2706    return uIoReqId % DRVVD_VDIOREQ_ALLOC_BINS; /** @todo: Find something better? */
     2707}
     2708
     2709/**
     2710 * Inserts the given I/O request in to the list of allocated I/O requests.
     2711 *
     2712 * @returns VBox status code.
     2713 * @param   pThis     VBox disk container instance data.
     2714 * @param   pIoReq    I/O request to insert.
     2715 */
     2716static int drvvdMediaExIoReqInsert(PVBOXDISK pThis, PPDMMEDIAEXIOREQINT pIoReq)
     2717{
     2718    int rc = VINF_SUCCESS;
     2719    unsigned idxBin = drvvdMediaExIoReqIdHash(pIoReq->uIoReqId);
     2720
     2721    rc = RTSemFastMutexRequest(pThis->aIoReqAllocBins[idxBin].hMtxLstIoReqAlloc);
     2722    if (RT_SUCCESS(rc))
     2723    {
     2724        /* Search for conflicting I/O request ID. */
     2725        PPDMMEDIAEXIOREQINT pIt;
     2726        RTListForEach(&pThis->aIoReqAllocBins[idxBin].LstIoReqAlloc, pIt, PDMMEDIAEXIOREQINT, NdAllocatedList)
     2727        {
     2728            if (RT_UNLIKELY(pIt->uIoReqId == pIoReq->uIoReqId))
     2729            {
     2730                rc = VERR_PDM_MEDIAEX_IOREQID_CONFLICT;
     2731                break;
     2732            }
     2733        }
     2734        if (RT_SUCCESS(rc))
     2735            RTListAppend(&pThis->aIoReqAllocBins[idxBin].LstIoReqAlloc, &pIoReq->NdAllocatedList);
     2736        RTSemFastMutexRelease(pThis->aIoReqAllocBins[idxBin].hMtxLstIoReqAlloc);
     2737    }
     2738
     2739    return rc;
     2740}
     2741
     2742/**
     2743 * Removes the given I/O request from the list of allocated I/O requests.
     2744 *
     2745 * @returns VBox status code.
     2746 * @param   pThis     VBox disk container instance data.
     2747 * @param   pIoReq    I/O request to insert.
     2748 */
     2749static int drvvdMediaExIoReqRemove(PVBOXDISK pThis, PPDMMEDIAEXIOREQINT pIoReq)
     2750{
     2751    int rc = VINF_SUCCESS;
     2752    unsigned idxBin = drvvdMediaExIoReqIdHash(pIoReq->uIoReqId);
     2753
     2754    rc = RTSemFastMutexRequest(pThis->aIoReqAllocBins[idxBin].hMtxLstIoReqAlloc);
     2755    if (RT_SUCCESS(rc))
     2756    {
     2757        RTListNodeRemove(&pIoReq->NdAllocatedList);
     2758        RTSemFastMutexRelease(pThis->aIoReqAllocBins[idxBin].hMtxLstIoReqAlloc);
     2759    }
     2760
     2761    return rc;
     2762}
     2763
     2764/**
     2765 * Allocates a memory buffer suitable for I/O for the given request.
     2766 *
     2767 * @returns VBox status code.
     2768 * @param   pThis     VBox disk container instance data.
     2769 * @param   pIoReq    I/O request to allocate memory for.
     2770 * @param   cb        Size of the buffer.
     2771 */
     2772static int drvvdMediaExIoReqBufAlloc(PVBOXDISK pThis, PPDMMEDIAEXIOREQINT pIoReq, size_t cb)
     2773{
     2774    int rc = VINF_SUCCESS;
     2775    void *pvBuf = NULL;
     2776
     2777    /* Configured encryption requires locked down memory. */
     2778    if (pThis->pCfgCrypto)
     2779        rc = RTMemSaferAllocZEx(&pvBuf, cb, RTMEMSAFER_F_REQUIRE_NOT_PAGABLE);
     2780    else
     2781    {
     2782        pvBuf = RTMemPageAlloc(RT_ALIGN_Z(cb, _4K));
     2783        if (RT_UNLIKELY(!pvBuf))
     2784            rc = VERR_NO_MEMORY;
     2785    }
     2786
     2787    if (RT_SUCCESS(rc))
     2788    {
     2789        pIoReq->DataSeg.pvSeg = pvBuf;
     2790        pIoReq->DataSeg.cbSeg = cb;
     2791        RTSgBufInit(&pIoReq->SgBuf, &pIoReq->DataSeg, 1);
     2792    }
     2793
     2794    return rc;
     2795}
     2796
     2797/**
     2798 * Frees a I/O memory buffer allocated previously.
     2799 *
     2800 * @returns nothing.
     2801 * @param   pThis     VBox disk container instance data.
     2802 * @param   pIoReq    I/O request for which to free memory.
     2803 */
     2804static void drvvdMediaExIoReqBufFree(PVBOXDISK pThis, PPDMMEDIAEXIOREQINT pIoReq)
     2805{
     2806    if (pThis->pCfgCrypto)
     2807        RTMemSaferFree(pIoReq->DataSeg.pvSeg, pIoReq->DataSeg.cbSeg);
     2808    else
     2809    {
     2810        size_t cb = RT_ALIGN_Z(pIoReq->DataSeg.cbSeg, _4K);
     2811        RTMemPageFree(pIoReq->DataSeg.pvSeg, cb);
     2812    }
     2813}
     2814
     2815/**
     2816 * I/O request completion worker.
     2817 *
     2818 * @returns VBox status code.
     2819 * @param   pThis     VBox disk container instance data.
     2820 * @param   pIoReq    I/O request to complete.
     2821 * @param   rcReq     The status code the request completed with.
     2822 * @param   fUpNotify Flag whether to notify the driver/device above us about the completion.
     2823 */
     2824static int drvvdMediaExIoReqCompleteWorker(PVBOXDISK pThis, PPDMMEDIAEXIOREQINT pIoReq, int rcReq, bool fUpNotify)
     2825{
     2826    int rc;
     2827    bool fXchg = ASMAtomicCmpXchgU32((volatile uint32_t *)&pIoReq->enmState, VDIOREQSTATE_COMPLETING, VDIOREQSTATE_ACTIVE);
     2828    if (fXchg)
     2829    {
     2830        ASMAtomicDecU32(&pThis->cIoReqsActive);
     2831
     2832        if (   RT_SUCCESS(rcReq)
     2833            && pIoReq->enmType == VDIOREQTYPE_READ)
     2834        {
     2835            /* Sync memory buffer with caller. */
     2836            rc = drvvdMediaExIoReqBufSync(pThis, pIoReq, false /* fToIoBuf */);
     2837            if (RT_FAILURE(rc))
     2838                rcReq = rc;
     2839        }
     2840    }
     2841    else
     2842    {
     2843        Assert(pIoReq->enmState == VDIOREQSTATE_CANCELED);
     2844        rcReq = VERR_PDM_MEDIAEX_IOREQ_CANCELED;
     2845    }
     2846
     2847    ASMAtomicXchgU32((volatile uint32_t *)&pIoReq->enmState, VDIOREQSTATE_COMPLETED);
     2848
     2849    if (fUpNotify)
     2850    {
     2851        rc = pThis->pDrvMediaExPort->pfnIoReqCompleteNotify(pThis->pDrvMediaExPort,
     2852                                                            pIoReq, &pIoReq->abAlloc[0], rcReq);
     2853        AssertRC(rc);
     2854    }
     2855
     2856    return rcReq;
     2857}
     2858
     2859/**
     2860 * @copydoc FNVDASYNCTRANSFERCOMPLETE
     2861 */
     2862static DECLCALLBACK(void) drvvdMediaExIoReqComplete(void *pvUser1, void *pvUser2, int rcReq)
     2863{
     2864    PVBOXDISK pThis = (PVBOXDISK)pvUser1;
     2865    PPDMMEDIAEXIOREQINT pIoReq = (PPDMMEDIAEXIOREQINT)pvUser2;
     2866
     2867    drvvdMediaExIoReqCompleteWorker(pThis, pIoReq, rcReq, true /* fUpNotify */);
     2868}
     2869
     2870/**
    26412871 * @interface_method_impl{PDMIMEDIAEX,pfnIoReqAllocSizeSet}
    26422872 */
     
    26442874{
    26452875    PVBOXDISK pThis = RT_FROM_MEMBER(pInterface, VBOXDISK, IMediaEx);
    2646     return VERR_NOT_IMPLEMENTED;
     2876    int rc = VINF_SUCCESS;
     2877
     2878    if (RT_UNLIKELY(pThis->hIoReqCache != NIL_RTMEMCACHE))
     2879        return VERR_INVALID_STATE;
     2880
     2881    return RTMemCacheCreate(&pThis->hIoReqCache, sizeof(PDMMEDIAEXIOREQINT) + cbIoReqAlloc, 0, UINT32_MAX,
     2882                            NULL, NULL, NULL, 0);
    26472883}
    26482884
     
    26542890{
    26552891    PVBOXDISK pThis = RT_FROM_MEMBER(pInterface, VBOXDISK, IMediaEx);
    2656     return VERR_NOT_IMPLEMENTED;
     2892    PPDMMEDIAEXIOREQINT pIoReq = (PPDMMEDIAEXIOREQINT)RTMemCacheAlloc(pThis->hIoReqCache);
     2893
     2894    if (RT_UNLIKELY(!pIoReq))
     2895        return VERR_NO_MEMORY;
     2896
     2897    pIoReq->uIoReqId = uIoReqId;
     2898    pIoReq->fFlags   = fFlags;
     2899    pIoReq->pDisk    = pThis;
     2900    pIoReq->enmState = VDIOREQSTATE_ALLOCATED;
     2901    pIoReq->enmType  = VDIOREQTYPE_INVALID;
     2902
     2903    int rc = drvvdMediaExIoReqInsert(pThis, pIoReq);
     2904    if (RT_SUCCESS(rc))
     2905    {
     2906        *phIoReq = pIoReq;
     2907        *ppvIoReqAlloc = &pIoReq->abAlloc[0];
     2908    }
     2909    else
     2910        RTMemCacheFree(pThis->hIoReqCache, pIoReq);
     2911
     2912    return rc;
    26572913}
    26582914
     
    26632919{
    26642920    PVBOXDISK pThis = RT_FROM_MEMBER(pInterface, VBOXDISK, IMediaEx);
    2665     return VERR_NOT_IMPLEMENTED;
     2921    PPDMMEDIAEXIOREQINT pIoReq = hIoReq;
     2922
     2923    if (   pIoReq->enmState != VDIOREQSTATE_COMPLETED
     2924        && pIoReq->enmState != VDIOREQSTATE_ALLOCATED)
     2925        return VERR_PDM_MEDIAEX_IOREQ_INVALID_STATE;
     2926
     2927    /* Remove from allocated list. */
     2928    int rc = drvvdMediaExIoReqRemove(pThis, pIoReq);
     2929    if (RT_FAILURE(rc))
     2930        return rc;
     2931
     2932    /* Free any associated I/O memory. */
     2933    drvvdMediaExIoReqBufFree(pThis, pIoReq);
     2934
     2935    pIoReq->enmState = VDIOREQSTATE_FREE;
     2936    RTMemCacheFree(pThis->hIoReqCache, pIoReq);
     2937    return VINF_SUCCESS;
    26662938}
    26672939
     
    26722944{
    26732945    PVBOXDISK pThis = RT_FROM_MEMBER(pInterface, VBOXDISK, IMediaEx);
    2674     return VERR_NOT_IMPLEMENTED;
     2946    unsigned idxBin = drvvdMediaExIoReqIdHash(uIoReqId);
     2947
     2948    int rc = RTSemFastMutexRequest(pThis->aIoReqAllocBins[idxBin].hMtxLstIoReqAlloc);
     2949    if (RT_SUCCESS(rc))
     2950    {
     2951        /* Search for I/O request with ID. */
     2952        PPDMMEDIAEXIOREQINT pIt;
     2953        rc = VERR_PDM_MEDIAEX_IOREQID_NOT_FOUND;
     2954
     2955        RTListForEach(&pThis->aIoReqAllocBins[idxBin].LstIoReqAlloc, pIt, PDMMEDIAEXIOREQINT, NdAllocatedList)
     2956        {
     2957            if (pIt->uIoReqId == uIoReqId)
     2958            {
     2959                bool fXchg = true;
     2960                VDIOREQSTATE enmStateOld = (VDIOREQSTATE)ASMAtomicReadU32((volatile uint32_t *)&pIt->enmState);
     2961
     2962                /*
     2963                 * We might have to try canceling the request multiple times if it transitioned from
     2964                 * ALLOCATED to ACTIVE between reading the state and trying to change it.
     2965                 */
     2966                while (   (   enmStateOld == VDIOREQSTATE_ALLOCATED
     2967                           || enmStateOld == VDIOREQSTATE_ACTIVE)
     2968                       && !fXchg)
     2969                {
     2970                    fXchg = ASMAtomicCmpXchgU32((volatile uint32_t *)&pIt->enmState, VDIOREQSTATE_CANCELED, enmStateOld);
     2971                    if (!fXchg)
     2972                        enmStateOld = (VDIOREQSTATE)ASMAtomicReadU32((volatile uint32_t *)&pIt->enmState);
     2973                }
     2974
     2975                if (fXchg)
     2976                {
     2977                    ASMAtomicDecU32(&pThis->cIoReqsActive);
     2978                    rc = VINF_SUCCESS;
     2979                }
     2980                break;
     2981            }
     2982        }
     2983        RTSemFastMutexRelease(pThis->aIoReqAllocBins[idxBin].hMtxLstIoReqAlloc);
     2984    }
     2985
     2986    return rc;
    26752987}
    26762988
     
    26812993{
    26822994    PVBOXDISK pThis = RT_FROM_MEMBER(pInterface, VBOXDISK, IMediaEx);
    2683     return VERR_NOT_IMPLEMENTED;
     2995    PPDMMEDIAEXIOREQINT pIoReq = hIoReq;
     2996    VDIOREQSTATE enmState = (VDIOREQSTATE)ASMAtomicReadU32((volatile uint32_t *)&pIoReq->enmState);
     2997
     2998    if (RT_UNLIKELY(enmState != VDIOREQSTATE_CANCELED))
     2999        return VERR_PDM_MEDIAEX_IOREQ_CANCELED;
     3000
     3001    if (RT_UNLIKELY(enmState != VDIOREQSTATE_ALLOCATED))
     3002        return VERR_PDM_MEDIAEX_IOREQ_INVALID_STATE;
     3003
     3004    pIoReq->enmType = VDIOREQTYPE_READ;
     3005    /* Allocate a suitable I/O buffer for this request. */
     3006    int rc = drvvdMediaExIoReqBufAlloc(pThis, pIoReq, cbRead);
     3007    if (RT_SUCCESS(rc))
     3008    {
     3009        bool fXchg = ASMAtomicCmpXchgU32((volatile uint32_t *)&pIoReq->enmState, VDIOREQSTATE_ACTIVE, VDIOREQSTATE_ALLOCATED);
     3010        if (RT_UNLIKELY(!fXchg))
     3011        {
     3012            /* Must have been canceled inbetween. */
     3013            Assert(pIoReq->enmState == VDIOREQSTATE_CANCELED);
     3014            return VERR_PDM_MEDIAEX_IOREQ_CANCELED;
     3015        }
     3016        ASMAtomicIncU32(&pThis->cIoReqsActive);
     3017        rc = VDAsyncRead(pThis->pDisk, off, cbRead, &pIoReq->SgBuf,
     3018                         drvvdMediaExIoReqComplete, pThis, pIoReq);
     3019        if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
     3020            rc = VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS;
     3021        else if (rc == VINF_VD_ASYNC_IO_FINISHED)
     3022            rc = VINF_SUCCESS;
     3023
     3024        if (rc != VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS)
     3025            rc = drvvdMediaExIoReqCompleteWorker(pThis, pIoReq, rc, false /* fUpNotify */);
     3026    }
     3027
     3028    return rc;
    26843029}
    26853030
     
    26903035{
    26913036    PVBOXDISK pThis = RT_FROM_MEMBER(pInterface, VBOXDISK, IMediaEx);
    2692     return VERR_NOT_IMPLEMENTED;
     3037    PPDMMEDIAEXIOREQINT pIoReq = hIoReq;
     3038    VDIOREQSTATE enmState = (VDIOREQSTATE)ASMAtomicReadU32((volatile uint32_t *)&pIoReq->enmState);
     3039
     3040    if (RT_UNLIKELY(enmState != VDIOREQSTATE_CANCELED))
     3041        return VERR_PDM_MEDIAEX_IOREQ_CANCELED;
     3042
     3043    if (RT_UNLIKELY(enmState != VDIOREQSTATE_ALLOCATED))
     3044        return VERR_PDM_MEDIAEX_IOREQ_INVALID_STATE;
     3045
     3046    pIoReq->enmType = VDIOREQTYPE_WRITE;
     3047    /* Allocate a suitable I/O buffer for this request. */
     3048    int rc = drvvdMediaExIoReqBufAlloc(pThis, pIoReq, cbWrite);
     3049    if (RT_SUCCESS(rc))
     3050    {
     3051        /* Sync memory buffer with caller. */
     3052        rc = drvvdMediaExIoReqBufSync(pThis, pIoReq, true /* fToIoBuf */);
     3053        if (RT_SUCCESS(rc))
     3054        {
     3055            bool fXchg = ASMAtomicCmpXchgU32((volatile uint32_t *)&pIoReq->enmState, VDIOREQSTATE_ACTIVE, VDIOREQSTATE_ALLOCATED);
     3056            if (RT_UNLIKELY(!fXchg))
     3057            {
     3058                /* Must have been canceled inbetween. */
     3059                Assert(pIoReq->enmState == VDIOREQSTATE_CANCELED);
     3060                return VERR_PDM_MEDIAEX_IOREQ_CANCELED;
     3061            }
     3062
     3063            ASMAtomicIncU32(&pThis->cIoReqsActive);
     3064            rc = VDAsyncRead(pThis->pDisk, off, cbWrite, &pIoReq->SgBuf,
     3065                             drvvdMediaExIoReqComplete, pThis, pIoReq);
     3066            if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
     3067                rc = VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS;
     3068            else if (rc == VINF_VD_ASYNC_IO_FINISHED)
     3069                rc = VINF_SUCCESS;
     3070
     3071            if (rc != VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS)
     3072                rc = drvvdMediaExIoReqCompleteWorker(pThis, pIoReq, rc, false /* fUpNotify */);
     3073        }
     3074    }
     3075
     3076    return rc;
    26933077}
    26943078
     
    26993083{
    27003084    PVBOXDISK pThis = RT_FROM_MEMBER(pInterface, VBOXDISK, IMediaEx);
    2701     return VERR_NOT_IMPLEMENTED;
     3085    PPDMMEDIAEXIOREQINT pIoReq = hIoReq;
     3086    VDIOREQSTATE enmState = (VDIOREQSTATE)ASMAtomicReadU32((volatile uint32_t *)&pIoReq->enmState);
     3087
     3088    if (RT_UNLIKELY(enmState != VDIOREQSTATE_CANCELED))
     3089        return VERR_PDM_MEDIAEX_IOREQ_CANCELED;
     3090
     3091    if (RT_UNLIKELY(enmState != VDIOREQSTATE_ALLOCATED))
     3092        return VERR_PDM_MEDIAEX_IOREQ_INVALID_STATE;
     3093
     3094    pIoReq->enmType = VDIOREQTYPE_FLUSH;
     3095
     3096    bool fXchg = ASMAtomicCmpXchgU32((volatile uint32_t *)&pIoReq->enmState, VDIOREQSTATE_ACTIVE, VDIOREQSTATE_ALLOCATED);
     3097    if (RT_UNLIKELY(!fXchg))
     3098    {
     3099        /* Must have been canceled inbetween. */
     3100        Assert(pIoReq->enmState == VDIOREQSTATE_CANCELED);
     3101        return VERR_PDM_MEDIAEX_IOREQ_CANCELED;
     3102    }
     3103
     3104    ASMAtomicIncU32(&pThis->cIoReqsActive);
     3105    int rc = VDAsyncFlush(pThis->pDisk, drvvdMediaExIoReqComplete, pThis, pIoReq);
     3106    if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
     3107        rc = VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS;
     3108    else if (rc == VINF_VD_ASYNC_IO_FINISHED)
     3109        rc = VINF_SUCCESS;
     3110
     3111    if (rc != VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS)
     3112        rc = drvvdMediaExIoReqCompleteWorker(pThis, pIoReq, rc, false /* fUpNotify */);
     3113
     3114    return rc;
    27023115}
    27033116
     
    27083121{
    27093122    PVBOXDISK pThis = RT_FROM_MEMBER(pInterface, VBOXDISK, IMediaEx);
    2710     return VERR_NOT_IMPLEMENTED;
     3123    PPDMMEDIAEXIOREQINT pIoReq = hIoReq;
     3124    VDIOREQSTATE enmState = (VDIOREQSTATE)ASMAtomicReadU32((volatile uint32_t *)&pIoReq->enmState);
     3125
     3126    if (RT_UNLIKELY(enmState != VDIOREQSTATE_CANCELED))
     3127        return VERR_PDM_MEDIAEX_IOREQ_CANCELED;
     3128
     3129    if (RT_UNLIKELY(enmState != VDIOREQSTATE_ALLOCATED))
     3130        return VERR_PDM_MEDIAEX_IOREQ_INVALID_STATE;
     3131
     3132    pIoReq->enmType = VDIOREQTYPE_DISCARD;
     3133
     3134    bool fXchg = ASMAtomicCmpXchgU32((volatile uint32_t *)&pIoReq->enmState, VDIOREQSTATE_ACTIVE, VDIOREQSTATE_ALLOCATED);
     3135    if (RT_UNLIKELY(!fXchg))
     3136    {
     3137        /* Must have been canceled inbetween. */
     3138        Assert(pIoReq->enmState == VDIOREQSTATE_CANCELED);
     3139        return VERR_PDM_MEDIAEX_IOREQ_CANCELED;
     3140    }
     3141
     3142    ASMAtomicIncU32(&pThis->cIoReqsActive);
     3143    int rc = VDAsyncDiscardRanges(pThis->pDisk, paRanges, cRanges,
     3144                                  drvvdMediaExIoReqComplete, pThis, pIoReq);
     3145    if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
     3146        rc = VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS;
     3147    else if (rc == VINF_VD_ASYNC_IO_FINISHED)
     3148        rc = VINF_SUCCESS;
     3149
     3150    if (rc != VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS)
     3151        rc = drvvdMediaExIoReqCompleteWorker(pThis, pIoReq, rc, false /* fUpNotify */);
     3152
     3153    return rc;
    27113154}
    27123155
     
    27173160{
    27183161    PVBOXDISK pThis = RT_FROM_MEMBER(pInterface, VBOXDISK, IMediaEx);
    2719     return 0;
     3162    return ASMAtomicReadU32(&pThis->cIoReqsActive);
    27203163}
    27213164
     
    31033546    if (pThis->hHbdMgr != NIL_HBDMGR)
    31043547        HBDMgrDestroy(pThis->hHbdMgr);
     3548    if (pThis->hIoReqCache != NIL_RTMEMCACHE)
     3549        RTMemCacheDestroy(pThis->hIoReqCache);
     3550    for (unsigned i = 0; i < RT_ELEMENTS(pThis->aIoReqAllocBins); i++)
     3551    {
     3552        if (pThis->aIoReqAllocBins[i].hMtxLstIoReqAlloc != NIL_RTSEMFASTMUTEX)
     3553            RTSemFastMutexDestroy(pThis->aIoReqAllocBins[i].hMtxLstIoReqAlloc);
     3554    }
    31053555}
    31063556
     
    31413591    pThis->pIfSecKey                    = NULL;
    31423592    pThis->hIoReqCache                  = NIL_RTMEMCACHE;
     3593
     3594    for (unsigned i = 0; i < RT_ELEMENTS(pThis->aIoReqAllocBins); i++)
     3595        pThis->aIoReqAllocBins[i].hMtxLstIoReqAlloc = NIL_RTSEMFASTMUTEX;
    31433596
    31443597    /* IMedia */
     
    32093662    pThis->pDrvMountNotify    = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIMOUNTNOTIFY);
    32103663
    3211     /* Try to attach the optional extended media interface port above. */
    3212     pThis->pDrvMediaExPort    = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIMEDIAEXPORT);
     3664    /*
     3665     * Try to attach the optional extended media interface port above and initialize associated
     3666     * structures if available.
     3667     */
     3668    pThis->pDrvMediaExPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIMEDIAEXPORT);
     3669    if (pThis->pDrvMediaExPort)
     3670    {
     3671        for (unsigned i = 0; i < RT_ELEMENTS(pThis->aIoReqAllocBins); i++)
     3672        {
     3673            rc = RTSemFastMutexCreate(&pThis->aIoReqAllocBins[i].hMtxLstIoReqAlloc);
     3674            if (RT_FAILURE(rc))
     3675                break;
     3676            RTListInit(&pThis->aIoReqAllocBins[i].LstIoReqAlloc);
     3677        }
     3678
     3679        if (RT_FAILURE(rc))
     3680            return PDMDRV_SET_ERROR(pDrvIns, rc, N_("Creating Mutex failed"));
     3681    }
    32133682
    32143683    /* Before we access any VD API load all given plugins. */
     
    32463715                                          "CachePath\0CacheFormat\0Discard\0InformAboutZeroBlocks\0"
    32473716                                          "SkipConsistencyChecks\0"
    3248                                           "SubType\0Locked\0BIOSVisible\0Cylinders\0Heads\0Sectors\0Mountable\0"
     3717                                          "Locked\0BIOSVisible\0Cylinders\0Heads\0Sectors\0Mountable\0"
    32493718                                          "EmptyDrive\0"
    32503719#if defined(VBOX_PERIODIC_FLUSH) || defined(VBOX_IGNORE_FLUSH)
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