VirtualBox

Changeset 22966 in vbox for trunk/src


Ignore:
Timestamp:
Sep 11, 2009 10:41:14 PM (15 years ago)
Author:
vboxsync
Message:

Storage: Convert the backends to use the interface for I/O rather than using the RTFile* API directly.

For a VM the PDMAsyncCompletion is used now as the I/O layer (fixing the I/O load problems).
Still disabled by default until it was tested on all supported platforms to not risk corruption
of images. To enable compile with VBOX_WITH_NEW_IO_CODE set.

Location:
trunk/src/VBox/Devices/Storage
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Storage/DrvVD.cpp

    r22277 r22966  
    209209    PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
    210210    PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pvTemplateUser;
    211     int rc = VINF_VD_ASYNC_IO_FINISHED;
    212     void *pvCallerUser = NULL;
    213211
    214212    if (pStorageBackend->fSyncIoPending)
    215213    {
    216         pStorageBackend->fSyncIoPending;
     214        pStorageBackend->fSyncIoPending = false;
    217215        RTSemEventSignal(pStorageBackend->EventSem);
    218216    }
    219     else if (pStorageBackend->pfnCompleted)
    220         rc = pStorageBackend->pfnCompleted(pvUser, &pvCallerUser);
    221217    else
    222         pvCallerUser = pvUser;
    223 
    224     if (rc == VINF_VD_ASYNC_IO_FINISHED)
    225     {
    226         rc = pThis->pDrvMediaAsyncPort->pfnTransferCompleteNotify(pThis->pDrvMediaAsyncPort, pvCallerUser);
    227         AssertRC(rc);
    228     }
    229     else
    230         AssertMsg(rc == VERR_VD_ASYNC_IO_IN_PROGRESS, ("Invalid return code from disk backend rc=%Rrc\n", rc));
    231 }
    232 
    233 static DECLCALLBACK(int) drvvdAsyncIOOpen(void *pvUser, const char *pszLocation, bool fReadonly,
     218    {
     219        int rc = VINF_VD_ASYNC_IO_FINISHED;
     220        void *pvCallerUser = NULL;
     221
     222        if (pStorageBackend->pfnCompleted)
     223            rc = pStorageBackend->pfnCompleted(pvUser, &pvCallerUser);
     224        else
     225            pvCallerUser = pvUser;
     226
     227        if (rc == VINF_VD_ASYNC_IO_FINISHED)
     228        {
     229            rc = pThis->pDrvMediaAsyncPort->pfnTransferCompleteNotify(pThis->pDrvMediaAsyncPort, pvCallerUser);
     230            AssertRC(rc);
     231        }
     232        else
     233            AssertMsg(rc == VERR_VD_ASYNC_IO_IN_PROGRESS, ("Invalid return code from disk backend rc=%Rrc\n", rc));
     234    }
     235}
     236
     237static DECLCALLBACK(int) drvvdAsyncIOOpen(void *pvUser, const char *pszLocation, unsigned uOpenFlags,
    234238                                          PFNVDCOMPLETED pfnCompleted, void **ppStorage)
    235239{
     
    251255            {
    252256                rc = PDMR3AsyncCompletionEpCreateForFile(&pStorageBackend->pEndpoint, pszLocation,
    253                                                          fReadonly
     257                                                         uOpenFlags & VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY
    254258                                                         ? PDMACEP_FILE_FLAGS_READ_ONLY | PDMACEP_FILE_FLAGS_CACHING
    255259                                                         : PDMACEP_FILE_FLAGS_CACHING,
     
    292296
    293297    return PDMR3AsyncCompletionEpGetSize(pStorageBackend->pEndpoint, pcbSize);
     298}
     299
     300static DECLCALLBACK(int) drvvdAsyncIOSetSize(void *pvUser, void *pStorage, uint64_t cbSize)
     301{
     302    PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
     303    PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
     304
     305    return VERR_NOT_SUPPORTED;
    294306}
    295307
     
    846858    pThis->VDIAsyncIOCallbacks.pfnClose                = drvvdAsyncIOClose;
    847859    pThis->VDIAsyncIOCallbacks.pfnGetSize              = drvvdAsyncIOGetSize;
     860    pThis->VDIAsyncIOCallbacks.pfnSetSize              = drvvdAsyncIOSetSize;
    848861    pThis->VDIAsyncIOCallbacks.pfnReadSync             = drvvdAsyncIOReadSync;
    849862    pThis->VDIAsyncIOCallbacks.pfnWriteSync            = drvvdAsyncIOWriteSync;
     
    871884    /* Try to attach async media port interface above.*/
    872885    pThis->pDrvMediaAsyncPort = (PPDMIMEDIAASYNCPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_MEDIA_ASYNC_PORT);
    873 
    874     /*
    875      * Attach the async transport driver below if the device above us implements the
    876      * async interface.
    877      */
    878     if (pThis->pDrvMediaAsyncPort)
    879     {
    880         /* Try to attach the driver. */
    881         PPDMIBASE pBase;
    882 
    883         rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pBase);
    884         if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
    885         {
    886             /*
    887              * Though the device supports async I/O there is no transport driver
    888              * which processes async requests.
    889              * Revert to non async I/O.
    890              */
    891             rc = VINF_SUCCESS;
    892             pThis->pDrvMediaAsyncPort = NULL;
    893             pThis->fAsyncIOSupported = false;
    894         }
    895         else if (RT_FAILURE(rc))
    896         {
    897             AssertMsgFailed(("Failed to attach async transport driver below rc=%Rrc\n", rc));
    898         }
    899         else
    900         {
    901             /*
    902              * The device supports async I/O and we successfully attached the transport driver.
    903              * Indicate that async I/O is supported for now as we check if the image backend supports
    904              * it later.
    905              */
    906             pThis->fAsyncIOSupported = true;
    907 
    908             /** @todo: Use PDM async completion manager */
    909         }
    910     }
    911886
    912887    /*
     
    10421017    }
    10431018
     1019    if (pThis->pDrvMediaAsyncPort)
     1020        pThis->fAsyncIOSupported = true;
     1021
    10441022    while (pCurNode && RT_SUCCESS(rc))
    10451023    {
     
    10861064        if (fHonorZeroWrites)
    10871065            uOpenFlags |= VD_OPEN_FLAGS_HONOR_ZEROES;
    1088         if (pThis->pDrvMediaAsyncPort)
     1066        if (pThis->fAsyncIOSupported)
    10891067            uOpenFlags |= VD_OPEN_FLAGS_ASYNC_IO;
    10901068
     
    10941072        {
    10951073            /* Seems async I/O is not supported by the backend, open in normal mode. */
     1074            pThis->fAsyncIOSupported = false;
    10961075            uOpenFlags &= ~VD_OPEN_FLAGS_ASYNC_IO;
    10971076            rc = VDOpen(pThis->pDisk, pszFormat, pszName, uOpenFlags, pImage->pVDIfsImage);
     
    11491128    else
    11501129    {
    1151         /*
    1152          * Check if every opened image supports async I/O.
    1153          * If not we revert to non async I/O.
    1154          */
    1155         if (pThis->fAsyncIOSupported)
    1156         {
    1157             for (unsigned i = 0; i < VDGetCount(pThis->pDisk); i++)
    1158             {
    1159                 VDBACKENDINFO vdBackendInfo;
    1160 
    1161                 rc = VDBackendInfoSingle(pThis->pDisk, i, &vdBackendInfo);
    1162                 AssertRC(rc);
    1163 
    1164                 if (vdBackendInfo.uBackendCaps & VD_CAP_ASYNC)
    1165                 {
    1166                     /*
    1167                      * Backend indicates support for at least some files.
    1168                      * Check if current file is supported with async I/O)
    1169                      */
    1170                     rc = VDImageIsAsyncIOSupported(pThis->pDisk, i, &pThis->fAsyncIOSupported);
    1171                     AssertRC(rc);
    1172 
    1173                     /*
    1174                      * Check if current image is supported.
    1175                      * If not we can stop checking because
    1176                      * at least one does not support it.
    1177                      */
    1178                     if (!pThis->fAsyncIOSupported)
    1179                         break;
    1180                 }
    1181                 else
    1182                 {
    1183                     pThis->fAsyncIOSupported = false;
    1184                     break;
    1185                 }
    1186             }
    1187         }
    1188 
    11891130        /* Switch to runtime error facility. */
    11901131        pThis->fErrorUseRuntime = true;
  • trunk/src/VBox/Devices/Storage/ParallelsHDDCore.cpp

    r21806 r22966  
    7070    /** Error interface callbacks. */
    7171    PVDINTERFACEERROR   pInterfaceErrorCallbacks;
     72#ifdef VBOX_WITH_NEW_IO_CODE
     73    /** Async I/O interface. */
     74    PVDINTERFACE        pInterfaceAsyncIO;
     75    /** Async I/O interface callbacks. */
     76    PVDINTERFACEASYNCIO pInterfaceAsyncIOCallbacks;
     77#endif
    7278
    7379    /** Image file name. */
    7480    const char         *pszFilename;
    75     /** File handle. */
     81#ifndef VBOX_WITH_NEW_IO_CODE
     82    /** File descriptor. */
    7683    RTFILE              File;
     84#else
     85    /** Opaque storage handle. */
     86    void               *pvStorage;
     87#endif
    7788    /** Open flags passed by VBoxHD layer. */
    7889    unsigned            uOpenFlags;
     
    125136}
    126137
     138static int parallelsFileOpen(PPARALLELSIMAGE pImage, bool fReadonly, bool fCreate)
     139{
     140    int rc = VINF_SUCCESS;
     141
     142    AssertMsg(!(fReadonly && fCreate), ("Image can't be opened readonly while being created\n"));
     143
     144#ifndef VBOX_WITH_NEW_IO_CODE
     145    unsigned uFileFlags = fReadonly ? RTFILE_O_READ      | RTFILE_O_DENY_NONE
     146                                    : RTFILE_O_READWRITE | RTFILE_O_DENY_WRITE;
     147
     148    if (fCreate)
     149        uFileFlags |= RTFILE_O_CREATE;
     150    else
     151        uFileFlags |= RTFILE_O_OPEN;
     152
     153    rc = RTFileOpen(&pImage->File, pImage->pszFilename, uFileFlags);
     154#else
     155
     156    unsigned uOpenFlags = fReadonly ? VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY : 0;
     157
     158    if (fCreate)
     159        uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE;
     160
     161    rc = pImage->pInterfaceAsyncIOCallbacks->pfnOpen(pImage->pInterfaceAsyncIO->pvUser,
     162                                                     pImage->pszFilename,
     163                                                     uOpenFlags,
     164                                                     NULL, &pImage->pvStorage);
     165#endif
     166
     167    return rc;
     168}
     169
     170static int parallelsFileClose(PPARALLELSIMAGE pImage)
     171{
     172    int rc = VINF_SUCCESS;
     173
     174#ifndef VBOX_WITH_NEW_IO_CODE
     175    if (pImage->File != NIL_RTFILE)
     176        rc = RTFileClose(pImage->File);
     177
     178    pImage->File = NIL_RTFILE;
     179#else
     180    if (pImage->pvStorage)
     181        rc = pImage->pInterfaceAsyncIOCallbacks->pfnClose(pImage->pInterfaceAsyncIO->pvUser,
     182                                                          pImage->pvStorage);
     183
     184    pImage->pvStorage = NULL;
     185#endif
     186
     187    return rc;
     188}
     189
     190static int parallelsFileFlushSync(PPARALLELSIMAGE pImage)
     191{
     192    int rc = VINF_SUCCESS;
     193
     194#ifndef VBOX_WITH_NEW_IO_CODE
     195    rc = RTFileFlush(pImage->File);
     196#else
     197    if (pImage->pvStorage)
     198        rc = pImage->pInterfaceAsyncIOCallbacks->pfnFlushSync(pImage->pInterfaceAsyncIO->pvUser,
     199                                                              pImage->pvStorage);
     200#endif
     201
     202    return rc;
     203}
     204
     205static int parallelsFileGetSize(PPARALLELSIMAGE pImage, uint64_t *pcbSize)
     206{
     207    int rc = VINF_SUCCESS;
     208
     209#ifndef VBOX_WITH_NEW_IO_CODE
     210    rc = RTFileGetSize(pImage->File, pcbSize);
     211#else
     212    if (pImage->pvStorage)
     213        rc = pImage->pInterfaceAsyncIOCallbacks->pfnGetSize(pImage->pInterfaceAsyncIO->pvUser,
     214                                                            pImage->pvStorage,
     215                                                            pcbSize);
     216#endif
     217
     218    return rc;
     219
     220}
     221
     222static int parallelsFileSetSize(PPARALLELSIMAGE pImage, uint64_t cbSize)
     223{
     224    int rc = VINF_SUCCESS;
     225
     226#ifndef VBOX_WITH_NEW_IO_CODE
     227    rc = RTFileSetSize(pImage->File, cbSize);
     228#else
     229    if (pImage->pvStorage)
     230        rc = pImage->pInterfaceAsyncIOCallbacks->pfnSetSize(pImage->pInterfaceAsyncIO->pvUser,
     231                                                            pImage->pvStorage,
     232                                                            cbSize);
     233#endif
     234
     235    return rc;
     236}
     237
     238
     239static int parallelsFileWriteSync(PPARALLELSIMAGE pImage, uint64_t off, const void *pcvBuf, size_t cbWrite, size_t *pcbWritten)
     240{
     241    int rc = VINF_SUCCESS;
     242
     243#ifndef VBOX_WITH_NEW_IO_CODE
     244    rc = RTFileWriteAt(pImage->File, off, pcvBuf, cbWrite, pcbWritten);
     245#else
     246    if (pImage->pvStorage)
     247        rc = pImage->pInterfaceAsyncIOCallbacks->pfnWriteSync(pImage->pInterfaceAsyncIO->pvUser,
     248                                                              pImage->pvStorage,
     249                                                              off, cbWrite, pcvBuf,
     250                                                              pcbWritten);
     251#endif
     252
     253    return rc;
     254}
     255
     256static int parallelsFileReadSync(PPARALLELSIMAGE pImage, uint64_t off, void *pvBuf, size_t cbRead, size_t *pcbRead)
     257{
     258    int rc = VINF_SUCCESS;
     259
     260#ifndef VBOX_WITH_NEW_IO_CODE
     261    rc = RTFileReadAt(pImage->File, off, pvBuf, cbRead, pcbRead);
     262#else
     263    if (pImage->pvStorage)
     264        rc = pImage->pInterfaceAsyncIOCallbacks->pfnReadSync(pImage->pInterfaceAsyncIO->pvUser,
     265                                                             pImage->pvStorage,
     266                                                             off, cbRead, pvBuf,
     267                                                             pcbRead);
     268#endif
     269
     270    return rc;
     271}
     272
     273static bool parallelsFileOpened(PPARALLELSIMAGE pImage)
     274{
     275#ifndef VBOX_WITH_NEW_IO_CODE
     276    return pImage->File != NIL_RTFILE;
     277#else
     278    return pImage->pvStorage != NULL;
     279#endif
     280}
     281
    127282static int parallelsOpenImage(PPARALLELSIMAGE pImage, unsigned uOpenFlags)
    128283{
    129284    int rc = VINF_SUCCESS;
    130     RTFILE File;
    131285    ParallelsHeader parallelsHeader;
    132286
     
    136290        pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError);
    137291
    138     rc = RTFileOpen(&File, pImage->pszFilename,
    139                     uOpenFlags & VD_OPEN_FLAGS_READONLY
    140                      ? RTFILE_O_READ      | RTFILE_O_OPEN | RTFILE_O_DENY_NONE
    141                      : RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
     292#ifdef VBOX_WITH_NEW_IO_CODE
     293    /* Try to get async I/O interface. */
     294    pImage->pInterfaceAsyncIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ASYNCIO);
     295    AssertPtr(pImage->pInterfaceAsyncIO);
     296    pImage->pInterfaceAsyncIOCallbacks = VDGetInterfaceAsyncIO(pImage->pInterfaceAsyncIO);
     297    AssertPtr(pImage->pInterfaceAsyncIOCallbacks);
     298#endif
     299
     300    rc = parallelsFileOpen(pImage, !!(uOpenFlags & VD_OPEN_FLAGS_READONLY), false);
    142301    if (RT_FAILURE(rc))
    143302        goto out;
    144303
    145     pImage->File = File;
    146 
    147     rc = RTFileGetSize(pImage->File, &pImage->cbFileCurrent);
     304    rc = parallelsFileGetSize(pImage, &pImage->cbFileCurrent);
    148305    if (RT_FAILURE(rc))
    149306        goto out;
    150307    AssertMsg(pImage->cbFileCurrent % 512 == 0, ("File size is not a multiple of 512\n"));
    151308
    152     rc = RTFileReadAt(File, 0, &parallelsHeader, sizeof(ParallelsHeader), NULL);
     309    rc = parallelsFileReadSync(pImage, 0, &parallelsHeader, sizeof(parallelsHeader), NULL);
    153310    if (RT_FAILURE(rc))
    154311        goto out;
     
    198355        }
    199356
    200         rc = RTFileReadAt(File, sizeof(ParallelsHeader), pImage->pAllocationBitmap,
    201                           pImage->cAllocationBitmapEntries * sizeof(uint32_t), NULL);
     357        rc = parallelsFileReadSync(pImage, sizeof(ParallelsHeader),
     358                                   pImage->pAllocationBitmap,
     359                                   pImage->cAllocationBitmapEntries * sizeof(uint32_t),
     360                                   NULL);
    202361        if (RT_FAILURE(rc))
    203362            goto out;
     
    223382        pImage->fAllocationBitmapChanged = false;
    224383        /* Write the allocation bitmap to the file. */
    225         rc = RTFileWriteAt(pImage->File, sizeof(ParallelsHeader),
    226                            pImage->pAllocationBitmap,
    227                            pImage->cAllocationBitmapEntries * sizeof(uint32_t),
    228                            NULL);
     384        rc = parallelsFileWriteSync(pImage, sizeof(ParallelsHeader),
     385                                    pImage->pAllocationBitmap,
     386                                    pImage->cAllocationBitmapEntries * sizeof(uint32_t),
     387                                    NULL);
    229388        if (RT_FAILURE(rc))
    230389            return rc;
     
    232391
    233392    /* Flush file. */
    234     rc = RTFileFlush(pImage->File);
     393    rc = parallelsFileFlushSync(pImage);
    235394
    236395    LogFlowFunc(("returns %Rrc\n", rc));
     
    245404        RTMemFree(pImage->pAllocationBitmap);
    246405
    247     if (pImage->File != NIL_RTFILE)
    248         RTFileClose(pImage->File);
     406    if (parallelsFileOpened(pImage))
     407        parallelsFileClose(pImage);
    249408}
    250409
     
    340499    }
    341500
     501#ifndef VBOX_WITH_NEW_IO_CODE
    342502    pImage->File = NIL_RTFILE;
     503#else
     504    pImage->pvStorage = NULL;
     505#endif
    343506    pImage->fAllocationBitmapChanged = false;
    344507    pImage->pszFilename = pszFilename;
     
    408571    if (pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED)
    409572    {
    410         rc = RTFileReadAt(pImage->File, uOffset, pvBuf, cbToRead, NULL);
     573        rc = parallelsFileReadSync(pImage, uOffset,
     574                                   pvBuf, cbToRead, NULL);
    411575    }
    412576    else
     
    427591        {
    428592            uOffsetInFile = (pImage->pAllocationBitmap[iIndexInAllocationTable] + uSector) * 512;
    429             rc = RTFileReadAt(pImage->File, uOffsetInFile, pvBuf, cbToRead, NULL);
     593            rc = parallelsFileReadSync(pImage, uOffsetInFile,
     594                                       pvBuf, cbToRead, NULL);
    430595        }
    431596    }
     
    455620    if (pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED)
    456621    {
    457         rc = RTFileWriteAt(pImage->File, uOffset, pvBuf, cbToWrite, NULL);
     622        rc = parallelsFileWriteSync(pImage, uOffset,
     623                                    pvBuf, cbToWrite, NULL);
    458624    }
    459625    else
     
    474640            pImage->cbFileCurrent += pImage->PCHSGeometry.cSectors * 512;
    475641            pImage->fAllocationBitmapChanged = true;
    476             rc = RTFileSetSize(pImage->File, pImage->cbFileCurrent);
    477             if (RT_FAILURE(rc))
    478                 return rc;
    479         }
    480 
    481         uOffsetInFile = (pImage->pAllocationBitmap[iIndexInAllocationTable] + uSector) * 512;
    482         rc = RTFileWriteAt(pImage->File, uOffsetInFile, pvBuf, cbToWrite, NULL);
     642
     643            uint8_t *pNewBlock = (uint8_t *)RTMemAllocZ(pImage->PCHSGeometry.cSectors * 512);
     644
     645            if (!pNewBlock)
     646                return VERR_NO_MEMORY;
     647
     648            uOffsetInFile = (uint64_t)pImage->pAllocationBitmap[iIndexInAllocationTable] * 512;
     649            memcpy(pNewBlock + (uOffset - ((uint64_t)iIndexInAllocationTable * pImage->PCHSGeometry.cSectors * 512)),
     650                   pvBuf, cbToWrite);
     651
     652            /*
     653             * Write the new block at the current end of the file.
     654             */
     655            rc = parallelsFileWriteSync(pImage, uOffsetInFile,
     656                                        pNewBlock,
     657                                        pImage->PCHSGeometry.cSectors * 512, NULL);
     658
     659            RTMemFree(pNewBlock);
     660        }
     661        else
     662        {
     663            uOffsetInFile = (pImage->pAllocationBitmap[iIndexInAllocationTable] + uSector) * 512;
     664            rc = parallelsFileWriteSync(pImage, uOffsetInFile,
     665                                        pvBuf, cbToWrite, NULL);
     666        }
    483667    }
    484668
     
    543727    if (pImage)
    544728    {
    545         if (pImage->File != NIL_RTFILE)
    546         {
    547             RTFileGetSize(pImage->File, &cb);
    548         }
     729        if (parallelsFileOpened(pImage))
     730            cb = pImage->cbFileCurrent;
    549731    }
    550732
  • trunk/src/VBox/Devices/Storage/RawHDDCore.cpp

    r21806 r22966  
    4444    /** Base image name. */
    4545    const char      *pszFilename;
     46#ifndef VBOX_WITH_NEW_IO_CODE
    4647    /** File descriptor. */
    4748    RTFILE          File;
     49#else
     50    /** Opaque storage handle. */
     51    void           *pvStorage;
     52#endif
    4853
    4954    /** Pointer to the per-disk VD interface list. */
     
    5459    /** Opaque data for error callback. */
    5560    PVDINTERFACEERROR pInterfaceErrorCallbacks;
     61#ifdef VBOX_WITH_NEW_IO_CODE
     62    /** Async I/O interface. */
     63    PVDINTERFACE        pInterfaceAsyncIO;
     64    /** Async I/O interface callbacks. */
     65    PVDINTERFACEASYNCIO pInterfaceAsyncIOCallbacks;
     66#endif
    5667
    5768    /** Open flags passed by VBoxHD layer. */
     
    104115}
    105116
     117static int rawFileOpen(PRAWIMAGE pImage, bool fReadonly, bool fCreate)
     118{
     119    int rc = VINF_SUCCESS;
     120
     121    AssertMsg(!(fReadonly && fCreate), ("Image can't be opened readonly while being created\n"));
     122
     123#ifndef VBOX_WITH_NEW_IO_CODE
     124    unsigned uFileFlags = fReadonly ? RTFILE_O_READ      | RTFILE_O_DENY_NONE
     125                                    : RTFILE_O_READWRITE | RTFILE_O_DENY_WRITE;
     126
     127    if (fCreate)
     128        uFileFlags |= RTFILE_O_CREATE;
     129    else
     130        uFileFlags |= RTFILE_O_OPEN;
     131
     132    rc = RTFileOpen(&pImage->File, pImage->pszFilename, uFileFlags);
     133#else
     134
     135    unsigned uOpenFlags = fReadonly ? VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY : 0;
     136
     137    if (fCreate)
     138        uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE;
     139
     140    rc = pImage->pInterfaceAsyncIOCallbacks->pfnOpen(pImage->pInterfaceAsyncIO->pvUser,
     141                                                     pImage->pszFilename,
     142                                                     uOpenFlags,
     143                                                     NULL, &pImage->pvStorage);
     144#endif
     145
     146    return rc;
     147}
     148
     149static int rawFileClose(PRAWIMAGE pImage)
     150{
     151    int rc = VINF_SUCCESS;
     152
     153#ifndef VBOX_WITH_NEW_IO_CODE
     154    if (pImage->File != NIL_RTFILE)
     155        rc = RTFileClose(pImage->File);
     156
     157    pImage->File = NIL_RTFILE;
     158#else
     159    if (pImage->pvStorage)
     160        rc = pImage->pInterfaceAsyncIOCallbacks->pfnClose(pImage->pInterfaceAsyncIO->pvUser,
     161                                                          pImage->pvStorage);
     162
     163    pImage->pvStorage = NULL;
     164#endif
     165
     166    return rc;
     167}
     168
     169static int rawFileFlushSync(PRAWIMAGE pImage)
     170{
     171    int rc = VINF_SUCCESS;
     172
     173#ifndef VBOX_WITH_NEW_IO_CODE
     174    rc = RTFileFlush(pImage->File);
     175#else
     176    if (pImage->pvStorage)
     177        rc = pImage->pInterfaceAsyncIOCallbacks->pfnFlushSync(pImage->pInterfaceAsyncIO->pvUser,
     178                                                              pImage->pvStorage);
     179#endif
     180
     181    return rc;
     182}
     183
     184static int rawFileGetSize(PRAWIMAGE pImage, uint64_t *pcbSize)
     185{
     186    int rc = VINF_SUCCESS;
     187
     188#ifndef VBOX_WITH_NEW_IO_CODE
     189    rc = RTFileGetSize(pImage->File, pcbSize);
     190#else
     191    if (pImage->pvStorage)
     192        rc = pImage->pInterfaceAsyncIOCallbacks->pfnGetSize(pImage->pInterfaceAsyncIO->pvUser,
     193                                                            pImage->pvStorage,
     194                                                            pcbSize);
     195#endif
     196
     197    return rc;
     198
     199}
     200
     201static int rawFileSetSize(PRAWIMAGE pImage, uint64_t cbSize)
     202{
     203    int rc = VINF_SUCCESS;
     204
     205#ifndef VBOX_WITH_NEW_IO_CODE
     206    rc = RTFileSetSize(pImage->File, cbSize);
     207#else
     208    if (pImage->pvStorage)
     209        rc = pImage->pInterfaceAsyncIOCallbacks->pfnSetSize(pImage->pInterfaceAsyncIO->pvUser,
     210                                                            pImage->pvStorage,
     211                                                            cbSize);
     212#endif
     213
     214    return rc;
     215}
     216
     217
     218static int rawFileWriteSync(PRAWIMAGE pImage, uint64_t off, const void *pcvBuf, size_t cbWrite, size_t *pcbWritten)
     219{
     220    int rc = VINF_SUCCESS;
     221
     222#ifndef VBOX_WITH_NEW_IO_CODE
     223    rc = RTFileWriteAt(pImage->File, off, pcvBuf, cbWrite, pcbWritten);
     224#else
     225    if (pImage->pvStorage)
     226        rc = pImage->pInterfaceAsyncIOCallbacks->pfnWriteSync(pImage->pInterfaceAsyncIO->pvUser,
     227                                                              pImage->pvStorage,
     228                                                              off, cbWrite, pcvBuf,
     229                                                              pcbWritten);
     230#endif
     231
     232    return rc;
     233}
     234
     235static int rawFileReadSync(PRAWIMAGE pImage, uint64_t off, void *pvBuf, size_t cbRead, size_t *pcbRead)
     236{
     237    int rc = VINF_SUCCESS;
     238
     239#ifndef VBOX_WITH_NEW_IO_CODE
     240    rc = RTFileReadAt(pImage->File, off, pvBuf, cbRead, pcbRead);
     241#else
     242    if (pImage->pvStorage)
     243        rc = pImage->pInterfaceAsyncIOCallbacks->pfnReadSync(pImage->pInterfaceAsyncIO->pvUser,
     244                                                             pImage->pvStorage,
     245                                                             off, cbRead, pvBuf,
     246                                                             pcbRead);
     247#endif
     248
     249    return rc;
     250}
     251
     252static bool rawFileOpened(PRAWIMAGE pImage)
     253{
     254#ifndef VBOX_WITH_NEW_IO_CODE
     255    return pImage->File != NIL_RTFILE;
     256#else
     257    return pImage->pvStorage != NULL;
     258#endif
     259}
     260
    106261/**
    107262 * Internal: Open an image, constructing all necessary data structures.
     
    110265{
    111266    int rc;
    112     RTFILE File;
    113267
    114268    if (uOpenFlags & VD_OPEN_FLAGS_ASYNC_IO)
     
    121275        pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError);
    122276
     277#ifdef VBOX_WITH_NEW_IO_CODE
     278    /* Try to get async I/O interface. */
     279    pImage->pInterfaceAsyncIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ASYNCIO);
     280    AssertPtr(pImage->pInterfaceAsyncIO);
     281    pImage->pInterfaceAsyncIOCallbacks = VDGetInterfaceAsyncIO(pImage->pInterfaceAsyncIO);
     282    AssertPtr(pImage->pInterfaceAsyncIOCallbacks);
     283#endif
     284
    123285    /*
    124286     * Open the image.
    125287     */
    126     rc = RTFileOpen(&File, pImage->pszFilename,
    127                     uOpenFlags & VD_OPEN_FLAGS_READONLY
    128                      ? RTFILE_O_READ      | RTFILE_O_OPEN | RTFILE_O_DENY_NONE
    129                      : RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
     288    rc = rawFileOpen(pImage, !!(uOpenFlags & VD_OPEN_FLAGS_READONLY), false);
    130289    if (RT_FAILURE(rc))
    131290    {
     
    134293        goto out;
    135294    }
    136     pImage->File = File;
    137 
    138     rc = RTFileGetSize(pImage->File, &pImage->cbSize);
     295
     296    rc = rawFileGetSize(pImage, &pImage->cbSize);
    139297    if (RT_FAILURE(rc))
    140298        goto out;
     
    163321{
    164322    int rc;
    165     RTFILE File;
    166323    RTFOFF cbFree = 0;
    167324    uint64_t uOff;
     
    184341        pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError);
    185342
     343#ifdef VBOX_WITH_NEW_IO_CODE
     344    /* Try to get async I/O interface. */
     345    pImage->pInterfaceAsyncIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ASYNCIO);
     346    AssertPtr(pImage->pInterfaceAsyncIO);
     347    pImage->pInterfaceAsyncIOCallbacks = VDGetInterfaceAsyncIO(pImage->pInterfaceAsyncIO);
     348    AssertPtr(pImage->pInterfaceAsyncIOCallbacks);
     349#endif
     350
    186351    /* Create image file. */
    187     rc = RTFileOpen(&File, pImage->pszFilename,
    188                     RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_ALL);
     352    rc = rawFileOpen(pImage, false, true);
    189353    if (RT_FAILURE(rc))
    190354    {
     
    192356        goto out;
    193357    }
    194     pImage->File = File;
    195358
    196359    /* Check the free space on the disk and leave early if there is not
     
    205368    /* Allocate & commit whole file if fixed image, it must be more
    206369     * effective than expanding file by write operations. */
    207     rc = RTFileSetSize(File, cbSize);
     370    rc = rawFileSetSize(pImage, cbSize);
    208371    if (RT_FAILURE(rc))
    209372    {
     
    229392        unsigned cbChunk = (unsigned)RT_MIN(cbSize, cbBuf);
    230393
    231         rc = RTFileWriteAt(File, uOff, pvBuf, cbChunk, NULL);
     394        rc = rawFileWriteSync(pImage, uOff, pvBuf, cbChunk, NULL);
    232395        if (RT_FAILURE(rc))
    233396        {
     
    275438    Assert(pImage);
    276439
    277     if (pImage->File != NIL_RTFILE)
     440    if (rawFileOpened(pImage))
    278441    {
    279442        if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    280443            rawFlushImage(pImage);
    281         RTFileClose(pImage->File);
    282         pImage->File = NIL_RTFILE;
     444        rawFileClose(pImage);
    283445    }
    284446    if (fDelete && pImage->pszFilename)
     
    293455    int rc = VINF_SUCCESS;
    294456
    295     if (   pImage->File != NIL_RTFILE
     457    if (   rawFileOpened(pImage)
    296458        && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    297         rc = RTFileFlush(pImage->File);
     459        rc = rawFileFlushSync(pImage);
    298460
    299461    return rc;
     
    354516    }
    355517    pImage->pszFilename = pszFilename;
     518#ifndef VBOX_WITH_NEW_IO_CODE
    356519    pImage->File = NIL_RTFILE;
     520#else
     521    pImage->pvStorage = NULL;
     522#endif
    357523    pImage->pVDIfsDisk = pVDIfsDisk;
    358524
     
    417583    }
    418584    pImage->pszFilename = pszFilename;
     585#ifndef VBOX_WITH_NEW_IO_CODE
    419586    pImage->File = NIL_RTFILE;
     587#else
     588    pImage->pvStorage = NULL;
     589#endif
    420590    pImage->pVDIfsDisk = pVDIfsDisk;
    421591
     
    487657    }
    488658
    489     rc = RTFileReadAt(pImage->File, uOffset, pvBuf, cbToRead, NULL);
     659    rc = rawFileReadSync(pImage, uOffset, pvBuf, cbToRead, NULL);
    490660    *pcbActuallyRead = cbToRead;
    491661
     
    521691    }
    522692
    523     rc = RTFileWriteAt(pImage->File, uOffset, pvBuf, cbToWrite, NULL);
     693    rc = rawFileWriteSync(pImage, uOffset, pvBuf, cbToWrite, NULL);
    524694    if (pcbWriteProcess)
    525695        *pcbWriteProcess = cbToWrite;
     
    582752    {
    583753        uint64_t cbFile;
    584         if (pImage->File != NIL_RTFILE)
     754        if (rawFileOpened(pImage))
    585755        {
    586             int rc = RTFileGetSize(pImage->File, &cbFile);
     756            int rc = rawFileGetSize(pImage, &cbFile);
    587757            if (RT_SUCCESS(rc))
    588758                cb += cbFile;
  • trunk/src/VBox/Devices/Storage/VBoxHDD.cpp

    r21806 r22966  
    4747/** Buffer size used for merging images. */
    4848#define VD_MERGE_BUFFER_SIZE    (16 * _1M)
     49
     50/**
     51 * VD async I/O interface storage descriptor.
     52 */
     53typedef struct VDIASYNCIOSTORAGE
     54{
     55    /** File handle. */
     56    RTFILE         File;
     57    /** Completion callback. */
     58    PFNVDCOMPLETED pfnCompleted;
     59    /** Thread for async access. */
     60    RTTHREAD       ThreadAsync;
     61} VDIASYNCIOSTORAGE, *PVDIASYNCIOSTORAGE;
    4962
    5063/**
     
    116129    /** Pointer to the error interface we use if available. */
    117130    PVDINTERFACEERROR   pInterfaceErrorCallbacks;
     131
     132    /** Fallback async interface. */
     133    VDINTERFACE         VDIAsyncIO;
     134    /** Fallback async I/O interface callback table. */
     135    VDINTERFACEASYNCIO  VDIAsyncIOCallbacks;
    118136};
    119137
     
    708726
    709727/**
     728 * VD async I/O interface open callback.
     729 */
     730static int vdAsyncIOOpen(void *pvUser, const char *pszLocation, unsigned uOpenFlags,
     731                         PFNVDCOMPLETED pfnCompleted, void **ppStorage)
     732{
     733    PVDIASYNCIOSTORAGE pStorage = (PVDIASYNCIOSTORAGE)RTMemAllocZ(sizeof(VDIASYNCIOSTORAGE));
     734
     735    if (!pStorage)
     736        return VERR_NO_MEMORY;
     737
     738    pStorage->pfnCompleted = pfnCompleted;
     739
     740    unsigned uFlags = 0;
     741
     742    if (uOpenFlags & VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY)
     743        uFlags |= RTFILE_O_READ | RTFILE_O_DENY_NONE;
     744    else
     745        uFlags |= RTFILE_O_READWRITE | RTFILE_O_DENY_WRITE;
     746
     747    if (uOpenFlags & VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE)
     748        uFlags |= RTFILE_O_CREATE;
     749    else
     750        uFlags |= RTFILE_O_OPEN;
     751
     752    /* Open the file. */
     753    int rc = RTFileOpen(&pStorage->File, pszLocation, uFlags);
     754    if (RT_SUCCESS(rc))
     755    {
     756        *ppStorage = pStorage;
     757        return VINF_SUCCESS;
     758    }
     759
     760    RTMemFree(pStorage);
     761    return rc;
     762}
     763
     764/**
     765 * VD async I/O interface close callback.
     766 */
     767static int vdAsyncIOClose(void *pvUser, void *pvStorage)
     768{
     769    PVDIASYNCIOSTORAGE pStorage = (PVDIASYNCIOSTORAGE)pvStorage;
     770
     771    RTFileClose(pStorage->File);
     772    RTMemFree(pStorage);
     773    return VINF_SUCCESS;
     774}
     775
     776/**
     777 * VD async I/O interface callback for retrieving the file size.
     778 */
     779static int vdAsyncIOGetSize(void *pvUser, void *pvStorage, uint64_t *pcbSize)
     780{
     781    PVDIASYNCIOSTORAGE pStorage = (PVDIASYNCIOSTORAGE)pvStorage;
     782
     783    return RTFileGetSize(pStorage->File, pcbSize);
     784}
     785
     786/**
     787 * VD async I/O interface callback for setting the file size.
     788 */
     789static int vdAsyncIOSetSize(void *pvUser, void *pvStorage, uint64_t cbSize)
     790{
     791    PVDIASYNCIOSTORAGE pStorage = (PVDIASYNCIOSTORAGE)pvStorage;
     792
     793    return RTFileSetSize(pStorage->File, cbSize);
     794}
     795
     796/**
     797 * VD async I/O interface callback for a synchronous write to the file.
     798 */
     799static int vdAsyncIOWriteSync(void *pvUser, void *pvStorage, uint64_t uOffset,
     800                             size_t cbWrite, const void *pvBuf, size_t *pcbWritten)
     801{
     802    PVDIASYNCIOSTORAGE pStorage = (PVDIASYNCIOSTORAGE)pvStorage;
     803
     804    return RTFileWriteAt(pStorage->File, uOffset, pvBuf, cbWrite, pcbWritten);
     805}
     806
     807/**
     808 * VD async I/O interface callback for a synchronous read from the file.
     809 */
     810static int vdAsyncIOReadSync(void *pvUser, void *pvStorage, uint64_t uOffset,
     811                             size_t cbRead, void *pvBuf, size_t *pcbRead)
     812{
     813    PVDIASYNCIOSTORAGE pStorage = (PVDIASYNCIOSTORAGE)pvStorage;
     814
     815    return RTFileReadAt(pStorage->File, uOffset, pvBuf, cbRead, pcbRead);
     816}
     817
     818/**
     819 * VD async I/O interface callback for a synchronous flush of the file data.
     820 */
     821static int vdAsyncIOFlushSync(void *pvUser, void *pvStorage)
     822{
     823    PVDIASYNCIOSTORAGE pStorage = (PVDIASYNCIOSTORAGE)pvStorage;
     824
     825    return RTFileFlush(pStorage->File);
     826}
     827
     828/**
     829 * VD async I/O interface callback for a asynchronous read from the file.
     830 */
     831static int vdAsyncIOReadAsync(void *pvUser, void *pStorage, uint64_t uOffset,
     832                              PCPDMDATASEG paSegments, size_t cSegments,
     833                              size_t cbRead, void *pvCompletion,
     834                              void **ppTask)
     835{
     836    return VERR_NOT_IMPLEMENTED;
     837}
     838
     839/**
     840 * VD async I/O interface callback for a asynchronous write to the file.
     841 */
     842static int vdAsyncIOWriteAsync(void *pvUser, void *pStorage, uint64_t uOffset,
     843                               PCPDMDATASEG paSegments, size_t cSegments,
     844                               size_t cbWrite, void *pvCompletion,
     845                               void **ppTask)
     846{
     847    return VERR_NOT_IMPLEMENTED;
     848}
     849
     850/**
     851 * VD async I/O interface callback for a asynchronous flush of the file data.
     852 */
     853static int vdAsyncIOFlushAsync(void *pvUser, void *pStorage,
     854                               void *pvCompletion, void **ppTask)
     855{
     856    return VERR_NOT_IMPLEMENTED;
     857}
     858
     859/**
    710860 * internal: send output to the log (unconditionally).
    711861 */
     
    8941044            if (pDisk->pInterfaceError)
    8951045                pDisk->pInterfaceErrorCallbacks = VDGetInterfaceError(pDisk->pInterfaceError);
     1046
     1047            /* Use the fallback async I/O interface if the caller doesn't provide one. */
     1048            PVDINTERFACE pVDIfAsyncIO = VDInterfaceGet(pVDIfsDisk, VDINTERFACETYPE_ASYNCIO);
     1049            if (!pVDIfAsyncIO)
     1050            {
     1051                pDisk->VDIAsyncIOCallbacks.cbSize        = sizeof(VDINTERFACEASYNCIO);
     1052                pDisk->VDIAsyncIOCallbacks.enmInterface  = VDINTERFACETYPE_ASYNCIO;
     1053                pDisk->VDIAsyncIOCallbacks.pfnOpen       = vdAsyncIOOpen;
     1054                pDisk->VDIAsyncIOCallbacks.pfnClose      = vdAsyncIOClose;
     1055                pDisk->VDIAsyncIOCallbacks.pfnGetSize    = vdAsyncIOGetSize;
     1056                pDisk->VDIAsyncIOCallbacks.pfnSetSize    = vdAsyncIOSetSize;
     1057                pDisk->VDIAsyncIOCallbacks.pfnReadSync   = vdAsyncIOReadSync;
     1058                pDisk->VDIAsyncIOCallbacks.pfnWriteSync  = vdAsyncIOWriteSync;
     1059                pDisk->VDIAsyncIOCallbacks.pfnFlushSync  = vdAsyncIOFlushSync;
     1060                pDisk->VDIAsyncIOCallbacks.pfnReadAsync  = vdAsyncIOReadAsync;
     1061                pDisk->VDIAsyncIOCallbacks.pfnWriteAsync = vdAsyncIOWriteAsync;
     1062                pDisk->VDIAsyncIOCallbacks.pfnFlushAsync = vdAsyncIOFlushAsync;
     1063                rc = VDInterfaceAdd(&pDisk->VDIAsyncIO, "VD_AsyncIO", VDINTERFACETYPE_ASYNCIO,
     1064                                    &pDisk->VDIAsyncIOCallbacks, pDisk, &pDisk->pVDIfsDisk);
     1065                AssertRC(rc);
     1066            }
     1067
    8961068            *ppDisk = pDisk;
    8971069        }
  • trunk/src/VBox/Devices/Storage/VDICore.h

    r20374 r22966  
    528528    struct VDIIMAGEDESC    *pNext;
    529529#endif /* !VBOX_VDICORE_VD */
     530#ifndef VBOX_WITH_NEW_IO_CODE
    530531    /** File handle. */
    531532    RTFILE                  File;
     533#else
     534    /** Opaque storage handle. */
     535    void                   *pvStorage;
     536#endif
    532537#ifndef VBOX_VDICORE_VD
    533538    /** True if the image is operating in readonly mode. */
     
    585590    /** Error interface callback table. */
    586591    PVDINTERFACEERROR       pInterfaceErrorCallbacks;
     592# ifdef VBOX_WITH_NEW_IO_CODE
     593    /** Async I/O interface. */
     594    PVDINTERFACE        pInterfaceAsyncIO;
     595    /** Async I/O interface callbacks. */
     596    PVDINTERFACEASYNCIO pInterfaceAsyncIOCallbacks;
     597# endif
    587598#endif /* VBOX_VDICORE_VD */
    588599} VDIIMAGEDESC, *PVDIIMAGEDESC;
  • trunk/src/VBox/Devices/Storage/VDIHDDCore.cpp

    r21806 r22966  
    8282
    8383
     84static int vdiFileOpen(PVDIIMAGEDESC pImage, bool fReadonly, bool fCreate)
     85{
     86    int rc = VINF_SUCCESS;
     87
     88    AssertMsg(!(fReadonly && fCreate), ("Image can't be opened readonly whilebeing created\n"));
     89
     90#ifndef VBOX_WITH_NEW_IO_CODE
     91    unsigned uFileFlags = fReadonly ? RTFILE_O_READ      | RTFILE_O_DENY_NONE
     92                                    : RTFILE_O_READWRITE | RTFILE_O_DENY_WRITE;
     93
     94    if (fCreate)
     95        uFileFlags |= RTFILE_O_CREATE;
     96    else
     97        uFileFlags |= RTFILE_O_OPEN;
     98
     99    rc = RTFileOpen(&pImage->File, pImage->pszFilename, uFileFlags);
     100#else
     101
     102    unsigned uOpenFlags = fReadonly ? VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY : 0;
     103
     104    if (fCreate)
     105        uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE;
     106
     107    rc = pImage->pInterfaceAsyncIOCallbacks->pfnOpen(pImage->pInterfaceAsyncIO->pvUser,
     108                                                     pImage->pszFilename,
     109                                                     uOpenFlags,
     110                                                     NULL, &pImage->pvStorage);
     111#endif
     112
     113    return rc;
     114}
     115
     116static int vdiFileClose(PVDIIMAGEDESC pImage)
     117{
     118    int rc = VINF_SUCCESS;
     119
     120#ifndef VBOX_WITH_NEW_IO_CODE
     121    if (pImage->File != NIL_RTFILE)
     122        rc = RTFileClose(pImage->File);
     123
     124    pImage->File = NIL_RTFILE;
     125#else
     126    if (pImage->pvStorage)
     127        rc = pImage->pInterfaceAsyncIOCallbacks->pfnClose(pImage->pInterfaceAsyncIO->pvUser,
     128                                                          pImage->pvStorage);
     129
     130    pImage->pvStorage = NULL;
     131#endif
     132
     133    return rc;
     134}
     135
     136static int vdiFileFlushSync(PVDIIMAGEDESC pImage)
     137{
     138    int rc = VINF_SUCCESS;
     139
     140#ifndef VBOX_WITH_NEW_IO_CODE
     141    rc = RTFileFlush(pImage->File);
     142#else
     143    if (pImage->pvStorage)
     144        rc = pImage->pInterfaceAsyncIOCallbacks->pfnFlushSync(pImage->pInterfaceAsyncIO->pvUser,
     145                                                              pImage->pvStorage);
     146#endif
     147
     148    return rc;
     149}
     150
     151static int vdiFileGetSize(PVDIIMAGEDESC pImage, uint64_t *pcbSize)
     152{
     153    int rc = VINF_SUCCESS;
     154
     155#ifndef VBOX_WITH_NEW_IO_CODE
     156    rc = RTFileGetSize(pImage->File, pcbSize);
     157#else
     158    if (pImage->pvStorage)
     159        rc = pImage->pInterfaceAsyncIOCallbacks->pfnGetSize(pImage->pInterfaceAsyncIO->pvUser,
     160                                                            pImage->pvStorage,
     161                                                            pcbSize);
     162#endif
     163
     164    return rc;
     165}
     166
     167static int vdiFileSetSize(PVDIIMAGEDESC pImage, uint64_t cbSize)
     168{
     169    int rc = VINF_SUCCESS;
     170
     171#ifndef VBOX_WITH_NEW_IO_CODE
     172    rc = RTFileSetSize(pImage->File, cbSize);
     173#else
     174    if (pImage->pvStorage)
     175        rc = pImage->pInterfaceAsyncIOCallbacks->pfnSetSize(pImage->pInterfaceAsyncIO->pvUser,
     176                                                            pImage->pvStorage,
     177                                                            cbSize);
     178#endif
     179
     180    return rc;
     181}
     182
     183static int vdiFileWriteSync(PVDIIMAGEDESC pImage, uint64_t off, const void *pcvBuf, size_t cbWrite, size_t *pcbWritten)
     184{
     185    int rc = VINF_SUCCESS;
     186
     187#ifndef VBOX_WITH_NEW_IO_CODE
     188    rc = RTFileWriteAt(pImage->File, off, pcvBuf, cbWrite, pcbWritten);
     189#else
     190    if (pImage->pvStorage)
     191        rc = pImage->pInterfaceAsyncIOCallbacks->pfnWriteSync(pImage->pInterfaceAsyncIO->pvUser,
     192                                                              pImage->pvStorage,
     193                                                              off, cbWrite, pcvBuf,
     194                                                              pcbWritten);
     195#endif
     196
     197    return rc;
     198}
     199
     200static int vdiFileReadSync(PVDIIMAGEDESC pImage, uint64_t off, void *pvBuf, size_t cbRead, size_t *pcbRead)
     201{
     202    int rc = VINF_SUCCESS;
     203
     204#ifndef VBOX_WITH_NEW_IO_CODE
     205    rc = RTFileReadAt(pImage->File, off, pvBuf, cbRead, pcbRead);
     206#else
     207    if (pImage->pvStorage)
     208        rc = pImage->pInterfaceAsyncIOCallbacks->pfnReadSync(pImage->pInterfaceAsyncIO->pvUser,
     209                                                             pImage->pvStorage,
     210                                                             off, cbRead, pvBuf,
     211                                                             pcbRead);
     212#endif
     213
     214    return rc;
     215}
     216
     217static bool vdiFileOpened(PVDIIMAGEDESC pImage)
     218{
     219#ifndef VBOX_WITH_NEW_IO_CODE
     220    return pImage->File != NIL_RTFILE;
     221#else
     222    return pImage->pvStorage != NULL;
     223#endif
     224}
     225
     226
    84227/**
    85228 * internal: return power of 2 or 0 if num error.
     
    415558
    416559    /* Create image file. */
    417     rc = RTFileOpen(&File, pImage->pszFilename,
    418                     RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_ALL);
     560    rc = vdiFileOpen(pImage, false /* fReadonly */, true /* fCreate */);
    419561    if (RT_FAILURE(rc))
    420562    {
     
    422564        goto out;
    423565    }
    424     pImage->File = File;
    425566
    426567    cbTotal =   pImage->offStartData
     
    446587         * effective than expanding file by write operations.
    447588         */
    448         rc = RTFileSetSize(File, cbTotal);
     589        rc = vdiFileSetSize(pImage, cbTotal);
    449590    }
    450591    else
    451592    {
    452593        /* Set file size to hold header and blocks array. */
    453         rc = RTFileSetSize(pImage->File, pImage->offStartData);
     594        rc = vdiFileSetSize(pImage, pImage->offStartData);
    454595    }
    455596    if (RT_FAILURE(rc))
     
    466607
    467608    /* Write pre-header. */
    468     rc = RTFileWriteAt(File, 0, &pImage->PreHeader, sizeof(pImage->PreHeader), NULL);
     609    rc = vdiFileWriteSync(pImage, 0, &pImage->PreHeader, sizeof(pImage->PreHeader), NULL);
    469610    if (RT_FAILURE(rc))
    470611    {
     
    474615
    475616    /* Write header. */
    476     rc = RTFileWriteAt(File, sizeof(pImage->PreHeader), &pImage->Header.u.v1plus, sizeof(pImage->Header.u.v1plus), NULL);
     617    rc = vdiFileWriteSync(pImage, sizeof(pImage->PreHeader), &pImage->Header.u.v1plus, sizeof(pImage->Header.u.v1plus), NULL);
    477618    if (RT_FAILURE(rc))
    478619    {
     
    481622    }
    482623
    483     rc = RTFileWriteAt(File, pImage->offStartBlocks,
    484                        pImage->paBlocks,
    485                        getImageBlocks(&pImage->Header) * sizeof(VDIIMAGEBLOCKPOINTER),
    486                        NULL);
     624    rc = vdiFileWriteSync(pImage, pImage->offStartBlocks,
     625                          pImage->paBlocks,
     626                          getImageBlocks(&pImage->Header) * sizeof(VDIIMAGEBLOCKPOINTER),
     627                          NULL);
    487628    if (RT_FAILURE(rc))
    488629    {
     
    516657            unsigned cbChunk = (unsigned)RT_MIN(cbFill, cbBuf);
    517658
    518             rc = RTFileWriteAt(File, pImage->offStartData + uOff,
    519                                pvBuf, cbChunk, NULL);
     659            rc = vdiFileWriteSync(pImage, pImage->offStartData + uOff,
     660                                  pvBuf, cbChunk, NULL);
    520661            if (RT_FAILURE(rc))
    521662            {
     
    554695{
    555696    int rc;
    556     RTFILE File;
    557697
    558698    if (uOpenFlags & VD_OPEN_FLAGS_ASYNC_IO)
     
    565705        pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError);
    566706
     707#ifdef VBOX_WITH_NEW_IO_CODE
     708    /* Try to get async I/O interface. */
     709    pImage->pInterfaceAsyncIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ASYNCIO);
     710    AssertPtr(pImage->pInterfaceAsyncIO);
     711    pImage->pInterfaceAsyncIOCallbacks = VDGetInterfaceAsyncIO(pImage->pInterfaceAsyncIO);
     712    AssertPtr(pImage->pInterfaceAsyncIOCallbacks);
     713#endif
     714
    567715    /*
    568716     * Open the image.
    569717     */
    570     rc = RTFileOpen(&File, pImage->pszFilename,
    571                     uOpenFlags & VD_OPEN_FLAGS_READONLY
    572                      ? RTFILE_O_READ      | RTFILE_O_OPEN | RTFILE_O_DENY_NONE
    573                      : RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
     718    rc = vdiFileOpen(pImage, !!(uOpenFlags & VD_OPEN_FLAGS_READONLY), false /* fCreate */);
    574719    if (RT_FAILURE(rc))
    575720    {
     
    578723        goto out;
    579724    }
    580     pImage->File = File;
    581725
    582726    /* Read pre-header. */
    583     rc = RTFileReadAt(File, 0, &pImage->PreHeader, sizeof(pImage->PreHeader),
    584                       NULL);
     727    rc = vdiFileReadSync(pImage, 0, &pImage->PreHeader, sizeof(pImage->PreHeader),
     728                         NULL);
    585729    if (RT_FAILURE(rc))
    586730    {
     
    600744    {
    601745        case 0:
    602             rc = RTFileReadAt(File, sizeof(pImage->PreHeader),
    603                               &pImage->Header.u.v0, sizeof(pImage->Header.u.v0),
    604                               NULL);
     746            rc = vdiFileReadSync(pImage, sizeof(pImage->PreHeader),
     747                                 &pImage->Header.u.v0, sizeof(pImage->Header.u.v0),
     748                                 NULL);
    605749            if (RT_FAILURE(rc))
    606750            {
     
    610754            break;
    611755        case 1:
    612             rc = RTFileReadAt(File, sizeof(pImage->PreHeader),
    613                               &pImage->Header.u.v1, sizeof(pImage->Header.u.v1),
    614                               NULL);
     756            rc = vdiFileReadSync(pImage, sizeof(pImage->PreHeader),
     757                                 &pImage->Header.u.v1, sizeof(pImage->Header.u.v1),
     758                                 NULL);
    615759            if (RT_FAILURE(rc))
    616760            {
     
    635779            {
    636780                /* Read the actual VDI 1.1+ header completely. */
    637                 rc = RTFileReadAt(File, sizeof(pImage->PreHeader), &pImage->Header.u.v1plus, sizeof(pImage->Header.u.v1plus), NULL);
     781                rc = vdiFileReadSync(pImage, sizeof(pImage->PreHeader), &pImage->Header.u.v1plus, sizeof(pImage->Header.u.v1plus), NULL);
    638782                if (RT_FAILURE(rc))
    639783                {
     
    667811
    668812    /* Read blocks array. */
    669     rc = RTFileReadAt(pImage->File, pImage->offStartBlocks, pImage->paBlocks,
    670                       getImageBlocks(&pImage->Header) * sizeof(VDIIMAGEBLOCKPOINTER),
    671                       NULL);
     813    rc = vdiFileReadSync(pImage, pImage->offStartBlocks, pImage->paBlocks,
     814                         getImageBlocks(&pImage->Header) * sizeof(VDIIMAGEBLOCKPOINTER),
     815                         NULL);
    672816
    673817out:
     
    686830    {
    687831        case 0:
    688             rc = RTFileWriteAt(pImage->File, sizeof(VDIPREHEADER), &pImage->Header.u.v0, sizeof(pImage->Header.u.v0), NULL);
     832            rc = vdiFileWriteSync(pImage, sizeof(VDIPREHEADER), &pImage->Header.u.v0, sizeof(pImage->Header.u.v0), NULL);
    689833            break;
    690834        case 1:
    691835            if (pImage->Header.u.v1plus.cbHeader < sizeof(pImage->Header.u.v1plus))
    692                 rc = RTFileWriteAt(pImage->File, sizeof(VDIPREHEADER), &pImage->Header.u.v1, sizeof(pImage->Header.u.v1), NULL);
     836                rc = vdiFileWriteSync(pImage, sizeof(VDIPREHEADER), &pImage->Header.u.v1, sizeof(pImage->Header.u.v1), NULL);
    693837            else
    694                 rc = RTFileWriteAt(pImage->File, sizeof(VDIPREHEADER), &pImage->Header.u.v1plus, sizeof(pImage->Header.u.v1plus), NULL);
     838                rc = vdiFileWriteSync(pImage, sizeof(VDIPREHEADER), &pImage->Header.u.v1plus, sizeof(pImage->Header.u.v1plus), NULL);
    695839            break;
    696840        default:
     
    712856    {
    713857        /* write only one block pointer. */
    714         rc = RTFileWriteAt(pImage->File,
    715                            pImage->offStartBlocks + uBlock * sizeof(VDIIMAGEBLOCKPOINTER),
    716                            &pImage->paBlocks[uBlock],
    717                            sizeof(VDIIMAGEBLOCKPOINTER),
    718                            NULL);
     858        rc = vdiFileWriteSync(pImage,
     859                              pImage->offStartBlocks + uBlock * sizeof(VDIIMAGEBLOCKPOINTER),
     860                              &pImage->paBlocks[uBlock],
     861                              sizeof(VDIIMAGEBLOCKPOINTER),
     862                              NULL);
    719863        AssertMsgRC(rc, ("vdiUpdateBlockInfo failed to update block=%u, filename=\"%s\", rc=%Rrc\n",
    720864                         uBlock, pImage->pszFilename, rc));
     
    734878        AssertMsgRC(rc, ("vdiUpdateHeader() failed, filename=\"%s\", rc=%Rrc\n",
    735879                         pImage->pszFilename, rc));
    736         RTFileFlush(pImage->File);
     880        vdiFileFlushSync(pImage);
    737881    }
    738882}
     
    746890    AssertPtr(pImage);
    747891
    748     if (pImage->File != NIL_RTFILE)
     892    if (vdiFileOpened(pImage))
    749893    {
    750894        vdiFlushImage(pImage);
    751         RTFileClose(pImage->File);
    752         pImage->File = NIL_RTFILE;
     895        vdiFileClose(pImage);
    753896    }
    754897    if (pImage->paBlocks)
     
    783926    }
    784927    pImage->pszFilename = pszFilename;
     928#ifndef VBOX_WITH_NEW_IO_CODE
    785929    pImage->File = NIL_RTFILE;
     930#else
     931    pImage->pvStorage = NULL;
     932#endif
    786933    pImage->paBlocks = NULL;
    787934    pImage->pVDIfsDisk = NULL;
     
    827974    }
    828975    pImage->pszFilename = pszFilename;
     976#ifndef VBOX_WITH_NEW_IO_CODE
    829977    pImage->File = NIL_RTFILE;
     978#else
     979    pImage->pvStorage = NULL;
     980#endif
    830981    pImage->paBlocks = NULL;
    831982    pImage->pVDIfsDisk = pVDIfsDisk;
     
    9011052    }
    9021053    pImage->pszFilename = pszFilename;
     1054#ifndef VBOX_WITH_NEW_IO_CODE
    9031055    pImage->File = NIL_RTFILE;
     1056#else
     1057    pImage->pvStorage = NULL;
     1058#endif
    9041059    pImage->paBlocks = NULL;
    9051060    pImage->pVDIfsDisk = pVDIfsDisk;
     
    10351190        uint64_t u64Offset = (uint64_t)pImage->paBlocks[uBlock] * pImage->cbTotalBlockData
    10361191                           + (pImage->offStartData + pImage->offStartBlockData + offRead);
    1037         rc = RTFileReadAt(pImage->File, u64Offset, pvBuf, cbToRead, NULL);
     1192        rc = vdiFileReadSync(pImage, u64Offset, pvBuf, cbToRead, NULL);
    10381193    }
    10391194
     
    11151270                uint64_t u64Offset = (uint64_t)cBlocksAllocated * pImage->cbTotalBlockData
    11161271                                   + (pImage->offStartData + pImage->offStartBlockData);
    1117                 rc = RTFileWriteAt(pImage->File, u64Offset, pvBuf, cbToWrite, NULL);
     1272                rc = vdiFileWriteSync(pImage, u64Offset, pvBuf, cbToWrite, NULL);
    11181273                if (RT_FAILURE(rc))
    11191274                    goto out;
     
    11421297            uint64_t u64Offset = (uint64_t)pImage->paBlocks[uBlock] * pImage->cbTotalBlockData
    11431298                               + (pImage->offStartData + pImage->offStartBlockData + offWrite);
    1144             rc = RTFileWriteAt(pImage->File, u64Offset, pvBuf, cbToWrite, NULL);
     1299            rc = vdiFileWriteSync(pImage, u64Offset, pvBuf, cbToWrite, NULL);
    11451300        }
    11461301    } while (0);
     
    12161371    {
    12171372        uint64_t cbFile;
    1218         if (pImage->File != NIL_RTFILE)
    1219         {
    1220             int rc = RTFileGetSize(pImage->File, &cbFile);
     1373        if (vdiFileOpened(pImage))
     1374        {
     1375            int rc = vdiFileGetSize(pImage, &cbFile);
    12211376            if (RT_SUCCESS(rc))
    12221377                cb += cbFile;
     
    17211876    PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData;
    17221877
     1878#ifndef VBOX_WITH_NEW_IO_CODE
    17231879    pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Dumping VDI image \"%s\" mode=%s uOpenFlags=%X File=%08X\n",
    17241880                pImage->pszFilename,
     
    17261882                pImage->uOpenFlags,
    17271883                pImage->File);
     1884#else
     1885    pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Dumping VDI image \"%s\" mode=%s uOpenFlags=%X File=%#p\n",
     1886                pImage->pszFilename,
     1887                (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) ? "r/o" : "r/w",
     1888                pImage->uOpenFlags,
     1889                pImage->pvStorage);
     1890#endif
    17281891    pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: Version=%08X Type=%X Flags=%X Size=%llu\n",
    17291892                pImage->PreHeader.u32Version,
     
    18892052
    18902053        uint64_t cbFile;
    1891         rc = RTFileGetSize(pImage->File, &cbFile);
     2054        rc = vdiFileGetSize(pImage, &cbFile);
    18922055        AssertRCBreak(rc);
    18932056        unsigned cBlocksAllocated = (unsigned)((cbFile - pImage->offStartData - pImage->offStartBlockData) >> pImage->uShiftOffset2Index);
     
    19522115                uint64_t u64Offset = (uint64_t)ptrBlock * pImage->cbTotalBlockData
    19532116                                   + (pImage->offStartData + pImage->offStartBlockData);
    1954                 rc = RTFileReadAt(pImage->File, u64Offset, pvTmp, cbBlock, NULL);
     2117                rc = vdiFileReadSync(pImage, u64Offset, pvTmp, cbBlock, NULL);
    19552118                if (RT_FAILURE(rc))
    19562119                    break;
     
    20152178                uint64_t u64Offset = (uint64_t)uBlockUsedPos * pImage->cbTotalBlockData
    20162179                                   + (pImage->offStartData + pImage->offStartBlockData);
    2017                 rc = RTFileReadAt(pImage->File, u64Offset, pvTmp, cbBlock, NULL);
     2180                rc = vdiFileReadSync(pImage, u64Offset, pvTmp, cbBlock, NULL);
    20182181                u64Offset = (uint64_t)i * pImage->cbTotalBlockData
    20192182                          + (pImage->offStartData + pImage->offStartBlockData);
    2020                 rc = RTFileWriteAt(pImage->File, u64Offset, pvTmp, cbBlock, NULL);
     2183                rc = vdiFileWriteSync(pImage, u64Offset, pvTmp, cbBlock, NULL);
    20212184                pImage->paBlocks[uBlockData] = i;
    20222185                setImageBlocksAllocated(&pImage->Header, cBlocksAllocated - cBlocksMoved);
     
    20462209
    20472210        /* Truncate the image to the proper size to finish compacting. */
    2048         rc = RTFileSetSize(pImage->File,
     2211        rc = vdiFileSetSize(pImage,
    20492212                           (uint64_t)uBlockUsedPos * pImage->cbTotalBlockData
    20502213                           + (pImage->offStartData + pImage->offStartBlockData));
  • trunk/src/VBox/Devices/Storage/VHDHDDCore.cpp

    r21008 r22966  
    130130    /** Base image name. */
    131131    const char      *pszFilename;
     132#ifndef VBOX_WITH_NEW_IO_CODE
    132133    /** Descriptor file if applicable. */
    133134    RTFILE          File;
     135#else
     136    /** Opaque storage handle. */
     137    void           *pvStorage;
     138#endif
    134139
    135140    /** Pointer to the per-disk VD interface list. */
     
    139144    /** Error interface callback table. */
    140145    PVDINTERFACEERROR pInterfaceErrorCallbacks;
     146#ifdef VBOX_WITH_NEW_IO_CODE
     147    /** Async I/O interface. */
     148    PVDINTERFACE        pInterfaceAsyncIO;
     149    /** Async I/O interface callbacks. */
     150    PVDINTERFACEASYNCIO pInterfaceAsyncIOCallbacks;
     151#endif
    141152
    142153    /** Open flags passed by VBoxHD layer. */
     
    208219static int vhdLoadDynamicDisk(PVHDIMAGE pImage, uint64_t uDynamicDiskHeaderOffset);
    209220
     221static int vhdFileOpen(PVHDIMAGE pImage, bool fReadonly, bool fCreate)
     222{
     223    int rc = VINF_SUCCESS;
     224
     225    AssertMsg(!(fReadonly && fCreate), ("Image can't be opened readonly while being created\n"));
     226
     227#ifndef VBOX_WITH_NEW_IO_CODE
     228    unsigned uFileFlags = fReadonly ? RTFILE_O_READ      | RTFILE_O_DENY_NONE
     229                                    : RTFILE_O_READWRITE | RTFILE_O_DENY_WRITE;
     230
     231    if (fCreate)
     232        uFileFlags |= RTFILE_O_CREATE;
     233    else
     234        uFileFlags |= RTFILE_O_OPEN;
     235
     236    rc = RTFileOpen(&pImage->File, pImage->pszFilename, uFileFlags);
     237#else
     238
     239    unsigned uOpenFlags = fReadonly ? VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY : 0;
     240
     241    if (fCreate)
     242        uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE;
     243
     244    rc = pImage->pInterfaceAsyncIOCallbacks->pfnOpen(pImage->pInterfaceAsyncIO->pvUser,
     245                                                     pImage->pszFilename,
     246                                                     uOpenFlags,
     247                                                     NULL, &pImage->pvStorage);
     248#endif
     249
     250    return rc;
     251}
     252
     253static int vhdFileClose(PVHDIMAGE pImage)
     254{
     255    int rc = VINF_SUCCESS;
     256
     257#ifndef VBOX_WITH_NEW_IO_CODE
     258    if (pImage->File != NIL_RTFILE)
     259        rc = RTFileClose(pImage->File);
     260
     261    pImage->File = NIL_RTFILE;
     262#else
     263    if (pImage->pvStorage)
     264        rc = pImage->pInterfaceAsyncIOCallbacks->pfnClose(pImage->pInterfaceAsyncIO->pvUser,
     265                                                          pImage->pvStorage);
     266
     267    pImage->pvStorage = NULL;
     268#endif
     269
     270    return rc;
     271}
     272
     273static int vhdFileFlushSync(PVHDIMAGE pImage)
     274{
     275    int rc = VINF_SUCCESS;
     276
     277#ifndef VBOX_WITH_NEW_IO_CODE
     278    rc = RTFileFlush(pImage->File);
     279#else
     280    if (pImage->pvStorage)
     281        rc = pImage->pInterfaceAsyncIOCallbacks->pfnFlushSync(pImage->pInterfaceAsyncIO->pvUser,
     282                                                              pImage->pvStorage);
     283#endif
     284
     285    return rc;
     286}
     287
     288static int vhdFileGetSize(PVHDIMAGE pImage, uint64_t *pcbSize)
     289{
     290    int rc = VINF_SUCCESS;
     291
     292#ifndef VBOX_WITH_NEW_IO_CODE
     293    rc = RTFileGetSize(pImage->File, pcbSize);
     294#else
     295    if (pImage->pvStorage)
     296        rc = pImage->pInterfaceAsyncIOCallbacks->pfnGetSize(pImage->pInterfaceAsyncIO->pvUser,
     297                                                            pImage->pvStorage,
     298                                                            pcbSize);
     299#endif
     300
     301    return rc;
     302
     303}
     304
     305static int vhdFileSetSize(PVHDIMAGE pImage, uint64_t cbSize)
     306{
     307    int rc = VINF_SUCCESS;
     308
     309#ifndef VBOX_WITH_NEW_IO_CODE
     310    rc = RTFileSetSize(pImage->File, cbSize);
     311#else
     312    if (pImage->pvStorage)
     313        rc = pImage->pInterfaceAsyncIOCallbacks->pfnSetSize(pImage->pInterfaceAsyncIO->pvUser,
     314                                                            pImage->pvStorage,
     315                                                            cbSize);
     316#endif
     317
     318    return rc;
     319}
     320
     321
     322static int vhdFileWriteSync(PVHDIMAGE pImage, uint64_t off, const void *pcvBuf, size_t cbWrite, size_t *pcbWritten)
     323{
     324    int rc = VINF_SUCCESS;
     325
     326#ifndef VBOX_WITH_NEW_IO_CODE
     327    rc = RTFileWriteAt(pImage->File, off, pcvBuf, cbWrite, pcbWritten);
     328#else
     329    if (pImage->pvStorage)
     330        rc = pImage->pInterfaceAsyncIOCallbacks->pfnWriteSync(pImage->pInterfaceAsyncIO->pvUser,
     331                                                              pImage->pvStorage,
     332                                                              off, cbWrite, pcvBuf,
     333                                                              pcbWritten);
     334#endif
     335
     336    return rc;
     337}
     338
     339static int vhdFileReadSync(PVHDIMAGE pImage, uint64_t off, void *pvBuf, size_t cbRead, size_t *pcbRead)
     340{
     341    int rc = VINF_SUCCESS;
     342
     343#ifndef VBOX_WITH_NEW_IO_CODE
     344    rc = RTFileReadAt(pImage->File, off, pvBuf, cbRead, pcbRead);
     345#else
     346    if (pImage->pvStorage)
     347        rc = pImage->pInterfaceAsyncIOCallbacks->pfnReadSync(pImage->pInterfaceAsyncIO->pvUser,
     348                                                             pImage->pvStorage,
     349                                                             off, cbRead, pvBuf,
     350                                                             pcbRead);
     351#endif
     352
     353    return rc;
     354}
     355
     356static bool vhdFileOpened(PVHDIMAGE pImage)
     357{
     358#ifndef VBOX_WITH_NEW_IO_CODE
     359    return pImage->File != NIL_RTFILE;
     360#else
     361    return pImage->pvStorage != NULL;
     362#endif
     363}
     364
    210365/* 946684800 is a number of seconds between 1/1/1970 and 1/1/2000 */
    211366#define VHD_TO_UNIX_EPOCH_SECONDS UINT64_C(946684800)
     
    338493            goto out;
    339494    }
    340     rc = RTFileWriteAt(pImage->File, RT_BE2H_U64(pLocator->u64DataOffset), pvBuf,
    341                        RT_BE2H_U32(pLocator->u32DataSpace) * VHD_SECTOR_SIZE, NULL);
     495    rc = vhdFileWriteSync(pImage, RT_BE2H_U64(pLocator->u64DataOffset), pvBuf,
     496                          RT_BE2H_U32(pLocator->u32DataSpace) * VHD_SECTOR_SIZE, NULL);
    342497
    343498out:
     
    358513        return VERR_VD_NOT_OPENED;
    359514
    360     rc = RTFileReadAt(pImage->File, pImage->u64DataOffset, &ddh, sizeof(ddh), NULL);
     515    rc = vhdFileReadSync(pImage, pImage->u64DataOffset, &ddh, sizeof(ddh), NULL);
    361516    if (RT_FAILURE(rc))
    362517        return rc;
     
    403558    ddh.Checksum = 0;
    404559    ddh.Checksum = RT_H2BE_U32(vhdChecksum(&ddh, sizeof(ddh)));
    405     rc = RTFileWriteAt(pImage->File, pImage->u64DataOffset, &ddh, sizeof(ddh), NULL);
     560    rc = vhdFileWriteSync(pImage, pImage->u64DataOffset, &ddh, sizeof(ddh), NULL);
    406561    if (RT_FAILURE(rc))
    407562        return rc;
    408563
    409564    /* Update the VHD footer copy. */
    410     rc = RTFileWriteAt(pImage->File, 0, &pImage->vhdFooterCopy, sizeof(VHDFooter), NULL);
     565    rc = vhdFileWriteSync(pImage, 0, &pImage->vhdFooterCopy, sizeof(VHDFooter), NULL);
    411566
    412567out:
     
    417572static int vhdOpenImage(PVHDIMAGE pImage, unsigned uOpenFlags)
    418573{
    419     RTFILE File;
    420574    uint64_t FileSize;
    421575    VHDFooter vhdFooter;
     
    430584        pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError);
    431585
     586#ifdef VBOX_WITH_NEW_IO_CODE
     587    /* Try to get async I/O interface. */
     588    pImage->pInterfaceAsyncIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ASYNCIO);
     589    AssertPtr(pImage->pInterfaceAsyncIO);
     590    pImage->pInterfaceAsyncIOCallbacks = VDGetInterfaceAsyncIO(pImage->pInterfaceAsyncIO);
     591    AssertPtr(pImage->pInterfaceAsyncIOCallbacks);
     592#endif
     593
    432594    /*
    433595     * Open the image.
    434596     */
    435     int rc = RTFileOpen(&File, pImage->pszFilename, uOpenFlags & VD_OPEN_FLAGS_READONLY
    436                     ? RTFILE_O_READ      | RTFILE_O_OPEN | RTFILE_O_DENY_NONE
    437                     : RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
     597    int rc = vhdFileOpen(pImage, !!(uOpenFlags & VD_OPEN_FLAGS_READONLY), false);
    438598    if (RT_FAILURE(rc))
    439599    {
     
    442602        return rc;
    443603    }
    444     pImage->File = File;
    445 
    446     rc = RTFileGetSize(File, &FileSize);
     604
     605    rc = vhdFileGetSize(pImage, &FileSize);
    447606    pImage->FileSize = FileSize;
    448607    pImage->uCurrentEndOfFile = FileSize - sizeof(VHDFooter);
    449608
    450     rc = RTFileReadAt(File, pImage->uCurrentEndOfFile, &vhdFooter, sizeof(VHDFooter), NULL);
     609    rc = vhdFileReadSync(pImage, pImage->uCurrentEndOfFile, &vhdFooter, sizeof(VHDFooter), NULL);
    451610    if (memcmp(vhdFooter.Cookie, VHD_FOOTER_COOKIE, VHD_FOOTER_COOKIE_SIZE) != 0)
    452611        return VERR_VD_VHD_INVALID_HEADER;
     
    524683    }
    525684    pImage->pszFilename = pszFilename;
     685#ifndef VBOX_WITH_NEW_IO_CODE
    526686    pImage->File = NIL_RTFILE;
     687#else
     688    pImage->pvStorage != NULL;
     689#endif
    527690    pImage->pVDIfsDisk = pVDIfsDisk;
    528691
     
    546709     * Read the dynamic disk header.
    547710     */
    548     rc = RTFileReadAt(pImage->File, uDynamicDiskHeaderOffset, &vhdDynamicDiskHeader, sizeof(VHDDynamicDiskHeader), NULL);
     711    rc = vhdFileReadSync(pImage, uDynamicDiskHeaderOffset, &vhdDynamicDiskHeader, sizeof(VHDDynamicDiskHeader), NULL);
    549712    if (memcmp(vhdDynamicDiskHeader.Cookie, VHD_DYNAMIC_DISK_HEADER_COOKIE, VHD_DYNAMIC_DISK_HEADER_COOKIE_SIZE) != 0)
    550713        return VERR_INVALID_PARAMETER;
     
    581744    LogFlowFunc(("uBlockAllocationTableOffset=%llu\n", uBlockAllocationTableOffset));
    582745    pImage->uBlockAllocationTableOffset = uBlockAllocationTableOffset;
    583     rc = RTFileReadAt(pImage->File, uBlockAllocationTableOffset, pBlockAllocationTable, pImage->cBlockAllocationTableEntries * sizeof(uint32_t), NULL);
     746    rc = vhdFileReadSync(pImage, uBlockAllocationTableOffset, pBlockAllocationTable, pImage->cBlockAllocationTableEntries * sizeof(uint32_t), NULL);
    584747    pImage->uDataBlockStart = uBlockAllocationTableOffset + pImage->cBlockAllocationTableEntries * sizeof(uint32_t);
    585748    LogFlowFunc(("uDataBlockStart=%llu\n", pImage->uDataBlockStart));
     
    793956    if (RT_FAILURE(rc))
    794957        goto out;
    795     RTFileClose(pImage->File);
     958    vhdFileClose(pImage);
    796959    pImage->uOpenFlags = uOpenFlags;
    797     rc = RTFileOpen(&pImage->File, pImage->pszFilename, uOpenFlags & VD_OPEN_FLAGS_READONLY
    798             ? RTFILE_O_READ      | RTFILE_O_OPEN | RTFILE_O_DENY_NONE
    799             : RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
     960    rc = vhdFileOpen(pImage, !!(uOpenFlags & VD_OPEN_FLAGS_READONLY), false);
    800961
    801962out:
     
    822983    /* Close the file. vhdFreeImage would additionally free pImage. */
    823984    vhdFlush(pImage);
    824     RTFileClose(pImage->File);
     985    vhdFileClose(pImage);
    825986
    826987    /* Rename the file. */
     
    8781039    {
    8791040        vhdFlush(pImage);
    880         RTFileClose(pImage->File);
     1041        vhdFileClose(pImage);
    8811042        vhdFreeImageMemory(pImage);
    8821043    }
     
    8981059        {
    8991060            /* No point in updating the file that is deleted anyway. */
    900             RTFileClose(pImage->File);
     1061            vhdFileClose(pImage);
    9011062            RTFileDelete(pImage->pszFilename);
    9021063            vhdFreeImageMemory(pImage);
     
    9941155
    9951156        /* Read in the block's bitmap. */
    996         rc = RTFileReadAt(pImage->File,
    997                           ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE,
    998                           pImage->pu8Bitmap, pImage->cbDataBlockBitmap, NULL);
     1157        rc = vhdFileReadSync(pImage,
     1158                             ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE,
     1159                             pImage->pu8Bitmap, pImage->cbDataBlockBitmap, NULL);
    9991160        if (RT_SUCCESS(rc))
    10001161        {
     
    10211182
    10221183                LogFlowFunc(("uVhdOffset=%llu cbRead=%u\n", uVhdOffset, cbRead));
    1023                 rc = RTFileReadAt(pImage->File, uVhdOffset, pvBuf, cbRead, NULL);
     1184                rc = vhdFileReadSync(pImage, uVhdOffset, pvBuf, cbRead, NULL);
    10241185            }
    10251186            else
     
    10531214    else
    10541215    {
    1055         rc = RTFileReadAt(pImage->File, uOffset, pvBuf, cbRead, NULL);
     1216        rc = vhdFileReadSync(pImage, uOffset, pvBuf, cbRead, NULL);
    10561217    }
    10571218
     
    11241285             * Write the new block at the current end of the file.
    11251286             */
    1126             rc = RTFileWriteAt(pImage->File, pImage->uCurrentEndOfFile, pNewBlock, cbNewBlock, NULL);
     1287            rc = vhdFileWriteSync(pImage, pImage->uCurrentEndOfFile, pNewBlock, cbNewBlock, NULL);
    11271288
    11281289            /*
     
    11401301
    11411302        /* Write data. */
    1142         RTFileWriteAt(pImage->File, uVhdOffset, pvBuf, cbToWrite, NULL);
     1303        vhdFileWriteSync(pImage, uVhdOffset, pvBuf, cbToWrite, NULL);
    11431304
    11441305        /* Read in the block's bitmap. */
    1145         rc = RTFileReadAt(pImage->File,
     1306        rc = vhdFileReadSync(pImage,
    11461307            ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE,
    11471308            pImage->pu8Bitmap, pImage->cbDataBlockBitmap, NULL);
     
    11561317
    11571318            /* Write the bitmap back. */
    1158             rc = RTFileWriteAt(pImage->File,
     1319            rc = vhdFileWriteSync(pImage,
    11591320                ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE,
    11601321                pImage->pu8Bitmap, pImage->cbDataBlockBitmap, NULL);
     
    11631324    else
    11641325    {
    1165         rc = RTFileWriteAt(pImage->File, uOffset, pvBuf, cbToWrite, NULL);
     1326        rc = vhdFileWriteSync(pImage, uOffset, pvBuf, cbToWrite, NULL);
    11661327    }
    11671328
     
    12041365         * Write the block allocation table after the copy of the disk footer and the dynamic disk header.
    12051366         */
    1206         RTFileWriteAt(pImage->File, pImage->uBlockAllocationTableOffset, pBlockAllocationTableToWrite, cbBlockAllocationTableToWrite, NULL);
    1207         RTFileWriteAt(pImage->File, pImage->uCurrentEndOfFile, &pImage->vhdFooterCopy, sizeof(VHDFooter), NULL);
     1367        vhdFileWriteSync(pImage, pImage->uBlockAllocationTableOffset, pBlockAllocationTableToWrite, cbBlockAllocationTableToWrite, NULL);
     1368        vhdFileWriteSync(pImage, pImage->uCurrentEndOfFile, &pImage->vhdFooterCopy, sizeof(VHDFooter), NULL);
    12081369        if (pImage->fDynHdrNeedsUpdate)
    12091370            vhdDynamicHeaderUpdate(pImage);
     
    12111372    }
    12121373
    1213     int rc = RTFileFlush(pImage->File);
     1374    int rc = vhdFileFlushSync(pImage);
    12141375
    12151376    return rc;
     
    12401401    {
    12411402        uint64_t cb;
    1242         int rc = RTFileGetSize(pImage->File, &cb);
     1403        int rc = vhdFileGetSize(pImage, &cb);
    12431404        if (RT_SUCCESS(rc))
    12441405            return cb;
     
    13911552    AssertPtr(pImage);
    13921553
    1393     if (pImage && pImage->File != NIL_RTFILE)
     1554    if (pImage && vhdFileOpened(pImage))
    13941555    {
    13951556        if (!(pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED))
     
    15461707    VHDDynamicDiskHeader DynamicDiskHeader;
    15471708    uint32_t u32BlockAllocationTableSectors;
     1709    void    *pvTmp = NULL;
    15481710
    15491711    memset(&DynamicDiskHeader, 0, sizeof(DynamicDiskHeader));
     
    15741736        pImage->uBlockAllocationTableOffset + u32BlockAllocationTableSectors * VHD_SECTOR_SIZE);
    15751737
    1576     rc = RTFileSetSize(pImage->File, pImage->uCurrentEndOfFile + sizeof(VHDFooter));
     1738    /* Set dynamic image size. */
     1739    pvTmp = RTMemTmpAllocZ(pImage->uCurrentEndOfFile + sizeof(VHDFooter));
     1740    if (!pvTmp)
     1741        return vhdError(pImage, VERR_NO_MEMORY, RT_SRC_POS, N_("VHD: cannot set the file size for '%s'"), pImage->pszFilename);
     1742
     1743    rc = vhdFileWriteSync(pImage, 0, pvTmp, pImage->uCurrentEndOfFile + sizeof(VHDFooter), NULL);
    15771744    if (RT_FAILURE(rc))
     1745    {
     1746        RTMemTmpFree(pvTmp);
    15781747        return vhdError(pImage, rc, RT_SRC_POS, N_("VHD: cannot set the file size for '%s'"), pImage->pszFilename);
     1748    }
     1749
     1750    RTMemTmpFree(pvTmp);
    15791751
    15801752    /* Initialize and write the dynamic disk header. */
     
    15891761    DynamicDiskHeader.Checksum = RT_H2BE_U32(vhdChecksum(&DynamicDiskHeader, sizeof(DynamicDiskHeader)));
    15901762
    1591     rc = RTFileWriteAt(pImage->File, sizeof(VHDFooter), &DynamicDiskHeader, sizeof(DynamicDiskHeader), NULL);
     1763    rc = vhdFileWriteSync(pImage, sizeof(VHDFooter), &DynamicDiskHeader, sizeof(DynamicDiskHeader), NULL);
    15921764    if (RT_FAILURE(rc))
    15931765        return vhdError(pImage, rc, RT_SRC_POS, N_("VHD: cannot write dynamic disk header to image '%s'"), pImage->pszFilename);
    15941766
    15951767    /* Write BAT. */
    1596     rc = RTFileWriteAt(pImage->File, pImage->uBlockAllocationTableOffset, pImage->pBlockAllocationTable,
    1597                        pImage->cBlockAllocationTableEntries * sizeof(uint32_t), NULL);
     1768    rc = vhdFileWriteSync(pImage, pImage->uBlockAllocationTableOffset, pImage->pBlockAllocationTable,
     1769                          pImage->cBlockAllocationTableEntries * sizeof(uint32_t), NULL);
    15981770    if (RT_FAILURE(rc))
    15991771        return vhdError(pImage, rc, RT_SRC_POS, N_("VHD: cannot write BAT to image '%s'"), pImage->pszFilename);
     
    16251797        pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError);
    16261798
    1627     /* Create image file. */
    1628     rc = RTFileOpen(&File, pImage->pszFilename,
    1629                     RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_ALL);
     1799    rc = vhdFileOpen(pImage, false /* fReadonly */, true /* fCreate */);
    16301800    if (RT_FAILURE(rc))
    16311801        return vhdError(pImage, rc, RT_SRC_POS, N_("VHD: cannot create image '%s'"), pImage->pszFilename);
    1632     pImage->File = File;
     1802
    16331803
    16341804    pImage->cbSize = cbSize;
     
    16701840        /** @todo r=klaus replace this with actual data writes, see the experience
    16711841         * with VDI files on Windows, can cause long freezes when writing. */
    1672         rc = RTFileSetSize(File, pImage->uCurrentEndOfFile + sizeof(VHDFooter));
     1842        rc = vhdFileSetSize(pImage, pImage->uCurrentEndOfFile + sizeof(VHDFooter));
    16731843        if (RT_FAILURE(rc))
    16741844        {
     
    17141884
    17151885    /* Store the footer */
    1716     rc = RTFileWriteAt(File, pImage->uCurrentEndOfFile, &Footer, sizeof(Footer), NULL);
     1886    rc = vhdFileWriteSync(pImage, pImage->uCurrentEndOfFile, &Footer, sizeof(Footer), NULL);
    17171887    if (RT_FAILURE(rc))
    17181888    {
     
    17251895    {
    17261896        /* Write the copy of the footer. */
    1727         rc = RTFileWriteAt(File, 0, &Footer, sizeof(Footer), NULL);
     1897        rc = vhdFileWriteSync(pImage, 0, &Footer, sizeof(Footer), NULL);
    17281898        if (RT_FAILURE(rc))
    17291899        {
     
    17811951    }
    17821952    pImage->pszFilename = pszFilename;
     1953#ifndef VBOX_WITH_NEW_IO_CODE
    17831954    pImage->File = NIL_RTFILE;
    1784     pImage->pVDIfsDisk = NULL;
     1955#else
     1956    pImage->pvStorage = NULL;
     1957#endif
     1958    pImage->pVDIfsDisk = pVDIfsDisk;
     1959
     1960#ifdef VBOX_WITH_NEW_IO_CODE
     1961    /* Try to get async I/O interface. */
     1962    pImage->pInterfaceAsyncIO = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ASYNCIO);
     1963    AssertPtr(pImage->pInterfaceAsyncIO);
     1964    pImage->pInterfaceAsyncIOCallbacks = VDGetInterfaceAsyncIO(pImage->pInterfaceAsyncIO);
     1965    AssertPtr(pImage->pInterfaceAsyncIOCallbacks);
     1966#endif
    17851967
    17861968    rc = vhdCreateImage(pImage, cbSize, uImageFlags, pszComment,
     
    18282010        RTFSOBJINFO info;
    18292011
     2012#ifndef VBOX_WITH_NEW_IO_CODE
    18302013        rc = RTFileQueryInfo(pImage->File, &info, RTFSOBJATTRADD_NOTHING);
     2014#else
     2015        /* Interface doesn't provide such a feature. */
     2016        RTFILE File;
     2017        rc = RTFileOpen(&File, pImage->pszFilename, RTFILE_O_OPEN | RTFILE_O_READ);
     2018        if (RT_SUCCESS(rc))
     2019        {
     2020            rc = RTFileQueryInfo(File, &info, RTFSOBJATTRADD_NOTHING);
     2021            RTFileClose(File);
     2022        }
     2023#endif
     2024
    18312025        *pTimeStamp = info.ModificationTime;
    18322026    }
  • trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp

    r21806 r22966  
    582582                                                         pszFilename,
    583583                                                         pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY
    584                                                            ? true
    585                                                            : false,
     584                                                           ? VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY
     585                                                           : 0,
    586586                                                         NULL,
    587587                                                         &pVmdkFile->pStorage);
     
    700700DECLINLINE(int) vmdkFileGetSize(PVMDKFILE pVmdkFile, uint64_t *pcbSize)
    701701{
     702    PVMDKIMAGE pImage = pVmdkFile->pImage;
     703
    702704    if (pVmdkFile->fAsyncIO)
    703705    {
    704         AssertMsgFailed(("TODO\n"));
    705         return 0;
     706        return pImage->pInterfaceAsyncIOCallbacks->pfnGetSize(pImage->pInterfaceAsyncIO->pvUser,
     707                                                              pVmdkFile->pStorage,
     708                                                              pcbSize);
    706709    }
    707710    else
     
    714717DECLINLINE(int) vmdkFileSetSize(PVMDKFILE pVmdkFile, uint64_t cbSize)
    715718{
     719    PVMDKIMAGE pImage = pVmdkFile->pImage;
     720
    716721    if (pVmdkFile->fAsyncIO)
    717722    {
    718         AssertMsgFailed(("TODO\n"));
    719         return VERR_NOT_SUPPORTED;
     723        return pImage->pInterfaceAsyncIOCallbacks->pfnSetSize(pImage->pInterfaceAsyncIO->pvUser,
     724                                                              pVmdkFile->pStorage,
     725                                                              cbSize);
    720726    }
    721727    else
     
    58145820            {
    58155821                /* Check for enough room first. */
    5816                 if (RT_LIKELY(cSegments >= pImage->cSegments))
     5822                if (RT_UNLIKELY(cSegments >= pImage->cSegments))
    58175823                {
    58185824                    /* We reached maximum, resize array. Try to realloc memory first. */
     
    59425948            {
    59435949                /* Check for enough room first. */
    5944                 if (RT_LIKELY(cSegments >= pImage->cSegments))
     5950                if (RT_UNLIKELY(cSegments >= pImage->cSegments))
    59455951                {
    59465952                    /* We reached maximum, resize array. Try to realloc memory first. */
Note: See TracChangeset for help on using the changeset viewer.

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