VirtualBox

Changeset 28154 in vbox


Ignore:
Timestamp:
Apr 9, 2010 7:11:23 PM (15 years ago)
Author:
vboxsync
Message:

VBoxHDD: async I/O for VDI and RAW images. Seems to work so far but still disabled ofc if UseNewIo is false

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

Legend:

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

    r27808 r28154  
    12001200static bool rawIsAsyncIOSupported(void *pvBackendData)
    12011201{
    1202     return false;
     1202    return true;
    12031203}
    12041204
     
    12061206                        PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
    12071207{
    1208     int rc = VERR_NOT_IMPLEMENTED;
    1209     LogFlowFunc(("returns %Rrc\n", rc));
     1208    int rc = VINF_SUCCESS;
     1209    PRAWIMAGE pImage = (PRAWIMAGE)pvBackendData;
     1210
     1211    rc = pImage->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser,
     1212                                                         pImage->pStorage,
     1213                                                         uOffset, pIoCtx, cbRead);
     1214    if (RT_SUCCESS(rc))
     1215        *pcbActuallyRead = cbRead;
     1216
    12101217    return rc;
    12111218}
     
    12161223                         size_t *pcbPostRead, unsigned fWrite)
    12171224{
    1218     int rc = VERR_NOT_IMPLEMENTED;
    1219     LogFlowFunc(("returns %Rrc\n", rc));
     1225    int rc = VINF_SUCCESS;
     1226    PRAWIMAGE pImage = (PRAWIMAGE)pvBackendData;
     1227
     1228    rc = pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser,
     1229                                                         pImage->pStorage,
     1230                                                         uOffset, pIoCtx, cbWrite);
     1231
     1232    if (RT_SUCCESS(rc))
     1233    {
     1234        *pcbWriteProcess = cbWrite;
     1235        *pcbPostRead = 0;
     1236        *pcbPreRead  = 0;
     1237    }
     1238
    12201239    return rc;
    12211240}
     
    12351254    sizeof(VBOXHDDBACKEND),
    12361255    /* uBackendCaps */
    1237     VD_CAP_CREATE_FIXED | VD_CAP_FILE,
     1256    VD_CAP_CREATE_FIXED | VD_CAP_FILE | VD_CAP_ASYNC,
    12381257    /* papszFileExtensions */
    12391258    s_apszRawFileExtensions,
  • trunk/src/VBox/Devices/Storage/VBoxHDD.cpp

    r28108 r28154  
    208208    /** Flag whether the request finished */
    209209    volatile bool                fComplete;
     210    /** Temporary allocated memory which is freed
     211     * when the context completes. */
     212    void                        *pvAllocation;
    210213    /** Parent I/O context if any. Sets the type of the context (root/child) */
    211214    PVDIOCTX                     pIoCtxParent;
     
    527530DECLINLINE(PVDIOCTX) vdIoCtxAlloc(PVBOXHDD pDisk, VDIOCTXTXDIR enmTxDir,
    528531                                  uint64_t uOffset, size_t cbTransfer,
    529                                   PCRTSGSEG pcaSeg, unsigned cSeg)
     532                                  PCRTSGSEG pcaSeg, unsigned cSeg,
     533                                  void *pvAllocation)
    530534{
    531535    PVDIOCTX pIoCtx = NULL;
     
    540544        pIoCtx->cMetaTransfersPending = 0;
    541545        pIoCtx->fComplete             = false;
     546        pIoCtx->pvAllocation          = pvAllocation;
    542547
    543548        RTSgBufInit(&pIoCtx->SgBuf, pcaSeg, cSeg);
     
    551556                                 PCRTSGSEG paSeg, unsigned cSeg,
    552557                                 PFNVDASYNCTRANSFERCOMPLETE pfnComplete,
    553                                  void *pvUser1, void *pvUser2)
     558                                 void *pvUser1, void *pvUser2,
     559                                 void *pvAllocation)
    554560{
    555561    PVDIOCTX pIoCtx = vdIoCtxAlloc(pDisk, enmTxDir, uOffset, cbTransfer,
    556                                    paSeg, cSeg);
     562                                   paSeg, cSeg, pvAllocation);
    557563
    558564    if (RT_LIKELY(pIoCtx))
     
    570576                                  uint64_t uOffset, size_t cbTransfer,
    571577                                  PCRTSGSEG paSeg, unsigned cSeg,
    572                                   PVDIOCTX pIoCtxParent, size_t cbTransferParent)
     578                                  PVDIOCTX pIoCtxParent, size_t cbTransferParent,
     579                                  void *pvAllocation)
    573580{
    574581    PVDIOCTX pIoCtx = vdIoCtxAlloc(pDisk, enmTxDir, uOffset, cbTransfer,
    575                                    paSeg, cSeg);
     582                                   paSeg, cSeg, pvAllocation);
    576583
    577584    if (RT_LIKELY(pIoCtx))
     
    621628static void vdIoCtxFree(PVBOXHDD pDisk, PVDIOCTX pIoCtx)
    622629{
     630    if (pIoCtx->pvAllocation)
     631        RTMemFree(pIoCtx->pvAllocation);
    623632    RTMemCacheFree(pDisk->hMemCacheIoCtx, pIoCtx);
    624633}
     
    11381147        return rc;
    11391148
    1140 #if 0
     1149    /** @todo Snapshots */
     1150    Assert(!pIoCtxDst->cbTransferLeft && !pIoCtxDst->cMetaTransfersPending);
     1151
     1152    vdIoCtxChildReset(pIoCtxDst);
     1153    RTSgBufAdvance(&pIoCtxDst->SgBuf, cbPreRead);
     1154
    11411155    /* Check if the write would modify anything in this block. */
    1142     if (   !memcmp((char *)pvTmp + cbPreRead, pvBuf, cbThisWrite)
    1143         && (!cbWriteCopy || !memcmp((char *)pvTmp + cbPreRead + cbThisWrite,
    1144                                     (char *)pvBuf + cbThisWrite, cbWriteCopy)))
    1145     {
    1146         /* Block is completely unchanged, so no need to write anything. */
    1147         return VINF_SUCCESS;
     1156    if (!RTSgBufCmp(&pIoCtxDst->SgBuf, &pIoCtxSrc->SgBuf, cbThisWrite))
     1157    {
     1158        RTSGBUF SgBufSrcTmp;
     1159
     1160        RTSgBufClone(&SgBufSrcTmp, &pIoCtxSrc->SgBuf);
     1161        RTSgBufAdvance(&SgBufSrcTmp, cbThisWrite);
     1162        RTSgBufAdvance(&pIoCtxDst->SgBuf, cbThisWrite);
     1163
     1164        if (!cbWriteCopy || !RTSgBufCmp(&pIoCtxDst->SgBuf, &SgBufSrcTmp, cbWriteCopy))
     1165        {
     1166            /* Block is completely unchanged, so no need to write anything. */
     1167            LogFlowFunc(("Block didn't changed\n"));
     1168            ASMAtomicWriteU32(&pIoCtxDst->cbTransferLeft, 0);
     1169            return VINF_SUCCESS;
     1170        }
    11481171    }
    11491172
    11501173    /* Copy the data to the right place in the buffer. */
    1151     memcpy((char *)pvTmp + cbPreRead, pvBuf, cbThisWrite);
     1174    RTSgBufReset(&pIoCtxDst->SgBuf);
     1175    RTSgBufAdvance(&pIoCtxDst->SgBuf, cbPreRead);
     1176    vdIoCtxCopy(pIoCtxDst, pIoCtxSrc, cbThisWrite);
    11521177
    11531178    /* Handle the data that goes after the write to fill the block. */
     
    11561181        /* Now assemble the remaining data. */
    11571182        if (cbWriteCopy)
    1158             memcpy((char *)pvTmp + cbPreRead + cbThisWrite,
    1159                    (char *)pvBuf + cbThisWrite, cbWriteCopy);
     1183            vdIoCtxCopy(pIoCtxDst, pIoCtxSrc, cbWriteCopy);
    11601184        /* Zero out the remainder of this block. Will never be visible, as this
    11611185         * is beyond the limit of the image. */
    11621186        if (cbFill)
    1163             memset((char *)pvTmp + cbPreRead + cbThisWrite + cbWriteCopy + cbReadImage,
    1164                    '\0', cbFill);
     1187        {
     1188            RTSgBufAdvance(&pIoCtxDst->SgBuf, cbReadImage);
     1189            vdIoCtxSet(pIoCtxDst, '\0', cbFill);
     1190        }
    11651191    }
    11661192
    11671193    /* Write the full block to the virtual disk. */
    1168     rc = pImage->Backend->pfnWrite(pImage->pvBackendData,
    1169                                    uOffset - cbPreRead, pvTmp,
    1170                                    cbPreRead + cbThisWrite + cbPostRead,
    1171                                    NULL, &cbPreRead, &cbPostRead, 0);
     1194    RTSgBufReset(&pIoCtxDst->SgBuf);
     1195    rc = pImage->Backend->pfnAsyncWrite(pImage->pvBackendData,
     1196                                        uOffset - cbPreRead,
     1197                                        cbPreRead + cbThisWrite + cbPostRead,
     1198                                        pIoCtxDst, NULL, &cbPreRead, &cbPostRead, 0);
    11721199    Assert(rc != VERR_VD_BLOCK_FREE);
    11731200    Assert(cbPreRead == 0);
    11741201    Assert(cbPostRead == 0);
    1175 #endif
     1202
    11761203    return rc;
    11771204}
     
    12111238             * A bit hackish but avoids the need to allocate memory twice.
    12121239             */
    1213             PRTSGSEG pTmp = (PRTSGSEG)RTMemTmpAlloc(cbPreRead + cbThisWrite + cbPostRead + sizeof(RTSGSEG));
     1240            PRTSGSEG pTmp = (PRTSGSEG)RTMemAlloc(cbPreRead + cbThisWrite + cbPostRead + sizeof(RTSGSEG));
    12141241            AssertBreakStmt(VALID_PTR(pTmp), rc = VERR_NO_MEMORY);
    12151242
     
    12181245
    12191246            PVDIOCTX pIoCtxWrite = vdIoCtxChildAlloc(pDisk, VDIOCTXTXDIR_WRITE,
    1220                                                      uOffset, pTmp->cbSeg,
     1247                                                     uOffset - cbPreRead, pTmp->cbSeg,
    12211248                                                     pTmp, 1,
    1222                                                      pIoCtx, cbThisWrite);
     1249                                                     pIoCtx, cbThisWrite,
     1250                                                     pTmp);
    12231251            if (!VALID_PTR(pIoCtxWrite))
    12241252            {
     
    12511279            if (RT_FAILURE(rc))
    12521280            {
    1253                 RTMemTmpFree(pTmp);
    12541281                vdIoCtxFree(pDisk, pIoCtxWrite);
    12551282                break;
     
    12591286                && ASMAtomicCmpXchgBool(&pIoCtxWrite->fComplete, true, false))
    12601287            {
     1288                LogFlow(("Child write request completed\n"));
    12611289                RTMemTmpFree(pTmp);
    12621290                ASMAtomicSubU32(&pIoCtx->cbTransferLeft, cbThisWrite);
    12631291                vdIoCtxFree(pDisk, pIoCtxWrite);
    12641292            }
     1293            else
     1294                LogFlow(("Child write pending\n"));
    12651295        }
    12661296
     
    15511581    {
    15521582        LogFlowFunc(("I/O context completed\n"));
    1553         Assert(!pIoCtx->pIoCtxParent);
    1554         pIoCtx->Type.Root.pfnComplete(pIoCtx->Type.Root.pvUser1, pIoCtx->Type.Root.pvUser2);
     1583        if (pIoCtx->pIoCtxParent)
     1584        {
     1585            PVDIOCTX pIoCtxParent = pIoCtx->pIoCtxParent;
     1586
     1587            /* Update the parent state. */
     1588            Assert(!pIoCtxParent->pIoCtxParent);
     1589            Assert(pIoCtx->enmTxDir == VDIOCTXTXDIR_WRITE);
     1590            RTMemFree((void *)pIoCtx->SgBuf.pcaSeg); /* This will also free the attached buffer. */
     1591            ASMAtomicSubU32(&pIoCtxParent->cbTransferLeft, pIoCtx->Type.Child.cbTransferParent);
     1592
     1593            if (   !pIoCtxParent->cbTransferLeft
     1594                && !pIoCtxParent->cMetaTransfersPending
     1595                && ASMAtomicCmpXchgBool(&pIoCtxParent->fComplete, true, false))
     1596            {
     1597                pIoCtxParent->Type.Root.pfnComplete(pIoCtxParent->Type.Root.pvUser1, pIoCtxParent->Type.Root.pvUser2);
     1598                vdIoCtxFree(pDisk, pIoCtxParent);
     1599            }
     1600        }
     1601        else
     1602            pIoCtx->Type.Root.pfnComplete(pIoCtx->Type.Root.pvUser1, pIoCtx->Type.Root.pvUser2);
     1603
    15551604        vdIoCtxFree(pDisk, pIoCtx);
    15561605    }
     
    55345583        pIoCtx = vdIoCtxRootAlloc(pDisk, VDIOCTXTXDIR_READ, uOffset,
    55355584                                  cbRead, paSeg, cSeg,
    5536                                   pfnComplete, pvUser1, pvUser2);
     5585                                  pfnComplete, pvUser1, pvUser2,
     5586                                  NULL);
    55375587        if (!pIoCtx)
    55385588        {
     
    56145664                           rc = VERR_INVALID_PARAMETER);
    56155665
    5616         pIoCtx = vdIoCtxRootAlloc(pDisk, VDIOCTXTXDIR_READ, uOffset,
     5666        pIoCtx = vdIoCtxRootAlloc(pDisk, VDIOCTXTXDIR_WRITE, uOffset,
    56175667                                  cbWrite, paSeg, cSeg,
    5618                                   pfnComplete, pvUser1, pvUser2);
     5668                                  pfnComplete, pvUser1, pvUser2,
     5669                                  NULL);
    56195670        if (!pIoCtx)
    56205671        {
  • trunk/src/VBox/Devices/Storage/VDIHDDCore.cpp

    r28065 r28154  
    712712{
    713713    int rc;
    714 
    715     if (uOpenFlags & VD_OPEN_FLAGS_ASYNC_IO)
    716         return VERR_NOT_SUPPORTED;
    717714
    718715    pImage->uOpenFlags = uOpenFlags;
     
    16321629    /* Image must be opened and the new flags must be valid. Just readonly and
    16331630     * info flags are supported. */
    1634     if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO)))
     1631    if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO)))
    16351632    {
    16361633        rc = VERR_INVALID_PARAMETER;
     
    20492046static bool vdiIsAsyncIOSupported(void *pBackendData)
    20502047{
    2051 #if 0
    20522048    return true;
    2053 #else
    2054     return false;
    2055 #endif
    20562049}
    20572050
     
    24842477    /* uBackendCaps */
    24852478      VD_CAP_UUID | VD_CAP_CREATE_FIXED | VD_CAP_CREATE_DYNAMIC
    2486     | VD_CAP_DIFF | VD_CAP_FILE
    2487 #if 0
    2488     | VD_CAP_ASYNC
    2489 #endif
    2490     ,
     2479    | VD_CAP_DIFF | VD_CAP_FILE | VD_CAP_ASYNC,
    24912480    /* papszFileExtensions */
    24922481    s_apszVdiFileExtensions,
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