Changeset 10715 in vbox
- Timestamp:
- Jul 16, 2008 10:38:23 PM (16 years ago)
- Location:
- trunk
- Files:
-
- 18 edited
-
include/VBox/VBoxHDD-new.h (modified) (7 diffs)
-
include/VBox/err.h (modified) (1 diff)
-
include/VBox/pdmifs.h (modified) (15 diffs)
-
include/VBox/types.h (modified) (1 diff)
-
src/VBox/Devices/Storage/DrvBlock.cpp (modified) (5 diffs)
-
src/VBox/Devices/Storage/DrvVD.cpp (modified) (14 diffs)
-
src/VBox/Devices/Storage/RawHDDCore.cpp (modified) (9 diffs)
-
src/VBox/Devices/Storage/VBoxHDD-new.cpp (modified) (13 diffs)
-
src/VBox/Devices/Storage/VBoxHDD-newInternal.h (modified) (3 diffs)
-
src/VBox/Devices/Storage/VDICore.h (modified) (1 diff)
-
src/VBox/Devices/Storage/VDIHDDCore.cpp (modified) (9 diffs)
-
src/VBox/Devices/Storage/VmdkHDDCore.cpp (modified) (80 diffs)
-
src/VBox/Devices/Storage/testcase/tstVD.cpp (modified) (6 diffs)
-
src/VBox/Devices/testcase/tstDeviceStructSizeGC.cpp (modified) (1 diff)
-
src/VBox/Frontends/VBoxManage/VBoxInternalManage.cpp (modified) (2 diffs)
-
src/VBox/Main/ConsoleImpl2.cpp (modified) (1 diff)
-
src/VBox/Main/HardDiskImpl.cpp (modified) (5 diffs)
-
src/VBox/Main/include/HardDiskImpl.h (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/VBoxHDD-new.h
r10467 r10715 178 178 * used for querying information, and nothing else. */ 179 179 #define VD_OPEN_FLAGS_INFO RT_BIT(3) 180 /** Open image for asynchronous access. 181 * Only available if VD_CAP_ASYNC_IO is set 182 * Check with VDIsAsynchonousIoSupported wether 183 * asynchronous I/O is really supported for this file. 184 */ 185 #define VD_OPEN_FLAGS_ASYNC_IO RT_BIT(4) 180 186 /** Mask of valid flags. */ 181 #define VD_OPEN_FLAGS_MASK (VD_OPEN_FLAGS_NORMAL | VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_HONOR_ZEROES | VD_OPEN_FLAGS_HONOR_SAME | VD_OPEN_FLAGS_INFO )187 #define VD_OPEN_FLAGS_MASK (VD_OPEN_FLAGS_NORMAL | VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_HONOR_ZEROES | VD_OPEN_FLAGS_HONOR_SAME | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO) 182 188 /** @}*/ 183 189 … … 196 202 /** Supports being used as differencing image format backend. */ 197 203 #define VD_CAP_DIFF RT_BIT(4) 204 /** Supports asynchronous I/O operations for at least some configurations. */ 205 #define VD_CAP_ASYNC RT_BIT(5) 198 206 /** The backend operates on files. The caller needs to know to handle the 199 207 * location appropriately. */ 200 208 #define VD_CAP_FILE RT_BIT(6) 201 209 /** @}*/ 202 203 210 204 211 /** … … 213 220 } VDBACKENDINFO, *PVDBACKENDINFO; 214 221 215 216 /** 217 * Error message callback. 218 * 219 * @param pvUser The opaque data passed on container creation. 220 * @param rc The VBox error code. 221 * @param RT_SRC_POS_DECL Use RT_SRC_POS. 222 * @param pszFormat Error message format string. 223 * @param va Error message arguments. 224 */ 225 typedef DECLCALLBACK(void) FNVDERROR(void *pvUser, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va); 226 /** Pointer to a FNVDERROR(). */ 227 typedef FNVDERROR *PFNVDERROR; 222 /** 223 * Supported interface types. 224 */ 225 typedef enum VDINTERFACETYPE 226 { 227 /** First valid interface. */ 228 VDINTERFACETYPE_FIRST = 0, 229 /** Interface to pass error message to upper layers. */ 230 VDINTERFACETYPE_ERROR = VDINTERFACETYPE_FIRST, 231 /** Interface for asynchronous I/O operations. */ 232 VDINTERFACETYPE_ASYNCIO, 233 /** Interface for progress notification. */ 234 VDINTERFACETYPE_PROGRESS, 235 /** invalid interface. */ 236 VDINTERFACETYPE_INVALID 237 } VDINTERFACETYPE; 238 239 /** 240 * Common structure for all interfaces. 241 */ 242 typedef struct VDINTERFACE 243 { 244 /** Human readable interface name. */ 245 const char *pszInterfaceName; 246 /** The size of the struct. */ 247 uint32_t cbSize; 248 /** Pointer to the next common interface structure. */ 249 struct VDINTERFACE *pNext; 250 /** Interface type. */ 251 VDINTERFACETYPE enmInterface; 252 /** Opaque user data which is passed on every call. */ 253 void *pvUser; 254 /** Pointer to the function call table of the interface. 255 * As this is opaque this must be casted to the right interface 256 * struct defined below based on the interface type in enmInterface. */ 257 void *pCallbacks; 258 } VDINTERFACE, *PVDINTERFACE; 259 /** Pointer to a const PVDINTERFACE. */ 260 typedef const PVDINTERFACE PCVDINTERFACE; 261 262 /** 263 * Helper functions to handle interface lists. 264 */ 265 266 /** 267 * Get a specific interface from a list of interfaces specified by the type. 268 * 269 * @returns Pointer to the matching interface or NULL if none was found. 270 * @param pInterfaces Pointer to the first interface in the list. 271 * @param enmInterface Interface to search for. 272 */ 273 DECLINLINE(PVDINTERFACE) VDGetInterfaceFromList(PVDINTERFACE pInterfaces, VDINTERFACETYPE enmInterface) 274 { 275 AssertMsgReturn( (enmInterface >= VDINTERFACETYPE_FIRST) 276 && (enmInterface < VDINTERFACETYPE_INVALID), 277 ("enmInterface=%u", enmInterface), NULL); 278 279 while (pInterfaces) 280 { 281 /* Sanity checks. */ 282 AssertMsgBreak(pInterfaces->cbSize == sizeof(VDINTERFACE), 283 ("cbSize=%u\n", pInterfaces->cbSize)); 284 285 if (pInterfaces->enmInterface == enmInterface) 286 return pInterfaces; 287 pInterfaces = pInterfaces->pNext; 288 } 289 290 /* No matching interface was found. */ 291 return NULL; 292 } 293 294 /** 295 * Initialize a common interface structure. 296 * 297 * @return VBox status code. 298 * @param pInterface Pointer to an unitialized common interface structure. 299 * @param pszName Name of the interface. 300 * @param enmInterface Type of the interface. 301 * @param pCallbacks The callback table of the interface. 302 * @param pvUser Opaque user data passed on every function call. 303 * @param pNext Pointer to the next supported interface if any. 304 */ 305 DECLINLINE(int) VDInterfaceCreate(PVDINTERFACE pInterface, const char *pszName, 306 VDINTERFACETYPE enmInterface, void *pCallbacks, 307 void *pvUser, PVDINTERFACE pNext) 308 { 309 310 /** Argument checks. */ 311 AssertMsgReturn( (enmInterface >= VDINTERFACETYPE_FIRST) 312 && (enmInterface < VDINTERFACETYPE_INVALID), 313 ("enmInterface=%u", enmInterface), VERR_INVALID_PARAMETER); 314 315 AssertMsgReturn(VALID_PTR(pCallbacks), 316 ("pCallbacks=%#p", pCallbacks), 317 VERR_INVALID_PARAMETER); 318 319 pInterface->cbSize = sizeof(VDINTERFACE); 320 pInterface->pszInterfaceName = pszName; 321 pInterface->enmInterface = enmInterface; 322 pInterface->pCallbacks = pCallbacks; 323 pInterface->pvUser = pvUser; 324 pInterface->pNext = pNext; 325 return VINF_SUCCESS; 326 } 327 328 /** 329 * Interface to deliver error messages to upper layers. 330 */ 331 typedef struct VDINTERFACEERROR 332 { 333 /** 334 * Size of the error interface. 335 */ 336 uint32_t cbSize; 337 338 /** 339 * Interface type. 340 */ 341 VDINTERFACETYPE enmInterface; 342 343 /** 344 * Error message callback. 345 * 346 * @param pvUser The opaque data passed on container creation. 347 * @param rc The VBox error code. 348 * @param RT_SRC_POS_DECL Use RT_SRC_POS. 349 * @param pszFormat Error message format string. 350 * @param va Error message arguments. 351 */ 352 DECLR3CALLBACKMEMBER(void, pfnError, (void *pvUser, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)); 353 354 } VDINTERFACEERROR, *PVDINTERFACEERROR; 355 356 /** 357 * Get error interface from opaque callback table. 358 * 359 * @return Pointer to the callback table. 360 * @param pCallbacks Opaque interface pointer. 361 */ 362 DECLINLINE(PVDINTERFACEERROR) VDGetInterfaceError(void *pCallbacks) 363 { 364 PVDINTERFACEERROR pInterfaceError = (PVDINTERFACEERROR)pCallbacks; 365 366 /* Do basic checks. */ 367 AssertMsgReturn( (pInterfaceError->cbSize == sizeof(VDINTERFACEERROR)) 368 && (pInterfaceError->enmInterface == VDINTERFACETYPE_ERROR), 369 ("Not an error interface\n"), NULL); 370 371 return pInterfaceError; 372 } 373 374 /** 375 * Completion callback which is called by the interface owner 376 * to inform the backend that a task finished. 377 * 378 * @returns VBox status code. 379 * @param pvUser Opaque user data which is passed on request submission. 380 */ 381 typedef DECLCALLBACK(int) FNVDCOMPLETED(void *pvUser); 382 /** Pointer to FNVDCOMPLETED() */ 383 typedef FNVDCOMPLETED *PFNVDCOMPLETED; 384 385 386 /** 387 * Support interface for asynchronous I/O 388 */ 389 typedef struct VDINTERFACEASYNCIO 390 { 391 /** 392 * Size of the async interface. 393 */ 394 uint32_t cbSize; 395 396 /** 397 * Interface type. 398 */ 399 VDINTERFACETYPE enmInterface; 400 401 /** 402 * Open callback 403 * 404 * @returns VBox status code. 405 * @param pvUser The opaque data passed on container creation. 406 * @param pszLocation Name of the location to open. 407 * @param fReadonly Whether to open the storage medium read only. 408 * @param ppStorage Where to store the opaque storage handle. 409 */ 410 DECLR3CALLBACKMEMBER(int, pfnOpen, (void *pvUser, const char *pszLocation, bool fReadonly, void **ppStorage)); 411 412 /** 413 * Close callback. 414 * 415 * @returns VBox status code. 416 * @param pvUser The opaque data passed on container creation. 417 * @param pStorage The opaque storage handle to close. 418 */ 419 DECLR3CALLBACKMEMBER(int, pfnClose, (void *pvUser, void *pStorage)); 420 421 /** 422 * Synchronous write callback. 423 * 424 * @returns VBox status code. 425 * @param pvUser The opaque data passed on container creation. 426 * @param pStorage The storage handle to use. 427 * @param uOffset The offset to start from. 428 * @þaram cbWrite How many bytes to write. 429 * @param pvBuf Pointer to the bits need to be written. 430 * @param pcbWritten Where to store how many bytes where actually written. 431 */ 432 DECLR3CALLBACKMEMBER(int, pfnWrite, (void *pvUser, void *pStorage, uint64_t uOffset, 433 size_t cbWrite, const void *pvBuf, size_t *pcbWritten)); 434 435 /** 436 * Synchronous read callback. 437 * 438 * @returns VBox status code. 439 * @param pvUser The opaque data passed on container creation. 440 * @param pStorage The storage handle to use. 441 * @param uOffset The offset to start from. 442 * @þaram cbRead How many bytes to read. 443 * @param pvBuf Where to store the read bits. 444 * @param pcbRead Where to store how many bytes where actually read. 445 */ 446 DECLR3CALLBACKMEMBER(int, pfnRead, (void *pvUser, void *pStorage, uint64_t uOffset, 447 size_t cbRead, void *pvBuf, size_t *pcbRead)); 448 449 /** 450 * Flush data to the storage backend. 451 * 452 * @returns VBox statis code. 453 * @param pvUser The opaque data passed on container creation. 454 * @param pStorage The storage handle to flush. 455 */ 456 DECLR3CALLBACKMEMBER(int, pfnFlush, (void *pvUser, void *pStorage)); 457 458 /** 459 * Prepare an asynchronous read task. 460 * 461 * @returns VBox status code. 462 * @param pvUser The opqaue user data passed on container creation. 463 * @param pStorage The storage handle. 464 * @param uOffset The offset to start reading from. 465 * @param pvBuf Where to store read bits. 466 * @param cbRead How many bytes to read. 467 * @param ppTask Where to store the opaque task handle. 468 */ 469 DECLR3CALLBACKMEMBER(int, pfnPrepareRead, (void *pvUser, void *pStorage, uint64_t uOffset, 470 void *pvBuf, size_t cbRead, void **ppTask)); 471 472 /** 473 * Prepare an asynchronous write task. 474 * 475 * @returns VBox status code. 476 * @param pvUser The opaque user data passed on conatiner creation. 477 * @param pStorage The storage handle. 478 * @param uOffset The offset to start writing to. 479 * @param pvBuf Where to read the data from. 480 * @param cbWrite How many bytes to write. 481 * @param ppTask Where to store the opaque task handle. 482 */ 483 DECLR3CALLBACKMEMBER(int, pfnPrepareWrite, (void *pvUser, void *pStorage, uint64_t uOffset, 484 void *pvBuf, size_t cbWrite, void **ppTask)); 485 486 /** 487 * Submit an array of tasks for processing 488 * 489 * @returns VBox status code. 490 * @param pvUser The opaque user data passed on container creation. 491 * @param apTasks Array of task handles to submit. 492 * @param cTasks How many tasks to submit. 493 * @param pvUser2 User data which is passed on completion. 494 * @param pvUserCaller Opaque user data the caller of VDAsyncWrite/Read passed. 495 * @param pfnTasksCompleted Pointer to callback which is called on request completion. 496 */ 497 DECLR3CALLBACKMEMBER(int, pfnTasksSubmit, (void *pvUser, void *apTasks[], unsigned cTasks, void *pvUser2, 498 void *pvUserCaller, PFNVDCOMPLETED pfnTasksCompleted)); 499 500 } VDINTERFACEASYNCIO, *PVDINTERFACEASYNCIO; 501 502 /** 503 * Get async I/O interface from opaque callback table. 504 * 505 * @return Pointer to the callback table. 506 * @param pCallbacks Opaque interface pointer. 507 */ 508 DECLINLINE(PVDINTERFACEASYNCIO) VDGetInterfaceAsyncIO(void *pCallbacks) 509 { 510 PVDINTERFACEASYNCIO pInterfaceAsyncIO = (PVDINTERFACEASYNCIO)pCallbacks; 511 512 /* Do basic checks. */ 513 AssertMsgReturn( (pInterfaceAsyncIO->cbSize == sizeof(VDINTERFACEASYNCIO)) 514 && (pInterfaceAsyncIO->enmInterface == VDINTERFACETYPE_ASYNCIO), 515 ("Not an async I/O interface\n"), NULL); 516 517 return pInterfaceAsyncIO; 518 } 519 520 /** 521 * Progress notification interface 522 */ 523 typedef struct VDINTERFACEPROGRESS 524 { 525 /** 526 * Size of the progress interface. 527 */ 528 uint32_t cbSize; 529 530 /** 531 * Interface type. 532 */ 533 VDINTERFACETYPE enmInterface; 534 535 /** 536 * Progress notification callbacks. 537 */ 538 PFNVMPROGRESS pfnProgress; 539 } VDINTERFACEPROGRESS, *PVDINTERFACEPROGRESS; 540 541 /** 542 * Get progress interface from opaque callback table. 543 * 544 * @return Pointer to the callback table. 545 * @param pCallbacks Opaque interface pointer. 546 */ 547 DECLINLINE(PVDINTERFACEPROGRESS) VDGetInterfaceProgress(void *pCallbacks) 548 { 549 PVDINTERFACEPROGRESS pInterfaceProgress = (PVDINTERFACEPROGRESS)pCallbacks; 550 551 /* Do basic checks. */ 552 AssertMsgReturn( (pInterfaceProgress->cbSize == sizeof(VDINTERFACEPROGRESS)) 553 && (pInterfaceProgress->enmInterface == VDINTERFACETYPE_PROGRESS), 554 ("Not an progress notification interface\n"), NULL); 555 556 return pInterfaceProgress; 557 } 228 558 229 559 … … 250 580 unsigned *pcEntriesUsed); 251 581 582 /** 583 * Lists the capablities of a backend indentified by its name. 584 * Free all returned names with RTStrFree() when you no longer need them. 585 * 586 * @returns VBox status code. 587 * @param pszBackend The backend name. 588 * @param pEntries Pointer to an entry. 589 */ 590 VBOXDDU_DECL(int) VDBackendInfoOne(const char *pszBackend, PVDBACKENDINFO pEntry); 252 591 253 592 /** … … 256 595 * 257 596 * @returns VBox status code. 258 * @param pfnError Callback for setting extended error information. 259 * @param pvErrorUser Opaque parameter for pfnError. 597 * @param pInterfaces Pointer to the first supported interface. 260 598 * @param ppDisk Where to store the reference to HDD container. 261 599 */ 262 VBOXDDU_DECL(int) VDCreate(PFNVDERROR pfnError, void *pvErrorUser, 263 PVBOXHDD *ppDisk); 600 VBOXDDU_DECL(int) VDCreate(PVDINTERFACE pInterfaces, PVBOXHDD *ppDisk); 264 601 265 602 /** … … 559 896 560 897 /** 898 * List the capabilities of image backend in HDD container. 899 * 900 * @returns VBox status code. 901 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 902 * @param pDisk Pointer to the HDD container. 903 * @param nImage Image number, counts from 0. 0 is always base image of container. 904 * @param pbackendInfo Where to store the backend information. 905 */ 906 VBOXDDU_DECL(int) VDBackendInfoSingle(PVBOXHDD pDisk, unsigned nImage, 907 PVDBACKENDINFO pBackendInfo); 908 909 /** 561 910 * Get flags of image in HDD container. 562 911 * … … 714 1063 VBOXDDU_DECL(void) VDDumpImages(PVBOXHDD pDisk); 715 1064 1065 1066 /** 1067 * Query if asynchronous operations are supported for this disk. 1068 * 1069 * @returns VBox status code. 1070 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 1071 * @param pDisk Pointer to the HDD container. 1072 * @param nImage Image number, counts from 0. 0 is always base image of container. 1073 * @param pfAIOSupported Where to store if async IO is supported. 1074 */ 1075 VBOXDDU_DECL(int) VDImageIsAsyncIOSupported(PVBOXHDD pDisk, unsigned nImage, bool *pfAIOSupported); 1076 1077 1078 /** 1079 * Start a asynchronous read request. 1080 * 1081 * @returns VBox status code. 1082 * @param pDisk Pointer to the HDD container. 1083 * @param uOffset The offset of the virtual disk to read from. 1084 * @param cbRead How many bytes to read. 1085 * @param paSeg Pointer to an array of segments. 1086 * @param cSeg Number of segments in the array. 1087 * @param pvUser User data which is passed on completion 1088 */ 1089 VBOXDDU_DECL(int) VDAsyncRead(PVBOXHDD pDisk, uint64_t uOffset, size_t cbRead, 1090 PPDMDATASEG paSeg, unsigned cSeg, 1091 void *pvUser); 1092 1093 1094 /** 1095 * Start a asynchronous write request. 1096 * 1097 * @returns VBox status code. 1098 * @param pDisk Pointer to the HDD container. 1099 * @param uOffset The offset of the virtual disk to write to. 1100 * @param cbWrtie How many bytes to write. 1101 * @param paSeg Pointer to an array of segments. 1102 * @param cSeg Number of segments in the array. 1103 * @param pvUser User data which is passed on completion. 1104 */ 1105 VBOXDDU_DECL(int) VDAsyncWrite(PVBOXHDD pDisk, uint64_t uOffset, size_t cbWrite, 1106 PPDMDATASEG paSeg, unsigned cSeg, 1107 void *pvUser); 1108 1109 716 1110 __END_DECLS 717 1111 -
trunk/include/VBox/err.h
r10530 r10715 1049 1049 /** Configuration value not found. */ 1050 1050 #define VERR_VDI_VALUE_NOT_FOUND (-3216) 1051 /** Asynchronous I/O request finished. */ 1052 #define VINF_VDI_ASYNC_IO_FINISHED 3218 1053 /** Asynchronous I/O is not finished yet. */ 1054 #define VERR_VDI_ASYNC_IO_IN_PROGRESS (-3219) 1051 1055 /** @} */ 1052 1056 -
trunk/include/VBox/pdmifs.h
r9765 r10715 1115 1115 1116 1116 1117 /**1118 * Data transport buffer (scatter/gather)1119 */1120 typedef struct PDMIDATATRANSPORTSEG1121 {1122 /** Length of buffer in entry. */1123 size_t cbSeg;1124 /** Pointer to the start of the buffer. */1125 void *pvSeg;1126 } PDMIDATATRANSPORTSEG;1127 /** Pointer to a data transport segment. */1128 typedef PDMIDATATRANSPORTSEG *PPDMIDATATRANSPORTSEG;1129 /** Pointer to a const data transport segment. */1130 typedef PDMIDATATRANSPORTSEG const *PCPDMIDATATRANSPORTSEG;1131 1132 1133 1117 /** Pointer to an asynchronous iSCSI transport driver interface. */ 1134 1118 typedef struct PDMIISCSITRANSPORTASYNC *PPDMIISCSITRANSPORTASYNC; … … 1207 1191 { 1208 1192 /** 1209 * Notify completion of a read task. 1210 * 1211 * @returns VBox status code. 1212 * @param pInterface Pointer to the interface structure containing the called function pointer. 1213 * @param off Offset the task read from. 1214 * @param pSeg Pointer to the first element in the gather list. 1215 * @param cSeg Number of segments in the gather list. 1216 * @param cbRead Number of bytes read. 1217 * @param pvUser The user argument given in pfnStartRead. 1218 * @thread Any thread. 1219 */ 1220 DECLR3CALLBACKMEMBER(int, pfnReadCompleteNotify, (PPDMIBLOCKASYNCPORT pInterface, uint64_t off, PPDMIDATATRANSPORTSEG pSeg, unsigned cSeg, size_t cbRead, void *pvUser)); 1221 1222 /** 1223 * Notify completion of a write task. 1224 * 1225 * @returns VBox status code. 1226 * @param pInterface Pointer to the interface structure containing the called function pointer. 1227 * @param off Offset the task has written to. 1228 * @param pSeg Pointer to the first element in the scatter list. 1229 * @param cSeg Number of segments in the scatter list. 1230 * @param cbWritten Number of bytes actually written. 1231 * @param pvUser The user argument given in pfnStartWrite. 1232 * @thread Any thread. 1233 */ 1234 DECLR3CALLBACKMEMBER(int, pfnWriteCompleteNotify, (PPDMIBLOCKASYNCPORT pInterface, uint64_t off, PPDMIDATATRANSPORTSEG pSeg, unsigned cSeg, size_t cbWritten, void *pvUser)); 1193 * Notify completion of a asynchronous transfer. 1194 * 1195 * @returns VBox status code. 1196 * @param pInterface Pointer to the interface structure containing the called function pointer. 1197 * @param pvUser The user argument given in pfnStartWrite/Read. 1198 * @thread Any thread. 1199 */ 1200 DECLR3CALLBACKMEMBER(int, pfnTransferCompleteNotify, (PPDMIBLOCKASYNCPORT pInterface, void *pvUser)); 1235 1201 } PDMIBLOCKASYNCPORT; 1236 1202 … … 1256 1222 * @thread Any thread. 1257 1223 */ 1258 DECLR3CALLBACKMEMBER(int, pfnStartRead,(PPDMIBLOCKASYNC pInterface, uint64_t off, PPDM IDATATRANSPORTSEG pSeg, unsigned cSeg, size_t cbRead, void *pvUser));1224 DECLR3CALLBACKMEMBER(int, pfnStartRead,(PPDMIBLOCKASYNC pInterface, uint64_t off, PPDMDATASEG pSeg, unsigned cSeg, size_t cbRead, void *pvUser)); 1259 1225 1260 1226 /** … … 1270 1236 * @thread Any thread. 1271 1237 */ 1272 DECLR3CALLBACKMEMBER(int, pfnStartWrite,(PPDMIBLOCKASYNC pInterface, uint64_t off, PPDM IDATATRANSPORTSEG pSeg, unsigned cSeg, size_t cbWrite, void *pvUser));1238 DECLR3CALLBACKMEMBER(int, pfnStartWrite,(PPDMIBLOCKASYNC pInterface, uint64_t off, PPDMDATASEG pSeg, unsigned cSeg, size_t cbWrite, void *pvUser)); 1273 1239 1274 1240 } PDMIBLOCKASYNC; … … 1284 1250 { 1285 1251 /** 1286 * Notify completion of a read task. 1287 * 1288 * @returns VBox status code. 1289 * @param pInterface Pointer to the interface structure containing the called function pointer. 1290 * @param off Offset the task read from. 1291 * @param pSeg Pointer to the first element in the scatter list. 1292 * @param cSeg Number of entries in the list. 1293 * @param cbRead Number of bytes read. 1294 * @param pvUser The user argument given in pfnStartRead. 1295 * @thread Any thread. 1296 */ 1297 DECLR3CALLBACKMEMBER(int, pfnReadCompleteNotify, (PPDMIMEDIAASYNCPORT pInterface, uint64_t off, PPDMIDATATRANSPORTSEG pSeg, unsigned cSeg, size_t cbRead, void *pvUser)); 1298 1299 /** 1300 * Notify completion of a write task. 1301 * 1302 * @returns VBox status code. 1303 * @param pInterface Pointer to the interface structure containing the called function pointer. 1304 * @param off Offset the task has written to. 1305 * @param pSeg Pointer to the first element in the gather list. 1306 * @param cSeg Number of entries in the list. 1307 * @param cbWritten Number of bytes actually written. 1252 * Notify completion of a task. 1253 * 1254 * @returns VBox status code. 1255 * @param pInterface Pointer to the interface structure containing the called function pointer. 1308 1256 * @param pvUser The user argument given in pfnStartWrite. 1309 1257 * @thread Any thread. 1310 1258 */ 1311 DECLR3CALLBACKMEMBER(int, pfn WriteCompleteNotify, (PPDMIMEDIAASYNCPORT pInterface, uint64_t off, PPDMIDATATRANSPORTSEG pSeg, unsigned cSeg, size_t cbWritten, void *pvUser));1259 DECLR3CALLBACKMEMBER(int, pfnTransferCompleteNotify, (PPDMIMEDIAASYNCPORT pInterface, void *pvUser)); 1312 1260 } PDMIMEDIAASYNCPORT; 1313 1261 … … 1333 1281 * @thread Any thread. 1334 1282 */ 1335 DECLR3CALLBACKMEMBER(int, pfnStartRead,(PPDMIMEDIAASYNC pInterface, uint64_t off, PPDM IDATATRANSPORTSEG pSeg, unsigned cSeg, size_t cbRead, void *pvUser));1283 DECLR3CALLBACKMEMBER(int, pfnStartRead,(PPDMIMEDIAASYNC pInterface, uint64_t off, PPDMDATASEG pSeg, unsigned cSeg, size_t cbRead, void *pvUser)); 1336 1284 1337 1285 /** … … 1347 1295 * @thread Any thread. 1348 1296 */ 1349 DECLR3CALLBACKMEMBER(int, pfnStartWrite,(PPDMIMEDIAASYNC pInterface, uint64_t off, PPDM IDATATRANSPORTSEG pSeg, unsigned cSeg, size_t cbWrite, void *pvUser));1297 DECLR3CALLBACKMEMBER(int, pfnStartWrite,(PPDMIMEDIAASYNC pInterface, uint64_t off, PPDMDATASEG pSeg, unsigned cSeg, size_t cbWrite, void *pvUser)); 1350 1298 1351 1299 } PDMIMEDIAASYNC; … … 1361 1309 { 1362 1310 /** 1363 * Notify completion of a read task. 1364 * 1365 * @returns VBox status code. 1366 * @param pInterface Pointer to the interface structure containing the called function pointer. 1367 * @param off Offset the task read from. 1368 * @param pSeg Pointer to the first element in the scatter list. 1369 * @param cSeg Number of entries in the list. 1370 * @param cbRead Number of bytes read. 1371 * @param pvUser The user argument given in pfnStartRead. 1372 * @thread Any thread. 1373 */ 1374 DECLR3CALLBACKMEMBER(int, pfnReadCompleteNotify, (PPDMITRANSPORTASYNCPORT pInterface, uint64_t off, PPDMIDATATRANSPORTSEG pSeg, unsigned cSeg, 1375 size_t cbRead, void *pvUser)); 1376 1377 /** 1378 * Notify completion of a write task. 1379 * 1380 * @returns VBox status code. 1381 * @param pInterface Pointer to the interface structure containing the called function pointer. 1382 * @param off Offset the task has written to. 1383 * @param pSeg Pointer to the first element in the gather list. 1384 * @param cSeg Number of entries in the list. 1385 * @param cbWritten Number of bytes actually written. 1386 * @param pvUser The user argument given in pfnStartWrite. 1387 * @thread Any thread. 1388 */ 1389 DECLR3CALLBACKMEMBER(int, pfnWriteCompleteNotify, (PPDMITRANSPORTASYNCPORT pInterface, uint64_t off, PPDMIDATATRANSPORTSEG pSeg, unsigned cSeg, 1390 size_t cbWritten, void *pvUser)); 1311 * Notify completion of tasks. 1312 * 1313 * @returns VBox status code. 1314 * @param pInterface Pointer to the interface structure containing the called function pointer. 1315 * @param pvUser The user argument given in pfnTasksSubmit. 1316 * @thread Any thread. 1317 */ 1318 DECLR3CALLBACKMEMBER(int, pfnTaskCompleteNotify, (PPDMITRANSPORTASYNCPORT pInterface, void *pvUser)); 1319 1391 1320 } PDMITRANSPORTASYNCPORT; 1392 1321 … … 1406 1335 * @returns VBox status code. 1407 1336 * @param pInterface Pointer to the interface structure containint the called function pointer. 1337 * @param pStorage The storage handle to read from. 1408 1338 * @param off Offset to start reading from. 1409 * @param pvBuf here to store the read bits.1339 * @param pvBuf Where to store the read bits. 1410 1340 * @param cbRead Number of bytes to read. 1411 1341 * @param pcbRead Where to store the number of bytes actually read. 1412 1342 * @thread Any thread. 1413 1343 */ 1414 DECLR3CALLBACKMEMBER(int, pfnReadSynchronous, (PPDMITRANSPORTASYNC pInterface, uint64_t off, void *pvBuf, size_t cbRead, size_t *pcbRead)); 1344 DECLR3CALLBACKMEMBER(int, pfnReadSynchronous, (PPDMITRANSPORTASYNC pInterface, void *pStorage, 1345 uint64_t off, void *pvBuf, size_t cbRead, size_t *pcbRead)); 1415 1346 1416 1347 /** … … 1420 1351 * @returns VBox status code. 1421 1352 * @param pInterface Pointer to the interface structure containint the called function pointer. 1353 * @param pStorage The storage handle to write to. 1422 1354 * @param off Offset to start reading from. 1423 * @param pvBuf here to store the read bits.1355 * @param pvBuf Pointer to the buffer which contains the data to write. 1424 1356 * @param cbWrite Number of bytes to read. 1425 1357 * @param pcbWritten Where to store the number of bytes actually read. 1426 1358 * @thread Any thread. 1427 1359 */ 1428 DECLR3CALLBACKMEMBER(int, pfnWriteSynchronous, (PPDMITRANSPORTASYNC pInterface, uint64_t off, void *pvBuf, size_t cbWrite, size_t *pcbWritten)); 1429 1430 /** 1431 * Start asynchronous read. 1432 * 1433 * @returns VBox status code. 1434 * @param pInterface Pointer to the interface structure containing the called function pointer. 1435 * @param off Offset to start reading from. 1436 * @param pSeg Pointer to the first element in the scatter list. 1437 * @param cSeg Number of entries in the list. 1438 * @param cbRead Number of bytes to read. 1439 * @param pvUser User argument returned in completion callback. 1440 * @thread Any thread. 1441 */ 1442 DECLR3CALLBACKMEMBER(int, pfnReadStartAsynchronous,(PPDMITRANSPORTASYNC pInterface, uint64_t off, PPDMIDATATRANSPORTSEG pSeg, unsigned cSeg, 1443 size_t cbRead, void *pvUser)); 1444 1445 /** 1446 * Start asynchronous write. 1447 * 1448 * @returns VBox status code. 1449 * @param pInterface Pointer to the interface structure containing the called function pointer. 1450 * @param off Offset to start writing at. 1451 * @param pSeg Pointer to the first element in the gather list. 1452 * @param cSeg Number of entries in the list. 1453 * @param cbWrite Number of bytes to write. 1454 * @param pvUser User argument returned in completion callback. 1455 * @thread Any thread. 1456 */ 1457 DECLR3CALLBACKMEMBER(int, pfnWriteStartAsynchronous,(PPDMITRANSPORTASYNC pInterface, uint64_t off, PPDMIDATATRANSPORTSEG pSeg, unsigned cSeg, 1458 size_t cbWrite, void *pvUser)); 1360 DECLR3CALLBACKMEMBER(int, pfnWriteSynchronous, (PPDMITRANSPORTASYNC pInterface, void *pStorage, 1361 uint64_t off, const void *pvBuf, size_t cbWrite, size_t *pcbWritten)); 1459 1362 1460 1363 /** … … 1464 1367 * @returns VBox status code. 1465 1368 * @param pInterface Pointer to the interface structure containing the called function pointer. 1466 * @thread Any thread. 1467 */ 1468 DECLR3CALLBACKMEMBER(int, pfnFlushSynchronous,(PPDMITRANSPORTASYNC pInterface)); 1369 * @param pStorage The storage handle to flush- 1370 * @thread Any thread. 1371 */ 1372 DECLR3CALLBACKMEMBER(int, pfnFlushSynchronous,(PPDMITRANSPORTASYNC pInterface, void *pStorage)); 1469 1373 1470 1374 /** … … 1473 1377 * @returns Media size in bytes. 1474 1378 * @param pInterface Pointer to the interface structure containing the called function pointer. 1475 * @thread Any thread. 1476 */ 1477 DECLR3CALLBACKMEMBER(uint64_t, pfnGetSize,(PPDMITRANSPORTASYNC pInterface)); 1379 * @param pStorage The storage handle. 1380 * @thread Any thread. 1381 */ 1382 DECLR3CALLBACKMEMBER(uint64_t, pfnGetSize,(PPDMITRANSPORTASYNC pInterface, void *pStorage)); 1478 1383 1479 1384 /** … … 1483 1388 * @returns false if read/write. 1484 1389 * @param pInterface Pointer to the interface structure containing the called function pointer. 1485 * @thread Any thread. 1486 */ 1487 DECLR3CALLBACKMEMBER(bool, pfnIsReadOnly,(PPDMITRANSPORTASYNC pInterface)); 1390 * @param pStorage The storage handle. 1391 * @thread Any thread. 1392 */ 1393 DECLR3CALLBACKMEMBER(bool, pfnIsReadOnly,(PPDMITRANSPORTASYNC pInterface, void *pStorage)); 1488 1394 1489 1395 /** … … 1494 1400 * @param pszPath The path to open. 1495 1401 * @param fReadonly If the target shoudl opened readonly. 1496 * @thread Any thread. 1497 */ 1498 DECLR3CALLBACKMEMBER(int, pfnOpen, (PPDMITRANSPORTASYNC pInterface, const char *pszTargetPath, bool fReadonly)); 1402 * @param ppStorage Where to store the storage handle. 1403 * @thread Any thread. 1404 */ 1405 DECLR3CALLBACKMEMBER(int, pfnOpen, (PPDMITRANSPORTASYNC pInterface, const char *pszTargetPath, bool fReadonly, void **ppStorage)); 1499 1406 1500 1407 /** … … 1503 1410 * @returns VBox status code. 1504 1411 * @param pInterface Pointer to the interface structure containing the called function pointer. 1505 * @thread Any thread. 1506 */ 1507 DECLR3CALLBACKMEMBER(int, pfnClose, (PPDMITRANSPORTASYNC pInterface)); 1508 1412 * @param pStorage The storage handle to close. 1413 * @thread Any thread. 1414 */ 1415 DECLR3CALLBACKMEMBER(int, pfnClose, (PPDMITRANSPORTASYNC pInterface, void *pStorage)); 1416 1417 /** 1418 * Prepare an asynchronous read task. 1419 * 1420 * @returns VBox status code. 1421 * @param pInterface Pointer to the interface structure containing the called function pointer. 1422 * @param pStorage The storage handle. 1423 * @param uOffset The offset to start reading from. 1424 * @param pvBuf Where to store read bits. 1425 * @param cbRead How many bytes to read. 1426 * @param ppTask Where to store the opaque task handle. 1427 */ 1428 DECLR3CALLBACKMEMBER(int, pfnPrepareRead, (PPDMITRANSPORTASYNC pInterface, void *pStorage, uint64_t uOffset, 1429 void *pvBuf, size_t cbRead, void **ppTask)); 1430 1431 /** 1432 * Prepare an asynchronous write task. 1433 * 1434 * @returns VBox status code. 1435 * @param pInterface Pointer to the interface structure containing the called function pointer. 1436 * @param pStorage The storage handle. 1437 * @param uOffset The offset to start writing to. 1438 * @param pvBuf Where to read the data from. 1439 * @param cbWrite How many bytes to write. 1440 * @param ppTask Where to store the opaque task handle. 1441 */ 1442 DECLR3CALLBACKMEMBER(int, pfnPrepareWrite, (PPDMITRANSPORTASYNC pInterface, void *pStorage, uint64_t uOffset, 1443 void *pvBuf, size_t cbWrite, void **ppTask)); 1444 1445 /** 1446 * Submit an array of tasks for processing 1447 * 1448 * @returns VBox status code. 1449 * @param pInterface Pointer to the interface structure containing the called function pointer. 1450 * @param apTasks Array of task handles to submit. 1451 * @param cTasks How many tasks to submit. 1452 * @param pvUser User data which is passed on completion. 1453 */ 1454 DECLR3CALLBACKMEMBER(int, pfnTasksSubmit, (PPDMITRANSPORTASYNC pInterface, void *apTasks[], unsigned cTasks, void *pvUser)); 1509 1455 } PDMITRANSPORTASYNC; 1510 1456 -
trunk/include/VBox/types.h
r10087 r10715 508 508 typedef const PDMMAC *PCPDMMAC; 509 509 510 /** 511 * Data transport buffer (scatter/gather) 512 */ 513 typedef struct PDMDATASEG 514 { 515 /** Length of buffer in entry. */ 516 size_t cbSeg; 517 /** Pointer to the start of the buffer. */ 518 void *pvSeg; 519 } PDMDATASEG; 520 /** Pointer to a data transport segment. */ 521 typedef PDMDATASEG *PPDMDATASEG; 522 /** Pointer to a const data transport segment. */ 523 typedef PDMDATASEG const *PCPDMDATASEG; 510 524 511 525 /** @} */ -
trunk/src/VBox/Devices/Storage/DrvBlock.cpp
r8529 r10715 260 260 261 261 /** @copydoc PDMIBLOCKASYNC::pfnRead */ 262 static DECLCALLBACK(int) drvblockAsyncReadStart(PPDMIBLOCKASYNC pInterface, uint64_t off, PPDM IDATATRANSPORTSEG pSeg, unsigned cSeg, size_t cbRead, void *pvUser)262 static DECLCALLBACK(int) drvblockAsyncReadStart(PPDMIBLOCKASYNC pInterface, uint64_t off, PPDMDATASEG pSeg, unsigned cSeg, size_t cbRead, void *pvUser) 263 263 { 264 264 PDRVBLOCK pData = PDMIBLOCKASYNC_2_DRVBLOCK(pInterface); … … 279 279 280 280 /** @copydoc PDMIBLOCKASYNC::pfnWrite */ 281 static DECLCALLBACK(int) drvblockAsyncWriteStart(PPDMIBLOCKASYNC pInterface, uint64_t off, PPDM IDATATRANSPORTSEG pSeg, unsigned cSeg, size_t cbWrite, void *pvUser)281 static DECLCALLBACK(int) drvblockAsyncWriteStart(PPDMIBLOCKASYNC pInterface, uint64_t off, PPDMDATASEG pSeg, unsigned cSeg, size_t cbWrite, void *pvUser) 282 282 { 283 283 PDRVBLOCK pData = PDMIBLOCKASYNC_2_DRVBLOCK(pInterface); … … 302 302 #define PDMIMEDIAASYNCPORT_2_DRVBLOCK(pInterface) ( (PDRVBLOCK((uintptr_t)pInterface - RT_OFFSETOF(DRVBLOCK, IMediaAsyncPort))) ) 303 303 304 305 static DECLCALLBACK(int) drvblockAsyncReadCompleteNotify(PPDMIMEDIAASYNCPORT pInterface, uint64_t uOffset, PPDMIDATATRANSPORTSEG pSeg, unsigned cSeg, size_t cbRead, void *pvUser) 304 static DECLCALLBACK(int) drvblockAsyncTransferCompleteNotify(PPDMIMEDIAASYNCPORT pInterface, void *pvUser) 306 305 { 307 306 PDRVBLOCK pData = PDMIMEDIAASYNCPORT_2_DRVBLOCK(pInterface); 308 307 309 return pData->pDrvBlockAsyncPort->pfnReadCompleteNotify(pData->pDrvBlockAsyncPort, uOffset, pSeg, cSeg, cbRead, pvUser); 310 } 311 312 static DECLCALLBACK(int) drvblockAsyncWriteCompleteNotify(PPDMIMEDIAASYNCPORT pInterface, uint64_t uOffset, PPDMIDATATRANSPORTSEG pSeg, unsigned cSeg, size_t cbWritten, void *pvUser) 313 { 314 PDRVBLOCK pData = PDMIMEDIAASYNCPORT_2_DRVBLOCK(pInterface); 315 316 #ifdef VBOX_PERIODIC_FLUSH 317 if (pData->cbFlushInterval) 318 { 319 pData->cbDataWritten += cbWritten; 320 if (pData->cbDataWritten > pData->cbFlushInterval) 321 { 322 pData->cbDataWritten = 0; 323 pData->pDrvMedia->pfnFlush(pData->pDrvMedia); 324 } 325 } 326 #endif /* VBOX_PERIODIC_FLUSH */ 327 328 return pData->pDrvBlockAsyncPort->pfnWriteCompleteNotify(pData->pDrvBlockAsyncPort, uOffset, pSeg, cSeg, cbWritten, pvUser); 308 return pData->pDrvBlockAsyncPort->pfnTransferCompleteNotify(pData->pDrvBlockAsyncPort, pvUser); 329 309 } 330 310 … … 678 658 return pData->pDrvMediaAsync ? &pData->IBlockAsync : NULL; 679 659 case PDMINTERFACE_MEDIA_ASYNC_PORT: 680 return &pData->IMediaAsyncPort;660 return pData->pDrvBlockAsyncPort ? &pData->IMediaAsyncPort : NULL; 681 661 default: 682 662 return NULL; … … 771 751 772 752 /* IMediaAsyncPort. */ 773 pData->IMediaAsyncPort.pfnReadCompleteNotify = drvblockAsyncReadCompleteNotify; 774 pData->IMediaAsyncPort.pfnWriteCompleteNotify = drvblockAsyncWriteCompleteNotify; 753 pData->IMediaAsyncPort.pfnTransferCompleteNotify = drvblockAsyncTransferCompleteNotify; 775 754 776 755 /* -
trunk/src/VBox/Devices/Storage/DrvVD.cpp
r8155 r10715 34 34 #include <iprt/file.h> 35 35 #include <iprt/string.h> 36 #include <iprt/cache.h> 36 37 37 38 #include "Builtins.h" … … 54 55 ( PDMINS2DATA(PDMIBASE_2_DRVINS(pInterface), PVBOXDISK) ) 55 56 57 /** Converts a pointer to VBOXDISK::IMediaAsync to a PVBOXDISK. */ 58 #define PDMIMEDIAASYNC_2_VBOXDISK(pInterface) \ 59 ( (PVBOXDISK)((uintptr_t)pInterface - RT_OFFSETOF(VBOXDISK, IMediaAsync)) ) 60 61 /** Converts a pointer to VBOXDISK::ITransportAsyncPort to a PVBOXDISK. */ 62 #define PDMITRANSPORTASYNCPORT_2_VBOXDISK(pInterface) \ 63 ( (PVBOXDISK)((uintptr_t)pInterface - RT_OFFSETOF(VBOXDISK, ITransportAsyncPort)) ) 64 65 /** 66 * Structure for an async I/O task. 67 */ 68 typedef struct DRVVDASYNCTASK 69 { 70 /** Callback which is called on completion. */ 71 PFNVDCOMPLETED pfnCompleted; 72 /** Opqaue user data which is passed on completion. */ 73 void *pvUser; 74 /** Opaque user data the caller passed on transfer initiation. */ 75 void *pvUserCaller; 76 } DRVVDASYNCTASK, *PDRVVDASYNCTASK; 56 77 57 78 /** … … 61 82 { 62 83 /** The VBox disk container. */ 63 PVBOXHDD pDisk;84 PVBOXHDD pDisk; 64 85 /** The media interface. */ 65 PDMIMEDIA IMedia;86 PDMIMEDIA IMedia; 66 87 /** Pointer to the driver instance. */ 67 PPDMDRVINS pDrvIns;88 PPDMDRVINS pDrvIns; 68 89 /** Flag whether suspend has changed image open mode to read only. */ 69 bool fTempReadOnly; 90 bool fTempReadOnly; 91 /** Common structure for the supported error interface. */ 92 VDINTERFACE VDIError; 93 /** Callback table for error interface. */ 94 VDINTERFACEERROR VDIErrorCallbacks; 95 /** Common structure for the supported async I/O interface. */ 96 VDINTERFACE VDIAsyncIO; 97 /** Callback table for async I/O interface. */ 98 VDINTERFACEASYNCIO VDIAsyncIOCallbacks; 99 /** Flag whether opened disk suppports async I/O operations. */ 100 bool fAsyncIOSupported; 101 /** The async media interface. */ 102 PDMIMEDIAASYNC IMediaAsync; 103 /** The async media port interface above. */ 104 PPDMIMEDIAASYNCPORT pDrvMediaAsyncPort; 105 /** Pointer to the asynchronous media driver below. */ 106 PPDMITRANSPORTASYNC pDrvTransportAsync; 107 /** Async transport port interface. */ 108 PDMITRANSPORTASYNCPORT ITransportAsyncPort; 109 /** Our cache to reduce allocation overhead. */ 110 PRTOBJCACHE pCache; 70 111 } VBOXDISK, *PVBOXDISK; 71 112 … … 79 120 PPDMDRVINS pDrvIns = (PPDMDRVINS)pvUser; 80 121 pDrvIns->pDrvHlp->pfnVMSetErrorV(pDrvIns, rc, RT_SRC_POS_ARGS, pszFormat, va); 122 } 123 124 /******************************************************************************* 125 * VD Async I/O interface implementation * 126 *******************************************************************************/ 127 128 static DECLCALLBACK(int) drvvdAsyncIOOpen(void *pvUser, const char *pszLocation, bool fReadonly, void **ppStorage) 129 { 130 PVBOXDISK pDrvVD = (PVBOXDISK)pvUser; 131 132 return pDrvVD->pDrvTransportAsync->pfnOpen(pDrvVD->pDrvTransportAsync, pszLocation, fReadonly, ppStorage); 133 } 134 135 static DECLCALLBACK(int) drvvdAsyncIOClose(void *pvUser, void *pStorage) 136 { 137 PVBOXDISK pDrvVD = (PVBOXDISK)pvUser; 138 139 AssertMsg(pDrvVD->pDrvTransportAsync, ("Asynchronous function called but no async transport interface below\n")); 140 141 return pDrvVD->pDrvTransportAsync->pfnClose(pDrvVD->pDrvTransportAsync, pStorage); 142 } 143 144 static DECLCALLBACK(int) drvvdAsyncIORead(void *pvUser, void *pStorage, uint64_t uOffset, 145 size_t cbRead, void *pvBuf, size_t *pcbRead) 146 { 147 PVBOXDISK pDrvVD = (PVBOXDISK)pvUser; 148 149 AssertMsg(pDrvVD->pDrvTransportAsync, ("Asynchronous function called but no async transport interface below\n")); 150 151 return pDrvVD->pDrvTransportAsync->pfnReadSynchronous(pDrvVD->pDrvTransportAsync, 152 pStorage, 153 uOffset, pvBuf, cbRead, pcbRead); 154 } 155 156 static DECLCALLBACK(int) drvvdAsyncIOWrite(void *pvUser, void *pStorage, uint64_t uOffset, 157 size_t cbWrite, const void *pvBuf, size_t *pcbWritten) 158 { 159 PVBOXDISK pDrvVD = (PVBOXDISK)pvUser; 160 161 AssertMsg(pDrvVD->pDrvTransportAsync, ("Asynchronous function called but no async transport interface below\n")); 162 163 return pDrvVD->pDrvTransportAsync->pfnWriteSynchronous(pDrvVD->pDrvTransportAsync, 164 pStorage, 165 uOffset, pvBuf, cbWrite, pcbWritten); 166 } 167 168 static DECLCALLBACK(int) drvvdAsyncIOFlush(void *pvUser, void *pStorage) 169 { 170 PVBOXDISK pDrvVD = (PVBOXDISK)pvUser; 171 172 AssertMsg(pDrvVD->pDrvTransportAsync, ("Asynchronous function called but no async transport interface below\n")); 173 174 return pDrvVD->pDrvTransportAsync->pfnFlushSynchronous(pDrvVD->pDrvTransportAsync, pStorage); 175 } 176 177 static DECLCALLBACK(int) drvvdAsyncIOPrepareRead(void *pvUser, void *pStorage, uint64_t uOffset, void *pvBuf, size_t cbRead, void **ppTask) 178 { 179 PVBOXDISK pDrvVD = (PVBOXDISK)pvUser; 180 181 AssertMsg(pDrvVD->pDrvTransportAsync, ("Asynchronous function called but no async transport interface below\n")); 182 183 return pDrvVD->pDrvTransportAsync->pfnPrepareRead(pDrvVD->pDrvTransportAsync, pStorage, uOffset, pvBuf, cbRead, ppTask); 184 } 185 186 static DECLCALLBACK(int) drvvdAsyncIOPrepareWrite(void *pvUser, void *pStorage, uint64_t uOffset, void *pvBuf, size_t cbWrite, void **ppTask) 187 { 188 PVBOXDISK pDrvVD = (PVBOXDISK)pvUser; 189 190 AssertMsg(pDrvVD->pDrvTransportAsync, ("Asynchronous function called but no async transport interface below\n")); 191 192 return pDrvVD->pDrvTransportAsync->pfnPrepareWrite(pDrvVD->pDrvTransportAsync, pStorage, uOffset, pvBuf, cbWrite, ppTask); 193 } 194 195 static DECLCALLBACK(int) drvvdAsyncIOTasksSubmit(void *pvUser, void *apTasks[], unsigned cTasks, void *pvUser2, 196 void *pvUserCaller, PFNVDCOMPLETED pfnTasksCompleted) 197 { 198 PVBOXDISK pDrvVD = (PVBOXDISK)pvUser; 199 PDRVVDASYNCTASK pDrvVDAsyncTask; 200 int rc; 201 202 AssertMsg(pDrvVD->pDrvTransportAsync, ("Asynchronous function called but no async transport interface below\n")); 203 204 rc = RTCacheRequest(pDrvVD->pCache, (void **)&pDrvVDAsyncTask); 205 206 if (RT_FAILURE(rc)) 207 return rc; 208 209 pDrvVDAsyncTask->pfnCompleted = pfnTasksCompleted; 210 pDrvVDAsyncTask->pvUser = pvUser2; 211 pDrvVDAsyncTask->pvUserCaller = pvUserCaller; 212 213 return pDrvVD->pDrvTransportAsync->pfnTasksSubmit(pDrvVD->pDrvTransportAsync, apTasks, cTasks, pDrvVDAsyncTask); 81 214 } 82 215 … … 213 346 } 214 347 348 /******************************************************************************* 349 * Async Media interface methods * 350 *******************************************************************************/ 351 352 static DECLCALLBACK(int) drvvdStartRead(PPDMIMEDIAASYNC pInterface, uint64_t uOffset, 353 PPDMDATASEG paSeg, unsigned cSeg, 354 size_t cbRead, void *pvUser) 355 { 356 LogFlow(("%s: uOffset=%#llx paSeg=%#p cSeg=%u cbRead=%d\n pvUser=%#p", __FUNCTION__, 357 uOffset, paSeg, cSeg, cbRead, pvUser)); 358 PVBOXDISK pData = PDMIMEDIAASYNC_2_VBOXDISK(pInterface); 359 int rc = VDAsyncRead(pData->pDisk, uOffset, cbRead, paSeg, cSeg, pvUser); 360 LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc)); 361 return rc; 362 } 363 364 static DECLCALLBACK(int) drvvdStartWrite(PPDMIMEDIAASYNC pInterface, uint64_t uOffset, 365 PPDMDATASEG paSeg, unsigned cSeg, 366 size_t cbWrite, void *pvUser) 367 { 368 LogFlow(("%s: uOffset=%#llx paSeg=%#p cSeg=%u cbWrite=%d\n pvUser=%#p", __FUNCTION__, 369 uOffset, paSeg, cSeg, cbWrite, pvUser)); 370 PVBOXDISK pData = PDMIMEDIAASYNC_2_VBOXDISK(pInterface); 371 int rc = VDAsyncWrite(pData->pDisk, uOffset, cbWrite, paSeg, cSeg, pvUser); 372 LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc)); 373 return rc; 374 } 375 376 /******************************************************************************* 377 * Async transport port interface methods * 378 *******************************************************************************/ 379 380 static DECLCALLBACK(int) drvvdTasksCompleteNotify(PPDMITRANSPORTASYNCPORT pInterface, void *pvUser) 381 { 382 PVBOXDISK pData = PDMITRANSPORTASYNCPORT_2_VBOXDISK(pInterface); 383 PDRVVDASYNCTASK pDrvVDAsyncTask = (PDRVVDASYNCTASK)pvUser; 384 int rc = VINF_VDI_ASYNC_IO_FINISHED; 385 386 /* Having a completion callback for a task is not mandatory. */ 387 if (pDrvVDAsyncTask->pfnCompleted) 388 rc = pDrvVDAsyncTask->pfnCompleted(pDrvVDAsyncTask->pvUser); 389 390 /* Check if the request is finished. */ 391 if (rc == VINF_VDI_ASYNC_IO_FINISHED) 392 { 393 rc = pData->pDrvMediaAsyncPort->pfnTransferCompleteNotify(pData->pDrvMediaAsyncPort, pDrvVDAsyncTask->pvUserCaller); 394 } 395 else if (rc == VERR_VDI_ASYNC_IO_IN_PROGRESS) 396 rc = VINF_SUCCESS; 397 398 rc = RTCacheInsert(pData->pCache, pDrvVDAsyncTask); 399 AssertRC(rc); 400 401 return rc; 402 } 403 215 404 216 405 /******************************************************************************* … … 230 419 case PDMINTERFACE_MEDIA: 231 420 return &pData->IMedia; 421 case PDMINTERFACE_MEDIA_ASYNC: 422 return pData->fAsyncIOSupported ? &pData->IMediaAsync : NULL; 423 case PDMINTERFACE_TRANSPORT_ASYNC_PORT: 424 return &pData->ITransportAsyncPort; 232 425 default: 233 426 return NULL; … … 282 475 pData->IMedia.pfnGetUuid = drvvdGetUuid; 283 476 477 /* IMediaAsync */ 478 pData->IMediaAsync.pfnStartRead = drvvdStartRead; 479 pData->IMediaAsync.pfnStartWrite = drvvdStartWrite; 480 481 /* ITransportAsyncPort */ 482 pData->ITransportAsyncPort.pfnTaskCompleteNotify = drvvdTasksCompleteNotify; 483 484 /* Initialize supported VD interfaces. */ 485 pData->VDIErrorCallbacks.cbSize = sizeof(VDINTERFACEERROR); 486 pData->VDIErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR; 487 pData->VDIErrorCallbacks.pfnError = drvvdErrorCallback; 488 489 rc = VDInterfaceCreate(&pData->VDIError, "DrvVD_VDIError", VDINTERFACETYPE_ERROR, 490 &pData->VDIErrorCallbacks, pData, NULL); 491 AssertRC(rc); 492 493 pData->VDIAsyncIOCallbacks.cbSize = sizeof(VDINTERFACEASYNCIO); 494 pData->VDIAsyncIOCallbacks.enmInterface = VDINTERFACETYPE_ASYNCIO; 495 pData->VDIAsyncIOCallbacks.pfnOpen = drvvdAsyncIOOpen; 496 pData->VDIAsyncIOCallbacks.pfnClose = drvvdAsyncIOClose; 497 pData->VDIAsyncIOCallbacks.pfnRead = drvvdAsyncIORead; 498 pData->VDIAsyncIOCallbacks.pfnWrite = drvvdAsyncIOWrite; 499 pData->VDIAsyncIOCallbacks.pfnFlush = drvvdAsyncIOFlush; 500 pData->VDIAsyncIOCallbacks.pfnPrepareRead = drvvdAsyncIOPrepareRead; 501 pData->VDIAsyncIOCallbacks.pfnPrepareWrite = drvvdAsyncIOPrepareWrite; 502 pData->VDIAsyncIOCallbacks.pfnTasksSubmit = drvvdAsyncIOTasksSubmit; 503 504 rc = VDInterfaceCreate(&pData->VDIAsyncIO, "DrvVD_AsyncIO", VDINTERFACETYPE_ASYNCIO, 505 &pData->VDIAsyncIOCallbacks, pData, &pData->VDIError); 506 AssertRC(rc); 507 508 /* Try to attach async media port interface above.*/ 509 pData->pDrvMediaAsyncPort = (PPDMIMEDIAASYNCPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_MEDIA_ASYNC_PORT); 510 511 /* 512 * Attach the async transport driver below of the device above us implements the 513 * async interface. 514 */ 515 if (pData->pDrvMediaAsyncPort) 516 { 517 /* Try to attach the driver. */ 518 PPDMIBASE pBase; 519 520 rc = pDrvIns->pDrvHlp->pfnAttach(pDrvIns, &pBase); 521 if (rc == VERR_PDM_NO_ATTACHED_DRIVER) 522 { 523 /* 524 * Though the device supports async I/O the backend seems to not support it. 525 * Revert to non async I/O. 526 */ 527 pData->pDrvMediaAsyncPort = NULL; 528 } 529 else if (VBOX_FAILURE(rc)) 530 { 531 AssertMsgFailed(("Failed to attach async transport driver below rc=%Vrc\n", rc)); 532 } 533 else 534 { 535 /* Success query the async transport interface. */ 536 pData->pDrvTransportAsync = (PPDMITRANSPORTASYNC)pBase->pfnQueryInterface(pBase, PDMINTERFACE_TRANSPORT_ASYNC); 537 if (!pData->pDrvTransportAsync) 538 { 539 /* Whoops. */ 540 AssertMsgFailed(("Configuration error: No async transport interface below!\n")); 541 return VERR_PDM_MISSING_INTERFACE_ABOVE; 542 543 } 544 } 545 } 546 284 547 /* 285 548 * Validate configuration and find all parent images. … … 325 588 if (VBOX_SUCCESS(rc)) 326 589 { 327 rc = VDCreate( drvvdErrorCallback, pDrvIns, &pData->pDisk);590 rc = VDCreate(&pData->VDIAsyncIO, &pData->pDisk); 328 591 /* Error message is already set correctly. */ 329 592 } … … 388 651 if (fHonorZeroWrites) 389 652 uOpenFlags |= VD_OPEN_FLAGS_HONOR_ZEROES; 653 if (pData->pDrvMediaAsyncPort) 654 uOpenFlags |= VD_OPEN_FLAGS_ASYNC_IO; 655 656 /** Try to open backend in asyc I/O mode first. */ 390 657 rc = VDOpen(pData->pDisk, pszFormat, pszName, uOpenFlags); 658 if (rc == VERR_NOT_SUPPORTED) 659 { 660 /* Seems asxnc I/O is not supported by the backend, open in normal mode. */ 661 uOpenFlags &= ~VD_OPEN_FLAGS_ASYNC_IO; 662 rc = VDOpen(pData->pDisk, pszFormat, pszName, uOpenFlags); 663 } 664 391 665 if (VBOX_SUCCESS(rc)) 392 666 Log(("%s: %d - Opened '%s' in %s mode\n", __FUNCTION__, … … 395 669 else 396 670 { 397 AssertMsgFailed(("Failed to open image '%s' rc=%Vrc\n", pszName, rc)); 398 break; 399 } 671 AssertMsgFailed(("Failed to open image '%s' rc=%Vrc\n", pszName, rc)); 672 break; 673 } 674 675 400 676 MMR3HeapFree(pszName); 401 677 pszName = NULL; … … 419 695 if (VALID_PTR(pszFormat)) 420 696 MMR3HeapFree(pszFormat); 697 } 698 699 /* 700 * Check for async I/O support. Every opened image has to support 701 * it. 702 */ 703 pData->fAsyncIOSupported = true; 704 for (unsigned i = 0; i < VDGetCount(pData->pDisk); i++) 705 { 706 VDBACKENDINFO vdBackendInfo; 707 708 rc = VDBackendInfoSingle(pData->pDisk, i, &vdBackendInfo); 709 AssertRC(rc); 710 711 if (vdBackendInfo.uBackendCaps & VD_CAP_ASYNC) 712 { 713 /* 714 * Backend indicates support for at least some files. 715 * Check if current file is supported with async I/O) 716 */ 717 rc = VDImageIsAsyncIOSupported(pData->pDisk, i, &pData->fAsyncIOSupported); 718 AssertRC(rc); 719 720 /* 721 * Check if current image is supported. 722 * If not we can stop checking because 723 * at least one does not support it. 724 */ 725 if (!pData->fAsyncIOSupported) 726 break; 727 } 728 else 729 { 730 pData->fAsyncIOSupported = false; 731 break; 732 } 733 } 734 735 /* Create cache if async I/O is supported. */ 736 if (pData->fAsyncIOSupported) 737 { 738 rc = RTCacheCreate(&pData->pCache, 0, sizeof(DRVVDASYNCTASK), RTOBJCACHE_PROTECT_INSERT); 739 AssertMsg(RT_SUCCESS(rc), ("Failed to create cache rc=%Vrc\n", rc)); 421 740 } 422 741 … … 435 754 static DECLCALLBACK(void) drvvdDestruct(PPDMDRVINS pDrvIns) 436 755 { 437 LogFlow(("%s:\n", __FUNCTION__));756 int rc; 438 757 PVBOXDISK pData = PDMINS2DATA(pDrvIns, PVBOXDISK); 439 int rc = VDCloseAll(pData->pDisk); 758 LogFlow(("%s:\n", __FUNCTION__)); 759 rc = RTCacheDestroy(pData->pCache); 440 760 AssertRC(rc); 441 761 } … … 487 807 } 488 808 489 809 static DECLCALLBACK(void) drvvdPowerOff(PPDMDRVINS pDrvIns) 810 { 811 LogFlow(("%s:\n", __FUNCTION__)); 812 PVBOXDISK pData = PDMINS2DATA(pDrvIns, PVBOXDISK); 813 814 /* 815 * We must close the disk here to ensure that 816 * the backend closes all files before the 817 * async transport driver is destructed. 818 */ 819 int rc = VDCloseAll(pData->pDisk); 820 AssertRC(rc); 821 } 490 822 491 823 /** … … 523 855 drvvdResume, 524 856 /* pfnDetach */ 525 NULL 857 NULL, 858 /* pfnPowerOff */ 859 drvvdPowerOff 526 860 }; -
trunk/src/VBox/Devices/Storage/RawHDDCore.cpp
r10467 r10715 48 48 49 49 /** Error callback. */ 50 P FNVDERROR pfnError;50 PVDINTERFACE pInterfaceError; 51 51 /** Opaque data for error callback. */ 52 void *pvErrorUser;52 PVDINTERFACEERROR pInterfaceErrorCallbacks; 53 53 54 54 /** Open flags passed by VBoxHD layer. */ … … 84 84 va_list va; 85 85 va_start(va, pszFormat); 86 if (pImage->p fnError)87 pImage->p fnError(pImage->pvErrorUser, rc, RT_SRC_POS_ARGS,88 pszFormat, va);86 if (pImage->pInterfaceError) 87 pImage->pInterfaceErrorCallbacks->pfnError(pImage->pInterfaceError->pvUser, rc, RT_SRC_POS_ARGS, 88 pszFormat, va); 89 89 va_end(va); 90 90 return rc; … … 98 98 int rc; 99 99 RTFILE File; 100 101 if (uOpenFlags & VD_OPEN_FLAGS_ASYNC_IO) 102 return VERR_NOT_SUPPORTED; 100 103 101 104 pImage->uOpenFlags = uOpenFlags; … … 305 308 /** @copydoc VBOXHDDBACKEND::pfnOpen */ 306 309 static int rawOpen(const char *pszFilename, unsigned uOpenFlags, 307 PFNVDERROR pfnError, void *pvErrorUser, 308 void **ppBackendData) 310 PVDINTERFACE pInterfaces, void **ppBackendData) 309 311 { 310 312 LogFlowFunc(("pszFilename=\"%s\" uOpenFlags=%#x ppBackendData=%#p\n", pszFilename, uOpenFlags, ppBackendData)); … … 336 338 pImage->pszFilename = pszFilename; 337 339 pImage->File = NIL_RTFILE; 338 pImage->pfnError = pfnError; 339 pImage->pvErrorUser = pvErrorUser; 340 pImage->pInterfaceError = NULL; 341 pImage->pInterfaceErrorCallbacks = NULL; 342 343 pImage->pInterfaceError = VDGetInterfaceFromList(pInterfaces, VDINTERFACETYPE_ERROR); 344 if (pImage->pInterfaceError) 345 pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError->pCallbacks); 340 346 341 347 rc = rawOpenImage(pImage, uOpenFlags); … … 356 362 unsigned uOpenFlags, PFNVMPROGRESS pfnProgress, 357 363 void *pvUser, unsigned uPercentStart, 358 unsigned uPercentSpan, P FNVDERROR pfnError,359 void * pvErrorUser, void **ppBackendData)360 { 361 LogFlowFunc(("pszFilename=\"%s\" enmType=%d cbSize=%llu uImageFlags=%#x pszComment=\"%s\" pPCHSGeometry=%#p pLCHSGeometry=%#p uOpenFlags=%#x pfnProgress=%#p pvUser=%#p uPercentStart=%u uPercentSpan=%u p fnError=%#p pvErrorUser=%#p ppBackendData=%#p", pszFilename, enmType, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, uOpenFlags, pfnProgress, pvUser, uPercentStart, uPercentSpan, pfnError, pvErrorUser, ppBackendData));364 unsigned uPercentSpan, PVDINTERFACE pInterfaces, 365 void **ppBackendData) 366 { 367 LogFlowFunc(("pszFilename=\"%s\" enmType=%d cbSize=%llu uImageFlags=%#x pszComment=\"%s\" pPCHSGeometry=%#p pLCHSGeometry=%#p uOpenFlags=%#x pfnProgress=%#p pvUser=%#p uPercentStart=%u uPercentSpan=%u pInterfaces=%#p ppBackendData=%#p", pszFilename, enmType, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, uOpenFlags, pfnProgress, pvUser, uPercentStart, uPercentSpan, pInterfaces, ppBackendData)); 362 368 int rc; 363 369 PRAWIMAGE pImage; … … 389 395 pImage->pszFilename = pszFilename; 390 396 pImage->File = NIL_RTFILE; 391 pImage->pfnError = pfnError; 392 pImage->pvErrorUser = pvErrorUser; 397 398 pImage->pInterfaceError = VDGetInterfaceFromList(pInterfaces, VDINTERFACETYPE_ERROR); 399 if (pImage->pInterfaceError) 400 pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError); 401 393 402 394 403 rc = rawCreateImage(pImage, enmType, cbSize, uImageFlags, pszComment, … … 987 996 } 988 997 998 static int rawGetTimeStamp(void *pvBackendData, PRTTIMESPEC pTimeStamp) 999 { 1000 int rc = VERR_NOT_IMPLEMENTED; 1001 LogFlow(("%s: returned %Vrc\n", __FUNCTION__, rc)); 1002 return rc; 1003 } 1004 1005 static int rawGetParentTimeStamp(void *pvBackendData, PRTTIMESPEC pTimeStamp) 1006 { 1007 int rc = VERR_NOT_IMPLEMENTED; 1008 LogFlow(("%s: returned %Vrc\n", __FUNCTION__, rc)); 1009 return rc; 1010 } 1011 1012 static int rawSetParentTimeStamp(void *pvBackendData, PCRTTIMESPEC pTimeStamp) 1013 { 1014 int rc = VERR_NOT_IMPLEMENTED; 1015 LogFlow(("%s: returned %Vrc\n", __FUNCTION__, rc)); 1016 return rc; 1017 } 1018 1019 static int rawGetParentFilename(void *pvBackendData, char **ppszParentFilename) 1020 { 1021 int rc = VERR_NOT_IMPLEMENTED; 1022 LogFlow(("%s: returned %Vrc\n", __FUNCTION__, rc)); 1023 return rc; 1024 } 1025 1026 static int rawSetParentFilename(void *pvBackendData, const char *pszParentFilename) 1027 { 1028 int rc = VERR_NOT_IMPLEMENTED; 1029 LogFlow(("%s: returned %Vrc\n", __FUNCTION__, rc)); 1030 return rc; 1031 } 1032 1033 static bool rawIsAsyncIOSupported(void *pvBackendData) 1034 { 1035 return false; 1036 } 1037 1038 static int rawAsyncRead(void *pvBackendData, uint64_t uOffset, size_t cbRead, 1039 PPDMDATASEG paSeg, unsigned cSeg, void *pvUser) 1040 { 1041 int rc = VERR_NOT_IMPLEMENTED; 1042 LogFlowFunc(("returns %Vrc\n", rc)); 1043 return rc; 1044 } 1045 1046 static int rawAsyncWrite(void *pvBackendData, uint64_t uOffset, size_t cbWrite, 1047 PPDMDATASEG paSeg, unsigned cSeg, void *pvUser) 1048 { 1049 int rc = VERR_NOT_IMPLEMENTED; 1050 LogFlowFunc(("returns %Vrc\n", rc)); 1051 return rc; 1052 } 989 1053 990 1054 VBOXHDDBACKEND g_RawBackend = … … 1055 1119 rawSetParentModificationUuid, 1056 1120 /* pfnDump */ 1057 rawDump 1121 rawDump, 1122 /* pfnGetTimeStamp */ 1123 rawGetTimeStamp, 1124 /* pfnGetParentTimeStamp */ 1125 rawGetParentTimeStamp, 1126 /* pfnSetParentTimeStamp */ 1127 rawSetParentTimeStamp, 1128 /* pfnGetParentFilename */ 1129 rawGetParentFilename, 1130 /* pfnSetParentFilename */ 1131 rawSetParentFilename, 1132 /* pfnIsAsyncIOSupported */ 1133 rawIsAsyncIOSupported, 1134 /* pfnAsyncRead */ 1135 rawAsyncRead, 1136 /* pfnAsyncWrite */ 1137 rawAsyncWrite 1058 1138 }; 1139 -
trunk/src/VBox/Devices/Storage/VBoxHDD-new.cpp
r10540 r10715 108 108 PDMMEDIAGEOMETRY LCHSGeometry; 109 109 110 /** Error message processing callback. */ 111 PFNVDERROR pfnError; 112 /** Opaque data for error callback. */ 113 void *pvErrorUser; 110 /** List of interfaces the caller supports. */ 111 PVDINTERFACE pInterfaces; 112 /** Pointer to the common interface structure for error reporting. */ 113 PVDINTERFACE pInterfaceError; 114 /** Pointer to the error interface we use if available. */ 115 PVDINTERFACEERROR pInterfaceErrorCallbacks; 114 116 }; 115 117 … … 148 150 va_list va; 149 151 va_start(va, pszFormat); 150 if (pDisk->p fnError)151 pDisk->p fnError(pDisk->pvErrorUser, rc, RT_SRC_POS_ARGS, pszFormat, va);152 if (pDisk->pInterfaceErrorCallbacks) 153 pDisk->pInterfaceErrorCallbacks->pfnError(pDisk->pInterfaceError->pvUser, rc, RT_SRC_POS_ARGS, pszFormat, va); 152 154 va_end(va); 153 155 return rc; … … 761 763 } 762 764 765 /** 766 * Lists the capablities of a backend indentified by its name. 767 * Free all returned names with RTStrFree() when you no longer need them. 768 * 769 * @returns VBox status code. 770 * @param pszBackend The backend name. 771 * @param pEntries Pointer to an entry. 772 */ 773 VBOXDDU_DECL(int) VDBackendInfoOne(const char *pszBackend, PVDBACKENDINFO pEntry) 774 { 775 return VERR_NOT_IMPLEMENTED; 776 } 763 777 764 778 /** … … 767 781 * 768 782 * @returns VBox status code. 769 * @param pfnError Callback for setting extended error information. 770 * @param pvErrorUser Opaque parameter for pfnError. 783 * @param pInterfaces Pointer to the first supported interface. 771 784 * @param ppDisk Where to store the reference to HDD container. 772 785 */ 773 VBOXDDU_DECL(int) VDCreate(PFNVDERROR pfnError, void *pvErrorUser, 774 PVBOXHDD *ppDisk) 786 VBOXDDU_DECL(int) VDCreate(PVDINTERFACE pInterfaces, PVBOXHDD *ppDisk) 775 787 { 776 788 int rc = VINF_SUCCESS; 777 789 PVBOXHDD pDisk = NULL; 778 790 779 LogFlowFunc(("p fnError=%#p pvErrorUser=%#p\n", pfnError, pvErrorUser));791 LogFlowFunc(("pInterfaces=%#p\n", pInterfaces)); 780 792 do 781 793 { 782 794 /* Check arguments. */ 783 AssertMsgBreakStmt(VALID_PTR(pfnError),784 ("pfnError=%#p\n", pfnError),785 rc = VERR_INVALID_PARAMETER);786 795 AssertMsgBreakStmt(VALID_PTR(ppDisk), 787 796 ("ppDisk=%#p\n", ppDisk), … … 802 811 pDisk->LCHSGeometry.cHeads = 0; 803 812 pDisk->LCHSGeometry.cSectors = 0; 804 pDisk->pfnError = pfnError; 805 pDisk->pvErrorUser = pvErrorUser; 813 pDisk->pInterfaces = pInterfaces; 814 pDisk->pInterfaceError = NULL; 815 pDisk->pInterfaceErrorCallbacks = NULL; 816 817 pDisk->pInterfaceError = VDGetInterfaceFromList(pInterfaces, VDINTERFACETYPE_ERROR); 818 if (pDisk->pInterfaceError) 819 pDisk->pInterfaceErrorCallbacks = VDGetInterfaceError(pDisk->pInterfaceError->pCallbacks); 806 820 *ppDisk = pDisk; 807 821 } … … 1078 1092 rc = pImage->Backend->pfnOpen(pImage->pszFilename, 1079 1093 uOpenFlags & ~VD_OPEN_FLAGS_HONOR_SAME, 1080 pDisk->p fnError, pDisk->pvErrorUser,1094 pDisk->pInterfaces, 1081 1095 &pImage->pvBackendData); 1082 1096 /* If the open in read-write mode failed, retry in read-only mode. */ … … 1092 1106 (uOpenFlags & ~VD_OPEN_FLAGS_HONOR_SAME) 1093 1107 | VD_OPEN_FLAGS_READONLY, 1094 pDisk->p fnError, pDisk->pvErrorUser,1108 pDisk->pInterfaces, 1095 1109 &pImage->pvBackendData); 1096 1110 if (VBOX_FAILURE(rc)) … … 1342 1356 uOpenFlags & ~VD_OPEN_FLAGS_HONOR_SAME, 1343 1357 pfnProgress, pvUser, 0, 99, 1344 pDisk->p fnError, pDisk->pvErrorUser,1358 pDisk->pInterfaces, 1345 1359 &pImage->pvBackendData); 1346 1360 … … 1515 1529 uOpenFlags & ~VD_OPEN_FLAGS_HONOR_SAME, 1516 1530 pfnProgress, pvUser, 0, 99, 1517 pDisk->p fnError, pDisk->pvErrorUser,1531 pDisk->pInterfaces, 1518 1532 &pImage->pvBackendData); 1519 1533 … … 2471 2485 } while (0); 2472 2486 2473 LogFlowFunc(("%s: %Vrc (PCHS=%u/%u/%u)\n", rc,2487 LogFlowFunc(("%s: %Vrc (PCHS=%u/%u/%u)\n", __FUNCTION__, rc, 2474 2488 pDisk->PCHSGeometry.cCylinders, pDisk->PCHSGeometry.cHeads, 2475 2489 pDisk->PCHSGeometry.cSectors)); … … 2617 2631 } while (0); 2618 2632 2619 LogFlowFunc((" %s: %Vrc (LCHS=%u/%u/%u)\n", rc,2633 LogFlowFunc((": %Vrc (LCHS=%u/%u/%u)\n", rc, 2620 2634 pDisk->LCHSGeometry.cCylinders, pDisk->LCHSGeometry.cHeads, 2621 2635 pDisk->LCHSGeometry.cSectors)); … … 2800 2814 } 2801 2815 2816 2817 /** 2818 * List the capabilities of image backend in HDD container. 2819 * 2820 * @returns VBox status code. 2821 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 2822 * @param pDisk Pointer to the HDD container. 2823 * @param nImage Image number, counts from 0. 0 is always base image of container. 2824 * @param pbackendInfo Where to store the backend information. 2825 */ 2826 VBOXDDU_DECL(int) VDBackendInfoSingle(PVBOXHDD pDisk, unsigned nImage, 2827 PVDBACKENDINFO pBackendInfo) 2828 { 2829 int rc = VINF_SUCCESS; 2830 2831 LogFlowFunc(("pDisk=%#p nImage=%u penmType=%#p\n", 2832 pDisk, nImage, pBackendInfo)); 2833 do 2834 { 2835 /* sanity check */ 2836 AssertPtrBreakStmt(pDisk, rc = VERR_INVALID_PARAMETER); 2837 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 2838 2839 /* Check arguments. */ 2840 AssertMsgBreakStmt(VALID_PTR(pBackendInfo), 2841 ("pBackendInfo=%#p\n", pBackendInfo), 2842 rc = VERR_INVALID_PARAMETER); 2843 2844 PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage); 2845 AssertPtrBreakStmt(pImage, rc = VERR_VDI_IMAGE_NOT_FOUND); 2846 2847 if ( pImage->enmImageType >= VD_IMAGE_TYPE_FIRST 2848 && pImage->enmImageType <= VD_IMAGE_TYPE_DIFF) 2849 { 2850 pBackendInfo->pszBackend = RTStrDup(pImage->Backend->pszBackendName); 2851 pBackendInfo->uBackendCaps = pImage->Backend->uBackendCaps; 2852 rc = VINF_SUCCESS; 2853 } 2854 else 2855 rc = VERR_VDI_INVALID_TYPE; 2856 } while (0); 2857 2858 LogFlowFunc(("returns %Vrc\n", rc)); 2859 return rc; 2860 } 2861 2802 2862 /** 2803 2863 * Get flags of image in HDD container. … … 3306 3366 } 3307 3367 3368 /** 3369 * Query if asynchronous operations are supported for this disk. 3370 * 3371 * @returns VBox status code. 3372 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 3373 * @param pDisk Pointer to the HDD container. 3374 * @param nImage Image number, counts from 0. 0 is always base image of container. 3375 * @param pfAIOSupported Where to store if async IO is supported. 3376 */ 3377 VBOXDDU_DECL(int) VDImageIsAsyncIOSupported(PVBOXHDD pDisk, unsigned nImage, bool *pfAIOSupported) 3378 { 3379 int rc = VINF_SUCCESS; 3380 3381 LogFlowFunc(("pDisk=%#p nImage=%u pfAIOSupported=%#p\n", pDisk, nImage, pfAIOSupported)); 3382 do 3383 { 3384 /* sanity check */ 3385 AssertPtrBreakStmt(pDisk, rc = VERR_INVALID_PARAMETER); 3386 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 3387 3388 /* Check arguments. */ 3389 AssertMsgBreakStmt(VALID_PTR(pfAIOSupported), 3390 ("pfAIOSupported=%#p\n", pfAIOSupported), 3391 rc = VERR_INVALID_PARAMETER); 3392 3393 PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage); 3394 AssertPtrBreakStmt(pImage, rc = VERR_VDI_IMAGE_NOT_FOUND); 3395 3396 if (pImage->Backend->uBackendCaps & VD_CAP_ASYNC) 3397 *pfAIOSupported = pImage->Backend->pfnIsAsyncIOSupported(pImage->pvBackendData); 3398 else 3399 *pfAIOSupported = false; 3400 } while (0); 3401 3402 LogFlowFunc(("returns %Vrc, fAIOSupported=%u\n", rc, *pfAIOSupported)); 3403 return rc; 3404 } 3405 3406 /** 3407 * Start a asynchronous read request. 3408 * 3409 * @returns VBox status code. 3410 * @param pDisk Pointer to the HDD container. 3411 * @param uOffset The offset of the virtual disk to read from. 3412 * @param cbRead How many bytes to read. 3413 * @param paSeg Pointer to an array of segments. 3414 * @param cSeg Number of segments in the array. 3415 * @param pvUser User data which is passed on completion 3416 */ 3417 VBOXDDU_DECL(int) VDAsyncRead(PVBOXHDD pDisk, uint64_t uOffset, size_t cbRead, 3418 PPDMDATASEG paSeg, unsigned cSeg, 3419 void *pvUser) 3420 { 3421 int rc = VERR_VDI_BLOCK_FREE; 3422 3423 LogFlowFunc(("pDisk=%#p uOffset=%llu paSeg=%p cSeg=%u cbRead=%zu\n", 3424 pDisk, uOffset, paSeg, cSeg, cbRead)); 3425 do 3426 { 3427 /* sanity check */ 3428 AssertPtrBreakStmt(pDisk, rc = VERR_INVALID_PARAMETER); 3429 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 3430 3431 /* Check arguments. */ 3432 AssertMsgBreakStmt(cbRead, 3433 ("cbRead=%zu\n", cbRead), 3434 rc = VERR_INVALID_PARAMETER); 3435 AssertMsgBreakStmt(uOffset + cbRead <= pDisk->cbSize, 3436 ("uOffset=%llu cbRead=%zu pDisk->cbSize=%llu\n", 3437 uOffset, cbRead, pDisk->cbSize), 3438 rc = VERR_INVALID_PARAMETER); 3439 AssertMsgBreakStmt(VALID_PTR(paSeg), 3440 ("paSeg=%#p\n", paSeg), 3441 rc = VERR_INVALID_PARAMETER); 3442 AssertMsgBreakStmt(cSeg, 3443 ("cSeg=%zu\n", cSeg), 3444 rc = VERR_INVALID_PARAMETER); 3445 3446 3447 PVDIMAGE pImage = pDisk->pLast; 3448 AssertPtrBreakStmt(pImage, rc = VERR_VDI_NOT_OPENED); 3449 3450 /* @todo: This does not work for images which do not have all meta data in memory. */ 3451 for (PVDIMAGE pCurrImage = pImage; 3452 pCurrImage != NULL && rc == VERR_VDI_BLOCK_FREE; 3453 pCurrImage = pCurrImage->pPrev) 3454 { 3455 rc = pCurrImage->Backend->pfnAsyncRead(pCurrImage->pvBackendData, 3456 uOffset, cbRead, paSeg, cSeg, 3457 pvUser); 3458 } 3459 3460 /* No image in the chain contains the data for the block. */ 3461 if (rc == VERR_VDI_BLOCK_FREE) 3462 { 3463 for (unsigned i = 0; i < cSeg && (cbRead > 0); i++) 3464 { 3465 memset(paSeg[i].pvSeg, '\0', paSeg[i].cbSeg); 3466 cbRead -= paSeg[i].cbSeg; 3467 } 3468 /* Request finished without the need to enqueue a async I/O request. Tell caller. */ 3469 rc = VINF_VDI_ASYNC_IO_FINISHED; 3470 } 3471 3472 } while (0); 3473 3474 LogFlowFunc(("returns %Vrc\n", rc)); 3475 return rc; 3476 } 3477 3478 3479 /** 3480 * Start a asynchronous write request. 3481 * 3482 * @returns VBox status code. 3483 * @param pDisk Pointer to the HDD container. 3484 * @param uOffset The offset of the virtual disk to write to. 3485 * @param cbWrtie How many bytes to write. 3486 * @param paSeg Pointer to an array of segments. 3487 * @param cSeg Number of segments in the array. 3488 * @param pvUser User data which is passed on completion. 3489 */ 3490 VBOXDDU_DECL(int) VDAsyncWrite(PVBOXHDD pDisk, uint64_t uOffset, size_t cbWrite, 3491 PPDMDATASEG paSeg, unsigned cSeg, 3492 void *pvUser) 3493 { 3494 int rc; 3495 3496 LogFlowFunc(("pDisk=%#p uOffset=%llu paSeg=%p cSeg=%u cbWrite=%zu\n", 3497 pDisk, uOffset, paSeg, cSeg, cbWrite)); 3498 do 3499 { 3500 /* sanity check */ 3501 AssertPtrBreakStmt(pDisk, rc = VERR_INVALID_PARAMETER); 3502 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 3503 3504 /* Check arguments. */ 3505 AssertMsgBreakStmt(cbWrite, 3506 ("cbWrite=%zu\n", cbWrite), 3507 rc = VERR_INVALID_PARAMETER); 3508 AssertMsgBreakStmt(uOffset + cbWrite <= pDisk->cbSize, 3509 ("uOffset=%llu cbWrite=%zu pDisk->cbSize=%llu\n", 3510 uOffset, cbWrite, pDisk->cbSize), 3511 rc = VERR_INVALID_PARAMETER); 3512 AssertMsgBreakStmt(VALID_PTR(paSeg), 3513 ("paSeg=%#p\n", paSeg), 3514 rc = VERR_INVALID_PARAMETER); 3515 AssertMsgBreakStmt(cSeg, 3516 ("cSeg=%zu\n", cSeg), 3517 rc = VERR_INVALID_PARAMETER); 3518 3519 3520 PVDIMAGE pImage = pDisk->pLast; 3521 AssertPtrBreakStmt(pImage, rc = VERR_VDI_NOT_OPENED); 3522 3523 vdSetModifiedFlag(pDisk); 3524 rc = pImage->Backend->pfnAsyncWrite(pImage->pvBackendData, 3525 uOffset, cbWrite, 3526 paSeg, cSeg, pvUser); 3527 } while (0); 3528 3529 LogFlowFunc(("returns %Vrc\n", rc)); 3530 return rc; 3531 3532 } 3533 -
trunk/src/VBox/Devices/Storage/VBoxHDD-newInternal.h
r9734 r10715 71 71 * unchanged during the lifetime of this image. 72 72 * @param uOpenFlags Image file open mode, see VD_OPEN_FLAGS_* constants. 73 * @param pfnError Callback for setting extended error information. 74 * @param pvErrorUser Opaque parameter for pfnError. 73 * @param pInterfaces Pointer to the first element of supported interfaces of the caller. 75 74 * @param ppvBackendData Opaque state data for this image. 76 75 */ 77 DECLR3CALLBACKMEMBER(int, pfnOpen, (const char *pszFilename, unsigned uOpenFlags, PFNVDERROR pfnError, void *pvErrorUser, void **ppvBackendData)); 76 DECLR3CALLBACKMEMBER(int, pfnOpen, (const char *pszFilename, unsigned uOpenFlags, 77 PVDINTERFACE pInterfaces, void **ppvBackendData)); 78 78 79 79 /** … … 94 94 * @param uPercentStart Starting value for progress percentage. 95 95 * @param uPercentSpan Span for varying progress percentage. 96 * @param pfnError Callback for setting extended error information. 97 * @param pvErrorUser Opaque parameter for pfnError. 96 * @param pInterfaces Pointer to the supported interfaces of the caller. 98 97 * @param ppvBackendData Opaque state data for this image. 99 98 */ 100 DECLR3CALLBACKMEMBER(int, pfnCreate, (const char *pszFilename, VDIMAGETYPE enmType, uint64_t cbSize, unsigned uImageFlags, const char *pszComment, PCPDMMEDIAGEOMETRY pPCHSGeometry, PCPDMMEDIAGEOMETRY pLCHSGeometry, unsigned uOpenFlags, PFNVMPROGRESS pfnProgress, void *pvUser, unsigned uPercentStart, unsigned uPercentSpan, P FNVDERROR pfnError, void *pvErrorUser, void **ppvBackendData));99 DECLR3CALLBACKMEMBER(int, pfnCreate, (const char *pszFilename, VDIMAGETYPE enmType, uint64_t cbSize, unsigned uImageFlags, const char *pszComment, PCPDMMEDIAGEOMETRY pPCHSGeometry, PCPDMMEDIAGEOMETRY pLCHSGeometry, unsigned uOpenFlags, PFNVMPROGRESS pfnProgress, void *pvUser, unsigned uPercentStart, unsigned uPercentSpan, PVDINTERFACE pInterfaces, void **ppvBackendData)); 101 100 102 101 /** … … 421 420 DECLR3CALLBACKMEMBER(int, pfnSetParentFilename, (void *pvBackendData, const char *pszParentFilename)); 422 421 422 /** 423 * Return whether asynchronous I/O operations are supported for this image. 424 * 425 * @returns true if asynchronous I/O is supported 426 * false otherwise. 427 * @param pvBackendData Opaque state data for this image. 428 */ 429 DECLR3CALLBACKMEMBER(bool, pfnIsAsyncIOSupported, (void *pvBackendData)); 430 431 /** 432 * Start an asynchronous read request. 433 * 434 * @returns VBox status code. 435 * @param pvBackendData Opaque state data for this image. 436 * @param uOffset The offset of the virtual disk to read from. 437 * @param cbRead How many bytes to read. 438 * @param paSeg Pointer to the segment array. 439 * @param cSeg Number of segments. 440 * @param pvUser Opaque user data. 441 */ 442 DECLR3CALLBACKMEMBER(int, pfnAsyncRead, (void *pvBackendData, uint64_t uOffset, size_t cbRead, 443 PPDMDATASEG paSeg, unsigned cSeg, void *pvUser)); 444 445 /** 446 * Start an asynchronous write request. 447 * 448 * @returns VBox status code. 449 * @param pvBackendData Opaque state data for this image. 450 * @param uOffset The offset of the virtual disk to write to. 451 * @param cbWrite How many bytes to write. 452 * @param paSeg Pointer to the segment array. 453 * @param cSeg Number of segments. 454 * @param pvUser Oaque user data- 455 */ 456 DECLR3CALLBACKMEMBER(int, pfnAsyncWrite, (void *pvBackendData, uint64_t uOffset, size_t cbWrite, 457 PPDMDATASEG paSeg, unsigned cSeg, void *pvUser)); 458 423 459 } VBOXHDDBACKEND; 424 460 -
trunk/src/VBox/Devices/Storage/VDICore.h
r8170 r10715 562 562 /** Physical geometry of this image (never actually stored). */ 563 563 PDMMEDIAGEOMETRY PCHSGeometry; 564 /** Error callback. */565 P FNVDERROR pfnError;566 /** Opaque data for error callback. */567 void *pvErrorUser;564 /** Error interface. */ 565 PVDINTERFACE pInterfaceError; 566 /** Error interface callback table. */ 567 PVDINTERFACEERROR pInterfaceErrorCallbacks; 568 568 #endif /* VBOX_VDICORE_VD */ 569 569 } VDIIMAGEDESC, *PVDIIMAGEDESC; -
trunk/src/VBox/Devices/Storage/VDIHDDCore.cpp
r10539 r10715 63 63 va_list va; 64 64 va_start(va, pszFormat); 65 if (pImage->pfnError) 66 pImage->pfnError(pImage->pvErrorUser, rc, RT_SRC_POS_ARGS, 67 pszFormat, va); 65 if (pImage->pInterfaceError && pImage->pInterfaceErrorCallbacks) 66 pImage->pInterfaceErrorCallbacks->pfnError(pImage->pInterfaceError->pvUser, 67 rc, RT_SRC_POS_ARGS, 68 pszFormat, va); 68 69 va_end(va); 69 70 return rc; … … 508 509 int rc; 509 510 RTFILE File; 511 512 if (uOpenFlags & VD_OPEN_FLAGS_ASYNC_IO) 513 return VERR_NOT_SUPPORTED; 510 514 511 515 pImage->uOpenFlags = uOpenFlags; … … 731 735 pImage->File = NIL_RTFILE; 732 736 pImage->paBlocks = NULL; 733 pImage->p fnError = NULL;734 pImage->p vErrorUser= NULL;737 pImage->pInterfaceError = NULL; 738 pImage->pInterfaceErrorCallbacks = NULL; 735 739 736 740 rc = vdiOpenImage(pImage, VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_READONLY); … … 744 748 /** @copydoc VBOXHDDBACKEND::pfnOpen */ 745 749 static int vdiOpen(const char *pszFilename, unsigned uOpenFlags, 746 P FNVDERROR pfnError, void *pvErrorUser,750 PVDINTERFACE pInterfaces, 747 751 void **ppBackendData) 748 752 { … … 775 779 pImage->File = NIL_RTFILE; 776 780 pImage->paBlocks = NULL; 777 pImage->pfnError = pfnError; 778 pImage->pvErrorUser = pvErrorUser; 781 pImage->pInterfaceError = NULL; 782 pImage->pInterfaceErrorCallbacks = NULL; 783 784 pImage->pInterfaceError = VDGetInterfaceFromList(pInterfaces, VDINTERFACETYPE_ERROR); 785 if (pImage->pInterfaceError) 786 pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError->pCallbacks); 779 787 780 788 rc = vdiOpenImage(pImage, uOpenFlags); … … 795 803 unsigned uOpenFlags, PFNVMPROGRESS pfnProgress, 796 804 void *pvUser, unsigned uPercentStart, 797 unsigned uPercentSpan, P FNVDERROR pfnError,798 void * pvErrorUser, void **ppBackendData)799 { 800 LogFlowFunc(("pszFilename=\"%s\" enmType=%d cbSize=%llu uImageFlags=%#x pszComment=\"%s\" pPCHSGeometry=%#p pLCHSGeometry=%#p uOpenFlags=%#x pfnProgress=%#p pvUser=%#p uPercentStart=%u uPercentSpan=%u p fnError=%#p pvErrorUser=%#p ppBackendData=%#p", pszFilename, enmType, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, uOpenFlags, pfnProgress, pvUser, uPercentStart, uPercentSpan, pfnError, pvErrorUser, ppBackendData));805 unsigned uPercentSpan, PVDINTERFACE pInterfaces, 806 void **ppBackendData) 807 { 808 LogFlowFunc(("pszFilename=\"%s\" enmType=%d cbSize=%llu uImageFlags=%#x pszComment=\"%s\" pPCHSGeometry=%#p pLCHSGeometry=%#p uOpenFlags=%#x pfnProgress=%#p pvUser=%#p uPercentStart=%u uPercentSpan=%u pInterfaces=%#p ppBackendData=%#p", pszFilename, enmType, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, uOpenFlags, pfnProgress, pvUser, uPercentStart, uPercentSpan, pInterfaces, ppBackendData)); 801 809 int rc; 802 810 PVDIIMAGEDESC pImage; … … 831 839 pImage->File = NIL_RTFILE; 832 840 pImage->paBlocks = NULL; 833 pImage->p fnError = pfnError;834 pImage->p vErrorUser = pvErrorUser;841 pImage->pInterfaceError = NULL; 842 pImage->pInterfaceErrorCallbacks = NULL; 835 843 836 844 rc = vdiCreateImage(pImage, enmType, cbSize, uImageFlags, pszComment, … … 1753 1761 return rc; 1754 1762 } 1763 1764 static bool vdiIsAsyncIOSupported(void *pvBackendData) 1765 { 1766 return false; 1767 } 1768 1769 static int vdiAsyncRead(void *pvBackendData, uint64_t uOffset, size_t cbRead, 1770 PPDMDATASEG paSeg, unsigned cSeg, void *pvUser) 1771 { 1772 int rc = VERR_NOT_IMPLEMENTED; 1773 LogFlowFunc(("returns %Vrc\n", rc)); 1774 return rc; 1775 } 1776 1777 static int vdiAsyncWrite(void *pvBackendData, uint64_t uOffset, size_t cbWrite, 1778 PPDMDATASEG paSeg, unsigned cSeg, void *pvUser) 1779 { 1780 int rc = VERR_NOT_IMPLEMENTED; 1781 LogFlowFunc(("returns %Vrc\n", rc)); 1782 return rc; 1783 } 1784 1755 1785 1756 1786 VBOXHDDBACKEND g_VDIBackend = … … 1832 1862 vdiGetParentFilename, 1833 1863 /* pfnSetParentFilename */ 1834 vdiSetParentFilename 1864 vdiSetParentFilename, 1865 /* pfnIsAsyncIOSupported */ 1866 vdiIsAsyncIOSupported, 1867 /* pfnAsyncRead */ 1868 vdiAsyncRead, 1869 /* pfnAsyncWrite */ 1870 vdiAsyncWrite 1835 1871 }; 1836 1872 -
trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp
r10539 r10715 179 179 } VMDKACCESS, *PVMDKACCESS; 180 180 181 /** Forward declaration for PVMDKIMAGE. */ 182 typedef struct VMDKIMAGE *PVMDKIMAGE; 183 184 /** 185 * Extents files entry. Used for opening a particular file only once. 186 */ 187 typedef struct VMDKFILE 188 { 189 /** Pointer to filename. Local copy. */ 190 const char *pszFilename; 191 /** File open flags for consistency checking. */ 192 unsigned fOpen; 193 /** File handle. */ 194 RTFILE File; 195 /** Handle for asnychronous access if requested.*/ 196 void *pStorage; 197 /** Flag whether to use File or pStorage. */ 198 bool fAsyncIO; 199 /** Reference counter. */ 200 unsigned uReferences; 201 /** Flag whether the file should be deleted on last close. */ 202 bool fDelete; 203 /** Pointer to the image we belong to. */ 204 PVMDKIMAGE pImage; 205 /** Pointer to next file descriptor. */ 206 struct VMDKFILE *pNext; 207 /** Pointer to the previous file descriptor. */ 208 struct VMDKFILE *pPrev; 209 } VMDKFILE, *PVMDKFILE; 210 181 211 /** 182 212 * VMDK extent data structure. … … 185 215 { 186 216 /** File handle. */ 187 RTFILEFile;217 PVMDKFILE pFile; 188 218 /** Base name of the image extent. */ 189 219 const char *pszBasename; … … 239 269 240 270 /** 241 * Extents files entry. Used for opening a particular file only once.242 */243 typedef struct VMDKFILE244 {245 /** Pointer to filename. Local copy. */246 const char *pszFilename;247 /** File open flags for consistency checking. */248 unsigned fOpen;249 /** File handle. */250 RTFILE File;251 /** Reference counter. */252 unsigned uReferences;253 /** Flag whether the file should be deleted on last close. */254 bool fDelete;255 /** Pointer to next file descriptor. Singly linked list is fast enough. */256 struct VMDKFILE *pNext;257 } VMDKFILE, *PVMDKFILE;258 259 /**260 271 * Grain table cache size. Allocated per image. 261 272 */ … … 346 357 const char *pszFilename; 347 358 /** Descriptor file if applicable. */ 348 RTFILE File; 349 350 /** Error callback. */ 351 PFNVDERROR pfnError; 352 /** Opaque data for error callback. */ 353 void *pvErrorUser; 359 PVMDKFILE pFile; 360 361 /** Error interface. */ 362 PVDINTERFACE pInterfaceError; 363 /** Error interface callbacks. */ 364 PVDINTERFACEERROR pInterfaceErrorCallbacks; 365 366 /** Async I/O interface. */ 367 PVDINTERFACE pInterfaceAsyncIO; 368 /** Async I/O interface callbacks. */ 369 PVDINTERFACEASYNCIO pInterfaceAsyncIOCallbacks; 370 /** 371 * Pointer to an array of task handles for task submission. 372 * This is an optimization because the task number to submit is not known 373 * and allocating/freeing an array in the read/write functions every time 374 * is too expensive. 375 */ 376 void **apTask; 377 /** Entries available in the task handle array. */ 378 unsigned cTask; 354 379 355 380 /** Open flags passed by VBoxHD layer. */ … … 382 407 /** Parsed descriptor file content. */ 383 408 VMDKDESCRIPTOR Descriptor; 384 } VMDKIMAGE , *PVMDKIMAGE;409 } VMDKIMAGE; 385 410 386 411 … … 408 433 va_list va; 409 434 va_start(va, pszFormat); 410 if (pImage->p fnError)411 pImage->p fnError(pImage->pvErrorUser, rc, RT_SRC_POS_ARGS,412 pszFormat, va);435 if (pImage->pInterfaceError && pImage->pInterfaceErrorCallbacks) 436 pImage->pInterfaceErrorCallbacks->pfnError(pImage->pInterfaceError->pvUser, rc, RT_SRC_POS_ARGS, 437 pszFormat, va); 413 438 va_end(va); 414 439 return rc; … … 419 444 * is only opened once - anything else can cause locking problems). 420 445 */ 421 static int vmdkFileOpen(PVMDKIMAGE pImage, P RTFILE pFile,422 const char *pszFilename, unsigned fOpen )446 static int vmdkFileOpen(PVMDKIMAGE pImage, PVMDKFILE *ppVmdkFile, 447 const char *pszFilename, unsigned fOpen, bool fAsyncIO) 423 448 { 424 449 int rc = VINF_SUCCESS; … … 433 458 Assert(fOpen == pVmdkFile->fOpen); 434 459 pVmdkFile->uReferences++; 435 *pFile = pVmdkFile->File; 460 461 *ppVmdkFile = pVmdkFile; 462 436 463 return rc; 437 464 } … … 442 469 if (!VALID_PTR(pVmdkFile)) 443 470 { 444 *p File = NIL_RTFILE;471 *ppVmdkFile = NULL; 445 472 return VERR_NO_MEMORY; 446 473 } … … 450 477 { 451 478 RTMemFree(pVmdkFile); 452 *p File = NIL_RTFILE;479 *ppVmdkFile = NULL; 453 480 return VERR_NO_MEMORY; 454 481 } 455 482 pVmdkFile->fOpen = fOpen; 456 rc = RTFileOpen(&pVmdkFile->File, pszFilename, fOpen); 483 if ((pImage->uOpenFlags & VD_OPEN_FLAGS_ASYNC_IO) && (fAsyncIO)) 484 { 485 rc = pImage->pInterfaceAsyncIOCallbacks->pfnOpen(pImage->pInterfaceAsyncIO->pvUser, 486 pszFilename, 487 pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY 488 ? true 489 : false, 490 &pVmdkFile->pStorage); 491 pVmdkFile->fAsyncIO = true; 492 } 493 else 494 { 495 rc = RTFileOpen(&pVmdkFile->File, pszFilename, fOpen); 496 pVmdkFile->fAsyncIO = false; 497 } 457 498 if (VBOX_SUCCESS(rc)) 458 499 { 459 500 pVmdkFile->uReferences = 1; 501 pVmdkFile->pImage = pImage; 460 502 pVmdkFile->pNext = pImage->pFiles; 503 if (pImage->pFiles) 504 pImage->pFiles->pPrev = pVmdkFile; 461 505 pImage->pFiles = pVmdkFile; 462 *p File = pVmdkFile->File;506 *ppVmdkFile = pVmdkFile; 463 507 } 464 508 else … … 466 510 RTStrFree((char *)(void *)pVmdkFile->pszFilename); 467 511 RTMemFree(pVmdkFile); 468 *p File = NIL_RTFILE;512 *ppVmdkFile = NULL; 469 513 } 470 514 … … 475 519 * Internal: close a file, updating the file descriptor cache. 476 520 */ 477 static int vmdkFileClose(PVMDKIMAGE pImage, P RTFILE pFile, bool fDelete)521 static int vmdkFileClose(PVMDKIMAGE pImage, PVMDKFILE *ppVmdkFile, bool fDelete) 478 522 { 479 523 int rc = VINF_SUCCESS; 480 RTFILE File; 481 PVMDKFILE pVmdkFile, pPrev; 482 483 Assert(VALID_PTR(pFile) && *pFile != NIL_RTFILE); 484 File = *pFile; 485 486 pPrev = NULL; 487 for (pVmdkFile = pImage->pFiles; 488 pVmdkFile != NULL; 489 pVmdkFile = pVmdkFile->pNext) 490 { 491 if (File == pVmdkFile->File) 492 { 493 pVmdkFile->fDelete |= fDelete; 494 Assert(pVmdkFile->uReferences); 495 pVmdkFile->uReferences--; 496 if (pVmdkFile->uReferences == 0) 497 { 498 /* Unchain the element from the list. */ 499 if (pPrev == NULL) 500 pImage->pFiles = pVmdkFile->pNext; 501 else 502 pPrev->pNext = pVmdkFile->pNext; 503 rc = RTFileClose(File); 504 *pFile = NIL_RTFILE; 505 if (VBOX_SUCCESS(rc) && pVmdkFile->fDelete) 506 rc = RTFileDelete(pVmdkFile->pszFilename); 507 RTStrFree((char *)(void *)pVmdkFile->pszFilename); 508 RTMemFree(pVmdkFile); 509 } 510 return rc; 511 } 512 pPrev = pVmdkFile; 513 } 514 515 AssertMsgFailed(("trying to close unknown file %#p", File)); 516 return VERR_INVALID_PARAMETER; 524 PVMDKFILE pVmdkFile = *ppVmdkFile; 525 526 Assert(VALID_PTR(pVmdkFile)); 527 528 pVmdkFile->fDelete |= fDelete; 529 Assert(pVmdkFile->uReferences); 530 pVmdkFile->uReferences--; 531 if (pVmdkFile->uReferences == 0) 532 { 533 PVMDKFILE pPrev; 534 PVMDKFILE pNext; 535 536 /* Unchain the element from the list. */ 537 pPrev = pVmdkFile->pPrev; 538 pNext = pVmdkFile->pNext; 539 540 if (pNext) 541 pNext->pPrev = pPrev; 542 if (pPrev) 543 pPrev->pNext = pNext; 544 else 545 pImage->pFiles = pNext; 546 547 if (pVmdkFile->fAsyncIO) 548 { 549 rc = pImage->pInterfaceAsyncIOCallbacks->pfnClose(pImage->pInterfaceAsyncIO->pvUser, 550 pVmdkFile->pStorage); 551 } 552 else 553 { 554 rc = RTFileClose(pVmdkFile->File); 555 } 556 if (VBOX_SUCCESS(rc) && pVmdkFile->fDelete) 557 rc = RTFileDelete(pVmdkFile->pszFilename); 558 RTStrFree((char *)(void *)pVmdkFile->pszFilename); 559 RTMemFree(pVmdkFile); 560 } 561 562 *ppVmdkFile = NULL; 563 return rc; 564 } 565 566 /** 567 * Internal: read from a file distinguishing between async and normal operation 568 */ 569 DECLINLINE(int) vmdkFileReadAt(PVMDKFILE pVmdkFile, 570 uint64_t uOffset, void *pvBuf, 571 size_t cbToRead, size_t *pcbRead) 572 { 573 PVMDKIMAGE pImage = pVmdkFile->pImage; 574 575 if (pVmdkFile->fAsyncIO) 576 return pImage->pInterfaceAsyncIOCallbacks->pfnRead(pImage->pInterfaceAsyncIO->pvUser, 577 pVmdkFile->pStorage, uOffset, 578 cbToRead, pvBuf, pcbRead); 579 else 580 return RTFileReadAt(pVmdkFile->File, uOffset, pvBuf, cbToRead, pcbRead); 581 } 582 583 /** 584 * Internal: write to a file distinguishing between async and normal operation 585 */ 586 DECLINLINE(int) vmdkFileWriteAt(PVMDKFILE pVmdkFile, 587 uint64_t uOffset, const void *pvBuf, 588 size_t cbToWrite, size_t *pcbWritten) 589 { 590 PVMDKIMAGE pImage = pVmdkFile->pImage; 591 592 if (pVmdkFile->fAsyncIO) 593 return pImage->pInterfaceAsyncIOCallbacks->pfnWrite(pImage->pInterfaceAsyncIO->pvUser, 594 pVmdkFile->pStorage, uOffset, 595 cbToWrite, pvBuf, pcbWritten); 596 else 597 return RTFileWriteAt(pVmdkFile->File, uOffset, pvBuf, cbToWrite, pcbWritten); 598 } 599 600 /** 601 * Internal: get the size of a file distinguishing beween async and normal operation 602 */ 603 DECLINLINE(int) vmdkFileGetSize(PVMDKFILE pVmdkFile, uint64_t *pcbSize) 604 { 605 if (pVmdkFile->fAsyncIO) 606 { 607 AssertMsgFailed(("TODO\n")); 608 return 0; 609 } 610 else 611 return RTFileGetSize(pVmdkFile->File, pcbSize); 612 } 613 614 /** 615 * Internal: set the size of a file distinguishing beween async and normal operation 616 */ 617 DECLINLINE(int) vmdkFileSetSize(PVMDKFILE pVmdkFile, uint64_t cbSize) 618 { 619 if (pVmdkFile->fAsyncIO) 620 { 621 AssertMsgFailed(("TODO\n")); 622 return VERR_NOT_SUPPORTED; 623 } 624 else 625 return RTFileSetSize(pVmdkFile->File, cbSize); 626 } 627 628 /** 629 * Internal: flush a file distinguishing between async and normal operation 630 */ 631 DECLINLINE(int) vmdkFileFlush(PVMDKFILE pVmdkFile) 632 { 633 PVMDKIMAGE pImage = pVmdkFile->pImage; 634 635 if (pVmdkFile->fAsyncIO) 636 return pImage->pInterfaceAsyncIOCallbacks->pfnFlush(pImage->pInterfaceAsyncIO->pvUser, 637 pVmdkFile->pStorage); 638 else 639 return RTFileFlush(pVmdkFile->File); 517 640 } 518 641 … … 533 656 pVmdkFile->pszFilename)); 534 657 pImage->pFiles = pVmdkFile->pNext; 535 rc2 = RTFileClose(pVmdkFile->File); 658 659 if (pImage->uOpenFlags & VD_OPEN_FLAGS_ASYNC_IO) 660 rc2 = pImage->pInterfaceAsyncIOCallbacks->pfnClose(pImage->pInterfaceAsyncIO->pvUser, 661 pVmdkFile->pStorage); 662 else 663 rc2 = RTFileClose(pVmdkFile->File); 664 536 665 if (VBOX_SUCCESS(rc) && pVmdkFile->fDelete) 537 666 rc2 = RTFileDelete(pVmdkFile->pszFilename); … … 649 778 } 650 779 pExtent->pGD = pGD; 651 rc = RTFileReadAt(pExtent->File, VMDK_SECTOR2BYTE(pExtent->uSectorGD),652 pGD, cbGD, NULL);780 rc = vmdkFileReadAt(pExtent->pFile, VMDK_SECTOR2BYTE(pExtent->uSectorGD), 781 pGD, cbGD, NULL); 653 782 AssertRC(rc); 654 783 if (VBOX_FAILURE(rc)) … … 669 798 } 670 799 pExtent->pRGD = pRGD; 671 rc = RTFileReadAt(pExtent->File, VMDK_SECTOR2BYTE(pExtent->uSectorRGD),672 pRGD, cbGD, NULL);800 rc = vmdkFileReadAt(pExtent->pFile, VMDK_SECTOR2BYTE(pExtent->uSectorRGD), 801 pRGD, cbGD, NULL); 673 802 AssertRC(rc); 674 803 if (VBOX_FAILURE(rc)) … … 714 843 goto out; 715 844 } 716 rc = RTFileReadAt(pExtent->File, VMDK_SECTOR2BYTE(*pGDTmp),717 pTmpGT1, cbGT, NULL);845 rc = vmdkFileReadAt(pExtent->pFile, VMDK_SECTOR2BYTE(*pGDTmp), 846 pTmpGT1, cbGT, NULL); 718 847 if (VBOX_FAILURE(rc)) 719 848 { … … 723 852 goto out; 724 853 } 725 rc = RTFileReadAt(pExtent->File, VMDK_SECTOR2BYTE(*pRGDTmp),726 pTmpGT2, cbGT, NULL);854 rc = vmdkFileReadAt(pExtent->pFile, VMDK_SECTOR2BYTE(*pRGDTmp), 855 pTmpGT2, cbGT, NULL); 727 856 if (VBOX_FAILURE(rc)) 728 857 { … … 782 911 783 912 cbOverhead = RT_ALIGN_64(VMDK_SECTOR2BYTE(uStartSector) + 2 * (cbGDRounded + cbGTRounded), VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain)); 784 rc = RTFileSetSize(pExtent->File, cbOverhead);913 rc = vmdkFileSetSize(pExtent->pFile, cbOverhead); 785 914 if (VBOX_FAILURE(rc)) 786 915 goto out; … … 799 928 uGTSectorLE = RT_H2LE_U64(uOffsetSectors); 800 929 /* Write the redundant grain directory entry to disk. */ 801 rc = RTFileWriteAt(pExtent->File,802 VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + i * sizeof(uGTSectorLE),803 &uGTSectorLE, sizeof(uGTSectorLE), NULL);930 rc = vmdkFileWriteAt(pExtent->pFile, 931 VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + i * sizeof(uGTSectorLE), 932 &uGTSectorLE, sizeof(uGTSectorLE), NULL); 804 933 if (VBOX_FAILURE(rc)) 805 934 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write new redundant grain directory entry in '%s'"), pExtent->pszFullname); … … 813 942 uGTSectorLE = RT_H2LE_U64(uOffsetSectors); 814 943 /* Write the grain directory entry to disk. */ 815 rc = RTFileWriteAt(pExtent->File,816 VMDK_SECTOR2BYTE(pExtent->uSectorGD) + i * sizeof(uGTSectorLE),817 &uGTSectorLE, sizeof(uGTSectorLE), NULL);944 rc = vmdkFileWriteAt(pExtent->pFile, 945 VMDK_SECTOR2BYTE(pExtent->uSectorGD) + i * sizeof(uGTSectorLE), 946 &uGTSectorLE, sizeof(uGTSectorLE), NULL); 818 947 if (VBOX_FAILURE(rc)) 819 948 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write new grain directory entry in '%s'"), pExtent->pszFullname); … … 1819 1948 uint64_t cbLimit; 1820 1949 uint64_t uOffset; 1821 RTFILEDescFile;1950 PVMDKFILE pDescFile; 1822 1951 1823 1952 if (pImage->pDescData) … … 1826 1955 uOffset = 0; 1827 1956 cbLimit = 0; 1828 DescFile = pImage->File;1957 pDescFile = pImage->pFile; 1829 1958 } 1830 1959 else … … 1834 1963 cbLimit = VMDK_SECTOR2BYTE(pImage->pExtents[0].cDescriptorSectors); 1835 1964 cbLimit += uOffset; 1836 DescFile = pImage->pExtents[0].File;1965 pDescFile = pImage->pExtents[0].pFile; 1837 1966 } 1838 1967 for (unsigned i = 0; i < pImage->Descriptor.cLines; i++) … … 1843 1972 if (cbLimit && uOffset + cb + 1 > cbLimit) 1844 1973 return vmdkError(pImage, VERR_BUFFER_OVERFLOW, RT_SRC_POS, N_("VMDK: descriptor too long in '%s'"), pImage->pszFilename); 1845 rc = RTFileWriteAt(DescFile, uOffset, psz, cb, NULL);1974 rc = vmdkFileWriteAt(pDescFile, uOffset, psz, cb, NULL); 1846 1975 if (VBOX_FAILURE(rc)) 1847 1976 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error writing descriptor in '%s'"), pImage->pszFilename); 1848 1977 uOffset += cb; 1849 rc = RTFileWriteAt(DescFile, uOffset, "\n", 1, NULL);1978 rc = vmdkFileWriteAt(pDescFile, uOffset, "\n", 1, NULL); 1850 1979 if (VBOX_FAILURE(rc)) 1851 1980 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error writing descriptor in '%s'"), pImage->pszFilename); … … 1857 1986 while (uOffset < cbLimit) 1858 1987 { 1859 rc = RTFileWriteAt(DescFile, uOffset, "", 1, NULL);1988 rc = vmdkFileWriteAt(pDescFile, uOffset, "", 1, NULL); 1860 1989 if (VBOX_FAILURE(rc)) 1861 1990 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error writing descriptor in '%s'"), pImage->pszFilename); … … 1865 1994 else 1866 1995 { 1867 rc = RTFileSetSize(DescFile, uOffset);1996 rc = vmdkFileSetSize(pDescFile, uOffset); 1868 1997 if (VBOX_FAILURE(rc)) 1869 1998 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error truncating descriptor in '%s'"), pImage->pszFilename); … … 1881 2010 uint64_t cbExtentSize, cSectorsPerGDE; 1882 2011 1883 int rc = RTFileReadAt(pExtent->File, 0, &Header, sizeof(Header), NULL);2012 int rc = vmdkFileReadAt(pExtent->pFile, 0, &Header, sizeof(Header), NULL); 1884 2013 AssertRC(rc); 1885 2014 if (VBOX_FAILURE(rc)) … … 1896 2025 /* The image must be a multiple of a sector in size. If not, it means the 1897 2026 * image is at least truncated, or even seriously garbled. */ 1898 rc = RTFileGetSize(pExtent->File, &cbExtentSize);2027 rc = vmdkFileGetSize(pExtent->pFile, &cbExtentSize); 1899 2028 if (VBOX_FAILURE(rc)) 1900 2029 { … … 2005 2134 Header.doubleEndLineChar2 = '\n'; 2006 2135 2007 int rc = RTFileWriteAt(pExtent->File, 0, &Header, sizeof(Header), NULL);2136 int rc = vmdkFileWriteAt(pExtent->pFile, 0, &Header, sizeof(Header), NULL); 2008 2137 AssertRC(rc); 2009 2138 if (VBOX_FAILURE(rc)) … … 2023 2152 uint64_t cSectorsPerGDE; 2024 2153 2025 int rc = RTFileReadAt(pExtent->File, 0, &Header, sizeof(Header), NULL);2154 int rc = vmdkFileReadAt(pExtent->pFile, 0, &Header, sizeof(Header), NULL); 2026 2155 AssertRC(rc); 2027 2156 if (VBOX_FAILURE(rc)) … … 2093 2222 pExtent->pDescData = NULL; 2094 2223 } 2095 if (pExtent-> File != NIL_RTFILE)2096 { 2097 vmdkFileClose(pImage, &pExtent-> File,2224 if (pExtent->pFile != NULL) 2225 { 2226 vmdkFileClose(pImage, &pExtent->pFile, 2098 2227 fDelete 2099 2228 && pExtent->pszFullname … … 2157 2286 for (unsigned i = 0; i < cExtents; i++) 2158 2287 { 2159 pExtents[i]. File = NIL_RTFILE;2288 pExtents[i].pFile = NULL; 2160 2289 pExtents[i].pszBasename = NULL; 2161 2290 pExtents[i].pszFullname = NULL; … … 2182 2311 int rc; 2183 2312 uint32_t u32Magic; 2184 RTFILEFile;2313 PVMDKFILE pFile; 2185 2314 PVMDKEXTENT pExtent; 2186 2315 … … 2189 2318 /* 2190 2319 * Open the image. 2320 * We don't have to check for asynchronous access because 2321 * we only support raw access and the opened file is a description 2322 * file were no data is stored. 2191 2323 */ 2192 rc = vmdkFileOpen(pImage, & File, pImage->pszFilename,2324 rc = vmdkFileOpen(pImage, &pFile, pImage->pszFilename, 2193 2325 uOpenFlags & VD_OPEN_FLAGS_READONLY 2194 2326 ? RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE 2195 : RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE );2327 : RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE, false); 2196 2328 if (VBOX_FAILURE(rc)) 2197 2329 { … … 2200 2332 goto out; 2201 2333 } 2202 pImage-> File =File;2334 pImage->pFile = pFile; 2203 2335 2204 2336 /* Read magic (if present). */ 2205 rc = RTFileReadAt(File, 0, &u32Magic, sizeof(u32Magic), NULL);2337 rc = vmdkFileReadAt(pFile, 0, &u32Magic, sizeof(u32Magic), NULL); 2206 2338 if (VBOX_FAILURE(rc)) 2207 2339 { … … 2220 2352 * file, so no need to keep anything open for the image. */ 2221 2353 pExtent = &pImage->pExtents[0]; 2222 pExtent-> File =File;2223 pImage-> File = NIL_RTFILE;2354 pExtent->pFile = pFile; 2355 pImage->pFile = NULL; 2224 2356 pExtent->pszFullname = RTStrDup(pImage->pszFilename); 2225 2357 if (!pExtent->pszFullname) … … 2245 2377 goto out; 2246 2378 } 2247 rc = RTFileReadAt(pExtent->File,2248 VMDK_SECTOR2BYTE(pExtent->uDescriptorSector),2249 pExtent->pDescData,2250 VMDK_SECTOR2BYTE(pExtent->cDescriptorSectors), NULL);2379 rc = vmdkFileReadAt(pExtent->pFile, 2380 VMDK_SECTOR2BYTE(pExtent->uDescriptorSector), 2381 pExtent->pDescData, 2382 VMDK_SECTOR2BYTE(pExtent->cDescriptorSectors), NULL); 2251 2383 AssertRC(rc); 2252 2384 if (VBOX_FAILURE(rc)) … … 2279 2411 2280 2412 size_t cbRead; 2281 rc = RTFileReadAt(pImage->File, 0, pImage->pDescData,2282 pImage->cbDescAlloc, &cbRead);2413 rc = vmdkFileReadAt(pImage->pFile, 0, pImage->pDescData, 2414 pImage->cbDescAlloc, &cbRead); 2283 2415 if (VBOX_FAILURE(rc)) 2284 2416 { … … 2298 2430 if (VBOX_FAILURE(rc)) 2299 2431 goto out; 2432 2433 /* 2434 * We have to check for the asynchronous open flag. The 2435 * extents are parsed and the type of all are known now. 2436 * Check if every extent is either FLAT or ZERO. 2437 */ 2438 if (uOpenFlags & VD_OPEN_FLAGS_ASYNC_IO) 2439 { 2440 for (unsigned i = 0; i < pImage->cExtents; i++) 2441 { 2442 PVMDKEXTENT pExtent = &pImage->pExtents[i]; 2443 2444 if ( (pExtent->enmType != VMDKETYPE_FLAT) 2445 && (pExtent->enmType != VMDKETYPE_ZERO)) 2446 { 2447 /* 2448 * Opened image contains at least one none flat or zero extent. 2449 * Return error but don't set error message as the caller 2450 * has the chance to open in non async I/O mode. 2451 */ 2452 rc = VERR_NOT_SUPPORTED; 2453 goto out; 2454 } 2455 } 2456 } 2300 2457 2301 2458 for (unsigned i = 0; i < pImage->cExtents; i++) … … 2344 2501 { 2345 2502 case VMDKETYPE_HOSTED_SPARSE: 2346 rc = vmdkFileOpen(pImage, &pExtent-> File, pExtent->pszFullname,2503 rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname, 2347 2504 uOpenFlags & VD_OPEN_FLAGS_READONLY 2348 2505 ? RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE 2349 : RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE );2506 : RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE, false); 2350 2507 if (VBOX_FAILURE(rc)) 2351 2508 { … … 2367 2524 break; 2368 2525 case VMDKETYPE_FLAT: 2369 rc = vmdkFileOpen(pImage, &pExtent-> File, pExtent->pszFullname,2526 rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname, 2370 2527 uOpenFlags & VD_OPEN_FLAGS_READONLY 2371 2528 ? RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE 2372 : RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE );2529 : RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE, true); 2373 2530 if (VBOX_FAILURE(rc)) 2374 2531 { … … 2469 2626 pExtent = &pImage->pExtents[0]; 2470 2627 /* Create raw disk descriptor file. */ 2471 rc = vmdkFileOpen(pImage, &pImage->File, pImage->pszFilename, 2472 RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_WRITE | RTFILE_O_NOT_CONTENT_INDEXED); 2628 rc = vmdkFileOpen(pImage, &pImage->pFile, pImage->pszFilename, 2629 RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_WRITE | RTFILE_O_NOT_CONTENT_INDEXED, 2630 false); 2473 2631 if (VBOX_FAILURE(rc)) 2474 2632 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pImage->pszFilename); … … 2492 2650 2493 2651 /* Open flat image, the raw disk. */ 2494 rc = vmdkFileOpen(pImage, &pExtent-> File, pExtent->pszFullname,2495 RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE );2652 rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname, 2653 RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE, false); 2496 2654 if (VBOX_FAILURE(rc)) 2497 2655 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not open raw disk file '%s'"), pExtent->pszFullname); … … 2541 2699 2542 2700 /* Create raw partition descriptor file. */ 2543 rc = vmdkFileOpen(pImage, &pImage->File, pImage->pszFilename, 2544 RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_WRITE | RTFILE_O_NOT_CONTENT_INDEXED); 2701 rc = vmdkFileOpen(pImage, &pImage->pFile, pImage->pszFilename, 2702 RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_WRITE | RTFILE_O_NOT_CONTENT_INDEXED, 2703 false); 2545 2704 if (VBOX_FAILURE(rc)) 2546 2705 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pImage->pszFilename); … … 2612 2771 2613 2772 /* Create partition table flat image. */ 2614 rc = vmdkFileOpen(pImage, &pExtent->File, pExtent->pszFullname, 2615 RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_WRITE | RTFILE_O_NOT_CONTENT_INDEXED); 2773 rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname, 2774 RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_WRITE | RTFILE_O_NOT_CONTENT_INDEXED, 2775 false); 2616 2776 if (VBOX_FAILURE(rc)) 2617 2777 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new partition data file '%s'"), pExtent->pszFullname); 2618 rc = RTFileWriteAt(pExtent->File,2619 VMDK_SECTOR2BYTE(uPartOffset),2620 pPart->pvPartitionData,2621 pPart->cbPartitionData, NULL);2778 rc = vmdkFileWriteAt(pExtent->pFile, 2779 VMDK_SECTOR2BYTE(uPartOffset), 2780 pPart->pvPartitionData, 2781 pPart->cbPartitionData, NULL); 2622 2782 if (VBOX_FAILURE(rc)) 2623 2783 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not write partition data to '%s'"), pExtent->pszFullname); … … 2659 2819 2660 2820 /* Open flat image, the raw partition. */ 2661 rc = vmdkFileOpen(pImage, &pExtent->File, pExtent->pszFullname, 2662 RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE); 2821 rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname, 2822 RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE, 2823 false); 2663 2824 if (VBOX_FAILURE(rc)) 2664 2825 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not open raw partition file '%s'"), pExtent->pszFullname); … … 2731 2892 if (cExtents != 1 || enmType == VD_IMAGE_TYPE_FIXED) 2732 2893 { 2733 rc = vmdkFileOpen(pImage, &pImage->File, pImage->pszFilename, 2734 RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_WRITE | RTFILE_O_NOT_CONTENT_INDEXED); 2894 rc = vmdkFileOpen(pImage, &pImage->pFile, pImage->pszFilename, 2895 RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_WRITE | RTFILE_O_NOT_CONTENT_INDEXED, 2896 false); 2735 2897 if (VBOX_FAILURE(rc)) 2736 2898 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new sparse descriptor file '%s'"), pImage->pszFilename); … … 2738 2900 } 2739 2901 else 2740 pImage-> File = NIL_RTFILE;2902 pImage->pFile = NULL; 2741 2903 2742 2904 /* Set up all extents. */ … … 2801 2963 2802 2964 /* Create file for extent. */ 2803 rc = vmdkFileOpen(pImage, &pExtent->File, pExtent->pszFullname, 2804 RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_WRITE | RTFILE_O_NOT_CONTENT_INDEXED); 2965 rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname, 2966 RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_WRITE | RTFILE_O_NOT_CONTENT_INDEXED, 2967 false); 2805 2968 if (VBOX_FAILURE(rc)) 2806 2969 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pExtent->pszFullname); 2807 2970 if (enmType == VD_IMAGE_TYPE_FIXED) 2808 2971 { 2809 rc = RTFileSetSize(pExtent->File, cbExtent);2972 rc = vmdkFileSetSize(pExtent->pFile, cbExtent); 2810 2973 if (VBOX_FAILURE(rc)) 2811 2974 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not set size of new file '%s'"), pExtent->pszFullname); … … 2830 2993 unsigned cbChunk = (unsigned)RT_MIN(cbExtent, cbBuf); 2831 2994 2832 rc = RTFileWriteAt(pExtent->File, uOff, pvBuf, cbChunk, NULL);2995 rc = vmdkFileWriteAt(pExtent->pFile, uOff, pvBuf, cbChunk, NULL); 2833 2996 if (VBOX_FAILURE(rc)) 2834 2997 { … … 3140 3303 pImage->pExtents = NULL; 3141 3304 } 3142 if (pImage-> File != NIL_RTFILE)3143 vmdkFileClose(pImage, &pImage-> File, fDelete);3305 if (pImage->pFile != NULL) 3306 vmdkFileClose(pImage, &pImage->pFile, fDelete); 3144 3307 vmdkFileCheckAllClose(pImage); 3145 3308 } … … 3164 3327 { 3165 3328 pExtent = &pImage->pExtents[i]; 3166 if (pExtent-> File != NIL_RTFILE&& pExtent->fMetaDirty)3329 if (pExtent->pFile != NULL && pExtent->fMetaDirty) 3167 3330 { 3168 3331 switch (pExtent->enmType) … … 3196 3359 case VMDKETYPE_FLAT: 3197 3360 /** @todo implement proper path absolute check. */ 3198 if ( pExtent-> File != NIL_RTFILE3361 if ( pExtent->pFile != NULL 3199 3362 && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 3200 3363 && !(pExtent->pszBasename[0] == RTPATH_SLASH)) 3201 rc = RTFileFlush(pExtent->File);3364 rc = vmdkFileFlush(pExtent->pFile); 3202 3365 break; 3203 3366 case VMDKETYPE_ZERO: … … 3285 3448 { 3286 3449 /* Cache miss, fetch data from disk. */ 3287 rc = RTFileReadAt(pExtent->File,3288 VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),3289 aGTDataTmp, sizeof(aGTDataTmp), NULL);3450 rc = vmdkFileReadAt(pExtent->pFile, 3451 VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp), 3452 aGTDataTmp, sizeof(aGTDataTmp), NULL); 3290 3453 if (VBOX_FAILURE(rc)) 3291 3454 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot read grain table entry in '%s'"), pExtent->pszFullname); … … 3334 3497 * entry. So there is absolutely no data in this area. Allocate 3335 3498 * a new grain table and put the reference to it in the GDs. */ 3336 rc = RTFileGetSize(pExtent->File, &cbExtentSize);3499 rc = vmdkFileGetSize(pExtent->pFile, &cbExtentSize); 3337 3500 if (VBOX_FAILURE(rc)) 3338 3501 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname); … … 3353 3516 i++) 3354 3517 { 3355 rc = RTFileWriteAt(pExtent->File,3356 VMDK_SECTOR2BYTE(uGTSector) + i * sizeof(aGTDataTmp),3357 aGTDataTmp, sizeof(aGTDataTmp), NULL);3518 rc = vmdkFileWriteAt(pExtent->pFile, 3519 VMDK_SECTOR2BYTE(uGTSector) + i * sizeof(aGTDataTmp), 3520 aGTDataTmp, sizeof(aGTDataTmp), NULL); 3358 3521 if (VBOX_FAILURE(rc)) 3359 3522 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write grain table allocation in '%s'"), pExtent->pszFullname); … … 3362 3525 { 3363 3526 AssertReturn(!uRGTSector, VERR_VDI_INVALID_HEADER); 3364 rc = RTFileGetSize(pExtent->File, &cbExtentSize);3527 rc = vmdkFileGetSize(pExtent->pFile, &cbExtentSize); 3365 3528 if (VBOX_FAILURE(rc)) 3366 3529 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname); … … 3380 3543 i++) 3381 3544 { 3382 rc = RTFileWriteAt(pExtent->File,3383 VMDK_SECTOR2BYTE(uRGTSector) + i * sizeof(aGTDataTmp),3384 aGTDataTmp, sizeof(aGTDataTmp), NULL);3545 rc = vmdkFileWriteAt(pExtent->pFile, 3546 VMDK_SECTOR2BYTE(uRGTSector) + i * sizeof(aGTDataTmp), 3547 aGTDataTmp, sizeof(aGTDataTmp), NULL); 3385 3548 if (VBOX_FAILURE(rc)) 3386 3549 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain table allocation in '%s'"), pExtent->pszFullname); … … 3393 3556 * some unused sectors in the extent. */ 3394 3557 uint32_t uGTSectorLE = RT_H2LE_U64(uGTSector); 3395 rc = RTFileWriteAt(pExtent->File,3396 VMDK_SECTOR2BYTE(pExtent->uSectorGD) + uGDIndex * sizeof(uGTSectorLE),3397 &uGTSectorLE, sizeof(uGTSectorLE), NULL);3558 rc = vmdkFileWriteAt(pExtent->pFile, 3559 VMDK_SECTOR2BYTE(pExtent->uSectorGD) + uGDIndex * sizeof(uGTSectorLE), 3560 &uGTSectorLE, sizeof(uGTSectorLE), NULL); 3398 3561 if (VBOX_FAILURE(rc)) 3399 3562 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write grain directory entry in '%s'"), pExtent->pszFullname); … … 3401 3564 { 3402 3565 uint32_t uRGTSectorLE = RT_H2LE_U64(uRGTSector); 3403 rc = RTFileWriteAt(pExtent->File,3404 VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + uGDIndex * sizeof(uRGTSectorLE),3405 &uRGTSectorLE, sizeof(uRGTSectorLE), NULL);3566 rc = vmdkFileWriteAt(pExtent->pFile, 3567 VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + uGDIndex * sizeof(uRGTSectorLE), 3568 &uRGTSectorLE, sizeof(uRGTSectorLE), NULL); 3406 3569 if (VBOX_FAILURE(rc)) 3407 3570 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain directory entry in '%s'"), pExtent->pszFullname); … … 3414 3577 } 3415 3578 3416 rc = RTFileGetSize(pExtent->File, &cbExtentSize);3579 rc = vmdkFileGetSize(pExtent->pFile, &cbExtentSize); 3417 3580 if (VBOX_FAILURE(rc)) 3418 3581 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname); … … 3420 3583 3421 3584 /* Write the data. */ 3422 rc = RTFileWriteAt(pExtent->File, cbExtentSize, pvBuf, cbWrite, NULL);3585 rc = vmdkFileWriteAt(pExtent->pFile, cbExtentSize, pvBuf, cbWrite, NULL); 3423 3586 if (VBOX_FAILURE(rc)) 3424 3587 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write allocated data block in '%s'"), pExtent->pszFullname); … … 3432 3595 { 3433 3596 /* Cache miss, fetch data from disk. */ 3434 rc = RTFileReadAt(pExtent->File,3435 VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),3436 aGTDataTmp, sizeof(aGTDataTmp), NULL);3597 rc = vmdkFileReadAt(pExtent->pFile, 3598 VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp), 3599 aGTDataTmp, sizeof(aGTDataTmp), NULL); 3437 3600 if (VBOX_FAILURE(rc)) 3438 3601 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot read allocated grain table entry in '%s'"), pExtent->pszFullname); … … 3453 3616 pGTCacheEntry->aGTData[uGTBlockIndex] = VMDK_BYTE2SECTOR(cbExtentSize); 3454 3617 /* Update grain table on disk. */ 3455 rc = RTFileWriteAt(pExtent->File,3456 VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),3457 aGTDataTmp, sizeof(aGTDataTmp), NULL);3618 rc = vmdkFileWriteAt(pExtent->pFile, 3619 VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp), 3620 aGTDataTmp, sizeof(aGTDataTmp), NULL); 3458 3621 if (VBOX_FAILURE(rc)) 3459 3622 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write updated grain table in '%s'"), pExtent->pszFullname); … … 3461 3624 { 3462 3625 /* Update backup grain table on disk. */ 3463 rc = RTFileWriteAt(pExtent->File,3464 VMDK_SECTOR2BYTE(uRGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),3465 aGTDataTmp, sizeof(aGTDataTmp), NULL);3626 rc = vmdkFileWriteAt(pExtent->pFile, 3627 VMDK_SECTOR2BYTE(uRGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp), 3628 aGTDataTmp, sizeof(aGTDataTmp), NULL); 3466 3629 if (VBOX_FAILURE(rc)) 3467 3630 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write updated backup grain table in '%s'"), pExtent->pszFullname); … … 3500 3663 } 3501 3664 pImage->pszFilename = pszFilename; 3502 pImage-> File = NIL_RTFILE;3665 pImage->pFile = NULL; 3503 3666 pImage->pExtents = NULL; 3504 3667 pImage->pFiles = NULL; 3505 3668 pImage->pGTCache = NULL; 3506 3669 pImage->pDescData = NULL; 3507 pImage->p fnError = NULL;3508 pImage->p vErrorUser= NULL;3670 pImage->pInterfaceError = NULL; 3671 pImage->pInterfaceErrorCallbacks = NULL; 3509 3672 /** @todo speed up this test open (VD_OPEN_FLAGS_INFO) by skipping as 3510 3673 * much as possible in vmdkOpenImage. */ … … 3519 3682 /** @copydoc VBOXHDDBACKEND::pfnOpen */ 3520 3683 static int vmdkOpen(const char *pszFilename, unsigned uOpenFlags, 3521 P FNVDERROR pfnError, void *pvErrorUser,3684 PVDINTERFACE pInterfaces, 3522 3685 void **ppBackendData) 3523 3686 { … … 3550 3713 } 3551 3714 pImage->pszFilename = pszFilename; 3552 pImage-> File = NIL_RTFILE;3715 pImage->pFile = NULL; 3553 3716 pImage->pExtents = NULL; 3554 3717 pImage->pFiles = NULL; 3555 3718 pImage->pGTCache = NULL; 3556 3719 pImage->pDescData = NULL; 3557 pImage->pfnError = pfnError; 3558 pImage->pvErrorUser = pvErrorUser; 3720 pImage->pInterfaceError = NULL; 3721 pImage->pInterfaceErrorCallbacks = NULL; 3722 3723 /* Try to get error interface. */ 3724 pImage->pInterfaceError = VDGetInterfaceFromList(pInterfaces, VDINTERFACETYPE_ERROR); 3725 if (pImage->pInterfaceError) 3726 pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError->pCallbacks); 3727 3728 /* Try to get async I/O interfaec. */ 3729 pImage->pInterfaceAsyncIO = VDGetInterfaceFromList(pInterfaces, VDINTERFACETYPE_ASYNCIO); 3730 if (pImage->pInterfaceAsyncIO) 3731 pImage->pInterfaceAsyncIOCallbacks = VDGetInterfaceAsyncIO(pImage->pInterfaceAsyncIO->pCallbacks); 3732 3559 3733 3560 3734 rc = vmdkOpenImage(pImage, uOpenFlags); … … 3575 3749 unsigned uOpenFlags, PFNVMPROGRESS pfnProgress, 3576 3750 void *pvUser, unsigned uPercentStart, 3577 unsigned uPercentSpan, P FNVDERROR pfnError,3578 void * pvErrorUser, void **ppBackendData)3579 { 3580 LogFlowFunc(("pszFilename=\"%s\" enmType=%d cbSize=%llu uImageFlags=%#x pszComment=\"%s\" pPCHSGeometry=%#p pLCHSGeometry=%#p uOpenFlags=%#x pfnProgress=%#p pvUser=%#p uPercentStart=%u uPercentSpan=%u p fnError=%#p pvErrorUser=%#p ppBackendData=%#p", pszFilename, enmType, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, uOpenFlags, pfnProgress, pvUser, uPercentStart, uPercentSpan, pfnError, pvErrorUser, ppBackendData));3751 unsigned uPercentSpan, PVDINTERFACE pInterfaces, 3752 void **ppBackendData) 3753 { 3754 LogFlowFunc(("pszFilename=\"%s\" enmType=%d cbSize=%llu uImageFlags=%#x pszComment=\"%s\" pPCHSGeometry=%#p pLCHSGeometry=%#p uOpenFlags=%#x pfnProgress=%#p pvUser=%#p uPercentStart=%u uPercentSpan=%u pInterfaces=%#p ppBackendData=%#p", pszFilename, enmType, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, uOpenFlags, pfnProgress, pvUser, uPercentStart, uPercentSpan, pInterfaces, ppBackendData)); 3581 3755 int rc; 3582 3756 PVMDKIMAGE pImage; … … 3612 3786 } 3613 3787 pImage->pszFilename = pszFilename; 3614 pImage-> File = NIL_RTFILE;3788 pImage->pFile = NULL; 3615 3789 pImage->pExtents = NULL; 3616 3790 pImage->pFiles = NULL; 3617 3791 pImage->pGTCache = NULL; 3618 3792 pImage->pDescData = NULL; 3619 pImage->p fnError = pfnError;3620 pImage->p vErrorUser = pvErrorUser;3793 pImage->pInterfaceError = NULL; 3794 pImage->pInterfaceErrorCallbacks = NULL; 3621 3795 pImage->cbDescAlloc = VMDK_SECTOR2BYTE(20); 3622 3796 pImage->pDescData = (char *)RTMemAllocZ(pImage->cbDescAlloc); … … 3626 3800 goto out; 3627 3801 } 3802 3803 /* Get error interface. */ 3804 pImage->pInterfaceError = VDGetInterfaceFromList(pInterfaces, VDINTERFACETYPE_ERROR); 3805 if (pImage->pInterfaceError) 3806 pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError); 3628 3807 3629 3808 rc = vmdkCreateImage(pImage, enmType, cbSize, uImageFlags, pszComment, … … 3780 3959 goto rollback; 3781 3960 /* Close the extent file. */ 3782 vmdkFileClose(pImage, &pExtent-> File, false);3961 vmdkFileClose(pImage, &pExtent->pFile, false); 3783 3962 /* Rename the extent file. */ 3784 3963 rc = RTFileMove(pExtent->pszFullname, apszNewName[i], 0); … … 3846 4025 } 3847 4026 /* Restore the old descriptor. */ 3848 RTFILEFile;3849 rrc = RTFileOpen(&File, pszOldDescName,3850 RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE );4027 PVMDKFILE pFile; 4028 rrc = vmdkFileOpen(pImage, &pFile, pszOldDescName, 4029 RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE, false); 3851 4030 AssertRC(rrc); 3852 4031 if (fEmbeddedDesc) 3853 4032 { 3854 ExtentCopy. File =File;4033 ExtentCopy.pFile = pFile; 3855 4034 pImage->pExtents = &ExtentCopy; 3856 4035 } 3857 4036 else 3858 pImage-> File =File;4037 pImage->pFile = pFile; 3859 4038 pImage->Descriptor = DescriptorCopy; 3860 4039 vmdkWriteDescriptor(pImage); 3861 RTFileClose(File);4040 vmdkFileClose(pImage, &pFile, false); 3862 4041 RTStrFree(pszOldDescName); 3863 4042 /* Re-open the image back. */ … … 3950 4129 rc = VERR_VDI_BLOCK_FREE; 3951 4130 else 3952 rc = RTFileReadAt(pExtent->File,3953 VMDK_SECTOR2BYTE(uSectorExtentAbs),3954 pvBuf, cbToRead, NULL);4131 rc = vmdkFileReadAt(pExtent->pFile, 4132 VMDK_SECTOR2BYTE(uSectorExtentAbs), 4133 pvBuf, cbToRead, NULL); 3955 4134 break; 3956 4135 case VMDKETYPE_FLAT: 3957 rc = RTFileReadAt(pExtent->File,3958 VMDK_SECTOR2BYTE(uSectorExtentRel),3959 pvBuf, cbToRead, NULL);4136 rc = vmdkFileReadAt(pExtent->pFile, 4137 VMDK_SECTOR2BYTE(uSectorExtentRel), 4138 pvBuf, cbToRead, NULL); 3960 4139 break; 3961 4140 case VMDKETYPE_ZERO: … … 4057 4236 } 4058 4237 else 4059 rc = RTFileWriteAt(pExtent->File,4060 VMDK_SECTOR2BYTE(uSectorExtentAbs),4061 pvBuf, cbToWrite, NULL);4238 rc = vmdkFileWriteAt(pExtent->pFile, 4239 VMDK_SECTOR2BYTE(uSectorExtentAbs), 4240 pvBuf, cbToWrite, NULL); 4062 4241 break; 4063 4242 case VMDKETYPE_FLAT: 4064 4243 /* Clip write range to remain in this extent. */ 4065 4244 cbToWrite = RT_MIN(cbToWrite, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel)); 4066 rc = RTFileWriteAt(pExtent->File,4067 VMDK_SECTOR2BYTE(uSectorExtentRel),4068 pvBuf, cbToWrite, NULL);4245 rc = vmdkFileWriteAt(pExtent->pFile, 4246 VMDK_SECTOR2BYTE(uSectorExtentRel), 4247 pvBuf, cbToWrite, NULL); 4069 4248 break; 4070 4249 case VMDKETYPE_ZERO: … … 4154 4333 { 4155 4334 uint64_t cbFile; 4156 if (pImage-> File != NIL_RTFILE)4157 { 4158 int rc = RTFileGetSize(pImage->File, &cbFile);4335 if (pImage->pFile != NULL) 4336 { 4337 int rc = vmdkFileGetSize(pImage->pFile, &cbFile); 4159 4338 if (VBOX_SUCCESS(rc)) 4160 4339 cb += cbFile; 4161 4340 for (unsigned i = 0; i <= pImage->cExtents; i++) 4162 4341 { 4163 rc = RTFileGetSize(pImage->File, &cbFile);4342 rc = vmdkFileGetSize(pImage->pFile, &cbFile); 4164 4343 if (VBOX_SUCCESS(rc)) 4165 4344 cb += cbFile; … … 4336 4515 /* Image must be opened and the new flags must be valid. Just readonly flag 4337 4516 * is supported. */ 4338 if (!pImage || uOpenFlags & ~ VD_OPEN_FLAGS_READONLY)4517 if (!pImage || uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_ASYNC_IO)) 4339 4518 { 4340 4519 rc = VERR_INVALID_PARAMETER; … … 4672 4851 } 4673 4852 4853 static bool vmdkIsAsyncIOSupported(void *pvBackendData) 4854 { 4855 PVMDKIMAGE pImage = (PVMDKIMAGE)pvBackendData; 4856 bool fAsyncIOSupported = false; 4857 4858 if (pImage) 4859 { 4860 /* We only support async I/O support if the image only consists of FLAT or ZERO extents. */ 4861 fAsyncIOSupported = true; 4862 for (unsigned i = 0; i < pImage->cExtents; i++) 4863 { 4864 if ( (pImage->pExtents[i].enmType != VMDKETYPE_FLAT) 4865 && (pImage->pExtents[i].enmType != VMDKETYPE_ZERO)) 4866 { 4867 fAsyncIOSupported = false; 4868 break; /* Stop search */ 4869 } 4870 } 4871 } 4872 4873 return fAsyncIOSupported; 4874 } 4875 4876 static int vmdkAsyncRead(void *pvBackendData, uint64_t uOffset, size_t cbRead, 4877 PPDMDATASEG paSeg, unsigned cSeg, void *pvUser) 4878 { 4879 PVMDKIMAGE pImage = (PVMDKIMAGE)pvBackendData; 4880 PVMDKEXTENT pExtent; 4881 int rc = VINF_SUCCESS; 4882 unsigned cTasksToSubmit = 0; 4883 PPDMDATASEG paSegCurrent = paSeg; 4884 unsigned cbLeftInCurrentSegment = paSegCurrent->cbSeg; 4885 unsigned uOffsetInCurrentSegment = 0; 4886 4887 Assert(pImage); 4888 Assert(uOffset % 512 == 0); 4889 Assert(cbRead % 512 == 0); 4890 4891 if ( uOffset + cbRead > pImage->cbSize 4892 || cbRead == 0) 4893 { 4894 rc = VERR_INVALID_PARAMETER; 4895 goto out; 4896 } 4897 4898 while (cbRead && cSeg) 4899 { 4900 unsigned cbToRead; 4901 uint64_t uSectorExtentRel; 4902 4903 rc = vmdkFindExtent(pImage, VMDK_BYTE2SECTOR(uOffset), 4904 &pExtent, &uSectorExtentRel); 4905 if (VBOX_FAILURE(rc)) 4906 goto out; 4907 4908 /* Check access permissions as defined in the extent descriptor. */ 4909 if (pExtent->enmAccess == VMDKACCESS_NOACCESS) 4910 { 4911 rc = VERR_VDI_INVALID_STATE; 4912 goto out; 4913 } 4914 4915 /* Clip read range to remain in this extent. */ 4916 cbToRead = RT_MIN(cbRead, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel)); 4917 /* Clip read range to remain into current data segment. */ 4918 cbToRead = RT_MIN(cbToRead, cbLeftInCurrentSegment); 4919 4920 switch (pExtent->enmType) 4921 { 4922 case VMDKETYPE_FLAT: 4923 { 4924 /* Setup new task. */ 4925 void *pTask; 4926 rc = pImage->pInterfaceAsyncIOCallbacks->pfnPrepareRead(pImage->pInterfaceAsyncIO->pvUser, pExtent->pFile->pStorage, 4927 VMDK_SECTOR2BYTE(uSectorExtentRel), 4928 (uint8_t *)paSegCurrent->pvSeg + uOffsetInCurrentSegment, 4929 cbToRead, &pTask); 4930 if (VBOX_FAILURE(rc)) 4931 { 4932 AssertMsgFailed(("Preparing read failed rc=%Vrc\n", rc)); 4933 goto out; 4934 } 4935 4936 /* Check for enough room first. */ 4937 if (cTasksToSubmit >= pImage->cTask) 4938 { 4939 /* We reached maximum, resize array. Try to realloc memory first. */ 4940 void **apTaskNew = (void **)RTMemRealloc(pImage->apTask, (cTasksToSubmit + 10)*sizeof(void *)); 4941 4942 if (!apTaskNew) 4943 { 4944 /* We failed. Allocate completely new. */ 4945 apTaskNew = (void **)RTMemAllocZ((cTasksToSubmit + 10)* sizeof(void *)); 4946 if (!apTaskNew) 4947 { 4948 /* Damn, we are out of memory. */ 4949 rc = VERR_NO_MEMORY; 4950 goto out; 4951 } 4952 4953 /* Copy task handles over. */ 4954 for (unsigned i = 0; i < cTasksToSubmit; i++) 4955 apTaskNew[i] = pImage->apTask[i]; 4956 4957 /* Free old memory. */ 4958 RTMemFree(pImage->apTask); 4959 } 4960 4961 pImage->cTask = cTasksToSubmit + 10; 4962 pImage->apTask = apTaskNew; 4963 } 4964 4965 pImage->apTask[cTasksToSubmit] = pTask; 4966 cTasksToSubmit++; 4967 break; 4968 } 4969 case VMDKETYPE_ZERO: 4970 memset((uint8_t *)paSegCurrent->pvSeg + uOffsetInCurrentSegment, 0, cbToRead); 4971 break; 4972 default: 4973 AssertMsgFailed(("Unsupported extent type %u\n", pExtent->enmType)); 4974 } 4975 4976 cbRead -= cbToRead; 4977 uOffset += cbToRead; 4978 cbLeftInCurrentSegment -= cbToRead; 4979 uOffsetInCurrentSegment += cbToRead; 4980 /* Go to next extent if there is no space left in current one. */ 4981 if (!cbLeftInCurrentSegment) 4982 { 4983 uOffsetInCurrentSegment = 0; 4984 paSegCurrent++; 4985 cSeg--; 4986 cbLeftInCurrentSegment = paSegCurrent->cbSeg; 4987 } 4988 } 4989 4990 AssertMsg((cSeg >= 0) && (cbRead == 0), ("No segment left but there is still data to read\n")); 4991 4992 if (cTasksToSubmit == 0) 4993 { 4994 /* The request was completely in a ZERO extent nothing to do. */ 4995 rc = VINF_VDI_ASYNC_IO_FINISHED; 4996 } 4997 else 4998 { 4999 /* Submit tasks. */ 5000 rc = pImage->pInterfaceAsyncIOCallbacks->pfnTasksSubmit(pImage->pInterfaceAsyncIO->pvUser, 5001 pImage->apTask, cTasksToSubmit, 5002 NULL, pvUser, 5003 NULL /* Nothing required after read. */); 5004 AssertMsg(VBOX_SUCCESS(rc), ("Failed to enqueue tasks rc=%Vrc\n", rc)); 5005 } 5006 5007 out: 5008 LogFlowFunc(("returns %Vrc\n", rc)); 5009 return rc; 5010 } 5011 5012 static int vmdkAsyncWrite(void *pvBackendData, uint64_t uOffset, size_t cbWrite, 5013 PPDMDATASEG paSeg, unsigned cSeg, void *pvUser) 5014 { 5015 PVMDKIMAGE pImage = (PVMDKIMAGE)pvBackendData; 5016 PVMDKEXTENT pExtent; 5017 int rc = VINF_SUCCESS; 5018 unsigned cTasksToSubmit = 0; 5019 PPDMDATASEG paSegCurrent = paSeg; 5020 unsigned cbLeftInCurrentSegment = paSegCurrent->cbSeg; 5021 unsigned uOffsetInCurrentSegment = 0; 5022 5023 Assert(pImage); 5024 Assert(uOffset % 512 == 0); 5025 Assert(cbWrite % 512 == 0); 5026 5027 if ( uOffset + cbWrite > pImage->cbSize 5028 || cbWrite == 0) 5029 { 5030 rc = VERR_INVALID_PARAMETER; 5031 goto out; 5032 } 5033 5034 while (cbWrite && cSeg) 5035 { 5036 unsigned cbToWrite; 5037 uint64_t uSectorExtentRel; 5038 5039 rc = vmdkFindExtent(pImage, VMDK_BYTE2SECTOR(uOffset), 5040 &pExtent, &uSectorExtentRel); 5041 if (VBOX_FAILURE(rc)) 5042 goto out; 5043 5044 /* Check access permissions as defined in the extent descriptor. */ 5045 if (pExtent->enmAccess == VMDKACCESS_NOACCESS) 5046 { 5047 rc = VERR_VDI_INVALID_STATE; 5048 goto out; 5049 } 5050 5051 /* Clip write range to remain in this extent. */ 5052 cbToWrite = RT_MIN(cbWrite, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel)); 5053 /* Clip write range to remain into current data segment. */ 5054 cbToWrite = RT_MIN(cbToWrite, cbLeftInCurrentSegment); 5055 5056 switch (pExtent->enmType) 5057 { 5058 case VMDKETYPE_FLAT: 5059 { 5060 /* Setup new task. */ 5061 void *pTask; 5062 rc = pImage->pInterfaceAsyncIOCallbacks->pfnPrepareWrite(pImage->pInterfaceAsyncIO->pvUser, pExtent->pFile->pStorage, 5063 VMDK_SECTOR2BYTE(uSectorExtentRel), 5064 (uint8_t *)paSegCurrent->pvSeg + uOffsetInCurrentSegment, 5065 cbToWrite, &pTask); 5066 if (VBOX_FAILURE(rc)) 5067 { 5068 AssertMsgFailed(("Preparing read failed rc=%Vrc\n", rc)); 5069 goto out; 5070 } 5071 5072 /* Check for enough room first. */ 5073 if (cTasksToSubmit >= pImage->cTask) 5074 { 5075 /* We reached maximum, resize array. Try to realloc memory first. */ 5076 void **apTaskNew = (void **)RTMemRealloc(pImage->apTask, (cTasksToSubmit + 10)*sizeof(void *)); 5077 5078 if (!apTaskNew) 5079 { 5080 /* We failed. Allocate completely new. */ 5081 apTaskNew = (void **)RTMemAllocZ((cTasksToSubmit + 10)* sizeof(void *)); 5082 if (!apTaskNew) 5083 { 5084 /* Damn, we are out of memory. */ 5085 rc = VERR_NO_MEMORY; 5086 goto out; 5087 } 5088 5089 /* Copy task handles over. */ 5090 for (unsigned i = 0; i < cTasksToSubmit; i++) 5091 apTaskNew[i] = pImage->apTask[i]; 5092 5093 /* Free old memory. */ 5094 RTMemFree(pImage->apTask); 5095 } 5096 5097 pImage->cTask = cTasksToSubmit + 10; 5098 pImage->apTask = apTaskNew; 5099 } 5100 5101 pImage->apTask[cTasksToSubmit] = pTask; 5102 cTasksToSubmit++; 5103 break; 5104 } 5105 case VMDKETYPE_ZERO: 5106 /* Nothing left to do. */ 5107 break; 5108 default: 5109 AssertMsgFailed(("Unsupported extent type %u\n", pExtent->enmType)); 5110 } 5111 5112 cbWrite -= cbToWrite; 5113 uOffset += cbToWrite; 5114 cbLeftInCurrentSegment -= cbToWrite; 5115 uOffsetInCurrentSegment += cbToWrite; 5116 /* Go to next extent if there is no space left in current one. */ 5117 if (!cbLeftInCurrentSegment) 5118 { 5119 uOffsetInCurrentSegment = 0; 5120 paSegCurrent++; 5121 cSeg--; 5122 cbLeftInCurrentSegment = paSegCurrent->cbSeg; 5123 } 5124 } 5125 5126 AssertMsg((cSeg >= 0) && (cbWrite == 0), ("No segment left but there is still data to read\n")); 5127 5128 if (cTasksToSubmit == 0) 5129 { 5130 /* The request was completely in a ZERO extent nothing to do. */ 5131 rc = VINF_VDI_ASYNC_IO_FINISHED; 5132 } 5133 else 5134 { 5135 /* Submit tasks. */ 5136 rc = pImage->pInterfaceAsyncIOCallbacks->pfnTasksSubmit(pImage->pInterfaceAsyncIO->pvUser, 5137 pImage->apTask, cTasksToSubmit, 5138 NULL, pvUser, 5139 NULL /* Nothing required after read. */); 5140 AssertMsg(VBOX_SUCCESS(rc), ("Failed to enqueue tasks rc=%Vrc\n", rc)); 5141 } 5142 5143 out: 5144 LogFlowFunc(("returns %Vrc\n", rc)); 5145 return rc; 5146 5147 } 5148 5149 4674 5150 VBOXHDDBACKEND g_VmdkBackend = 4675 5151 { … … 4680 5156 /* uBackendCaps */ 4681 5157 VD_CAP_UUID | VD_CAP_CREATE_FIXED | VD_CAP_CREATE_DYNAMIC 4682 | VD_CAP_CREATE_SPLIT_2G | VD_CAP_DIFF | VD_CAP_FILE ,5158 | VD_CAP_CREATE_SPLIT_2G | VD_CAP_DIFF | VD_CAP_FILE |VD_CAP_ASYNC, 4683 5159 /* pfnCheckIfValid */ 4684 5160 vmdkCheckIfValid, … … 4750 5226 vmdkGetParentFilename, 4751 5227 /* pfnSetParentFilename */ 4752 vmdkSetParentFilename 5228 vmdkSetParentFilename, 5229 /* pfnIsAsyncIOSupported */ 5230 vmdkIsAsyncIOSupported, 5231 /* pfnAsyncRead */ 5232 vmdkAsyncRead, 5233 /* pfnAsyncWrite */ 5234 vmdkAsyncWrite 4753 5235 }; -
trunk/src/VBox/Devices/Storage/testcase/tstVD.cpp
r9734 r10715 56 56 PDMMEDIAGEOMETRY PCHS = { 0, 0, 0 }; 57 57 PDMMEDIAGEOMETRY LCHS = { 0, 0, 0 }; 58 VDINTERFACE VDIError; 59 VDINTERFACEERROR VDIErrorCallbacks; 58 60 59 61 #define CHECK(str) \ … … 68 70 } while (0) 69 71 70 rc = VDCreate(tstVDError, NULL, &pVD); 72 /* Create error interface. */ 73 VDIErrorCallbacks.cbSize = sizeof(VDINTERFACEERROR); 74 VDIErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR; 75 VDIErrorCallbacks.pfnError = tstVDError; 76 77 rc = VDInterfaceCreate(&VDIError, "tstVD_Error", VDINTERFACETYPE_ERROR, &VDIErrorCallbacks, 78 NULL, NULL); 79 AssertRC(rc); 80 81 rc = VDCreate(&VDIError, &pVD); 71 82 CHECK("VDCreate()"); 72 83 … … 420 431 uint64_t u64DiskSize = 1000 * _1M; 421 432 uint32_t u32SectorSize = 512; 433 VDINTERFACE VDIError; 434 VDINTERFACEERROR VDIErrorCallbacks; 422 435 423 436 #define CHECK(str) \ … … 432 445 } while (0) 433 446 434 rc = VDCreate(tstVDError, NULL, &pVD); 447 /* Create error interface. */ 448 VDIErrorCallbacks.cbSize = sizeof(VDINTERFACEERROR); 449 VDIErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR; 450 VDIErrorCallbacks.pfnError = tstVDError; 451 452 rc = VDInterfaceCreate(&VDIError, "tstVD_Error", VDINTERFACETYPE_ERROR, &VDIErrorCallbacks, 453 NULL, NULL); 454 AssertRC(rc); 455 456 457 rc = VDCreate(&VDIError, &pVD); 435 458 CHECK("VDCreate()"); 436 459 … … 526 549 uint64_t u64DiskSize = 1000 * _1M; 527 550 uint32_t u32SectorSize = 512; 551 VDINTERFACE VDIError; 552 VDINTERFACEERROR VDIErrorCallbacks; 528 553 529 554 #define CHECK(str) \ … … 538 563 } while (0) 539 564 540 rc = VDCreate(tstVDError, NULL, &pVD); 565 /* Create error interface. */ 566 VDIErrorCallbacks.cbSize = sizeof(VDINTERFACEERROR); 567 VDIErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR; 568 VDIErrorCallbacks.pfnError = tstVDError; 569 570 rc = VDInterfaceCreate(&VDIError, "tstVD_Error", VDINTERFACETYPE_ERROR, &VDIErrorCallbacks, 571 NULL, NULL); 572 AssertRC(rc); 573 574 575 rc = VDCreate(&VDIError, &pVD); 541 576 CHECK("VDCreate()"); 542 577 -
trunk/src/VBox/Devices/testcase/tstDeviceStructSizeGC.cpp
r9387 r10715 908 908 GEN_CHECK_OFF(AHCIPort, u32TasksFinished); 909 909 GEN_CHECK_OFF(AHCIPort, u32QueuedTasksFinished); 910 GEN_CHECK_OFF(AHCIPort, StatDMA); 911 GEN_CHECK_OFF(AHCIPort, StatBytesWritten); 912 GEN_CHECK_OFF(AHCIPort, StatBytesRead); 913 GEN_CHECK_OFF(AHCIPort, StatQueueFillRate); 910 914 911 915 GEN_CHECK_SIZE(AHCI); -
trunk/src/VBox/Frontends/VBoxManage/VBoxInternalManage.cpp
r9975 r10715 1093 1093 RTFileClose(RawFile); 1094 1094 1095 vrc = VDCreate(handleVDError, NULL, &pDisk); 1095 VDINTERFACE vdInterfaceError; 1096 VDINTERFACEERROR vdInterfaceErrorCallbacks; 1097 vdInterfaceErrorCallbacks.cbSize = sizeof(VDINTERFACEERROR); 1098 vdInterfaceErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR; 1099 vdInterfaceErrorCallbacks.pfnError = handleVDError; 1100 1101 vrc = VDInterfaceCreate(&vdInterfaceError, "VBoxManage_IError", VDINTERFACETYPE_ERROR, 1102 &vdInterfaceErrorCallbacks, NULL, NULL); 1103 AssertRC(vrc); 1104 1105 vrc = VDCreate(&vdInterfaceError, &pDisk); 1096 1106 if (VBOX_FAILURE(vrc)) 1097 1107 { … … 1192 1202 PVBOXHDD pDisk = NULL; 1193 1203 1194 int vrc = VDCreate(handleVDError, NULL, &pDisk); 1204 VDINTERFACE vdInterfaceError; 1205 VDINTERFACEERROR vdInterfaceErrorCallbacks; 1206 vdInterfaceErrorCallbacks.cbSize = sizeof(VDINTERFACEERROR); 1207 vdInterfaceErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR; 1208 vdInterfaceErrorCallbacks.pfnError = handleVDError; 1209 1210 int vrc = VDInterfaceCreate(&vdInterfaceError, "VBoxManage_IError", VDINTERFACETYPE_ERROR, 1211 &vdInterfaceErrorCallbacks, NULL, NULL); 1212 AssertRC(vrc); 1213 1214 vrc = VDCreate(&vdInterfaceError, &pDisk); 1195 1215 if (VBOX_FAILURE(vrc)) 1196 1216 { -
trunk/src/VBox/Main/ConsoleImpl2.cpp
r10693 r10715 854 854 STR_FREE(); 855 855 rc = CFGMR3InsertString(pCfg, "Format", "VMDK"); RC_CHECK(); 856 857 /* 858 * Create cfgm nodes for async transport driver because VMDK is currently the only 859 * one which may support async I/O. This has to be made generic based on the capabiliy flags 860 * when the new HardDisk interface is merged. 861 */ 862 rc = CFGMR3InsertNode(pLunL1, "AttachedDriver", &pLunL2); RC_CHECK(); 863 rc = CFGMR3InsertString(pLunL2, "Driver", "TransportAsync"); RC_CHECK(); 864 /* The async transport driver has no config options yet. */ 856 865 } 857 866 else if (hddType == HardDiskStorageType_CustomHardDisk) -
trunk/src/VBox/Main/HardDiskImpl.cpp
r9497 r10715 3403 3403 mActualSize = 0; 3404 3404 3405 /* Create supported error interface. */ 3406 mInterfaceErrorCallbacks.cbSize = sizeof(VDINTERFACEERROR); 3407 mInterfaceErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR; 3408 mInterfaceErrorCallbacks.pfnError = VDError; 3409 int vrc = VDInterfaceCreate(&mInterfaceError, "VMDK_IError", VDINTERFACETYPE_ERROR, 3410 &mInterfaceErrorCallbacks, this, NULL); 3411 ComAssertRCRet (vrc, E_FAIL); 3412 3405 3413 /* initialize the container */ 3406 int vrc = VDCreate (VDError, this, &mContainer);3414 vrc = VDCreate (&mInterfaceError, &mContainer); 3407 3415 ComAssertRCRet (vrc, E_FAIL); 3408 3416 … … 4283 4291 ComAssertRCRet (rc, E_FAIL); 4284 4292 4293 /* Create supported error interface. */ 4294 mInterfaceErrorCallbacks.cbSize = sizeof(VDINTERFACEERROR); 4295 mInterfaceErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR; 4296 mInterfaceErrorCallbacks.pfnError = VDError; 4297 int vrc = VDInterfaceCreate(&mInterfaceError, "Custom_IError", VDINTERFACETYPE_ERROR, 4298 &mInterfaceErrorCallbacks, this, NULL); 4299 ComAssertRCRet (vrc, E_FAIL); 4300 4285 4301 return S_OK; 4286 4302 } … … 4344 4360 4345 4361 /* initialize the container */ 4346 vrc = VDCreate ( VDError, this, &mContainer);4362 vrc = VDCreate (&mInterfaceError, &mContainer); 4347 4363 if (VBOX_FAILURE (vrc)) 4348 4364 { … … 4447 4463 RTStrFree (pszFormat); 4448 4464 4449 /* Create the corresponding container.*/4450 vrc = VDCreate ( VDError, this, &mContainer);4465 /* initialize the container */ 4466 vrc = VDCreate (&mInterfaceError, &mContainer); 4451 4467 4452 4468 /* the format has been already checked for presence at this point */ … … 5111 5127 mActualSize = 0; 5112 5128 5129 /* Create supported error interface. */ 5130 mInterfaceErrorCallbacks.cbSize = sizeof(VDINTERFACEERROR); 5131 mInterfaceErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR; 5132 mInterfaceErrorCallbacks.pfnError = VDError; 5133 int vrc = VDInterfaceCreate(&mInterfaceError, "VHD_IError", VDINTERFACETYPE_ERROR, 5134 &mInterfaceErrorCallbacks, this, NULL); 5135 ComAssertRCRet (vrc, E_FAIL); 5136 5113 5137 /* initialize the container */ 5114 int vrc = VDCreate (VDError, this, &mContainer);5138 vrc = VDCreate (&mInterfaceError, &mContainer); 5115 5139 ComAssertRCRet (vrc, E_FAIL); 5116 5140 -
trunk/src/VBox/Main/include/HardDiskImpl.h
r8155 r10715 539 539 PVBOXHDD mContainer; 540 540 541 VDINTERFACE mInterfaceError; 542 VDINTERFACEERROR mInterfaceErrorCallbacks; 543 541 544 Utf8Str mLastVDError; 542 545 … … 651 654 PVBOXHDD mContainer; 652 655 656 VDINTERFACE mInterfaceError; 657 VDINTERFACEERROR mInterfaceErrorCallbacks; 658 653 659 Utf8Str mLastVDError; 654 660 … … 764 770 PVBOXHDD mContainer; 765 771 772 VDINTERFACE mInterfaceError; 773 VDINTERFACEERROR mInterfaceErrorCallbacks; 774 766 775 Utf8Str mLastVDError; 767 776
Note:
See TracChangeset
for help on using the changeset viewer.

