VirtualBox

Changeset 44242 in vbox for trunk/src/VBox/Storage


Ignore:
Timestamp:
Jan 7, 2013 8:19:15 PM (12 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
83098
Message:

Storage: Next step in the sync/async I/O unification, change all calls to pfnRead/pfnWrite/pfnFlush to pfnAsyncRead/pfnAsyncWrite/pfnFlush

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Storage/ISCSI.cpp

    r44232 r44242  
    52805280                          PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
    52815281{
     5282    PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
     5283    int rc = VINF_SUCCESS;
     5284
    52825285    LogFlowFunc(("pBackendData=%p uOffset=%#llx pIoCtx=%#p cbToRead=%u pcbActuallyRead=%p\n",
    52835286                 pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead));
    5284     PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
    5285     int rc = VINF_SUCCESS;
    5286 
    5287     if (uOffset + cbToRead > pImage->cbSize)
     5287
     5288    if (   uOffset + cbToRead > pImage->cbSize
     5289        || cbToRead == 0)
    52885290        return VERR_INVALID_PARAMETER;
    52895291
     
    52925294     */
    52935295    cbToRead = RT_MIN(cbToRead, pImage->cbRecvDataLength);
     5296
     5297    /** @todo: Remove iscsiRead and integrate properly. */
     5298    if (vdIfIoIntIoCtxIsSynchronous(pImage->pIfIo, pIoCtx))
     5299    {
     5300        RTSGSEG Segment;
     5301        unsigned cSegments = 1;
     5302        size_t cbSegs;
     5303
     5304        cbSegs = pImage->pIfIo->pfnIoCtxSegArrayCreate(pImage->pIfIo->Core.pvUser, pIoCtx,
     5305                                                       &Segment, &cSegments, cbToRead);
     5306        Assert(cbSegs == cbToRead);
     5307
     5308        return iscsiRead(pBackendData, uOffset, Segment.pvSeg, cbToRead, pcbActuallyRead);
     5309    }
    52945310
    52955311    unsigned cT2ISegs = 0;
     
    54185434    cbToWrite = RT_MIN(cbToWrite, pImage->cbSendDataLength);
    54195435
     5436    /** @todo: Remove iscsiWrite and integrate properly. */
     5437    if (vdIfIoIntIoCtxIsSynchronous(pImage->pIfIo, pIoCtx))
     5438    {
     5439        RTSGSEG Segment;
     5440        unsigned cSegments = 1;
     5441        size_t cbSegs;
     5442
     5443        cbSegs = pImage->pIfIo->pfnIoCtxSegArrayCreate(pImage->pIfIo->Core.pvUser, pIoCtx,
     5444                                                       &Segment, &cSegments, cbToWrite);
     5445        Assert(cbSegs == cbToWrite);
     5446
     5447        return iscsiWrite(pBackendData, uOffset, Segment.pvSeg, cbToWrite,
     5448                          pcbWriteProcess, pcbPreRead, pcbPostRead, fWrite);
     5449    }
     5450
    54205451    unsigned cI2TSegs = 0;
    54215452    size_t   cbSegs = 0;
     
    55265557    PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
    55275558    int rc = VINF_SUCCESS;
     5559
     5560    /** @todo: Remove iscsiFlush and integrate properly. */
     5561    if (vdIfIoIntIoCtxIsSynchronous(pImage->pIfIo, pIoCtx))
     5562        return iscsiFlush(pBackendData);
    55285563
    55295564    PSCSIREQASYNC pReqAsync = (PSCSIREQASYNC)RTMemAllocZ(sizeof(SCSIREQASYNC));
  • trunk/src/VBox/Storage/VD.cpp

    r44233 r44242  
    306306    /** Return code. */
    307307    int                          rcReq;
    308     /** Flag whether the I/O context is blocked because it is in the growing list. */
    309     bool                         fBlocked;
     308    /** Various flags for the I/O context. */
     309    uint32_t                     fFlags;
    310310    /** Number of data transfers currently pending. */
    311311    volatile uint32_t            cDataTransfersPending;
     
    410410} VDIOCTX;
    411411
     412/** Flag whether the context is blocked. */
     413#define VDIOCTX_FLAGS_BLOCKED RT_BIT_32(0)
     414/** Flag whether the I/O context is using synchronous I/O. */
     415#define VDIOCTX_FLAGS_SYNC    RT_BIT_32(1)
     416
    412417/**
    413418 * List node for deferred I/O contexts.
     
    763768    }
    764769    return pImage;
     770}
     771
     772/**
     773 * Initialize the structure members of a given I/O context.
     774 */
     775DECLINLINE(void) vdIoCtxInit(PVDIOCTX pIoCtx, PVBOXHDD pDisk, VDIOCTXTXDIR enmTxDir,
     776                             uint64_t uOffset, size_t cbTransfer, PVDIMAGE pImageStart,
     777                             PCRTSGBUF pcSgBuf, void *pvAllocation,
     778                             PFNVDIOCTXTRANSFER pfnIoCtxTransfer, uint32_t fFlags)
     779{
     780    pIoCtx->pDisk                 = pDisk;
     781    pIoCtx->enmTxDir              = enmTxDir;
     782    pIoCtx->Req.Io.cbTransferLeft = cbTransfer;
     783    pIoCtx->Req.Io.uOffset        = uOffset;
     784    pIoCtx->Req.Io.cbTransfer     = cbTransfer;
     785    pIoCtx->Req.Io.pImageStart    = pImageStart;
     786    pIoCtx->Req.Io.pImageCur      = pImageStart;
     787    pIoCtx->cDataTransfersPending = 0;
     788    pIoCtx->cMetaTransfersPending = 0;
     789    pIoCtx->fComplete             = false;
     790    pIoCtx->fFlags                = fFlags;
     791    pIoCtx->pvAllocation          = pvAllocation;
     792    pIoCtx->pfnIoCtxTransfer      = pfnIoCtxTransfer;
     793    pIoCtx->pfnIoCtxTransferNext  = NULL;
     794    pIoCtx->rcReq                 = VINF_SUCCESS;
     795
     796    /* There is no S/G list for a flush request. */
     797    if (   enmTxDir != VDIOCTXTXDIR_FLUSH
     798        && enmTxDir != VDIOCTXTXDIR_DISCARD)
     799        RTSgBufClone(&pIoCtx->Req.Io.SgBuf, pcSgBuf);
     800    else
     801        memset(&pIoCtx->Req.Io.SgBuf, 0, sizeof(RTSGBUF));
    765802}
    766803
     
    794831    AssertPtr(pcbRead);
    795832
     833#if 0 /** @todo: Cache implementation update */
    796834    rc = pCache->Backend->pfnRead(pCache->pBackendData, uOffset, pvBuf,
    797835                                  cbRead, pcbRead);
     836#endif
    798837
    799838    LogFlowFunc(("returns rc=%Rrc pcbRead=%zu\n", rc, *pcbRead));
     
    823862    Assert(cbWrite > 0);
    824863
     864#if 0 /** @todo: Change cache implementation */
    825865    if (pcbWritten)
    826866        rc = pCache->Backend->pfnWrite(pCache->pBackendData, uOffset, pcvBuf,
     
    840880                 && RT_SUCCESS(rc));
    841881    }
     882#endif
    842883
    843884    LogFlowFunc(("returns rc=%Rrc pcbWritten=%zu\n",
     
    854895    int rc = VINF_SUCCESS;
    855896    size_t cbThisRead = cbRead;
     897    RTSGSEG SegmentBuf;
     898    RTSGBUF SgBuf;
     899    VDIOCTX IoCtx;
    856900
    857901    AssertPtr(pcbThisRead);
    858902
    859903    *pcbThisRead = 0;
     904
     905    SegmentBuf.pvSeg = pvBuf;
     906    SegmentBuf.cbSeg = VD_MERGE_BUFFER_SIZE;
     907    RTSgBufInit(&SgBuf, &SegmentBuf, 1);
     908    vdIoCtxInit(&IoCtx, pDisk, VDIOCTXTXDIR_READ, 0, 0, NULL,
     909                &SgBuf, NULL, NULL, VDIOCTX_FLAGS_SYNC);
    860910
    861911    /*
     
    863913     * If the block is not allocated read from override chain if present.
    864914     */
    865     rc = pImage->Backend->pfnRead(pImage->pBackendData,
    866                                   uOffset, pvBuf, cbThisRead,
    867                                   &cbThisRead);
     915    rc = pImage->Backend->pfnAsyncRead(pImage->pBackendData,
     916                                       uOffset, cbThisRead, &IoCtx,
     917                                       &cbThisRead);
    868918
    869919    if (rc == VERR_VD_BLOCK_FREE)
     
    873923             pCurrImage = pCurrImage->pPrev)
    874924        {
    875             rc = pCurrImage->Backend->pfnRead(pCurrImage->pBackendData,
    876                                               uOffset, pvBuf, cbThisRead,
    877                                               &cbThisRead);
     925            rc = pCurrImage->Backend->pfnAsyncRead(pCurrImage->pBackendData,
     926                                                   uOffset, cbThisRead, &IoCtx,
     927                                                   &cbThisRead);
    878928        }
    879929    }
     
    949999        else
    9501000        {
    951             /** @todo can be be replaced by vdDiskReadHelper if it proves to be reliable,
    952              * don't want to be responsible for data corruption...
    953              */
     1001            RTSGSEG SegmentBuf;
     1002            RTSGBUF SgBuf;
     1003            VDIOCTX IoCtx;
     1004
     1005            SegmentBuf.pvSeg = pvBuf;
     1006            SegmentBuf.cbSeg = cbThisRead;
     1007            RTSgBufInit(&SgBuf, &SegmentBuf, 1);
     1008            vdIoCtxInit(&IoCtx, pDisk, VDIOCTXTXDIR_READ, 0, 0, NULL,
     1009                        &SgBuf, NULL, NULL, VDIOCTX_FLAGS_SYNC);
     1010
    9541011            /*
    9551012             * Try to read from the given image.
    9561013             * If the block is not allocated read from override chain if present.
    9571014             */
    958             rc = pImage->Backend->pfnRead(pImage->pBackendData,
    959                                           uOffset, pvBuf, cbThisRead,
    960                                           &cbThisRead);
     1015            rc = pImage->Backend->pfnAsyncRead(pImage->pBackendData,
     1016                                               uOffset, cbThisRead, &IoCtx,
     1017                                               &cbThisRead);
    9611018
    9621019            if (   rc == VERR_VD_BLOCK_FREE
     
    9691026                     pCurrImage = pCurrImage->pPrev)
    9701027                {
    971                     rc = pCurrImage->Backend->pfnRead(pCurrImage->pBackendData,
    972                                                       uOffset, pvBuf, cbThisRead,
    973                                                       &cbThisRead);
     1028                    rc = pCurrImage->Backend->pfnAsyncRead(pCurrImage->pBackendData,
     1029                                                           uOffset, cbThisRead,
     1030                                                           &IoCtx, &cbThisRead);
    9741031                    if (cImagesToProcess == 1)
    9751032                        break;
     
    11001157                    cbThis = (idxEnd - idxStart) * 512;
    11011158
    1102                 rc = pDisk->pLast->Backend->pfnDiscard(pDisk->pLast->pBackendData, offStart,
    1103                                                        cbThis, NULL, NULL, &cbThis,
    1104                                                        NULL, VD_DISCARD_MARK_UNUSED);
     1159
     1160                VDIOCTX IoCtx;
     1161                vdIoCtxInit(&IoCtx, pDisk, VDIOCTXTXDIR_DISCARD, 0, 0, NULL,
     1162                            NULL, NULL, NULL, VDIOCTX_FLAGS_SYNC);
     1163                rc = pDisk->pLast->Backend->pfnAsyncDiscard(pDisk->pLast->pBackendData,
     1164                                                            &IoCtx, offStart, cbThis, NULL,
     1165                                                            NULL, &cbThis, NULL,
     1166                                                            VD_DISCARD_MARK_UNUSED);
    11051167                if (RT_FAILURE(rc))
    11061168                    break;
     
    11901252
    11911253            /* No block found, try to discard using the backend first. */
    1192             rc = pDisk->pLast->Backend->pfnDiscard(pDisk->pLast->pBackendData, offStart,
    1193                                                    cbThisDiscard, &cbPreAllocated,
    1194                                                    &cbPostAllocated, &cbThisDiscard,
    1195                                                    &pbmAllocated, 0);
     1254            VDIOCTX IoCtx;
     1255
     1256            vdIoCtxInit(&IoCtx, pDisk, VDIOCTXTXDIR_DISCARD, 0, 0, NULL,
     1257                        NULL, NULL, NULL, VDIOCTX_FLAGS_SYNC);
     1258            rc = pDisk->pLast->Backend->pfnAsyncDiscard(pDisk->pLast->pBackendData,
     1259                                                        &IoCtx, offStart,
     1260                                                        cbThisDiscard, &cbPreAllocated,
     1261                                                        &cbPostAllocated, &cbThisDiscard,
     1262                                                        &pbmAllocated, 0);
    11961263            if (rc == VERR_VD_DISCARD_ALIGNMENT_NOT_MET)
    11971264            {
     
    12411308            if (ASMBitFirstSet((volatile void *)pBlock->pbmAllocated, pBlock->cbDiscard / 512) == -1)
    12421309            {
     1310                VDIOCTX IoCtx;
    12431311                size_t cbPreAllocated, cbPostAllocated, cbActuallyDiscarded;
    12441312
    1245                 rc = pDisk->pLast->Backend->pfnDiscard(pDisk->pLast->pBackendData, pBlock->Core.Key,
    1246                                                        pBlock->cbDiscard, &cbPreAllocated,
    1247                                                        &cbPostAllocated, &cbActuallyDiscarded,
    1248                                                        NULL, 0);
     1313                vdIoCtxInit(&IoCtx, pDisk, VDIOCTXTXDIR_DISCARD, 0, 0, NULL,
     1314                            NULL, NULL, NULL, VDIOCTX_FLAGS_SYNC);
     1315                rc = pDisk->pLast->Backend->pfnAsyncDiscard(pDisk->pLast->pBackendData,
     1316                                                            &IoCtx, pBlock->Core.Key,
     1317                                                            pBlock->cbDiscard, &cbPreAllocated,
     1318                                                            &cbPostAllocated, &cbActuallyDiscarded,
     1319                                                            NULL, 0);
    12491320                Assert(rc != VERR_VD_DISCARD_ALIGNMENT_NOT_MET);
    12501321                Assert(!cbPreAllocated);
     
    13691440DECLINLINE(PVDIOCTX) vdIoCtxAlloc(PVBOXHDD pDisk, VDIOCTXTXDIR enmTxDir,
    13701441                                  uint64_t uOffset, size_t cbTransfer,
    1371                                   PVDIMAGE pImageStart,
    1372                                   PCRTSGBUF pcSgBuf, void *pvAllocation,
    1373                                   PFNVDIOCTXTRANSFER pfnIoCtxTransfer)
     1442                                  PVDIMAGE pImageStart,PCRTSGBUF pcSgBuf,
     1443                                  void *pvAllocation, PFNVDIOCTXTRANSFER pfnIoCtxTransfer,
     1444                                  uint32_t fFlags)
    13741445{
    13751446    PVDIOCTX pIoCtx = NULL;
     
    13781449    if (RT_LIKELY(pIoCtx))
    13791450    {
    1380         pIoCtx->pDisk                 = pDisk;
    1381         pIoCtx->enmTxDir              = enmTxDir;
    1382         pIoCtx->Req.Io.cbTransferLeft = cbTransfer;
    1383         pIoCtx->Req.Io.uOffset        = uOffset;
    1384         pIoCtx->Req.Io.cbTransfer     = cbTransfer;
    1385         pIoCtx->Req.Io.pImageStart    = pImageStart;
    1386         pIoCtx->Req.Io.pImageCur      = pImageStart;
    1387         pIoCtx->cDataTransfersPending = 0;
    1388         pIoCtx->cMetaTransfersPending = 0;
    1389         pIoCtx->fComplete             = false;
    1390         pIoCtx->fBlocked              = false;
    1391         pIoCtx->pvAllocation          = pvAllocation;
    1392         pIoCtx->pfnIoCtxTransfer      = pfnIoCtxTransfer;
    1393         pIoCtx->pfnIoCtxTransferNext  = NULL;
    1394         pIoCtx->rcReq                 = VINF_SUCCESS;
    1395 
    1396         /* There is no S/G list for a flush request. */
    1397         if (enmTxDir != VDIOCTXTXDIR_FLUSH)
    1398             RTSgBufClone(&pIoCtx->Req.Io.SgBuf, pcSgBuf);
    1399         else
    1400             memset(&pIoCtx->Req.Io.SgBuf, 0, sizeof(RTSGBUF));
     1451        vdIoCtxInit(pIoCtx, pDisk, enmTxDir, uOffset, cbTransfer, pImageStart,
     1452                    pcSgBuf, pvAllocation, pfnIoCtxTransfer, fFlags);
    14011453    }
    14021454
     
    14131465{
    14141466    PVDIOCTX pIoCtx = vdIoCtxAlloc(pDisk, enmTxDir, uOffset, cbTransfer, pImageStart,
    1415                                    pcSgBuf, pvAllocation, pfnIoCtxTransfer);
     1467                                   pcSgBuf, pvAllocation, pfnIoCtxTransfer, 0);
    14161468
    14171469    if (RT_LIKELY(pIoCtx))
     
    14451497        pIoCtx->cMetaTransfersPending     = 0;
    14461498        pIoCtx->fComplete                 = false;
    1447         pIoCtx->fBlocked                  = false;
     1499        pIoCtx->fFlags                    = 0;
    14481500        pIoCtx->pvAllocation              = pvAllocation;
    14491501        pIoCtx->pfnIoCtxTransfer          = pfnIoCtxTransfer;
     
    14751527{
    14761528    PVDIOCTX pIoCtx = vdIoCtxAlloc(pDisk, enmTxDir, uOffset, cbTransfer, pImageStart,
    1477                                    pcSgBuf, pvAllocation, pfnIoCtxTransfer);
     1529                                   pcSgBuf, pvAllocation, pfnIoCtxTransfer, 0);
    14781530
    14791531    AssertPtr(pIoCtxParent);
     
    15791631    LogFlowFunc(("Deferring write pIoCtx=%#p\n", pIoCtx));
    15801632
    1581     Assert(!pIoCtx->pIoCtxParent && !pIoCtx->fBlocked);
     1633    Assert(!pIoCtx->pIoCtxParent && !(pIoCtx->fFlags & VDIOCTX_FLAGS_BLOCKED));
    15821634
    15831635    RTListInit(&pDeferred->NodeDeferred);
    15841636    pDeferred->pIoCtx = pIoCtx;
    15851637    RTListAppend(&pDisk->ListWriteLocked, &pDeferred->NodeDeferred);
    1586     pIoCtx->fBlocked = true;
     1638    pIoCtx->fFlags |= VDIOCTX_FLAGS_BLOCKED;
    15871639    return VINF_SUCCESS;
    15881640}
     
    16511703    /* Don't change anything if there is a metadata transfer pending or we are blocked. */
    16521704    if (   pIoCtx->cMetaTransfersPending
    1653         || pIoCtx->fBlocked)
     1705        || (pIoCtx->fFlags & VDIOCTX_FLAGS_BLOCKED))
    16541706    {
    16551707        rc = VERR_VD_ASYNC_IO_IN_PROGRESS;
     
    19552007                Assert(!pIoCtxWait->pIoCtxParent);
    19562008
    1957                 pIoCtxWait->fBlocked = false;
     2009                pIoCtxWait->fFlags &= ~VDIOCTX_FLAGS_BLOCKED;
    19582010                LogFlowFunc(("Processing waiting I/O context pIoCtxWait=%#p\n", pIoCtxWait));
    19592011
     
    20322084            uOffset  += cbThisRead;
    20332085            cbToRead -= cbThisRead;
    2034             pIoCtx->fBlocked = true;
     2086            pIoCtx->fFlags |= VDIOCTX_FLAGS_BLOCKED;
    20352087        }
    20362088
     
    21052157
    21062158        if (!(pDisk->uModified & VD_IMAGE_MODIFIED_DISABLE_UUID_UPDATE))
    2107             pDisk->pLast->Backend->pfnFlush(pDisk->pLast->pBackendData);
     2159        {
     2160            VDIOCTX IoCtx;
     2161            vdIoCtxInit(&IoCtx, pDisk, VDIOCTXTXDIR_FLUSH, 0, 0, NULL,
     2162                        NULL, NULL, NULL, VDIOCTX_FLAGS_SYNC);
     2163            pDisk->pLast->Backend->pfnAsyncFlush(pDisk->pLast->pBackendData, &IoCtx);
     2164        }
    21082165    }
    21092166}
     
    21832240
    21842241    /* Write the full block to the virtual disk. */
    2185     rc = pImage->Backend->pfnWrite(pImage->pBackendData,
    2186                                    uOffset - cbPreRead, pvTmp,
    2187                                    cbPreRead + cbThisWrite + cbPostRead,
    2188                                    NULL, &cbPreRead, &cbPostRead, 0);
     2242    RTSGSEG SegmentBuf;
     2243    RTSGBUF SgBuf;
     2244    VDIOCTX IoCtx;
     2245
     2246    SegmentBuf.pvSeg = pvTmp;
     2247    SegmentBuf.cbSeg = cbPreRead + cbThisWrite + cbPostRead;
     2248    RTSgBufInit(&SgBuf, &SegmentBuf, 1);
     2249    vdIoCtxInit(&IoCtx, pDisk, VDIOCTXTXDIR_WRITE, 0, 0, NULL,
     2250                &SgBuf, NULL, NULL, VDIOCTX_FLAGS_SYNC);
     2251    rc = pImage->Backend->pfnAsyncWrite(pImage->pBackendData, uOffset - cbPreRead,
     2252                                        cbPreRead + cbThisWrite + cbPostRead,
     2253                                        &IoCtx, NULL, &cbPreRead, &cbPostRead, 0);
    21892254    Assert(rc != VERR_VD_BLOCK_FREE);
    21902255    Assert(cbPreRead == 0);
     
    22652330
    22662331    /* Write the full block to the virtual disk. */
    2267     rc = pImage->Backend->pfnWrite(pImage->pBackendData,
    2268                                    uOffset - cbPreRead, pvTmp,
    2269                                    cbPreRead + cbThisWrite + cbPostRead,
    2270                                    NULL, &cbPreRead, &cbPostRead, 0);
     2332    RTSGSEG SegmentBuf;
     2333    RTSGBUF SgBuf;
     2334    VDIOCTX IoCtx;
     2335
     2336    SegmentBuf.pvSeg = pvTmp;
     2337    SegmentBuf.cbSeg = cbPreRead + cbThisWrite + cbPostRead;
     2338    RTSgBufInit(&SgBuf, &SegmentBuf, 1);
     2339    vdIoCtxInit(&IoCtx, pDisk, VDIOCTXTXDIR_WRITE, 0, 0, NULL,
     2340                &SgBuf, NULL, NULL, VDIOCTX_FLAGS_SYNC);
     2341    rc = pImage->Backend->pfnAsyncWrite(pImage->pBackendData, uOffset - cbPreRead,
     2342                                        cbPreRead + cbThisWrite + cbPostRead,
     2343                                        &IoCtx, NULL, &cbPreRead, &cbPostRead, 0);
    22712344    Assert(rc != VERR_VD_BLOCK_FREE);
    22722345    Assert(cbPreRead == 0);
     
    22922365    size_t cbWriteCur = cbWrite;
    22932366    const void *pcvBufCur = pvBuf;
     2367    RTSGSEG SegmentBuf;
     2368    RTSGBUF SgBuf;
     2369    VDIOCTX IoCtx;
    22942370
    22952371    /* Loop until all written. */
     
    23052381        fWrite =   (pImage->uOpenFlags & VD_OPEN_FLAGS_HONOR_SAME)
    23062382                 ? 0 : VD_WRITE_NO_ALLOC;
    2307         rc = pImage->Backend->pfnWrite(pImage->pBackendData, uOffsetCur, pcvBufCur,
    2308                                        cbThisWrite, &cbThisWrite, &cbPreRead,
    2309                                        &cbPostRead, fWrite);
     2383
     2384        SegmentBuf.pvSeg = (void *)pcvBufCur;
     2385        SegmentBuf.cbSeg = cbWrite;
     2386        RTSgBufInit(&SgBuf, &SegmentBuf, 1);
     2387        vdIoCtxInit(&IoCtx, pDisk, VDIOCTXTXDIR_WRITE, 0, 0, NULL,
     2388                    &SgBuf, NULL, NULL, VDIOCTX_FLAGS_SYNC);
     2389        rc = pImage->Backend->pfnAsyncWrite(pImage->pBackendData, uOffsetCur, cbThisWrite,
     2390                                            &IoCtx, &cbThisWrite, &cbPreRead,
     2391                                            &cbPostRead, fWrite);
    23102392        if (rc == VERR_VD_BLOCK_FREE)
    23112393        {
     
    24082490        if (fBlockwiseCopy)
    24092491        {
     2492            RTSGSEG SegmentBuf;
     2493            RTSGBUF SgBuf;
     2494            VDIOCTX IoCtx;
     2495
     2496            SegmentBuf.pvSeg = pvBuf;
     2497            SegmentBuf.cbSeg = VD_MERGE_BUFFER_SIZE;
     2498            RTSgBufInit(&SgBuf, &SegmentBuf, 1);
     2499            vdIoCtxInit(&IoCtx, pDiskFrom, VDIOCTXTXDIR_READ, 0, 0, NULL,
     2500                        &SgBuf, NULL, NULL, VDIOCTX_FLAGS_SYNC);
     2501
    24102502            /* Read the source data. */
    2411             rc = pImageFrom->Backend->pfnRead(pImageFrom->pBackendData,
    2412                                               uOffset, pvBuf, cbThisRead,
    2413                                               &cbThisRead);
     2503            rc = pImageFrom->Backend->pfnAsyncRead(pImageFrom->pBackendData,
     2504                                                   uOffset, cbThisRead, &IoCtx,
     2505                                                   &cbThisRead);
    24142506
    24152507            if (   rc == VERR_VD_BLOCK_FREE
     
    24222514                     pCurrImage = pCurrImage->pPrev)
    24232515                {
    2424                     rc = pCurrImage->Backend->pfnRead(pCurrImage->pBackendData,
    2425                                                       uOffset, pvBuf, cbThisRead,
    2426                                                       &cbThisRead);
     2516                    rc = pCurrImage->Backend->pfnAsyncRead(pCurrImage->pBackendData,
     2517                                                           uOffset, cbThisRead,
     2518                                                           &IoCtx, &cbThisRead);
    24272519                    if (cImagesToProcess == 1)
    24282520                        break;
     
    25582650                    {
    25592651                        ASMAtomicIncU32(&pIoCtx->cDataTransfersPending);
    2560                         pIoCtx->fBlocked = true;
     2652                        pIoCtx->fFlags |= VDIOCTX_FLAGS_BLOCKED;
    25612653                    }
    25622654                    else /* Another error */
     
    26862778    else if (rc == VERR_VD_IOCTX_HALT)
    26872779    {
    2688         pIoCtx->fBlocked = true;
     2780        pIoCtx->fFlags |= VDIOCTX_FLAGS_BLOCKED;
    26892781        rc = VINF_SUCCESS;
    26902782    }
     
    29483040                    LogFlow(("Child write pending\n"));
    29493041                    ASMAtomicIncU32(&pIoCtx->cDataTransfersPending);
    2950                     pIoCtx->fBlocked = true;
     3042                    pIoCtx->fFlags |= VDIOCTX_FLAGS_BLOCKED;
    29513043                    rc = VERR_VD_ASYNC_IO_IN_PROGRESS;
    29523044                    cbWrite -= cbThisWrite;
     
    29663058            cbWrite -= cbThisWrite;
    29673059            uOffset += cbThisWrite;
    2968             pIoCtx->fBlocked = true;
     3060            pIoCtx->fFlags |= VDIOCTX_FLAGS_BLOCKED;
    29693061            break;
    29703062        }
     
    37513843        ASMAtomicCmpXchgS32(&pIoCtx->rcReq, rcReq, VINF_SUCCESS);
    37523844
    3753     if (!pIoCtx->fBlocked)
     3845    if (!(pIoCtx->fFlags & VDIOCTX_FLAGS_BLOCKED))
    37543846    {
    37553847        /* Continue the transfer */
     
    37893881
    37903882                /* Unblock the parent */
    3791                 pIoCtxParent->fBlocked = false;
     3883                pIoCtxParent->fFlags &= ~VDIOCTX_FLAGS_BLOCKED;
    37923884
    37933885                rc = vdIoCtxProcess(pIoCtxParent);
     
    38353927                        Assert(!pIoCtxWait->pIoCtxParent);
    38363928
    3837                         pIoCtxWait->fBlocked = false;
     3929                        pIoCtxWait->fFlags &= ~VDIOCTX_FLAGS_BLOCKED;
    38383930                        LogFlowFunc(("Processing waiting I/O context pIoCtxWait=%#p\n", pIoCtxWait));
    38393931
     
    41384230                 pvUser, pIoStorage, uOffset, pIoCtx, cbRead));
    41394231
    4140     VD_THREAD_IS_CRITSECT_OWNER(pDisk);
    4141 
    4142     /** @todo: Handle synchronous I/O contexts. */
     4232    /** @todo: Enable check for sync I/O later. */
     4233    if (!(pIoCtx->fFlags & VDIOCTX_FLAGS_SYNC))
     4234        VD_THREAD_IS_CRITSECT_OWNER(pDisk);
    41434235
    41444236    Assert(cbRead > 0);
    41454237
    4146     /* Build the S/G array and spawn a new I/O task */
    4147     while (cbRead)
    4148     {
    4149         RTSGSEG  aSeg[VD_IO_TASK_SEGMENTS_MAX];
    4150         unsigned cSegments  = VD_IO_TASK_SEGMENTS_MAX;
    4151         size_t   cbTaskRead = 0;
    4152 
    4153         cbTaskRead = RTSgBufSegArrayCreate(&pIoCtx->Req.Io.SgBuf, aSeg, &cSegments, cbRead);
    4154 
    4155         Assert(cSegments > 0);
    4156         Assert(cbTaskRead > 0);
    4157         AssertMsg(cbTaskRead <= cbRead, ("Invalid number of bytes to read\n"));
    4158 
    4159         LogFlow(("Reading %u bytes into %u segments\n", cbTaskRead, cSegments));
     4238    if (pIoCtx->fFlags & VDIOCTX_FLAGS_SYNC)
     4239    {
     4240        RTSGSEG Seg;
     4241        unsigned cSegments = 1;
     4242        size_t cbTaskRead = 0;
     4243
     4244        /* Synchronous I/O contexts only have one buffer segment. */
     4245        AssertMsgReturn(pIoCtx->Req.Io.SgBuf.cSegs == 1,
     4246                        ("Invalid number of buffer segments for synchronous I/O context"),
     4247                        VERR_INVALID_PARAMETER);
     4248
     4249        cbTaskRead = RTSgBufSegArrayCreate(&pIoCtx->Req.Io.SgBuf, &Seg, &cSegments, cbRead);
     4250        Assert(cbRead == cbTaskRead);
     4251        Assert(cSegments == 1);
     4252        rc = pVDIo->pInterfaceIo->pfnReadSync(pVDIo->pInterfaceIo->Core.pvUser,
     4253                                              pIoStorage->pStorage, uOffset,
     4254                                              Seg.pvSeg, cbRead, NULL);
     4255    }
     4256    else
     4257    {
     4258        /* Build the S/G array and spawn a new I/O task */
     4259        while (cbRead)
     4260        {
     4261            RTSGSEG  aSeg[VD_IO_TASK_SEGMENTS_MAX];
     4262            unsigned cSegments  = VD_IO_TASK_SEGMENTS_MAX;
     4263            size_t   cbTaskRead = 0;
     4264
     4265            cbTaskRead = RTSgBufSegArrayCreate(&pIoCtx->Req.Io.SgBuf, aSeg, &cSegments, cbRead);
     4266
     4267            Assert(cSegments > 0);
     4268            Assert(cbTaskRead > 0);
     4269            AssertMsg(cbTaskRead <= cbRead, ("Invalid number of bytes to read\n"));
     4270
     4271            LogFlow(("Reading %u bytes into %u segments\n", cbTaskRead, cSegments));
    41604272
    41614273#ifdef RT_STRICT
    4162         for (unsigned i = 0; i < cSegments; i++)
    4163                 AssertMsg(aSeg[i].pvSeg && !(aSeg[i].cbSeg % 512),
    4164                           ("Segment %u is invalid\n", i));
     4274            for (unsigned i = 0; i < cSegments; i++)
     4275                    AssertMsg(aSeg[i].pvSeg && !(aSeg[i].cbSeg % 512),
     4276                              ("Segment %u is invalid\n", i));
    41654277#endif
    41664278
    4167         PVDIOTASK pIoTask = vdIoTaskUserAlloc(pIoStorage, NULL, NULL, pIoCtx, cbTaskRead);
    4168 
    4169         if (!pIoTask)
    4170             return VERR_NO_MEMORY;
    4171 
    4172         ASMAtomicIncU32(&pIoCtx->cDataTransfersPending);
    4173 
    4174         void *pvTask;
    4175         rc = pVDIo->pInterfaceIo->pfnReadAsync(pVDIo->pInterfaceIo->Core.pvUser,
    4176                                                pIoStorage->pStorage, uOffset,
    4177                                                aSeg, cSegments, cbTaskRead, pIoTask,
    4178                                                &pvTask);
    4179         if (RT_SUCCESS(rc))
    4180         {
    4181             AssertMsg(cbTaskRead <= pIoCtx->Req.Io.cbTransferLeft, ("Impossible!\n"));
    4182             ASMAtomicSubU32(&pIoCtx->Req.Io.cbTransferLeft, cbTaskRead);
    4183             ASMAtomicDecU32(&pIoCtx->cDataTransfersPending);
    4184             vdIoTaskFree(pDisk, pIoTask);
    4185         }
    4186         else if (rc != VERR_VD_ASYNC_IO_IN_PROGRESS)
    4187         {
    4188             ASMAtomicDecU32(&pIoCtx->cDataTransfersPending);
    4189             vdIoTaskFree(pDisk, pIoTask);
    4190             break;
    4191         }
    4192 
    4193         uOffset += cbTaskRead;
    4194         cbRead  -= cbTaskRead;
     4279            PVDIOTASK pIoTask = vdIoTaskUserAlloc(pIoStorage, NULL, NULL, pIoCtx, cbTaskRead);
     4280
     4281            if (!pIoTask)
     4282                return VERR_NO_MEMORY;
     4283
     4284            ASMAtomicIncU32(&pIoCtx->cDataTransfersPending);
     4285
     4286            void *pvTask;
     4287            rc = pVDIo->pInterfaceIo->pfnReadAsync(pVDIo->pInterfaceIo->Core.pvUser,
     4288                                                   pIoStorage->pStorage, uOffset,
     4289                                                   aSeg, cSegments, cbTaskRead, pIoTask,
     4290                                                   &pvTask);
     4291            if (RT_SUCCESS(rc))
     4292            {
     4293                AssertMsg(cbTaskRead <= pIoCtx->Req.Io.cbTransferLeft, ("Impossible!\n"));
     4294                ASMAtomicSubU32(&pIoCtx->Req.Io.cbTransferLeft, cbTaskRead);
     4295                ASMAtomicDecU32(&pIoCtx->cDataTransfersPending);
     4296                vdIoTaskFree(pDisk, pIoTask);
     4297            }
     4298            else if (rc != VERR_VD_ASYNC_IO_IN_PROGRESS)
     4299            {
     4300                ASMAtomicDecU32(&pIoCtx->cDataTransfersPending);
     4301                vdIoTaskFree(pDisk, pIoTask);
     4302                break;
     4303            }
     4304
     4305            uOffset += cbTaskRead;
     4306            cbRead  -= cbTaskRead;
     4307        }
    41954308    }
    41964309
     
    42104323                 pvUser, pIoStorage, uOffset, pIoCtx, cbWrite));
    42114324
    4212     VD_THREAD_IS_CRITSECT_OWNER(pDisk);
    4213 
    4214     /** @todo: Handle synchronous I/O contexts. */
     4325    /** @todo: Enable check for sync I/O later. */
     4326    if (!(pIoCtx->fFlags & VDIOCTX_FLAGS_SYNC))
     4327        VD_THREAD_IS_CRITSECT_OWNER(pDisk);
    42154328
    42164329    Assert(cbWrite > 0);
    42174330
    4218     /* Build the S/G array and spawn a new I/O task */
    4219     while (cbWrite)
    4220     {
    4221         RTSGSEG  aSeg[VD_IO_TASK_SEGMENTS_MAX];
    4222         unsigned cSegments   = VD_IO_TASK_SEGMENTS_MAX;
    4223         size_t   cbTaskWrite = 0;
    4224 
    4225         cbTaskWrite = RTSgBufSegArrayCreate(&pIoCtx->Req.Io.SgBuf, aSeg, &cSegments, cbWrite);
    4226 
    4227         Assert(cSegments > 0);
    4228         Assert(cbTaskWrite > 0);
    4229         AssertMsg(cbTaskWrite <= cbWrite, ("Invalid number of bytes to write\n"));
    4230 
    4231         LogFlow(("Writing %u bytes from %u segments\n", cbTaskWrite, cSegments));
     4331    if (pIoCtx->fFlags & VDIOCTX_FLAGS_SYNC)
     4332    {
     4333        RTSGSEG Seg;
     4334        unsigned cSegments = 1;
     4335        size_t cbTaskWrite = 0;
     4336
     4337        /* Synchronous I/O contexts only have one buffer segment. */
     4338        AssertMsgReturn(pIoCtx->Req.Io.SgBuf.cSegs == 1,
     4339                        ("Invalid number of buffer segments for synchronous I/O context"),
     4340                        VERR_INVALID_PARAMETER);
     4341
     4342        cbTaskWrite = RTSgBufSegArrayCreate(&pIoCtx->Req.Io.SgBuf, &Seg, &cSegments, cbWrite);
     4343        Assert(cbWrite == cbTaskWrite);
     4344        Assert(cSegments == 1);
     4345        rc = pVDIo->pInterfaceIo->pfnWriteSync(pVDIo->pInterfaceIo->Core.pvUser,
     4346                                              pIoStorage->pStorage, uOffset,
     4347                                              Seg.pvSeg, cbWrite, NULL);
     4348    }
     4349    else
     4350    {
     4351        /* Build the S/G array and spawn a new I/O task */
     4352        while (cbWrite)
     4353        {
     4354            RTSGSEG  aSeg[VD_IO_TASK_SEGMENTS_MAX];
     4355            unsigned cSegments   = VD_IO_TASK_SEGMENTS_MAX;
     4356            size_t   cbTaskWrite = 0;
     4357
     4358            cbTaskWrite = RTSgBufSegArrayCreate(&pIoCtx->Req.Io.SgBuf, aSeg, &cSegments, cbWrite);
     4359
     4360            Assert(cSegments > 0);
     4361            Assert(cbTaskWrite > 0);
     4362            AssertMsg(cbTaskWrite <= cbWrite, ("Invalid number of bytes to write\n"));
     4363
     4364            LogFlow(("Writing %u bytes from %u segments\n", cbTaskWrite, cSegments));
    42324365
    42334366#ifdef DEBUG
    4234         for (unsigned i = 0; i < cSegments; i++)
    4235                 AssertMsg(aSeg[i].pvSeg && !(aSeg[i].cbSeg % 512),
    4236                           ("Segment %u is invalid\n", i));
     4367            for (unsigned i = 0; i < cSegments; i++)
     4368                    AssertMsg(aSeg[i].pvSeg && !(aSeg[i].cbSeg % 512),
     4369                              ("Segment %u is invalid\n", i));
    42374370#endif
    42384371
    4239         PVDIOTASK pIoTask = vdIoTaskUserAlloc(pIoStorage, pfnComplete, pvCompleteUser, pIoCtx, cbTaskWrite);
    4240 
    4241         if (!pIoTask)
    4242             return VERR_NO_MEMORY;
    4243 
    4244         ASMAtomicIncU32(&pIoCtx->cDataTransfersPending);
    4245 
    4246         void *pvTask;
    4247         rc = pVDIo->pInterfaceIo->pfnWriteAsync(pVDIo->pInterfaceIo->Core.pvUser,
    4248                                                 pIoStorage->pStorage,
    4249                                                 uOffset, aSeg, cSegments,
    4250                                                 cbTaskWrite, pIoTask, &pvTask);
    4251         if (RT_SUCCESS(rc))
    4252         {
    4253             AssertMsg(cbTaskWrite <= pIoCtx->Req.Io.cbTransferLeft, ("Impossible!\n"));
    4254             ASMAtomicSubU32(&pIoCtx->Req.Io.cbTransferLeft, cbTaskWrite);
    4255             ASMAtomicDecU32(&pIoCtx->cDataTransfersPending);
    4256             vdIoTaskFree(pDisk, pIoTask);
    4257         }
    4258         else if (rc != VERR_VD_ASYNC_IO_IN_PROGRESS)
    4259         {
    4260             ASMAtomicDecU32(&pIoCtx->cDataTransfersPending);
    4261             vdIoTaskFree(pDisk, pIoTask);
    4262             break;
    4263         }
    4264 
    4265         uOffset += cbTaskWrite;
    4266         cbWrite -= cbTaskWrite;
    4267     }
    4268 
     4372            PVDIOTASK pIoTask = vdIoTaskUserAlloc(pIoStorage, pfnComplete, pvCompleteUser, pIoCtx, cbTaskWrite);
     4373
     4374            if (!pIoTask)
     4375                return VERR_NO_MEMORY;
     4376
     4377            ASMAtomicIncU32(&pIoCtx->cDataTransfersPending);
     4378
     4379            void *pvTask;
     4380            rc = pVDIo->pInterfaceIo->pfnWriteAsync(pVDIo->pInterfaceIo->Core.pvUser,
     4381                                                    pIoStorage->pStorage,
     4382                                                    uOffset, aSeg, cSegments,
     4383                                                    cbTaskWrite, pIoTask, &pvTask);
     4384            if (RT_SUCCESS(rc))
     4385            {
     4386                AssertMsg(cbTaskWrite <= pIoCtx->Req.Io.cbTransferLeft, ("Impossible!\n"));
     4387                ASMAtomicSubU32(&pIoCtx->Req.Io.cbTransferLeft, cbTaskWrite);
     4388                ASMAtomicDecU32(&pIoCtx->cDataTransfersPending);
     4389                vdIoTaskFree(pDisk, pIoTask);
     4390            }
     4391            else if (rc != VERR_VD_ASYNC_IO_IN_PROGRESS)
     4392            {
     4393                ASMAtomicDecU32(&pIoCtx->cDataTransfersPending);
     4394                vdIoTaskFree(pDisk, pIoTask);
     4395                break;
     4396            }
     4397
     4398            uOffset += cbTaskWrite;
     4399            cbWrite -= cbTaskWrite;
     4400        }
     4401    }
     4402
     4403    LogFlowFunc(("returns rc=%Rrc\n", rc));
    42694404    return rc;
    42704405}
     
    42914426                    VERR_INVALID_POINTER);
    42924427
    4293     if (!pIoCtx)
     4428    /** @todo: Enable check for sync I/O later. */
     4429    if (   pIoCtx
     4430        && !(pIoCtx->fFlags & VDIOCTX_FLAGS_SYNC))
     4431        VD_THREAD_IS_CRITSECT_OWNER(pDisk);
     4432
     4433    if (   !pIoCtx
     4434        || pIoCtx->fFlags & VDIOCTX_FLAGS_SYNC)
    42944435    {
    42954436        /* Handle synchronous metadata I/O. */
    42964437        /** @todo: Integrate with metadata transfers below. */
    4297         return pVDIo->pInterfaceIo->pfnReadSync(pVDIo->pInterfaceIo->Core.pvUser,
    4298                                                 pIoStorage->pStorage, uOffset,
    4299                                                 pvBuf, cbRead, NULL);
    4300     }
    4301 
    4302     VD_THREAD_IS_CRITSECT_OWNER(pDisk);
    4303 
    4304     pMetaXfer = (PVDMETAXFER)RTAvlrFileOffsetGet(pIoStorage->pTreeMetaXfers, uOffset);
    4305     if (!pMetaXfer)
    4306     {
     4438        rc = pVDIo->pInterfaceIo->pfnReadSync(pVDIo->pInterfaceIo->Core.pvUser,
     4439                                               pIoStorage->pStorage, uOffset,
     4440                                               pvBuf, cbRead, NULL);
     4441        if (ppMetaXfer)
     4442            *ppMetaXfer = NULL;
     4443    }
     4444    else
     4445    {
     4446        pMetaXfer = (PVDMETAXFER)RTAvlrFileOffsetGet(pIoStorage->pTreeMetaXfers, uOffset);
     4447        if (!pMetaXfer)
     4448        {
    43074449#ifdef RT_STRICT
    4308         pMetaXfer = (PVDMETAXFER)RTAvlrFileOffsetGetBestFit(pIoStorage->pTreeMetaXfers, uOffset, false /* fAbove */);
    4309         AssertMsg(!pMetaXfer || (pMetaXfer->Core.Key + (RTFOFF)pMetaXfer->cbMeta <= (RTFOFF)uOffset),
    4310                   ("Overlapping meta transfers!\n"));
     4450            pMetaXfer = (PVDMETAXFER)RTAvlrFileOffsetGetBestFit(pIoStorage->pTreeMetaXfers, uOffset, false /* fAbove */);
     4451            AssertMsg(!pMetaXfer || (pMetaXfer->Core.Key + (RTFOFF)pMetaXfer->cbMeta <= (RTFOFF)uOffset),
     4452                      ("Overlapping meta transfers!\n"));
    43114453#endif
    43124454
    4313         /* Allocate a new meta transfer. */
    4314         pMetaXfer = vdMetaXferAlloc(pIoStorage, uOffset, cbRead);
    4315         if (!pMetaXfer)
    4316             return VERR_NO_MEMORY;
    4317 
    4318         pIoTask = vdIoTaskMetaAlloc(pIoStorage, pfnComplete, pvCompleteUser, pMetaXfer);
    4319         if (!pIoTask)
    4320         {
    4321             RTMemFree(pMetaXfer);
    4322             return VERR_NO_MEMORY;
    4323         }
    4324 
    4325         Seg.cbSeg = cbRead;
    4326         Seg.pvSeg = pMetaXfer->abData;
    4327 
    4328         VDMETAXFER_TXDIR_SET(pMetaXfer->fFlags, VDMETAXFER_TXDIR_READ);
    4329         rc = pVDIo->pInterfaceIo->pfnReadAsync(pVDIo->pInterfaceIo->Core.pvUser,
    4330                                                pIoStorage->pStorage,
    4331                                                uOffset, &Seg, 1,
    4332                                                cbRead, pIoTask, &pvTask);
    4333 
    4334         if (RT_SUCCESS(rc) || rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
    4335         {
    4336             bool fInserted = RTAvlrFileOffsetInsert(pIoStorage->pTreeMetaXfers, &pMetaXfer->Core);
    4337             Assert(fInserted);
    4338         }
    4339         else
    4340             RTMemFree(pMetaXfer);
    4341 
    4342         if (RT_SUCCESS(rc))
    4343         {
    4344             VDMETAXFER_TXDIR_SET(pMetaXfer->fFlags, VDMETAXFER_TXDIR_NONE);
    4345             vdIoTaskFree(pDisk, pIoTask);
    4346         }
    4347         else if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS && !pfnComplete)
    4348             rc = VERR_VD_NOT_ENOUGH_METADATA;
    4349     }
    4350 
    4351     Assert(VALID_PTR(pMetaXfer) || RT_FAILURE(rc));
    4352 
    4353     if (RT_SUCCESS(rc) || rc == VERR_VD_NOT_ENOUGH_METADATA || rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
    4354     {
    4355         /* If it is pending add the request to the list. */
    4356         if (VDMETAXFER_TXDIR_GET(pMetaXfer->fFlags) == VDMETAXFER_TXDIR_READ)
    4357         {
    4358             PVDIOCTXDEFERRED pDeferred = (PVDIOCTXDEFERRED)RTMemAllocZ(sizeof(VDIOCTXDEFERRED));
    4359             AssertPtr(pDeferred);
    4360 
    4361             RTListInit(&pDeferred->NodeDeferred);
    4362             pDeferred->pIoCtx = pIoCtx;
    4363 
    4364             ASMAtomicIncU32(&pIoCtx->cMetaTransfersPending);
    4365             RTListAppend(&pMetaXfer->ListIoCtxWaiting, &pDeferred->NodeDeferred);
    4366             rc = VERR_VD_NOT_ENOUGH_METADATA;
    4367         }
    4368         else
    4369         {
    4370             /* Transfer the data. */
    4371             pMetaXfer->cRefs++;
    4372             Assert(pMetaXfer->cbMeta >= cbRead);
    4373             Assert(pMetaXfer->Core.Key == (RTFOFF)uOffset);
    4374             memcpy(pvBuf, pMetaXfer->abData, cbRead);
    4375             *ppMetaXfer = pMetaXfer;
    4376         }
    4377     }
    4378 
     4455            /* Allocate a new meta transfer. */
     4456            pMetaXfer = vdMetaXferAlloc(pIoStorage, uOffset, cbRead);
     4457            if (!pMetaXfer)
     4458                return VERR_NO_MEMORY;
     4459
     4460            pIoTask = vdIoTaskMetaAlloc(pIoStorage, pfnComplete, pvCompleteUser, pMetaXfer);
     4461            if (!pIoTask)
     4462            {
     4463                RTMemFree(pMetaXfer);
     4464                return VERR_NO_MEMORY;
     4465            }
     4466
     4467            Seg.cbSeg = cbRead;
     4468            Seg.pvSeg = pMetaXfer->abData;
     4469
     4470            VDMETAXFER_TXDIR_SET(pMetaXfer->fFlags, VDMETAXFER_TXDIR_READ);
     4471            rc = pVDIo->pInterfaceIo->pfnReadAsync(pVDIo->pInterfaceIo->Core.pvUser,
     4472                                                   pIoStorage->pStorage,
     4473                                                   uOffset, &Seg, 1,
     4474                                                   cbRead, pIoTask, &pvTask);
     4475
     4476            if (RT_SUCCESS(rc) || rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
     4477            {
     4478                bool fInserted = RTAvlrFileOffsetInsert(pIoStorage->pTreeMetaXfers, &pMetaXfer->Core);
     4479                Assert(fInserted);
     4480            }
     4481            else
     4482                RTMemFree(pMetaXfer);
     4483
     4484            if (RT_SUCCESS(rc))
     4485            {
     4486                VDMETAXFER_TXDIR_SET(pMetaXfer->fFlags, VDMETAXFER_TXDIR_NONE);
     4487                vdIoTaskFree(pDisk, pIoTask);
     4488            }
     4489            else if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS && !pfnComplete)
     4490                rc = VERR_VD_NOT_ENOUGH_METADATA;
     4491        }
     4492
     4493        Assert(VALID_PTR(pMetaXfer) || RT_FAILURE(rc));
     4494
     4495        if (RT_SUCCESS(rc) || rc == VERR_VD_NOT_ENOUGH_METADATA || rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
     4496        {
     4497            /* If it is pending add the request to the list. */
     4498            if (VDMETAXFER_TXDIR_GET(pMetaXfer->fFlags) == VDMETAXFER_TXDIR_READ)
     4499            {
     4500                PVDIOCTXDEFERRED pDeferred = (PVDIOCTXDEFERRED)RTMemAllocZ(sizeof(VDIOCTXDEFERRED));
     4501                AssertPtr(pDeferred);
     4502
     4503                RTListInit(&pDeferred->NodeDeferred);
     4504                pDeferred->pIoCtx = pIoCtx;
     4505
     4506                ASMAtomicIncU32(&pIoCtx->cMetaTransfersPending);
     4507                RTListAppend(&pMetaXfer->ListIoCtxWaiting, &pDeferred->NodeDeferred);
     4508                rc = VERR_VD_NOT_ENOUGH_METADATA;
     4509            }
     4510            else
     4511            {
     4512                /* Transfer the data. */
     4513                pMetaXfer->cRefs++;
     4514                Assert(pMetaXfer->cbMeta >= cbRead);
     4515                Assert(pMetaXfer->Core.Key == (RTFOFF)uOffset);
     4516                memcpy(pvBuf, pMetaXfer->abData, cbRead);
     4517                *ppMetaXfer = pMetaXfer;
     4518            }
     4519        }
     4520    }
     4521
     4522    LogFlowFunc(("returns rc=%Rrc\n", rc));
    43794523    return rc;
    43804524}
     
    44014545                    VERR_INVALID_POINTER);
    44024546
    4403     if (!pIoCtx)
     4547    /** @todo: Enable check for sync I/O later. */
     4548    if (   pIoCtx
     4549        && !(pIoCtx->fFlags & VDIOCTX_FLAGS_SYNC))
     4550        VD_THREAD_IS_CRITSECT_OWNER(pDisk);
     4551
     4552    if (   !pIoCtx
     4553        || pIoCtx->fFlags & VDIOCTX_FLAGS_SYNC)
    44044554    {
    44054555        /* Handle synchronous metadata I/O. */
    44064556        /** @todo: Integrate with metadata transfers below. */
    4407         return pVDIo->pInterfaceIo->pfnWriteSync(pVDIo->pInterfaceIo->Core.pvUser,
    4408                                                  pIoStorage->pStorage, uOffset,
    4409                                                  pvBuf, cbWrite, NULL);
    4410     }
    4411 
    4412     VD_THREAD_IS_CRITSECT_OWNER(pDisk);
    4413 
    4414     pMetaXfer = (PVDMETAXFER)RTAvlrFileOffsetGet(pIoStorage->pTreeMetaXfers, uOffset);
    4415     if (!pMetaXfer)
    4416     {
    4417         /* Allocate a new meta transfer. */
    4418         pMetaXfer = vdMetaXferAlloc(pIoStorage, uOffset, cbWrite);
     4557        rc = pVDIo->pInterfaceIo->pfnWriteSync(pVDIo->pInterfaceIo->Core.pvUser,
     4558                                               pIoStorage->pStorage, uOffset,
     4559                                               pvBuf, cbWrite, NULL);
     4560    }
     4561    else
     4562    {
     4563        pMetaXfer = (PVDMETAXFER)RTAvlrFileOffsetGet(pIoStorage->pTreeMetaXfers, uOffset);
    44194564        if (!pMetaXfer)
     4565        {
     4566            /* Allocate a new meta transfer. */
     4567            pMetaXfer = vdMetaXferAlloc(pIoStorage, uOffset, cbWrite);
     4568            if (!pMetaXfer)
     4569                return VERR_NO_MEMORY;
     4570        }
     4571        else
     4572        {
     4573            Assert(pMetaXfer->cbMeta >= cbWrite);
     4574            Assert(pMetaXfer->Core.Key == (RTFOFF)uOffset);
     4575            fInTree = true;
     4576        }
     4577
     4578        Assert(VDMETAXFER_TXDIR_GET(pMetaXfer->fFlags) == VDMETAXFER_TXDIR_NONE);
     4579
     4580        pIoTask = vdIoTaskMetaAlloc(pIoStorage, pfnComplete, pvCompleteUser, pMetaXfer);
     4581        if (!pIoTask)
     4582        {
     4583            RTMemFree(pMetaXfer);
    44204584            return VERR_NO_MEMORY;
    4421     }
    4422     else
    4423     {
    4424         Assert(pMetaXfer->cbMeta >= cbWrite);
    4425         Assert(pMetaXfer->Core.Key == (RTFOFF)uOffset);
    4426         fInTree = true;
    4427     }
    4428 
    4429     Assert(VDMETAXFER_TXDIR_GET(pMetaXfer->fFlags) == VDMETAXFER_TXDIR_NONE);
    4430 
    4431     pIoTask = vdIoTaskMetaAlloc(pIoStorage, pfnComplete, pvCompleteUser, pMetaXfer);
    4432     if (!pIoTask)
    4433     {
    4434         RTMemFree(pMetaXfer);
    4435         return VERR_NO_MEMORY;
    4436     }
    4437 
    4438     memcpy(pMetaXfer->abData, pvBuf, cbWrite);
    4439     Seg.cbSeg = cbWrite;
    4440     Seg.pvSeg = pMetaXfer->abData;
    4441 
    4442     ASMAtomicIncU32(&pIoCtx->cMetaTransfersPending);
    4443 
    4444     VDMETAXFER_TXDIR_SET(pMetaXfer->fFlags, VDMETAXFER_TXDIR_WRITE);
    4445     rc = pVDIo->pInterfaceIo->pfnWriteAsync(pVDIo->pInterfaceIo->Core.pvUser,
    4446                                             pIoStorage->pStorage,
    4447                                             uOffset, &Seg, 1, cbWrite, pIoTask,
    4448                                             &pvTask);
    4449     if (RT_SUCCESS(rc))
    4450     {
    4451         VDMETAXFER_TXDIR_SET(pMetaXfer->fFlags, VDMETAXFER_TXDIR_NONE);
    4452         ASMAtomicDecU32(&pIoCtx->cMetaTransfersPending);
    4453         vdIoTaskFree(pDisk, pIoTask);
    4454         if (fInTree && !pMetaXfer->cRefs)
    4455         {
    4456             LogFlow(("Removing meta xfer=%#p\n", pMetaXfer));
    4457             bool fRemoved = RTAvlrFileOffsetRemove(pIoStorage->pTreeMetaXfers, pMetaXfer->Core.Key) != NULL;
    4458             AssertMsg(fRemoved, ("Metadata transfer wasn't removed\n"));
     4585        }
     4586
     4587        memcpy(pMetaXfer->abData, pvBuf, cbWrite);
     4588        Seg.cbSeg = cbWrite;
     4589        Seg.pvSeg = pMetaXfer->abData;
     4590
     4591        ASMAtomicIncU32(&pIoCtx->cMetaTransfersPending);
     4592
     4593        VDMETAXFER_TXDIR_SET(pMetaXfer->fFlags, VDMETAXFER_TXDIR_WRITE);
     4594        rc = pVDIo->pInterfaceIo->pfnWriteAsync(pVDIo->pInterfaceIo->Core.pvUser,
     4595                                                pIoStorage->pStorage,
     4596                                                uOffset, &Seg, 1, cbWrite, pIoTask,
     4597                                                &pvTask);
     4598        if (RT_SUCCESS(rc))
     4599        {
     4600            VDMETAXFER_TXDIR_SET(pMetaXfer->fFlags, VDMETAXFER_TXDIR_NONE);
     4601            ASMAtomicDecU32(&pIoCtx->cMetaTransfersPending);
     4602            vdIoTaskFree(pDisk, pIoTask);
     4603            if (fInTree && !pMetaXfer->cRefs)
     4604            {
     4605                LogFlow(("Removing meta xfer=%#p\n", pMetaXfer));
     4606                bool fRemoved = RTAvlrFileOffsetRemove(pIoStorage->pTreeMetaXfers, pMetaXfer->Core.Key) != NULL;
     4607                AssertMsg(fRemoved, ("Metadata transfer wasn't removed\n"));
     4608                RTMemFree(pMetaXfer);
     4609                pMetaXfer = NULL;
     4610            }
     4611        }
     4612        else if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
     4613        {
     4614            PVDIOCTXDEFERRED pDeferred = (PVDIOCTXDEFERRED)RTMemAllocZ(sizeof(VDIOCTXDEFERRED));
     4615            AssertPtr(pDeferred);
     4616
     4617            RTListInit(&pDeferred->NodeDeferred);
     4618            pDeferred->pIoCtx = pIoCtx;
     4619
     4620            if (!fInTree)
     4621            {
     4622                bool fInserted = RTAvlrFileOffsetInsert(pIoStorage->pTreeMetaXfers, &pMetaXfer->Core);
     4623                Assert(fInserted);
     4624            }
     4625
     4626            RTListAppend(&pMetaXfer->ListIoCtxWaiting, &pDeferred->NodeDeferred);
     4627        }
     4628        else
     4629        {
    44594630            RTMemFree(pMetaXfer);
    44604631            pMetaXfer = NULL;
    44614632        }
    44624633    }
    4463     else if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
    4464     {
    4465         PVDIOCTXDEFERRED pDeferred = (PVDIOCTXDEFERRED)RTMemAllocZ(sizeof(VDIOCTXDEFERRED));
    4466         AssertPtr(pDeferred);
    4467 
    4468         RTListInit(&pDeferred->NodeDeferred);
    4469         pDeferred->pIoCtx = pIoCtx;
    4470 
    4471         if (!fInTree)
    4472         {
    4473             bool fInserted = RTAvlrFileOffsetInsert(pIoStorage->pTreeMetaXfers, &pMetaXfer->Core);
    4474             Assert(fInserted);
    4475         }
    4476 
    4477         RTListAppend(&pMetaXfer->ListIoCtxWaiting, &pDeferred->NodeDeferred);
    4478     }
    4479     else
    4480     {
    4481         RTMemFree(pMetaXfer);
    4482         pMetaXfer = NULL;
    4483     }
    4484 
     4634
     4635    LogFlowFunc(("returns rc=%Rrc\n", rc));
    44854636    return rc;
    44864637}
     
    44904641    PVDIO    pVDIo = (PVDIO)pvUser;
    44914642    PVBOXHDD pDisk = pVDIo->pDisk;
    4492     PVDIOSTORAGE pIoStorage = pMetaXfer->pIoStorage;
     4643    PVDIOSTORAGE pIoStorage;
     4644
     4645    /*
     4646     * It is possible that we get called with a NULL metadata xfer handle
     4647     * for synchronous I/O. Just exit.
     4648     */
     4649    if (!pMetaXfer)
     4650        return;
     4651
     4652    pIoStorage = pMetaXfer->pIoStorage;
    44934653
    44944654    VD_THREAD_IS_CRITSECT_OWNER(pDisk);
     
    45304690                    VERR_INVALID_POINTER);
    45314691
    4532     if (!pIoCtx)
     4692    /** @todo: Enable check for sync I/O later. */
     4693    if (   pIoCtx
     4694        && !(pIoCtx->fFlags & VDIOCTX_FLAGS_SYNC))
     4695        VD_THREAD_IS_CRITSECT_OWNER(pDisk);
     4696
     4697    if (pVDIo->fIgnoreFlush)
     4698        return VINF_SUCCESS;
     4699
     4700    if (   !pIoCtx
     4701        || pIoCtx->fFlags & VDIOCTX_FLAGS_SYNC)
    45334702    {
    45344703        /* Handle synchronous flushes. */
    45354704        /** @todo: Integrate with metadata transfers below. */
    4536         return pVDIo->pInterfaceIo->pfnFlushSync(pVDIo->pInterfaceIo->Core.pvUser,
    4537                                                  pIoStorage->pStorage);
    4538     }
    4539 
    4540     VD_THREAD_IS_CRITSECT_OWNER(pDisk);
    4541 
    4542     if (pVDIo->fIgnoreFlush)
    4543         return VINF_SUCCESS;
    4544 
    4545     /* Allocate a new meta transfer. */
    4546     pMetaXfer = vdMetaXferAlloc(pIoStorage, 0, 0);
    4547     if (!pMetaXfer)
    4548         return VERR_NO_MEMORY;
    4549 
    4550     pIoTask = vdIoTaskMetaAlloc(pIoStorage, pfnComplete, pvUser, pMetaXfer);
    4551     if (!pIoTask)
    4552     {
    4553         RTMemFree(pMetaXfer);
    4554         return VERR_NO_MEMORY;
    4555     }
    4556 
    4557     ASMAtomicIncU32(&pIoCtx->cMetaTransfersPending);
    4558 
    4559     PVDIOCTXDEFERRED pDeferred = (PVDIOCTXDEFERRED)RTMemAllocZ(sizeof(VDIOCTXDEFERRED));
    4560     AssertPtr(pDeferred);
    4561 
    4562     RTListInit(&pDeferred->NodeDeferred);
    4563     pDeferred->pIoCtx = pIoCtx;
    4564 
    4565     RTListAppend(&pMetaXfer->ListIoCtxWaiting, &pDeferred->NodeDeferred);
    4566     VDMETAXFER_TXDIR_SET(pMetaXfer->fFlags, VDMETAXFER_TXDIR_FLUSH);
    4567     rc = pVDIo->pInterfaceIo->pfnFlushAsync(pVDIo->pInterfaceIo->Core.pvUser,
    4568                                             pIoStorage->pStorage,
    4569                                             pIoTask, &pvTask);
    4570     if (RT_SUCCESS(rc))
    4571     {
    4572         VDMETAXFER_TXDIR_SET(pMetaXfer->fFlags, VDMETAXFER_TXDIR_NONE);
    4573         ASMAtomicDecU32(&pIoCtx->cMetaTransfersPending);
    4574         vdIoTaskFree(pDisk, pIoTask);
    4575         RTMemFree(pDeferred);
    4576         RTMemFree(pMetaXfer);
    4577     }
    4578     else if (rc != VERR_VD_ASYNC_IO_IN_PROGRESS)
    4579         RTMemFree(pMetaXfer);
    4580 
     4705        rc = pVDIo->pInterfaceIo->pfnFlushSync(pVDIo->pInterfaceIo->Core.pvUser,
     4706                                               pIoStorage->pStorage);
     4707    }
     4708    else
     4709    {
     4710        /* Allocate a new meta transfer. */
     4711        pMetaXfer = vdMetaXferAlloc(pIoStorage, 0, 0);
     4712        if (!pMetaXfer)
     4713            return VERR_NO_MEMORY;
     4714
     4715        pIoTask = vdIoTaskMetaAlloc(pIoStorage, pfnComplete, pvUser, pMetaXfer);
     4716        if (!pIoTask)
     4717        {
     4718            RTMemFree(pMetaXfer);
     4719            return VERR_NO_MEMORY;
     4720        }
     4721
     4722        ASMAtomicIncU32(&pIoCtx->cMetaTransfersPending);
     4723
     4724        PVDIOCTXDEFERRED pDeferred = (PVDIOCTXDEFERRED)RTMemAllocZ(sizeof(VDIOCTXDEFERRED));
     4725        AssertPtr(pDeferred);
     4726
     4727        RTListInit(&pDeferred->NodeDeferred);
     4728        pDeferred->pIoCtx = pIoCtx;
     4729
     4730        RTListAppend(&pMetaXfer->ListIoCtxWaiting, &pDeferred->NodeDeferred);
     4731        VDMETAXFER_TXDIR_SET(pMetaXfer->fFlags, VDMETAXFER_TXDIR_FLUSH);
     4732        rc = pVDIo->pInterfaceIo->pfnFlushAsync(pVDIo->pInterfaceIo->Core.pvUser,
     4733                                                pIoStorage->pStorage,
     4734                                                pIoTask, &pvTask);
     4735        if (RT_SUCCESS(rc))
     4736        {
     4737            VDMETAXFER_TXDIR_SET(pMetaXfer->fFlags, VDMETAXFER_TXDIR_NONE);
     4738            ASMAtomicDecU32(&pIoCtx->cMetaTransfersPending);
     4739            vdIoTaskFree(pDisk, pIoTask);
     4740            RTMemFree(pDeferred);
     4741            RTMemFree(pMetaXfer);
     4742        }
     4743        else if (rc != VERR_VD_ASYNC_IO_IN_PROGRESS)
     4744            RTMemFree(pMetaXfer);
     4745    }
     4746
     4747    LogFlowFunc(("returns rc=%Rrc\n", rc));
    45814748    return rc;
    45824749}
     
    45894756    size_t cbCopied = 0;
    45904757
    4591     VD_THREAD_IS_CRITSECT_OWNER(pDisk);
     4758    /** @todo: Enable check for sync I/O later. */
     4759    if (!(pIoCtx->fFlags & VDIOCTX_FLAGS_SYNC))
     4760        VD_THREAD_IS_CRITSECT_OWNER(pDisk);
    45924761
    45934762    cbCopied = vdIoCtxCopyTo(pIoCtx, (uint8_t *)pvBuf, cbBuf);
     
    46064775    size_t cbCopied = 0;
    46074776
    4608     VD_THREAD_IS_CRITSECT_OWNER(pDisk);
     4777    /** @todo: Enable check for sync I/O later. */
     4778    if (!(pIoCtx->fFlags & VDIOCTX_FLAGS_SYNC))
     4779        VD_THREAD_IS_CRITSECT_OWNER(pDisk);
    46094780
    46104781    cbCopied = vdIoCtxCopyFrom(pIoCtx, (uint8_t *)pvBuf, cbBuf);
     
    46224793    size_t cbSet = 0;
    46234794
    4624     VD_THREAD_IS_CRITSECT_OWNER(pDisk);
     4795    /** @todo: Enable check for sync I/O later. */
     4796    if (!(pIoCtx->fFlags & VDIOCTX_FLAGS_SYNC))
     4797        VD_THREAD_IS_CRITSECT_OWNER(pDisk);
    46254798
    46264799    cbSet = vdIoCtxSet(pIoCtx, ch, cb);
     
    46404813    size_t cbCreated = 0;
    46414814
    4642     VD_THREAD_IS_CRITSECT_OWNER(pDisk);
     4815    /** @todo: Enable check for sync I/O later. */
     4816    if (!(pIoCtx->fFlags & VDIOCTX_FLAGS_SYNC))
     4817        VD_THREAD_IS_CRITSECT_OWNER(pDisk);
    46434818
    46444819    cbCreated = RTSgBufSegArrayCreate(&pIoCtx->Req.Io.SgBuf, paSeg, pcSeg, cbData);
     
    46594834     * Example is that iSCSI is doing an asynchronous write but calls us already
    46604835     * while the other thread is still hanging in vdWriteHelperAsync and couldn't update
    4661      * the fBlocked state yet.
     4836     * the blocked state yet.
    46624837     * It can overwrite the state to true before we call vdIoCtxContinue and the
    46634838     * the request would hang indefinite.
     
    46674842
    46684843    /* Continue */
    4669     pIoCtx->fBlocked = false;
     4844    pIoCtx->fFlags &= ~VDIOCTX_FLAGS_BLOCKED;
    46704845    ASMAtomicSubU32(&pIoCtx->Req.Io.cbTransferLeft, cbCompleted);
    46714846
     
    46784853
    46794854    vdDiskCritSectLeave(pDisk, NULL);
     4855}
     4856
     4857static DECLCALLBACK(bool) vdIOIntIoCtxIsSynchronous(void *pvUser, PVDIOCTX pIoCtx)
     4858{
     4859    NOREF(pvUser);
     4860    return !!(pIoCtx->fFlags & VDIOCTX_FLAGS_SYNC);
     4861}
     4862
     4863static DECLCALLBACK(bool) vdIOIntIoCtxIsZero(void *pvUser, PVDIOCTX pIoCtx, size_t cbCheck,
     4864                                             bool fAdvance)
     4865{
     4866    NOREF(pvUser);
     4867
     4868    bool fIsZero = RTSgBufIsZero(&pIoCtx->Req.Io.SgBuf, cbCheck);
     4869    if (fIsZero && fAdvance)
     4870        RTSgBufAdvance(&pIoCtx->Req.Io.SgBuf, cbCheck);
     4871
     4872    return fIsZero;
    46804873}
    46814874
     
    49625155    pIfIoInt->pfnIoCtxSegArrayCreate = vdIOIntIoCtxSegArrayCreate;
    49635156    pIfIoInt->pfnIoCtxCompleted      = vdIOIntIoCtxCompleted;
     5157    pIfIoInt->pfnIoCtxIsSynchronous  = vdIOIntIoCtxIsSynchronous;
     5158    pIfIoInt->pfnIoCtxIsZero         = vdIOIntIoCtxIsZero;
    49645159}
    49655160
     
    67486943            {
    67496944                size_t cbThisRead = RT_MIN(VD_MERGE_BUFFER_SIZE, cbRemaining);
     6945                RTSGSEG SegmentBuf;
     6946                RTSGBUF SgBuf;
     6947                VDIOCTX IoCtx;
     6948
     6949                SegmentBuf.pvSeg = pvBuf;
     6950                SegmentBuf.cbSeg = VD_MERGE_BUFFER_SIZE;
     6951                RTSgBufInit(&SgBuf, &SegmentBuf, 1);
     6952                vdIoCtxInit(&IoCtx, pDisk, VDIOCTXTXDIR_READ, 0, 0, NULL,
     6953                            &SgBuf, NULL, NULL, VDIOCTX_FLAGS_SYNC);
    67506954
    67516955                /* Need to hold the write lock during a read-write operation. */
     
    67546958                fLockWrite = true;
    67556959
    6756                 rc = pImageTo->Backend->pfnRead(pImageTo->pBackendData,
    6757                                                 uOffset, pvBuf, cbThisRead,
    6758                                                 &cbThisRead);
     6960                rc = pImageTo->Backend->pfnAsyncRead(pImageTo->pBackendData,
     6961                                                     uOffset, cbThisRead,
     6962                                                     &IoCtx, &cbThisRead);
    67596963                if (rc == VERR_VD_BLOCK_FREE)
    67606964                {
     
    67676971                         pCurrImage = pCurrImage->pPrev)
    67686972                    {
    6769                         rc = pCurrImage->Backend->pfnRead(pCurrImage->pBackendData,
    6770                                                           uOffset, pvBuf,
    6771                                                           cbThisRead,
    6772                                                           &cbThisRead);
     6973                        rc = pCurrImage->Backend->pfnAsyncRead(pCurrImage->pBackendData,
     6974                                                               uOffset, cbThisRead,
     6975                                                               &IoCtx, &cbThisRead);
    67736976                    }
    67746977
     
    68697072            {
    68707073                size_t cbThisRead = RT_MIN(VD_MERGE_BUFFER_SIZE, cbRemaining);
     7074                RTSGSEG SegmentBuf;
     7075                RTSGBUF SgBuf;
     7076                VDIOCTX IoCtx;
     7077
    68717078                rc = VERR_VD_BLOCK_FREE;
     7079
     7080                SegmentBuf.pvSeg = pvBuf;
     7081                SegmentBuf.cbSeg = VD_MERGE_BUFFER_SIZE;
     7082                RTSgBufInit(&SgBuf, &SegmentBuf, 1);
     7083                vdIoCtxInit(&IoCtx, pDisk, VDIOCTXTXDIR_READ, 0, 0, NULL,
     7084                            &SgBuf, NULL, NULL, VDIOCTX_FLAGS_SYNC);
    68727085
    68737086                /* Need to hold the write lock during a read-write operation. */
     
    68847097                     pCurrImage = pCurrImage->pPrev)
    68857098                {
    6886                     rc = pCurrImage->Backend->pfnRead(pCurrImage->pBackendData,
    6887                                                       uOffset, pvBuf,
    6888                                                       cbThisRead, &cbThisRead);
     7099                    rc = pCurrImage->Backend->pfnAsyncRead(pCurrImage->pBackendData,
     7100                                                           uOffset, cbThisRead,
     7101                                                           &IoCtx, &cbThisRead);
    68897102                }
    68907103
     
    80818294
    80828295        vdResetModifiedFlag(pDisk);
    8083         rc = pImage->Backend->pfnFlush(pImage->pBackendData);
    8084 
     8296
     8297        VDIOCTX IoCtx;
     8298        vdIoCtxInit(&IoCtx, pDisk, VDIOCTXTXDIR_FLUSH, 0, 0, NULL,
     8299                    NULL, NULL, NULL, VDIOCTX_FLAGS_SYNC);
     8300        rc = pImage->Backend->pfnAsyncFlush(pImage->pBackendData, &IoCtx);
     8301
     8302#if 0 /** @todo: Change cache implementation. */
    80858303        if (   RT_SUCCESS(rc)
    80868304            && pDisk->pCache)
    80878305            rc = pDisk->pCache->Backend->pfnFlush(pDisk->pCache->pBackendData);
     8306#endif
    80888307    } while (0);
    80898308
  • trunk/src/VBox/Storage/VDI.cpp

    r44233 r44242  
    25482548                    || cbToWrite == getImageBlockSize(&pImage->Header)))
    25492549            {
    2550 #if 0 /** @todo Provide interface to check an I/O context for a specific value */
    25512550                /* If the destination block is unallocated at this point, it's
    25522551                 * either a zero block or a block which hasn't been used so far
    25532552                 * (which also means that it's a zero block. Don't need to write
    25542553                 * anything to this block  if the data consists of just zeroes. */
    2555                 Assert(!(cbToWrite % 4));
    2556                 Assert(cbToWrite * 8 <= UINT32_MAX);
    2557                 if (ASMBitFirstSet((volatile void *)pvBuf, (uint32_t)cbToWrite * 8) == -1)
     2554                if (vdIfIoIntIoCtxIsZero(pImage->pIfIo, pIoCtx, cbToWrite, true))
    25582555                {
    25592556                    pImage->paBlocks[uBlock] = VDI_IMAGE_BLOCK_ZERO;
     2557                    *pcbPreRead = 0;
     2558                    *pcbPostRead = 0;
    25602559                    break;
    25612560                }
    2562 #endif
    25632561            }
    25642562
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette