VirtualBox

Changeset 20167 in vbox


Ignore:
Timestamp:
Jun 1, 2009 8:25:54 PM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
47996
Message:

First part of the PDMAsyncCompletion rewrite:

  • The Host specific parts in VMM are deleted (moved into Runtime)
  • Implemented a incomplete manager for file operations:
    • A slightly tested failsafe method to do operations is implemented using the synchronous RTFile* API. The failsafe method will be always used if the host has no support for async I/O or something bad happens during the operation reducing the risk of VM termination
  • Changed the testcase and drivers to use the new API
  • Removed the now obsolete async transport driver
  • Removed the obsolete raw async image driver
  • Removed the fault injection driver (useless from the beginning)
Location:
trunk
Files:
1 added
12 edited

Legend:

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

    r19176 r20167  
    395395 * @return  VBox status code.
    396396 * @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 */
     400typedef DECLCALLBACK(int) FNVDCOMPLETED(void *pvUser, void **ppvCaller);
    399401/** Pointer to FNVDCOMPLETED() */
    400402typedef FNVDCOMPLETED *PFNVDCOMPLETED;
     
    425427     * @param   pszLocation     Name of the location to open.
    426428     * @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.
    427434     * @param   ppStorage       Where to store the opaque storage handle.
    428435     */
    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));
    430438
    431439    /**
     
    437445     */
    438446    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));
    439457
    440458    /**
     
    449467     * @param   pcbWritten      Where to store how many bytes where actually written.
    450468     */
    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));
    453471
    454472    /**
     
    463481     * @param   pcbRead         Where to store how many bytes where actually read.
    464482     */
    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));
    467485
    468486    /**
     
    473491     * @param   pStorage        The storage handle to flush.
    474492     */
    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.
    479497     *
    480498     * @return  VBox status code.
     
    482500     * @param   pStorage       The storage handle.
    483501     * @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.
    485504     * @param   cbRead         How many bytes to read.
     505     * @param   pvCompletion   The opaque user data which is returned upon completion.
    486506     * @param   ppTask         Where to store the opaque task handle.
    487507     */
    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.
    493515     *
    494516     * @return  VBox status code.
     
    496518     * @param   pStorage       The storage handle.
    497519     * @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.
    499522     * @param   cbWrite        How many bytes to write.
     523     * @param   pvCompletion   The opaque user data which is returned upon completion.
    500524     * @param   ppTask         Where to store the opaque task handle.
    501525     */
    502     DECLR3CALLBACKMEMBER(int, pfnPrepareWrite, (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   pvUser2       User data which is passed on completion.
    513      * @param   pvUserCaller  Opaque user data the caller of VDAsyncWrite/Read passed.
    514      * @param   pfnTasksCompleted Pointer to callback which is called on request completion.
    515      */
    516     DECLR3CALLBACKMEMBER(int, pfnTasksSubmit, (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));
    518542
    519543} VDINTERFACEASYNCIO, *PVDINTERFACEASYNCIO;
  • trunk/include/VBox/pdmasynccompletion.h

    r13835 r20167  
    55
    66/*
    7  * Copyright (C) 2007 Sun Microsystems, Inc.
     7 * Copyright (C) 2007-2009 Sun Microsystems, Inc.
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    5353typedef PPDMASYNCCOMPLETIONTASK *PPPDMASYNCCOMPLETIONTASK;
    5454
     55/** Pointer to a PDM async completion endpoint handle. */
     56typedef struct PDMASYNCCOMPLETIONENDPOINT *PPDMASYNCCOMPLETIONENDPOINT;
     57/** Pointer to a PDM async completion endpoint handle pointer. */
     58typedef PPDMASYNCCOMPLETIONENDPOINT *PPPDMASYNCCOMPLETIONENDPOINT;
     59
    5560
    5661/**
     
    5863 *
    5964 * @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 must
    62  *                      call PDMR3AsyncCompletionSuspend or PDMR3AsyncCompletionDestroy if any other
    63  *                      action is wanted upon return.
    64  * @param   pvCtx       Pointer to any additional, OS specific, completion context. TBD.
    6565 * @param   pvUser      User argument.
    6666 */
    67 typedef DECLCALLBACK(void) FNPDMASYNCCOMPLETEDEV(PPDMDEVINS pDevIns, PPDMASYNCCOMPLETIONTASK pTask, void *pvCtx, void *pvUser);
     67typedef DECLCALLBACK(void) FNPDMASYNCCOMPLETEDEV(PPDMDEVINS pDevIns, void *pvUser);
    6868/** Pointer to a FNPDMASYNCCOMPLETEDEV(). */
    6969typedef FNPDMASYNCCOMPLETEDEV *PFNPDMASYNCCOMPLETEDEV;
     
    7373 * Completion callback for drivers.
    7474 *
    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 */
     79typedef DECLCALLBACK(void) FNPDMASYNCCOMPLETEDRV(PPDMDRVINS pDrvIns, void *pvTemplateUser, void *pvUser);
    8480/** Pointer to a FNPDMASYNCCOMPLETEDRV(). */
    8581typedef FNPDMASYNCCOMPLETEDRV *PFNPDMASYNCCOMPLETEDRV;
     
    9086 *
    9187 * @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 must
    94  *                      call PDMR3AsyncCompletionSuspend or PDMR3AsyncCompletionDestroy if any other
    95  *                      action is wanted upon return.
    96  * @param   pvCtx       Pointer to any additional, OS specific, completion context. TBD.
    9788 * @param   pvUser      User argument.
    9889 */
    99 typedef DECLCALLBACK(void) FNPDMASYNCCOMPLETEUSB(PPDMUSBINS pUsbIns, PPDMASYNCCOMPLETIONTASK pTask, void *pvCtx, void *pvUser);
     90typedef DECLCALLBACK(void) FNPDMASYNCCOMPLETEUSB(PPDMUSBINS pUsbIns, void *pvUser);
    10091/** Pointer to a FNPDMASYNCCOMPLETEUSB(). */
    10192typedef FNPDMASYNCCOMPLETEUSB *PFNPDMASYNCCOMPLETEUSB;
     
    10697 *
    10798 * @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 must
    110  *                      call PDMR3AsyncCompletionSuspend or PDMR3AsyncCompletionDestroy if any other
    111  *                      action is wanted upon return.
    112  * @param   pvCtx       Pointer to any additional, OS specific, completion context. TBD.
    11399 * @param   pvUser      User argument for the task.
    114100 * @param   pvUser2     User argument for the template.
    115101 */
    116 typedef DECLCALLBACK(void) FNPDMASYNCCOMPLETEINT(PVM pVM, PPDMASYNCCOMPLETIONTASK pTask, void *pvCtx, void *pvUser, void *pvUser2);
     102typedef DECLCALLBACK(void) FNPDMASYNCCOMPLETEINT(PVM pVM, void *pvUser, void *pvUser2);
    117103/** Pointer to a FNPDMASYNCCOMPLETEINT(). */
    118104typedef FNPDMASYNCCOMPLETEINT *PFNPDMASYNCCOMPLETEINT;
     
    143129 * @param   ppTemplate      Where to store the template pointer on success.
    144130 * @param   pfnCompleted    The completion callback routine.
     131 * @param   pvTemplateUser  Template user argument.
    145132 * @param   pszDesc         Description.
    146133 */
    147 VMMR3DECL(int) PDMR3AsyncCompletionTemplateCreateDriver(PVM pVM, PPDMDRVINS pDrvIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate, PFNPDMASYNCCOMPLETEDRV pfnCompleted, const char *pszDesc);
     134VMMR3DECL(int) PDMR3AsyncCompletionTemplateCreateDriver(PVM pVM, PPDMDRVINS pDrvIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate, PFNPDMASYNCCOMPLETEDRV pfnCompleted, void *pvTemplateUser, const char *pszDesc);
    148135
    149136/**
     
    222209VMMR3DECL(int) PDMR3AsyncCompletionTemplateDestroyUsb(PVM pVM, PPDMUSBINS pUsbIns);
    223210
    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 */
     222VMMR3DECL(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 */
     240VMMR3DECL(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.
    249253 * @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 */
     255VMMR3DECL(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 */
     273VMMR3DECL(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 */
     290VMMR3DECL(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 */
     304VMMR3DECL(int) PDMR3AsyncCompletionEpGetSize(PPDMASYNCCOMPLETIONENDPOINT pEndpoint,
     305                                             uint64_t *pcbSize);
    297306
    298307/**
    299308 * 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.
    301314 *
    302315 * @returns VBox status code
    303  * @param   pTask The Task to cancel.
     316 * @param   pTask           The Task to cancel.
    304317 */
    305318VMMR3DECL(int) PDMR3AsyncCompletionTaskCancel(PPDMASYNCCOMPLETIONTASK pTask);
    306319
    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
    535324#endif
    536325
    537 /** @} */
    538 
    539 __END_DECLS
    540 
    541 #endif
    542 
    543 
    544 
  • trunk/include/VBox/pdmdrv.h

    r20096 r20167  
    684684     * @param   ppTemplate      Where to store the template pointer on success.
    685685     * @param   pfnCompleted    The completion callback routine.
     686     * @param   pvTemplateUser  Template user argument.
    686687     * @param   pszDesc         Description.
    687688     */
    688689    DECLR3CALLBACKMEMBER(int, pfnPDMAsyncCompletionTemplateCreate,(PPDMDRVINS pDrvIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate,
    689                                                                    PFNPDMASYNCCOMPLETEDRV pfnCompleted, const char *pszDesc));
     690                                                                   PFNPDMASYNCCOMPLETEDRV pfnCompleted, void *pvTemplateUser,
     691                                                                   const char *pszDesc));
    690692#endif
    691693
     
    906908 */
    907909DECLINLINE(int) PDMDrvHlpPDMAsyncCompletionTemplateCreate(PPDMDRVINS pDrvIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate,
    908                                                           PFNPDMASYNCCOMPLETEDRV pfnCompleted, const char *pszDesc)
    909 {
    910     return pDrvIns->pDrvHlp->pfnPDMAsyncCompletionTemplateCreate(pDrvIns, ppTemplate, pfnCompleted, pszDesc);
     910                                                          PFNPDMASYNCCOMPLETEDRV pfnCompleted, void *pvTemplateUser, const char *pszDesc)
     911{
     912    return pDrvIns->pDrvHlp->pfnPDMAsyncCompletionTemplateCreate(pDrvIns, ppTemplate, pfnCompleted, pvTemplateUser, pszDesc);
    911913}
    912914#endif
  • trunk/include/VBox/pdmifs.h

    r19959 r20167  
    104104    /** PDMIBLOCKASYNCPORT      - Async version of the block interface  (Up)    Coupled with PDMINTERFACE_BLOCK_ASYNC. */
    105105    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,
    110106
    111107
     
    13181314
    13191315} 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 PDMITRANSPORTASYNCPORT
    1329 {
    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 PDMITRANSPORTASYNC
    1350 {
    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 task
    1386      *
    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 processing
    1467      *
    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;
    14761316
    14771317
  • trunk/src/VBox/Devices/Builtins.cpp

    r19968 r20167  
    276276#endif
    277277
    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 #endif
    287278#ifdef VBOX_WITH_SCSI
    288279    rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvSCSI);
     
    295286        return rc;
    296287#endif
    297 #endif
    298 
    299 #ifdef VBOX_WITH_FAULT_INJECTION
    300     rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvFaultInject);
    301     if (RT_FAILURE(rc))
    302         return rc;
    303288#endif
    304289
  • trunk/src/VBox/Devices/Builtins.h

    r19624 r20167  
    120120#endif
    121121
    122 #ifdef VBOX_WITH_PDM_ASYNC_COMPLETION
    123 extern const PDMDRVREG g_DrvRawImageAsync;
    124 extern const PDMDRVREG g_DrvTransportAsync;
    125 #endif
    126 
    127122#ifdef VBOX_WITH_SCSI
    128123extern const PDMDRVREG g_DrvSCSI;
     
    132127#endif
    133128
    134 #ifdef VBOX_WITH_FAULT_INJECTION
    135 extern const PDMDRVREG g_DrvFaultInject;
    136 #endif
    137 
    138129__END_DECLS
    139130
  • trunk/src/VBox/Devices/Makefile.kmk

    r20100 r20167  
    903903ifdef VBOX_WITH_PDM_ASYNC_COMPLETION
    904904 Drivers_DEFS += VBOX_WITH_PDM_ASYNC_COMPLETION
    905  Drivers_SOURCES += \
    906         Storage/DrvRawImageAsync.cpp \
    907         Storage/DrvTransportAsync.cpp
    908905endif #VBOX_WITH_PDM_ASYNC_COMPLETION
    909906
     
    915912        Storage/DrvSCSIHost.cpp
    916913endif # VBOX_WITH_SCSI
    917 
    918 ifdef VBOX_WITH_FAULT_INJECTION
    919  Drivers_DEFS += VBOX_WITH_FAULT_INJECTION
    920  Drivers_SOURCES += \
    921         Storage/DrvFaultInject.cpp
    922 endif # VBOX_WITH_FAULT_INJECTION
    923914
    924915#
  • trunk/src/VBox/Devices/Storage/DrvVD.cpp

    r18778 r20167  
    2727#include <VBox/VBoxHDD.h>
    2828#include <VBox/pdmdrv.h>
     29#include <VBox/pdmasynccompletion.h>
    2930#include <iprt/alloc.h>
    3031#include <iprt/assert.h>
     
    3435#include <iprt/cache.h>
    3536#include <iprt/tcp.h>
     37#include <iprt/semaphore.h>
    3638
    3739#ifdef VBOX_WITH_INIP
     
    7274    ( (PVBOXDISK)((uintptr_t)pInterface - RT_OFFSETOF(VBOXDISK, IMediaAsync)) )
    7375
    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 DRVVDASYNCTASK
    82 {
    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 
    9176/**
    9277 * VBox disk container, image information, private part.
     
    10287    VDINTERFACE        VDIConfig;
    10388} VBOXIMAGE, *PVBOXIMAGE;
     89
     90/**
     91 * Storage backend data.
     92 */
     93typedef 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;
    104106
    105107/**
     
    140142    /** The async media port interface above. */
    141143    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;
    148144    /** Pointer to the list of data we need to keep per image. */
    149145    PVBOXIMAGE               pImages;
     
    207203*******************************************************************************/
    208204
    209 static DECLCALLBACK(int) drvvdAsyncIOOpen(void *pvUser, const char *pszLocation, bool fReadonly, void **ppStorage)
     205static 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
     231static DECLCALLBACK(int) drvvdAsyncIOOpen(void *pvUser, const char *pszLocation, bool fReadonly,
     232                                          PFNVDCOMPLETED pfnCompleted, void **ppStorage)
    210233{
    211234    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;
    214271}
    215272
     
    217274{
    218275    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
     286static DECLCALLBACK(int) drvvdAsyncIOGetSize(void *pvUser, void *pStorage, uint64_t *pcbSize)
    227287{
    228288    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
     294static DECLCALLBACK(int) drvvdAsyncIOReadSync(void *pvUser, void *pStorage, uint64_t uOffset,
     295                                              size_t cbRead, void *pvBuf, size_t *pcbRead)
    239296{
    240297    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);
    287308    if (RT_FAILURE(rc))
    288309        return rc;
    289310
    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
     321static 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
     348static 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
     368static 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
     380static 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
     392static 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
    296402
    297403/*******************************************************************************
     
    641747*******************************************************************************/
    642748
    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;
     749static DECLCALLBACK(int) drvvdTasksCompleteNotify(PPDMDRVINS pDrvIns, void *pvUser)
     750{
     751    return VERR_NOT_IMPLEMENTED;
    665752}
    666753
     
    684771        case PDMINTERFACE_MEDIA_ASYNC:
    685772            return pThis->fAsyncIOSupported ? &pThis->IMediaAsync : NULL;
    686         case PDMINTERFACE_TRANSPORT_ASYNC_PORT:
    687             return &pThis->ITransportAsyncPort;
    688773        default:
    689774            return NULL;
     
    743828    pThis->IMediaAsync.pfnStartWrite      = drvvdStartWrite;
    744829
    745     /* ITransportAsyncPort */
    746     pThis->ITransportAsyncPort.pfnTaskCompleteNotify  = drvvdTasksCompleteNotify;
    747 
    748830    /* Initialize supported VD interfaces. */
    749831    pThis->pVDIfsDisk = NULL;
     
    761843    pThis->VDIAsyncIOCallbacks.pfnOpen                 = drvvdAsyncIOOpen;
    762844    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;
    769852
    770853    rc = VDInterfaceAdd(&pThis->VDIAsyncIO, "DrvVD_AsyncIO", VDINTERFACETYPE_ASYNCIO,
     
    820903            pThis->fAsyncIOSupported = true;
    821904
    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 */
    830906        }
    831907    }
     
    11081184        }
    11091185
    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 
    11201186        /* Switch to runtime error facility. */
    11211187        pThis->fErrorUseRuntime = true;
     
    11411207
    11421208    drvvdFreeImages(pThis);
    1143     if (pThis->pCache)
    1144     {
    1145         rc = RTCacheDestroy(pThis->pCache);
    1146         AssertRC(rc);
    1147     }
    11481209}
    11491210
  • trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp

    r19921 r20167  
    432432    PVDINTERFACEASYNCIO pInterfaceAsyncIOCallbacks;
    433433    /**
    434      * Pointer to an array of task handles for task submission.
     434     * Pointer to an array of segment entries for async I/O.
    435435     * This is an optimization because the task number to submit is not known
    436436     * and allocating/freeing an array in the read/write functions every time
    437437     * is too expensive.
    438438     */
    439     void            **apTask;
    440     /** Entries available in the task handle array. */
    441     unsigned        cTask;
     439    PPDMDATASEG     paSegments;
     440    /** Entries available in the segments array. */
     441    unsigned        cSegments;
    442442
    443443    /** Open flags passed by VBoxHD layer. */
     
    584584                                                           ? true
    585585                                                           : false,
     586                                                         NULL,
    586587                                                         &pVmdkFile->pStorage);
    587588        pVmdkFile->fAsyncIO = true;
     
    670671
    671672    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);
    675676    else
    676677        return RTFileReadAt(pVmdkFile->File, uOffset, pvBuf, cbToRead, pcbRead);
     
    687688
    688689    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);
    692693    else
    693694        return RTFileWriteAt(pVmdkFile->File, uOffset, pvBuf, cbToWrite, pcbWritten);
     
    730731
    731732    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);
    734735    else
    735736        return RTFileFlush(pVmdkFile->File);
     
    57405741    PVMDKEXTENT pExtent;
    57415742    int rc = VINF_SUCCESS;
    5742     unsigned cTasksToSubmit = 0;
     5743    unsigned cSegments = 0;
    57435744    PPDMDATASEG paSegCurrent = paSeg;
    57445745    size_t cbLeftInCurrentSegment = paSegCurrent->cbSeg;
     
    57735774        }
    57745775
    5775         /* Clip read range to remain in this extent. */
     5776        /* Clip write range to remain in this extent. */
    57765777        cbToRead = RT_MIN(cbRead, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel));
    5777         /* Clip read range to remain into current data segment. */
     5778        /* Clip write range to remain into current data segment. */
    57785779        cbToRead = RT_MIN(cbToRead, cbLeftInCurrentSegment);
    57795780
     
    57835784            case VMDKETYPE_FLAT:
    57845785            {
    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 
    57975786                /* Check for enough room first. */
    5798                 if (cTasksToSubmit >= pImage->cTask)
     5787                if (RT_LIKELY(cSegments >= pImage->cSegments))
    57995788                {
    58005789                    /* 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)
    58045793                    {
    58055794                        /* 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)
    58085797                        {
    58095798                            /* Damn, we are out of memory. */
     
    58135802
    58145803                        /* Copy task handles over. */
    5815                         for (unsigned i = 0; i < cTasksToSubmit; i++)
    5816                             apTaskNew[i] = pImage->apTask[i];
     5804                        for (unsigned i = 0; i < cSegments; i++)
     5805                            paSegmentsNew[i] = pImage->paSegments[i];
    58175806
    58185807                        /* Free old memory. */
    5819                         RTMemFree(pImage->apTask);
     5808                        RTMemFree(pImage->paSegments);
    58205809                    }
    58215810
    5822                     pImage->cTask = cTasksToSubmit + 10;
    5823                     pImage->apTask = apTaskNew;
     5811                    pImage->cSegments = cSegments + 10;
     5812                    pImage->paSegments = paSegmentsNew;
    58245813                }
    58255814
    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++;
    59655818                break;
    59665819            }
     
    59725825        }
    59735826
     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
     5858out:
     5859    LogFlowFunc(("returns %Rrc\n", rc));
     5860    return rc;
     5861}
     5862
     5863static 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
    59745953        cbWrite -= cbToWrite;
    59755954        uOffset += cbToWrite;
     
    59865965    }
    59875966
    5988     AssertMsg(cbWrite == 0, ("No segment left but there is still data to read\n"));
    5989 
    5990     if (cTasksToSubmit == 0)
     5967    AssertMsg(cbWrite == 0, ("No segment left but there is still data to write\n"));
     5968
     5969    if (cSegments == 0)
    59915970    {
    59925971        /* The request was completely in a ZERO extent nothing to do. */
     
    59955974    else
    59965975    {
    5997         /* Submit 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);
    60035982    }
    60045983
     
    60065985    LogFlowFunc(("returns %Rrc\n", rc));
    60075986    return rc;
    6008 
    60095987}
    60105988
  • trunk/src/VBox/VMM/Makefile.kmk

    r19957 r20167  
    164164ifdef VBOX_WITH_PDM_ASYNC_COMPLETION
    165165VMMR3_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 
     166VMMR3_SOURCES += \
     167        PDMAsyncCompletion.cpp \
     168        PDMAsyncCompletionFile.cpp
    188169endif
    189170
  • trunk/src/VBox/VMM/PDMDriver.cpp

    r20096 r20167  
    10131013/** @copydoc PDMDRVHLP::pfnPDMAsyncCompletionTemplateCreate */
    10141014static DECLCALLBACK(int) pdmR3DrvHlp_PDMAsyncCompletionTemplateCreate(PPDMDRVINS pDrvIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate,
    1015                                                                       PFNPDMASYNCCOMPLETEDRV pfnCompleted, const char *pszDesc)
     1015                                                                      PFNPDMASYNCCOMPLETEDRV pfnCompleted, void *pvTemplateUser,
     1016                                                                      const char *pszDesc)
    10161017{
    10171018    PDMDRV_ASSERT_DRVINS(pDrvIns);
     
    10201021             pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, ppTemplate, pfnCompleted, pszDesc, pszDesc));
    10211022
    1022     int rc = PDMR3AsyncCompletionTemplateCreateDriver(pDrvIns->Internal.s.pVM, pDrvIns, ppTemplate, pfnCompleted, pszDesc);
     1023    int rc = PDMR3AsyncCompletionTemplateCreateDriver(pDrvIns->Internal.s.pVM, pDrvIns, ppTemplate, pfnCompleted, pvTemplateUser, pszDesc);
    10231024
    10241025    LogFlow(("pdmR3DrvHlp_PDMAsyncCompletionTemplateCreate: caller='%s'/%d: returns %Rrc *ppThread=%p\n", pDrvIns->pDrvReg->szDriverName,
  • trunk/src/VBox/VMM/PDMInternal.h

    r20056 r20167  
    805805typedef struct PDMASYNCCOMPLETIONTEMPLATE *PPDMASYNCCOMPLETIONTEMPLATE;
    806806
    807 /** Pointer to the main PDM Async completion structure. */
    808 typedef struct PDMASYNCCOMPLETIONMANAGER *PPDMASYNCCOMPLETIONMANAGER;
     807/** Pointer to the main PDM Async completion endpoint class. */
     808typedef struct PDMASYNCCOMPLETIONEPCLASS *PPDMASYNCCOMPLETIONEPCLASS;
    809809
    810810
     
    897897    R3PTRTYPE(PPDMTHREAD)           pThreadsTail;
    898898
    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;
    901903    /** Head of the templates. (singly linked) */
    902904    R3PTRTYPE(PPDMASYNCCOMPLETIONTEMPLATE) pAsyncCompletionTemplates;
     905    /** @} */
    903906
    904907    /** @name   VMM device heap
Note: See TracChangeset for help on using the changeset viewer.

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