Changeset 20167 in vbox
- Timestamp:
- Jun 1, 2009 8:25:54 PM (16 years ago)
- svn:sync-xref-src-repo-rev:
- 47996
- Location:
- trunk
- Files:
-
- 1 added
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/VBoxHDD.h
r19176 r20167 395 395 * @return VBox status code. 396 396 * @param pvUser Opaque user data which is passed on request submission. 397 */ 398 typedef DECLCALLBACK(int) FNVDCOMPLETED(void *pvUser); 397 * @param ppvCaller Where to store the opaque user data the caller of 398 * VDAsyncRead or VDAsyncWrite passed. 399 */ 400 typedef DECLCALLBACK(int) FNVDCOMPLETED(void *pvUser, void **ppvCaller); 399 401 /** Pointer to FNVDCOMPLETED() */ 400 402 typedef FNVDCOMPLETED *PFNVDCOMPLETED; … … 425 427 * @param pszLocation Name of the location to open. 426 428 * @param fReadonly Whether to open the storage medium read only. 429 * @param pfnCompleted The callabck which is called whenever a task 430 * completed. The backend has to pass the user data 431 * of the request initiator (ie the one who calls 432 * VDAsyncRead or VDAsyncWrite) in pvCompletion 433 * if this is NULL. 427 434 * @param ppStorage Where to store the opaque storage handle. 428 435 */ 429 DECLR3CALLBACKMEMBER(int, pfnOpen, (void *pvUser, const char *pszLocation, bool fReadonly, void **ppStorage)); 436 DECLR3CALLBACKMEMBER(int, pfnOpen, (void *pvUser, const char *pszLocation, bool fReadonly, 437 PFNVDCOMPLETED pfnCompleted, void **ppStorage)); 430 438 431 439 /** … … 437 445 */ 438 446 DECLR3CALLBACKMEMBER(int, pfnClose, (void *pvUser, void *pStorage)); 447 448 /** 449 * Returns the size of the opened storage backend. 450 * 451 * @return VBox status code. 452 * @param pvUser The opaque data passed on container creation. 453 * @param pStorage The opaque storage handle to close. 454 * @param pcbSize Where to store the size of the storage backend. 455 */ 456 DECLR3CALLBACKMEMBER(int, pfnGetSize, (void *pvUser, void *pStorage, uint64_t *pcbSize)); 439 457 440 458 /** … … 449 467 * @param pcbWritten Where to store how many bytes where actually written. 450 468 */ 451 DECLR3CALLBACKMEMBER(int, pfnWrite , (void *pvUser, void *pStorage, uint64_t uOffset,452 size_t cbWrite, const void *pvBuf, size_t *pcbWritten));469 DECLR3CALLBACKMEMBER(int, pfnWriteSync, (void *pvUser, void *pStorage, uint64_t uOffset, 470 size_t cbWrite, const void *pvBuf, size_t *pcbWritten)); 453 471 454 472 /** … … 463 481 * @param pcbRead Where to store how many bytes where actually read. 464 482 */ 465 DECLR3CALLBACKMEMBER(int, pfnRead , (void *pvUser, void *pStorage, uint64_t uOffset,466 size_t cbRead, void *pvBuf, size_t *pcbRead));483 DECLR3CALLBACKMEMBER(int, pfnReadSync, (void *pvUser, void *pStorage, uint64_t uOffset, 484 size_t cbRead, void *pvBuf, size_t *pcbRead)); 467 485 468 486 /** … … 473 491 * @param pStorage The storage handle to flush. 474 492 */ 475 DECLR3CALLBACKMEMBER(int, pfnFlush , (void *pvUser, void *pStorage));476 477 /** 478 * Prepare an asynchronous read task.493 DECLR3CALLBACKMEMBER(int, pfnFlushSync, (void *pvUser, void *pStorage)); 494 495 /** 496 * Initiate a asynchronous read request. 479 497 * 480 498 * @return VBox status code. … … 482 500 * @param pStorage The storage handle. 483 501 * @param uOffset The offset to start reading from. 484 * @param pvBuf Where to store read bits. 502 * @param paSegments Scatter gather list to store the data in. 503 * @param cSegments Number of segments in the list. 485 504 * @param cbRead How many bytes to read. 505 * @param pvCompletion The opaque user data which is returned upon completion. 486 506 * @param ppTask Where to store the opaque task handle. 487 507 */ 488 DECLR3CALLBACKMEMBER(int, pfnPrepareRead, (void *pvUser, void *pStorage, uint64_t uOffset, 489 void *pvBuf, size_t cbRead, void **ppTask)); 490 491 /** 492 * Prepare an asynchronous write task. 508 DECLR3CALLBACKMEMBER(int, pfnReadAsync, (void *pvUser, void *pStorage, uint64_t uOffset, 509 PCPDMDATASEG paSegments, size_t cSegments, 510 size_t cbRead, void *pvCompletion, 511 void **ppTask)); 512 513 /** 514 * Initiate a asynchronous write request. 493 515 * 494 516 * @return VBox status code. … … 496 518 * @param pStorage The storage handle. 497 519 * @param uOffset The offset to start writing to. 498 * @param pvBuf Where to read the data from. 520 * @param paSegments Scatter gather list of the data to write 521 * @param cSegments Number of segments in the list. 499 522 * @param cbWrite How many bytes to write. 523 * @param pvCompletion The opaque user data which is returned upon completion. 500 524 * @param ppTask Where to store the opaque task handle. 501 525 */ 502 DECLR3CALLBACKMEMBER(int, pfn PrepareWrite, (void *pvUser, void *pStorage, uint64_t uOffset,503 void *pvBuf, size_t cbWrite, void **ppTask));504 505 /**506 * Submit an array of tasks for processing 507 508 * @return VBox status code.509 * @param pvUser The opaque user data passed on container creation.510 * @ param apTasks Array of task handles to submit.511 * @param cTasks How many tasks to submit.512 * @param p vUser2 User data which is passed on completion.513 * @param pv UserCaller Opaque user data the caller of VDAsyncWrite/Read passed.514 * @param p fnTasksCompleted Pointer to callback which is called on request completion.515 */ 516 DECLR3CALLBACKMEMBER(int, pfn TasksSubmit, (void *pvUser, void *apTasks[], unsigned cTasks, void *pvUser2,517 void *pvUserCaller, PFNVDCOMPLETED pfnTasksCompleted));526 DECLR3CALLBACKMEMBER(int, pfnWriteAsync, (void *pvUser, void *pStorage, uint64_t uOffset, 527 PCPDMDATASEG paSegments, size_t cSegments, 528 size_t cbWrite, void *pvCompletion, 529 void **ppTask)); 530 531 /** 532 * Initiates a async flush request. 533 * 534 * @return VBox statis code. 535 * @param pvUser The opaque data passed on container creation. 536 * @param pStorage The storage handle to flush. 537 * @param pvCompletion The opaque user data which is returned upon completion. 538 * @param ppTask Where to store the opaque task handle. 539 */ 540 DECLR3CALLBACKMEMBER(int, pfnFlushAsync, (void *pvUser, void *pStorage, 541 void *pvCompletion, void **ppTask)); 518 542 519 543 } VDINTERFACEASYNCIO, *PVDINTERFACEASYNCIO; -
trunk/include/VBox/pdmasynccompletion.h
r13835 r20167 5 5 6 6 /* 7 * Copyright (C) 2007 Sun Microsystems, Inc.7 * Copyright (C) 2007-2009 Sun Microsystems, Inc. 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 53 53 typedef PPDMASYNCCOMPLETIONTASK *PPPDMASYNCCOMPLETIONTASK; 54 54 55 /** Pointer to a PDM async completion endpoint handle. */ 56 typedef struct PDMASYNCCOMPLETIONENDPOINT *PPDMASYNCCOMPLETIONENDPOINT; 57 /** Pointer to a PDM async completion endpoint handle pointer. */ 58 typedef PPDMASYNCCOMPLETIONENDPOINT *PPPDMASYNCCOMPLETIONENDPOINT; 59 55 60 56 61 /** … … 58 63 * 59 64 * @param pDevIns The device instance. 60 * @param pTask Pointer to the completion task.61 * The task is at the time of the call setup to be resumed. So, the callback must62 * call PDMR3AsyncCompletionSuspend or PDMR3AsyncCompletionDestroy if any other63 * action is wanted upon return.64 * @param pvCtx Pointer to any additional, OS specific, completion context. TBD.65 65 * @param pvUser User argument. 66 66 */ 67 typedef DECLCALLBACK(void) FNPDMASYNCCOMPLETEDEV(PPDMDEVINS pDevIns, PPDMASYNCCOMPLETIONTASK pTask, void *pvCtx,void *pvUser);67 typedef DECLCALLBACK(void) FNPDMASYNCCOMPLETEDEV(PPDMDEVINS pDevIns, void *pvUser); 68 68 /** Pointer to a FNPDMASYNCCOMPLETEDEV(). */ 69 69 typedef FNPDMASYNCCOMPLETEDEV *PFNPDMASYNCCOMPLETEDEV; … … 73 73 * Completion callback for drivers. 74 74 * 75 * @param pDrvIns The driver instance. 76 * @param pTask Pointer to the completion task. 77 * The task is at the time of the call setup to be resumed. So, the callback must 78 * call PDMR3AsyncCompletionSuspend or PDMR3AsyncCompletionDestroy if any other 79 * action is wanted upon return. 80 * @param pvCtx Pointer to any additional, OS specific, completion context. TBD. 81 * @param pvUser User argument. 82 */ 83 typedef DECLCALLBACK(void) FNPDMASYNCCOMPLETEDRV(PPDMDRVINS pDrvIns, PPDMASYNCCOMPLETIONTASK pTask, void *pvCtx, void *pvUser); 75 * @param pDrvIns The driver instance. 76 * @param pvTemplateUser User argument given when creating the template. 77 * @param pvUser User argument given during request initiation. 78 */ 79 typedef DECLCALLBACK(void) FNPDMASYNCCOMPLETEDRV(PPDMDRVINS pDrvIns, void *pvTemplateUser, void *pvUser); 84 80 /** Pointer to a FNPDMASYNCCOMPLETEDRV(). */ 85 81 typedef FNPDMASYNCCOMPLETEDRV *PFNPDMASYNCCOMPLETEDRV; … … 90 86 * 91 87 * @param pUsbIns The USB device instance. 92 * @param pTask Pointer to the completion task.93 * The task is at the time of the call setup to be resumed. So, the callback must94 * call PDMR3AsyncCompletionSuspend or PDMR3AsyncCompletionDestroy if any other95 * action is wanted upon return.96 * @param pvCtx Pointer to any additional, OS specific, completion context. TBD.97 88 * @param pvUser User argument. 98 89 */ 99 typedef DECLCALLBACK(void) FNPDMASYNCCOMPLETEUSB(PPDMUSBINS pUsbIns, PPDMASYNCCOMPLETIONTASK pTask, void *pvCtx,void *pvUser);90 typedef DECLCALLBACK(void) FNPDMASYNCCOMPLETEUSB(PPDMUSBINS pUsbIns, void *pvUser); 100 91 /** Pointer to a FNPDMASYNCCOMPLETEUSB(). */ 101 92 typedef FNPDMASYNCCOMPLETEUSB *PFNPDMASYNCCOMPLETEUSB; … … 106 97 * 107 98 * @param pVM Pointer to the shared VM structure. 108 * @param pTask Pointer to the completion task.109 * The task is at the time of the call setup to be resumed. So, the callback must110 * call PDMR3AsyncCompletionSuspend or PDMR3AsyncCompletionDestroy if any other111 * action is wanted upon return.112 * @param pvCtx Pointer to any additional, OS specific, completion context. TBD.113 99 * @param pvUser User argument for the task. 114 100 * @param pvUser2 User argument for the template. 115 101 */ 116 typedef DECLCALLBACK(void) FNPDMASYNCCOMPLETEINT(PVM pVM, PPDMASYNCCOMPLETIONTASK pTask, void *pvCtx,void *pvUser, void *pvUser2);102 typedef DECLCALLBACK(void) FNPDMASYNCCOMPLETEINT(PVM pVM, void *pvUser, void *pvUser2); 117 103 /** Pointer to a FNPDMASYNCCOMPLETEINT(). */ 118 104 typedef FNPDMASYNCCOMPLETEINT *PFNPDMASYNCCOMPLETEINT; … … 143 129 * @param ppTemplate Where to store the template pointer on success. 144 130 * @param pfnCompleted The completion callback routine. 131 * @param pvTemplateUser Template user argument. 145 132 * @param pszDesc Description. 146 133 */ 147 VMMR3DECL(int) PDMR3AsyncCompletionTemplateCreateDriver(PVM pVM, PPDMDRVINS pDrvIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate, PFNPDMASYNCCOMPLETEDRV pfnCompleted, const char *pszDesc);134 VMMR3DECL(int) PDMR3AsyncCompletionTemplateCreateDriver(PVM pVM, PPDMDRVINS pDrvIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate, PFNPDMASYNCCOMPLETEDRV pfnCompleted, void *pvTemplateUser, const char *pszDesc); 148 135 149 136 /** … … 222 209 VMMR3DECL(int) PDMR3AsyncCompletionTemplateDestroyUsb(PVM pVM, PPDMUSBINS pUsbIns); 223 210 224 /** 225 * Async completion task type 226 */ 227 typedef enum PDMASYNCCOMPLETIONTASKTYPE 228 { 229 /** Socket. */ 230 PDMASYNCCOMPLETIONTASKTYPE_SOCKET = 0, 231 /** Host OS specific. */ 232 PDMASYNCCOMPLETIONTASKTYPE_HOST, 233 /** Number of supported backends. This has to be last entry! */ 234 PDMASYNCCOMPLETIONTASKTYPE_SUPPORTED 235 } PDMASYNCCOMPLETIONTASKTYPE; 236 237 /** 238 * Get the backend name of a task type. 239 * 240 * @returns Name of the backend. 241 * @param enmTaskType The task type to get the backend name from. 242 */ 243 VMMR3DECL(const char *) PDMR3AsyncCompletionGetBackendName(PDMASYNCCOMPLETIONTASKTYPE enmTaskType); 244 245 /** 246 * Creates a completion task. 247 * 248 * @returns VBox status code. 211 212 /** 213 * Opens a file as a async completion endpoint. 214 * 215 * @returns VBox status code. 216 * @param ppEndpoint Where to store the opaque endpoint handle on success. 217 * @param pszFilename Path to the file which is to be opened. (UTF-8) 218 * @param fFlags Open flags, see grp_pdmacep_file_flags. 219 * @param pTemplate Handle to the completion callback template to use 220 * for this end point. 221 */ 222 VMMR3DECL(int) PDMR3AsyncCompletionEpCreateForFile(PPPDMASYNCCOMPLETIONENDPOINT ppEndpoint, 223 const char *pszFilename, uint32_t fFlags, 224 PPDMASYNCCOMPLETIONTEMPLATE pTemplate); 225 226 /** @defgroup grp_pdmacep_file_flags Flags for PDMR3AsyncCompletionEpCreateForFile 227 * @{ */ 228 /** Open the file in read-only mode. */ 229 #define PDMACEP_FILE_FLAGS_READ_ONLY RT_BIT_32(0) 230 /** whether file content should be cached by the endpoint. */ 231 #define PDMACEP_FILE_FLAGS_CACHING RT_BIT_32(1) 232 /** @} */ 233 234 /** 235 * Closes a endpoint waiting for any pending tasks to finish. 236 * 237 * @returns nothing. 238 * @param pEndpoint Handle of the endpoint. 239 */ 240 VMMR3DECL(void) PDMR3AsyncCompletionEpClose(PPDMASYNCCOMPLETIONENDPOINT pEndpoint); 241 242 /** 243 * Creates a read task on the given endpoint. 244 * 245 * @returns VBox status code. 246 * @param pEndpoint The file endpoint to read from. 247 * @param off Where to start reading from. 248 * @param paSegments Scatter gather list to store the data in. 249 * @param cSegments Number of segments in the list. 250 * @param cbRead The overall number of bytes to read. 251 * @param pvUser Opaque user data returned in the completion callback 252 * upon completion of the task. 249 253 * @param ppTask Where to store the task handle on success. 250 * @param pTemplate The async completion template. 251 * @param enmType The type of the task. 252 * @param pvCtx The task specific context. 253 * @param pvUser The user argument for the callback. 254 */ 255 VMMR3DECL(int) PDMR3AsyncCompletionTaskCreate(PPPDMASYNCCOMPLETIONTASK ppTask, PPDMASYNCCOMPLETIONTEMPLATE pTemplate, PDMASYNCCOMPLETIONTASKTYPE enmType, void *pvCtx, void *pvUser); 256 257 /** 258 * Submit an array of tasks for processing 259 * The tasks must have a type specific context. 260 * 261 * @returns VBox status code. 262 * @param apTasks Array of tasks which should be processed. 263 * @param cTasks Number of tasks in the array which should be processed. 264 */ 265 VMMR3DECL(int) PDMR3AsyncCompletionTaskSubmit(PPDMASYNCCOMPLETIONTASK apTasks[], unsigned cTasks); 266 267 /** 268 * Sets the user argument of a completion task. 269 * 270 * @returns VBox status code. 271 * @param pTask The async completion task. 272 * @param pvUser The user argument for the callback. 273 */ 274 VMMR3DECL(int) PDMR3AsyncCompletionTaskSetUserArg(PPDMASYNCCOMPLETIONTASK pTask, void *pvUser); 275 276 /** 277 * Suspends a async completion task. 278 * 279 * @returns VBox status codes: 280 * @retval VINF_SUCCESS on success. 281 * @retval VERR_PDM_ASYNC_COMPLETION_ALREADY_SUSPENDED if already suspended. 282 * @retval VERR_INVALID_HANDLE if pTask is invalid (asserts). 283 * @param pTask The async completion task. 284 */ 285 VMMR3DECL(int) PDMR3AsyncCompletionTaskSuspend(PPDMASYNCCOMPLETIONTASK pTask); 286 287 /** 288 * Suspends a async completion task. 289 * 290 * @returns VBox status codes: 291 * @retval VINF_SUCCESS on success. 292 * @retval VERR_PDM_ASYNC_COMPLETION_NOT_SUSPENDED if not suspended. 293 * @retval VERR_INVALID_HANDLE if pTask is invalid (asserts). 294 * @param pTask The async completion task. 295 */ 296 VMMR3DECL(int) PDMR3AsyncCompletionTaskResume(PPDMASYNCCOMPLETIONTASK pTask); 254 */ 255 VMMR3DECL(int) PDMR3AsyncCompletionEpRead(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, RTFOFF off, 256 PCPDMDATASEG paSegments, size_t cSegments, 257 size_t cbRead, void *pvUser, 258 PPPDMASYNCCOMPLETIONTASK ppTask); 259 260 /** 261 * Creates a write task on the given endpoint. 262 * 263 * @returns VBox status code. 264 * @param pEndpoint The file endpoint to write to. 265 * @param off Where to start writing at. 266 * @param paSegments Scatter gather list of the data to write. 267 * @param cSegments Number of segments in the list. 268 * @param cbWrite The overall number of bytes to write. 269 * @param pvUser Opaque user data returned in the completion callback 270 * upon completion of the task. 271 * @param ppTask Where to store the task handle on success. 272 */ 273 VMMR3DECL(int) PDMR3AsyncCompletionEpWrite(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, RTFOFF off, 274 PCPDMDATASEG paSegments, size_t cSegments, 275 size_t cbWrite, void *pvUser, 276 PPPDMASYNCCOMPLETIONTASK ppTask); 277 278 /** 279 * Creates a flush task on the given endpoint. 280 * 281 * Every read and write task initiated before the flush task is 282 * finished upon completion of this task. 283 * 284 * @returns VBox status code. 285 * @param pEndpoint The file endpoint to flush. 286 * @param pvUser Opaque user data returned in the completion callback 287 * upon completion of the task. 288 * @param ppTask Where to store the task handle on success. 289 */ 290 VMMR3DECL(int) PDMR3AsyncCompletionEpFlush(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, 291 void *pvUser, 292 PPPDMASYNCCOMPLETIONTASK ppTask); 293 294 /** 295 * Queries the size of an endpoint. 296 * Not that some endpoints may not support this and will return an error 297 * (sockets for example). 298 * 299 * @returns VBox status code. 300 * @retval VERR_NOT_SUPPORTED if the endpoint does not support this operation. 301 * @param pEndpoint The file endpoint. 302 * @param pcbSize Where to store the size of the endpoint. 303 */ 304 VMMR3DECL(int) PDMR3AsyncCompletionEpGetSize(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, 305 uint64_t *pcbSize); 297 306 298 307 /** 299 308 * Cancels a async completion task. 300 * The task doesn't have to be suspended. 309 * 310 * If you want to use this method, you have to take great create to make sure 311 * you will never attempt cancel a task which has been completed. Since there is 312 * no reference counting or anything on the task it self, you have to serialize 313 * the cancelation and completion paths such that the aren't racing one another. 301 314 * 302 315 * @returns VBox status code 303 * @param pTask The Task to cancel.316 * @param pTask The Task to cancel. 304 317 */ 305 318 VMMR3DECL(int) PDMR3AsyncCompletionTaskCancel(PPDMASYNCCOMPLETIONTASK pTask); 306 319 307 /** 308 * Destroys a async completion task. 309 * 310 * The task doesn't have to be suspended or anything. 311 * 312 * @returns VBox status codes: 313 * @retval VINF_SUCCESS on success. 314 * @retval VERR_INVALID_HANDLE if pTask is invalid but not NIL (asserts). 315 * @param pTask The async completion task. 316 */ 317 VMMR3DECL(int) PDMR3AsyncCompletionTaskDestroy(PPDMASYNCCOMPLETIONTASK pTask); 318 319 /* 320 * Host specific wrapper functions for the above API 321 */ 322 #if defined(RT_OS_LINUX) 323 324 struct iocb; 325 326 /** 327 * Creates a completion task for an IO operation on Linux. 328 * 329 * The pvCtx callback argument will be pIoCB. 330 * 331 * @returns VBox status code. 332 * @param ppTask Where to store the task handle on success. 333 * @param pTemplate The async completion template. 334 * @param pIoCB The asynchronous I/O control block to wait for. 335 * @param pvUser The user argument for the callback. 336 */ 337 DECLINLINE(int) PDMR3AsyncCompletionCreateLnxIO(PPPDMASYNCCOMPLETIONTASK ppTask, PPDMASYNCCOMPLETIONTEMPLATE pTemplate, const struct iocb *pIoCB, void *pvUser) 338 { 339 int rc = VINF_SUCCESS; 340 PPDMASYNCCOMPLETIONTASK pTask; 341 342 rc = PDMR3AsyncCompletionTaskCreate(&pTask, pTemplate, PDMASYNCCOMPLETIONTASKTYPE_HOST, (void *)pIoCB, pvUser); 343 if (RT_FAILURE(rc)) 344 { 345 AssertMsgFailed(("Creating Linux task failed\n")); 346 return rc; 347 } 348 349 *ppTask = pTask; 350 351 return rc; 352 } 353 #endif /* RT_OS_LINUX */ 354 355 #if defined(RT_OS_SOLARIS) || defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD) || defined(RT_OS_LINUX) 356 357 struct aiocb; 358 359 /** 360 * Creates a completion task for an AIO operation on Unix like systems like Solaris, Darwin or FreeBSD. 361 * This method must be used too on Linux if the real asynchronous solution is not available. 362 * 363 * The pvCtx callback argument will be pAioCB. 364 * 365 * @returns VBox status code. 366 * @param ppTask Where to store the task handle on success. 367 * @param pTemplate The async completion template. 368 * @param pIoCB The asynchronous I/O control block to wait for. 369 * @param pvUser The user argument for the callback. 370 */ 371 DECLINLINE(int) PDMR3AsyncCompletionCreateUnxAIO(PPPDMASYNCCOMPLETIONTASK ppTask, PPDMASYNCCOMPLETIONTEMPLATE pTemplate, const struct aiocb *pAioCB, void *pvUser) 372 { 373 int rc = VINF_SUCCESS; 374 PPDMASYNCCOMPLETIONTASK pTask; 375 376 rc = PDMR3AsyncCompletionTaskCreate(&pTask, pTemplate, PDMASYNCCOMPLETIONTASKTYPE_HOST, (void *)pAioCB, pvUser); 377 if (RT_FAILURE(rc)) 378 { 379 AssertMsgFailed(("Creating AIO task failed\n")); 380 return rc; 381 } 382 383 *ppTask = pTask; 384 385 return rc; 386 } 387 #endif /* RT_OS_SOLARIS || RT_OS_DARWIN || RT_OS_FREEBSD || RT_OS_LINUX */ 388 389 #ifdef RT_OS_OS2 390 /** 391 * Creates a completion task for an event semaphore on OS/2. 392 * 393 * The pvCtx callback argument will be hev. 394 * 395 * @returns VBox status code. 396 * @param ppTask Where to store the task handle on success. 397 * @param pTemplate The async completion template. 398 * @param hev The handle of the event semaphore to wait on. 399 * @param pvUser The user argument for the callback. 400 */ 401 DECLINLINE(int) PDMR3AsyncCompletionCreateOs2Event(PPPDMASYNCCOMPLETIONTASK ppTask, PPDMASYNCCOMPLETIONTEMPLATE pTemplate, unsigned long hev, void *pvUser) 402 { 403 int rc = VINF_SUCCESS; 404 PPDMASYNCCOMPLETIONTASK pTask; 405 406 rc = PDMR3AsyncCompletionTaskCreate(&pTask, pTemplate, PDMASYNCCOMPLETIONTASKTYPE_HOST, (void *)&hev, pvUser); 407 if (RT_FAILURE(rc)) 408 { 409 AssertMsgFailed(("Creating OS/2 task failed\n")); 410 return rc; 411 } 412 413 *ppTask = pTask; 414 415 return rc; 416 } 417 #endif /* RT_OS_OS2 */ 418 419 #ifdef RT_OS_WINDOWS 420 /** 421 * Creates a completion task for an object on Windows. 422 * 423 * The pvCtx callback argument will be hObject. 424 * 425 * @returns VBox status code. 426 * @param ppTask Where to store the task handle on success. 427 * @param pTemplate The async completion template. 428 * @param hObject The object to wait for. 429 * @param pvUser The user argument for the callback. 430 */ 431 DECLINLINE(int) PDMR3AsyncCompletionCreateWinObject(PPPDMASYNCCOMPLETIONTASK ppTask, PPDMASYNCCOMPLETIONTEMPLATE pTemplate, void *hObject, void *pvUser) 432 { 433 int rc = VINF_SUCCESS; 434 PPDMASYNCCOMPLETIONTASK pTask; 435 436 rc = PDMR3AsyncCompletionTaskCreate(&pTask, pTemplate, PDMASYNCCOMPLETIONTASKTYPE_HOST, (void *)hObject, pvUser); 437 if (RT_FAILURE(rc)) 438 { 439 AssertMsgFailed(("Creating Windows task failed\n")); 440 return rc; 441 } 442 443 *ppTask = pTask; 444 445 return rc; 446 } 447 #endif /* RT_OS_WINDOWS */ 448 449 /** 450 * Socket completion context (pvCtx). 451 */ 452 typedef struct PDMASYNCCOMPLETIONSOCKET 453 { 454 /** The socket. */ 455 RTSOCKET Socket; 456 /** Readable. */ 457 bool fReadable; 458 /** Writable. */ 459 bool fWriteable; 460 /** Exceptions. */ 461 bool fXcpt; 462 } PDMASYNCCOMPLETIONSOCKET; 463 /** Pointer to a socket completion context. */ 464 typedef PDMASYNCCOMPLETIONSOCKET *PPDMASYNCCOMPLETIONSOCKET; 465 466 /** 467 * Creates a completion task for a socket. 468 * 469 * The pvCtx callback argument will be pointing to a PDMASYNCCOMPLETIONSOCKET structure. 470 * 471 * @returns VBox status code. 472 * @param ppTask Where to store the task handle on success. 473 * @param pTemplate The async completion template. 474 * @param Socket The socket. 475 * @param fReadable Whether to callback when the socket becomes readable. 476 * @param fWriteable Whether to callback when the socket becomes writable. 477 * @param fXcpt Whether to callback on exception. 478 * @param pvUser The user argument for the callback. 479 */ 480 DECLINLINE(int) PDMR3AsyncCompletionCreateSocket(PPPDMASYNCCOMPLETIONTASK ppTask, PPDMASYNCCOMPLETIONTEMPLATE pTemplate, RTSOCKET Socket, bool fReadable, bool fWriteable, bool fXcpt, void *pvUser) 481 { 482 int rc = VINF_SUCCESS; 483 PPDMASYNCCOMPLETIONTASK pTask; 484 PDMASYNCCOMPLETIONSOCKET SocketContext; 485 486 SocketContext.Socket = Socket; 487 SocketContext.fReadable = fReadable; 488 SocketContext.fWriteable = fWriteable; 489 SocketContext.fXcpt = fXcpt; 490 491 rc = PDMR3AsyncCompletionTaskCreate(&pTask, pTemplate, PDMASYNCCOMPLETIONTASKTYPE_SOCKET, (void *)&SocketContext, pvUser); 492 if (RT_FAILURE(rc)) 493 { 494 AssertMsgFailed(("Creating Socket task failed\n")); 495 return rc; 496 } 497 498 *ppTask = pTask; 499 500 return rc; 501 } 502 503 #if 0 504 /** 505 * Modifies a socket completion task. 506 * 507 * @returns VBox status code. 508 * @retval VINF_SUCCESS on success. 509 * @retval VERR_NOT_SUPPORTED if the task isn't a socket task. 510 * @param pTemplate The async completion template. 511 * @param Socket The socket 512 * @param fReadable Whether to callback when the socket becomes readable. 513 * @param fWriteable Whether to callback when the socket becomes writable. 514 * @param fXcpt Whether to callback on exception. 515 */ 516 DECLINLINE(int) PDMR3AsyncCompletionModifySocket(PPDMASYNCCOMPLETIONTASK pTask, RTSOCKET Socket, bool fReadable, bool fWriteable, bool fXcpt) 517 { 518 int rc = VINF_SUCCESS; 519 PDMASYNCCOMPLETIONSOCKET SocketContext; 520 521 SocketContext.Socket = Socket; 522 SocketContext.fReadable = fReadable; 523 SocketContext.fWriteable = fWriteable; 524 SocketContext.fXcpt = fXcpt; 525 526 rc = PDMR3AsyncCompletionTaskAssociate(pTask, &SocketContext); 527 if (RT_FAILURE(rc)) 528 { 529 AssertMsgFailed(("Modifying Socket task failed\n")); 530 return rc; 531 } 532 533 return rc; 534 } 320 /** @} */ 321 322 __END_DECLS 323 535 324 #endif 536 325 537 /** @} */538 539 __END_DECLS540 541 #endif542 543 544 -
trunk/include/VBox/pdmdrv.h
r20096 r20167 684 684 * @param ppTemplate Where to store the template pointer on success. 685 685 * @param pfnCompleted The completion callback routine. 686 * @param pvTemplateUser Template user argument. 686 687 * @param pszDesc Description. 687 688 */ 688 689 DECLR3CALLBACKMEMBER(int, pfnPDMAsyncCompletionTemplateCreate,(PPDMDRVINS pDrvIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate, 689 PFNPDMASYNCCOMPLETEDRV pfnCompleted, const char *pszDesc)); 690 PFNPDMASYNCCOMPLETEDRV pfnCompleted, void *pvTemplateUser, 691 const char *pszDesc)); 690 692 #endif 691 693 … … 906 908 */ 907 909 DECLINLINE(int) PDMDrvHlpPDMAsyncCompletionTemplateCreate(PPDMDRVINS pDrvIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate, 908 PFNPDMASYNCCOMPLETEDRV pfnCompleted, const char *pszDesc)909 { 910 return pDrvIns->pDrvHlp->pfnPDMAsyncCompletionTemplateCreate(pDrvIns, ppTemplate, pfnCompleted, p szDesc);910 PFNPDMASYNCCOMPLETEDRV pfnCompleted, void *pvTemplateUser, const char *pszDesc) 911 { 912 return pDrvIns->pDrvHlp->pfnPDMAsyncCompletionTemplateCreate(pDrvIns, ppTemplate, pfnCompleted, pvTemplateUser, pszDesc); 911 913 } 912 914 #endif -
trunk/include/VBox/pdmifs.h
r19959 r20167 104 104 /** PDMIBLOCKASYNCPORT - Async version of the block interface (Up) Coupled with PDMINTERFACE_BLOCK_ASYNC. */ 105 105 PDMINTERFACE_BLOCK_ASYNC_PORT, 106 /** PDMITRANSPORTASYNC - Transport data async to their target (Down) Coupled with PDMINTERFACE_TRANSPORT_ASYNC_PORT. */107 PDMINTERFACE_TRANSPORT_ASYNC,108 /** PDMITRANSPORTASYNCPORT - Transport data async to their target (Up) Coupled with PDMINTERFACE_TRANSPORT_ASYNC. */109 PDMINTERFACE_TRANSPORT_ASYNC_PORT,110 106 111 107 … … 1318 1314 1319 1315 } PDMIMEDIAASYNC; 1320 1321 1322 /** Pointer to a async media notify interface. */1323 typedef struct PDMITRANSPORTASYNCPORT *PPDMITRANSPORTASYNCPORT;1324 /**1325 * Notification interface for completed I/O tasks.1326 * Pair with PDMITRANSPORTASYNC.1327 */1328 typedef struct PDMITRANSPORTASYNCPORT1329 {1330 /**1331 * Notify completion of tasks.1332 *1333 * @returns VBox status code.1334 * @param pInterface Pointer to the interface structure containing the called function pointer.1335 * @param pvUser The user argument given in pfnTasksSubmit.1336 * @thread Any thread.1337 */1338 DECLR3CALLBACKMEMBER(int, pfnTaskCompleteNotify, (PPDMITRANSPORTASYNCPORT pInterface, void *pvUser));1339 1340 } PDMITRANSPORTASYNCPORT;1341 1342 1343 /** Pointer to a async media interface. */1344 typedef struct PDMITRANSPORTASYNC *PPDMITRANSPORTASYNC;1345 /**1346 * Asynchronous transport interface.1347 * Makes up the fundation for PDMIMEDIAASYNC.1348 */1349 typedef struct PDMITRANSPORTASYNC1350 {1351 /**1352 * Read bits synchronous.1353 * Blocks until finished.1354 *1355 * @returns VBox status code.1356 * @param pInterface Pointer to the interface structure containint the called function pointer.1357 * @param pStorage The storage handle to read from.1358 * @param off Offset to start reading from.1359 * @param pvBuf Where to store the read bits.1360 * @param cbRead Number of bytes to read.1361 * @param pcbRead Where to store the number of bytes actually read.1362 * @thread Any thread.1363 */1364 DECLR3CALLBACKMEMBER(int, pfnReadSynchronous, (PPDMITRANSPORTASYNC pInterface, void *pStorage,1365 uint64_t off, void *pvBuf, size_t cbRead, size_t *pcbRead));1366 1367 /**1368 * Write bits synchronous.1369 * Blocks until finished.1370 *1371 * @returns VBox status code.1372 * @param pInterface Pointer to the interface structure containint the called function pointer.1373 * @param pStorage The storage handle to write to.1374 * @param off Offset to start reading from.1375 * @param pvBuf Pointer to the buffer which contains the data to write.1376 * @param cbWrite Number of bytes to read.1377 * @param pcbWritten Where to store the number of bytes actually read.1378 * @thread Any thread.1379 */1380 DECLR3CALLBACKMEMBER(int, pfnWriteSynchronous, (PPDMITRANSPORTASYNC pInterface, void *pStorage,1381 uint64_t off, const void *pvBuf, size_t cbWrite, size_t *pcbWritten));1382 1383 /**1384 * Make sure that the bits written are actually on the storage medium.1385 * This is a synchronous task1386 *1387 * @returns VBox status code.1388 * @param pInterface Pointer to the interface structure containing the called function pointer.1389 * @param pStorage The storage handle to flush-1390 * @thread Any thread.1391 */1392 DECLR3CALLBACKMEMBER(int, pfnFlushSynchronous,(PPDMITRANSPORTASYNC pInterface, void *pStorage));1393 1394 /**1395 * Get the media size in bytes.1396 *1397 * @returns Media size in bytes.1398 * @param pInterface Pointer to the interface structure containing the called function pointer.1399 * @param pStorage The storage handle.1400 * @thread Any thread.1401 */1402 DECLR3CALLBACKMEMBER(uint64_t, pfnGetSize,(PPDMITRANSPORTASYNC pInterface, void *pStorage));1403 1404 /**1405 * Check if the media is readonly or not.1406 *1407 * @returns true if readonly.1408 * @returns false if read/write.1409 * @param pInterface Pointer to the interface structure containing the called function pointer.1410 * @param pStorage The storage handle.1411 * @thread Any thread.1412 */1413 DECLR3CALLBACKMEMBER(bool, pfnIsReadOnly,(PPDMITRANSPORTASYNC pInterface, void *pStorage));1414 1415 /**1416 * Opens the data source.1417 *1418 * @returns VBox status code.1419 * @param pInterface Pointer to the interface structure containing the called function pointer.1420 * @param pszPath The path to open.1421 * @param fReadonly If the target shoudl opened readonly.1422 * @param ppStorage Where to store the storage handle.1423 * @thread Any thread.1424 */1425 DECLR3CALLBACKMEMBER(int, pfnOpen, (PPDMITRANSPORTASYNC pInterface, const char *pszTargetPath, bool fReadonly, void **ppStorage));1426 1427 /**1428 * Close the data source.1429 *1430 * @returns VBox status code.1431 * @param pInterface Pointer to the interface structure containing the called function pointer.1432 * @param pStorage The storage handle to close.1433 * @thread Any thread.1434 */1435 DECLR3CALLBACKMEMBER(int, pfnClose, (PPDMITRANSPORTASYNC pInterface, void *pStorage));1436 1437 /**1438 * Prepare an asynchronous read task.1439 *1440 * @returns VBox status code.1441 * @param pInterface Pointer to the interface structure containing the called function pointer.1442 * @param pStorage The storage handle.1443 * @param uOffset The offset to start reading from.1444 * @param pvBuf Where to store read bits.1445 * @param cbRead How many bytes to read.1446 * @param ppTask Where to store the opaque task handle.1447 */1448 DECLR3CALLBACKMEMBER(int, pfnPrepareRead, (PPDMITRANSPORTASYNC pInterface, void *pStorage, uint64_t uOffset,1449 void *pvBuf, size_t cbRead, void **ppTask));1450 1451 /**1452 * Prepare an asynchronous write task.1453 *1454 * @returns VBox status code.1455 * @param pInterface Pointer to the interface structure containing the called function pointer.1456 * @param pStorage The storage handle.1457 * @param uOffset The offset to start writing to.1458 * @param pvBuf Where to read the data from.1459 * @param cbWrite How many bytes to write.1460 * @param ppTask Where to store the opaque task handle.1461 */1462 DECLR3CALLBACKMEMBER(int, pfnPrepareWrite, (PPDMITRANSPORTASYNC pInterface, void *pStorage, uint64_t uOffset,1463 void *pvBuf, size_t cbWrite, void **ppTask));1464 1465 /**1466 * Submit an array of tasks for processing1467 *1468 * @returns VBox status code.1469 * @param pInterface Pointer to the interface structure containing the called function pointer.1470 * @param apTasks Array of task handles to submit.1471 * @param cTasks How many tasks to submit.1472 * @param pvUser User data which is passed on completion.1473 */1474 DECLR3CALLBACKMEMBER(int, pfnTasksSubmit, (PPDMITRANSPORTASYNC pInterface, void *apTasks[], unsigned cTasks, void *pvUser));1475 } PDMITRANSPORTASYNC;1476 1316 1477 1317 -
trunk/src/VBox/Devices/Builtins.cpp
r19968 r20167 276 276 #endif 277 277 278 #if defined(VBOX_WITH_PDM_ASYNC_COMPLETION)279 rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvRawImageAsync);280 if (RT_FAILURE(rc))281 return rc;282 283 rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvTransportAsync);284 if (RT_FAILURE(rc))285 return rc;286 #endif287 278 #ifdef VBOX_WITH_SCSI 288 279 rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvSCSI); … … 295 286 return rc; 296 287 #endif 297 #endif298 299 #ifdef VBOX_WITH_FAULT_INJECTION300 rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvFaultInject);301 if (RT_FAILURE(rc))302 return rc;303 288 #endif 304 289 -
trunk/src/VBox/Devices/Builtins.h
r19624 r20167 120 120 #endif 121 121 122 #ifdef VBOX_WITH_PDM_ASYNC_COMPLETION123 extern const PDMDRVREG g_DrvRawImageAsync;124 extern const PDMDRVREG g_DrvTransportAsync;125 #endif126 127 122 #ifdef VBOX_WITH_SCSI 128 123 extern const PDMDRVREG g_DrvSCSI; … … 132 127 #endif 133 128 134 #ifdef VBOX_WITH_FAULT_INJECTION135 extern const PDMDRVREG g_DrvFaultInject;136 #endif137 138 129 __END_DECLS 139 130 -
trunk/src/VBox/Devices/Makefile.kmk
r20100 r20167 903 903 ifdef VBOX_WITH_PDM_ASYNC_COMPLETION 904 904 Drivers_DEFS += VBOX_WITH_PDM_ASYNC_COMPLETION 905 Drivers_SOURCES += \906 Storage/DrvRawImageAsync.cpp \907 Storage/DrvTransportAsync.cpp908 905 endif #VBOX_WITH_PDM_ASYNC_COMPLETION 909 906 … … 915 912 Storage/DrvSCSIHost.cpp 916 913 endif # VBOX_WITH_SCSI 917 918 ifdef VBOX_WITH_FAULT_INJECTION919 Drivers_DEFS += VBOX_WITH_FAULT_INJECTION920 Drivers_SOURCES += \921 Storage/DrvFaultInject.cpp922 endif # VBOX_WITH_FAULT_INJECTION923 914 924 915 # -
trunk/src/VBox/Devices/Storage/DrvVD.cpp
r18778 r20167 27 27 #include <VBox/VBoxHDD.h> 28 28 #include <VBox/pdmdrv.h> 29 #include <VBox/pdmasynccompletion.h> 29 30 #include <iprt/alloc.h> 30 31 #include <iprt/assert.h> … … 34 35 #include <iprt/cache.h> 35 36 #include <iprt/tcp.h> 37 #include <iprt/semaphore.h> 36 38 37 39 #ifdef VBOX_WITH_INIP … … 72 74 ( (PVBOXDISK)((uintptr_t)pInterface - RT_OFFSETOF(VBOXDISK, IMediaAsync)) ) 73 75 74 /** Converts a pointer to VBOXDISK::ITransportAsyncPort to a PVBOXDISK. */75 #define PDMITRANSPORTASYNCPORT_2_VBOXDISK(pInterface) \76 ( (PVBOXDISK)((uintptr_t)pInterface - RT_OFFSETOF(VBOXDISK, ITransportAsyncPort)) )77 78 /**79 * Structure for an async I/O task.80 */81 typedef struct DRVVDASYNCTASK82 {83 /** Callback which is called on completion. */84 PFNVDCOMPLETED pfnCompleted;85 /** Opqaue user data which is passed on completion. */86 void *pvUser;87 /** Opaque user data the caller passed on transfer initiation. */88 void *pvUserCaller;89 } DRVVDASYNCTASK, *PDRVVDASYNCTASK;90 91 76 /** 92 77 * VBox disk container, image information, private part. … … 102 87 VDINTERFACE VDIConfig; 103 88 } VBOXIMAGE, *PVBOXIMAGE; 89 90 /** 91 * Storage backend data. 92 */ 93 typedef struct DRVVDSTORAGEBACKEND 94 { 95 /** PDM async completion end point. */ 96 PPDMASYNCCOMPLETIONENDPOINT pEndpoint; 97 /** The template. */ 98 PPDMASYNCCOMPLETIONTEMPLATE pTemplate; 99 /** Event semaphore for synchronous operations. */ 100 RTSEMEVENT EventSem; 101 /** Flag whether a synchronous operation is currently pending. */ 102 volatile bool fSyncIoPending; 103 /** Callback routine */ 104 PFNVDCOMPLETED pfnCompleted; 105 } DRVVDSTORAGEBACKEND, *PDRVVDSTORAGEBACKEND; 104 106 105 107 /** … … 140 142 /** The async media port interface above. */ 141 143 PPDMIMEDIAASYNCPORT pDrvMediaAsyncPort; 142 /** Pointer to the asynchronous media driver below. */143 PPDMITRANSPORTASYNC pDrvTransportAsync;144 /** Async transport port interface. */145 PDMITRANSPORTASYNCPORT ITransportAsyncPort;146 /** Our cache to reduce allocation overhead. */147 PRTOBJCACHE pCache;148 144 /** Pointer to the list of data we need to keep per image. */ 149 145 PVBOXIMAGE pImages; … … 207 203 *******************************************************************************/ 208 204 209 static DECLCALLBACK(int) drvvdAsyncIOOpen(void *pvUser, const char *pszLocation, bool fReadonly, void **ppStorage) 205 static DECLCALLBACK(void) drvvdAsyncTaskCompleted(PPDMDRVINS pDrvIns, void *pvTemplateUser, void *pvUser) 206 { 207 PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK); 208 PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pvTemplateUser; 209 int rc = VINF_VD_ASYNC_IO_FINISHED; 210 void *pvCallerUser = NULL; 211 212 if (pStorageBackend->fSyncIoPending) 213 { 214 pStorageBackend->fSyncIoPending; 215 RTSemEventSignal(pStorageBackend->EventSem); 216 } 217 else if (pStorageBackend->pfnCompleted) 218 rc = pStorageBackend->pfnCompleted(pvUser, &pvCallerUser); 219 else 220 pvCallerUser = pvUser; 221 222 if (rc == VINF_VD_ASYNC_IO_FINISHED) 223 { 224 rc = pThis->pDrvMediaAsyncPort->pfnTransferCompleteNotify(pThis->pDrvMediaAsyncPort, pvCallerUser); 225 AssertRC(rc); 226 } 227 else 228 AssertMsg(rc == VERR_VD_ASYNC_IO_IN_PROGRESS, ("Invalid return code from disk backend rc=%Rrc\n", rc)); 229 } 230 231 static DECLCALLBACK(int) drvvdAsyncIOOpen(void *pvUser, const char *pszLocation, bool fReadonly, 232 PFNVDCOMPLETED pfnCompleted, void **ppStorage) 210 233 { 211 234 PVBOXDISK pDrvVD = (PVBOXDISK)pvUser; 212 213 return pDrvVD->pDrvTransportAsync->pfnOpen(pDrvVD->pDrvTransportAsync, pszLocation, fReadonly, ppStorage); 235 PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)RTMemAllocZ(sizeof(DRVVDSTORAGEBACKEND)); 236 int rc = VINF_SUCCESS; 237 238 if (pStorageBackend) 239 { 240 pStorageBackend->fSyncIoPending = false; 241 pStorageBackend->pfnCompleted = pfnCompleted; 242 243 int rc = RTSemEventCreate(&pStorageBackend->EventSem); 244 if (RT_SUCCESS(rc)) 245 { 246 rc = PDMDrvHlpPDMAsyncCompletionTemplateCreate(pDrvVD->pDrvIns, &pStorageBackend->pTemplate, 247 drvvdAsyncTaskCompleted, pStorageBackend, "AsyncTaskCompleted"); 248 if (RT_SUCCESS(rc)) 249 { 250 rc = PDMR3AsyncCompletionEpCreateForFile(&pStorageBackend->pEndpoint, pszLocation, 251 fReadonly 252 ? PDMACEP_FILE_FLAGS_READ_ONLY | PDMACEP_FILE_FLAGS_CACHING 253 : PDMACEP_FILE_FLAGS_CACHING, 254 pStorageBackend->pTemplate); 255 if (RT_SUCCESS(rc)) 256 { 257 *ppStorage = pStorageBackend; 258 return VINF_SUCCESS; 259 } 260 261 PDMR3AsyncCompletionTemplateDestroy(pStorageBackend->pTemplate); 262 } 263 RTSemEventDestroy(pStorageBackend->EventSem); 264 } 265 RTMemFree(pStorageBackend); 266 } 267 else 268 rc = VERR_NO_MEMORY; 269 270 return rc; 214 271 } 215 272 … … 217 274 { 218 275 PVBOXDISK pDrvVD = (PVBOXDISK)pvUser; 219 220 AssertMsg(pDrvVD->pDrvTransportAsync, ("Asynchronous function called but no async transport interface below\n")); 221 222 return pDrvVD->pDrvTransportAsync->pfnClose(pDrvVD->pDrvTransportAsync, pStorage); 223 } 224 225 static DECLCALLBACK(int) drvvdAsyncIORead(void *pvUser, void *pStorage, uint64_t uOffset, 226 size_t cbRead, void *pvBuf, size_t *pcbRead) 276 PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage; 277 278 PDMR3AsyncCompletionEpClose(pStorageBackend->pEndpoint); 279 PDMR3AsyncCompletionTemplateDestroy(pStorageBackend->pTemplate); 280 RTSemEventDestroy(pStorageBackend->EventSem); 281 RTMemFree(pStorageBackend); 282 283 return VINF_SUCCESS;; 284 } 285 286 static DECLCALLBACK(int) drvvdAsyncIOGetSize(void *pvUser, void *pStorage, uint64_t *pcbSize) 227 287 { 228 288 PVBOXDISK pDrvVD = (PVBOXDISK)pvUser; 229 230 AssertMsg(pDrvVD->pDrvTransportAsync, ("Asynchronous function called but no async transport interface below\n")); 231 232 return pDrvVD->pDrvTransportAsync->pfnReadSynchronous(pDrvVD->pDrvTransportAsync, 233 pStorage, 234 uOffset, pvBuf, cbRead, pcbRead); 235 } 236 237 static DECLCALLBACK(int) drvvdAsyncIOWrite(void *pvUser, void *pStorage, uint64_t uOffset, 238 size_t cbWrite, const void *pvBuf, size_t *pcbWritten) 289 PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage; 290 291 return PDMR3AsyncCompletionEpGetSize(pStorageBackend->pEndpoint, pcbSize); 292 } 293 294 static DECLCALLBACK(int) drvvdAsyncIOReadSync(void *pvUser, void *pStorage, uint64_t uOffset, 295 size_t cbRead, void *pvBuf, size_t *pcbRead) 239 296 { 240 297 PVBOXDISK pDrvVD = (PVBOXDISK)pvUser; 241 242 AssertMsg(pDrvVD->pDrvTransportAsync, ("Asynchronous function called but no async transport interface below\n")); 243 244 return pDrvVD->pDrvTransportAsync->pfnWriteSynchronous(pDrvVD->pDrvTransportAsync, 245 pStorage, 246 uOffset, pvBuf, cbWrite, pcbWritten); 247 } 248 249 static DECLCALLBACK(int) drvvdAsyncIOFlush(void *pvUser, void *pStorage) 250 { 251 PVBOXDISK pDrvVD = (PVBOXDISK)pvUser; 252 253 AssertMsg(pDrvVD->pDrvTransportAsync, ("Asynchronous function called but no async transport interface below\n")); 254 255 return pDrvVD->pDrvTransportAsync->pfnFlushSynchronous(pDrvVD->pDrvTransportAsync, pStorage); 256 } 257 258 static DECLCALLBACK(int) drvvdAsyncIOPrepareRead(void *pvUser, void *pStorage, uint64_t uOffset, void *pvBuf, size_t cbRead, void **ppTask) 259 { 260 PVBOXDISK pDrvVD = (PVBOXDISK)pvUser; 261 262 AssertMsg(pDrvVD->pDrvTransportAsync, ("Asynchronous function called but no async transport interface below\n")); 263 264 return pDrvVD->pDrvTransportAsync->pfnPrepareRead(pDrvVD->pDrvTransportAsync, pStorage, uOffset, pvBuf, cbRead, ppTask); 265 } 266 267 static DECLCALLBACK(int) drvvdAsyncIOPrepareWrite(void *pvUser, void *pStorage, uint64_t uOffset, void *pvBuf, size_t cbWrite, void **ppTask) 268 { 269 PVBOXDISK pDrvVD = (PVBOXDISK)pvUser; 270 271 AssertMsg(pDrvVD->pDrvTransportAsync, ("Asynchronous function called but no async transport interface below\n")); 272 273 return pDrvVD->pDrvTransportAsync->pfnPrepareWrite(pDrvVD->pDrvTransportAsync, pStorage, uOffset, pvBuf, cbWrite, ppTask); 274 } 275 276 static DECLCALLBACK(int) drvvdAsyncIOTasksSubmit(void *pvUser, void *apTasks[], unsigned cTasks, void *pvUser2, 277 void *pvUserCaller, PFNVDCOMPLETED pfnTasksCompleted) 278 { 279 PVBOXDISK pDrvVD = (PVBOXDISK)pvUser; 280 PDRVVDASYNCTASK pDrvVDAsyncTask; 281 int rc; 282 283 AssertMsg(pDrvVD->pDrvTransportAsync, ("Asynchronous function called but no async transport interface below\n")); 284 285 rc = RTCacheRequest(pDrvVD->pCache, (void **)&pDrvVDAsyncTask); 286 298 PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage; 299 PDMDATASEG DataSeg; 300 PPDMASYNCCOMPLETIONTASK pTask; 301 302 Assert(!pStorageBackend->fSyncIoPending); 303 pStorageBackend->fSyncIoPending = true; 304 DataSeg.cbSeg = cbRead; 305 DataSeg.pvSeg = pvBuf; 306 307 int rc = PDMR3AsyncCompletionEpRead(pStorageBackend->pEndpoint, uOffset, &DataSeg, 1, cbRead, NULL, &pTask); 287 308 if (RT_FAILURE(rc)) 288 309 return rc; 289 310 290 pDrvVDAsyncTask->pfnCompleted = pfnTasksCompleted; 291 pDrvVDAsyncTask->pvUser = pvUser2; 292 pDrvVDAsyncTask->pvUserCaller = pvUserCaller; 293 294 return pDrvVD->pDrvTransportAsync->pfnTasksSubmit(pDrvVD->pDrvTransportAsync, apTasks, cTasks, pDrvVDAsyncTask); 295 } 311 /* Wait */ 312 rc = RTSemEventWait(pStorageBackend->EventSem, RT_INDEFINITE_WAIT); 313 AssertRC(rc); 314 315 if (pcbRead) 316 *pcbRead = cbRead; 317 318 return VINF_SUCCESS; 319 } 320 321 static DECLCALLBACK(int) drvvdAsyncIOWriteSync(void *pvUser, void *pStorage, uint64_t uOffset, 322 size_t cbWrite, const void *pvBuf, size_t *pcbWritten) 323 { 324 PVBOXDISK pDrvVD = (PVBOXDISK)pvUser; 325 PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage; 326 PDMDATASEG DataSeg; 327 PPDMASYNCCOMPLETIONTASK pTask; 328 329 Assert(!pStorageBackend->fSyncIoPending); 330 pStorageBackend->fSyncIoPending = true; 331 DataSeg.cbSeg = cbWrite; 332 DataSeg.pvSeg = (void *)pvBuf; 333 334 int rc = PDMR3AsyncCompletionEpWrite(pStorageBackend->pEndpoint, uOffset, &DataSeg, 1, cbWrite, NULL, &pTask); 335 if (RT_FAILURE(rc)) 336 return rc; 337 338 /* Wait */ 339 rc = RTSemEventWait(pStorageBackend->EventSem, RT_INDEFINITE_WAIT); 340 AssertRC(rc); 341 342 if (pcbWritten) 343 *pcbWritten = cbWrite; 344 345 return VINF_SUCCESS; 346 } 347 348 static DECLCALLBACK(int) drvvdAsyncIOFlushSync(void *pvUser, void *pStorage) 349 { 350 PVBOXDISK pDrvVD = (PVBOXDISK)pvUser; 351 PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage; 352 PPDMASYNCCOMPLETIONTASK pTask; 353 354 Assert(!pStorageBackend->fSyncIoPending); 355 pStorageBackend->fSyncIoPending = true; 356 357 int rc = PDMR3AsyncCompletionEpFlush(pStorageBackend->pEndpoint, NULL, &pTask); 358 if (RT_FAILURE(rc)) 359 return rc; 360 361 /* Wait */ 362 rc = RTSemEventWait(pStorageBackend->EventSem, RT_INDEFINITE_WAIT); 363 AssertRC(rc); 364 365 return VINF_SUCCESS; 366 } 367 368 static DECLCALLBACK(int) drvvdAsyncIOReadAsync(void *pvUser, void *pStorage, uint64_t uOffset, 369 PCPDMDATASEG paSegments, size_t cSegments, 370 size_t cbRead, void *pvCompletion, 371 void **ppTask) 372 { 373 PVBOXDISK pDrvVD = (PVBOXDISK)pvUser; 374 PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage; 375 376 return PDMR3AsyncCompletionEpRead(pStorageBackend->pEndpoint, uOffset, paSegments, cSegments, cbRead, 377 pvCompletion, (PPPDMASYNCCOMPLETIONTASK)ppTask); 378 } 379 380 static DECLCALLBACK(int) drvvdAsyncIOWriteAsync(void *pvUser, void *pStorage, uint64_t uOffset, 381 PCPDMDATASEG paSegments, size_t cSegments, 382 size_t cbWrite, void *pvCompletion, 383 void **ppTask) 384 { 385 PVBOXDISK pDrvVD = (PVBOXDISK)pvUser; 386 PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage; 387 388 return PDMR3AsyncCompletionEpWrite(pStorageBackend->pEndpoint, uOffset, paSegments, cSegments, cbWrite, 389 pvCompletion, (PPPDMASYNCCOMPLETIONTASK)ppTask); 390 } 391 392 static DECLCALLBACK(int) drvvdAsyncIOFlushAsync(void *pvUser, void *pStorage, 393 void *pvCompletion, void **ppTask) 394 { 395 PVBOXDISK pDrvVD = (PVBOXDISK)pvUser; 396 PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage; 397 398 return PDMR3AsyncCompletionEpFlush(pStorageBackend->pEndpoint, pvCompletion, 399 (PPPDMASYNCCOMPLETIONTASK)ppTask); 400 } 401 296 402 297 403 /******************************************************************************* … … 641 747 *******************************************************************************/ 642 748 643 static DECLCALLBACK(int) drvvdTasksCompleteNotify(PPDMITRANSPORTASYNCPORT pInterface, void *pvUser) 644 { 645 PVBOXDISK pThis = PDMITRANSPORTASYNCPORT_2_VBOXDISK(pInterface); 646 PDRVVDASYNCTASK pDrvVDAsyncTask = (PDRVVDASYNCTASK)pvUser; 647 int rc = VINF_VD_ASYNC_IO_FINISHED; 648 649 /* Having a completion callback for a task is not mandatory. */ 650 if (pDrvVDAsyncTask->pfnCompleted) 651 rc = pDrvVDAsyncTask->pfnCompleted(pDrvVDAsyncTask->pvUser); 652 653 /* Check if the request is finished. */ 654 if (rc == VINF_VD_ASYNC_IO_FINISHED) 655 { 656 rc = pThis->pDrvMediaAsyncPort->pfnTransferCompleteNotify(pThis->pDrvMediaAsyncPort, pDrvVDAsyncTask->pvUserCaller); 657 } 658 else if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS) 659 rc = VINF_SUCCESS; 660 661 rc = RTCacheInsert(pThis->pCache, pDrvVDAsyncTask); 662 AssertRC(rc); 663 664 return rc; 749 static DECLCALLBACK(int) drvvdTasksCompleteNotify(PPDMDRVINS pDrvIns, void *pvUser) 750 { 751 return VERR_NOT_IMPLEMENTED; 665 752 } 666 753 … … 684 771 case PDMINTERFACE_MEDIA_ASYNC: 685 772 return pThis->fAsyncIOSupported ? &pThis->IMediaAsync : NULL; 686 case PDMINTERFACE_TRANSPORT_ASYNC_PORT:687 return &pThis->ITransportAsyncPort;688 773 default: 689 774 return NULL; … … 743 828 pThis->IMediaAsync.pfnStartWrite = drvvdStartWrite; 744 829 745 /* ITransportAsyncPort */746 pThis->ITransportAsyncPort.pfnTaskCompleteNotify = drvvdTasksCompleteNotify;747 748 830 /* Initialize supported VD interfaces. */ 749 831 pThis->pVDIfsDisk = NULL; … … 761 843 pThis->VDIAsyncIOCallbacks.pfnOpen = drvvdAsyncIOOpen; 762 844 pThis->VDIAsyncIOCallbacks.pfnClose = drvvdAsyncIOClose; 763 pThis->VDIAsyncIOCallbacks.pfnRead = drvvdAsyncIORead; 764 pThis->VDIAsyncIOCallbacks.pfnWrite = drvvdAsyncIOWrite; 765 pThis->VDIAsyncIOCallbacks.pfnFlush = drvvdAsyncIOFlush; 766 pThis->VDIAsyncIOCallbacks.pfnPrepareRead = drvvdAsyncIOPrepareRead; 767 pThis->VDIAsyncIOCallbacks.pfnPrepareWrite = drvvdAsyncIOPrepareWrite; 768 pThis->VDIAsyncIOCallbacks.pfnTasksSubmit = drvvdAsyncIOTasksSubmit; 845 pThis->VDIAsyncIOCallbacks.pfnGetSize = drvvdAsyncIOGetSize; 846 pThis->VDIAsyncIOCallbacks.pfnReadSync = drvvdAsyncIOReadSync; 847 pThis->VDIAsyncIOCallbacks.pfnWriteSync = drvvdAsyncIOWriteSync; 848 pThis->VDIAsyncIOCallbacks.pfnFlushSync = drvvdAsyncIOFlushSync; 849 pThis->VDIAsyncIOCallbacks.pfnReadAsync = drvvdAsyncIOReadAsync; 850 pThis->VDIAsyncIOCallbacks.pfnWriteAsync = drvvdAsyncIOWriteAsync; 851 pThis->VDIAsyncIOCallbacks.pfnFlushAsync = drvvdAsyncIOFlushAsync; 769 852 770 853 rc = VDInterfaceAdd(&pThis->VDIAsyncIO, "DrvVD_AsyncIO", VDINTERFACETYPE_ASYNCIO, … … 820 903 pThis->fAsyncIOSupported = true; 821 904 822 /* Success query the async transport interface. */ 823 pThis->pDrvTransportAsync = (PPDMITRANSPORTASYNC)pBase->pfnQueryInterface(pBase, PDMINTERFACE_TRANSPORT_ASYNC); 824 if (!pThis->pDrvTransportAsync) 825 { 826 /* An attached driver without an async transport interface - impossible. */ 827 AssertMsgFailed(("Configuration error: No async transport interface below!\n")); 828 return VERR_PDM_MISSING_INTERFACE_ABOVE; 829 } 905 /** @todo: Use PDM async completion manager */ 830 906 } 831 907 } … … 1108 1184 } 1109 1185 1110 /*1111 * We know definitly if async I/O is supported now.1112 * Create cache if it is supported.1113 */1114 if (pThis->fAsyncIOSupported)1115 {1116 rc = RTCacheCreate(&pThis->pCache, 0, sizeof(DRVVDASYNCTASK), RTOBJCACHE_PROTECT_INSERT);1117 AssertMsgRC(rc, ("Failed to create cache rc=%Rrc\n", rc));1118 }1119 1120 1186 /* Switch to runtime error facility. */ 1121 1187 pThis->fErrorUseRuntime = true; … … 1141 1207 1142 1208 drvvdFreeImages(pThis); 1143 if (pThis->pCache)1144 {1145 rc = RTCacheDestroy(pThis->pCache);1146 AssertRC(rc);1147 }1148 1209 } 1149 1210 -
trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp
r19921 r20167 432 432 PVDINTERFACEASYNCIO pInterfaceAsyncIOCallbacks; 433 433 /** 434 * Pointer to an array of task handles for task submission.434 * Pointer to an array of segment entries for async I/O. 435 435 * This is an optimization because the task number to submit is not known 436 436 * and allocating/freeing an array in the read/write functions every time 437 437 * is too expensive. 438 438 */ 439 void **apTask;440 /** Entries available in the task handlearray. */441 unsigned c Task;439 PPDMDATASEG paSegments; 440 /** Entries available in the segments array. */ 441 unsigned cSegments; 442 442 443 443 /** Open flags passed by VBoxHD layer. */ … … 584 584 ? true 585 585 : false, 586 NULL, 586 587 &pVmdkFile->pStorage); 587 588 pVmdkFile->fAsyncIO = true; … … 670 671 671 672 if (pVmdkFile->fAsyncIO) 672 return pImage->pInterfaceAsyncIOCallbacks->pfnRead (pImage->pInterfaceAsyncIO->pvUser,673 pVmdkFile->pStorage, uOffset,674 cbToRead, pvBuf, pcbRead);673 return pImage->pInterfaceAsyncIOCallbacks->pfnReadSync(pImage->pInterfaceAsyncIO->pvUser, 674 pVmdkFile->pStorage, uOffset, 675 cbToRead, pvBuf, pcbRead); 675 676 else 676 677 return RTFileReadAt(pVmdkFile->File, uOffset, pvBuf, cbToRead, pcbRead); … … 687 688 688 689 if (pVmdkFile->fAsyncIO) 689 return pImage->pInterfaceAsyncIOCallbacks->pfnWrite (pImage->pInterfaceAsyncIO->pvUser,690 pVmdkFile->pStorage, uOffset,691 cbToWrite, pvBuf, pcbWritten);690 return pImage->pInterfaceAsyncIOCallbacks->pfnWriteSync(pImage->pInterfaceAsyncIO->pvUser, 691 pVmdkFile->pStorage, uOffset, 692 cbToWrite, pvBuf, pcbWritten); 692 693 else 693 694 return RTFileWriteAt(pVmdkFile->File, uOffset, pvBuf, cbToWrite, pcbWritten); … … 730 731 731 732 if (pVmdkFile->fAsyncIO) 732 return pImage->pInterfaceAsyncIOCallbacks->pfnFlush (pImage->pInterfaceAsyncIO->pvUser,733 pVmdkFile->pStorage);733 return pImage->pInterfaceAsyncIOCallbacks->pfnFlushSync(pImage->pInterfaceAsyncIO->pvUser, 734 pVmdkFile->pStorage); 734 735 else 735 736 return RTFileFlush(pVmdkFile->File); … … 5740 5741 PVMDKEXTENT pExtent; 5741 5742 int rc = VINF_SUCCESS; 5742 unsigned c TasksToSubmit= 0;5743 unsigned cSegments = 0; 5743 5744 PPDMDATASEG paSegCurrent = paSeg; 5744 5745 size_t cbLeftInCurrentSegment = paSegCurrent->cbSeg; … … 5773 5774 } 5774 5775 5775 /* Clip readrange to remain in this extent. */5776 /* Clip write range to remain in this extent. */ 5776 5777 cbToRead = RT_MIN(cbRead, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel)); 5777 /* Clip readrange to remain into current data segment. */5778 /* Clip write range to remain into current data segment. */ 5778 5779 cbToRead = RT_MIN(cbToRead, cbLeftInCurrentSegment); 5779 5780 … … 5783 5784 case VMDKETYPE_FLAT: 5784 5785 { 5785 /* Setup new task. */5786 void *pTask;5787 rc = pImage->pInterfaceAsyncIOCallbacks->pfnPrepareRead(pImage->pInterfaceAsyncIO->pvUser, pExtent->pFile->pStorage,5788 VMDK_SECTOR2BYTE(uSectorExtentRel),5789 (uint8_t *)paSegCurrent->pvSeg + uOffsetInCurrentSegment,5790 cbToRead, &pTask);5791 if (RT_FAILURE(rc))5792 {5793 AssertMsgFailed(("Preparing read failed rc=%Rrc\n", rc));5794 goto out;5795 }5796 5797 5786 /* Check for enough room first. */ 5798 if ( cTasksToSubmit >= pImage->cTask)5787 if (RT_LIKELY(cSegments >= pImage->cSegments)) 5799 5788 { 5800 5789 /* We reached maximum, resize array. Try to realloc memory first. */ 5801 void **apTaskNew = (void **)RTMemRealloc(pImage->apTask, (cTasksToSubmit + 10)*sizeof(void *));5802 5803 if (! apTaskNew)5790 PPDMDATASEG paSegmentsNew = (PPDMDATASEG)RTMemRealloc(pImage->paSegments, (cSegments + 10)*sizeof(PDMDATASEG)); 5791 5792 if (!paSegmentsNew) 5804 5793 { 5805 5794 /* We failed. Allocate completely new. */ 5806 apTaskNew = (void **)RTMemAllocZ((cTasksToSubmit + 10)* sizeof(void *));5807 if (! apTaskNew)5795 paSegmentsNew = (PPDMDATASEG)RTMemAllocZ((cSegments + 10)* sizeof(PDMDATASEG)); 5796 if (!paSegmentsNew) 5808 5797 { 5809 5798 /* Damn, we are out of memory. */ … … 5813 5802 5814 5803 /* Copy task handles over. */ 5815 for (unsigned i = 0; i < c TasksToSubmit; i++)5816 apTaskNew[i] = pImage->apTask[i];5804 for (unsigned i = 0; i < cSegments; i++) 5805 paSegmentsNew[i] = pImage->paSegments[i]; 5817 5806 5818 5807 /* Free old memory. */ 5819 RTMemFree(pImage-> apTask);5808 RTMemFree(pImage->paSegments); 5820 5809 } 5821 5810 5822 pImage->c Task = cTasksToSubmit+ 10;5823 pImage-> apTask = apTaskNew;5811 pImage->cSegments = cSegments + 10; 5812 pImage->paSegments = paSegmentsNew; 5824 5813 } 5825 5814 5826 pImage->apTask[cTasksToSubmit] = pTask; 5827 cTasksToSubmit++; 5828 break; 5829 } 5830 case VMDKETYPE_ZERO: 5831 memset((uint8_t *)paSegCurrent->pvSeg + uOffsetInCurrentSegment, 0, cbToRead); 5832 break; 5833 default: 5834 AssertMsgFailed(("Unsupported extent type %u\n", pExtent->enmType)); 5835 } 5836 5837 cbRead -= cbToRead; 5838 uOffset += cbToRead; 5839 cbLeftInCurrentSegment -= cbToRead; 5840 uOffsetInCurrentSegment += cbToRead; 5841 /* Go to next extent if there is no space left in current one. */ 5842 if (!cbLeftInCurrentSegment) 5843 { 5844 uOffsetInCurrentSegment = 0; 5845 paSegCurrent++; 5846 cSeg--; 5847 cbLeftInCurrentSegment = paSegCurrent->cbSeg; 5848 } 5849 } 5850 5851 AssertMsg(cbRead == 0, ("No segment left but there is still data to read\n")); 5852 5853 if (cTasksToSubmit == 0) 5854 { 5855 /* The request was completely in a ZERO extent nothing to do. */ 5856 rc = VINF_VD_ASYNC_IO_FINISHED; 5857 } 5858 else 5859 { 5860 /* Submit tasks. */ 5861 rc = pImage->pInterfaceAsyncIOCallbacks->pfnTasksSubmit(pImage->pInterfaceAsyncIO->pvUser, 5862 pImage->apTask, cTasksToSubmit, 5863 NULL, pvUser, 5864 NULL /* Nothing required after read. */); 5865 AssertMsgRC(rc, ("Failed to enqueue tasks rc=%Rrc\n", rc)); 5866 } 5867 5868 out: 5869 LogFlowFunc(("returns %Rrc\n", rc)); 5870 return rc; 5871 } 5872 5873 static int vmdkAsyncWrite(void *pvBackendData, uint64_t uOffset, size_t cbWrite, 5874 PPDMDATASEG paSeg, unsigned cSeg, void *pvUser) 5875 { 5876 PVMDKIMAGE pImage = (PVMDKIMAGE)pvBackendData; 5877 PVMDKEXTENT pExtent; 5878 int rc = VINF_SUCCESS; 5879 unsigned cTasksToSubmit = 0; 5880 PPDMDATASEG paSegCurrent = paSeg; 5881 size_t cbLeftInCurrentSegment = paSegCurrent->cbSeg; 5882 size_t uOffsetInCurrentSegment = 0; 5883 5884 AssertPtr(pImage); 5885 Assert(uOffset % 512 == 0); 5886 Assert(cbWrite % 512 == 0); 5887 5888 if ( uOffset + cbWrite > pImage->cbSize 5889 || cbWrite == 0) 5890 { 5891 rc = VERR_INVALID_PARAMETER; 5892 goto out; 5893 } 5894 5895 while (cbWrite && cSeg) 5896 { 5897 size_t cbToWrite; 5898 uint64_t uSectorExtentRel; 5899 5900 rc = vmdkFindExtent(pImage, VMDK_BYTE2SECTOR(uOffset), 5901 &pExtent, &uSectorExtentRel); 5902 if (RT_FAILURE(rc)) 5903 goto out; 5904 5905 /* Check access permissions as defined in the extent descriptor. */ 5906 if (pExtent->enmAccess == VMDKACCESS_NOACCESS) 5907 { 5908 rc = VERR_VD_VMDK_INVALID_STATE; 5909 goto out; 5910 } 5911 5912 /* Clip write range to remain in this extent. */ 5913 cbToWrite = RT_MIN(cbWrite, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel)); 5914 /* Clip write range to remain into current data segment. */ 5915 cbToWrite = RT_MIN(cbToWrite, cbLeftInCurrentSegment); 5916 5917 switch (pExtent->enmType) 5918 { 5919 case VMDKETYPE_VMFS: 5920 case VMDKETYPE_FLAT: 5921 { 5922 /* Setup new task. */ 5923 void *pTask; 5924 rc = pImage->pInterfaceAsyncIOCallbacks->pfnPrepareWrite(pImage->pInterfaceAsyncIO->pvUser, pExtent->pFile->pStorage, 5925 VMDK_SECTOR2BYTE(uSectorExtentRel), 5926 (uint8_t *)paSegCurrent->pvSeg + uOffsetInCurrentSegment, 5927 cbToWrite, &pTask); 5928 if (RT_FAILURE(rc)) 5929 { 5930 AssertMsgFailed(("Preparing read failed rc=%Rrc\n", rc)); 5931 goto out; 5932 } 5933 5934 /* Check for enough room first. */ 5935 if (cTasksToSubmit >= pImage->cTask) 5936 { 5937 /* We reached maximum, resize array. Try to realloc memory first. */ 5938 void **apTaskNew = (void **)RTMemRealloc(pImage->apTask, (cTasksToSubmit + 10)*sizeof(void *)); 5939 5940 if (!apTaskNew) 5941 { 5942 /* We failed. Allocate completely new. */ 5943 apTaskNew = (void **)RTMemAllocZ((cTasksToSubmit + 10)* sizeof(void *)); 5944 if (!apTaskNew) 5945 { 5946 /* Damn, we are out of memory. */ 5947 rc = VERR_NO_MEMORY; 5948 goto out; 5949 } 5950 5951 /* Copy task handles over. */ 5952 for (unsigned i = 0; i < cTasksToSubmit; i++) 5953 apTaskNew[i] = pImage->apTask[i]; 5954 5955 /* Free old memory. */ 5956 RTMemFree(pImage->apTask); 5957 } 5958 5959 pImage->cTask = cTasksToSubmit + 10; 5960 pImage->apTask = apTaskNew; 5961 } 5962 5963 pImage->apTask[cTasksToSubmit] = pTask; 5964 cTasksToSubmit++; 5815 pImage->paSegments[cSegments].cbSeg = cbToRead; 5816 pImage->paSegments[cSegments].pvSeg = (uint8_t *)paSegCurrent->pvSeg + uOffsetInCurrentSegment; 5817 cSegments++; 5965 5818 break; 5966 5819 } … … 5972 5825 } 5973 5826 5827 cbRead -= cbToRead; 5828 uOffset += cbToRead; 5829 cbLeftInCurrentSegment -= cbToRead; 5830 uOffsetInCurrentSegment += cbToRead; 5831 /* Go to next extent if there is no space left in current one. */ 5832 if (!cbLeftInCurrentSegment) 5833 { 5834 uOffsetInCurrentSegment = 0; 5835 paSegCurrent++; 5836 cSeg--; 5837 cbLeftInCurrentSegment = paSegCurrent->cbSeg; 5838 } 5839 } 5840 5841 AssertMsg(cbRead == 0, ("No segment left but there is still data to write\n")); 5842 5843 if (cSegments == 0) 5844 { 5845 /* The request was completely in a ZERO extent nothing to do. */ 5846 rc = VINF_VD_ASYNC_IO_FINISHED; 5847 } 5848 else 5849 { 5850 /* Start the write */ 5851 void *pTask; 5852 rc = pImage->pInterfaceAsyncIOCallbacks->pfnReadAsync(pImage->pInterfaceAsyncIO->pvUser, 5853 pExtent->pFile->pStorage, uOffset, 5854 pImage->paSegments, cSegments, cbRead, 5855 pvUser, &pTask); 5856 } 5857 5858 out: 5859 LogFlowFunc(("returns %Rrc\n", rc)); 5860 return rc; 5861 } 5862 5863 static int vmdkAsyncWrite(void *pvBackendData, uint64_t uOffset, size_t cbWrite, 5864 PPDMDATASEG paSeg, unsigned cSeg, void *pvUser) 5865 { 5866 PVMDKIMAGE pImage = (PVMDKIMAGE)pvBackendData; 5867 PVMDKEXTENT pExtent; 5868 int rc = VINF_SUCCESS; 5869 unsigned cSegments = 0; 5870 PPDMDATASEG paSegCurrent = paSeg; 5871 size_t cbLeftInCurrentSegment = paSegCurrent->cbSeg; 5872 size_t uOffsetInCurrentSegment = 0; 5873 5874 AssertPtr(pImage); 5875 Assert(uOffset % 512 == 0); 5876 Assert(cbWrite % 512 == 0); 5877 5878 if ( uOffset + cbWrite > pImage->cbSize 5879 || cbWrite == 0) 5880 { 5881 rc = VERR_INVALID_PARAMETER; 5882 goto out; 5883 } 5884 5885 while (cbWrite && cSeg) 5886 { 5887 size_t cbToWrite; 5888 uint64_t uSectorExtentRel; 5889 5890 rc = vmdkFindExtent(pImage, VMDK_BYTE2SECTOR(uOffset), 5891 &pExtent, &uSectorExtentRel); 5892 if (RT_FAILURE(rc)) 5893 goto out; 5894 5895 /* Check access permissions as defined in the extent descriptor. */ 5896 if (pExtent->enmAccess == VMDKACCESS_NOACCESS) 5897 { 5898 rc = VERR_VD_VMDK_INVALID_STATE; 5899 goto out; 5900 } 5901 5902 /* Clip write range to remain in this extent. */ 5903 cbToWrite = RT_MIN(cbWrite, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel)); 5904 /* Clip write range to remain into current data segment. */ 5905 cbToWrite = RT_MIN(cbToWrite, cbLeftInCurrentSegment); 5906 5907 switch (pExtent->enmType) 5908 { 5909 case VMDKETYPE_VMFS: 5910 case VMDKETYPE_FLAT: 5911 { 5912 /* Check for enough room first. */ 5913 if (RT_LIKELY(cSegments >= pImage->cSegments)) 5914 { 5915 /* We reached maximum, resize array. Try to realloc memory first. */ 5916 PPDMDATASEG paSegmentsNew = (PPDMDATASEG)RTMemRealloc(pImage->paSegments, (cSegments + 10)*sizeof(PDMDATASEG)); 5917 5918 if (!paSegmentsNew) 5919 { 5920 /* We failed. Allocate completely new. */ 5921 paSegmentsNew = (PPDMDATASEG)RTMemAllocZ((cSegments + 10)* sizeof(PDMDATASEG)); 5922 if (!paSegmentsNew) 5923 { 5924 /* Damn, we are out of memory. */ 5925 rc = VERR_NO_MEMORY; 5926 goto out; 5927 } 5928 5929 /* Copy task handles over. */ 5930 for (unsigned i = 0; i < cSegments; i++) 5931 paSegmentsNew[i] = pImage->paSegments[i]; 5932 5933 /* Free old memory. */ 5934 RTMemFree(pImage->paSegments); 5935 } 5936 5937 pImage->cSegments = cSegments + 10; 5938 pImage->paSegments = paSegmentsNew; 5939 } 5940 5941 pImage->paSegments[cSegments].cbSeg = cbToWrite; 5942 pImage->paSegments[cSegments].pvSeg = (uint8_t *)paSegCurrent->pvSeg + uOffsetInCurrentSegment; 5943 cSegments++; 5944 break; 5945 } 5946 case VMDKETYPE_ZERO: 5947 /* Nothing left to do. */ 5948 break; 5949 default: 5950 AssertMsgFailed(("Unsupported extent type %u\n", pExtent->enmType)); 5951 } 5952 5974 5953 cbWrite -= cbToWrite; 5975 5954 uOffset += cbToWrite; … … 5986 5965 } 5987 5966 5988 AssertMsg(cbWrite == 0, ("No segment left but there is still data to read\n"));5989 5990 if (c TasksToSubmit== 0)5967 AssertMsg(cbWrite == 0, ("No segment left but there is still data to write\n")); 5968 5969 if (cSegments == 0) 5991 5970 { 5992 5971 /* The request was completely in a ZERO extent nothing to do. */ … … 5995 5974 else 5996 5975 { 5997 /* S ubmit tasks.*/5998 rc = pImage->pInterfaceAsyncIOCallbacks->pfnTasksSubmit(pImage->pInterfaceAsyncIO->pvUser,5999 pImage->apTask, cTasksToSubmit,6000 NULL, pvUser,6001 NULL /* Nothing required after read. */);6002 AssertMsgRC(rc, ("Failed to enqueue tasks rc=%Rrc\n", rc));5976 /* Start the write */ 5977 void *pTask; 5978 rc = pImage->pInterfaceAsyncIOCallbacks->pfnWriteAsync(pImage->pInterfaceAsyncIO->pvUser, 5979 pExtent->pFile->pStorage, uOffset, 5980 pImage->paSegments, cSegments, cbWrite, 5981 pvUser, &pTask); 6003 5982 } 6004 5983 … … 6006 5985 LogFlowFunc(("returns %Rrc\n", rc)); 6007 5986 return rc; 6008 6009 5987 } 6010 5988 -
trunk/src/VBox/VMM/Makefile.kmk
r19957 r20167 164 164 ifdef VBOX_WITH_PDM_ASYNC_COMPLETION 165 165 VMMR3_DEFS += VBOX_WITH_PDM_ASYNC_COMPLETION 166 VMMR3_DEFS.linux += __USE_FILE_OFFSET64 __USE_LARGEFILE64 167 VMMR3_SOURCES += PDMAsyncCompletion.cpp 168 VMMR3_SOURCES.linux += \ 169 PDMAsyncCompletionSocketPosix.cpp \ 170 PDMAsyncCompletionHostPosix.cpp 171 172 VMMR3_SOURCES.win += \ 173 PDMAsyncCompletionSocketWin.cpp \ 174 PDMAsyncCompletionHostWin.cpp 175 176 VMMR3_SOURCES.solaris += \ 177 PDMAsyncCompletionSocketPosix.cpp \ 178 PDMAsyncCompletionHostSolaris.cpp 179 180 VMMR3_SOURCES.darwin += \ 181 PDMAsyncCompletionSocketPosix.cpp \ 182 PDMAsyncCompletionHostPosix.cpp 183 184 VMMR3_SOURCES.freebsd += \ 185 PDMAsyncCompletionSocketPosix.cpp \ 186 PDMAsyncCompletionHostFreeBSD.cpp 187 166 VMMR3_SOURCES += \ 167 PDMAsyncCompletion.cpp \ 168 PDMAsyncCompletionFile.cpp 188 169 endif 189 170 -
trunk/src/VBox/VMM/PDMDriver.cpp
r20096 r20167 1013 1013 /** @copydoc PDMDRVHLP::pfnPDMAsyncCompletionTemplateCreate */ 1014 1014 static DECLCALLBACK(int) pdmR3DrvHlp_PDMAsyncCompletionTemplateCreate(PPDMDRVINS pDrvIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate, 1015 PFNPDMASYNCCOMPLETEDRV pfnCompleted, const char *pszDesc) 1015 PFNPDMASYNCCOMPLETEDRV pfnCompleted, void *pvTemplateUser, 1016 const char *pszDesc) 1016 1017 { 1017 1018 PDMDRV_ASSERT_DRVINS(pDrvIns); … … 1020 1021 pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, ppTemplate, pfnCompleted, pszDesc, pszDesc)); 1021 1022 1022 int rc = PDMR3AsyncCompletionTemplateCreateDriver(pDrvIns->Internal.s.pVM, pDrvIns, ppTemplate, pfnCompleted, p szDesc);1023 int rc = PDMR3AsyncCompletionTemplateCreateDriver(pDrvIns->Internal.s.pVM, pDrvIns, ppTemplate, pfnCompleted, pvTemplateUser, pszDesc); 1023 1024 1024 1025 LogFlow(("pdmR3DrvHlp_PDMAsyncCompletionTemplateCreate: caller='%s'/%d: returns %Rrc *ppThread=%p\n", pDrvIns->pDrvReg->szDriverName, -
trunk/src/VBox/VMM/PDMInternal.h
r20056 r20167 805 805 typedef struct PDMASYNCCOMPLETIONTEMPLATE *PPDMASYNCCOMPLETIONTEMPLATE; 806 806 807 /** Pointer to the main PDM Async completion structure. */808 typedef struct PDMASYNCCOMPLETION MANAGER *PPDMASYNCCOMPLETIONMANAGER;807 /** Pointer to the main PDM Async completion endpoint class. */ 808 typedef struct PDMASYNCCOMPLETIONEPCLASS *PPDMASYNCCOMPLETIONEPCLASS; 809 809 810 810 … … 897 897 R3PTRTYPE(PPDMTHREAD) pThreadsTail; 898 898 899 /** Head of the asychronous tasks managers. (singly linked) */ 900 R3PTRTYPE(PPDMASYNCCOMPLETIONMANAGER) pAsyncCompletionManagerHead; 899 /** @name PDM Async Completion 900 * @{ */ 901 /** Pointer to the array of supported endpoint classes. */ 902 R3PTRTYPE(PPDMASYNCCOMPLETIONEPCLASS *) papAsyncCompletionEndpointClass; 901 903 /** Head of the templates. (singly linked) */ 902 904 R3PTRTYPE(PPDMASYNCCOMPLETIONTEMPLATE) pAsyncCompletionTemplates; 905 /** @} */ 903 906 904 907 /** @name VMM device heap
Note:
See TracChangeset
for help on using the changeset viewer.