VirtualBox

Changeset 27808 in vbox


Ignore:
Timestamp:
Mar 29, 2010 8:52:56 PM (15 years ago)
Author:
vboxsync
Message:

VBoxHDD: First part of the async I/O support

  • The async I/O interface is not presented to the backend directly anymore but goes through a new interface in VBoxHDD doing the request management
  • Implemented everything to make the old coe work again
  • Async I/O completely disabled for now because it is not working atm (the old code for VMDK was removed)
Location:
trunk
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/VBoxHDD-Plugin.h

    r27232 r27808  
    471471     * @param   uOffset         The offset of the virtual disk to read from.
    472472     * @param   cbRead          How many bytes to read.
    473      * @param   paSeg           Pointer to the segment array.
    474      * @param   cSeg            Number of segments.
    475      * @param   pvUser          Opaque user data.
     473     * @param   pIoCtx          I/O context associated with this request.
     474     * @param   pcbActuallyRead Pointer to returned number of bytes read.
    476475     */
    477476    DECLR3CALLBACKMEMBER(int, pfnAsyncRead, (void *pvBackendData, uint64_t uOffset, size_t cbRead,
    478                                              PPDMDATASEG paSeg, unsigned cSeg, void *pvUser));
     477                                             PVDIOCTX pIoCtx, size_t *pcbActuallyRead));
    479478
    480479    /**
     
    485484     * @param   uOffset         The offset of the virtual disk to write to.
    486485     * @param   cbWrite         How many bytes to write.
    487      * @param   paSeg           Pointer to the segment array.
    488      * @param   cSeg            Number of segments.
    489      * @param   pvUser          Oaque user data-
     486     * @param   pIoCtx          I/O context associated with this request.
     487     * @param   pcbWriteProcess Pointer to returned number of bytes that could
     488     *                          be processed. In case the function returned
     489     *                          VERR_VD_BLOCK_FREE this is the number of bytes
     490     *                          that could be written in a full block write,
     491     *                          when prefixed/postfixed by the appropriate
     492     *                          amount of (previously read) padding data.
     493     * @param   pcbPreRead      Pointer to the returned amount of data that must
     494     *                          be prefixed to perform a full block write.
     495     * @param   pcbPostRead     Pointer to the returned amount of data that must
     496     *                          be postfixed to perform a full block write.
     497     * @param   fWrite          Flags which affect write behavior. Combination
     498     *                          of the VD_WRITE_* flags.
    490499     */
    491500    DECLR3CALLBACKMEMBER(int, pfnAsyncWrite, (void *pvBackendData, uint64_t uOffset, size_t cbWrite,
    492                                               PPDMDATASEG paSeg, unsigned cSeg, void *pvUser));
     501                                              PVDIOCTX pIoCtx,
     502                                              size_t *pcbWriteProcess, size_t *pcbPreRead,
     503                                              size_t *pcbPostRead, unsigned fWrite));
     504
     505    /**
     506     * Flush data to disk.
     507     *
     508     * @returns VBox status code.
     509     * @param   pvBackendData   Opaque state data for this image.
     510     * @param   pIoCtx          I/O context associated with this request.
     511     */
     512    DECLR3CALLBACKMEMBER(int, pfnAsyncFlush, (void *pvBackendData, PVDIOCTX pIoCtx));
    493513
    494514    /** Returns a human readable hard disk location string given a
  • trunk/include/VBox/VBoxHDD.h

    r27232 r27808  
    226226    /** Interface for synchronizing accesses from several threads. Per-disk. */
    227227    VDINTERFACETYPE_THREADSYNC,
     228    /** Interface for I/O between the generic VBoxHDD code and the backend. Per-image. */
     229    VDINTERFACETYPE_IO,
    228230    /** invalid interface. */
    229231    VDINTERFACETYPE_INVALID
     
    334336
    335337    return VINF_SUCCESS;
     338}
     339
     340/**
     341 * Removes an interface from a list of interfaces.
     342 *
     343 * @return VBox status code
     344 * @param  pInterface   Pointer to an initialized common interface structure to remove.
     345 * @param  ppVDIfs      Pointer to the VD interface list to remove from.
     346 */
     347DECLINLINE(int) VDInterfaceRemove(PVDINTERFACE pInterface, PVDINTERFACE *ppVDIfs)
     348{
     349    int rc = VERR_NOT_FOUND;
     350
     351    /** Argument checks. */
     352    AssertMsgReturn(VALID_PTR(pInterface),
     353                    ("pInterface=%#p", pInterface),
     354                    VERR_INVALID_PARAMETER);
     355
     356    AssertMsgReturn(VALID_PTR(ppVDIfs),
     357                    ("pInterfaceList=%#p", ppVDIfs),
     358                    VERR_INVALID_PARAMETER);
     359
     360    if (*ppVDIfs)
     361    {
     362        PVDINTERFACE pPrev = NULL;
     363        PVDINTERFACE pCurr = *ppVDIfs;
     364
     365        while (   pCurr
     366               && (pCurr != pInterface))
     367        {
     368            pPrev = pCurr;
     369            pCurr = pCurr->pNext;
     370        }
     371
     372        /* First interface */
     373        if (!pPrev)
     374        {
     375            *ppVDIfs = pCurr->pNext;
     376            rc = VINF_SUCCESS;
     377        }
     378        else if (pCurr)
     379        {
     380            pPrev = pCurr->pNext;
     381            rc = VINF_SUCCESS;
     382        }
     383    }
     384
     385    return rc;
    336386}
    337387
     
    12891339} VDBACKENDINFO, *PVDBACKENDINFO;
    12901340
     1341/**
     1342 * Completion callback for metadata reads or writes.
     1343 *
     1344 * @return  nothing.
     1345 * @param   pvBackendData   The opaque backend data.
     1346 * @param   pvMetaUser      Opaque user data passed during a metadata read/write request.
     1347 */
     1348typedef DECLCALLBACK(void) FNVDMETACOMPLETED(void *pvBackendData, void *pvMetaUser);
     1349/** Pointer to FNVDCOMPLETED() */
     1350typedef FNVDMETACOMPLETED *PFNVDMETACOMPLETED;
     1351
     1352/** Forward declaration. Only visible in the VBoxHDD module. */
     1353/** I/O context */
     1354typedef struct VDIOCTX *PVDIOCTX;
     1355/** Storage backend handle. */
     1356typedef struct VDIOSTORAGE *PVDIOSTORAGE;
     1357/** Pointer to a storage backend handle. */
     1358typedef PVDIOSTORAGE *PPVDIOSTORAGE;
     1359
     1360/**
     1361 * Support interface for I/O
     1362 *
     1363 * Per-image. Required.
     1364 */
     1365typedef struct VDINTERFACEIO
     1366{
     1367    /**
     1368     * Size of the I/O interface.
     1369     */
     1370    uint32_t    cbSize;
     1371
     1372    /**
     1373     * Interface type.
     1374     */
     1375    VDINTERFACETYPE enmInterface;
     1376
     1377    /**
     1378     * Open callback
     1379     *
     1380     * @return  VBox status code.
     1381     * @param   pvUser          The opaque data passed on container creation.
     1382     * @param   pszLocation     Name of the location to open.
     1383     * @param   uOpenFlags      Flags for opening the backend.
     1384     *                          See VD_INTERFACEASYNCIO_OPEN_FLAGS_* #defines
     1385     * @param   ppStorage       Where to store the storage handle.
     1386     */
     1387    DECLR3CALLBACKMEMBER(int, pfnOpen, (void *pvUser, const char *pszLocation,
     1388                                        unsigned uOpenFlags, PPVDIOSTORAGE ppStorage));
     1389
     1390    /**
     1391     * Close callback.
     1392     *
     1393     * @return  VBox status code.
     1394     * @param   pvUser          The opaque data passed on container creation.
     1395     * @param   pStorage        The storage handle to close.
     1396     */
     1397    DECLR3CALLBACKMEMBER(int, pfnClose, (void *pvUser, PVDIOSTORAGE pStorage));
     1398
     1399    /**
     1400     * Returns the size of the opened storage backend.
     1401     *
     1402     * @return  VBox status code.
     1403     * @param   pvUser          The opaque data passed on container creation.
     1404     * @param   pStorage        The storage handle to get the size from.
     1405     * @param   pcbSize         Where to store the size of the storage backend.
     1406     */
     1407    DECLR3CALLBACKMEMBER(int, pfnGetSize, (void *pvUser, PVDIOSTORAGE pStorage,
     1408                                           uint64_t *pcbSize));
     1409
     1410    /**
     1411     * Sets the size of the opened storage backend if possible.
     1412     *
     1413     * @return  VBox status code.
     1414     * @retval  VERR_NOT_SUPPORTED if the backend does not support this operation.
     1415     * @param   pvUser          The opaque data passed on container creation.
     1416     * @param   pStorage        The storage handle.
     1417     * @param   cbSize          The new size of the image.
     1418     */
     1419    DECLR3CALLBACKMEMBER(int, pfnSetSize, (void *pvUser, PVDIOSTORAGE pStorage,
     1420                                           uint64_t cbSize));
     1421
     1422    /**
     1423     * Synchronous write callback.
     1424     *
     1425     * @return  VBox status code.
     1426     * @param   pvUser          The opaque data passed on container creation.
     1427     * @param   pStorage        The storage handle to use.
     1428     * @param   uOffset         The offset to start from.
     1429     * @param   cbWrite         How many bytes to write.
     1430     * @param   pvBuf           Pointer to the bits need to be written.
     1431     * @param   pcbWritten      Where to store how many bytes where actually written.
     1432     *
     1433     * @notes Do not use in code called from the async read/write entry points in the backends.
     1434     *        This should be only used during open/close of images and for the support functions
     1435     *        which are not called while a VM is running (pfnCompact).
     1436     */
     1437    DECLR3CALLBACKMEMBER(int, pfnWriteSync, (void *pvUser, PVDIOSTORAGE pStorage, uint64_t uOffset,
     1438                                             size_t cbWrite, const void *pvBuf, size_t *pcbWritten));
     1439
     1440    /**
     1441     * Synchronous read callback.
     1442     *
     1443     * @return  VBox status code.
     1444     * @param   pvUser          The opaque data passed on container creation.
     1445     * @param   pStorage        The storage handle to use.
     1446     * @param   uOffset         The offset to start from.
     1447     * @param   cbRead          How many bytes to read.
     1448     * @param   pvBuf           Where to store the read bits.
     1449     * @param   pcbRead         Where to store how many bytes where actually read.
     1450     *
     1451     * @notes See pfnWriteSync()
     1452     */
     1453    DECLR3CALLBACKMEMBER(int, pfnReadSync, (void *pvUser, PVDIOSTORAGE pStorage, uint64_t uOffset,
     1454                                            size_t cbRead, void *pvBuf, size_t *pcbRead));
     1455
     1456    /**
     1457     * Flush data to the storage backend.
     1458     *
     1459     * @return  VBox statis code.
     1460     * @param   pvUser          The opaque data passed on container creation.
     1461     * @param   pStorage        The storage handle to flush.
     1462     *
     1463     * @notes See pfnWriteSync()
     1464     */
     1465    DECLR3CALLBACKMEMBER(int, pfnFlushSync, (void *pvUser, PVDIOSTORAGE pStorage));
     1466
     1467    /**
     1468     * Initiate a asynchronous read request for user data.
     1469     *
     1470     * @return  VBox status code.
     1471     * @param   pvUser         The opqaue user data passed on container creation.
     1472     * @param   pStorage       The storage handle.
     1473     * @param   uOffset        The offset to start reading from.
     1474     * @param   pIoCtx         I/O context passed in VDAsyncRead/Write.
     1475     * @param   cbRead         How many bytes to read.
     1476     */
     1477    DECLR3CALLBACKMEMBER(int, pfnReadUserAsync, (void *pvUser, PVDIOSTORAGE pStorage,
     1478                                                 uint64_t uOffset, PVDIOCTX pIoCtx,
     1479                                                 size_t cbRead));
     1480
     1481    /**
     1482     * Initiate a asynchronous write request for user data.
     1483     *
     1484     * @return  VBox status code.
     1485     * @param   pvUser         The opaque user data passed on container creation.
     1486     * @param   pStorage       The storage handle.
     1487     * @param   uOffset        The offset to start writing to.
     1488     * @param   pIoCtx         I/O context passed in VDAsyncRead/Write
     1489     * @param   cbWrite        How many bytes to write.
     1490     */
     1491    DECLR3CALLBACKMEMBER(int, pfnWriteUserAsync, (void *pvUser, PVDIOSTORAGE pStorage,
     1492                                                  uint64_t uOffset, PVDIOCTX pIoCtx,
     1493                                                  size_t cbWrite));
     1494
     1495    /**
     1496     * Reads metadata asynchronously from storage.
     1497     * The current I/O context will be halted.
     1498     *
     1499     * @returns VBox status code.
     1500     * @param   pvUser              The opaque user data passed on container creation.
     1501     * @param   pStorage            The storage handle.
     1502     * @param   uOffset             Offsete to start reading from.
     1503     * @param   pvBuf               Where to store the data.
     1504     * @param   cbRead              How many bytes to read.
     1505     * @param   pIoCtx              The I/O context which triggered the read.
     1506     * @param   pfnMetaCompleted    Callback to call when the read completes.
     1507     * @param   pvMetaUser          Opaque user data which is passed in the callback.
     1508     */
     1509    DECLR3CALLBACKMEMBER(int, pfnReadMetaAsync, (void *pvUser, PVDIOSTORAGE pStorage,
     1510                                                 uint64_t uOffset, void *pvBuf,
     1511                                                 size_t cbRead, PVDIOCTX pIoCtx,
     1512                                                 PFNVDMETACOMPLETED pfnMetaCompleted,
     1513                                                 void *pvMetaUser));
     1514
     1515    /**
     1516     * Writes metadata asynchronously to storage.
     1517     *
     1518     * @returns VBox status code.
     1519     * @param   pvUser              The opaque user data passed on container creation.
     1520     * @param   pStorage            The storage handle.
     1521     * @param   uOffset             Offsete to start writing to.
     1522     * @param   pvBuf               Written data.
     1523     * @param   cbWrite             How many bytes to write.
     1524     * @param   pIoCtx              The I/O context which triggered the write.
     1525     * @param   pfnMetaCompleted    Callback to call when the write completes.
     1526     * @param   pvMetaUser          Opaque user data which is passed in the callback.
     1527     */
     1528    DECLR3CALLBACKMEMBER(int, pfnWriteMetaAsync, (void *pvUser, PVDIOSTORAGE pStorage,
     1529                                                  uint64_t uOffset, void *pvBuf,
     1530                                                  size_t cbWrite, PVDIOCTX pIoCtx,
     1531                                                  PFNVDMETACOMPLETED pfnMetaCompleted,
     1532                                                  void *pvMetaUser));
     1533
     1534    /**
     1535     * Initiates a async flush request.
     1536     *
     1537     * @return  VBox statis code.
     1538     * @param   pvUser          The opaque data passed on container creation.
     1539     * @param   pStorage        The storage handle to flush.
     1540     * @param   pIoCtx          I/O context which triggered the flush.
     1541     */
     1542    DECLR3CALLBACKMEMBER(int, pfnFlushAsync, (void *pvUser, PVDIOSTORAGE pStorage,
     1543                                              PVDIOCTX pIoCtx));
     1544
     1545    /**
     1546     * Copies a buffer into the I/O context.
     1547     *
     1548     * @return Number of bytes copied.
     1549     * @param  pvUser          The opaque user data passed on conatiner creation.
     1550     * @param  pIoCtx          I/O context to copy the data to.
     1551     * @param  pvBuf           Buffer to copy.
     1552     * @param  cbBuf           Number of bytes to copy.
     1553     */
     1554    DECLR3CALLBACKMEMBER(size_t, pfnIoCtxCopyTo, (void *pvUser, PVDIOCTX pIoCtx,
     1555                                                  void *pvBuf, size_t cbBuf));
     1556
     1557    /**
     1558     * Copies data from the I/O context into a buffer.
     1559     *
     1560     * @return Number of bytes copied.
     1561     * @param  pvUser          The opaque user data passed on conatiner creation.
     1562     * @param  pIoCtx          I/O context to copy the data from.
     1563     * @param  pvBuf           Destination buffer.
     1564     * @param  cbBuf           Number of bytes to copy.
     1565     */
     1566    DECLR3CALLBACKMEMBER(size_t, pfnIoCtxCopyFrom, (void *pvUser, PVDIOCTX pIoCtx,
     1567                                                    void *pvBuf, size_t cbBuf));
     1568
     1569    /**
     1570     * Sets the buffer of the given context to a specific byte.
     1571     *
     1572     * @return Number of bytes set.
     1573     * @param  pvUser          The opaque user data passed on conatiner creation.
     1574     * @param  pIoCtx          I/O context to copy the data from.
     1575     * @param  ch              The byte to set.
     1576     * @param  cbSet           Number of bytes to set.
     1577     */
     1578    DECLR3CALLBACKMEMBER(size_t, pfnIoCtxSet, (void *pvUser, PVDIOCTX pIoCtx,
     1579                                               int ch, size_t cbSet));
     1580
     1581} VDINTERFACEIO, *PVDINTERFACEIO;
     1582
     1583/**
     1584 * Get async I/O interface from opaque callback table.
     1585 *
     1586 * @return Pointer to the callback table.
     1587 * @param  pInterface Pointer to the interface descriptor.
     1588 */
     1589DECLINLINE(PVDINTERFACEIO) VDGetInterfaceIO(PVDINTERFACE pInterface)
     1590{
     1591    /* Check that the interface descriptor is a async I/O interface. */
     1592    AssertMsgReturn(   (pInterface->enmInterface == VDINTERFACETYPE_IO)
     1593                    && (pInterface->cbSize == sizeof(VDINTERFACE)),
     1594                    ("Not an I/O interface"), NULL);
     1595
     1596    PVDINTERFACEIO pInterfaceIO = (PVDINTERFACEIO)pInterface->pCallbacks;
     1597
     1598    /* Do basic checks. */
     1599    AssertMsgReturn(   (pInterfaceIO->cbSize == sizeof(VDINTERFACEIO))
     1600                    && (pInterfaceIO->enmInterface == VDINTERFACETYPE_IO),
     1601                    ("A non I/O callback table attached to a I/O interface descriptor\n"), NULL);
     1602
     1603    return pInterfaceIO;
     1604}
    12911605
    12921606/**
     
    12971611typedef struct VBOXHDD VBOXHDD;
    12981612typedef VBOXHDD *PVBOXHDD;
     1613
     1614/**
     1615 * Request completion callback for the async read/write API.
     1616 */
     1617typedef void (FNVDASYNCTRANSFERCOMPLETE) (void *pvUser1, void *pvUser2);
     1618/** Pointer to a transfer compelte callback. */
     1619typedef FNVDASYNCTRANSFERCOMPLETE *PFNVDASYNCTRANSFERCOMPLETE;
    12991620
    13001621/**
     
    18652186 * @param   paSeg           Pointer to an array of segments.
    18662187 * @param   cSeg            Number of segments in the array.
     2188 * @param   pfnComplete     Completion callback.
    18672189 * @param   pvUser          User data which is passed on completion
    18682190 */
    18692191VBOXDDU_DECL(int) VDAsyncRead(PVBOXHDD pDisk, uint64_t uOffset, size_t cbRead,
    18702192                              PPDMDATASEG paSeg, unsigned cSeg,
    1871                               void *pvUser);
     2193                              PFNVDASYNCTRANSFERCOMPLETE pfnComplete,
     2194                              void *pvUser1, void *pvUser2);
    18722195
    18732196
     
    18812204 * @param   paSeg           Pointer to an array of segments.
    18822205 * @param   cSeg            Number of segments in the array.
     2206 * @param   pfnComplete     Completion callback.
    18832207 * @param   pvUser          User data which is passed on completion.
    18842208 */
    18852209VBOXDDU_DECL(int) VDAsyncWrite(PVBOXHDD pDisk, uint64_t uOffset, size_t cbWrite,
    18862210                               PPDMDATASEG paSeg, unsigned cSeg,
    1887                                void *pvUser);
     2211                               PFNVDASYNCTRANSFERCOMPLETE pfnComplete,
     2212                               void *pvUser1, void *pvUser2);
    18882213
    18892214
  • trunk/src/VBox/Devices/Storage/DrvVD.cpp

    r27806 r27808  
    486486    PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
    487487
    488     return PDMR3AsyncCompletionEpRead(pStorageBackend->pEndpoint, uOffset, paSegments, cSegments, cbRead,
    489                                       pvCompletion, (PPPDMASYNCCOMPLETIONTASK)ppTask);
     488    int rc = PDMR3AsyncCompletionEpRead(pStorageBackend->pEndpoint, uOffset, paSegments, cSegments, cbRead,
     489                                        pvCompletion, (PPPDMASYNCCOMPLETIONTASK)ppTask);
     490    if (rc == VINF_AIO_TASK_PENDING)
     491        rc = VERR_VD_ASYNC_IO_IN_PROGRESS;
     492
     493    return rc;
    490494}
    491495
     
    498502    PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
    499503
    500     return PDMR3AsyncCompletionEpWrite(pStorageBackend->pEndpoint, uOffset, paSegments, cSegments, cbWrite,
    501                                        pvCompletion, (PPPDMASYNCCOMPLETIONTASK)ppTask);
     504    int rc = PDMR3AsyncCompletionEpWrite(pStorageBackend->pEndpoint, uOffset, paSegments, cSegments, cbWrite,
     505                                         pvCompletion, (PPPDMASYNCCOMPLETIONTASK)ppTask);
     506    if (rc == VINF_AIO_TASK_PENDING)
     507        rc = VERR_VD_ASYNC_IO_IN_PROGRESS;
     508
     509    return rc;
    502510}
    503511
     
    508516    PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
    509517
    510     return PDMR3AsyncCompletionEpFlush(pStorageBackend->pEndpoint, pvCompletion,
    511                                        (PPPDMASYNCCOMPLETIONTASK)ppTask);
     518    int rc = PDMR3AsyncCompletionEpFlush(pStorageBackend->pEndpoint, pvCompletion,
     519                                         (PPPDMASYNCCOMPLETIONTASK)ppTask);
     520    if (rc == VINF_AIO_TASK_PENDING)
     521        rc = VERR_VD_ASYNC_IO_IN_PROGRESS;
     522
     523    return rc;
    512524}
    513525
     
    984996*******************************************************************************/
    985997
     998static void drvvdAsyncReqComplete(void *pvUser1, void *pvUser2)
     999{
     1000    PVBOXDISK pThis = (PVBOXDISK)pThis;
     1001
     1002    int rc = pThis->pDrvMediaAsyncPort->pfnTransferCompleteNotify(pThis->pDrvMediaAsyncPort,
     1003                                                                  pvUser2);
     1004    AssertRC(rc);
     1005}
     1006
    9861007static DECLCALLBACK(int) drvvdStartRead(PPDMIMEDIAASYNC pInterface, uint64_t uOffset,
    9871008                                        PPDMDATASEG paSeg, unsigned cSeg,
     
    9911012             uOffset, paSeg, cSeg, cbRead, pvUser));
    9921013    PVBOXDISK pThis = PDMIMEDIAASYNC_2_VBOXDISK(pInterface);
    993     int rc = VDAsyncRead(pThis->pDisk, uOffset, cbRead, paSeg, cSeg, pvUser);
     1014    int rc = VDAsyncRead(pThis->pDisk, uOffset, cbRead, paSeg, cSeg,
     1015                         drvvdAsyncReqComplete, pThis, pvUser);
    9941016    LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
    9951017    return rc;
     
    10031025             uOffset, paSeg, cSeg, cbWrite, pvUser));
    10041026    PVBOXDISK pThis = PDMIMEDIAASYNC_2_VBOXDISK(pInterface);
    1005     int rc = VDAsyncWrite(pThis->pDisk, uOffset, cbWrite, paSeg, cSeg, pvUser);
     1027    int rc = VDAsyncWrite(pThis->pDisk, uOffset, cbWrite, paSeg, cSeg,
     1028                          drvvdAsyncReqComplete, pThis, pvUser);
    10061029    LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
    10071030    return rc;
    1008 }
    1009 
    1010 /*******************************************************************************
    1011 *   Async transport port interface methods                                     *
    1012 *******************************************************************************/
    1013 
    1014 static DECLCALLBACK(int) drvvdTasksCompleteNotify(PPDMDRVINS pDrvIns, void *pvUser)
    1015 {
    1016     return VERR_NOT_IMPLEMENTED;
    10171031}
    10181032
     
    14641478    }
    14651479
     1480#if 0 /* Temporary disabled. WIP
    14661481    if (pThis->pDrvMediaAsyncPort)
    14671482        pThis->fAsyncIOSupported = true;
     1483#else
     1484    pThis->fAsyncIOSupported = false;
     1485#endif
    14681486
    14691487    unsigned iImageIdx = 0;
  • trunk/src/VBox/Devices/Storage/ISCSIHDDCore.cpp

    r27181 r27808  
    38403840    /* pfnAsyncWrite */
    38413841    NULL,
     3842    /* pfnAsyncFlush */
     3843    NULL,
    38423844    /* pfnComposeLocation */
    38433845    iscsiComposeLocation,
  • trunk/src/VBox/Devices/Storage/ParallelsHDDCore.cpp

    r27232 r27808  
    7272#ifdef VBOX_WITH_NEW_IO_CODE
    7373    /** Async I/O interface. */
    74     PVDINTERFACE        pInterfaceAsyncIO;
     74    PVDINTERFACE        pInterfaceIO;
    7575    /** Async I/O interface callbacks. */
    76     PVDINTERFACEASYNCIO pInterfaceAsyncIOCallbacks;
     76    PVDINTERFACEIO      pInterfaceIOCallbacks;
    7777#endif
    7878
     
    8484#else
    8585    /** Opaque storage handle. */
    86     void               *pvStorage;
     86    PVDIOSTORAGE        pStorage;
    8787#endif
    8888    /** Open flags passed by VBoxHD layer. */
     
    153153    rc = RTFileOpen(&pImage->File, pImage->pszFilename, fOpen);
    154154#else
    155 
    156155    unsigned uOpenFlags = fReadonly ? VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY : 0;
    157156
     
    159158        uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE;
    160159
    161     rc = pImage->pInterfaceAsyncIOCallbacks->pfnOpen(pImage->pInterfaceAsyncIO->pvUser,
    162                                                      pImage->pszFilename,
    163                                                      uOpenFlags,
    164                                                      NULL,
    165                                                      pImage->pVDIfsDisk,
    166                                                      &pImage->pvStorage);
     160    rc = pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser,
     161                                                pImage->pszFilename,
     162                                                uOpenFlags,
     163                                                &pImage->pStorage);
    167164#endif
    168165
     
    180177    pImage->File = NIL_RTFILE;
    181178#else
    182     if (pImage->pvStorage)
    183         rc = pImage->pInterfaceAsyncIOCallbacks->pfnClose(pImage->pInterfaceAsyncIO->pvUser,
    184                                                           pImage->pvStorage);
    185 
    186     pImage->pvStorage = NULL;
     179    rc = pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser,
     180                                                 pImage->pStorage);
     181
     182    pImage->pStorage = NULL;
    187183#endif
    188184
     
    197193    rc = RTFileFlush(pImage->File);
    198194#else
    199     if (pImage->pvStorage)
    200         rc = pImage->pInterfaceAsyncIOCallbacks->pfnFlushSync(pImage->pInterfaceAsyncIO->pvUser,
    201                                                               pImage->pvStorage);
     195    rc = pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser,
     196                                                     pImage->pStorage);
    202197#endif
    203198
     
    212207    rc = RTFileGetSize(pImage->File, pcbSize);
    213208#else
    214     if (pImage->pvStorage)
    215         rc = pImage->pInterfaceAsyncIOCallbacks->pfnGetSize(pImage->pInterfaceAsyncIO->pvUser,
    216                                                             pImage->pvStorage,
    217                                                             pcbSize);
     209    rc = pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser,
     210                                                   pImage->pStorage, pcbSize);
    218211#endif
    219212
     
    229222    rc = RTFileSetSize(pImage->File, cbSize);
    230223#else
    231     if (pImage->pvStorage)
    232         rc = pImage->pInterfaceAsyncIOCallbacks->pfnSetSize(pImage->pInterfaceAsyncIO->pvUser,
    233                                                             pImage->pvStorage,
    234                                                             cbSize);
     224    rc = pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser,
     225                                                   pImage->pStorage,
     226                                                   cbSize);
    235227#endif
    236228
     
    246238    rc = RTFileWriteAt(pImage->File, off, pcvBuf, cbWrite, pcbWritten);
    247239#else
    248     if (pImage->pvStorage)
    249         rc = pImage->pInterfaceAsyncIOCallbacks->pfnWriteSync(pImage->pInterfaceAsyncIO->pvUser,
    250                                                               pImage->pvStorage,
    251                                                               off, cbWrite, pcvBuf,
    252                                                               pcbWritten);
     240    rc = pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser,
     241                                                     pImage->pStorage,
     242                                                     off, cbWrite, pcvBuf,
     243                                                     pcbWritten);
    253244#endif
    254245
     
    263254    rc = RTFileReadAt(pImage->File, off, pvBuf, cbRead, pcbRead);
    264255#else
    265     if (pImage->pvStorage)
    266         rc = pImage->pInterfaceAsyncIOCallbacks->pfnReadSync(pImage->pInterfaceAsyncIO->pvUser,
    267                                                              pImage->pvStorage,
    268                                                              off, cbRead, pvBuf,
    269                                                              pcbRead);
     256    rc = pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser,
     257                                                    pImage->pStorage,
     258                                                    off, cbRead, pvBuf,
     259                                                    pcbRead);
    270260#endif
    271261
     
    278268    return pImage->File != NIL_RTFILE;
    279269#else
    280     return pImage->pvStorage != NULL;
     270    return pImage->pStorage != NULL;
    281271#endif
    282272}
     
    294284#ifdef VBOX_WITH_NEW_IO_CODE
    295285    /* Try to get async I/O interface. */
    296     pImage->pInterfaceAsyncIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ASYNCIO);
    297     AssertPtr(pImage->pInterfaceAsyncIO);
    298     pImage->pInterfaceAsyncIOCallbacks = VDGetInterfaceAsyncIO(pImage->pInterfaceAsyncIO);
    299     AssertPtr(pImage->pInterfaceAsyncIOCallbacks);
     286    pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_IO);
     287    AssertPtr(pImage->pInterfaceIO);
     288    pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO);
     289    AssertPtr(pImage->pInterfaceIOCallbacks);
    300290#endif
    301291
     
    504494    pImage->File = NIL_RTFILE;
    505495#else
    506     pImage->pvStorage = NULL;
     496    pImage->pStorage = NULL;
    507497#endif
    508498    pImage->fAllocationBitmapChanged = false;
     
    11921182
    11931183static int parallelsAsyncRead(void *pvBackendData, uint64_t uOffset, size_t cbRead,
    1194                               PPDMDATASEG paSeg, unsigned cSeg, void *pvUser)
    1195 {
    1196     return VERR_NOT_SUPPORTED;
     1184                              PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
     1185{
     1186    int rc = VERR_NOT_IMPLEMENTED;
     1187    LogFlowFunc(("returns %Rrc\n", rc));
     1188    return rc;
    11971189}
    11981190
    11991191static int parallelsAsyncWrite(void *pvBackendData, uint64_t uOffset, size_t cbWrite,
    1200                                PPDMDATASEG paSeg, unsigned cSeg, void *pvUser)
    1201 {
    1202     return VERR_NOT_SUPPORTED;
     1192                               PVDIOCTX pIoCtx,
     1193                               size_t *pcbWriteProcess, size_t *pcbPreRead,
     1194                               size_t *pcbPostRead, unsigned fWrite)
     1195{
     1196    int rc = VERR_NOT_IMPLEMENTED;
     1197    LogFlowFunc(("returns %Rrc\n", rc));
     1198    return rc;
     1199}
     1200
     1201static int parallelsAsyncFlush(void *pvBackendData, PVDIOCTX pIoCtx)
     1202{
     1203    int rc = VERR_NOT_IMPLEMENTED;
     1204    LogFlowFunc(("returns %Rrc\n", rc));
     1205    return rc;
    12031206}
    12041207
     
    12911294    /* pfnAsyncWrite */
    12921295    parallelsAsyncWrite,
     1296    /* pfnAsyncFlush */
     1297    parallelsAsyncFlush,
    12931298    /* pfnComposeLocation */
    12941299    genericFileComposeLocation,
  • trunk/src/VBox/Devices/Storage/RawHDDCore.cpp

    r27232 r27808  
    4343{
    4444    /** Base image name. */
    45     const char      *pszFilename;
     45    const char       *pszFilename;
    4646#ifndef VBOX_WITH_NEW_IO_CODE
    4747    /** File descriptor. */
    48     RTFILE          File;
     48    RTFILE            File;
    4949#else
    50     /** Opaque storage handle. */
    51     void           *pvStorage;
     50    /** Storage handle. */
     51    PVDIOSTORAGE      pStorage;
     52    /** I/O interface. */
     53    PVDINTERFACE      pInterfaceIO;
     54    /** Async I/O interface callbacks. */
     55    PVDINTERFACEIO    pInterfaceIOCallbacks;
    5256#endif
    5357
     
    5963    /** Opaque data for error callback. */
    6064    PVDINTERFACEERROR pInterfaceErrorCallbacks;
    61 #ifdef VBOX_WITH_NEW_IO_CODE
    62     /** Async I/O interface. */
    63     PVDINTERFACE        pInterfaceAsyncIO;
    64     /** Async I/O interface callbacks. */
    65     PVDINTERFACEASYNCIO pInterfaceAsyncIOCallbacks;
    66 #endif
    6765
    6866    /** Open flags passed by VBoxHD layer. */
    69     unsigned        uOpenFlags;
     67    unsigned          uOpenFlags;
    7068    /** Image flags defined during creation or determined during open. */
    71     unsigned        uImageFlags;
     69    unsigned          uImageFlags;
    7270    /** Total size of the image. */
    73     uint64_t        cbSize;
     71    uint64_t          cbSize;
    7472    /** Physical geometry of this image. */
    75     PDMMEDIAGEOMETRY PCHSGeometry;
     73    PDMMEDIAGEOMETRY  PCHSGeometry;
    7674    /** Logical geometry of this image. */
    77     PDMMEDIAGEOMETRY LCHSGeometry;
     75    PDMMEDIAGEOMETRY  LCHSGeometry;
    7876
    7977} RAWIMAGE, *PRAWIMAGE;
     
    132130    rc = RTFileOpen(&pImage->File, pImage->pszFilename, fOpen);
    133131#else
    134 
    135132    unsigned uOpenFlags = fReadonly ? VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY : 0;
    136133
     
    138135        uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE;
    139136
    140     rc = pImage->pInterfaceAsyncIOCallbacks->pfnOpen(pImage->pInterfaceAsyncIO->pvUser,
    141                                                      pImage->pszFilename,
    142                                                      uOpenFlags,
    143                                                      NULL,
    144                                                      pImage->pVDIfsDisk,
    145                                                      &pImage->pvStorage);
     137    rc = pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser,
     138                                                pImage->pszFilename,
     139                                                uOpenFlags,
     140                                                &pImage->pStorage);
    146141#endif
    147142
     
    159154    pImage->File = NIL_RTFILE;
    160155#else
    161     if (pImage->pvStorage)
    162         rc = pImage->pInterfaceAsyncIOCallbacks->pfnClose(pImage->pInterfaceAsyncIO->pvUser,
    163                                                           pImage->pvStorage);
    164 
    165     pImage->pvStorage = NULL;
     156    if (pImage->pStorage)
     157        rc = pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser,
     158                                                     pImage->pStorage);
     159
     160    pImage->pStorage = NULL;
    166161#endif
    167162
     
    176171    rc = RTFileFlush(pImage->File);
    177172#else
    178     if (pImage->pvStorage)
    179         rc = pImage->pInterfaceAsyncIOCallbacks->pfnFlushSync(pImage->pInterfaceAsyncIO->pvUser,
    180                                                               pImage->pvStorage);
     173    rc = pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser,
     174                                                     pImage->pStorage);
    181175#endif
    182176
     
    191185    rc = RTFileGetSize(pImage->File, pcbSize);
    192186#else
    193     if (pImage->pvStorage)
    194         rc = pImage->pInterfaceAsyncIOCallbacks->pfnGetSize(pImage->pInterfaceAsyncIO->pvUser,
    195                                                             pImage->pvStorage,
    196                                                             pcbSize);
     187    rc = pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser,
     188                                                   pImage->pStorage,
     189                                                   pcbSize);
    197190#endif
    198191
     
    208201    rc = RTFileSetSize(pImage->File, cbSize);
    209202#else
    210     if (pImage->pvStorage)
    211         rc = pImage->pInterfaceAsyncIOCallbacks->pfnSetSize(pImage->pInterfaceAsyncIO->pvUser,
    212                                                             pImage->pvStorage,
    213                                                             cbSize);
     203    rc = pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser,
     204                                                   pImage->pStorage,
     205                                                   cbSize);
    214206#endif
    215207
     
    225217    rc = RTFileWriteAt(pImage->File, off, pcvBuf, cbWrite, pcbWritten);
    226218#else
    227     if (pImage->pvStorage)
    228         rc = pImage->pInterfaceAsyncIOCallbacks->pfnWriteSync(pImage->pInterfaceAsyncIO->pvUser,
    229                                                               pImage->pvStorage,
    230                                                               off, cbWrite, pcvBuf,
    231                                                               pcbWritten);
     219    rc = pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser,
     220                                                     pImage->pStorage,
     221                                                     off, cbWrite, pcvBuf,
     222                                                     pcbWritten);
    232223#endif
    233224
     
    242233    rc = RTFileReadAt(pImage->File, off, pvBuf, cbRead, pcbRead);
    243234#else
    244     if (pImage->pvStorage)
    245         rc = pImage->pInterfaceAsyncIOCallbacks->pfnReadSync(pImage->pInterfaceAsyncIO->pvUser,
    246                                                              pImage->pvStorage,
    247                                                              off, cbRead, pvBuf,
    248                                                              pcbRead);
     235    rc = pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser,
     236                                                    pImage->pStorage,
     237                                                    off, cbRead, pvBuf,
     238                                                    pcbRead);
    249239#endif
    250240
     
    257247    return pImage->File != NIL_RTFILE;
    258248#else
    259     return pImage->pvStorage != NULL;
     249    return pImage->pStorage != NULL;
    260250#endif
    261251}
     
    278268
    279269#ifdef VBOX_WITH_NEW_IO_CODE
    280     /* Try to get async I/O interface. */
    281     pImage->pInterfaceAsyncIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ASYNCIO);
    282     AssertPtr(pImage->pInterfaceAsyncIO);
    283     pImage->pInterfaceAsyncIOCallbacks = VDGetInterfaceAsyncIO(pImage->pInterfaceAsyncIO);
    284     AssertPtr(pImage->pInterfaceAsyncIOCallbacks);
     270    /* Try to get I/O interface. */
     271    pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_IO);
     272    AssertPtr(pImage->pInterfaceIO);
     273    pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO);
     274    AssertPtr(pImage->pInterfaceIOCallbacks);
    285275#endif
    286276
     
    345335#ifdef VBOX_WITH_NEW_IO_CODE
    346336    /* Try to get async I/O interface. */
    347     pImage->pInterfaceAsyncIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ASYNCIO);
    348     AssertPtr(pImage->pInterfaceAsyncIO);
    349     pImage->pInterfaceAsyncIOCallbacks = VDGetInterfaceAsyncIO(pImage->pInterfaceAsyncIO);
    350     AssertPtr(pImage->pInterfaceAsyncIOCallbacks);
     337    pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_IO);
     338    AssertPtr(pImage->pInterfaceIO);
     339    pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO);
     340    AssertPtr(pImage->pInterfaceIOCallbacks);
    351341#endif
    352342
     
    518508    pImage->File = NIL_RTFILE;
    519509#else
    520     pImage->pvStorage = NULL;
     510    pImage->pStorage = NULL;
    521511#endif
    522512    pImage->pVDIfsDisk = pVDIfsDisk;
     
    587577    pImage->File = NIL_RTFILE;
    588578#else
    589     pImage->pvStorage = NULL;
     579    pImage->pStorage = NULL;
    590580#endif
    591581    pImage->pVDIfsDisk = pVDIfsDisk;
     
    12141204
    12151205static int rawAsyncRead(void *pvBackendData, uint64_t uOffset, size_t cbRead,
    1216                         PPDMDATASEG paSeg, unsigned cSeg, void *pvUser)
     1206                        PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
    12171207{
    12181208    int rc = VERR_NOT_IMPLEMENTED;
     
    12221212
    12231213static int rawAsyncWrite(void *pvBackendData, uint64_t uOffset, size_t cbWrite,
    1224                          PPDMDATASEG paSeg, unsigned cSeg, void *pvUser)
     1214                         PVDIOCTX pIoCtx,
     1215                         size_t *pcbWriteProcess, size_t *pcbPreRead,
     1216                         size_t *pcbPostRead, unsigned fWrite)
     1217{
     1218    int rc = VERR_NOT_IMPLEMENTED;
     1219    LogFlowFunc(("returns %Rrc\n", rc));
     1220    return rc;
     1221}
     1222
     1223static int rawAsyncFlush(void *pvBackendData, PVDIOCTX pIoCtx)
    12251224{
    12261225    int rc = VERR_NOT_IMPLEMENTED;
     
    13171316    /* pfnAsyncWrite */
    13181317    rawAsyncWrite,
     1318    /* pfnAsyncFlush */
     1319    rawAsyncFlush,
    13191320    /* pfnComposeLocation */
    13201321    genericFileComposeLocation,
  • trunk/src/VBox/Devices/Storage/VBoxHDD.cpp

    r27806 r27808  
    3939#include <iprt/path.h>
    4040#include <iprt/param.h>
     41#include <iprt/memcache.h>
    4142
    4243#include <VBox/VBoxHDD-Plugin.h>
     
    8283    /** Function pointers for the various backend methods. */
    8384    PCVBOXHDDBACKEND    Backend;
    84 
    8585    /** Pointer to list of VD interfaces, per-image. */
    8686    PVDINTERFACE        pVDIfsImage;
     
    135135    PVDINTERFACETHREADSYNC pInterfaceThreadSyncCallbacks;
    136136
    137     /** Fallback async interface. */
     137    /** I/O interface for the disk. */
     138    VDINTERFACE         VDIIO;
     139    /** I/O interface callback table for the images. */
     140    VDINTERFACEIO       VDIIOCallbacks;
     141
     142    /** Async I/O interface to the upper layer. */
     143    PVDINTERFACE        pInterfaceAsyncIO;
     144    /** Async I/O interface callback table. */
     145    PVDINTERFACEASYNCIO pInterfaceAsyncIOCallbacks;
     146
     147    /** Fallback async I/O interface. */
    138148    VDINTERFACE         VDIAsyncIO;
    139     /** Fallback async I/O interface callback table. */
     149    /** Callback table for the fallback async I/O interface. */
    140150    VDINTERFACEASYNCIO  VDIAsyncIOCallbacks;
     151
     152    /** Memory cache for I/O contexts */
     153    RTMEMCACHE          hMemCacheIoCtx;
    141154};
    142155
     
    153166} VDPARENTSTATEDESC, *PVDPARENTSTATEDESC;
    154167
     168/**
     169 * Transfer direction.
     170 */
     171typedef enum VDIOCTXTXDIR
     172{
     173    /** Read */
     174    VDIOCTXTXDIR_READ = 0,
     175    /** Write */
     176    VDIOCTXTXDIR_WRITE,
     177    /** Flush */
     178    VDIOCTXTXDIR_FLUSH,
     179    /** 32bit hack */
     180    VDIOCTXTXDIR_32BIT_HACK = 0x7fffffff
     181} VDIOCTXTXDIR, *PVDIOCTXTXDIR;
     182
     183/**
     184 * I/O context
     185 */
     186typedef struct VDIOCTX
     187{
     188    /** Completion callback */
     189    PFNVDASYNCTRANSFERCOMPLETE   pfnComplete;
     190    /** User argument 1 passed on completion. */
     191    void                        *pvUser1;
     192    /** User argument 1 passed on completion. */
     193    void                        *pvUser2;
     194    /** Transfer direction */
     195    VDIOCTXTXDIR                 enmTxDir;
     196    /** Number of bytes left until this context completes. */
     197    volatile uint32_t            cbTransferLeft;
     198    /** Current offset */
     199    volatile uint64_t            uOffset;
     200    /** Pointer to the scatter/gather list. */
     201    PCPDMDATASEG                 paDataSeg;
     202    /** Number of segments. */
     203    size_t                       cSeg;
     204    /** Current segment we are in. */
     205    unsigned                     iSegIdx;
     206    /** Pointer to the current buffer. */
     207    uint8_t                     *pbBuf;
     208    /** Number of bytes left in the current buffer. */
     209    size_t                       cbBufLeft;
     210} VDIOCTX;
     211
     212/**
     213 * Storage handle.
     214 */
     215typedef struct VDIOSTORAGE
     216{
     217    /** Storage handle */
     218    void                        *pStorage;
     219} VDIOSTORAGE;
    155220
    156221extern VBOXHDDBACKEND g_RawBackend;
     
    394459        pvBuf = (char *)pvBuf + cbThisRead;
    395460    } while (cbRead != 0 && RT_SUCCESS(rc));
     461
     462    return rc;
     463}
     464
     465static PVDIOCTX vdIoCtxAlloc(PVBOXHDD pDisk, VDIOCTXTXDIR enmTxDir,
     466                             uint64_t uOffset, size_t cbTransfer,
     467                             PPDMDATASEG paSeg, unsigned cSeg,
     468                             PFNVDASYNCTRANSFERCOMPLETE pfnComplete,
     469                             void *pvUser1, void *pvUser2)
     470{
     471    PVDIOCTX pIoCtx = NULL;
     472
     473    pIoCtx = (PVDIOCTX)RTMemCacheAlloc(pDisk->hMemCacheIoCtx);
     474    if (pIoCtx)
     475    {
     476        pIoCtx->pfnComplete    = pfnComplete;
     477        pIoCtx->pvUser1        = pvUser1;
     478        pIoCtx->pvUser2        = pvUser2;
     479        pIoCtx->enmTxDir       = enmTxDir;
     480        pIoCtx->cbTransferLeft = cbTransfer;
     481        pIoCtx->uOffset        = uOffset;
     482        pIoCtx->paDataSeg      = paSeg;
     483        pIoCtx->cSeg           = cSeg;
     484        pIoCtx->iSegIdx        = 0;
     485        pIoCtx->pbBuf          = (uint8_t *)pIoCtx->paDataSeg[0].pvSeg;
     486        pIoCtx->cbBufLeft      = pIoCtx->paDataSeg[0].cbSeg;
     487    }
     488
     489    return pIoCtx;
     490}
     491
     492static void vdIoCtxFree(PVBOXHDD pDisk, PVDIOCTX pIoCtx)
     493{
     494    RTMemCacheFree(pDisk->hMemCacheIoCtx, pIoCtx);
     495}
     496
     497static uint8_t *vdIoCtxGetBuffer(PVDIOCTX pIoCtx, size_t *pcbData)
     498{
     499    size_t cbData = RT_MIN(*pcbData, pIoCtx->cbBufLeft);
     500    uint8_t *pbBuf = pIoCtx->pbBuf;
     501
     502    pIoCtx->cbBufLeft -= cbData;
     503
     504    /* Advance to the next segment if required. */
     505    if (!pIoCtx->cbBufLeft)
     506    {
     507        pIoCtx->iSegIdx++;
     508
     509        if (RT_UNLIKELY(pIoCtx->iSegIdx == pIoCtx->cSeg))
     510        {
     511            pIoCtx->cbBufLeft = 0;
     512            pIoCtx->pbBuf     = NULL;
     513        }
     514        else
     515        {
     516            pIoCtx->pbBuf     = (uint8_t *)pIoCtx->paDataSeg[pIoCtx->iSegIdx].pvSeg;
     517            pIoCtx->cbBufLeft = pIoCtx->paDataSeg[pIoCtx->iSegIdx].cbSeg;
     518        }
     519
     520        *pcbData = cbData;
     521    }
     522    else
     523        pIoCtx->pbBuf += cbData;
     524
     525    return pbBuf;
     526}
     527
     528
     529static size_t vdIoCtxCopyTo(PVDIOCTX pIoCtx, uint8_t *pbData, size_t cbData)
     530{
     531    size_t cbLeft = cbData;
     532
     533    while (cbLeft)
     534    {
     535        size_t cbCopy = cbLeft;
     536        uint8_t *pbBuf = vdIoCtxGetBuffer(pIoCtx, &cbCopy);
     537
     538        if (!cbCopy)
     539            break;
     540
     541        memcpy(pbBuf, pbData, cbCopy);
     542
     543        cbLeft -= cbCopy;
     544        pbData += cbCopy;
     545    }
     546
     547    return cbData - cbLeft;
     548}
     549
     550
     551static size_t vdIoCtxCopyFrom(PVDIOCTX pIoCtx, uint8_t *pbData, size_t cbData)
     552{
     553    size_t cbLeft = cbData;
     554
     555    while (cbLeft)
     556    {
     557        size_t cbCopy = cbData;
     558        uint8_t *pbBuf = vdIoCtxGetBuffer(pIoCtx, &cbCopy);
     559
     560        if (!cbCopy)
     561            break;
     562
     563        memcpy(pbData, pbBuf, cbCopy);
     564
     565        cbData -= cbCopy;
     566        pbData += cbCopy;
     567    }
     568
     569    return cbData - cbLeft;
     570}
     571
     572static size_t vdIoCtxSet(PVDIOCTX pIoCtx, int ch, size_t cbData)
     573{
     574    size_t cbLeft = cbData;
     575
     576    while (cbLeft)
     577    {
     578        size_t cbCopy = cbData;
     579        uint8_t *pbBuf = vdIoCtxGetBuffer(pIoCtx, &cbCopy);
     580
     581        if (!cbCopy)
     582            break;
     583
     584        memset(pbBuf, ch, cbCopy);
     585
     586        cbData -= cbCopy;
     587    }
     588
     589    return cbData - cbLeft;
     590}
     591
     592/**
     593 * internal: read the specified amount of data in whatever blocks the backend
     594 * will give us - async version.
     595 */
     596static int vdReadHelperAsync(PVBOXHDD pDisk, PVDIMAGE pImage, PVDIMAGE pImageParentOverride,
     597                             PVDIOCTX pIoCtx, uint64_t uOffset, size_t cbRead)
     598{
     599    int rc;
     600    size_t cbThisRead;
     601
     602    /* Loop until all reads started or we have a backend which needs to read metadata. */
     603    do
     604    {
     605        /* Search for image with allocated block. Do not attempt to read more
     606         * than the previous reads marked as valid. Otherwise this would return
     607         * stale data when different block sizes are used for the images. */
     608        cbThisRead = cbRead;
     609
     610        /*
     611         * Try to read from the given image.
     612         * If the block is not allocated read from override chain if present.
     613         */
     614        rc = pImage->Backend->pfnAsyncRead(pImage->pvBackendData,
     615                                           uOffset, cbThisRead,
     616                                           pIoCtx, &cbThisRead);
     617
     618        if (rc == VERR_VD_BLOCK_FREE)
     619        {
     620            for (PVDIMAGE pCurrImage = pImageParentOverride ? pImageParentOverride : pImage->pPrev;
     621                 pCurrImage != NULL && rc == VERR_VD_BLOCK_FREE;
     622                 pCurrImage = pCurrImage->pPrev)
     623            {
     624                rc = pCurrImage->Backend->pfnAsyncRead(pCurrImage->pvBackendData,
     625                                                       uOffset, cbThisRead,
     626                                                       pIoCtx, &cbThisRead);
     627            }
     628        }
     629
     630        if (rc == VERR_VD_BLOCK_FREE)
     631        {
     632            /* No image in the chain contains the data for the block. */
     633            vdIoCtxSet(pIoCtx, '\0', cbThisRead);
     634            rc = VINF_SUCCESS;
     635        }
     636
     637        if (RT_SUCCESS(rc))
     638        {
     639            /* Success and no async task is pending. */
     640            ASMAtomicSubU32(&pIoCtx->cbTransferLeft, cbThisRead);
     641        }
     642
     643        cbRead  -= cbThisRead;
     644        uOffset += cbThisRead;
     645    } while (cbRead != 0 && (   RT_SUCCESS(rc)
     646                             || rc == VERR_VD_ASYNC_IO_IN_PROGRESS));
     647
     648    if (rc == VERR_VD_NOT_ENOUGH_METADATA)
     649    {
     650        pIoCtx->uOffset = uOffset;
     651    }
    396652
    397653    return rc;
     
    9221178}
    9231179
     1180static int vdIOReqCompleted(void *pvUser, void **ppvCaller)
     1181{
     1182    return VINF_SUCCESS;
     1183}
     1184
     1185/**
     1186 * VD I/O interface callback for opening a file.
     1187 */
     1188static int vdIOOpen(void *pvUser, const char *pszLocation,
     1189                    unsigned uOpenFlags, PPVDIOSTORAGE ppIoStorage)
     1190{
     1191    int rc = VINF_SUCCESS;
     1192    PVBOXHDD pDisk          = (PVBOXHDD)pvUser;
     1193    PVDIOSTORAGE pIoStorage = (PVDIOSTORAGE)RTMemAllocZ(sizeof(VDIOSTORAGE));
     1194
     1195    if (!pIoStorage)
     1196        return VERR_NO_MEMORY;
     1197
     1198    rc = pDisk->pInterfaceAsyncIOCallbacks->pfnOpen(pDisk->pInterfaceAsyncIO->pvUser,
     1199                                                    pszLocation, uOpenFlags,
     1200                                                    vdIOReqCompleted,
     1201                                                    pDisk->pVDIfsDisk,
     1202                                                    &pIoStorage->pStorage);
     1203    if (RT_SUCCESS(rc))
     1204        *ppIoStorage = pIoStorage;
     1205    else
     1206        RTMemFree(pIoStorage);
     1207
     1208    return rc;
     1209}
     1210
     1211static int vdIOClose(void *pvUser, PVDIOSTORAGE pIoStorage)
     1212{
     1213    PVBOXHDD pDisk = (PVBOXHDD)pvUser;
     1214
     1215    int rc = pDisk->pInterfaceAsyncIOCallbacks->pfnClose(pDisk->pInterfaceAsyncIO->pvUser,
     1216                                                         pIoStorage->pStorage);
     1217    AssertRC(rc);
     1218
     1219    RTMemFree(pIoStorage);
     1220    return VINF_SUCCESS;
     1221}
     1222
     1223static int vdIOGetSize(void *pvUser, PVDIOSTORAGE pIoStorage,
     1224                       uint64_t *pcbSize)
     1225{
     1226    PVBOXHDD pDisk = (PVBOXHDD)pvUser;
     1227
     1228    return pDisk->pInterfaceAsyncIOCallbacks->pfnGetSize(pDisk->pInterfaceAsyncIO->pvUser,
     1229                                                         pIoStorage->pStorage,
     1230                                                         pcbSize);
     1231}
     1232
     1233static int vdIOSetSize(void *pvUser, PVDIOSTORAGE pIoStorage,
     1234                       uint64_t cbSize)
     1235{
     1236    PVBOXHDD pDisk = (PVBOXHDD)pvUser;
     1237
     1238    return pDisk->pInterfaceAsyncIOCallbacks->pfnSetSize(pDisk->pInterfaceAsyncIO->pvUser,
     1239                                                         pIoStorage->pStorage,
     1240                                                         cbSize);
     1241}
     1242
     1243static int vdIOWriteSync(void *pvUser, PVDIOSTORAGE pIoStorage, uint64_t uOffset,
     1244                         size_t cbWrite, const void *pvBuf, size_t *pcbWritten)
     1245{
     1246    PVBOXHDD pDisk = (PVBOXHDD)pvUser;
     1247
     1248    return pDisk->pInterfaceAsyncIOCallbacks->pfnWriteSync(pDisk->pInterfaceAsyncIO->pvUser,
     1249                                                           pIoStorage->pStorage,
     1250                                                           uOffset, cbWrite, pvBuf,
     1251                                                           pcbWritten);
     1252}
     1253
     1254static int vdIOReadSync(void *pvUser, PVDIOSTORAGE pIoStorage, uint64_t uOffset,
     1255                        size_t cbRead, void *pvBuf, size_t *pcbRead)
     1256{
     1257    PVBOXHDD pDisk = (PVBOXHDD)pvUser;
     1258
     1259    return pDisk->pInterfaceAsyncIOCallbacks->pfnReadSync(pDisk->pInterfaceAsyncIO->pvUser,
     1260                                                          pIoStorage->pStorage,
     1261                                                          uOffset, cbRead, pvBuf,
     1262                                                          pcbRead);
     1263}
     1264
     1265static int vdIOFlushSync(void *pvUser, PVDIOSTORAGE pIoStorage)
     1266{
     1267    PVBOXHDD pDisk = (PVBOXHDD)pvUser;
     1268
     1269    return pDisk->pInterfaceAsyncIOCallbacks->pfnFlushSync(pDisk->pInterfaceAsyncIO->pvUser,
     1270                                                           pIoStorage->pStorage);
     1271}
     1272
     1273static int vdIOReadUserAsync(void *pvUser, PVDIOSTORAGE pIoStorage,
     1274                             uint64_t uOffset, PVDIOCTX pIoCtx,
     1275                             size_t cbRead)
     1276{
     1277    return VERR_NOT_IMPLEMENTED;
     1278}
     1279
     1280static int vdIOWriteUserAsync(void *pvUser, PVDIOSTORAGE pIoStorage,
     1281                              uint64_t uOffset, PVDIOCTX pIoCtx,
     1282                              size_t cbWrite)
     1283{
     1284    return VERR_NOT_IMPLEMENTED;
     1285}
     1286
     1287static int vdIOReadMetaAsync(void *pvUser, PVDIOSTORAGE pIoStorage,
     1288                             uint64_t uOffset, void *pvBuf,
     1289                             size_t cbRead, PVDIOCTX pIoCtx,
     1290                             PFNVDMETACOMPLETED pfnMetaCompleted,
     1291                             void *pvMetaUser)
     1292{
     1293    return VERR_NOT_IMPLEMENTED;
     1294}
     1295
     1296static int vdIOWriteMetaAsync(void *pvUser, PVDIOSTORAGE pStorage,
     1297                              uint64_t uOffset, void *pvBuf,
     1298                              size_t cbWrite, PVDIOCTX pIoCtx,
     1299                              PFNVDMETACOMPLETED pfnMetaCompleted,
     1300                              void *pvMetaUser)
     1301{
     1302    return VERR_NOT_IMPLEMENTED;
     1303}
     1304
     1305static int vdIOFlushAsync(void *pvUser, PVDIOSTORAGE pIoStorage,
     1306                          PVDIOCTX pIoCtx)
     1307{
     1308    return VERR_NOT_IMPLEMENTED;
     1309}
     1310
     1311static size_t vdIOIoCtxCopyTo(void *pvUser, PVDIOCTX pIoCtx,
     1312                              void *pvBuf, size_t cbBuf)
     1313{
     1314    return vdIoCtxCopyTo(pIoCtx, (uint8_t *)pvBuf, cbBuf);
     1315}
     1316
     1317static size_t vdIOIoCtxCopyFrom(void *pvUser, PVDIOCTX pIoCtx,
     1318                                void *pvBuf, size_t cbBuf)
     1319{
     1320    return vdIoCtxCopyFrom(pIoCtx, (uint8_t *)pvBuf, cbBuf);
     1321}
     1322
     1323static size_t vdIOIoCtxSet(void *pvUser, PVDIOCTX pIoCtx,
     1324                           int ch, size_t cb)
     1325{
     1326    return vdIoCtxSet(pIoCtx, ch, cb);
     1327}
     1328
    9241329/**
    9251330 * internal: send output to the log (unconditionally).
     
    11031508            pDisk->pInterfaceThreadSyncCallbacks = NULL;
    11041509
     1510            /* Create the mem cache */
     1511            rc = RTMemCacheCreate(&pDisk->hMemCacheIoCtx, sizeof(VDIOCTX), 0, UINT32_MAX,
     1512                                  NULL, NULL, NULL, 0);
     1513            if (RT_FAILURE(rc))
     1514            {
     1515                RTMemFree(pDisk);
     1516                break;
     1517            }
     1518
    11051519            pDisk->pInterfaceError = VDInterfaceGet(pVDIfsDisk, VDINTERFACETYPE_ERROR);
    11061520            if (pDisk->pInterfaceError)
     
    11101524            if (pDisk->pInterfaceThreadSync)
    11111525                pDisk->pInterfaceThreadSyncCallbacks = VDGetInterfaceThreadSync(pDisk->pInterfaceThreadSync);
    1112 
    1113             /* Use the fallback async I/O interface if the caller doesn't provide one. */
    1114             PVDINTERFACE pVDIfAsyncIO = VDInterfaceGet(pVDIfsDisk, VDINTERFACETYPE_ASYNCIO);
    1115             if (!pVDIfAsyncIO)
     1526            pDisk->pInterfaceAsyncIO    = VDInterfaceGet(pVDIfsDisk, VDINTERFACETYPE_ASYNCIO);
     1527            if (pDisk->pInterfaceAsyncIO)
     1528                pDisk->pInterfaceAsyncIOCallbacks = VDGetInterfaceAsyncIO(pDisk->pInterfaceAsyncIO);
     1529            else
    11161530            {
     1531                /* Create fallback async I/O interface */
    11171532                pDisk->VDIAsyncIOCallbacks.cbSize        = sizeof(VDINTERFACEASYNCIO);
    11181533                pDisk->VDIAsyncIOCallbacks.enmInterface  = VDINTERFACETYPE_ASYNCIO;
     
    11271542                pDisk->VDIAsyncIOCallbacks.pfnWriteAsync = vdAsyncIOWriteAsync;
    11281543                pDisk->VDIAsyncIOCallbacks.pfnFlushAsync = vdAsyncIOFlushAsync;
    1129                 rc = VDInterfaceAdd(&pDisk->VDIAsyncIO, "VD_AsyncIO", VDINTERFACETYPE_ASYNCIO,
    1130                                     &pDisk->VDIAsyncIOCallbacks, pDisk, &pDisk->pVDIfsDisk);
    1131                 AssertRC(rc);
     1544                pDisk->pInterfaceAsyncIOCallbacks = &pDisk->VDIAsyncIOCallbacks;
     1545
     1546                pDisk->VDIAsyncIO.pszInterfaceName = "VD_AsyncIO";
     1547                pDisk->VDIAsyncIO.cbSize           = sizeof(VDINTERFACE);
     1548                pDisk->VDIAsyncIO.pNext            = NULL;
     1549                pDisk->VDIAsyncIO.enmInterface     = VDINTERFACETYPE_ASYNCIO;
     1550                pDisk->VDIAsyncIO.pvUser           = pDisk;
     1551                pDisk->VDIAsyncIO.pCallbacks       = pDisk->pInterfaceAsyncIOCallbacks;
     1552                pDisk->pInterfaceAsyncIO           = &pDisk->VDIAsyncIO;
    11321553            }
     1554
     1555            /* Create the I/O callback table. */
     1556            pDisk->VDIIOCallbacks.cbSize            = sizeof(VDINTERFACEIO);
     1557            pDisk->VDIIOCallbacks.enmInterface      = VDINTERFACETYPE_IO;
     1558            pDisk->VDIIOCallbacks.pfnOpen           = vdIOOpen;
     1559            pDisk->VDIIOCallbacks.pfnClose          = vdIOClose;
     1560            pDisk->VDIIOCallbacks.pfnGetSize        = vdIOGetSize;
     1561            pDisk->VDIIOCallbacks.pfnSetSize        = vdIOSetSize;
     1562            pDisk->VDIIOCallbacks.pfnReadSync       = vdIOReadSync;
     1563            pDisk->VDIIOCallbacks.pfnWriteSync      = vdIOWriteSync;
     1564            pDisk->VDIIOCallbacks.pfnFlushSync      = vdIOFlushSync;
     1565            pDisk->VDIIOCallbacks.pfnReadUserAsync  = vdIOReadUserAsync;
     1566            pDisk->VDIIOCallbacks.pfnWriteUserAsync = vdIOWriteUserAsync;
     1567            pDisk->VDIIOCallbacks.pfnReadMetaAsync  = vdIOReadMetaAsync;
     1568            pDisk->VDIIOCallbacks.pfnWriteMetaAsync = vdIOWriteMetaAsync;
     1569            pDisk->VDIIOCallbacks.pfnFlushAsync     = vdIOFlushAsync;
     1570            pDisk->VDIIOCallbacks.pfnIoCtxCopyFrom  = vdIOIoCtxCopyFrom;
     1571            pDisk->VDIIOCallbacks.pfnIoCtxCopyTo    = vdIOIoCtxCopyTo;
     1572            pDisk->VDIIOCallbacks.pfnIoCtxSet       = vdIOIoCtxSet;
     1573
     1574            /* Set up the I/O interface. */
     1575            rc = VDInterfaceAdd(&pDisk->VDIIO, "VD_IO", VDINTERFACETYPE_IO,
     1576                                &pDisk->VDIIOCallbacks, pDisk, &pDisk->pVDIfsDisk);
     1577            AssertRC(rc);
    11331578
    11341579            *ppDisk = pDisk;
     
    11601605        AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
    11611606        VDCloseAll(pDisk);
     1607        RTMemCacheDestroy(pDisk->hMemCacheIoCtx);
    11621608        RTMemFree(pDisk);
    11631609    } while (0);
     
    11801626{
    11811627    int rc = VERR_NOT_SUPPORTED;
    1182     PVDINTERFACE pVDIfAsyncIO;
    1183     VDINTERFACEASYNCIO VDIAsyncIOCallbacks;
    1184     VDINTERFACE        VDIAsyncIO;
     1628    VDINTERFACEIO VDIIOCallbacks;
     1629    VDINTERFACE   VDIIO;
    11851630
    11861631    LogFlowFunc(("pszFilename=\"%s\"\n", pszFilename));
     
    11961641        VDInit();
    11971642
    1198     /* Use the fallback async I/O interface if the caller doesn't provide one. */
    1199     pVDIfAsyncIO = VDInterfaceGet(pVDIfsDisk, VDINTERFACETYPE_ASYNCIO);
    1200     if (!pVDIfAsyncIO)
    1201     {
    1202         VDIAsyncIOCallbacks.cbSize        = sizeof(VDINTERFACEASYNCIO);
    1203         VDIAsyncIOCallbacks.enmInterface  = VDINTERFACETYPE_ASYNCIO;
    1204         VDIAsyncIOCallbacks.pfnOpen       = vdAsyncIOOpen;
    1205         VDIAsyncIOCallbacks.pfnClose      = vdAsyncIOClose;
    1206         VDIAsyncIOCallbacks.pfnGetSize    = vdAsyncIOGetSize;
    1207         VDIAsyncIOCallbacks.pfnSetSize    = vdAsyncIOSetSize;
    1208         VDIAsyncIOCallbacks.pfnReadSync   = vdAsyncIOReadSync;
    1209         VDIAsyncIOCallbacks.pfnWriteSync  = vdAsyncIOWriteSync;
    1210         VDIAsyncIOCallbacks.pfnFlushSync  = vdAsyncIOFlushSync;
    1211         VDIAsyncIOCallbacks.pfnReadAsync  = vdAsyncIOReadAsync;
    1212         VDIAsyncIOCallbacks.pfnWriteAsync = vdAsyncIOWriteAsync;
    1213         VDIAsyncIOCallbacks.pfnFlushAsync = vdAsyncIOFlushAsync;
    1214         rc = VDInterfaceAdd(&VDIAsyncIO, "VD_AsyncIO", VDINTERFACETYPE_ASYNCIO,
    1215                             &VDIAsyncIOCallbacks, NULL, &pVDIfsDisk);
    1216         AssertRC(rc);
    1217     }
     1643    VDIIOCallbacks.cbSize            = sizeof(VDINTERFACEIO);
     1644    VDIIOCallbacks.enmInterface      = VDINTERFACETYPE_IO;
     1645    VDIIOCallbacks.pfnOpen           = vdIOOpen;
     1646    VDIIOCallbacks.pfnClose          = vdIOClose;
     1647    VDIIOCallbacks.pfnGetSize        = vdIOGetSize;
     1648    VDIIOCallbacks.pfnSetSize        = vdIOSetSize;
     1649    VDIIOCallbacks.pfnReadSync       = vdIOReadSync;
     1650    VDIIOCallbacks.pfnWriteSync      = vdIOWriteSync;
     1651    VDIIOCallbacks.pfnFlushSync      = vdIOFlushSync;
     1652    VDIIOCallbacks.pfnReadUserAsync  = NULL;
     1653    VDIIOCallbacks.pfnWriteUserAsync = NULL;
     1654    VDIIOCallbacks.pfnReadMetaAsync  = NULL;
     1655    VDIIOCallbacks.pfnWriteMetaAsync = NULL;
     1656    VDIIOCallbacks.pfnFlushAsync     = NULL;
     1657    rc = VDInterfaceAdd(&VDIIO, "VD_IO", VDINTERFACETYPE_IO,
     1658                        &VDIIOCallbacks, NULL, &pVDIfsDisk);
     1659    AssertRC(rc);
    12181660
    12191661    /* Find the backend supporting this file format. */
     
    13161758            break;
    13171759        }
     1760
    13181761        pImage->pVDIfsImage = pVDIfsImage;
    13191762
     
    44464889}
    44474890
    4448 /**
    4449  * Start a asynchronous read request.
    4450  *
    4451  * @returns VBox status code.
    4452  * @param   pDisk           Pointer to the HDD container.
    4453  * @param   uOffset         The offset of the virtual disk to read from.
    4454  * @param   cbRead          How many bytes to read.
    4455  * @param   paSeg           Pointer to an array of segments.
    4456  * @param   cSeg            Number of segments in the array.
    4457  * @param   pvUser          User data which is passed on completion
    4458  */
     4891
    44594892VBOXDDU_DECL(int) VDAsyncRead(PVBOXHDD pDisk, uint64_t uOffset, size_t cbRead,
    44604893                              PPDMDATASEG paSeg, unsigned cSeg,
    4461                               void *pvUser)
     4894                              PFNVDASYNCTRANSFERCOMPLETE pfnComplete,
     4895                              void *pvUser1, void *pvUser2)
    44624896{
    44634897    int rc = VERR_VD_BLOCK_FREE;
    44644898    int rc2;
    4465     bool fLockWrite = false;
     4899    bool fLockRead = false;
    44664900
    44674901    LogFlowFunc(("pDisk=%#p uOffset=%llu paSeg=%p cSeg=%u cbRead=%zu\n",
     
    44844918                           rc = VERR_INVALID_PARAMETER);
    44854919
    4486         /** @todo handle this just like a write, as in the completion code in
    4487          * DrvVD.cpp there is no way to figure out if it is a read or write. */
    4488         rc2 = vdThreadStartWrite(pDisk);
    4489         AssertRC(rc2);
    4490         fLockWrite = true;
     4920        rc2 = vdThreadStartRead(pDisk);
     4921        AssertRC(rc2);
     4922        fLockRead = true;
    44914923
    44924924        AssertMsgBreakStmt(uOffset + cbRead <= pDisk->cbSize,
     
    44954927                           rc = VERR_INVALID_PARAMETER);
    44964928
     4929        PVDIOCTX pIoCtx = vdIoCtxAlloc(pDisk, VDIOCTXTXDIR_READ, uOffset,
     4930                                       cbRead, paSeg, cSeg,
     4931                                       pfnComplete, pvUser1, pvUser2);
     4932        if (!pIoCtx)
     4933        {
     4934            rc = VERR_NO_MEMORY;
     4935            break;
     4936        }
     4937
    44974938        PVDIMAGE pImage = pDisk->pLast;
    44984939        AssertPtrBreakStmt(pImage, rc = VERR_VD_NOT_OPENED);
    44994940
    4500         /* @todo: This does not work for images which do not have all meta data in memory. */
    4501         for (PVDIMAGE pCurrImage = pImage;
    4502              pCurrImage != NULL && rc == VERR_VD_BLOCK_FREE;
    4503              pCurrImage = pCurrImage->pPrev)
    4504         {
    4505             rc = pCurrImage->Backend->pfnAsyncRead(pCurrImage->pvBackendData,
    4506                                                    uOffset, cbRead, paSeg, cSeg,
    4507                                                    pvUser);
    4508         }
    4509 
    4510         /* No image in the chain contains the data for the block. */
    4511         if (rc == VERR_VD_BLOCK_FREE)
    4512         {
    4513             for (unsigned i = 0; i < cSeg && (cbRead > 0); i++)
    4514             {
    4515                 memset(paSeg[i].pvSeg, '\0', paSeg[i].cbSeg);
    4516                 cbRead -= paSeg[i].cbSeg;
    4517             }
    4518             /* Request finished without the need to enqueue a async I/O request. Tell caller. */
    4519             rc = VINF_VD_ASYNC_IO_FINISHED;
    4520 
    4521             rc2 = vdThreadFinishWrite(pDisk);
    4522             AssertRC(rc2);
    4523             fLockWrite = false;
    4524         }
    4525 
     4941        rc = vdReadHelperAsync(pDisk, pImage, NULL, pIoCtx, uOffset, cbRead);
    45264942    } while (0);
    45274943
    4528     if (RT_UNLIKELY(fLockWrite) && RT_FAILURE(rc))
    4529     {
    4530         rc2 = vdThreadFinishWrite(pDisk);
     4944    if (RT_UNLIKELY(fLockRead))
     4945    {
     4946        rc2 = vdThreadFinishRead(pDisk);
    45314947        AssertRC(rc2);
    45324948    }
     
    45404956
    45414957
    4542 /**
    4543  * Start a asynchronous write request.
    4544  *
    4545  * @returns VBox status code.
    4546  * @param   pDisk           Pointer to the HDD container.
    4547  * @param   uOffset         The offset of the virtual disk to write to.
    4548  * @param   cbWrtie         How many bytes to write.
    4549  * @param   paSeg           Pointer to an array of segments.
    4550  * @param   cSeg            Number of segments in the array.
    4551  * @param   pvUser          User data which is passed on completion.
    4552  */
    45534958VBOXDDU_DECL(int) VDAsyncWrite(PVBOXHDD pDisk, uint64_t uOffset, size_t cbWrite,
    45544959                               PPDMDATASEG paSeg, unsigned cSeg,
    4555                                void *pvUser)
     4960                               PFNVDASYNCTRANSFERCOMPLETE pfnComplete,
     4961                               void *pvUser1, void *pvUser2)
    45564962{
    45574963    int rc;
     
    45774983                           ("cSeg=%zu\n", cSeg),
    45784984                           rc = VERR_INVALID_PARAMETER);
    4579 
     4985#if 0
    45804986        rc2 = vdThreadStartWrite(pDisk);
    45814987        AssertRC(rc2);
     
    45945000                                            uOffset, cbWrite,
    45955001                                            paSeg, cSeg, pvUser);
     5002#endif
    45965003    } while (0);
    45975004
  • trunk/src/VBox/Devices/Storage/VDICore.h

    r22966 r27808  
    533533#else
    534534    /** Opaque storage handle. */
    535     void                   *pvStorage;
     535    PVDIOSTORAGE            pStorage;
    536536#endif
    537537#ifndef VBOX_VDICORE_VD
     
    591591    PVDINTERFACEERROR       pInterfaceErrorCallbacks;
    592592# ifdef VBOX_WITH_NEW_IO_CODE
    593     /** Async I/O interface. */
    594     PVDINTERFACE        pInterfaceAsyncIO;
    595     /** Async I/O interface callbacks. */
    596     PVDINTERFACEASYNCIO pInterfaceAsyncIOCallbacks;
     593    /** I/O interface. */
     594    PVDINTERFACE            pInterfaceIO;
     595    /** I/O interface callbacks. */
     596    PVDINTERFACEIO          pInterfaceIOCallbacks;
    597597# endif
    598598#endif /* VBOX_VDICORE_VD */
  • trunk/src/VBox/Devices/Storage/VDIHDDCore.cpp

    r27232 r27808  
    9999    rc = RTFileOpen(&pImage->File, pImage->pszFilename, fOpen);
    100100#else
    101 
    102101    unsigned uOpenFlags = fReadonly ? VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY : 0;
    103102
     
    105104        uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE;
    106105
    107     rc = pImage->pInterfaceAsyncIOCallbacks->pfnOpen(pImage->pInterfaceAsyncIO->pvUser,
    108                                                      pImage->pszFilename,
    109                                                      uOpenFlags,
    110                                                      NULL,
    111                                                      pImage->pVDIfsDisk,
    112                                                      &pImage->pvStorage);
     106    rc = pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser,
     107                                                pImage->pszFilename,
     108                                                uOpenFlags,
     109                                                &pImage->pStorage);
    113110#endif
    114111
     
    126123    pImage->File = NIL_RTFILE;
    127124#else
    128     if (pImage->pvStorage)
    129         rc = pImage->pInterfaceAsyncIOCallbacks->pfnClose(pImage->pInterfaceAsyncIO->pvUser,
    130                                                           pImage->pvStorage);
    131 
    132     pImage->pvStorage = NULL;
     125    rc = pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser,
     126                                                 pImage->pStorage);
     127
     128    pImage->pStorage = NULL;
    133129#endif
    134130
     
    143139    rc = RTFileFlush(pImage->File);
    144140#else
    145     if (pImage->pvStorage)
    146         rc = pImage->pInterfaceAsyncIOCallbacks->pfnFlushSync(pImage->pInterfaceAsyncIO->pvUser,
    147                                                               pImage->pvStorage);
     141    rc = pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser,
     142                                                     pImage->pStorage);
    148143#endif
    149144
     
    158153    rc = RTFileGetSize(pImage->File, pcbSize);
    159154#else
    160     if (pImage->pvStorage)
    161         rc = pImage->pInterfaceAsyncIOCallbacks->pfnGetSize(pImage->pInterfaceAsyncIO->pvUser,
    162                                                             pImage->pvStorage,
    163                                                             pcbSize);
     155    rc = pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser,
     156                                                   pImage->pStorage,
     157                                                   pcbSize);
    164158#endif
    165159
     
    174168    rc = RTFileSetSize(pImage->File, cbSize);
    175169#else
    176     if (pImage->pvStorage)
    177         rc = pImage->pInterfaceAsyncIOCallbacks->pfnSetSize(pImage->pInterfaceAsyncIO->pvUser,
    178                                                             pImage->pvStorage,
    179                                                             cbSize);
     170    rc = pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser,
     171                                                   pImage->pStorage,
     172                                                   cbSize);
    180173#endif
    181174
     
    190183    rc = RTFileWriteAt(pImage->File, off, pcvBuf, cbWrite, pcbWritten);
    191184#else
    192     if (pImage->pvStorage)
    193         rc = pImage->pInterfaceAsyncIOCallbacks->pfnWriteSync(pImage->pInterfaceAsyncIO->pvUser,
    194                                                               pImage->pvStorage,
    195                                                               off, cbWrite, pcvBuf,
    196                                                               pcbWritten);
     185    rc = pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser,
     186                                                     pImage->pStorage,
     187                                                     off, cbWrite, pcvBuf,
     188                                                     pcbWritten);
    197189#endif
    198190
     
    207199    rc = RTFileReadAt(pImage->File, off, pvBuf, cbRead, pcbRead);
    208200#else
    209     if (pImage->pvStorage)
    210         rc = pImage->pInterfaceAsyncIOCallbacks->pfnReadSync(pImage->pInterfaceAsyncIO->pvUser,
    211                                                              pImage->pvStorage,
    212                                                              off, cbRead, pvBuf,
    213                                                              pcbRead);
     201    rc = pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser,
     202                                                    pImage->pStorage,
     203                                                    off, cbRead, pvBuf,
     204                                                    pcbRead);
    214205#endif
    215206
     
    222213    return pImage->File != NIL_RTFILE;
    223214#else
    224     return pImage->pvStorage != NULL;
     215    return pImage->pStorage != NULL;
    225216#endif
    226217}
     
    524515
    525516#ifdef VBOX_WITH_NEW_IO_CODE
    526     /* Try to get async I/O interface. */
    527     pImage->pInterfaceAsyncIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ASYNCIO);
    528     AssertPtr(pImage->pInterfaceAsyncIO);
    529     pImage->pInterfaceAsyncIOCallbacks = VDGetInterfaceAsyncIO(pImage->pInterfaceAsyncIO);
    530     AssertPtr(pImage->pInterfaceAsyncIOCallbacks);
     517    /* Try to get I/O interface. */
     518    pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_IO);
     519    AssertPtr(pImage->pInterfaceIO);
     520    pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO);
     521    AssertPtr(pImage->pInterfaceIOCallbacks);
    531522#endif
    532523
     
    713704
    714705#ifdef VBOX_WITH_NEW_IO_CODE
    715     /* Try to get async I/O interface. */
    716     pImage->pInterfaceAsyncIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ASYNCIO);
    717     AssertPtr(pImage->pInterfaceAsyncIO);
    718     pImage->pInterfaceAsyncIOCallbacks = VDGetInterfaceAsyncIO(pImage->pInterfaceAsyncIO);
    719     AssertPtr(pImage->pInterfaceAsyncIOCallbacks);
     706    /* Try to get I/O interface. */
     707    pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_IO);
     708    AssertPtr(pImage->pInterfaceIO);
     709    pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO);
     710    AssertPtr(pImage->pInterfaceIOCallbacks);
    720711#endif
    721712
     
    936927    pImage->File = NIL_RTFILE;
    937928#else
    938     pImage->pvStorage = NULL;
     929    pImage->pStorage = NULL;
    939930#endif
    940931    pImage->paBlocks = NULL;
     
    984975    pImage->File = NIL_RTFILE;
    985976#else
    986     pImage->pvStorage = NULL;
     977    pImage->pStorage = NULL;
    987978#endif
    988979    pImage->paBlocks = NULL;
     
    10621053    pImage->File = NIL_RTFILE;
    10631054#else
    1064     pImage->pvStorage = NULL;
     1055    pImage->pStorage = NULL;
    10651056#endif
    10661057    pImage->paBlocks = NULL;
     
    18941885                (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) ? "r/o" : "r/w",
    18951886                pImage->uOpenFlags,
    1896                 pImage->pvStorage);
     1887                pImage->pStorage);
    18971888#endif
    18981889    pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: Version=%08X Type=%X Flags=%X Size=%llu\n",
     
    19881979}
    19891980
    1990 static int vdiAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbRead,
    1991                         PPDMDATASEG paSeg, unsigned cSeg, void *pvUser)
     1981static int vdiAsyncRead(void *pvBackendData, uint64_t uOffset, size_t cbRead,
     1982                        PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
    19921983{
    19931984    int rc = VERR_NOT_IMPLEMENTED;
     
    19961987}
    19971988
    1998 static int vdiAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbWrite,
    1999                          PPDMDATASEG paSeg, unsigned cSeg, void *pvUser)
     1989static int vdiAsyncWrite(void *pvBackendData, uint64_t uOffset, size_t cbWrite,
     1990                         PVDIOCTX pIoCtx,
     1991                         size_t *pcbWriteProcess, size_t *pcbPreRead,
     1992                         size_t *pcbPostRead, unsigned fWrite)
     1993{
     1994    int rc = VERR_NOT_IMPLEMENTED;
     1995    LogFlowFunc(("returns %Rrc\n", rc));
     1996    return rc;
     1997}
     1998
     1999static int vdiAsyncFlush(void *pvBackendData, PVDIOCTX pIoCtx)
    20002000{
    20012001    int rc = VERR_NOT_IMPLEMENTED;
     
    23282328    /* pfnAsyncWrite */
    23292329    vdiAsyncWrite,
     2330    /* pfnAsyncFlush */
     2331    vdiAsyncFlush,
    23302332    /* pfnComposeLocation */
    23312333    genericFileComposeLocation,
  • trunk/src/VBox/Devices/Storage/VHDHDDCore.cpp

    r27358 r27808  
    134134    RTFILE          File;
    135135#else
    136     /** Opaque storage handle. */
    137     void           *pvStorage;
     136    /** storage handle. */
     137    PVDIOSTORAGE    pStorage;
     138    /** I/O interface. */
     139    PVDINTERFACE    pInterfaceIO;
     140    /** I/O interface callbacks. */
     141    PVDINTERFACEIO  pInterfaceIOCallbacks;
    138142#endif
    139143
     
    144148    /** Error interface callback table. */
    145149    PVDINTERFACEERROR pInterfaceErrorCallbacks;
    146 #ifdef VBOX_WITH_NEW_IO_CODE
    147     /** Async I/O interface. */
    148     PVDINTERFACE        pInterfaceAsyncIO;
    149     /** Async I/O interface callbacks. */
    150     PVDINTERFACEASYNCIO pInterfaceAsyncIOCallbacks;
    151 #endif
    152150
    153151    /** Open flags passed by VBoxHD layer. */
     
    236234    rc = RTFileOpen(&pImage->File, pImage->pszFilename, fOpen);
    237235#else
    238 
    239236    unsigned uOpenFlags = fReadonly ? VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY : 0;
    240237
     
    242239        uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE;
    243240
    244     rc = pImage->pInterfaceAsyncIOCallbacks->pfnOpen(pImage->pInterfaceAsyncIO->pvUser,
    245                                                      pImage->pszFilename,
    246                                                      uOpenFlags,
    247                                                      NULL,
    248                                                      pImage->pVDIfsDisk,
    249                                                      &pImage->pvStorage);
     241    rc = pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser,
     242                                                pImage->pszFilename,
     243                                                uOpenFlags,
     244                                                &pImage->pStorage);
    250245#endif
    251246
     
    263258    pImage->File = NIL_RTFILE;
    264259#else
    265     if (pImage->pvStorage)
    266         rc = pImage->pInterfaceAsyncIOCallbacks->pfnClose(pImage->pInterfaceAsyncIO->pvUser,
    267                                                           pImage->pvStorage);
    268 
    269     pImage->pvStorage = NULL;
     260    rc = pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser,
     261                                                 pImage->pStorage);
     262    pImage->pStorage = NULL;
    270263#endif
    271264
     
    280273    rc = RTFileFlush(pImage->File);
    281274#else
    282     if (pImage->pvStorage)
    283         rc = pImage->pInterfaceAsyncIOCallbacks->pfnFlushSync(pImage->pInterfaceAsyncIO->pvUser,
    284                                                               pImage->pvStorage);
     275    rc = pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser,
     276                                                     pImage->pStorage);
    285277#endif
    286278
     
    295287    rc = RTFileGetSize(pImage->File, pcbSize);
    296288#else
    297     if (pImage->pvStorage)
    298         rc = pImage->pInterfaceAsyncIOCallbacks->pfnGetSize(pImage->pInterfaceAsyncIO->pvUser,
    299                                                             pImage->pvStorage,
    300                                                             pcbSize);
     289    rc = pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser,
     290                                                   pImage->pStorage,
     291                                                   pcbSize);
    301292#endif
    302293
     
    312303    rc = RTFileSetSize(pImage->File, cbSize);
    313304#else
    314     if (pImage->pvStorage)
    315         rc = pImage->pInterfaceAsyncIOCallbacks->pfnSetSize(pImage->pInterfaceAsyncIO->pvUser,
    316                                                             pImage->pvStorage,
    317                                                             cbSize);
     305    rc = pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser,
     306                                                   pImage->pStorage,
     307                                                   cbSize);
    318308#endif
    319309
     
    329319    rc = RTFileWriteAt(pImage->File, off, pcvBuf, cbWrite, pcbWritten);
    330320#else
    331     if (pImage->pvStorage)
    332         rc = pImage->pInterfaceAsyncIOCallbacks->pfnWriteSync(pImage->pInterfaceAsyncIO->pvUser,
    333                                                               pImage->pvStorage,
    334                                                               off, cbWrite, pcvBuf,
    335                                                               pcbWritten);
     321    rc = pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser,
     322                                                     pImage->pStorage,
     323                                                     off, cbWrite, pcvBuf,
     324                                                     pcbWritten);
    336325#endif
    337326
     
    346335    rc = RTFileReadAt(pImage->File, off, pvBuf, cbRead, pcbRead);
    347336#else
    348     if (pImage->pvStorage)
    349         rc = pImage->pInterfaceAsyncIOCallbacks->pfnReadSync(pImage->pInterfaceAsyncIO->pvUser,
    350                                                              pImage->pvStorage,
    351                                                              off, cbRead, pvBuf,
    352                                                              pcbRead);
     337    rc = pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser,
     338                                                    pImage->pStorage,
     339                                                    off, cbRead, pvBuf,
     340                                                    pcbRead);
    353341#endif
    354342
     
    361349    return pImage->File != NIL_RTFILE;
    362350#else
    363     return pImage->pvStorage != NULL;
     351    return pImage->pStorage != NULL;
    364352#endif
    365353}
     
    593581#ifdef VBOX_WITH_NEW_IO_CODE
    594582    /* Try to get async I/O interface. */
    595     pImage->pInterfaceAsyncIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ASYNCIO);
    596     AssertPtr(pImage->pInterfaceAsyncIO);
    597     pImage->pInterfaceAsyncIOCallbacks = VDGetInterfaceAsyncIO(pImage->pInterfaceAsyncIO);
    598     AssertPtr(pImage->pInterfaceAsyncIOCallbacks);
     583    pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_IO);
     584    AssertPtr(pImage->pInterfaceIO);
     585    pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO);
     586    AssertPtr(pImage->pInterfaceIOCallbacks);
    599587#endif
    600588
     
    693681    pImage->File = NIL_RTFILE;
    694682#else
    695     pImage->pvStorage = NULL;
     683    pImage->pStorage = NULL;
    696684#endif
    697685    pImage->pVDIfsDisk = pVDIfsDisk;
     
    19811969    pImage->File = NIL_RTFILE;
    19821970#else
    1983     pImage->pvStorage = NULL;
     1971    pImage->pStorage = NULL;
    19841972#endif
    19851973    pImage->pVDIfsDisk = pVDIfsDisk;
    19861974
    19871975#ifdef VBOX_WITH_NEW_IO_CODE
    1988     /* Try to get async I/O interface. */
    1989     pImage->pInterfaceAsyncIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ASYNCIO);
    1990     AssertPtr(pImage->pInterfaceAsyncIO);
    1991     pImage->pInterfaceAsyncIOCallbacks = VDGetInterfaceAsyncIO(pImage->pInterfaceAsyncIO);
    1992     AssertPtr(pImage->pInterfaceAsyncIOCallbacks);
     1976    /* Try to get I/O interface. */
     1977    pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_IO);
     1978    AssertPtr(pImage->pInterfaceIO);
     1979    pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO);
     1980    AssertPtr(pImage->pInterfaceIOCallbacks);
    19931981#endif
    19941982
     
    21462134
    21472135static int vhdAsyncRead(void *pvBackendData, uint64_t uOffset, size_t cbRead,
    2148                         PPDMDATASEG paSeg, unsigned cSeg, void *pvUser)
     2136                        PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
    21492137{
    21502138    int rc = VERR_NOT_IMPLEMENTED;
     
    21532141}
    21542142
    2155 static int vhdAsyncWrite(void *pvBackendData, uint64_t uOffset, size_t cbToWrite,
    2156                          PPDMDATASEG paSeg, unsigned cSeg, void *pvUser)
     2143static int vhdAsyncWrite(void *pvBackendData, uint64_t uOffset, size_t cbWrite,
     2144                         PVDIOCTX pIoCtx,
     2145                         size_t *pcbWriteProcess, size_t *pcbPreRead,
     2146                         size_t *pcbPostRead, unsigned fWrite)
    21572147{
    21582148    int rc = VERR_NOT_IMPLEMENTED;
     
    21612151}
    21622152
     2153static int vhdAsyncFlush(void *pvBackendData, PVDIOCTX pIoCtx)
     2154{
     2155    int rc = VERR_NOT_IMPLEMENTED;
     2156    LogFlowFunc(("returns %Rrc\n", rc));
     2157    return rc;
     2158}
    21632159
    21642160VBOXHDDBACKEND g_VhdBackend =
     
    22512247    /* pfnAsyncWrite */
    22522248    vhdAsyncWrite,
     2249    /* pfnAsyncFlush */
     2250    vhdAsyncFlush,
    22532251    /* pfnComposeLocation */
    22542252    genericFileComposeLocation,
  • trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp

    r27735 r27808  
    230230{
    231231    /** Pointer to filename. Local copy. */
    232     const char *pszFilename;
     232    const char      *pszFilename;
    233233    /** File open flags for consistency checking. */
    234     unsigned    fOpen;
     234    unsigned         fOpen;
    235235    /** File handle. */
    236     RTFILE      File;
     236    RTFILE           File;
    237237    /** Handle for asnychronous access if requested.*/
    238     void       *pStorage;
     238    PVDIOSTORAGE     pStorage;
    239239    /** Flag whether to use File or pStorage. */
    240     bool        fAsyncIO;
     240    bool             fAsyncIO;
    241241    /** Reference counter. */
    242     unsigned    uReferences;
     242    unsigned         uReferences;
    243243    /** Flag whether the file should be deleted on last close. */
    244     bool        fDelete;
     244    bool             fDelete;
    245245    /** Pointer to the image we belong to. */
    246     PVMDKIMAGE  pImage;
     246    PVMDKIMAGE       pImage;
    247247    /** Pointer to next file descriptor. */
    248248    struct VMDKFILE *pNext;
     
    429429    PVDINTERFACEERROR pInterfaceErrorCallbacks;
    430430
    431     /** Async I/O interface. */
    432     PVDINTERFACE    pInterfaceAsyncIO;
    433     /** Async I/O interface callbacks. */
    434     PVDINTERFACEASYNCIO pInterfaceAsyncIOCallbacks;
     431    /** I/O interface. */
     432    PVDINTERFACE    pInterfaceIO;
     433    /** I/O interface callbacks. */
     434    PVDINTERFACEIO  pInterfaceIOCallbacks;
    435435    /**
    436436     * Pointer to an array of segment entries for async I/O.
     
    583583    if ((pImage->uOpenFlags & VD_OPEN_FLAGS_ASYNC_IO) && (fAsyncIO))
    584584    {
    585         rc = pImage->pInterfaceAsyncIOCallbacks->pfnOpen(pImage->pInterfaceAsyncIO->pvUser,
     585        rc = pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser,
    586586                                                         pszFilename,
    587587                                                         pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY
     
    606606        uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE;
    607607
    608     rc = pImage->pInterfaceAsyncIOCallbacks->pfnOpen(pImage->pInterfaceAsyncIO->pvUser,
    609                                                         pszFilename,
    610                                                         uOpenFlags,
    611                                                         NULL,
    612                                                         pImage->pVDIfsDisk,
    613                                                         &pVmdkFile->pStorage);
     608    rc = pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser,
     609                                                pszFilename,
     610                                                uOpenFlags,
     611                                                &pVmdkFile->pStorage);
    614612#endif
    615613    if (RT_SUCCESS(rc))
     
    665663        if (pVmdkFile->fAsyncIO)
    666664        {
    667             rc = pImage->pInterfaceAsyncIOCallbacks->pfnClose(pImage->pInterfaceAsyncIO->pvUser,
     665            rc = pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser,
    668666                                                              pVmdkFile->pStorage);
    669667        }
     
    673671        }
    674672#else
    675         rc = pImage->pInterfaceAsyncIOCallbacks->pfnClose(pImage->pInterfaceAsyncIO->pvUser,
    676                                                           pVmdkFile->pStorage);
     673        rc = pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser,
     674                                                     pVmdkFile->pStorage);
    677675#endif
    678676        if (RT_SUCCESS(rc) && pVmdkFile->fDelete)
     
    697695#ifndef VBOX_WITH_NEW_IO_CODE
    698696    if (pVmdkFile->fAsyncIO)
    699         return pImage->pInterfaceAsyncIOCallbacks->pfnReadSync(pImage->pInterfaceAsyncIO->pvUser,
    700                                                                pVmdkFile->pStorage, uOffset,
    701                                                                cbToRead, pvBuf, pcbRead);
     697        return pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser,
     698                                                          pVmdkFile->pStorage, uOffset,
     699                                                          cbToRead, pvBuf, pcbRead);
    702700    else
    703701        return RTFileReadAt(pVmdkFile->File, uOffset, pvBuf, cbToRead, pcbRead);
    704702#else
    705     return pImage->pInterfaceAsyncIOCallbacks->pfnReadSync(pImage->pInterfaceAsyncIO->pvUser,
    706                                                                pVmdkFile->pStorage, uOffset,
    707                                                                cbToRead, pvBuf, pcbRead);
     703    return pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser,
     704                                                      pVmdkFile->pStorage, uOffset,
     705                                                      cbToRead, pvBuf, pcbRead);
    708706#endif
    709707}
     
    720718#ifndef VBOX_WITH_NEW_IO_CODE
    721719    if (pVmdkFile->fAsyncIO)
    722         return pImage->pInterfaceAsyncIOCallbacks->pfnWriteSync(pImage->pInterfaceAsyncIO->pvUser,
     720        return pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser,
    723721                                                                pVmdkFile->pStorage, uOffset,
    724722                                                                cbToWrite, pvBuf, pcbWritten);
     
    726724        return RTFileWriteAt(pVmdkFile->File, uOffset, pvBuf, cbToWrite, pcbWritten);
    727725#else
    728         return pImage->pInterfaceAsyncIOCallbacks->pfnWriteSync(pImage->pInterfaceAsyncIO->pvUser,
     726        return pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser,
    729727                                                                pVmdkFile->pStorage, uOffset,
    730728                                                                cbToWrite, pvBuf, pcbWritten);
     
    742740    if (pVmdkFile->fAsyncIO)
    743741    {
    744         return pImage->pInterfaceAsyncIOCallbacks->pfnGetSize(pImage->pInterfaceAsyncIO->pvUser,
     742        return pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser,
    745743                                                              pVmdkFile->pStorage,
    746744                                                              pcbSize);
     
    749747        return RTFileGetSize(pVmdkFile->File, pcbSize);
    750748#else
    751     return pImage->pInterfaceAsyncIOCallbacks->pfnGetSize(pImage->pInterfaceAsyncIO->pvUser,
     749    return pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser,
    752750                                                            pVmdkFile->pStorage,
    753751                                                            pcbSize);
     
    765763    if (pVmdkFile->fAsyncIO)
    766764    {
    767         return pImage->pInterfaceAsyncIOCallbacks->pfnSetSize(pImage->pInterfaceAsyncIO->pvUser,
     765        return pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser,
    768766                                                              pVmdkFile->pStorage,
    769767                                                              cbSize);
     
    772770        return RTFileSetSize(pVmdkFile->File, cbSize);
    773771#else
    774     return pImage->pInterfaceAsyncIOCallbacks->pfnSetSize(pImage->pInterfaceAsyncIO->pvUser,
     772    return pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser,
    775773                                                          pVmdkFile->pStorage,
    776774                                                          cbSize);
     
    787785#ifndef VBOX_WITH_NEW_IO_CODE
    788786    if (pVmdkFile->fAsyncIO)
    789         return pImage->pInterfaceAsyncIOCallbacks->pfnFlushSync(pImage->pInterfaceAsyncIO->pvUser,
     787        return pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser,
    790788                                                                pVmdkFile->pStorage);
    791789    else
    792790        return RTFileFlush(pVmdkFile->File);
    793791#else
    794     return pImage->pInterfaceAsyncIOCallbacks->pfnFlushSync(pImage->pInterfaceAsyncIO->pvUser,
     792    return pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser,
    795793                                                            pVmdkFile->pStorage);
    796794#endif
     
    10261024
    10271025        if (pImage->uOpenFlags & VD_OPEN_FLAGS_ASYNC_IO)
    1028             rc2 = pImage->pInterfaceAsyncIOCallbacks->pfnClose(pImage->pInterfaceAsyncIO->pvUser,
     1026            rc2 = pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser,
    10291027                                                               pVmdkFile->pStorage);
    10301028        else
     
    29762974
    29772975    /* Try to get async I/O interface. */
    2978     pImage->pInterfaceAsyncIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ASYNCIO);
    2979     if (pImage->pInterfaceAsyncIO)
    2980         pImage->pInterfaceAsyncIOCallbacks = VDGetInterfaceAsyncIO(pImage->pInterfaceAsyncIO);
     2976    pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_IO);
     2977    if (pImage->pInterfaceIO)
     2978        pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO);
    29812979
    29822980    /*
     
    38453843
    38463844    /* Try to get async I/O interface. */
    3847     pImage->pInterfaceAsyncIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ASYNCIO);
    3848     if (pImage->pInterfaceAsyncIO)
    3849         pImage->pInterfaceAsyncIOCallbacks = VDGetInterfaceAsyncIO(pImage->pInterfaceAsyncIO);
     3845    pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_IO);
     3846    if (pImage->pInterfaceIO)
     3847        pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO);
    38503848
    38513849    rc = vmdkCreateDescriptor(pImage, pImage->pDescData, pImage->cbDescAlloc,
     
    58585856static bool vmdkIsAsyncIOSupported(void *pvBackendData)
    58595857{
    5860     PVMDKIMAGE pImage = (PVMDKIMAGE)pvBackendData;
    5861     bool fAsyncIOSupported = false;
    5862 
    5863     if (pImage)
    5864     {
    5865         unsigned cFlatExtents = 0;
    5866 
    5867         /* We only support async I/O support if the image only consists of FLAT or ZERO extents.
    5868          *
    5869          * @todo: At the moment we only support async I/O if there is at most one FLAT extent
    5870          *        More than one doesn't work yet with the async I/O interface.
    5871          */
    5872         fAsyncIOSupported = true;
    5873         for (unsigned i = 0; i < pImage->cExtents; i++)
    5874         {
    5875             if ((    pImage->pExtents[i].enmType != VMDKETYPE_FLAT
    5876                  &&  pImage->pExtents[i].enmType != VMDKETYPE_ZERO
    5877                  &&  pImage->pExtents[i].enmType != VMDKETYPE_VMFS)
    5878                 || ((pImage->pExtents[i].enmType == VMDKETYPE_FLAT) && (cFlatExtents > 0)))
    5879             {
    5880                 fAsyncIOSupported = false;
    5881                 break; /* Stop search */
    5882             }
    5883             if (pImage->pExtents[i].enmType == VMDKETYPE_FLAT)
    5884                 cFlatExtents++;
    5885         }
    5886     }
    5887 
    5888     return fAsyncIOSupported;
     5858    return false;
    58895859}
    58905860
    58915861static int vmdkAsyncRead(void *pvBackendData, uint64_t uOffset, size_t cbRead,
    5892                          PPDMDATASEG paSeg, unsigned cSeg, void *pvUser)
    5893 {
    5894     PVMDKIMAGE pImage = (PVMDKIMAGE)pvBackendData;
    5895     PVMDKEXTENT pExtent = NULL;
    5896     int rc = VINF_SUCCESS;
    5897     unsigned cSegments = 0;
    5898     PPDMDATASEG paSegCurrent = paSeg;
    5899     size_t cbLeftInCurrentSegment = paSegCurrent->cbSeg;
    5900     size_t uOffsetInCurrentSegment = 0;
    5901     size_t cbReadLeft = cbRead;
    5902     uint64_t uOffCurr = uOffset;
    5903 
    5904     AssertPtr(pImage);
    5905     Assert(uOffset % 512 == 0);
    5906     Assert(cbRead % 512 == 0);
    5907 
    5908     if (   uOffset + cbRead > pImage->cbSize
    5909         || cbRead == 0)
    5910     {
    5911         rc = VERR_INVALID_PARAMETER;
    5912         goto out;
    5913     }
    5914 
    5915     while (cbReadLeft && cSeg)
    5916     {
    5917         size_t cbToRead;
    5918         uint64_t uSectorExtentRel;
    5919 
    5920         rc = vmdkFindExtent(pImage, VMDK_BYTE2SECTOR(uOffCurr),
    5921                             &pExtent, &uSectorExtentRel);
    5922         if (RT_FAILURE(rc))
    5923             goto out;
    5924 
    5925         /* Check access permissions as defined in the extent descriptor. */
    5926         if (pExtent->enmAccess == VMDKACCESS_NOACCESS)
    5927         {
    5928             rc = VERR_VD_VMDK_INVALID_STATE;
    5929             goto out;
    5930         }
    5931 
    5932         /* Clip read range to remain in this extent. */
    5933         cbToRead = RT_MIN(cbRead, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel));
    5934         /* Clip read range to remain into current data segment. */
    5935         cbToRead = RT_MIN(cbToRead, cbLeftInCurrentSegment);
    5936 
    5937         switch (pExtent->enmType)
    5938         {
    5939             case VMDKETYPE_VMFS:
    5940             case VMDKETYPE_FLAT:
    5941             {
    5942                 /* Check for enough room first. */
    5943                 if (RT_UNLIKELY(cSegments >= pImage->cSegments))
    5944                 {
    5945                     /* We reached maximum, resize array. Try to realloc memory first. */
    5946                     PPDMDATASEG paSegmentsNew = (PPDMDATASEG)RTMemRealloc(pImage->paSegments, (cSegments + 10)*sizeof(PDMDATASEG));
    5947 
    5948                     if (!paSegmentsNew)
    5949                     {
    5950                         /* We failed. Allocate completely new. */
    5951                         paSegmentsNew = (PPDMDATASEG)RTMemAllocZ((cSegments + 10)* sizeof(PDMDATASEG));
    5952                         if (!paSegmentsNew)
    5953                         {
    5954                             /* Damn, we are out of memory. */
    5955                             rc = VERR_NO_MEMORY;
    5956                             goto out;
    5957                         }
    5958 
    5959                         /* Copy task handles over. */
    5960                         for (unsigned i = 0; i < cSegments; i++)
    5961                             paSegmentsNew[i] = pImage->paSegments[i];
    5962 
    5963                         /* Free old memory. */
    5964                         RTMemFree(pImage->paSegments);
    5965                     }
    5966 
    5967                     pImage->cSegments = cSegments + 10;
    5968                     pImage->paSegments = paSegmentsNew;
    5969                 }
    5970 
    5971                 pImage->paSegments[cSegments].cbSeg = cbToRead;
    5972                 pImage->paSegments[cSegments].pvSeg = (uint8_t *)paSegCurrent->pvSeg + uOffsetInCurrentSegment;
    5973                 cSegments++;
    5974                 break;
    5975             }
    5976             case VMDKETYPE_ZERO:
    5977                 /* Nothing left to do. */
    5978                 break;
    5979             default:
    5980                 AssertMsgFailed(("Unsupported extent type %u\n", pExtent->enmType));
    5981         }
    5982 
    5983         cbReadLeft -= cbToRead;
    5984         uOffCurr   += cbToRead;
    5985         cbLeftInCurrentSegment -= cbToRead;
    5986         uOffsetInCurrentSegment += cbToRead;
    5987         /* Go to next extent if there is no space left in current one. */
    5988         if (!cbLeftInCurrentSegment)
    5989         {
    5990             uOffsetInCurrentSegment = 0;
    5991             paSegCurrent++;
    5992             cSeg--;
    5993             cbLeftInCurrentSegment = paSegCurrent->cbSeg;
    5994         }
    5995     }
    5996 
    5997     AssertMsg(cbReadLeft == 0, ("No segment left but there is still data to write\n"));
    5998 
    5999     if (cSegments == 0)
    6000     {
    6001         /* The request was completely in a ZERO extent nothing to do. */
    6002         rc = VINF_VD_ASYNC_IO_FINISHED;
    6003     }
    6004     else
    6005     {
    6006         /* Start the write */
    6007         void *pTask;
    6008         rc = pImage->pInterfaceAsyncIOCallbacks->pfnReadAsync(pImage->pInterfaceAsyncIO->pvUser,
    6009                                                                pExtent->pFile->pStorage, uOffset,
    6010                                                                pImage->paSegments, cSegments, cbRead,
    6011                                                                pvUser, &pTask);
    6012     }
    6013 
    6014 out:
     5862                         PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
     5863{
     5864    int rc = VERR_NOT_IMPLEMENTED;
    60155865    LogFlowFunc(("returns %Rrc\n", rc));
    60165866    return rc;
     
    60185868
    60195869static int vmdkAsyncWrite(void *pvBackendData, uint64_t uOffset, size_t cbWrite,
    6020                           PPDMDATASEG paSeg, unsigned cSeg, void *pvUser)
    6021 {
    6022     PVMDKIMAGE pImage = (PVMDKIMAGE)pvBackendData;
    6023     PVMDKEXTENT pExtent = NULL;
    6024     int rc = VINF_SUCCESS;
    6025     unsigned cSegments = 0;
    6026     PPDMDATASEG paSegCurrent = paSeg;
    6027     size_t cbLeftInCurrentSegment = paSegCurrent->cbSeg;
    6028     size_t uOffsetInCurrentSegment = 0;
    6029     size_t cbWriteLeft = cbWrite;
    6030     uint64_t uOffCurr = uOffset;
    6031 
    6032     AssertPtr(pImage);
    6033     Assert(uOffset % 512 == 0);
    6034     Assert(cbWrite % 512 == 0);
    6035 
    6036     if (   uOffset + cbWrite > pImage->cbSize
    6037         || cbWrite == 0)
    6038     {
    6039         rc = VERR_INVALID_PARAMETER;
    6040         goto out;
    6041     }
    6042 
    6043     while (cbWriteLeft && cSeg)
    6044     {
    6045         size_t cbToWrite;
    6046         uint64_t uSectorExtentRel;
    6047 
    6048         rc = vmdkFindExtent(pImage, VMDK_BYTE2SECTOR(uOffCurr),
    6049                             &pExtent, &uSectorExtentRel);
    6050         if (RT_FAILURE(rc))
    6051             goto out;
    6052 
    6053         /* Check access permissions as defined in the extent descriptor. */
    6054         if (pExtent->enmAccess == VMDKACCESS_NOACCESS)
    6055         {
    6056             rc = VERR_VD_VMDK_INVALID_STATE;
    6057             goto out;
    6058         }
    6059 
    6060         /* Clip write range to remain in this extent. */
    6061         cbToWrite = RT_MIN(cbWrite, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel));
    6062         /* Clip write range to remain into current data segment. */
    6063         cbToWrite = RT_MIN(cbToWrite, cbLeftInCurrentSegment);
    6064 
    6065         switch (pExtent->enmType)
    6066         {
    6067             case VMDKETYPE_VMFS:
    6068             case VMDKETYPE_FLAT:
    6069             {
    6070                 /* Check for enough room first. */
    6071                 if (RT_UNLIKELY(cSegments >= pImage->cSegments))
    6072                 {
    6073                     /* We reached maximum, resize array. Try to realloc memory first. */
    6074                     PPDMDATASEG paSegmentsNew = (PPDMDATASEG)RTMemRealloc(pImage->paSegments, (cSegments + 10)*sizeof(PDMDATASEG));
    6075 
    6076                     if (!paSegmentsNew)
    6077                     {
    6078                         /* We failed. Allocate completely new. */
    6079                         paSegmentsNew = (PPDMDATASEG)RTMemAllocZ((cSegments + 10)* sizeof(PDMDATASEG));
    6080                         if (!paSegmentsNew)
    6081                         {
    6082                             /* Damn, we are out of memory. */
    6083                             rc = VERR_NO_MEMORY;
    6084                             goto out;
    6085                         }
    6086 
    6087                         /* Copy task handles over. */
    6088                         for (unsigned i = 0; i < cSegments; i++)
    6089                             paSegmentsNew[i] = pImage->paSegments[i];
    6090 
    6091                         /* Free old memory. */
    6092                         RTMemFree(pImage->paSegments);
    6093                     }
    6094 
    6095                     pImage->cSegments = cSegments + 10;
    6096                     pImage->paSegments = paSegmentsNew;
    6097                 }
    6098 
    6099                 pImage->paSegments[cSegments].cbSeg = cbToWrite;
    6100                 pImage->paSegments[cSegments].pvSeg = (uint8_t *)paSegCurrent->pvSeg + uOffsetInCurrentSegment;
    6101                 cSegments++;
    6102                 break;
    6103             }
    6104             case VMDKETYPE_ZERO:
    6105                 /* Nothing left to do. */
    6106                 break;
    6107             default:
    6108                 AssertMsgFailed(("Unsupported extent type %u\n", pExtent->enmType));
    6109         }
    6110 
    6111         cbWriteLeft -= cbToWrite;
    6112         uOffCurr    += cbToWrite;
    6113         cbLeftInCurrentSegment -= cbToWrite;
    6114         uOffsetInCurrentSegment += cbToWrite;
    6115         /* Go to next extent if there is no space left in current one. */
    6116         if (!cbLeftInCurrentSegment)
    6117         {
    6118             uOffsetInCurrentSegment = 0;
    6119             paSegCurrent++;
    6120             cSeg--;
    6121             cbLeftInCurrentSegment = paSegCurrent->cbSeg;
    6122         }
    6123     }
    6124 
    6125     AssertMsg(cbWriteLeft == 0, ("No segment left but there is still data to write\n"));
    6126 
    6127     if (cSegments == 0)
    6128     {
    6129         /* The request was completely in a ZERO extent nothing to do. */
    6130         rc = VINF_VD_ASYNC_IO_FINISHED;
    6131     }
    6132     else
    6133     {
    6134         /* Start the write */
    6135         void *pTask;
    6136         rc = pImage->pInterfaceAsyncIOCallbacks->pfnWriteAsync(pImage->pInterfaceAsyncIO->pvUser,
    6137                                                                pExtent->pFile->pStorage, uOffset,
    6138                                                                pImage->paSegments, cSegments, cbWrite,
    6139                                                                pvUser, &pTask);
    6140     }
    6141 
    6142 out:
     5870                          PVDIOCTX pIoCtx,
     5871                          size_t *pcbWriteProcess, size_t *pcbPreRead,
     5872                          size_t *pcbPostRead, unsigned fWrite)
     5873{
     5874    int rc = VERR_NOT_IMPLEMENTED;
     5875    LogFlowFunc(("returns %Rrc\n", rc));
     5876    return rc;
     5877}
     5878
     5879static int vmdkAsyncFlush(void *pvBackendData, PVDIOCTX pIoCtx)
     5880{
     5881    int rc = VERR_NOT_IMPLEMENTED;
    61435882    LogFlowFunc(("returns %Rrc\n", rc));
    61445883    return rc;
     
    62355974    /* pfnAsyncWrite */
    62365975    vmdkAsyncWrite,
     5976    /* pfnAsyncFlush */
     5977    vmdkAsyncFlush,
    62375978    /* pfnComposeLocation */
    62385979    genericFileComposeLocation,
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