VirtualBox

Changeset 38878 in vbox


Ignore:
Timestamp:
Sep 27, 2011 9:07:07 AM (13 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
74200
Message:

PDM,Devices,Drivers: Add async discard API and make us of it

Location:
trunk
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/pdmdrv.h

    r37418 r38878  
    12631263                                                  PFNPDMBLKCACHEXFERCOMPLETEDRV pfnXferComplete,
    12641264                                                  PFNPDMBLKCACHEXFERENQUEUEDRV pfnXferEnqueue,
     1265                                                  PFNPDMBLKCACHEXFERENQUEUEDISCARDDRV pfnXferEnqueueDiscard,
    12651266                                                  const char *pcszId));
    12661267
     
    17201721                                        PFNPDMBLKCACHEXFERCOMPLETEDRV pfnXferComplete,
    17211722                                        PFNPDMBLKCACHEXFERENQUEUEDRV pfnXferEnqueue,
     1723                                        PFNPDMBLKCACHEXFERENQUEUEDISCARDDRV pfnXferEnqueueDiscard,
    17221724                                        const char *pcszId)
    17231725{
    1724     return pDrvIns->pHlpR3->pfnBlkCacheRetain(pDrvIns, ppBlkCache, pfnXferComplete, pfnXferEnqueue, pcszId);
     1726    return pDrvIns->pHlpR3->pfnBlkCacheRetain(pDrvIns, ppBlkCache, pfnXferComplete, pfnXferEnqueue, pfnXferEnqueueDiscard, pcszId);
    17251727}
    17261728
  • trunk/include/VBox/vmm/pdmifs.h

    r38622 r38878  
    913913
    914914
    915 /**
    916  * PDM range.
    917  */
    918 typedef struct PDMRANGE
    919 {
    920     /** Start offset. */
    921     uint64_t    offStart;
    922     /** Size. */
    923     size_t      cbRange;
    924 } PDMRANGE;
    925 /** Pointer to a PDM range. */
    926 typedef PDMRANGE *PPDMRANGE;
    927 
    928 
    929915/** Pointer to a block interface. */
    930916typedef struct PDMIBLOCK *PPDMIBLOCK;
     
    10431029     * @thread  Any thread.
    10441030     */
    1045     DECLR3CALLBACKMEMBER(int, pfnDiscard,(PPDMIBLOCK pInterface, PPDMRANGE paRanges, unsigned cRanges));
     1031    DECLR3CALLBACKMEMBER(int, pfnDiscard,(PPDMIBLOCK pInterface, PCRTRANGE paRanges, unsigned cRanges));
    10461032} PDMIBLOCK;
    10471033/** PDMIBLOCK interface ID. */
     
    13411327     * @thread  Any thread.
    13421328     */
    1343     DECLR3CALLBACKMEMBER(int, pfnDiscard,(PPDMIMEDIA pInterface, PPDMRANGE paRanges, unsigned cRanges));
     1329    DECLR3CALLBACKMEMBER(int, pfnDiscard,(PPDMIMEDIA pInterface, PCRTRANGE paRanges, unsigned cRanges));
    13441330
    13451331} PDMIMEDIA;
     
    15251511    DECLR3CALLBACKMEMBER(int, pfnStartFlush,(PPDMIBLOCKASYNC pInterface, void *pvUser));
    15261512
     1513    /**
     1514     * Discards the given range.
     1515     *
     1516     * @returns VBox status code.
     1517     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     1518     * @param   paRanges        Array of ranges to discard.
     1519     * @param   cRanges         Number of entries in the array.
     1520     * @param   pvUser          User argument which is returned in completion callback.
     1521     * @thread  Any thread.
     1522     */
     1523    DECLR3CALLBACKMEMBER(int, pfnStartDiscard,(PPDMIBLOCKASYNC pInterface, PCRTRANGE paRanges, unsigned cRanges, void *pvUser));
     1524
    15271525} PDMIBLOCKASYNC;
    15281526/** PDMIBLOCKASYNC interface ID. */
    1529 #define PDMIBLOCKASYNC_IID                      "78302d0d-4978-498c-be3c-8989cb5ff5c8"
     1527#define PDMIBLOCKASYNC_IID                      "a921dd96-1748-4ecd-941e-d5f3cd4c8fe4"
    15301528
    15311529
     
    15991597    DECLR3CALLBACKMEMBER(int, pfnStartFlush,(PPDMIMEDIAASYNC pInterface, void *pvUser));
    16001598
     1599    /**
     1600     * Discards the given range.
     1601     *
     1602     * @returns VBox status code.
     1603     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     1604     * @param   paRanges        Array of ranges to discard.
     1605     * @param   cRanges         Number of entries in the array.
     1606     * @param   pvUser          User argument which is returned in completion callback.
     1607     * @thread  Any thread.
     1608     */
     1609    DECLR3CALLBACKMEMBER(int, pfnStartDiscard,(PPDMIMEDIAASYNC pInterface, PCRTRANGE paRanges, unsigned cRanges, void *pvUser));
     1610
    16011611} PDMIMEDIAASYNC;
    16021612/** PDMIMEDIAASYNC interface ID. */
    1603 #define PDMIMEDIAASYNC_IID                      "3553227d-714d-4d28-b993-59f4e671588e"
     1613#define PDMIMEDIAASYNC_IID                      "4be209d3-ccb5-4297-82fe-7d8018bc6ab4"
    16041614
    16051615
  • trunk/include/VBox/vscsi.h

    r38680 r38878  
    9595typedef VSCSILUNTYPE *PVSCSILUNTYPE;
    9696
    97 /**
    98  * Range descriptor.
    99  */
    100 typedef struct VSCSIRANGE
    101 {
    102     /** Start offset. */
    103     uint64_t offStart;
    104     /** Size of the range. */
    105     size_t   cbRange;
    106 } VSCSIRANGE;
    107 /** Pointer to a range descriptor. */
    108 typedef VSCSIRANGE *PVSCSIRANGE;
    109 
    11097/** The LUN can handle the UNMAP command. */
    11198#define VSCSI_LUN_FEATURE_UNMAP          RT_BIT(0)
     
    326313 * @param   pcRanges       Where to store the number of ranges on success.
    327314 */
    328 VBOXDDU_DECL(int) VSCSIIoReqUnmapParamsGet(VSCSIIOREQ hVScsiIoReq, PVSCSIRANGE *ppaRanges,
     315VBOXDDU_DECL(int) VSCSIIoReqUnmapParamsGet(VSCSIIOREQ hVScsiIoReq, PCRTRANGE *ppaRanges,
    329316                                           unsigned *pcRanges);
    330317
  • trunk/src/VBox/Devices/Storage/DevAHCI.cpp

    r38838 r38878  
    329329    PFNAHCIPOSTPROCESS         pfnPostProcess;
    330330    /** Pointer to the array of PDM ranges. */
    331     PPDMRANGE                  paRanges;
     331    PRTRANGE                   paRanges;
    332332    /** Number of entries in the array. */
    333333    unsigned                   cRanges;
     
    30763076    p[67] = RT_H2LE_U16(120); /* minimum PIO cycle time without flow control */
    30773077    p[68] = RT_H2LE_U16(120); /* minimum PIO cycle time with IORDY flow control */
    3078     if (pAhciPort->pDrvBlock->pfnDiscard)
     3078    if (   pAhciPort->pDrvBlock->pfnDiscard
     3079        || ( pAhciPort->fAsyncInterface
     3080            && pAhciPort->pDrvBlockAsync->pfnStartDiscard))
    30793081    {
    30803082        p[80] = RT_H2LE_U16(0x1f0); /* support everything up to ATA/ATAPI-8 ACS */
     
    31013103        p[217] = RT_H2LE_U16(1); /* Non-rotational medium */
    31023104
    3103     if (pAhciPort->pDrvBlock->pfnDiscard) /** @todo: Set bit 14 in word 69 too? (Deterministic read after TRIM). */
     3105    if (   pAhciPort->pDrvBlock->pfnDiscard
     3106        || (   pAhciPort->fAsyncInterface
     3107            && pAhciPort->pDrvBlockAsync->pfnStartDiscard)) /** @todo: Set bit 14 in word 69 too? (Deterministic read after TRIM). */
    31043108        p[169] = RT_H2LE_U16(1); /* DATA SET MANAGEMENT command supported. */
    31053109
     
    53485352    pAhciPortTaskState->paSGEntries[0].u.temp.pvBuf = pAhciPortTaskState->pvBufferUnaligned;
    53495353
    5350     if (pAhciPortTaskState->enmTxDir == AHCITXDIR_WRITE)
     5354    if (   pAhciPortTaskState->enmTxDir == AHCITXDIR_WRITE
     5355        || pAhciPortTaskState->enmTxDir == AHCITXDIR_TRIM)
    53515356        ahciCopyFromSGListIntoBuffer(pDevIns, &pAhciPortTaskState->paSGEntries[0]);
    53525357
     
    60766081
    60776082/**
    6078  * Complete a data transfer task by freeing all occupied resources
    6079  * and notifying the guest.
    6080  *
    6081  * @returns VBox status code
    6082  *
    6083  * @param pAhciPort             Pointer to the port where to request completed.
    6084  * @param pAhciPortTaskState    Pointer to the task which finished.
    6085  * @param rcReq                 IPRT status code of the completed request.
    6086  */
    6087 static int ahciTransferComplete(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState, int rcReq)
    6088 {
    6089     bool fXchg = false;
    6090     bool fRedo = false;
    6091 
    6092     ASMAtomicCmpXchgSize(&pAhciPortTaskState->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE, fXchg);
    6093 
    6094     if (fXchg)
    6095     {
    6096         /* Free system resources occupied by the scatter gather list. */
    6097         if (pAhciPortTaskState->enmTxDir != AHCITXDIR_FLUSH)
    6098             ahciScatterGatherListDestroy(pAhciPort, pAhciPortTaskState);
    6099 
    6100         if (pAhciPortTaskState->enmTxDir == AHCITXDIR_READ)
    6101         {
    6102             STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesRead, pAhciPortTaskState->cbTransfer);
    6103             pAhciPort->Led.Actual.s.fReading = 0;
    6104         }
    6105         else if (pAhciPortTaskState->enmTxDir == AHCITXDIR_WRITE)
    6106         {
    6107             STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesWritten, pAhciPortTaskState->cbTransfer);
    6108             pAhciPort->Led.Actual.s.fWriting = 0;
    6109         }
    6110 
    6111         if (RT_FAILURE(rcReq))
    6112         {
    6113             /* Log the error. */
    6114             if (pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS)
    6115             {
    6116                 if (pAhciPortTaskState->enmTxDir == AHCITXDIR_FLUSH)
    6117                     LogRel(("AHCI#%u: Flush returned rc=%Rrc\n",
    6118                             pAhciPort->iLUN, rcReq));
    6119                 else
    6120                     LogRel(("AHCI#%u: %s at offset %llu (%u bytes left) returned rc=%Rrc\n",
    6121                             pAhciPort->iLUN,
    6122                             pAhciPortTaskState->enmTxDir == AHCITXDIR_READ
    6123                             ? "Read"
    6124                             : "Write",
    6125                             pAhciPortTaskState->uOffset,
    6126                             pAhciPortTaskState->cbTransfer, rcReq));
    6127             }
    6128 
    6129             fRedo = ahciIsRedoSetWarning(pAhciPort, rcReq);
    6130             if (!fRedo)
    6131             {
    6132                 pAhciPortTaskState->cmdHdr.u32PRDBC = 0;
    6133                 pAhciPortTaskState->uATARegError = ID_ERR;
    6134                 pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
    6135                 ASMAtomicCmpXchgPtr(&pAhciPort->pTaskErr, pAhciPortTaskState, NULL);
    6136             }
    6137             else
    6138                 ASMAtomicOrU32(&pAhciPort->u32TasksNew, (1 << pAhciPortTaskState->uTag));
    6139         }
    6140         else
    6141         {
    6142             pAhciPortTaskState->cmdHdr.u32PRDBC = pAhciPortTaskState->cbTransfer;
    6143 
    6144             pAhciPortTaskState->uATARegError = 0;
    6145             pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
    6146 
    6147             /* Write updated command header into memory of the guest. */
    6148             PDMDevHlpPhysWrite(pAhciPort->CTX_SUFF(pDevIns), pAhciPortTaskState->GCPhysCmdHdrAddr,
    6149                                &pAhciPortTaskState->cmdHdr, sizeof(CmdHdr));
    6150         }
    6151 
    6152         /* Add the task to the cache. */
    6153         ASMAtomicWritePtr(&pAhciPort->aCachedTasks[pAhciPortTaskState->uTag], pAhciPortTaskState);
    6154         ASMAtomicDecU32(&pAhciPort->cTasksActive);
    6155 
    6156         if (!fRedo)
    6157         {
    6158             if (pAhciPortTaskState->fQueued)
    6159             {
    6160                 if (RT_SUCCESS(rcReq) && !ASMAtomicReadPtrT(&pAhciPort->pTaskErr, PAHCIPORTTASKSTATE))
    6161                     ASMAtomicOrU32(&pAhciPort->u32QueuedTasksFinished, (1 << pAhciPortTaskState->uTag));
    6162 
    6163                 /*
    6164                  * Always raise an interrupt after task completion; delaying
    6165                  * this (interrupt coalescing) increases latency and has a significant
    6166                  * impact on performance (see #5071)
    6167                  */
    6168                 ahciSendSDBFis(pAhciPort, 0, true);
    6169             }
    6170             else
    6171                 ahciSendD2HFis(pAhciPort, pAhciPortTaskState, pAhciPortTaskState->cmdFis, true);
    6172         }
    6173     }
    6174     else
    6175     {
    6176         /*
    6177          * Task was canceled, do the cleanup but DO NOT access the guest memory!
    6178          * The guest might use it for other things now because it doesn't know about that task anymore.
    6179          */
    6180         AssertMsg(pAhciPortTaskState->enmTxState == AHCITXSTATE_CANCELED,
    6181                   ("Task is not active but wasn't canceled!\n"));
    6182 
    6183         ahciScatterGatherListFree(pAhciPortTaskState);
    6184 
    6185         /* Leave a log message about the canceled request. */
    6186         if (pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS)
    6187         {
    6188             if (pAhciPortTaskState->enmTxDir == AHCITXDIR_FLUSH)
    6189                 LogRel(("AHCI#%u: Canceled flush returned rc=%Rrc\n",
    6190                         pAhciPort->iLUN, rcReq));
    6191             else
    6192                 LogRel(("AHCI#%u: Canceled %s at offset %llu (%u bytes left) returned rc=%Rrc\n",
    6193                         pAhciPort->iLUN,
    6194                         pAhciPortTaskState->enmTxDir == AHCITXDIR_READ
    6195                         ? "read"
    6196                         : "write",
    6197                         pAhciPortTaskState->uOffset,
    6198                         pAhciPortTaskState->cbTransfer, rcReq));
    6199          }
    6200 
    6201         /* Finally free the task state structure because it is completely unused now. */
    6202         RTMemFree(pAhciPortTaskState);
    6203     }
    6204 
    6205     return VINF_SUCCESS;
    6206 }
    6207 
    6208 /**
    6209  * Notification callback for a completed transfer.
    6210  *
    6211  * @returns VBox status code.
    6212  * @param   pInterface   Pointer to the interface.
    6213  * @param   pvUser       User data.
    6214  * @param   rcReq        IPRT Status code of the completed request.
    6215  */
    6216 static DECLCALLBACK(int) ahciTransferCompleteNotify(PPDMIBLOCKASYNCPORT pInterface, void *pvUser, int rcReq)
    6217 {
    6218     PAHCIPort pAhciPort = PDMIBLOCKASYNCPORT_2_PAHCIPORT(pInterface);
    6219     PAHCIPORTTASKSTATE pAhciPortTaskState = (PAHCIPORTTASKSTATE)pvUser;
    6220 
    6221     ahciLog(("%s: pInterface=%p pvUser=%p uTag=%u\n",
    6222              __FUNCTION__, pInterface, pvUser, pAhciPortTaskState->uTag));
    6223 
    6224     int rc = ahciTransferComplete(pAhciPort, pAhciPortTaskState, rcReq);
    6225 
    6226     if (pAhciPort->cTasksActive == 0 && pAhciPort->pAhciR3->fSignalIdle)
    6227         PDMDevHlpAsyncNotificationCompleted(pAhciPort->pDevInsR3);
    6228     return rc;
    6229 }
    6230 
    6231 /**
    62326083 * Creates the array of ranges to trim.
    62336084 *
     
    62776128    AssertReturn(cRanges != 0, VERR_INVALID_PARAMETER);
    62786129
    6279     pAhciPortTaskState->paRanges = (PPDMRANGE)RTMemAllocZ(sizeof(PDMRANGE) * cRanges);
     6130    pAhciPortTaskState->paRanges = (PRTRANGE)RTMemAllocZ(sizeof(RTRANGE) * cRanges);
    62806131    if (pAhciPortTaskState->paRanges)
    62816132    {
     
    63096160}
    63106161
     6162/**
     6163 * Destroy the trim range list.
     6164 *
     6165 * @returns nothing.
     6166 * @param   pAhciPortTaskState    The task state.
     6167 */
    63116168static void ahciTrimRangesDestroy(PAHCIPORTTASKSTATE pAhciPortTaskState)
    63126169{
    63136170    RTMemFree(pAhciPortTaskState->paRanges);
     6171}
     6172
     6173/**
     6174 * Complete a data transfer task by freeing all occupied resources
     6175 * and notifying the guest.
     6176 *
     6177 * @returns VBox status code
     6178 *
     6179 * @param pAhciPort             Pointer to the port where to request completed.
     6180 * @param pAhciPortTaskState    Pointer to the task which finished.
     6181 * @param rcReq                 IPRT status code of the completed request.
     6182 */
     6183static int ahciTransferComplete(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState, int rcReq)
     6184{
     6185    bool fXchg = false;
     6186    bool fRedo = false;
     6187
     6188    ASMAtomicCmpXchgSize(&pAhciPortTaskState->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE, fXchg);
     6189
     6190    if (fXchg)
     6191    {
     6192        /* Free system resources occupied by the scatter gather list. */
     6193        if (pAhciPortTaskState->enmTxDir != AHCITXDIR_FLUSH)
     6194            ahciScatterGatherListDestroy(pAhciPort, pAhciPortTaskState);
     6195
     6196        if (pAhciPortTaskState->enmTxDir == AHCITXDIR_READ)
     6197        {
     6198            STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesRead, pAhciPortTaskState->cbTransfer);
     6199            pAhciPort->Led.Actual.s.fReading = 0;
     6200        }
     6201        else if (pAhciPortTaskState->enmTxDir == AHCITXDIR_WRITE)
     6202        {
     6203            STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesWritten, pAhciPortTaskState->cbTransfer);
     6204            pAhciPort->Led.Actual.s.fWriting = 0;
     6205        }
     6206        else if (pAhciPortTaskState->enmTxDir == AHCITXDIR_TRIM)
     6207        {
     6208            ahciTrimRangesDestroy(pAhciPortTaskState);
     6209            pAhciPort->Led.Actual.s.fWriting = 0;
     6210        }
     6211
     6212        if (RT_FAILURE(rcReq))
     6213        {
     6214            /* Log the error. */
     6215            if (pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS)
     6216            {
     6217                if (pAhciPortTaskState->enmTxDir == AHCITXDIR_FLUSH)
     6218                    LogRel(("AHCI#%u: Flush returned rc=%Rrc\n",
     6219                            pAhciPort->iLUN, rcReq));
     6220                else if (pAhciPortTaskState->enmTxDir == AHCITXDIR_TRIM)
     6221                    LogRel(("AHCI#%u: Trim returned rc=%Rrc\n",
     6222                            pAhciPort->iLUN, rcReq));
     6223                else
     6224                    LogRel(("AHCI#%u: %s at offset %llu (%u bytes left) returned rc=%Rrc\n",
     6225                            pAhciPort->iLUN,
     6226                            pAhciPortTaskState->enmTxDir == AHCITXDIR_READ
     6227                            ? "Read"
     6228                            : "Write",
     6229                            pAhciPortTaskState->uOffset,
     6230                            pAhciPortTaskState->cbTransfer, rcReq));
     6231            }
     6232
     6233            fRedo = ahciIsRedoSetWarning(pAhciPort, rcReq);
     6234            if (!fRedo)
     6235            {
     6236                pAhciPortTaskState->cmdHdr.u32PRDBC = 0;
     6237                pAhciPortTaskState->uATARegError = ID_ERR;
     6238                pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
     6239                ASMAtomicCmpXchgPtr(&pAhciPort->pTaskErr, pAhciPortTaskState, NULL);
     6240            }
     6241            else
     6242                ASMAtomicOrU32(&pAhciPort->u32TasksNew, (1 << pAhciPortTaskState->uTag));
     6243        }
     6244        else
     6245        {
     6246            pAhciPortTaskState->cmdHdr.u32PRDBC = pAhciPortTaskState->cbTransfer;
     6247
     6248            pAhciPortTaskState->uATARegError = 0;
     6249            pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
     6250
     6251            /* Write updated command header into memory of the guest. */
     6252            PDMDevHlpPhysWrite(pAhciPort->CTX_SUFF(pDevIns), pAhciPortTaskState->GCPhysCmdHdrAddr,
     6253                               &pAhciPortTaskState->cmdHdr, sizeof(CmdHdr));
     6254        }
     6255
     6256        /* Add the task to the cache. */
     6257        ASMAtomicWritePtr(&pAhciPort->aCachedTasks[pAhciPortTaskState->uTag], pAhciPortTaskState);
     6258        ASMAtomicDecU32(&pAhciPort->cTasksActive);
     6259
     6260        if (!fRedo)
     6261        {
     6262            if (pAhciPortTaskState->fQueued)
     6263            {
     6264                if (RT_SUCCESS(rcReq) && !ASMAtomicReadPtrT(&pAhciPort->pTaskErr, PAHCIPORTTASKSTATE))
     6265                    ASMAtomicOrU32(&pAhciPort->u32QueuedTasksFinished, (1 << pAhciPortTaskState->uTag));
     6266
     6267                /*
     6268                 * Always raise an interrupt after task completion; delaying
     6269                 * this (interrupt coalescing) increases latency and has a significant
     6270                 * impact on performance (see #5071)
     6271                 */
     6272                ahciSendSDBFis(pAhciPort, 0, true);
     6273            }
     6274            else
     6275                ahciSendD2HFis(pAhciPort, pAhciPortTaskState, pAhciPortTaskState->cmdFis, true);
     6276        }
     6277    }
     6278    else
     6279    {
     6280        /*
     6281         * Task was canceled, do the cleanup but DO NOT access the guest memory!
     6282         * The guest might use it for other things now because it doesn't know about that task anymore.
     6283         */
     6284        AssertMsg(pAhciPortTaskState->enmTxState == AHCITXSTATE_CANCELED,
     6285                  ("Task is not active but wasn't canceled!\n"));
     6286
     6287        ahciScatterGatherListFree(pAhciPortTaskState);
     6288
     6289        /* Leave a log message about the canceled request. */
     6290        if (pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS)
     6291        {
     6292            if (pAhciPortTaskState->enmTxDir == AHCITXDIR_FLUSH)
     6293                LogRel(("AHCI#%u: Canceled flush returned rc=%Rrc\n",
     6294                        pAhciPort->iLUN, rcReq));
     6295            else
     6296                LogRel(("AHCI#%u: Canceled %s at offset %llu (%u bytes left) returned rc=%Rrc\n",
     6297                        pAhciPort->iLUN,
     6298                        pAhciPortTaskState->enmTxDir == AHCITXDIR_READ
     6299                        ? "read"
     6300                        : "write",
     6301                        pAhciPortTaskState->uOffset,
     6302                        pAhciPortTaskState->cbTransfer, rcReq));
     6303         }
     6304
     6305        /* Finally free the task state structure because it is completely unused now. */
     6306        RTMemFree(pAhciPortTaskState);
     6307    }
     6308
     6309    return VINF_SUCCESS;
     6310}
     6311
     6312/**
     6313 * Notification callback for a completed transfer.
     6314 *
     6315 * @returns VBox status code.
     6316 * @param   pInterface   Pointer to the interface.
     6317 * @param   pvUser       User data.
     6318 * @param   rcReq        IPRT Status code of the completed request.
     6319 */
     6320static DECLCALLBACK(int) ahciTransferCompleteNotify(PPDMIBLOCKASYNCPORT pInterface, void *pvUser, int rcReq)
     6321{
     6322    PAHCIPort pAhciPort = PDMIBLOCKASYNCPORT_2_PAHCIPORT(pInterface);
     6323    PAHCIPORTTASKSTATE pAhciPortTaskState = (PAHCIPORTTASKSTATE)pvUser;
     6324
     6325    ahciLog(("%s: pInterface=%p pvUser=%p uTag=%u\n",
     6326             __FUNCTION__, pInterface, pvUser, pAhciPortTaskState->uTag));
     6327
     6328    int rc = ahciTransferComplete(pAhciPort, pAhciPortTaskState, rcReq);
     6329
     6330    if (pAhciPort->cTasksActive == 0 && pAhciPort->pAhciR3->fSignalIdle)
     6331        PDMDevHlpAsyncNotificationCompleted(pAhciPort->pDevInsR3);
     6332    return rc;
    63146333}
    63156334
     
    65906609        case ATA_DATA_SET_MANAGEMENT:
    65916610        {
    6592             if (pAhciPort->pDrvBlock->pfnDiscard)
     6611            if (   pAhciPort->pDrvBlock->pfnDiscard
     6612                || (   pAhciPort->fAsyncInterface
     6613                    && pAhciPort->pDrvBlockAsync->pfnStartDiscard))
    65936614            {
    65946615                rc = AHCITXDIR_TRIM;
     
    68066827                    if (enmTxDir != AHCITXDIR_FLUSH)
    68076828                    {
     6829                        bool fReadonly = true;
    68086830                        STAM_REL_COUNTER_INC(&pAhciPort->StatDMA);
    68096831
    6810                         rc = ahciScatterGatherListCreate(pAhciPort, pAhciPortTaskState, (enmTxDir == AHCITXDIR_READ) ? false : true);
     6832                        if (   enmTxDir == AHCITXDIR_WRITE
     6833                            || enmTxDir == AHCITXDIR_TRIM)
     6834                            fReadonly = false;
     6835
     6836                        rc = ahciScatterGatherListCreate(pAhciPort, pAhciPortTaskState, fReadonly);
    68116837                        if (RT_FAILURE(rc))
    68126838                            AssertMsgFailed(("%s: Failed to process command %Rrc\n", __FUNCTION__, rc));
     
    68176843                        rc = pAhciPort->pDrvBlockAsync->pfnStartFlush(pAhciPort->pDrvBlockAsync,
    68186844                                                                      pAhciPortTaskState);
     6845                    }
     6846                    else if (enmTxDir == AHCITXDIR_TRIM)
     6847                    {
     6848                        rc = ahciTrimRangesCreate(pAhciPort, pAhciPortTaskState);
     6849                        if (RT_SUCCESS(rc))
     6850                        {
     6851                            pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
     6852                            rc = pAhciPort->pDrvBlockAsync->pfnStartDiscard(pAhciPort->pDrvBlockAsync, pAhciPortTaskState->paRanges,
     6853                                                                            pAhciPortTaskState->cRanges, pAhciPortTaskState);
     6854                        }
    68196855                    }
    68206856                    else if (enmTxDir == AHCITXDIR_READ)
  • trunk/src/VBox/Devices/Storage/DrvBlock.cpp

    r38622 r38878  
    286286}
    287287
    288 static DECLCALLBACK(int) drvblockDiscard(PPDMIBLOCK pInterface, PPDMRANGE paRanges, unsigned cRanges)
     288static DECLCALLBACK(int) drvblockDiscard(PPDMIBLOCK pInterface, PCRTRANGE paRanges, unsigned cRanges)
    289289{
    290290    PDRVBLOCK pThis = PDMIBLOCK_2_DRVBLOCK(pInterface);
     
    337337
    338338
    339 /** @copydoc PDMIBLOCKASYNC::pfnStartFLush */
     339/** @copydoc PDMIBLOCKASYNC::pfnStartFlush */
    340340static DECLCALLBACK(int) drvblockAsyncFlushStart(PPDMIBLOCKASYNC pInterface, void *pvUser)
    341341{
     
    359359
    360360    return rc;
     361}
     362
     363
     364/** @copydoc PDMIBLOCKASYNC::pfnStartDiscard */
     365static DECLCALLBACK(int) drvblockStartDiscard(PPDMIBLOCKASYNC pInterface, PCRTRANGE paRanges, unsigned cRanges, void *pvUser)
     366{
     367    PDRVBLOCK pThis = PDMIBLOCKASYNC_2_DRVBLOCK(pInterface);
     368
     369    /*
     370     * Check the state.
     371     */
     372    if (!pThis->pDrvMediaAsync)
     373    {
     374        AssertMsgFailed(("Invalid state! Not mounted!\n"));
     375        return VERR_PDM_MEDIA_NOT_MOUNTED;
     376    }
     377
     378    return pThis->pDrvMediaAsync->pfnStartDiscard(pThis->pDrvMediaAsync, paRanges, cRanges, pvUser);
    361379}
    362380
     
    976994                                N_("No media or async media interface below"));
    977995
     996    /* Try to get the optional async interface. */
     997    pThis->pDrvMediaAsync = PDMIBASE_QUERY_INTERFACE(pBase, PDMIMEDIAASYNC);
     998
    978999    if (pThis->pDrvMedia->pfnDiscard)
    9791000        pThis->IBlock.pfnDiscard = drvblockDiscard;
    9801001
    981     /* Try to get the optional async interface. */
    982     pThis->pDrvMediaAsync = PDMIBASE_QUERY_INTERFACE(pBase, PDMIMEDIAASYNC);
     1002    if (   pThis->pDrvMediaAsync
     1003        && pThis->pDrvMediaAsync->pfnStartDiscard)
     1004        pThis->IBlockAsync.pfnStartDiscard = drvblockStartDiscard;
    9831005
    9841006    if (RTUuidIsNull(&pThis->Uuid))
  • trunk/src/VBox/Devices/Storage/DrvDiskIntegrity.cpp

    r38670 r38878  
    5151    DRVDISKAIOTXDIR_WRITE,
    5252    /** Flush */
    53     DRVDISKAIOTXDIR_FLUSH
     53    DRVDISKAIOTXDIR_FLUSH,
     54    /** Discard */
     55    DRVDISKAIOTXDIR_DISCARD
    5456} DRVDISKAIOTXDIR;
    5557
     
    7981    /** I/O log entry if configured. */
    8082    VDIOLOGENT      hIoLogEntry;
     83    /** Ranges to discard. */
     84    PCRTRANGE       paRanges;
     85    /** Number of ranges. */
     86    unsigned        cRanges;
    8187} DRVDISKAIOREQ, *PDRVDISKAIOREQ;
    8288
     
    941947}
    942948
     949/** @copydoc PDMIMEDIAASYNC::pfnStartDiscard */
     950static DECLCALLBACK(int) drvdiskintStartDiscard(PPDMIMEDIA pInterface, PPDMRANGE paRanges, unsigned cRanges, void *pvUser)
     951{
     952    int rc = VINF_SUCCESS;
     953    VDIOLOGENT hIoLogEntry;
     954    PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
     955    PDRVDISKAIOREQ pIoReq = drvdiskintIoReqAlloc(DRVDISKAIOTXDIR_DISCARD, 0, NULL, 0, 0, pvUser);
     956    AssertPtr(pIoReq);
     957
     958    pIoReq->paRanges = paRanges;
     959    pIoReq->cRanges  = cRanges;
     960
     961    if (pThis->hIoLogger)
     962    {
     963        rc = VDDbgIoLogStartDiscard(pThis->hIoLogger, true, (PVDRANGE)paRanges, cRanges, &hIoLogEntry);
     964        AssertRC(rc);
     965    }
     966
     967    rc = pThis->pDrvMedia->pfnStartDiscard(pThis->pDrvMedia, paRanges, cRanges, pIoReq);
     968
     969    if (rc == VINF_VD_ASYNC_IO_FINISHED)
     970    {
     971        if (pThis->hIoLogger)
     972        {
     973            int rc2 = VDDbgIoLogComplete(pThis->hIoLogger, pIoReq->hIoLogEntry, VINF_SUCCESS, NULL);
     974            AssertRC(rc2);
     975        }
     976
     977        RTMemFree(pIoReq);
     978    }
     979    else if (RT_FAILURE(rc) && rc != VERR_VD_ASYNC_IO_IN_PROGRESS)
     980        RTMemFree(pIoReq);
     981
     982    return rc;
     983}
     984
    943985/** @copydoc PDMIMEDIA::pfnFlush */
    944986static DECLCALLBACK(int) drvdiskintFlush(PPDMIMEDIA pInterface)
     
    10691111        else if (pIoReq->enmTxDir == DRVDISKAIOTXDIR_WRITE)
    10701112            rc = drvdiskintWriteRecord(pThis, pIoReq->paSeg, pIoReq->cSeg, pIoReq->off, pIoReq->cbTransfer);
     1113        else if (pIoReq->enmTxDir == DRVDISKAIOTXDIR_DISCARD)
     1114            rc = drvdiskintDiscardRecords(pThis, paRanges, cRanges);
    10711115        else
    10721116            AssertMsg(pIoReq->enmTxDir == DRVDISKAIOTXDIR_FLUSH, ("Huh?\n"));
     
    12761320    if (pThis->pDrvMedia->pfnDiscard)
    12771321        pThis->IMedia.pfnDiscard = drvdiskintDiscard;
     1322    if (   pThis->pDrvMediaAsync
     1323        && pThis->pDrvMediaAsync->pfnStartDiscard)
     1324        pThis->IMediaAsync.pfnStartDiscard = drvdiskintStartDiscard;
    12781325
    12791326    if (pThis->fCheckConsistency)
  • trunk/src/VBox/Devices/Storage/DrvSCSI.cpp

    r38680 r38878  
    192192        case VSCSIIOREQTXDIR_UNMAP:
    193193        {
    194             PVSCSIRANGE paRanges;
     194            PCRTRANGE paRanges;
    195195            unsigned cRanges;
    196196
     
    199199
    200200            pThis->pLed->Asserted.s.fWriting = pThis->pLed->Actual.s.fWriting = 1;
    201             rc = pThis->pDrvBlock->pfnDiscard(pThis->pDrvBlock, (PPDMRANGE)paRanges, cRanges);
     201            rc = pThis->pDrvBlock->pfnDiscard(pThis->pDrvBlock, paRanges, cRanges);
    202202            pThis->pLed->Actual.s.fWriting = 0;
    203203            break;
     
    234234    if (enmTxDir == VSCSIIOREQTXDIR_READ)
    235235        pThis->pLed->Actual.s.fReading = 0;
    236     else if (enmTxDir == VSCSIIOREQTXDIR_WRITE)
     236    else if (   enmTxDir == VSCSIIOREQTXDIR_WRITE
     237             || enmTxDir == VSCSIIOREQTXDIR_UNMAP)
    237238        pThis->pLed->Actual.s.fWriting = 0;
    238239    else
     
    299300                    && pThis->cErrors++ < MAX_LOG_REL_ERRORS)
    300301                    LogRel(("SCSI#%u: Flush returned rc=%Rrc\n",
     302                            pThis->pDrvIns->iInstance, rc));
     303                break;
     304            }
     305            case VSCSIIOREQTXDIR_UNMAP:
     306            {
     307                PCRTRANGE paRanges;
     308                unsigned cRanges;
     309
     310                rc = VSCSIIoReqUnmapParamsGet(hVScsiIoReq, &paRanges, &cRanges);
     311                AssertRC(rc);
     312
     313                pThis->pLed->Asserted.s.fWriting = pThis->pLed->Actual.s.fWriting = 1;
     314                rc = pThis->pDrvBlockAsync->pfnStartDiscard(pThis->pDrvBlockAsync, paRanges, cRanges, hVScsiIoReq);
     315                if (   RT_FAILURE(rc)
     316                    && rc != VERR_VD_ASYNC_IO_IN_PROGRESS
     317                    && pThis->cErrors++ < MAX_LOG_REL_ERRORS)
     318                    LogRel(("SCSI#%u: Discard returned rc=%Rrc\n",
    301319                            pThis->pDrvIns->iInstance, rc));
    302320                break;
     
    396414    *pfFeatures = 0;
    397415
    398     if (pThis->pDrvBlock->pfnDiscard)
     416    if (   pThis->pDrvBlock->pfnDiscard
     417        || (   pThis->pDrvBlockAsync
     418            && pThis->pDrvBlockAsync->pfnStartDiscard))
    399419        *pfFeatures |= VSCSI_LUN_FEATURE_UNMAP;
    400420
     
    886906    else
    887907        LogRel(("SCSI#%d: using async I/O\n", pDrvIns->iInstance));
     908
     909    if (   pThis->pDrvBlock->pfnDiscard
     910        || (   pThis->pDrvBlockAsync
     911            && pThis->pDrvBlockAsync->pfnStartDiscard))
     912        LogRel(("SCSI#%d: Enabled UNMAP support\n"));
    888913
    889914    return VINF_SUCCESS;
  • trunk/src/VBox/Devices/Storage/DrvVD.cpp

    r38622 r38878  
    560560    PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
    561561
    562     int rc = drvvdAsyncIOFlushSync(pvUser, pStorage);
    563     if (RT_SUCCESS(rc))
    564         rc = PDMR3AsyncCompletionEpSetSize(pStorageBackend->pEndpoint, cbSize);
    565 
    566     return rc;
     562    return PDMR3AsyncCompletionEpSetSize(pStorageBackend->pEndpoint, cbSize);
    567563}
    568564
     
    16741670}
    16751671
    1676 static DECLCALLBACK(int) drvvdDiscard(PPDMIMEDIA pInterface, PPDMRANGE paRanges, unsigned cRanges)
     1672static DECLCALLBACK(int) drvvdDiscard(PPDMIMEDIA pInterface, PCRTRANGE paRanges, unsigned cRanges)
    16771673{
    16781674    LogFlowFunc(("\n"));
    16791675    PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
    16801676
    1681     /** @todo: Fix the cast properly without allocating temporary memory (maybe move the type to IPRT). */
    1682     int rc = VDDiscardRanges(pThis->pDisk, (PVDRANGE)paRanges, cRanges);
     1677    int rc = VDDiscardRanges(pThis->pDisk, paRanges, cRanges);
    16831678    LogFlowFunc(("returns %Rrc\n", rc));
    16841679    return rc;
     
    17731768    {
    17741769        rc = PDMR3BlkCacheFlush(pThis->pBlkCache, pvUser);
     1770        if (rc == VINF_AIO_TASK_PENDING)
     1771            rc = VERR_VD_ASYNC_IO_IN_PROGRESS;
     1772        else if (rc == VINF_SUCCESS)
     1773            rc = VINF_VD_ASYNC_IO_FINISHED;
     1774    }
     1775    LogFlowFunc(("returns %Rrc\n", rc));
     1776    return rc;
     1777}
     1778
     1779static DECLCALLBACK(int) drvvdStartDiscard(PPDMIMEDIAASYNC pInterface, PCRTRANGE paRanges,
     1780                                           unsigned cRanges, void *pvUser)
     1781{
     1782    int rc = VINF_SUCCESS;
     1783    PVBOXDISK pThis = PDMIMEDIAASYNC_2_VBOXDISK(pInterface);
     1784
     1785    LogFlowFunc(("paRanges=%#p cRanges=%u pvUser=%#p\n",
     1786                 paRanges, cRanges, pvUser));
     1787
     1788    if (!pThis->pBlkCache)
     1789        rc = VDAsyncDiscardRanges(pThis->pDisk, paRanges, cRanges, drvvdAsyncReqComplete,
     1790                                  pThis, pvUser);
     1791    else
     1792    {
     1793        rc = PDMR3BlkCacheDiscard(pThis->pBlkCache, paRanges, cRanges, pvUser);
    17751794        if (rc == VINF_AIO_TASK_PENDING)
    17761795            rc = VERR_VD_ASYNC_IO_IN_PROGRESS;
     
    18181837            rc = VERR_INVALID_PARAMETER;
    18191838    }
     1839
     1840    if (rc == VINF_VD_ASYNC_IO_FINISHED)
     1841        PDMR3BlkCacheIoXferComplete(pThis->pBlkCache, hIoXfer, VINF_SUCCESS);
     1842    else if (RT_FAILURE(rc) && rc != VERR_VD_ASYNC_IO_IN_PROGRESS)
     1843        PDMR3BlkCacheIoXferComplete(pThis->pBlkCache, hIoXfer, rc);
     1844
     1845    return VINF_SUCCESS;
     1846}
     1847
     1848/** @copydoc FNPDMBLKCACHEXFERENQUEUEDISCARDDRV */
     1849static int drvvdBlkCacheXferEnqueueDiscard(PPDMDRVINS pDrvIns, PCRTRANGE paRanges,
     1850                                           unsigned cRanges, PPDMBLKCACHEIOXFER hIoXfer)
     1851{
     1852    int rc = VINF_SUCCESS;
     1853    PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
     1854
     1855    rc = VDAsyncDiscardRanges(pThis->pDisk, paRanges, cRanges,
     1856                              drvvdAsyncReqComplete, pThis, hIoXfer);
    18201857
    18211858    if (rc == VINF_VD_ASYNC_IO_FINISHED)
     
    20762113    pThis->IMediaAsync.pfnStartWrite      = drvvdStartWrite;
    20772114    pThis->IMediaAsync.pfnStartFlush      = drvvdStartFlush;
     2115    pThis->IMediaAsync.pfnStartDiscard    = drvvdStartDiscard;
    20782116
    20792117    /* Initialize supported VD interfaces. */
     
    25752613
    25762614        if (!fDiscard)
     2615        {
    25772616            pThis->IMedia.pfnDiscard = NULL;
     2617            pThis->IMediaAsync.pfnStartDiscard = NULL;
     2618        }
    25782619
    25792620        if (RT_SUCCESS(rc))
     
    26662707    if (   fUseBlockCache
    26672708        && !pThis->fShareable
     2709        && !fDiscard
    26682710        && RT_SUCCESS(rc))
    26692711    {
     
    26952737                                             drvvdBlkCacheXferComplete,
    26962738                                             drvvdBlkCacheXferEnqueue,
     2739                                             drvvdBlkCacheXferEnqueueDiscard,
    26972740                                             pszId);
    26982741                if (rc == VERR_NOT_SUPPORTED)
  • trunk/src/VBox/Devices/Storage/VSCSI/VSCSIInternal.h

    r38680 r38878  
    149149        {
    150150            /** Array of ranges to unmap. */
    151             PVSCSIRANGE    paRanges;
     151            PRTRANGE       paRanges;
    152152            /** Number of ranges. */
    153153            unsigned       cRanges;
     
    335335 */
    336336int vscsiIoReqUnmapEnqueue(PVSCSILUNINT pVScsiLun, PVSCSIREQINT pVScsiReq,
    337                            PVSCSIRANGE paRanges, unsigned cRanges);
     337                           PRTRANGE paRanges, unsigned cRanges);
    338338
    339339/**
  • trunk/src/VBox/Devices/Storage/VSCSI/VSCSIIoReq.cpp

    r38680 r38878  
    8888
    8989int vscsiIoReqUnmapEnqueue(PVSCSILUNINT pVScsiLun, PVSCSIREQINT pVScsiReq,
    90                            PVSCSIRANGE paRanges, unsigned cRanges)
     90                           PRTRANGE paRanges, unsigned cRanges)
    9191{
    9292    int rc = VINF_SUCCESS;
     
    202202}
    203203
    204 VBOXDDU_DECL(int) VSCSIIoReqUnmapParamsGet(VSCSIIOREQ hVScsiIoReq, PVSCSIRANGE *ppaRanges,
     204VBOXDDU_DECL(int) VSCSIIoReqUnmapParamsGet(VSCSIIOREQ hVScsiIoReq, PCRTRANGE *ppaRanges,
    205205                                           unsigned *pcRanges)
    206206{
  • trunk/src/VBox/Devices/Storage/VSCSI/VSCSILunSbc.cpp

    r38702 r38878  
    447447                    if (cBlkDesc)
    448448                    {
    449                         PVSCSIRANGE paRanges;
    450 
    451                         paRanges = (PVSCSIRANGE)RTMemAllocZ(cBlkDesc * sizeof(PVSCSIRANGE));
     449                        PRTRANGE paRanges;
     450
     451                        paRanges = (PRTRANGE)RTMemAllocZ(cBlkDesc * sizeof(RTRANGE));
    452452                        if (paRanges)
    453453                        {
  • trunk/src/VBox/VMM/VMMR3/PDMDriver.cpp

    r38847 r38878  
    14291429                                                    PFNPDMBLKCACHEXFERCOMPLETEDRV pfnXferComplete,
    14301430                                                    PFNPDMBLKCACHEXFERENQUEUEDRV pfnXferEnqueue,
     1431                                                    PFNPDMBLKCACHEXFERENQUEUEDISCARDDRV pfnXferEnqueueDiscard,
    14311432                                                    const char *pcszId)
    14321433{
    14331434    PDMDRV_ASSERT_DRVINS(pDrvIns);
    14341435    return PDMR3BlkCacheRetainDriver(pDrvIns->Internal.s.pVMR3, pDrvIns, ppBlkCache,
    1435                                      pfnXferComplete, pfnXferEnqueue, pcszId);
     1436                                     pfnXferComplete, pfnXferEnqueue, pfnXferEnqueueDiscard, pcszId);
    14361437}
    14371438
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