VirtualBox

Changeset 63992 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Sep 25, 2016 5:58:56 PM (8 years ago)
Author:
vboxsync
Message:

VSCSI,DrvSCSI: Switch to PDMIMEDIAEX instead of using PDMIMEDIAASYNC

Location:
trunk/src/VBox/Devices/Storage
Files:
4 edited

Legend:

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

    r63562 r63992  
    4545 *
    4646 * @implements  PDMISCSICONNECTOR
    47  * @implements  PDMIMEDIAASYNCPORT
     47 * @implements  PDMIMEDIAEXPORT
    4848 * @implements  PDMIMOUNTNOTIFY
    4949 */
     
    5757    /** Pointer to the attached driver's block interface. */
    5858    PPDMIMEDIA              pDrvMedia;
    59     /** Pointer to the attached driver's async block interface. */
    60     PPDMIMEDIAASYNC         pDrvMediaAsync;
     59    /** Pointer to the attached driver's extended media interface. */
     60    PPDMIMEDIAEX            pDrvMediaEx;
    6161    /** Pointer to the attached driver's mount interface. */
    6262    PPDMIMOUNT              pDrvMount;
     
    6969    /** The media port interface. */
    7070    PDMIMEDIAPORT           IPort;
    71     /** The optional media async port interface. */
    72     PDMIMEDIAASYNCPORT      IPortAsync;
     71    /** The optional extended media port interface. */
     72    PDMIMEDIAEXPORT         IPortEx;
    7373    /** The mount notify interface. */
    7474    PDMIMOUNTNOTIFY         IMountNotify;
     
    8686    VSCSILUNIOCALLBACKS     VScsiIoCallbacks;
    8787
    88     /** The dedicated I/O thread for the non async approach. */
    89     PPDMTHREAD              pAsyncIOThread;
    90     /** Queue for passing the requests to the thread. */
    91     RTREQQUEUE              hQueueRequests;
    92     /** Request that we've left pending on wakeup or reset. */
    93     PRTREQ                  pPendingDummyReq;
    9488    /** Indicates whether PDMDrvHlpAsyncNotificationCompleted should be called by
    9589     * any of the dummy functions. */
     
    109103} DRVSCSI, *PDRVSCSI;
    110104
    111 /** Converts a pointer to DRVSCSI::ISCSIConnector to a PDRVSCSI. */
    112 #define PDMISCSICONNECTOR_2_DRVSCSI(pInterface)  ( (PDRVSCSI)((uintptr_t)pInterface - RT_OFFSETOF(DRVSCSI, ISCSIConnector)) )
    113 /** Converts a pointer to DRVSCSI::IPortAsync to a PDRVSCSI. */
    114 #define PDMIMEDIAASYNCPORT_2_DRVSCSI(pInterface) ( (PDRVSCSI)((uintptr_t)pInterface - RT_OFFSETOF(DRVSCSI, IPortAsync)) )
    115 /** Converts a pointer to DRVSCSI::IMountNotify to PDRVSCSI. */
    116 #define PDMIMOUNTNOTIFY_2_DRVSCSI(pInterface)    ( (PDRVSCSI)((uintptr_t)pInterface - RT_OFFSETOF(DRVSCSI, IMountNotify)) )
    117 /** Converts a pointer to DRVSCSI::IPort to a PDRVSCSI. */
    118 #define PDMIMEDIAPORT_2_DRVSCSI(pInterface)      ( (PDRVSCSI)((uintptr_t)pInterface - RT_OFFSETOF(DRVSCSI, IPort)) )
    119 
    120 static bool drvscsiIsRedoPossible(int rc)
     105/** Convert a VSCSI I/O request handle to the associated PDMIMEDIAEX I/O request. */
     106#define DRVSCSI_VSCSIIOREQ_2_PDMMEDIAEXIOREQ(a_hVScsiIoReq) (*(PPDMMEDIAEXIOREQ)((uint8_t *)(a_hVScsiIoReq) - sizeof(PDMMEDIAEXIOREQ)))
     107/** Convert a PDMIMEDIAEX I/O additional request memory to a VSCSI I/O request. */
     108#define DRVSCSI_PDMMEDIAEXIOREQ_2_VSCSIIOREQ(a_pvIoReqAlloc) ((VSCSIIOREQ)((uint8_t *)(a_pvIoReqAlloc) + sizeof(PDMMEDIAEXIOREQ)))
     109
     110/**
     111 * Returns whether the given status code indicates a non fatal error.
     112 *
     113 * @returns True if the error can be fixed by the user after the VM was suspended.
     114 *          False if not and the error should be reported to the guest.
     115 * @param   rc          The status code to check.
     116 */
     117DECLINLINE(bool) drvscsiIsRedoPossible(int rc)
    121118{
    122119    if (   rc == VERR_DISK_FULL
     
    130127}
    131128
    132 static int drvscsiProcessRequestOne(PDRVSCSI pThis, VSCSIIOREQ hVScsiIoReq)
    133 {
     129/* -=-=-=-=- VScsiIoCallbacks -=-=-=-=- */
     130
     131/**
     132 * @interface_method_impl{VSCSILUNIOCALLBACKS,pfnVScsiLunReqAllocSizeSet}
     133 */
     134static DECLCALLBACK(int) drvscsiReqAllocSizeSet(VSCSILUN hVScsiLun, void *pvScsiLunUser, size_t cbVScsiIoReqAlloc)
     135{
     136    RT_NOREF(hVScsiLun);
     137    PDRVSCSI pThis = (PDRVSCSI)pvScsiLunUser;
     138
     139    /* We need to store the I/O request handle so we can get it when VSCSI queues an I/O request. */
     140    return pThis->pDrvMediaEx->pfnIoReqAllocSizeSet(pThis->pDrvMediaEx, cbVScsiIoReqAlloc + sizeof(PDMMEDIAEXIOREQ));
     141}
     142
     143/**
     144 * @interface_method_impl{VSCSILUNIOCALLBACKS,pfnVScsiLunReqAlloc}
     145 */
     146static DECLCALLBACK(int) drvscsiReqAlloc(VSCSILUN hVScsiLun, void *pvScsiLunUser,
     147                                         uint64_t u64Tag, PVSCSIIOREQ phVScsiIoReq)
     148{
     149    RT_NOREF(hVScsiLun);
     150    PDRVSCSI pThis = (PDRVSCSI)pvScsiLunUser;
     151    PDMMEDIAEXIOREQ hIoReq;
     152    void *pvIoReqAlloc;
     153    int rc = pThis->pDrvMediaEx->pfnIoReqAlloc(pThis->pDrvMediaEx, &hIoReq, &pvIoReqAlloc, u64Tag,
     154                                               PDMIMEDIAEX_F_DEFAULT);
     155    if (RT_SUCCESS(rc))
     156    {
     157        PPDMMEDIAEXIOREQ phIoReq = (PPDMMEDIAEXIOREQ)pvIoReqAlloc;
     158
     159        *phIoReq = hIoReq;
     160        *phVScsiIoReq = (VSCSIIOREQ)(phIoReq + 1);
     161    }
     162
     163    return rc;
     164}
     165
     166/**
     167 * @interface_method_impl{VSCSILUNIOCALLBACKS,pfnVScsiLunReqFree}
     168 */
     169static DECLCALLBACK(int) drvscsiReqFree(VSCSILUN hVScsiLun, void *pvScsiLunUser, VSCSIIOREQ hVScsiIoReq)
     170{
     171    RT_NOREF(hVScsiLun);
     172    PDRVSCSI pThis = (PDRVSCSI)pvScsiLunUser;
     173    PDMMEDIAEXIOREQ hIoReq = DRVSCSI_VSCSIIOREQ_2_PDMMEDIAEXIOREQ(hVScsiIoReq);
     174
     175    return pThis->pDrvMediaEx->pfnIoReqFree(pThis->pDrvMediaEx, hIoReq);
     176}
     177
     178/**
     179 * @interface_method_impl{VSCSILUNIOCALLBACKS,pfnVScsiLunMediumGetSize}
     180 */
     181static DECLCALLBACK(int) drvscsiGetSize(VSCSILUN hVScsiLun, void *pvScsiLunUser, uint64_t *pcbSize)
     182{
     183    RT_NOREF(hVScsiLun);
     184    PDRVSCSI pThis = (PDRVSCSI)pvScsiLunUser;
     185
     186    *pcbSize = pThis->pDrvMedia->pfnGetSize(pThis->pDrvMedia);
     187
     188    return VINF_SUCCESS;
     189}
     190
     191/**
     192 * @interface_method_impl{VSCSILUNIOCALLBACKS,pfnVScsiLunMediumGetSectorSize}
     193 */
     194static DECLCALLBACK(int) drvscsiGetSectorSize(VSCSILUN hVScsiLun, void *pvScsiLunUser, uint32_t *pcbSectorSize)
     195{
     196    RT_NOREF(hVScsiLun);
     197    PDRVSCSI pThis = (PDRVSCSI)pvScsiLunUser;
     198
     199    *pcbSectorSize = pThis->pDrvMedia->pfnGetSectorSize(pThis->pDrvMedia);
     200
     201    return VINF_SUCCESS;
     202}
     203
     204/**
     205 * @interface_method_impl{VSCSILUNIOCALLBACKS,pfnVScsiLunMediumSetLock}
     206 */
     207static DECLCALLBACK(int) drvscsiSetLock(VSCSILUN hVScsiLun, void *pvScsiLunUser, bool fLocked)
     208{
     209    RT_NOREF(hVScsiLun);
     210    PDRVSCSI pThis = (PDRVSCSI)pvScsiLunUser;
     211
     212    if (fLocked)
     213        pThis->pDrvMount->pfnLock(pThis->pDrvMount);
     214    else
     215        pThis->pDrvMount->pfnUnlock(pThis->pDrvMount);
     216
     217    return VINF_SUCCESS;
     218}
     219
     220/**
     221 * @interface_method_impl{VSCSILUNIOCALLBACKS,pfnVScsiLunReqTransferEnqueue}
     222 */
     223static DECLCALLBACK(int) drvscsiReqTransferEnqueue(VSCSILUN hVScsiLun, void *pvScsiLunUser, VSCSIIOREQ hVScsiIoReq)
     224{
     225    RT_NOREF(hVScsiLun);
    134226    int rc = VINF_SUCCESS;
    135     VSCSIIOREQTXDIR enmTxDir;
    136 
    137     enmTxDir = VSCSIIoReqTxDirGet(hVScsiIoReq);
    138 
     227    PDRVSCSI pThis = (PDRVSCSI)pvScsiLunUser;
     228    PDMMEDIAEXIOREQ hIoReq = DRVSCSI_VSCSIIOREQ_2_PDMMEDIAEXIOREQ(hVScsiIoReq);
     229
     230    LogFlowFunc(("Enqueuing hVScsiIoReq=%#p\n", hVScsiIoReq));
     231
     232    VSCSIIOREQTXDIR enmTxDir = VSCSIIoReqTxDirGet(hVScsiIoReq);
    139233    switch (enmTxDir)
    140234    {
    141235        case VSCSIIOREQTXDIR_FLUSH:
    142236        {
    143             rc = pThis->pDrvMedia->pfnFlush(pThis->pDrvMedia);
     237            rc = pThis->pDrvMediaEx->pfnIoReqFlush(pThis->pDrvMediaEx, hIoReq);
    144238            if (   RT_FAILURE(rc)
    145239                && pThis->cErrors++ < MAX_LOG_REL_ERRORS)
    146240                LogRel(("SCSI#%u: Flush returned rc=%Rrc\n",
     241                        pThis->pDrvIns->iInstance, rc));
     242            break;
     243        }
     244        case VSCSIIOREQTXDIR_UNMAP:
     245        {
     246            PCRTRANGE paRanges;
     247            unsigned cRanges;
     248
     249            rc = VSCSIIoReqUnmapParamsGet(hVScsiIoReq, &paRanges, &cRanges);
     250            AssertRC(rc);
     251
     252            pThis->pLed->Asserted.s.fWriting = pThis->pLed->Actual.s.fWriting = 1;
     253            rc = pThis->pDrvMediaEx->pfnIoReqDiscard(pThis->pDrvMediaEx, hIoReq, paRanges, cRanges);
     254            if (   RT_FAILURE(rc)
     255                && pThis->cErrors++ < MAX_LOG_REL_ERRORS)
     256                LogRel(("SCSI#%u: Discard returned rc=%Rrc\n",
    147257                        pThis->pDrvIns->iInstance, rc));
    148258            break;
     
    157267            unsigned  cSeg       = 0;
    158268
    159             rc = VSCSIIoReqParamsGet(hVScsiIoReq, &uOffset, &cbTransfer, &cSeg, &cbSeg,
    160                                      &paSeg);
     269            rc = VSCSIIoReqParamsGet(hVScsiIoReq, &uOffset, &cbTransfer,
     270                                     &cSeg, &cbSeg, &paSeg);
    161271            AssertRC(rc);
    162272
    163             while (cbTransfer && cSeg)
     273            if (enmTxDir == VSCSIIOREQTXDIR_READ)
    164274            {
    165                 size_t cbProcess = (cbTransfer < paSeg->cbSeg) ? cbTransfer : paSeg->cbSeg;
    166 
    167                 Log(("%s: uOffset=%llu cbProcess=%u\n", __FUNCTION__, uOffset, cbProcess));
    168 
    169                 if (enmTxDir == VSCSIIOREQTXDIR_READ)
    170                 {
    171                     pThis->pLed->Asserted.s.fReading = pThis->pLed->Actual.s.fReading = 1;
    172                     rc = pThis->pDrvMedia->pfnRead(pThis->pDrvMedia, uOffset,
    173                                                     paSeg->pvSeg, cbProcess);
    174                     pThis->pLed->Actual.s.fReading = 0;
    175                     if (RT_FAILURE(rc))
    176                         break;
    177                     STAM_REL_COUNTER_ADD(&pThis->StatBytesRead, cbProcess);
    178                 }
    179                 else
    180                 {
    181                     pThis->pLed->Asserted.s.fWriting = pThis->pLed->Actual.s.fWriting = 1;
    182                     rc = pThis->pDrvMedia->pfnWrite(pThis->pDrvMedia, uOffset,
    183                                                     paSeg->pvSeg, cbProcess);
    184                     pThis->pLed->Actual.s.fWriting = 0;
    185                     if (RT_FAILURE(rc))
    186                         break;
    187                     STAM_REL_COUNTER_ADD(&pThis->StatBytesWritten, cbProcess);
    188                 }
    189 
    190                 /* Go to the next entry. */
    191                 uOffset     += cbProcess;
    192                 cbTransfer -= cbProcess;
    193                 paSeg++;
    194                 cSeg--;
     275                pThis->pLed->Asserted.s.fReading = pThis->pLed->Actual.s.fReading = 1;
     276                rc = pThis->pDrvMediaEx->pfnIoReqRead(pThis->pDrvMediaEx, hIoReq, uOffset, cbTransfer);
     277                STAM_REL_COUNTER_ADD(&pThis->StatBytesRead, cbTransfer);
     278            }
     279            else
     280            {
     281                pThis->pLed->Asserted.s.fWriting = pThis->pLed->Actual.s.fWriting = 1;
     282                rc = pThis->pDrvMediaEx->pfnIoReqWrite(pThis->pDrvMediaEx, hIoReq, uOffset, cbTransfer);
     283                STAM_REL_COUNTER_ADD(&pThis->StatBytesWritten, cbTransfer);
    195284            }
    196285
     
    204293                        uOffset,
    205294                        cbTransfer, rc));
    206 
    207             break;
    208         }
    209         case VSCSIIOREQTXDIR_UNMAP:
    210         {
    211             PCRTRANGE paRanges;
    212             unsigned cRanges;
    213 
    214             rc = VSCSIIoReqUnmapParamsGet(hVScsiIoReq, &paRanges, &cRanges);
    215             AssertRC(rc);
    216 
    217             pThis->pLed->Asserted.s.fWriting = pThis->pLed->Actual.s.fWriting = 1;
    218             rc = pThis->pDrvMedia->pfnDiscard(pThis->pDrvMedia, paRanges, cRanges);
    219             pThis->pLed->Actual.s.fWriting = 0;
    220 
    221             if (   RT_FAILURE(rc)
    222                 && pThis->cErrors++ < MAX_LOG_REL_ERRORS)
    223                 LogRel(("SCSI#%u: Unmap returned rc=%Rrc\n",
    224                         pThis->pDrvIns->iInstance, rc));
    225 
    226295            break;
    227296        }
    228297        default:
    229             AssertMsgFailed(("Invalid transfer direction %d\n", enmTxDir));
    230     }
    231 
    232     if (RT_SUCCESS(rc))
    233         VSCSIIoReqCompleted(hVScsiIoReq, rc, false /* fRedoPossible */);
     298            AssertMsgFailed(("Invalid transfer direction %u\n", enmTxDir));
     299    }
     300
     301    if (rc == VINF_SUCCESS)
     302    {
     303        if (enmTxDir == VSCSIIOREQTXDIR_READ)
     304            pThis->pLed->Actual.s.fReading = 0;
     305        else if (enmTxDir == VSCSIIOREQTXDIR_WRITE)
     306            pThis->pLed->Actual.s.fWriting = 0;
     307        else
     308            AssertMsg(enmTxDir == VSCSIIOREQTXDIR_FLUSH, ("Invalid transfer direction %u\n", enmTxDir));
     309
     310        VSCSIIoReqCompleted(hVScsiIoReq, VINF_SUCCESS, false);
     311        rc = VINF_SUCCESS;
     312    }
     313    else if (rc == VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS)
     314        rc = VINF_SUCCESS;
     315    else if (RT_FAILURE(rc))
     316    {
     317        if (enmTxDir == VSCSIIOREQTXDIR_READ)
     318            pThis->pLed->Actual.s.fReading = 0;
     319        else if (enmTxDir == VSCSIIOREQTXDIR_WRITE)
     320            pThis->pLed->Actual.s.fWriting = 0;
     321        else
     322            AssertMsg(enmTxDir == VSCSIIOREQTXDIR_FLUSH, ("Invalid transfer direction %u\n", enmTxDir));
     323
     324        VSCSIIoReqCompleted(hVScsiIoReq, rc, drvscsiIsRedoPossible(rc));
     325        rc = VINF_SUCCESS;
     326    }
    234327    else
    235         VSCSIIoReqCompleted(hVScsiIoReq, rc, drvscsiIsRedoPossible(rc));
    236 
    237     return VINF_SUCCESS;
    238 }
    239 
    240 static DECLCALLBACK(int) drvscsiGetSize(VSCSILUN hVScsiLun, void *pvScsiLunUser, uint64_t *pcbSize)
     328        AssertMsgFailed(("Invalid return code rc=%Rrc\n", rc));
     329
     330    return rc;
     331}
     332
     333/**
     334 * @interface_method_impl{VSCSILUNIOCALLBACKS,pfnVScsiLunGetFeatureFlags}
     335 */
     336static DECLCALLBACK(int) drvscsiGetFeatureFlags(VSCSILUN hVScsiLun, void *pvScsiLunUser, uint64_t *pfFeatures)
    241337{
    242338    RT_NOREF(hVScsiLun);
    243339    PDRVSCSI pThis = (PDRVSCSI)pvScsiLunUser;
    244340
    245     *pcbSize = pThis->pDrvMedia->pfnGetSize(pThis->pDrvMedia);
     341    *pfFeatures = 0;
     342
     343    uint32_t fFeatures = 0;
     344    int rc = pThis->pDrvMediaEx->pfnQueryFeatures(pThis->pDrvMediaEx, &fFeatures);
     345    if (RT_SUCCESS(rc) && (fFeatures & PDMIMEDIAEX_FEATURE_F_DISCARD))
     346        *pfFeatures |= VSCSI_LUN_FEATURE_UNMAP;
     347
     348    if (pThis->fNonRotational)
     349        *pfFeatures |= VSCSI_LUN_FEATURE_NON_ROTATIONAL;
     350
     351    if (pThis->fReadonly)
     352        *pfFeatures |= VSCSI_LUN_FEATURE_READONLY;
    246353
    247354    return VINF_SUCCESS;
     
    249356
    250357
    251 static DECLCALLBACK(int) drvscsiGetSectorSize(VSCSILUN hVScsiLun, void *pvScsiLunUser, uint32_t *pcbSectorSize)
    252 {
    253     RT_NOREF(hVScsiLun);
    254     PDRVSCSI pThis = (PDRVSCSI)pvScsiLunUser;
    255 
    256     *pcbSectorSize = pThis->pDrvMedia->pfnGetSectorSize(pThis->pDrvMedia);
    257 
    258     return VINF_SUCCESS;
    259 }
    260 static DECLCALLBACK(int) drvscsiSetLock(VSCSILUN hVScsiLun, void *pvScsiLunUser, bool fLocked)
    261 {
    262     RT_NOREF(hVScsiLun);
    263     PDRVSCSI pThis = (PDRVSCSI)pvScsiLunUser;
    264 
    265     if (fLocked)
    266         pThis->pDrvMount->pfnLock(pThis->pDrvMount);
    267     else
    268         pThis->pDrvMount->pfnUnlock(pThis->pDrvMount);
    269 
    270     return VINF_SUCCESS;
    271 }
    272 
    273 static DECLCALLBACK(int) drvscsiTransferCompleteNotify(PPDMIMEDIAASYNCPORT pInterface, void *pvUser, int rc)
    274 {
    275     PDRVSCSI pThis = PDMIMEDIAASYNCPORT_2_DRVSCSI(pInterface);
    276     VSCSIIOREQ hVScsiIoReq = (VSCSIIOREQ)pvUser;
     358/* -=-=-=-=- IPortEx -=-=-=-=- */
     359
     360/**
     361 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCompleteNotify}
     362 */
     363static DECLCALLBACK(int) drvscsiIoReqCompleteNotify(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
     364                                                    void *pvIoReqAlloc, int rcReq)
     365{
     366    RT_NOREF1(hIoReq);
     367
     368    PDRVSCSI pThis = RT_FROM_MEMBER(pInterface, DRVSCSI, IPortEx);
     369    VSCSIIOREQ hVScsiIoReq = (VSCSIIOREQ)((uint8_t *)pvIoReqAlloc + sizeof(PDMMEDIAEXIOREQ));
    277370    VSCSIIOREQTXDIR enmTxDir = VSCSIIoReqTxDirGet(hVScsiIoReq);
    278371
     
    287380        AssertMsg(enmTxDir == VSCSIIOREQTXDIR_FLUSH, ("Invalid transfer direction %u\n", enmTxDir));
    288381
    289     if (RT_SUCCESS(rc))
    290         VSCSIIoReqCompleted(hVScsiIoReq, rc, false /* fRedoPossible */);
     382    if (RT_SUCCESS(rcReq))
     383        VSCSIIoReqCompleted(hVScsiIoReq, rcReq, false /* fRedoPossible */);
    291384    else
    292385    {
     
    296389            if (enmTxDir == VSCSIIOREQTXDIR_FLUSH)
    297390                LogRel(("SCSI#%u: Flush returned rc=%Rrc\n",
    298                         pThis->pDrvIns->iInstance, rc));
     391                        pThis->pDrvIns->iInstance, rcReq));
    299392            else if (enmTxDir == VSCSIIOREQTXDIR_UNMAP)
    300393                LogRel(("SCSI#%u: Unmap returned rc=%Rrc\n",
    301                         pThis->pDrvIns->iInstance, rc));
     394                        pThis->pDrvIns->iInstance, rcReq));
    302395            else
    303396            {
     
    317410                        : "Write",
    318411                        uOffset,
    319                         cbTransfer, rc));
     412                        cbTransfer, rcReq));
    320413            }
    321414        }
    322415
    323         VSCSIIoReqCompleted(hVScsiIoReq, rc, drvscsiIsRedoPossible(rc));
     416        VSCSIIoReqCompleted(hVScsiIoReq, rcReq, drvscsiIsRedoPossible(rcReq));
    324417    }
    325418
     
    327420}
    328421
    329 static DECLCALLBACK(int) drvscsiReqTransferEnqueue(VSCSILUN hVScsiLun, void *pvScsiLunUser, VSCSIIOREQ hVScsiIoReq)
    330 {
    331     RT_NOREF(hVScsiLun);
    332     int rc = VINF_SUCCESS;
    333     PDRVSCSI pThis = (PDRVSCSI)pvScsiLunUser;
    334 
    335     if (pThis->pDrvMediaAsync)
    336     {
    337         /* async I/O path. */
    338         VSCSIIOREQTXDIR enmTxDir;
    339 
    340         LogFlowFunc(("Enqueuing hVScsiIoReq=%#p\n", hVScsiIoReq));
    341 
    342         enmTxDir = VSCSIIoReqTxDirGet(hVScsiIoReq);
    343 
    344         switch (enmTxDir)
    345         {
    346             case VSCSIIOREQTXDIR_FLUSH:
    347             {
    348                 rc = pThis->pDrvMediaAsync->pfnStartFlush(pThis->pDrvMediaAsync, hVScsiIoReq);
    349                 if (   RT_FAILURE(rc)
    350                     && rc != VERR_VD_ASYNC_IO_IN_PROGRESS
    351                     && pThis->cErrors++ < MAX_LOG_REL_ERRORS)
    352                     LogRel(("SCSI#%u: Flush returned rc=%Rrc\n",
    353                             pThis->pDrvIns->iInstance, rc));
    354                 break;
    355             }
    356             case VSCSIIOREQTXDIR_UNMAP:
    357             {
    358                 PCRTRANGE paRanges;
    359                 unsigned cRanges;
    360 
    361                 rc = VSCSIIoReqUnmapParamsGet(hVScsiIoReq, &paRanges, &cRanges);
    362                 AssertRC(rc);
    363 
    364                 pThis->pLed->Asserted.s.fWriting = pThis->pLed->Actual.s.fWriting = 1;
    365                 rc = pThis->pDrvMediaAsync->pfnStartDiscard(pThis->pDrvMediaAsync, paRanges, cRanges, hVScsiIoReq);
    366                 if (   RT_FAILURE(rc)
    367                     && rc != VERR_VD_ASYNC_IO_IN_PROGRESS
    368                     && pThis->cErrors++ < MAX_LOG_REL_ERRORS)
    369                     LogRel(("SCSI#%u: Discard returned rc=%Rrc\n",
    370                             pThis->pDrvIns->iInstance, rc));
    371                 break;
    372             }
    373             case VSCSIIOREQTXDIR_READ:
    374             case VSCSIIOREQTXDIR_WRITE:
    375             {
    376                 uint64_t  uOffset    = 0;
    377                 size_t    cbTransfer = 0;
    378                 size_t    cbSeg      = 0;
    379                 PCRTSGSEG paSeg      = NULL;
    380                 unsigned  cSeg       = 0;
    381 
    382                 rc = VSCSIIoReqParamsGet(hVScsiIoReq, &uOffset, &cbTransfer,
    383                                          &cSeg, &cbSeg, &paSeg);
    384                 AssertRC(rc);
    385 
    386                 if (enmTxDir == VSCSIIOREQTXDIR_READ)
    387                 {
    388                     pThis->pLed->Asserted.s.fReading = pThis->pLed->Actual.s.fReading = 1;
    389                     rc = pThis->pDrvMediaAsync->pfnStartRead(pThis->pDrvMediaAsync, uOffset,
    390                                                              paSeg, cSeg, cbTransfer,
    391                                                              hVScsiIoReq);
    392                     STAM_REL_COUNTER_ADD(&pThis->StatBytesRead, cbTransfer);
    393                 }
    394                 else
    395                 {
    396                     pThis->pLed->Asserted.s.fWriting = pThis->pLed->Actual.s.fWriting = 1;
    397                     rc = pThis->pDrvMediaAsync->pfnStartWrite(pThis->pDrvMediaAsync, uOffset,
    398                                                               paSeg, cSeg, cbTransfer,
    399                                                               hVScsiIoReq);
    400                     STAM_REL_COUNTER_ADD(&pThis->StatBytesWritten, cbTransfer);
    401                 }
    402 
    403                 if (   RT_FAILURE(rc)
    404                     && rc != VERR_VD_ASYNC_IO_IN_PROGRESS
    405                     && pThis->cErrors++ < MAX_LOG_REL_ERRORS)
    406                     LogRel(("SCSI#%u: %s at offset %llu (%u bytes left) returned rc=%Rrc\n",
    407                             pThis->pDrvIns->iInstance,
    408                             enmTxDir == VSCSIIOREQTXDIR_READ
    409                             ? "Read"
    410                             : "Write",
    411                             uOffset,
    412                             cbTransfer, rc));
    413                 break;
    414             }
    415             default:
    416                 AssertMsgFailed(("Invalid transfer direction %u\n", enmTxDir));
    417         }
    418 
    419         if (rc == VINF_VD_ASYNC_IO_FINISHED)
    420         {
    421             if (enmTxDir == VSCSIIOREQTXDIR_READ)
    422                 pThis->pLed->Actual.s.fReading = 0;
    423             else if (enmTxDir == VSCSIIOREQTXDIR_WRITE)
    424                 pThis->pLed->Actual.s.fWriting = 0;
    425             else
    426                 AssertMsg(enmTxDir == VSCSIIOREQTXDIR_FLUSH, ("Invalid transfer direction %u\n", enmTxDir));
    427 
    428             VSCSIIoReqCompleted(hVScsiIoReq, VINF_SUCCESS, false);
    429             rc = VINF_SUCCESS;
    430         }
    431         else if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
    432             rc = VINF_SUCCESS;
    433         else if (RT_FAILURE(rc))
    434         {
    435             if (enmTxDir == VSCSIIOREQTXDIR_READ)
    436                 pThis->pLed->Actual.s.fReading = 0;
    437             else if (enmTxDir == VSCSIIOREQTXDIR_WRITE)
    438                 pThis->pLed->Actual.s.fWriting = 0;
    439             else
    440                 AssertMsg(enmTxDir == VSCSIIOREQTXDIR_FLUSH, ("Invalid transfer direction %u\n", enmTxDir));
    441 
    442             VSCSIIoReqCompleted(hVScsiIoReq, rc, drvscsiIsRedoPossible(rc));
    443             rc = VINF_SUCCESS;
    444         }
    445         else
    446             AssertMsgFailed(("Invalid return code rc=%Rrc\n", rc));
    447     }
    448     else
    449     {
    450         /* I/O thread. */
    451         rc = RTReqQueueCallEx(pThis->hQueueRequests, NULL, 0, RTREQFLAGS_NO_WAIT,
    452                               (PFNRT)drvscsiProcessRequestOne, 2, pThis, hVScsiIoReq);
    453     }
    454 
    455     return rc;
    456 }
    457 
    458 static DECLCALLBACK(int) drvscsiGetFeatureFlags(VSCSILUN hVScsiLun, void *pvScsiLunUser, uint64_t *pfFeatures)
    459 {
    460     RT_NOREF(hVScsiLun);
    461     PDRVSCSI pThis = (PDRVSCSI)pvScsiLunUser;
    462 
    463     *pfFeatures = 0;
    464 
    465     if (   pThis->pDrvMedia->pfnDiscard
    466         || (   pThis->pDrvMediaAsync
    467             && pThis->pDrvMediaAsync->pfnStartDiscard))
    468         *pfFeatures |= VSCSI_LUN_FEATURE_UNMAP;
    469 
    470     if (pThis->fNonRotational)
    471         *pfFeatures |= VSCSI_LUN_FEATURE_NON_ROTATIONAL;
    472 
    473     if (pThis->fReadonly)
    474         *pfFeatures |= VSCSI_LUN_FEATURE_READONLY;
    475 
    476     return VINF_SUCCESS;
     422/**
     423 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyFromBuf}
     424 */
     425static DECLCALLBACK(int) drvscsiIoReqCopyFromBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
     426                                                 void *pvIoReqAlloc, uint32_t offDst, PRTSGBUF pSgBuf,
     427                                                 size_t cbCopy)
     428{
     429    RT_NOREF2(pInterface, hIoReq);
     430
     431    VSCSIIOREQ hVScsiIoReq = DRVSCSI_PDMMEDIAEXIOREQ_2_VSCSIIOREQ(pvIoReqAlloc);
     432    uint64_t  uOffset    = 0;
     433    size_t    cbTransfer = 0;
     434    size_t    cbSeg      = 0;
     435    PCRTSGSEG paSeg      = NULL;
     436    unsigned  cSeg       = 0;
     437    size_t    cbCopied   = 0;
     438
     439    int rc = VSCSIIoReqParamsGet(hVScsiIoReq, &uOffset, &cbTransfer, &cSeg, &cbSeg, &paSeg);
     440    if (RT_SUCCESS(rc))
     441    {
     442        RTSGBUF SgBuf;
     443        RTSgBufInit(&SgBuf, paSeg, cSeg);
     444
     445        RTSgBufAdvance(&SgBuf, offDst);
     446        cbCopied = RTSgBufCopy(&SgBuf, pSgBuf, cbCopy);
     447    }
     448
     449    return cbCopied == cbCopy ? VINF_SUCCESS : VERR_PDM_MEDIAEX_IOBUF_OVERFLOW;
     450}
     451
     452/**
     453 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyToBuf}
     454 */
     455static DECLCALLBACK(int) drvscsiIoReqCopyToBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
     456                                               void *pvIoReqAlloc, uint32_t offSrc, PRTSGBUF pSgBuf,
     457                                               size_t cbCopy)
     458{
     459    RT_NOREF2(pInterface, hIoReq);
     460
     461    VSCSIIOREQ hVScsiIoReq = DRVSCSI_PDMMEDIAEXIOREQ_2_VSCSIIOREQ(pvIoReqAlloc);
     462    uint64_t  uOffset    = 0;
     463    size_t    cbTransfer = 0;
     464    size_t    cbSeg      = 0;
     465    PCRTSGSEG paSeg      = NULL;
     466    unsigned  cSeg       = 0;
     467    size_t    cbCopied   = 0;
     468
     469    int rc = VSCSIIoReqParamsGet(hVScsiIoReq, &uOffset, &cbTransfer, &cSeg, &cbSeg, &paSeg);
     470    if (RT_SUCCESS(rc))
     471    {
     472        RTSGBUF SgBuf;
     473        RTSgBufInit(&SgBuf, paSeg, cSeg);
     474
     475        RTSgBufAdvance(&SgBuf, offSrc);
     476        cbCopied = RTSgBufCopy(pSgBuf, &SgBuf, cbCopy);
     477    }
     478
     479    return cbCopied == cbCopy ? VINF_SUCCESS : VERR_PDM_MEDIAEX_IOBUF_UNDERRUN;
     480}
     481
     482/**
     483 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqStateChanged}
     484 */
     485static DECLCALLBACK(void) drvscsiIoReqStateChanged(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,
     486                                                   void *pvIoReqAlloc, PDMMEDIAEXIOREQSTATE enmState)
     487{
     488    RT_NOREF4(pInterface, hIoReq, pvIoReqAlloc, enmState);
     489    AssertLogRelMsgFailed(("This should not be hit because I/O requests should not be suspended\n"));
    477490}
    478491
     
    490503    if (RT_UNLIKELY(pThis->fDummySignal) && !pThis->StatIoDepth)
    491504        PDMDrvHlpAsyncNotificationCompleted(pThis->pDrvIns);
    492 }
    493 
    494 /**
    495  * Dummy request function used by drvscsiReset to wait for all pending requests
    496  * to complete prior to the device reset.
    497  *
    498  * @param   pThis           Pointer to the instance data.
    499  * @returns VINF_SUCCESS.
    500  */
    501 static int drvscsiAsyncIOLoopSyncCallback(PDRVSCSI pThis)
    502 {
    503     if (pThis->fDummySignal)
    504         PDMDrvHlpAsyncNotificationCompleted(pThis->pDrvIns);
    505     return VINF_SUCCESS;
    506 }
    507 
    508 /**
    509  * Request function to wakeup the thread.
    510  *
    511  * @param   pThis           Pointer to the instance data.
    512  * @returns VWRN_STATE_CHANGED.
    513  */
    514 static int drvscsiAsyncIOLoopWakeupFunc(PDRVSCSI pThis)
    515 {
    516     if (pThis->fDummySignal)
    517         PDMDrvHlpAsyncNotificationCompleted(pThis->pDrvIns);
    518     return VWRN_STATE_CHANGED;
    519 }
    520 
    521 /**
    522  * The thread function which processes the requests asynchronously.
    523  *
    524  * @returns VBox status code.
    525  * @param   pDrvIns    Pointer to the driver instance data.
    526  * @param   pThread    Pointer to the thread instance data.
    527  */
    528 static DECLCALLBACK(int) drvscsiAsyncIOLoop(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
    529 {
    530     int rc = VINF_SUCCESS;
    531     PDRVSCSI pThis = PDMINS_2_DATA(pDrvIns, PDRVSCSI);
    532 
    533     LogFlowFunc(("Entering async IO loop.\n"));
    534 
    535     if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
    536         return VINF_SUCCESS;
    537 
    538     while (pThread->enmState == PDMTHREADSTATE_RUNNING)
    539     {
    540         rc = RTReqQueueProcess(pThis->hQueueRequests, RT_INDEFINITE_WAIT);
    541         AssertMsg(rc == VWRN_STATE_CHANGED, ("Left RTReqProcess and error code is not VWRN_STATE_CHANGED rc=%Rrc\n", rc));
    542     }
    543 
    544     return VINF_SUCCESS;
    545 }
    546 
    547 /**
    548  * Deals with any pending dummy request
    549  *
    550  * @returns true if no pending dummy request, false if still pending.
    551  * @param   pThis               The instance data.
    552  * @param   cMillies            The number of milliseconds to wait for any
    553  *                              pending request to finish.
    554  */
    555 static bool drvscsiAsyncIOLoopNoPendingDummy(PDRVSCSI pThis, uint32_t cMillies)
    556 {
    557     if (!pThis->pPendingDummyReq)
    558         return true;
    559     int rc = RTReqWait(pThis->pPendingDummyReq, cMillies);
    560     if (RT_FAILURE(rc))
    561         return false;
    562     RTReqRelease(pThis->pPendingDummyReq);
    563     pThis->pPendingDummyReq = NULL;
    564     return true;
    565 }
    566 
    567 static DECLCALLBACK(int) drvscsiAsyncIOLoopWakeup(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
    568 {
    569     RT_NOREF(pThread);
    570     PDRVSCSI pThis = PDMINS_2_DATA(pDrvIns, PDRVSCSI);
    571     PRTREQ pReq;
    572     int rc;
    573 
    574     AssertMsgReturn(pThis->hQueueRequests != NIL_RTREQQUEUE, ("hQueueRequests is NULL\n"), VERR_INVALID_STATE);
    575 
    576     if (!drvscsiAsyncIOLoopNoPendingDummy(pThis, 10000 /* 10 sec */))
    577     {
    578         LogRel(("drvscsiAsyncIOLoopWakeup#%u: previous dummy request is still pending\n", pDrvIns->iInstance));
    579         return VERR_TIMEOUT;
    580     }
    581 
    582     rc = RTReqQueueCall(pThis->hQueueRequests, &pReq, 10000 /* 10 sec. */, (PFNRT)drvscsiAsyncIOLoopWakeupFunc, 1, pThis);
    583     if (RT_SUCCESS(rc))
    584         RTReqRelease(pReq);
    585     else
    586     {
    587         pThis->pPendingDummyReq = pReq;
    588         LogRel(("drvscsiAsyncIOLoopWakeup#%u: %Rrc pReq=%p\n", pDrvIns->iInstance, rc, pReq));
    589     }
    590 
    591     return rc;
    592505}
    593506
     
    623536{
    624537    int rc;
    625     PDRVSCSI pThis = PDMISCSICONNECTOR_2_DRVSCSI(pInterface);
     538    PDRVSCSI pThis = RT_FROM_MEMBER(pInterface, DRVSCSI, ISCSIConnector);
    626539    VSCSIREQ hVScsiReq;
    627540
     
    652565static DECLCALLBACK(int) drvscsiQueryLUNType(PPDMISCSICONNECTOR pInterface, uint32_t iLun, PPDMSCSILUNTYPE pLunType)
    653566{
    654     int rc;
    655     PDRVSCSI pThis = PDMISCSICONNECTOR_2_DRVSCSI(pInterface);
     567    PDRVSCSI pThis = RT_FROM_MEMBER(pInterface, DRVSCSI, ISCSIConnector);
    656568    VSCSILUNTYPE enmLunType;
    657569
    658     rc = VSCSIDeviceLunQueryType(pThis->hVScsiDevice, iLun, &enmLunType);
     570    int rc = VSCSIDeviceLunQueryType(pThis->hVScsiDevice, iLun, &enmLunType);
    659571    if (RT_FAILURE(rc))
    660572        return rc;
     
    686598    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAPORT, &pThis->IPort);
    687599    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMOUNTNOTIFY, &pThis->IMountNotify);
    688     PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAASYNCPORT, &pThis->IPortAsync);
     600    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAEXPORT, &pThis->IPortEx);
    689601    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIA, pThis->pDrvMedia);
    690602    return NULL;
     
    694606                                                    uint32_t *piInstance, uint32_t *piLUN)
    695607{
    696     PDRVSCSI pThis = PDMIMEDIAPORT_2_DRVSCSI(pInterface);
     608    PDRVSCSI pThis = RT_FROM_MEMBER(pInterface, DRVSCSI, IPort);
    697609
    698610    return pThis->pDevScsiPort->pfnQueryDeviceLocation(pThis->pDevScsiPort, ppcszController,
     
    707619static DECLCALLBACK(void) drvscsiMountNotify(PPDMIMOUNTNOTIFY pInterface)
    708620{
    709     PDRVSCSI pThis = PDMIMOUNTNOTIFY_2_DRVSCSI(pInterface);
     621    PDRVSCSI pThis = RT_FROM_MEMBER(pInterface, DRVSCSI, IMountNotify);
    710622    LogFlowFunc(("mounting LUN#%p\n", pThis->hVScsiLun));
    711623
     
    725637static DECLCALLBACK(void) drvscsiUnmountNotify(PPDMIMOUNTNOTIFY pInterface)
    726638{
    727     PDRVSCSI pThis = PDMIMOUNTNOTIFY_2_DRVSCSI(pInterface);
     639    PDRVSCSI pThis = RT_FROM_MEMBER(pInterface, DRVSCSI, IMountNotify);
    728640    LogFlowFunc(("unmounting LUN#%p\n", pThis->hVScsiLun));
    729641
     
    740652static void drvscsiR3ResetOrSuspendOrPowerOff(PPDMDRVINS pDrvIns, PFNPDMDRVASYNCNOTIFY pfnAsyncNotify)
    741653{
     654    RT_NOREF1(pfnAsyncNotify);
     655
    742656    PDRVSCSI pThis = PDMINS_2_DATA(pDrvIns, PDRVSCSI);
    743657
    744     if (!pThis->pDrvMediaAsync)
    745     {
    746         if (pThis->hQueueRequests != NIL_RTREQQUEUE)
    747             return;
    748 
     658    if (pThis->StatIoDepth > 0)
    749659        ASMAtomicWriteBool(&pThis->fDummySignal, true);
    750         if (drvscsiAsyncIOLoopNoPendingDummy(pThis, 0 /*ms*/))
    751         {
    752             if (!RTReqQueueIsBusy(pThis->hQueueRequests))
    753             {
    754                 ASMAtomicWriteBool(&pThis->fDummySignal, false);
    755                 return;
    756             }
    757 
    758             PRTREQ pReq;
    759             int rc = RTReqQueueCall(pThis->hQueueRequests, &pReq, 0 /*ms*/, (PFNRT)drvscsiAsyncIOLoopSyncCallback, 1, pThis);
    760             if (RT_SUCCESS(rc))
    761             {
    762                 ASMAtomicWriteBool(&pThis->fDummySignal, false);
    763                 RTReqRelease(pReq);
    764                 return;
    765             }
    766 
    767             pThis->pPendingDummyReq = pReq;
    768         }
    769     }
    770     else
    771     {
    772         if (pThis->StatIoDepth > 0)
    773         {
    774             ASMAtomicWriteBool(&pThis->fDummySignal, true);
    775         }
    776         return;
    777     }
    778 
    779     PDMDrvHlpSetAsyncNotification(pDrvIns, pfnAsyncNotify);
    780660}
    781661
     
    790670    PDRVSCSI pThis = PDMINS_2_DATA(pDrvIns, PDRVSCSI);
    791671
    792     if (pThis->pDrvMediaAsync)
    793     {
    794         if (pThis->StatIoDepth > 0)
    795             return false;
    796         else
    797             return true;
    798     }
     672    if (pThis->StatIoDepth > 0)
     673        return false;
    799674    else
    800     {
    801         if (!drvscsiAsyncIOLoopNoPendingDummy(pThis, 0 /*ms*/))
    802             return false;
    803         ASMAtomicWriteBool(&pThis->fDummySignal, false);
    804         PDMR3ThreadSuspend(pThis->pAsyncIOThread);
    805675        return true;
    806     }
    807676}
    808677
     
    833702    PDRVSCSI pThis = PDMINS_2_DATA(pDrvIns, PDRVSCSI);
    834703
    835     if (pThis->pDrvMediaAsync)
    836     {
    837         if (pThis->StatIoDepth > 0)
    838             return false;
    839         else
    840             return true;
    841     }
     704    if (pThis->StatIoDepth > 0)
     705        return false;
    842706    else
    843     {
    844         if (!drvscsiAsyncIOLoopNoPendingDummy(pThis, 0 /*ms*/))
    845             return false;
    846         ASMAtomicWriteBool(&pThis->fDummySignal, false);
    847707        return true;
    848     }
    849708}
    850709
     
    869728    PDRVSCSI pThis = PDMINS_2_DATA(pDrvIns, PDRVSCSI);
    870729    PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
    871 
    872     if (pThis->hQueueRequests != NIL_RTREQQUEUE)
    873     {
    874         if (!drvscsiAsyncIOLoopNoPendingDummy(pThis, 100 /*ms*/))
    875             LogRel(("drvscsiDestruct#%u: previous dummy request is still pending\n", pDrvIns->iInstance));
    876 
    877         int rc = RTReqQueueDestroy(pThis->hQueueRequests);
    878         AssertMsgRC(rc, ("Failed to destroy queue rc=%Rrc\n", rc));
    879         pThis->hQueueRequests = NIL_RTREQQUEUE;
    880     }
    881730
    882731    /* Free the VSCSI device and LUN handle. */
     
    926775    pThis->IMountNotify.pfnUnmountNotify        = drvscsiUnmountNotify;
    927776    pThis->IPort.pfnQueryDeviceLocation         = drvscsiQueryDeviceLocation;
    928     pThis->IPortAsync.pfnTransferCompleteNotify = drvscsiTransferCompleteNotify;
    929     pThis->hQueueRequests                       = NIL_RTREQQUEUE;
     777    pThis->IPortEx.pfnIoReqCompleteNotify       = drvscsiIoReqCompleteNotify;
     778    pThis->IPortEx.pfnIoReqCopyFromBuf          = drvscsiIoReqCopyFromBuf;
     779    pThis->IPortEx.pfnIoReqCopyToBuf            = drvscsiIoReqCopyToBuf;
     780    pThis->IPortEx.pfnIoReqStateChanged         = drvscsiIoReqStateChanged;
    930781
    931782    /* Query the SCSI port interface above. */
     
    972823     */
    973824    pThis->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMIMEDIA);
    974     if (!pThis->pDrvMedia)
    975     {
    976         AssertMsgFailed(("Configuration error: No block interface!\n"));
    977         return VERR_PDM_MISSING_INTERFACE;
    978     }
     825    AssertMsgReturn(VALID_PTR(pThis->pDrvMedia), ("VSCSI configuration error: No media interface!\n"),
     826                    VERR_PDM_MISSING_INTERFACE);
     827
     828    /* Query the extended media interface. */
     829    pThis->pDrvMediaEx = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMIMEDIAEX);
     830    AssertMsgReturn(VALID_PTR(pThis->pDrvMediaEx), ("VSCSI configuration error: No extended media interface!\n"),
     831                    VERR_PDM_MISSING_INTERFACE);
    979832
    980833    pThis->pDrvMount = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMIMOUNT);
    981 
    982     /* Try to get the optional async block interface. */
    983     pThis->pDrvMediaAsync = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMIMEDIAASYNC);
    984834
    985835    PDMMEDIATYPE enmType = pThis->pDrvMedia->pfnGetType(pThis->pDrvMedia);
     
    1008858
    1009859    /* Create VSCSI device and LUN. */
     860    pThis->VScsiIoCallbacks.pfnVScsiLunReqAllocSizeSet     = drvscsiReqAllocSizeSet;
     861    pThis->VScsiIoCallbacks.pfnVScsiLunReqAlloc            = drvscsiReqAlloc;
     862    pThis->VScsiIoCallbacks.pfnVScsiLunReqFree             = drvscsiReqFree;
    1010863    pThis->VScsiIoCallbacks.pfnVScsiLunMediumGetSize       = drvscsiGetSize;
    1011864    pThis->VScsiIoCallbacks.pfnVScsiLunMediumGetSectorSize = drvscsiGetSectorSize;
     
    1059912    pThis->StatIoDepth = 0;
    1060913
    1061     if (!pThis->pDrvMediaAsync)
    1062     {
    1063         /* Create request queue. */
    1064         rc = RTReqQueueCreate(&pThis->hQueueRequests);
    1065         AssertMsgReturn(RT_SUCCESS(rc), ("Failed to create request queue rc=%Rrc\n", rc), rc);
    1066         /* Create I/O thread. */
    1067         rc = PDMDrvHlpThreadCreate(pDrvIns, &pThis->pAsyncIOThread, pThis, drvscsiAsyncIOLoop,
    1068                                    drvscsiAsyncIOLoopWakeup, 0, RTTHREADTYPE_IO, "SCSI async IO");
    1069         AssertMsgReturn(RT_SUCCESS(rc), ("Failed to create async I/O thread rc=%Rrc\n", rc), rc);
    1070 
    1071         LogRel(("SCSI#%d: using normal I/O\n", pDrvIns->iInstance));
    1072     }
    1073     else
    1074         LogRel(("SCSI#%d: using async I/O\n", pDrvIns->iInstance));
    1075 
    1076     if (   pThis->pDrvMedia->pfnDiscard
    1077         || (   pThis->pDrvMediaAsync
    1078             && pThis->pDrvMediaAsync->pfnStartDiscard))
     914    uint32_t fFeatures = 0;
     915    rc = pThis->pDrvMediaEx->pfnQueryFeatures(pThis->pDrvMediaEx, &fFeatures);
     916    if (RT_FAILURE(rc))
     917        return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
     918                                   N_("VSCSI configuration error: Failed to query features of device"));
     919    if (fFeatures & PDMIMEDIAEX_FEATURE_F_DISCARD)
    1079920        LogRel(("SCSI#%d: Enabled UNMAP support\n", pDrvIns->iInstance));
    1080921
  • trunk/src/VBox/Devices/Storage/VSCSI/VSCSIInternal.h

    r62506 r63992  
    321321
    322322/**
     323 * Inits the I/O request related state for the LUN.
     324 *
     325 * @returns VBox status code.
     326 * @param   pVScsiLun    The LUN instance.
     327 */
     328int vscsiIoReqInit(PVSCSILUNINT pVScsiLun);
     329
     330/**
    323331 * Enqueues a new flush request
    324332 *
     
    364372
    365373/**
     374 * Wrapper for the set I/O request allocation size I/O callback.
     375 *
     376 * @returns VBox status code.
     377 * @param   pVScsiLun             The LUN.
     378 * @param   cbVScsiIoReqAlloc     The additional size for the request to allocate.
     379 */
     380DECLINLINE(int) vscsiLunReqAllocSizeSet(PVSCSILUNINT pVScsiLun, size_t cbVScsiIoReqAlloc)
     381{
     382    return pVScsiLun->pVScsiLunIoCallbacks->pfnVScsiLunReqAllocSizeSet(pVScsiLun,
     383                                                                       pVScsiLun->pvVScsiLunUser,
     384                                                                       cbVScsiIoReqAlloc);
     385}
     386
     387/**
     388 * Wrapper for the allocate I/O request I/O callback.
     389 *
     390 * @returns VBox status code.
     391 * @param   pVScsiLun             The LUN.
     392 * @param   u64Tag                A unique tag to assign to the request.
     393 * @param   ppVScsiIoReq          Where to store the pointer to the request on success.
     394 */
     395DECLINLINE(int) vscsiLunReqAlloc(PVSCSILUNINT pVScsiLun, uint64_t u64Tag, PVSCSIIOREQINT *ppVScsiIoReq)
     396{
     397    return pVScsiLun->pVScsiLunIoCallbacks->pfnVScsiLunReqAlloc(pVScsiLun,
     398                                                                pVScsiLun->pvVScsiLunUser,
     399                                                                u64Tag, ppVScsiIoReq);
     400}
     401
     402/**
     403 * Wrapper for the free I/O request I/O callback.
     404 *
     405 * @returns VBox status code.
     406 * @param   pVScsiLun   The LUN.
     407 * @param   pVScsiIoReq The request to free.
     408 */
     409DECLINLINE(int) vscsiLunReqFree(PVSCSILUNINT pVScsiLun, PVSCSIIOREQINT pVScsiIoReq)
     410{
     411    return pVScsiLun->pVScsiLunIoCallbacks->pfnVScsiLunReqFree(pVScsiLun,
     412                                                               pVScsiLun->pvVScsiLunUser,
     413                                                               pVScsiIoReq);
     414}
     415
     416/**
    366417 * Wrapper for the get medium size I/O callback.
    367418 *
  • trunk/src/VBox/Devices/Storage/VSCSI/VSCSIIoReq.cpp

    r62506 r63992  
    2626#include "VSCSIInternal.h"
    2727
     28int vscsiIoReqInit(PVSCSILUNINT pVScsiLun)
     29{
     30    return vscsiLunReqAllocSizeSet(pVScsiLun, sizeof(VSCSIIOREQINT));
     31}
     32
    2833int vscsiIoReqFlushEnqueue(PVSCSILUNINT pVScsiLun, PVSCSIREQINT pVScsiReq)
    2934{
     
    3136    PVSCSIIOREQINT pVScsiIoReq = NULL;
    3237
    33     pVScsiIoReq = (PVSCSIIOREQINT)RTMemAllocZ(sizeof(VSCSIIOREQINT));
    34     if (!pVScsiIoReq)
    35         return VERR_NO_MEMORY;
    36 
    37     pVScsiIoReq->pVScsiReq = pVScsiReq;
    38     pVScsiIoReq->pVScsiLun = pVScsiLun;
    39     pVScsiIoReq->enmTxDir  = VSCSIIOREQTXDIR_FLUSH;
    40 
    41     ASMAtomicIncU32(&pVScsiLun->IoReq.cReqOutstanding);
    42 
    43     rc = vscsiLunReqTransferEnqueue(pVScsiLun, pVScsiIoReq);
    44     if (RT_FAILURE(rc))
    45     {
    46         ASMAtomicDecU32(&pVScsiLun->IoReq.cReqOutstanding);
    47         RTMemFree(pVScsiIoReq);
     38    rc = vscsiLunReqAlloc(pVScsiLun, (uint64_t)pVScsiReq, &pVScsiIoReq);
     39    if (RT_SUCCESS(rc))
     40    {
     41        pVScsiIoReq->pVScsiReq = pVScsiReq;
     42        pVScsiIoReq->pVScsiLun = pVScsiLun;
     43        pVScsiIoReq->enmTxDir  = VSCSIIOREQTXDIR_FLUSH;
     44
     45        ASMAtomicIncU32(&pVScsiLun->IoReq.cReqOutstanding);
     46
     47        rc = vscsiLunReqTransferEnqueue(pVScsiLun, pVScsiIoReq);
     48        if (RT_FAILURE(rc))
     49        {
     50            ASMAtomicDecU32(&pVScsiLun->IoReq.cReqOutstanding);
     51            RTMemFree(pVScsiIoReq);
     52        }
    4853    }
    4954
     
    6267                 pVScsiLun, pVScsiReq, enmTxDir, uOffset, cbTransfer));
    6368
    64     pVScsiIoReq = (PVSCSIIOREQINT)RTMemAllocZ(sizeof(VSCSIIOREQINT));
    65     if (!pVScsiIoReq)
    66         return VERR_NO_MEMORY;
    67 
    68     pVScsiIoReq->pVScsiReq       = pVScsiReq;
    69     pVScsiIoReq->pVScsiLun       = pVScsiLun;
    70     pVScsiIoReq->enmTxDir        = enmTxDir;
    71     pVScsiIoReq->u.Io.uOffset    = uOffset;
    72     pVScsiIoReq->u.Io.cbTransfer = cbTransfer;
    73     pVScsiIoReq->u.Io.paSeg      = pVScsiReq->SgBuf.paSegs;
    74     pVScsiIoReq->u.Io.cSeg       = pVScsiReq->SgBuf.cSegs;
    75 
    76     ASMAtomicIncU32(&pVScsiLun->IoReq.cReqOutstanding);
    77 
    78     rc = vscsiLunReqTransferEnqueue(pVScsiLun, pVScsiIoReq);
    79     if (RT_FAILURE(rc))
    80     {
    81         ASMAtomicDecU32(&pVScsiLun->IoReq.cReqOutstanding);
    82         RTMemFree(pVScsiIoReq);
     69    rc = vscsiLunReqAlloc(pVScsiLun, (uint64_t)pVScsiReq, &pVScsiIoReq);
     70    if (RT_SUCCESS(rc))
     71    {
     72        pVScsiIoReq->pVScsiReq       = pVScsiReq;
     73        pVScsiIoReq->pVScsiLun       = pVScsiLun;
     74        pVScsiIoReq->enmTxDir        = enmTxDir;
     75        pVScsiIoReq->u.Io.uOffset    = uOffset;
     76        pVScsiIoReq->u.Io.cbTransfer = cbTransfer;
     77        pVScsiIoReq->u.Io.paSeg      = pVScsiReq->SgBuf.paSegs;
     78        pVScsiIoReq->u.Io.cSeg       = pVScsiReq->SgBuf.cSegs;
     79
     80        ASMAtomicIncU32(&pVScsiLun->IoReq.cReqOutstanding);
     81
     82        rc = vscsiLunReqTransferEnqueue(pVScsiLun, pVScsiIoReq);
     83        if (RT_FAILURE(rc))
     84        {
     85            ASMAtomicDecU32(&pVScsiLun->IoReq.cReqOutstanding);
     86            vscsiLunReqFree(pVScsiLun, pVScsiIoReq);
     87        }
    8388    }
    8489
     
    96101                 pVScsiLun, pVScsiReq, paRanges, cRanges));
    97102
    98     pVScsiIoReq = (PVSCSIIOREQINT)RTMemAllocZ(sizeof(VSCSIIOREQINT));
    99     if (!pVScsiIoReq)
    100         return VERR_NO_MEMORY;
    101 
    102     pVScsiIoReq->pVScsiReq        = pVScsiReq;
    103     pVScsiIoReq->pVScsiLun        = pVScsiLun;
    104     pVScsiIoReq->enmTxDir         = VSCSIIOREQTXDIR_UNMAP;
    105     pVScsiIoReq->u.Unmap.paRanges = paRanges;
    106     pVScsiIoReq->u.Unmap.cRanges  = cRanges;
    107 
    108     ASMAtomicIncU32(&pVScsiLun->IoReq.cReqOutstanding);
    109 
    110     rc = vscsiLunReqTransferEnqueue(pVScsiLun, pVScsiIoReq);
    111     if (RT_FAILURE(rc))
    112     {
    113         ASMAtomicDecU32(&pVScsiLun->IoReq.cReqOutstanding);
    114         RTMemFree(pVScsiIoReq);
     103    rc = vscsiLunReqAlloc(pVScsiLun, (uint64_t)pVScsiReq, &pVScsiIoReq);
     104    if (RT_SUCCESS(rc))
     105    {
     106        pVScsiIoReq->pVScsiReq        = pVScsiReq;
     107        pVScsiIoReq->pVScsiLun        = pVScsiLun;
     108        pVScsiIoReq->enmTxDir         = VSCSIIOREQTXDIR_UNMAP;
     109        pVScsiIoReq->u.Unmap.paRanges = paRanges;
     110        pVScsiIoReq->u.Unmap.cRanges  = cRanges;
     111
     112        ASMAtomicIncU32(&pVScsiLun->IoReq.cReqOutstanding);
     113
     114        rc = vscsiLunReqTransferEnqueue(pVScsiLun, pVScsiIoReq);
     115        if (RT_FAILURE(rc))
     116        {
     117            ASMAtomicDecU32(&pVScsiLun->IoReq.cReqOutstanding);
     118            vscsiLunReqFree(pVScsiLun, pVScsiIoReq);
     119        }
    115120    }
    116121
     
    163168
    164169    /* Free the I/O request */
    165     RTMemFree(pVScsiIoReq);
     170    vscsiLunReqFree(pVScsiLun, pVScsiIoReq);
    166171
    167172    /* Notify completion of the SCSI request. */
  • trunk/src/VBox/Devices/Storage/VSCSI/VSCSILun.cpp

    r62506 r63992  
    7272    pVScsiLun->pVScsiLunDesc        = pVScsiLunDesc;
    7373
    74     int rc = vscsiLunGetFeatureFlags(pVScsiLun, &pVScsiLun->fFeatures);
     74    int rc = vscsiIoReqInit(pVScsiLun);
    7575    if (RT_SUCCESS(rc))
    7676    {
    77         rc = pVScsiLunDesc->pfnVScsiLunInit(pVScsiLun);
     77        rc = vscsiLunGetFeatureFlags(pVScsiLun, &pVScsiLun->fFeatures);
    7878        if (RT_SUCCESS(rc))
    7979        {
    80             *phVScsiLun = pVScsiLun;
    81             return VINF_SUCCESS;
     80            rc = pVScsiLunDesc->pfnVScsiLunInit(pVScsiLun);
     81            if (RT_SUCCESS(rc))
     82            {
     83                *phVScsiLun = pVScsiLun;
     84                return VINF_SUCCESS;
     85            }
    8286        }
    8387    }
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