Changeset 27808 in vbox
- Timestamp:
- Mar 29, 2010 8:52:56 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/VBoxHDD-Plugin.h
r27232 r27808 471 471 * @param uOffset The offset of the virtual disk to read from. 472 472 * @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. 476 475 */ 477 476 DECLR3CALLBACKMEMBER(int, pfnAsyncRead, (void *pvBackendData, uint64_t uOffset, size_t cbRead, 478 P PDMDATASEG paSeg, unsigned cSeg, void *pvUser));477 PVDIOCTX pIoCtx, size_t *pcbActuallyRead)); 479 478 480 479 /** … … 485 484 * @param uOffset The offset of the virtual disk to write to. 486 485 * @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. 490 499 */ 491 500 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)); 493 513 494 514 /** Returns a human readable hard disk location string given a -
trunk/include/VBox/VBoxHDD.h
r27232 r27808 226 226 /** Interface for synchronizing accesses from several threads. Per-disk. */ 227 227 VDINTERFACETYPE_THREADSYNC, 228 /** Interface for I/O between the generic VBoxHDD code and the backend. Per-image. */ 229 VDINTERFACETYPE_IO, 228 230 /** invalid interface. */ 229 231 VDINTERFACETYPE_INVALID … … 334 336 335 337 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 */ 347 DECLINLINE(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; 336 386 } 337 387 … … 1289 1339 } VDBACKENDINFO, *PVDBACKENDINFO; 1290 1340 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 */ 1348 typedef DECLCALLBACK(void) FNVDMETACOMPLETED(void *pvBackendData, void *pvMetaUser); 1349 /** Pointer to FNVDCOMPLETED() */ 1350 typedef FNVDMETACOMPLETED *PFNVDMETACOMPLETED; 1351 1352 /** Forward declaration. Only visible in the VBoxHDD module. */ 1353 /** I/O context */ 1354 typedef struct VDIOCTX *PVDIOCTX; 1355 /** Storage backend handle. */ 1356 typedef struct VDIOSTORAGE *PVDIOSTORAGE; 1357 /** Pointer to a storage backend handle. */ 1358 typedef PVDIOSTORAGE *PPVDIOSTORAGE; 1359 1360 /** 1361 * Support interface for I/O 1362 * 1363 * Per-image. Required. 1364 */ 1365 typedef 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 */ 1589 DECLINLINE(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 } 1291 1605 1292 1606 /** … … 1297 1611 typedef struct VBOXHDD VBOXHDD; 1298 1612 typedef VBOXHDD *PVBOXHDD; 1613 1614 /** 1615 * Request completion callback for the async read/write API. 1616 */ 1617 typedef void (FNVDASYNCTRANSFERCOMPLETE) (void *pvUser1, void *pvUser2); 1618 /** Pointer to a transfer compelte callback. */ 1619 typedef FNVDASYNCTRANSFERCOMPLETE *PFNVDASYNCTRANSFERCOMPLETE; 1299 1620 1300 1621 /** … … 1865 2186 * @param paSeg Pointer to an array of segments. 1866 2187 * @param cSeg Number of segments in the array. 2188 * @param pfnComplete Completion callback. 1867 2189 * @param pvUser User data which is passed on completion 1868 2190 */ 1869 2191 VBOXDDU_DECL(int) VDAsyncRead(PVBOXHDD pDisk, uint64_t uOffset, size_t cbRead, 1870 2192 PPDMDATASEG paSeg, unsigned cSeg, 1871 void *pvUser); 2193 PFNVDASYNCTRANSFERCOMPLETE pfnComplete, 2194 void *pvUser1, void *pvUser2); 1872 2195 1873 2196 … … 1881 2204 * @param paSeg Pointer to an array of segments. 1882 2205 * @param cSeg Number of segments in the array. 2206 * @param pfnComplete Completion callback. 1883 2207 * @param pvUser User data which is passed on completion. 1884 2208 */ 1885 2209 VBOXDDU_DECL(int) VDAsyncWrite(PVBOXHDD pDisk, uint64_t uOffset, size_t cbWrite, 1886 2210 PPDMDATASEG paSeg, unsigned cSeg, 1887 void *pvUser); 2211 PFNVDASYNCTRANSFERCOMPLETE pfnComplete, 2212 void *pvUser1, void *pvUser2); 1888 2213 1889 2214 -
trunk/src/VBox/Devices/Storage/DrvVD.cpp
r27806 r27808 486 486 PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage; 487 487 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; 490 494 } 491 495 … … 498 502 PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage; 499 503 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; 502 510 } 503 511 … … 508 516 PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage; 509 517 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; 512 524 } 513 525 … … 984 996 *******************************************************************************/ 985 997 998 static 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 986 1007 static DECLCALLBACK(int) drvvdStartRead(PPDMIMEDIAASYNC pInterface, uint64_t uOffset, 987 1008 PPDMDATASEG paSeg, unsigned cSeg, … … 991 1012 uOffset, paSeg, cSeg, cbRead, pvUser)); 992 1013 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); 994 1016 LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc)); 995 1017 return rc; … … 1003 1025 uOffset, paSeg, cSeg, cbWrite, pvUser)); 1004 1026 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); 1006 1029 LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc)); 1007 1030 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;1017 1031 } 1018 1032 … … 1464 1478 } 1465 1479 1480 #if 0 /* Temporary disabled. WIP 1466 1481 if (pThis->pDrvMediaAsyncPort) 1467 1482 pThis->fAsyncIOSupported = true; 1483 #else 1484 pThis->fAsyncIOSupported = false; 1485 #endif 1468 1486 1469 1487 unsigned iImageIdx = 0; -
trunk/src/VBox/Devices/Storage/ISCSIHDDCore.cpp
r27181 r27808 3840 3840 /* pfnAsyncWrite */ 3841 3841 NULL, 3842 /* pfnAsyncFlush */ 3843 NULL, 3842 3844 /* pfnComposeLocation */ 3843 3845 iscsiComposeLocation, -
trunk/src/VBox/Devices/Storage/ParallelsHDDCore.cpp
r27232 r27808 72 72 #ifdef VBOX_WITH_NEW_IO_CODE 73 73 /** Async I/O interface. */ 74 PVDINTERFACE pInterface AsyncIO;74 PVDINTERFACE pInterfaceIO; 75 75 /** Async I/O interface callbacks. */ 76 PVDINTERFACE ASYNCIO pInterfaceAsyncIOCallbacks;76 PVDINTERFACEIO pInterfaceIOCallbacks; 77 77 #endif 78 78 … … 84 84 #else 85 85 /** Opaque storage handle. */ 86 void *pvStorage;86 PVDIOSTORAGE pStorage; 87 87 #endif 88 88 /** Open flags passed by VBoxHD layer. */ … … 153 153 rc = RTFileOpen(&pImage->File, pImage->pszFilename, fOpen); 154 154 #else 155 156 155 unsigned uOpenFlags = fReadonly ? VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY : 0; 157 156 … … 159 158 uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE; 160 159 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); 167 164 #endif 168 165 … … 180 177 pImage->File = NIL_RTFILE; 181 178 #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; 187 183 #endif 188 184 … … 197 193 rc = RTFileFlush(pImage->File); 198 194 #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); 202 197 #endif 203 198 … … 212 207 rc = RTFileGetSize(pImage->File, pcbSize); 213 208 #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); 218 211 #endif 219 212 … … 229 222 rc = RTFileSetSize(pImage->File, cbSize); 230 223 #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); 235 227 #endif 236 228 … … 246 238 rc = RTFileWriteAt(pImage->File, off, pcvBuf, cbWrite, pcbWritten); 247 239 #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); 253 244 #endif 254 245 … … 263 254 rc = RTFileReadAt(pImage->File, off, pvBuf, cbRead, pcbRead); 264 255 #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); 270 260 #endif 271 261 … … 278 268 return pImage->File != NIL_RTFILE; 279 269 #else 280 return pImage->p vStorage != NULL;270 return pImage->pStorage != NULL; 281 271 #endif 282 272 } … … 294 284 #ifdef VBOX_WITH_NEW_IO_CODE 295 285 /* Try to get async I/O interface. */ 296 pImage->pInterface AsyncIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ASYNCIO);297 AssertPtr(pImage->pInterface AsyncIO);298 pImage->pInterface AsyncIOCallbacks = VDGetInterfaceAsyncIO(pImage->pInterfaceAsyncIO);299 AssertPtr(pImage->pInterface AsyncIOCallbacks);286 pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_IO); 287 AssertPtr(pImage->pInterfaceIO); 288 pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO); 289 AssertPtr(pImage->pInterfaceIOCallbacks); 300 290 #endif 301 291 … … 504 494 pImage->File = NIL_RTFILE; 505 495 #else 506 pImage->p vStorage = NULL;496 pImage->pStorage = NULL; 507 497 #endif 508 498 pImage->fAllocationBitmapChanged = false; … … 1192 1182 1193 1183 static 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; 1197 1189 } 1198 1190 1199 1191 static 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 1201 static int parallelsAsyncFlush(void *pvBackendData, PVDIOCTX pIoCtx) 1202 { 1203 int rc = VERR_NOT_IMPLEMENTED; 1204 LogFlowFunc(("returns %Rrc\n", rc)); 1205 return rc; 1203 1206 } 1204 1207 … … 1291 1294 /* pfnAsyncWrite */ 1292 1295 parallelsAsyncWrite, 1296 /* pfnAsyncFlush */ 1297 parallelsAsyncFlush, 1293 1298 /* pfnComposeLocation */ 1294 1299 genericFileComposeLocation, -
trunk/src/VBox/Devices/Storage/RawHDDCore.cpp
r27232 r27808 43 43 { 44 44 /** Base image name. */ 45 const char *pszFilename;45 const char *pszFilename; 46 46 #ifndef VBOX_WITH_NEW_IO_CODE 47 47 /** File descriptor. */ 48 RTFILE File;48 RTFILE File; 49 49 #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; 52 56 #endif 53 57 … … 59 63 /** Opaque data for error callback. */ 60 64 PVDINTERFACEERROR pInterfaceErrorCallbacks; 61 #ifdef VBOX_WITH_NEW_IO_CODE62 /** Async I/O interface. */63 PVDINTERFACE pInterfaceAsyncIO;64 /** Async I/O interface callbacks. */65 PVDINTERFACEASYNCIO pInterfaceAsyncIOCallbacks;66 #endif67 65 68 66 /** Open flags passed by VBoxHD layer. */ 69 unsigned uOpenFlags;67 unsigned uOpenFlags; 70 68 /** Image flags defined during creation or determined during open. */ 71 unsigned uImageFlags;69 unsigned uImageFlags; 72 70 /** Total size of the image. */ 73 uint64_t cbSize;71 uint64_t cbSize; 74 72 /** Physical geometry of this image. */ 75 PDMMEDIAGEOMETRY PCHSGeometry;73 PDMMEDIAGEOMETRY PCHSGeometry; 76 74 /** Logical geometry of this image. */ 77 PDMMEDIAGEOMETRY LCHSGeometry;75 PDMMEDIAGEOMETRY LCHSGeometry; 78 76 79 77 } RAWIMAGE, *PRAWIMAGE; … … 132 130 rc = RTFileOpen(&pImage->File, pImage->pszFilename, fOpen); 133 131 #else 134 135 132 unsigned uOpenFlags = fReadonly ? VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY : 0; 136 133 … … 138 135 uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE; 139 136 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); 146 141 #endif 147 142 … … 159 154 pImage->File = NIL_RTFILE; 160 155 #else 161 if (pImage->p vStorage)162 rc = pImage->pInterface AsyncIOCallbacks->pfnClose(pImage->pInterfaceAsyncIO->pvUser,163 pImage->pvStorage);164 165 pImage->p vStorage = NULL;156 if (pImage->pStorage) 157 rc = pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser, 158 pImage->pStorage); 159 160 pImage->pStorage = NULL; 166 161 #endif 167 162 … … 176 171 rc = RTFileFlush(pImage->File); 177 172 #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); 181 175 #endif 182 176 … … 191 185 rc = RTFileGetSize(pImage->File, pcbSize); 192 186 #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); 197 190 #endif 198 191 … … 208 201 rc = RTFileSetSize(pImage->File, cbSize); 209 202 #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); 214 206 #endif 215 207 … … 225 217 rc = RTFileWriteAt(pImage->File, off, pcvBuf, cbWrite, pcbWritten); 226 218 #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); 232 223 #endif 233 224 … … 242 233 rc = RTFileReadAt(pImage->File, off, pvBuf, cbRead, pcbRead); 243 234 #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); 249 239 #endif 250 240 … … 257 247 return pImage->File != NIL_RTFILE; 258 248 #else 259 return pImage->p vStorage != NULL;249 return pImage->pStorage != NULL; 260 250 #endif 261 251 } … … 278 268 279 269 #ifdef VBOX_WITH_NEW_IO_CODE 280 /* Try to get asyncI/O interface. */281 pImage->pInterface AsyncIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ASYNCIO);282 AssertPtr(pImage->pInterface AsyncIO);283 pImage->pInterface AsyncIOCallbacks = VDGetInterfaceAsyncIO(pImage->pInterfaceAsyncIO);284 AssertPtr(pImage->pInterface AsyncIOCallbacks);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); 285 275 #endif 286 276 … … 345 335 #ifdef VBOX_WITH_NEW_IO_CODE 346 336 /* Try to get async I/O interface. */ 347 pImage->pInterface AsyncIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ASYNCIO);348 AssertPtr(pImage->pInterface AsyncIO);349 pImage->pInterface AsyncIOCallbacks = VDGetInterfaceAsyncIO(pImage->pInterfaceAsyncIO);350 AssertPtr(pImage->pInterface AsyncIOCallbacks);337 pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_IO); 338 AssertPtr(pImage->pInterfaceIO); 339 pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO); 340 AssertPtr(pImage->pInterfaceIOCallbacks); 351 341 #endif 352 342 … … 518 508 pImage->File = NIL_RTFILE; 519 509 #else 520 pImage->p vStorage = NULL;510 pImage->pStorage = NULL; 521 511 #endif 522 512 pImage->pVDIfsDisk = pVDIfsDisk; … … 587 577 pImage->File = NIL_RTFILE; 588 578 #else 589 pImage->p vStorage = NULL;579 pImage->pStorage = NULL; 590 580 #endif 591 581 pImage->pVDIfsDisk = pVDIfsDisk; … … 1214 1204 1215 1205 static int rawAsyncRead(void *pvBackendData, uint64_t uOffset, size_t cbRead, 1216 P PDMDATASEG paSeg, unsigned cSeg, void *pvUser)1206 PVDIOCTX pIoCtx, size_t *pcbActuallyRead) 1217 1207 { 1218 1208 int rc = VERR_NOT_IMPLEMENTED; … … 1222 1212 1223 1213 static 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 1223 static int rawAsyncFlush(void *pvBackendData, PVDIOCTX pIoCtx) 1225 1224 { 1226 1225 int rc = VERR_NOT_IMPLEMENTED; … … 1317 1316 /* pfnAsyncWrite */ 1318 1317 rawAsyncWrite, 1318 /* pfnAsyncFlush */ 1319 rawAsyncFlush, 1319 1320 /* pfnComposeLocation */ 1320 1321 genericFileComposeLocation, -
trunk/src/VBox/Devices/Storage/VBoxHDD.cpp
r27806 r27808 39 39 #include <iprt/path.h> 40 40 #include <iprt/param.h> 41 #include <iprt/memcache.h> 41 42 42 43 #include <VBox/VBoxHDD-Plugin.h> … … 82 83 /** Function pointers for the various backend methods. */ 83 84 PCVBOXHDDBACKEND Backend; 84 85 85 /** Pointer to list of VD interfaces, per-image. */ 86 86 PVDINTERFACE pVDIfsImage; … … 135 135 PVDINTERFACETHREADSYNC pInterfaceThreadSyncCallbacks; 136 136 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. */ 138 148 VDINTERFACE VDIAsyncIO; 139 /** Fallback async I/O interface callback table. */149 /** Callback table for the fallback async I/O interface. */ 140 150 VDINTERFACEASYNCIO VDIAsyncIOCallbacks; 151 152 /** Memory cache for I/O contexts */ 153 RTMEMCACHE hMemCacheIoCtx; 141 154 }; 142 155 … … 153 166 } VDPARENTSTATEDESC, *PVDPARENTSTATEDESC; 154 167 168 /** 169 * Transfer direction. 170 */ 171 typedef 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 */ 186 typedef 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 */ 215 typedef struct VDIOSTORAGE 216 { 217 /** Storage handle */ 218 void *pStorage; 219 } VDIOSTORAGE; 155 220 156 221 extern VBOXHDDBACKEND g_RawBackend; … … 394 459 pvBuf = (char *)pvBuf + cbThisRead; 395 460 } while (cbRead != 0 && RT_SUCCESS(rc)); 461 462 return rc; 463 } 464 465 static 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 492 static void vdIoCtxFree(PVBOXHDD pDisk, PVDIOCTX pIoCtx) 493 { 494 RTMemCacheFree(pDisk->hMemCacheIoCtx, pIoCtx); 495 } 496 497 static 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 529 static 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 551 static 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 572 static 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 */ 596 static 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 } 396 652 397 653 return rc; … … 922 1178 } 923 1179 1180 static 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 */ 1188 static 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 1211 static 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 1223 static 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 1233 static 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 1243 static 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 1254 static 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 1265 static 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 1273 static int vdIOReadUserAsync(void *pvUser, PVDIOSTORAGE pIoStorage, 1274 uint64_t uOffset, PVDIOCTX pIoCtx, 1275 size_t cbRead) 1276 { 1277 return VERR_NOT_IMPLEMENTED; 1278 } 1279 1280 static int vdIOWriteUserAsync(void *pvUser, PVDIOSTORAGE pIoStorage, 1281 uint64_t uOffset, PVDIOCTX pIoCtx, 1282 size_t cbWrite) 1283 { 1284 return VERR_NOT_IMPLEMENTED; 1285 } 1286 1287 static 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 1296 static 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 1305 static int vdIOFlushAsync(void *pvUser, PVDIOSTORAGE pIoStorage, 1306 PVDIOCTX pIoCtx) 1307 { 1308 return VERR_NOT_IMPLEMENTED; 1309 } 1310 1311 static size_t vdIOIoCtxCopyTo(void *pvUser, PVDIOCTX pIoCtx, 1312 void *pvBuf, size_t cbBuf) 1313 { 1314 return vdIoCtxCopyTo(pIoCtx, (uint8_t *)pvBuf, cbBuf); 1315 } 1316 1317 static size_t vdIOIoCtxCopyFrom(void *pvUser, PVDIOCTX pIoCtx, 1318 void *pvBuf, size_t cbBuf) 1319 { 1320 return vdIoCtxCopyFrom(pIoCtx, (uint8_t *)pvBuf, cbBuf); 1321 } 1322 1323 static size_t vdIOIoCtxSet(void *pvUser, PVDIOCTX pIoCtx, 1324 int ch, size_t cb) 1325 { 1326 return vdIoCtxSet(pIoCtx, ch, cb); 1327 } 1328 924 1329 /** 925 1330 * internal: send output to the log (unconditionally). … … 1103 1508 pDisk->pInterfaceThreadSyncCallbacks = NULL; 1104 1509 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 1105 1519 pDisk->pInterfaceError = VDInterfaceGet(pVDIfsDisk, VDINTERFACETYPE_ERROR); 1106 1520 if (pDisk->pInterfaceError) … … 1110 1524 if (pDisk->pInterfaceThreadSync) 1111 1525 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 1116 1530 { 1531 /* Create fallback async I/O interface */ 1117 1532 pDisk->VDIAsyncIOCallbacks.cbSize = sizeof(VDINTERFACEASYNCIO); 1118 1533 pDisk->VDIAsyncIOCallbacks.enmInterface = VDINTERFACETYPE_ASYNCIO; … … 1127 1542 pDisk->VDIAsyncIOCallbacks.pfnWriteAsync = vdAsyncIOWriteAsync; 1128 1543 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; 1132 1553 } 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); 1133 1578 1134 1579 *ppDisk = pDisk; … … 1160 1605 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 1161 1606 VDCloseAll(pDisk); 1607 RTMemCacheDestroy(pDisk->hMemCacheIoCtx); 1162 1608 RTMemFree(pDisk); 1163 1609 } while (0); … … 1180 1626 { 1181 1627 int rc = VERR_NOT_SUPPORTED; 1182 PVDINTERFACE pVDIfAsyncIO; 1183 VDINTERFACEASYNCIO VDIAsyncIOCallbacks; 1184 VDINTERFACE VDIAsyncIO; 1628 VDINTERFACEIO VDIIOCallbacks; 1629 VDINTERFACE VDIIO; 1185 1630 1186 1631 LogFlowFunc(("pszFilename=\"%s\"\n", pszFilename)); … … 1196 1641 VDInit(); 1197 1642 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); 1218 1660 1219 1661 /* Find the backend supporting this file format. */ … … 1316 1758 break; 1317 1759 } 1760 1318 1761 pImage->pVDIfsImage = pVDIfsImage; 1319 1762 … … 4446 4889 } 4447 4890 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 4459 4892 VBOXDDU_DECL(int) VDAsyncRead(PVBOXHDD pDisk, uint64_t uOffset, size_t cbRead, 4460 4893 PPDMDATASEG paSeg, unsigned cSeg, 4461 void *pvUser) 4894 PFNVDASYNCTRANSFERCOMPLETE pfnComplete, 4895 void *pvUser1, void *pvUser2) 4462 4896 { 4463 4897 int rc = VERR_VD_BLOCK_FREE; 4464 4898 int rc2; 4465 bool fLock Write= false;4899 bool fLockRead = false; 4466 4900 4467 4901 LogFlowFunc(("pDisk=%#p uOffset=%llu paSeg=%p cSeg=%u cbRead=%zu\n", … … 4484 4918 rc = VERR_INVALID_PARAMETER); 4485 4919 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; 4491 4923 4492 4924 AssertMsgBreakStmt(uOffset + cbRead <= pDisk->cbSize, … … 4495 4927 rc = VERR_INVALID_PARAMETER); 4496 4928 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 4497 4938 PVDIMAGE pImage = pDisk->pLast; 4498 4939 AssertPtrBreakStmt(pImage, rc = VERR_VD_NOT_OPENED); 4499 4940 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); 4526 4942 } while (0); 4527 4943 4528 if (RT_UNLIKELY(fLock Write) && RT_FAILURE(rc))4529 { 4530 rc2 = vdThreadFinish Write(pDisk);4944 if (RT_UNLIKELY(fLockRead)) 4945 { 4946 rc2 = vdThreadFinishRead(pDisk); 4531 4947 AssertRC(rc2); 4532 4948 } … … 4540 4956 4541 4957 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 */4553 4958 VBOXDDU_DECL(int) VDAsyncWrite(PVBOXHDD pDisk, uint64_t uOffset, size_t cbWrite, 4554 4959 PPDMDATASEG paSeg, unsigned cSeg, 4555 void *pvUser) 4960 PFNVDASYNCTRANSFERCOMPLETE pfnComplete, 4961 void *pvUser1, void *pvUser2) 4556 4962 { 4557 4963 int rc; … … 4577 4983 ("cSeg=%zu\n", cSeg), 4578 4984 rc = VERR_INVALID_PARAMETER); 4579 4985 #if 0 4580 4986 rc2 = vdThreadStartWrite(pDisk); 4581 4987 AssertRC(rc2); … … 4594 5000 uOffset, cbWrite, 4595 5001 paSeg, cSeg, pvUser); 5002 #endif 4596 5003 } while (0); 4597 5004 -
trunk/src/VBox/Devices/Storage/VDICore.h
r22966 r27808 533 533 #else 534 534 /** Opaque storage handle. */ 535 void *pvStorage;535 PVDIOSTORAGE pStorage; 536 536 #endif 537 537 #ifndef VBOX_VDICORE_VD … … 591 591 PVDINTERFACEERROR pInterfaceErrorCallbacks; 592 592 # ifdef VBOX_WITH_NEW_IO_CODE 593 /** AsyncI/O interface. */594 PVDINTERFACE pInterfaceAsyncIO;595 /** AsyncI/O interface callbacks. */596 PVDINTERFACE ASYNCIO pInterfaceAsyncIOCallbacks;593 /** I/O interface. */ 594 PVDINTERFACE pInterfaceIO; 595 /** I/O interface callbacks. */ 596 PVDINTERFACEIO pInterfaceIOCallbacks; 597 597 # endif 598 598 #endif /* VBOX_VDICORE_VD */ -
trunk/src/VBox/Devices/Storage/VDIHDDCore.cpp
r27232 r27808 99 99 rc = RTFileOpen(&pImage->File, pImage->pszFilename, fOpen); 100 100 #else 101 102 101 unsigned uOpenFlags = fReadonly ? VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY : 0; 103 102 … … 105 104 uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE; 106 105 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); 113 110 #endif 114 111 … … 126 123 pImage->File = NIL_RTFILE; 127 124 #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; 133 129 #endif 134 130 … … 143 139 rc = RTFileFlush(pImage->File); 144 140 #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); 148 143 #endif 149 144 … … 158 153 rc = RTFileGetSize(pImage->File, pcbSize); 159 154 #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); 164 158 #endif 165 159 … … 174 168 rc = RTFileSetSize(pImage->File, cbSize); 175 169 #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); 180 173 #endif 181 174 … … 190 183 rc = RTFileWriteAt(pImage->File, off, pcvBuf, cbWrite, pcbWritten); 191 184 #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); 197 189 #endif 198 190 … … 207 199 rc = RTFileReadAt(pImage->File, off, pvBuf, cbRead, pcbRead); 208 200 #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); 214 205 #endif 215 206 … … 222 213 return pImage->File != NIL_RTFILE; 223 214 #else 224 return pImage->p vStorage != NULL;215 return pImage->pStorage != NULL; 225 216 #endif 226 217 } … … 524 515 525 516 #ifdef VBOX_WITH_NEW_IO_CODE 526 /* Try to get asyncI/O interface. */527 pImage->pInterface AsyncIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ASYNCIO);528 AssertPtr(pImage->pInterface AsyncIO);529 pImage->pInterface AsyncIOCallbacks = VDGetInterfaceAsyncIO(pImage->pInterfaceAsyncIO);530 AssertPtr(pImage->pInterface AsyncIOCallbacks);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); 531 522 #endif 532 523 … … 713 704 714 705 #ifdef VBOX_WITH_NEW_IO_CODE 715 /* Try to get asyncI/O interface. */716 pImage->pInterface AsyncIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ASYNCIO);717 AssertPtr(pImage->pInterface AsyncIO);718 pImage->pInterface AsyncIOCallbacks = VDGetInterfaceAsyncIO(pImage->pInterfaceAsyncIO);719 AssertPtr(pImage->pInterface AsyncIOCallbacks);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); 720 711 #endif 721 712 … … 936 927 pImage->File = NIL_RTFILE; 937 928 #else 938 pImage->p vStorage = NULL;929 pImage->pStorage = NULL; 939 930 #endif 940 931 pImage->paBlocks = NULL; … … 984 975 pImage->File = NIL_RTFILE; 985 976 #else 986 pImage->p vStorage = NULL;977 pImage->pStorage = NULL; 987 978 #endif 988 979 pImage->paBlocks = NULL; … … 1062 1053 pImage->File = NIL_RTFILE; 1063 1054 #else 1064 pImage->p vStorage = NULL;1055 pImage->pStorage = NULL; 1065 1056 #endif 1066 1057 pImage->paBlocks = NULL; … … 1894 1885 (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) ? "r/o" : "r/w", 1895 1886 pImage->uOpenFlags, 1896 pImage->p vStorage);1887 pImage->pStorage); 1897 1888 #endif 1898 1889 pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: Version=%08X Type=%X Flags=%X Size=%llu\n", … … 1988 1979 } 1989 1980 1990 static int vdiAsyncRead(void *p BackendData, uint64_t uOffset, size_t cbRead,1991 P PDMDATASEG paSeg, unsigned cSeg, void *pvUser)1981 static int vdiAsyncRead(void *pvBackendData, uint64_t uOffset, size_t cbRead, 1982 PVDIOCTX pIoCtx, size_t *pcbActuallyRead) 1992 1983 { 1993 1984 int rc = VERR_NOT_IMPLEMENTED; … … 1996 1987 } 1997 1988 1998 static int vdiAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbWrite, 1999 PPDMDATASEG paSeg, unsigned cSeg, void *pvUser) 1989 static 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 1999 static int vdiAsyncFlush(void *pvBackendData, PVDIOCTX pIoCtx) 2000 2000 { 2001 2001 int rc = VERR_NOT_IMPLEMENTED; … … 2328 2328 /* pfnAsyncWrite */ 2329 2329 vdiAsyncWrite, 2330 /* pfnAsyncFlush */ 2331 vdiAsyncFlush, 2330 2332 /* pfnComposeLocation */ 2331 2333 genericFileComposeLocation, -
trunk/src/VBox/Devices/Storage/VHDHDDCore.cpp
r27358 r27808 134 134 RTFILE File; 135 135 #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; 138 142 #endif 139 143 … … 144 148 /** Error interface callback table. */ 145 149 PVDINTERFACEERROR pInterfaceErrorCallbacks; 146 #ifdef VBOX_WITH_NEW_IO_CODE147 /** Async I/O interface. */148 PVDINTERFACE pInterfaceAsyncIO;149 /** Async I/O interface callbacks. */150 PVDINTERFACEASYNCIO pInterfaceAsyncIOCallbacks;151 #endif152 150 153 151 /** Open flags passed by VBoxHD layer. */ … … 236 234 rc = RTFileOpen(&pImage->File, pImage->pszFilename, fOpen); 237 235 #else 238 239 236 unsigned uOpenFlags = fReadonly ? VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY : 0; 240 237 … … 242 239 uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE; 243 240 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); 250 245 #endif 251 246 … … 263 258 pImage->File = NIL_RTFILE; 264 259 #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; 270 263 #endif 271 264 … … 280 273 rc = RTFileFlush(pImage->File); 281 274 #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); 285 277 #endif 286 278 … … 295 287 rc = RTFileGetSize(pImage->File, pcbSize); 296 288 #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); 301 292 #endif 302 293 … … 312 303 rc = RTFileSetSize(pImage->File, cbSize); 313 304 #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); 318 308 #endif 319 309 … … 329 319 rc = RTFileWriteAt(pImage->File, off, pcvBuf, cbWrite, pcbWritten); 330 320 #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); 336 325 #endif 337 326 … … 346 335 rc = RTFileReadAt(pImage->File, off, pvBuf, cbRead, pcbRead); 347 336 #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); 353 341 #endif 354 342 … … 361 349 return pImage->File != NIL_RTFILE; 362 350 #else 363 return pImage->p vStorage != NULL;351 return pImage->pStorage != NULL; 364 352 #endif 365 353 } … … 593 581 #ifdef VBOX_WITH_NEW_IO_CODE 594 582 /* Try to get async I/O interface. */ 595 pImage->pInterface AsyncIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ASYNCIO);596 AssertPtr(pImage->pInterface AsyncIO);597 pImage->pInterface AsyncIOCallbacks = VDGetInterfaceAsyncIO(pImage->pInterfaceAsyncIO);598 AssertPtr(pImage->pInterface AsyncIOCallbacks);583 pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_IO); 584 AssertPtr(pImage->pInterfaceIO); 585 pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO); 586 AssertPtr(pImage->pInterfaceIOCallbacks); 599 587 #endif 600 588 … … 693 681 pImage->File = NIL_RTFILE; 694 682 #else 695 pImage->p vStorage = NULL;683 pImage->pStorage = NULL; 696 684 #endif 697 685 pImage->pVDIfsDisk = pVDIfsDisk; … … 1981 1969 pImage->File = NIL_RTFILE; 1982 1970 #else 1983 pImage->p vStorage = NULL;1971 pImage->pStorage = NULL; 1984 1972 #endif 1985 1973 pImage->pVDIfsDisk = pVDIfsDisk; 1986 1974 1987 1975 #ifdef VBOX_WITH_NEW_IO_CODE 1988 /* Try to get asyncI/O interface. */1989 pImage->pInterface AsyncIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ASYNCIO);1990 AssertPtr(pImage->pInterface AsyncIO);1991 pImage->pInterface AsyncIOCallbacks = VDGetInterfaceAsyncIO(pImage->pInterfaceAsyncIO);1992 AssertPtr(pImage->pInterface AsyncIOCallbacks);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); 1993 1981 #endif 1994 1982 … … 2146 2134 2147 2135 static int vhdAsyncRead(void *pvBackendData, uint64_t uOffset, size_t cbRead, 2148 P PDMDATASEG paSeg, unsigned cSeg, void *pvUser)2136 PVDIOCTX pIoCtx, size_t *pcbActuallyRead) 2149 2137 { 2150 2138 int rc = VERR_NOT_IMPLEMENTED; … … 2153 2141 } 2154 2142 2155 static int vhdAsyncWrite(void *pvBackendData, uint64_t uOffset, size_t cbToWrite, 2156 PPDMDATASEG paSeg, unsigned cSeg, void *pvUser) 2143 static 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) 2157 2147 { 2158 2148 int rc = VERR_NOT_IMPLEMENTED; … … 2161 2151 } 2162 2152 2153 static int vhdAsyncFlush(void *pvBackendData, PVDIOCTX pIoCtx) 2154 { 2155 int rc = VERR_NOT_IMPLEMENTED; 2156 LogFlowFunc(("returns %Rrc\n", rc)); 2157 return rc; 2158 } 2163 2159 2164 2160 VBOXHDDBACKEND g_VhdBackend = … … 2251 2247 /* pfnAsyncWrite */ 2252 2248 vhdAsyncWrite, 2249 /* pfnAsyncFlush */ 2250 vhdAsyncFlush, 2253 2251 /* pfnComposeLocation */ 2254 2252 genericFileComposeLocation, -
trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp
r27735 r27808 230 230 { 231 231 /** Pointer to filename. Local copy. */ 232 const char *pszFilename;232 const char *pszFilename; 233 233 /** File open flags for consistency checking. */ 234 unsigned fOpen;234 unsigned fOpen; 235 235 /** File handle. */ 236 RTFILE File;236 RTFILE File; 237 237 /** Handle for asnychronous access if requested.*/ 238 void *pStorage;238 PVDIOSTORAGE pStorage; 239 239 /** Flag whether to use File or pStorage. */ 240 bool fAsyncIO;240 bool fAsyncIO; 241 241 /** Reference counter. */ 242 unsigned uReferences;242 unsigned uReferences; 243 243 /** Flag whether the file should be deleted on last close. */ 244 bool fDelete;244 bool fDelete; 245 245 /** Pointer to the image we belong to. */ 246 PVMDKIMAGE pImage;246 PVMDKIMAGE pImage; 247 247 /** Pointer to next file descriptor. */ 248 248 struct VMDKFILE *pNext; … … 429 429 PVDINTERFACEERROR pInterfaceErrorCallbacks; 430 430 431 /** AsyncI/O interface. */432 PVDINTERFACE pInterface AsyncIO;433 /** AsyncI/O interface callbacks. */434 PVDINTERFACE ASYNCIO pInterfaceAsyncIOCallbacks;431 /** I/O interface. */ 432 PVDINTERFACE pInterfaceIO; 433 /** I/O interface callbacks. */ 434 PVDINTERFACEIO pInterfaceIOCallbacks; 435 435 /** 436 436 * Pointer to an array of segment entries for async I/O. … … 583 583 if ((pImage->uOpenFlags & VD_OPEN_FLAGS_ASYNC_IO) && (fAsyncIO)) 584 584 { 585 rc = pImage->pInterface AsyncIOCallbacks->pfnOpen(pImage->pInterfaceAsyncIO->pvUser,585 rc = pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser, 586 586 pszFilename, 587 587 pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY … … 606 606 uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE; 607 607 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); 614 612 #endif 615 613 if (RT_SUCCESS(rc)) … … 665 663 if (pVmdkFile->fAsyncIO) 666 664 { 667 rc = pImage->pInterface AsyncIOCallbacks->pfnClose(pImage->pInterfaceAsyncIO->pvUser,665 rc = pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser, 668 666 pVmdkFile->pStorage); 669 667 } … … 673 671 } 674 672 #else 675 rc = pImage->pInterface AsyncIOCallbacks->pfnClose(pImage->pInterfaceAsyncIO->pvUser,676 673 rc = pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser, 674 pVmdkFile->pStorage); 677 675 #endif 678 676 if (RT_SUCCESS(rc) && pVmdkFile->fDelete) … … 697 695 #ifndef VBOX_WITH_NEW_IO_CODE 698 696 if (pVmdkFile->fAsyncIO) 699 return pImage->pInterface AsyncIOCallbacks->pfnReadSync(pImage->pInterfaceAsyncIO->pvUser,700 701 697 return pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser, 698 pVmdkFile->pStorage, uOffset, 699 cbToRead, pvBuf, pcbRead); 702 700 else 703 701 return RTFileReadAt(pVmdkFile->File, uOffset, pvBuf, cbToRead, pcbRead); 704 702 #else 705 return pImage->pInterface AsyncIOCallbacks->pfnReadSync(pImage->pInterfaceAsyncIO->pvUser,706 707 703 return pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser, 704 pVmdkFile->pStorage, uOffset, 705 cbToRead, pvBuf, pcbRead); 708 706 #endif 709 707 } … … 720 718 #ifndef VBOX_WITH_NEW_IO_CODE 721 719 if (pVmdkFile->fAsyncIO) 722 return pImage->pInterface AsyncIOCallbacks->pfnWriteSync(pImage->pInterfaceAsyncIO->pvUser,720 return pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser, 723 721 pVmdkFile->pStorage, uOffset, 724 722 cbToWrite, pvBuf, pcbWritten); … … 726 724 return RTFileWriteAt(pVmdkFile->File, uOffset, pvBuf, cbToWrite, pcbWritten); 727 725 #else 728 return pImage->pInterface AsyncIOCallbacks->pfnWriteSync(pImage->pInterfaceAsyncIO->pvUser,726 return pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser, 729 727 pVmdkFile->pStorage, uOffset, 730 728 cbToWrite, pvBuf, pcbWritten); … … 742 740 if (pVmdkFile->fAsyncIO) 743 741 { 744 return pImage->pInterface AsyncIOCallbacks->pfnGetSize(pImage->pInterfaceAsyncIO->pvUser,742 return pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser, 745 743 pVmdkFile->pStorage, 746 744 pcbSize); … … 749 747 return RTFileGetSize(pVmdkFile->File, pcbSize); 750 748 #else 751 return pImage->pInterface AsyncIOCallbacks->pfnGetSize(pImage->pInterfaceAsyncIO->pvUser,749 return pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser, 752 750 pVmdkFile->pStorage, 753 751 pcbSize); … … 765 763 if (pVmdkFile->fAsyncIO) 766 764 { 767 return pImage->pInterface AsyncIOCallbacks->pfnSetSize(pImage->pInterfaceAsyncIO->pvUser,765 return pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser, 768 766 pVmdkFile->pStorage, 769 767 cbSize); … … 772 770 return RTFileSetSize(pVmdkFile->File, cbSize); 773 771 #else 774 return pImage->pInterface AsyncIOCallbacks->pfnSetSize(pImage->pInterfaceAsyncIO->pvUser,772 return pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser, 775 773 pVmdkFile->pStorage, 776 774 cbSize); … … 787 785 #ifndef VBOX_WITH_NEW_IO_CODE 788 786 if (pVmdkFile->fAsyncIO) 789 return pImage->pInterface AsyncIOCallbacks->pfnFlushSync(pImage->pInterfaceAsyncIO->pvUser,787 return pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser, 790 788 pVmdkFile->pStorage); 791 789 else 792 790 return RTFileFlush(pVmdkFile->File); 793 791 #else 794 return pImage->pInterface AsyncIOCallbacks->pfnFlushSync(pImage->pInterfaceAsyncIO->pvUser,792 return pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser, 795 793 pVmdkFile->pStorage); 796 794 #endif … … 1026 1024 1027 1025 if (pImage->uOpenFlags & VD_OPEN_FLAGS_ASYNC_IO) 1028 rc2 = pImage->pInterface AsyncIOCallbacks->pfnClose(pImage->pInterfaceAsyncIO->pvUser,1026 rc2 = pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser, 1029 1027 pVmdkFile->pStorage); 1030 1028 else … … 2976 2974 2977 2975 /* Try to get async I/O interface. */ 2978 pImage->pInterface AsyncIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ASYNCIO);2979 if (pImage->pInterface AsyncIO)2980 pImage->pInterface AsyncIOCallbacks = VDGetInterfaceAsyncIO(pImage->pInterfaceAsyncIO);2976 pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_IO); 2977 if (pImage->pInterfaceIO) 2978 pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO); 2981 2979 2982 2980 /* … … 3845 3843 3846 3844 /* Try to get async I/O interface. */ 3847 pImage->pInterface AsyncIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ASYNCIO);3848 if (pImage->pInterface AsyncIO)3849 pImage->pInterface AsyncIOCallbacks = VDGetInterfaceAsyncIO(pImage->pInterfaceAsyncIO);3845 pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_IO); 3846 if (pImage->pInterfaceIO) 3847 pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO); 3850 3848 3851 3849 rc = vmdkCreateDescriptor(pImage, pImage->pDescData, pImage->cbDescAlloc, … … 5858 5856 static bool vmdkIsAsyncIOSupported(void *pvBackendData) 5859 5857 { 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; 5889 5859 } 5890 5860 5891 5861 static 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; 6015 5865 LogFlowFunc(("returns %Rrc\n", rc)); 6016 5866 return rc; … … 6018 5868 6019 5869 static 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 5879 static int vmdkAsyncFlush(void *pvBackendData, PVDIOCTX pIoCtx) 5880 { 5881 int rc = VERR_NOT_IMPLEMENTED; 6143 5882 LogFlowFunc(("returns %Rrc\n", rc)); 6144 5883 return rc; … … 6235 5974 /* pfnAsyncWrite */ 6236 5975 vmdkAsyncWrite, 5976 /* pfnAsyncFlush */ 5977 vmdkAsyncFlush, 6237 5978 /* pfnComposeLocation */ 6238 5979 genericFileComposeLocation,
Note:
See TracChangeset
for help on using the changeset viewer.