Changeset 59290 in vbox for trunk/src/VBox/Devices/Storage
- Timestamp:
- Jan 8, 2016 6:15:30 PM (9 years ago)
- svn:sync-xref-src-repo-rev:
- 104944
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DrvVD.cpp
r59284 r59290 40 40 #include <iprt/memsafer.h> 41 41 #include <iprt/memcache.h> 42 #include <iprt/list.h> 42 43 43 44 #ifdef VBOX_WITH_INIP … … 97 98 #define PDMIMEDIAASYNC_2_VBOXDISK(pInterface) \ 98 99 ( (PVBOXDISK)((uintptr_t)pInterface - RT_OFFSETOF(VBOXDISK, IMediaAsync)) ) 100 101 /** Forward declaration for the dis kcontainer. */ 102 typedef struct VBOXDISK *PVBOXDISK; 99 103 100 104 /** … … 161 165 /** The request is not in use and resides on the free list. */ 162 166 VDIOREQSTATE_FREE, 167 /** The request was just allocated and is not active. */ 168 VDIOREQSTATE_ALLOCATED, 163 169 /** The request was allocated and is in use. */ 164 170 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, 165 175 /** The request was aborted but wasn't returned as complete from the storage 166 176 * layer below us. */ 167 VDIOREQSTATE_ ABORTED,177 VDIOREQSTATE_CANCELED, 168 178 /** 32bit hack. */ 169 179 VDIOREQSTATE_32BIT_HACK = 0x7fffffff … … 173 183 * VD I/O Request. 174 184 */ 175 typedef struct VDIOREQ 176 { 185 typedef struct PDMMEDIAEXIOREQINT 186 { 187 /** List node for the list of allocated requests. */ 188 RTLISTNODE NdAllocatedList; 177 189 /** I/O request type. */ 178 190 VDIOREQTYPE enmType; 179 191 /** Request state. */ 180 192 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; 181 203 /** Allocator specific memory - variable size. */ 182 204 uint8_t abAlloc[1]; 183 } VDIOREQ;205 } PDMMEDIAEXIOREQINT; 184 206 /** Pointer to a VD I/O request. */ 185 typedef VDIOREQ *PVDIOREQ; 207 typedef PDMMEDIAEXIOREQINT *PPDMMEDIAEXIOREQINT; 208 209 /** 210 * Structure for holding a list of allocated requests. 211 */ 212 typedef struct VDLSTIOREQALLOC 213 { 214 /** Mutex protecting the table of allocated requests. */ 215 RTSEMFASTMUTEX hMtxLstIoReqAlloc; 216 /** List anchor. */ 217 RTLISTANCHOR LstIoReqAlloc; 218 } VDLSTIOREQALLOC; 219 typedef VDLSTIOREQALLOC *PVDLSTIOREQALLOC; 220 221 /** Number of bins for allocated requests. */ 222 #define DRVVD_VDIOREQ_ALLOC_BINS 8 186 223 187 224 /** … … 322 359 /** Memory cache for the I/O requests. */ 323 360 RTMEMCACHE hIoReqCache; 361 /** Active request counter. */ 362 volatile uint32_t cIoReqsActive; 363 /** Bins for allocated requests. */ 364 VDLSTIOREQALLOC aIoReqAllocBins[DRVVD_VDIOREQ_ALLOC_BINS]; 324 365 /** @} */ 325 } VBOXDISK , *PVBOXDISK;366 } VBOXDISK; 326 367 327 368 … … 2403 2444 *********************************************************************************************************************************/ 2404 2445 2405 static voiddrvvdAsyncReqComplete(void *pvUser1, void *pvUser2, int rcReq)2446 static DECLCALLBACK(void) drvvdAsyncReqComplete(void *pvUser1, void *pvUser2, int rcReq) 2406 2447 { 2407 2448 PVBOXDISK pThis = (PVBOXDISK)pvUser1; … … 2639 2680 2640 2681 /** 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 */ 2691 DECLINLINE(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 */ 2704 DECLINLINE(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 */ 2716 static 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 */ 2749 static 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 */ 2772 static 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 */ 2804 static 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 */ 2824 static 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 */ 2862 static 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 /** 2641 2871 * @interface_method_impl{PDMIMEDIAEX,pfnIoReqAllocSizeSet} 2642 2872 */ … … 2644 2874 { 2645 2875 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); 2647 2883 } 2648 2884 … … 2654 2890 { 2655 2891 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; 2657 2913 } 2658 2914 … … 2663 2919 { 2664 2920 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; 2666 2938 } 2667 2939 … … 2672 2944 { 2673 2945 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; 2675 2987 } 2676 2988 … … 2681 2993 { 2682 2994 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; 2684 3029 } 2685 3030 … … 2690 3035 { 2691 3036 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; 2693 3077 } 2694 3078 … … 2699 3083 { 2700 3084 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; 2702 3115 } 2703 3116 … … 2708 3121 { 2709 3122 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; 2711 3154 } 2712 3155 … … 2717 3160 { 2718 3161 PVBOXDISK pThis = RT_FROM_MEMBER(pInterface, VBOXDISK, IMediaEx); 2719 return 0;3162 return ASMAtomicReadU32(&pThis->cIoReqsActive); 2720 3163 } 2721 3164 … … 3103 3546 if (pThis->hHbdMgr != NIL_HBDMGR) 3104 3547 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 } 3105 3555 } 3106 3556 … … 3141 3591 pThis->pIfSecKey = NULL; 3142 3592 pThis->hIoReqCache = NIL_RTMEMCACHE; 3593 3594 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aIoReqAllocBins); i++) 3595 pThis->aIoReqAllocBins[i].hMtxLstIoReqAlloc = NIL_RTSEMFASTMUTEX; 3143 3596 3144 3597 /* IMedia */ … … 3209 3662 pThis->pDrvMountNotify = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIMOUNTNOTIFY); 3210 3663 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 } 3213 3682 3214 3683 /* Before we access any VD API load all given plugins. */ … … 3246 3715 "CachePath\0CacheFormat\0Discard\0InformAboutZeroBlocks\0" 3247 3716 "SkipConsistencyChecks\0" 3248 " SubType\0Locked\0BIOSVisible\0Cylinders\0Heads\0Sectors\0Mountable\0"3717 "Locked\0BIOSVisible\0Cylinders\0Heads\0Sectors\0Mountable\0" 3249 3718 "EmptyDrive\0" 3250 3719 #if defined(VBOX_PERIODIC_FLUSH) || defined(VBOX_IGNORE_FLUSH)
Note:
See TracChangeset
for help on using the changeset viewer.