VirtualBox

Changeset 32536 in vbox


Ignore:
Timestamp:
Sep 15, 2010 6:25:32 PM (14 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
65918
Message:

Storage/VBoxHDD: replace custom open flags with regular IPRT file open flags, introduce user-providable filesystem access interface, eliminate dependency on PGM geometry structure, change pvBuffer/cbBuffer parameter ordering to the usual conventions, eliminate the remains of the old I/O code, make more plugin methods optional to reduce redundancy, lots of cleanups

Storage/DrvVD+testcases,Main/Medium+Frontends: adapt to VBoxHDD changes, logging fixes

Storage/VDI+VMDK+DMG+Raw+VHD+Parallels+VCI: made as similar to each other as possible, added inline VFS wrappers to improve readability, full VFS support, VDI files are now 4K aligned, eliminate the remains of the old I/O code, various more or less severe bugfixes, code sort

Storage/iSCSI: support disks bigger than 2T, streamline the code to be more similar to the file-based backends, memory leak fix, error code usage like file-based backends, code sort

log+err: added new error codes/log groups and eliminated unused old ones

Location:
trunk
Files:
30 edited

Legend:

Unmodified
Added
Removed
  • trunk/Config.kmk

    r32471 r32536  
    397397if1of ($(KBUILD_TARGET), darwin freebsd linux solaris win)
    398398 VBOX_WITH_HOSTNETIF_API = 1
    399 endif
    400 # Enable the new storage I/O path.
    401 if1of ($(KBUILD_TARGET), darwin freebsd linux solaris win)
    402  VBOX_WITH_NEW_IO_CODE = 1
    403399endif
    404400## @}
  • trunk/include/VBox/VBoxHDD-CachePlugin.h

    r32370 r32536  
    7474     * @returns VBox status code.
    7575     * @param   pszFilename     Name of the image file.
    76      * @param   pVDIfsCache     Pointer to the per-cache VD interface list.
    77      */
    78     DECLR3CALLBACKMEMBER(int, pfnProbe, (const char *pszFilename, PVDINTERFACE pVDIfsCache));
     76     * @param   pVDIfsDisk      Pointer to the per-disk VD interface list.
     77     * @param   pVDIfsImage     Pointer to the per-image VD interface list.
     78     */
     79    DECLR3CALLBACKMEMBER(int, pfnProbe, (const char *pszFilename, PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage));
    7980
    8081    /**
     
    8788     * @param   pVDIfsDisk      Pointer to the per-disk VD interface list.
    8889     * @param   pVDIfsImage     Pointer to the per-image VD interface list.
    89      * @param   ppvBackendData  Opaque state data for this image.
     90     * @param   ppBackendData   Opaque state data for this image.
    9091     */
    9192    DECLR3CALLBACKMEMBER(int, pfnOpen, (const char *pszFilename, unsigned uOpenFlags,
    9293                                        PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
    93                                         void **ppvBackendData));
     94                                        void **ppBackendData));
    9495
    9596    /**
     
    109110     * @param   pVDIfsImage     Pointer to the per-image VD interface list.
    110111     * @param   pVDIfsOperation Pointer to the per-operation VD interface list.
    111      * @param   ppvBackendData  Opaque state data for this image.
     112     * @param   ppBackendData   Opaque state data for this image.
    112113     */
    113114    DECLR3CALLBACKMEMBER(int, pfnCreate, (const char *pszFilename, uint64_t cbSize,
     
    118119                                          PVDINTERFACE pVDIfsImage,
    119120                                          PVDINTERFACE pVDIfsOperation,
    120                                           void **ppvBackendData));
     121                                          void **ppBackendData));
    121122
    122123    /**
     
    124125     *
    125126     * @returns VBox status code.
    126      * @param   pvBackendData   Opaque state data for this image.
     127     * @param   pBackendData    Opaque state data for this image.
    127128     * @param   fDelete         If true, delete the image from the host disk.
    128129     */
    129     DECLR3CALLBACKMEMBER(int, pfnClose, (void *pvBackendData, bool fDelete));
     130    DECLR3CALLBACKMEMBER(int, pfnClose, (void *pBackendData, bool fDelete));
    130131
    131132    /**
     
    135136     * @returns VBox status code.
    136137     * @returns VERR_VD_BLOCK_FREE if this image contains no data for this block.
    137      * @param   pvBackendData   Opaque state data for this image.
     138     * @param   pBackendData    Opaque state data for this image.
    138139     * @param   uOffset         Offset to start reading from.
    139140     * @param   pvBuf           Where to store the read bits.
     
    141142     * @param   pcbActuallyRead Pointer to returned number of bytes read.
    142143     */
    143     DECLR3CALLBACKMEMBER(int, pfnRead, (void *pvBackendData, uint64_t uOffset, void *pvBuf,
     144    DECLR3CALLBACKMEMBER(int, pfnRead, (void *pBackendData, uint64_t uOffset, void *pvBuf,
    144145                                        size_t cbRead, size_t *pcbActuallyRead));
    145146
     
    149150     *
    150151     * @returns VBox status code.
    151      * @param   pvBackendData   Opaque state data for this image.
     152     * @param   pBackendData    Opaque state data for this image.
    152153     * @param   uOffset         Offset to start writing to.
    153154     * @param   pvBuf           Where to retrieve the written bits.
     
    156157     *                          be processed.
    157158     */
    158     DECLR3CALLBACKMEMBER(int, pfnWrite, (void *pvBackendData, uint64_t uOffset,
     159    DECLR3CALLBACKMEMBER(int, pfnWrite, (void *pBackendData, uint64_t uOffset,
    159160                                         const void *pvBuf, size_t cbWrite,
    160161                                         size_t *pcbWriteProcess));
     
    164165     *
    165166     * @returns VBox status code.
    166      * @param   pvBackendData   Opaque state data for this image.
    167      */
    168     DECLR3CALLBACKMEMBER(int, pfnFlush, (void *pvBackendData));
     167     * @param   pBackendData    Opaque state data for this image.
     168     */
     169    DECLR3CALLBACKMEMBER(int, pfnFlush, (void *pBackendData));
    169170
    170171    /**
     
    172173     *
    173174     * @returns version of cache image.
    174      * @param   pvBackendData   Opaque state data for this image.
    175      */
    176     DECLR3CALLBACKMEMBER(unsigned, pfnGetVersion, (void *pvBackendData));
     175     * @param   pBackendData    Opaque state data for this image.
     176     */
     177    DECLR3CALLBACKMEMBER(unsigned, pfnGetVersion, (void *pBackendData));
    177178
    178179    /**
     
    180181     *
    181182     * @returns size of cache image in bytes.
    182      * @param   pvBackendData   Opaque state data for this image.
    183      */
    184     DECLR3CALLBACKMEMBER(uint64_t, pfnGetSize, (void *pvBackendData));
     183     * @param   pBackendData    Opaque state data for this image.
     184     */
     185    DECLR3CALLBACKMEMBER(uint64_t, pfnGetSize, (void *pBackendData));
    185186
    186187    /**
     
    188189     *
    189190     * @returns size of cache image in bytes.
    190      * @param   pvBackendData   Opaque state data for this image.
    191      */
    192     DECLR3CALLBACKMEMBER(uint64_t, pfnGetFileSize, (void *pvBackendData));
     191     * @param   pBackendData    Opaque state data for this image.
     192     */
     193    DECLR3CALLBACKMEMBER(uint64_t, pfnGetFileSize, (void *pBackendData));
    193194
    194195    /**
     
    196197     *
    197198     * @returns image flags of cache image.
    198      * @param   pvBackendData   Opaque state data for this image.
    199      */
    200     DECLR3CALLBACKMEMBER(unsigned, pfnGetImageFlags, (void *pvBackendData));
     199     * @param   pBackendData    Opaque state data for this image.
     200     */
     201    DECLR3CALLBACKMEMBER(unsigned, pfnGetImageFlags, (void *pBackendData));
    201202
    202203    /**
     
    204205     *
    205206     * @returns open flags of cache image.
    206      * @param   pvBackendData   Opaque state data for this image.
    207      */
    208     DECLR3CALLBACKMEMBER(unsigned, pfnGetOpenFlags, (void *pvBackendData));
     207     * @param   pBackendData    Opaque state data for this image.
     208     */
     209    DECLR3CALLBACKMEMBER(unsigned, pfnGetOpenFlags, (void *pBackendData));
    209210
    210211    /**
     
    213214     *
    214215     * @returns VBox status code.
    215      * @param   pvBackendData   Opaque state data for this image.
     216     * @param   pBackendData    Opaque state data for this image.
    216217     * @param   uOpenFlags      New open flags for this image.
    217218     */
    218     DECLR3CALLBACKMEMBER(int, pfnSetOpenFlags, (void *pvBackendData, unsigned uOpenFlags));
     219    DECLR3CALLBACKMEMBER(int, pfnSetOpenFlags, (void *pBackendData, unsigned uOpenFlags));
    219220
    220221    /**
     
    222223     *
    223224     * @returns VBox status code.
    224      * @param   pvBackendData   Opaque state data for this image.
     225     * @param   pBackendData    Opaque state data for this image.
    225226     * @param   pszComment      Where to store the comment.
    226227     * @param   cbComment       Size of the comment buffer.
    227228     */
    228     DECLR3CALLBACKMEMBER(int, pfnGetComment, (void *pvBackendData, char *pszComment, size_t cbComment));
     229    DECLR3CALLBACKMEMBER(int, pfnGetComment, (void *pBackendData, char *pszComment, size_t cbComment));
    229230
    230231    /**
     
    232233     *
    233234     * @returns VBox status code.
    234      * @param   pvBackendData   Opaque state data for this image.
     235     * @param   pBackendData    Opaque state data for this image.
    235236     * @param   pszComment      Where to get the comment from. NULL resets comment.
    236237     *                          The comment is silently truncated if the image format
    237238     *                          limit is exceeded.
    238239     */
    239     DECLR3CALLBACKMEMBER(int, pfnSetComment, (void *pvBackendData, const char *pszComment));
     240    DECLR3CALLBACKMEMBER(int, pfnSetComment, (void *pBackendData, const char *pszComment));
    240241
    241242    /**
     
    243244     *
    244245     * @returns VBox status code.
    245      * @param   pvBackendData   Opaque state data for this image.
     246     * @param   pBackendData    Opaque state data for this image.
    246247     * @param   pUuid           Where to store the image UUID.
    247248     */
    248     DECLR3CALLBACKMEMBER(int, pfnGetUuid, (void *pvBackendData, PRTUUID pUuid));
     249    DECLR3CALLBACKMEMBER(int, pfnGetUuid, (void *pBackendData, PRTUUID pUuid));
    249250
    250251    /**
     
    252253     *
    253254     * @returns VBox status code.
    254      * @param   pvBackendData   Opaque state data for this image.
     255     * @param   pBackendData    Opaque state data for this image.
    255256     * @param   pUuid           Where to get the image UUID from.
    256257     */
    257     DECLR3CALLBACKMEMBER(int, pfnSetUuid, (void *pvBackendData, PCRTUUID pUuid));
     258    DECLR3CALLBACKMEMBER(int, pfnSetUuid, (void *pBackendData, PCRTUUID pUuid));
    258259
    259260    /**
     
    261262     *
    262263     * @returns VBox status code.
    263      * @param   pvBackendData   Opaque state data for this image.
     264     * @param   pBackendData    Opaque state data for this image.
    264265     * @param   pUuid           Where to store the image modification UUID.
    265266     */
    266     DECLR3CALLBACKMEMBER(int, pfnGetModificationUuid, (void *pvBackendData, PRTUUID pUuid));
     267    DECLR3CALLBACKMEMBER(int, pfnGetModificationUuid, (void *pBackendData, PRTUUID pUuid));
    267268
    268269    /**
     
    270271     *
    271272     * @returns VBox status code.
    272      * @param   pvBackendData   Opaque state data for this image.
     273     * @param   pBackendData    Opaque state data for this image.
    273274     * @param   pUuid           Where to get the image modification UUID from.
    274275     */
    275     DECLR3CALLBACKMEMBER(int, pfnSetModificationUuid, (void *pvBackendData, PCRTUUID pUuid));
     276    DECLR3CALLBACKMEMBER(int, pfnSetModificationUuid, (void *pBackendData, PCRTUUID pUuid));
    276277
    277278    /**
    278279     * Dump information about a cache image.
    279280     *
    280      * @param   pvBackendData   Opaque state data for this image.
    281      */
    282     DECLR3CALLBACKMEMBER(void, pfnDump, (void *pvBackendData));
     281     * @param   pBackendData    Opaque state data for this image.
     282     */
     283    DECLR3CALLBACKMEMBER(void, pfnDump, (void *pBackendData));
    283284
    284285    /**
     
    286287     *
    287288     * @returns VBox status code.
    288      * @param   pvBackendData   Opaque state data for this image.
     289     * @param   pBackendData    Opaque state data for this image.
    289290     * @param   uOffset         The offset of the virtual disk to read from.
    290291     * @param   cbRead          How many bytes to read.
     
    292293     * @param   pcbActuallyRead Pointer to returned number of bytes read.
    293294     */
    294     DECLR3CALLBACKMEMBER(int, pfnAsyncRead, (void *pvBackendData, uint64_t uOffset, size_t cbRead,
     295    DECLR3CALLBACKMEMBER(int, pfnAsyncRead, (void *pBackendData, uint64_t uOffset, size_t cbRead,
    295296                                             PVDIOCTX pIoCtx, size_t *pcbActuallyRead));
    296297
     
    299300     *
    300301     * @returns VBox status code.
    301      * @param   pvBackendData   Opaque state data for this image.
     302     * @param   pBackendData    Opaque state data for this image.
    302303     * @param   uOffset         The offset of the virtual disk to write to.
    303304     * @param   cbWrite         How many bytes to write.
     
    310311     *                          amount of (previously read) padding data.
    311312     */
    312     DECLR3CALLBACKMEMBER(int, pfnAsyncWrite, (void *pvBackendData, uint64_t uOffset, size_t cbWrite,
     313    DECLR3CALLBACKMEMBER(int, pfnAsyncWrite, (void *pBackendData, uint64_t uOffset, size_t cbWrite,
    313314                                              PVDIOCTX pIoCtx, size_t *pcbWriteProcess));
    314315
     
    317318     *
    318319     * @returns VBox status code.
    319      * @param   pvBackendData   Opaque state data for this image.
     320     * @param   pBackendData    Opaque state data for this image.
    320321     * @param   pIoCtx          I/O context associated with this request.
    321322     */
    322     DECLR3CALLBACKMEMBER(int, pfnAsyncFlush, (void *pvBackendData, PVDIOCTX pIoCtx));
     323    DECLR3CALLBACKMEMBER(int, pfnAsyncFlush, (void *pBackendData, PVDIOCTX pIoCtx));
    323324
    324325    /** Returns a human readable hard disk location string given a
  • trunk/include/VBox/VBoxHDD-Plugin.h

    r32370 r32536  
    2727#define __VBoxHDD_Plugin_h__
    2828
    29 #include <VBox/pdm.h>
    3029#include <VBox/VBoxHDD.h>
    3130
     
    8786     * @param   pszFilename     Name of the image file.
    8887     * @param   pVDIfsDisk      Pointer to the per-disk VD interface list.
    89      */
    90     DECLR3CALLBACKMEMBER(int, pfnCheckIfValid, (const char *pszFilename, PVDINTERFACE pVDIfsDisk));
     88     * @param   pVDIfsImage     Pointer to the per-image VD interface list.
     89     */
     90    DECLR3CALLBACKMEMBER(int, pfnCheckIfValid, (const char *pszFilename, PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage));
    9191
    9292    /**
     
    9999     * @param   pVDIfsDisk      Pointer to the per-disk VD interface list.
    100100     * @param   pVDIfsImage     Pointer to the per-image VD interface list.
    101      * @param   ppvBackendData  Opaque state data for this image.
     101     * @param   ppBackendData   Opaque state data for this image.
    102102     */
    103103    DECLR3CALLBACKMEMBER(int, pfnOpen, (const char *pszFilename, unsigned uOpenFlags,
    104104                                        PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
    105                                         void **ppvBackendData));
     105                                        void **ppBackendData));
    106106
    107107    /**
     
    123123     * @param   pVDIfsImage     Pointer to the per-image VD interface list.
    124124     * @param   pVDIfsOperation Pointer to the per-operation VD interface list.
    125      * @param   ppvBackendData  Opaque state data for this image.
     125     * @param   ppBackendData   Opaque state data for this image.
    126126     */
    127127    DECLR3CALLBACKMEMBER(int, pfnCreate, (const char *pszFilename, uint64_t cbSize,
    128128                                          unsigned uImageFlags, const char *pszComment,
    129                                           PCPDMMEDIAGEOMETRY pPCHSGeometry,
    130                                           PCPDMMEDIAGEOMETRY pLCHSGeometry,
     129                                          PCVDGEOMETRY pPCHSGeometry,
     130                                          PCVDGEOMETRY pLCHSGeometry,
    131131                                          PCRTUUID pUuid, unsigned uOpenFlags,
    132132                                          unsigned uPercentStart, unsigned uPercentSpan,
     
    134134                                          PVDINTERFACE pVDIfsImage,
    135135                                          PVDINTERFACE pVDIfsOperation,
    136                                           void **ppvBackendData));
     136                                          void **ppBackendData));
    137137
    138138    /**
     
    142142     * may just fail with an appropriate error code (not changing the opened
    143143     * image data at all). Also works only on images which actually refer to
    144      * files (and not for raw disk images).
    145      *
    146      * @returns VBox status code.
    147      * @param   pvBackendData   Opaque state data for this image.
     144     * regular files. May be NULL.
     145     *
     146     * @returns VBox status code.
     147     * @param   pBackendData    Opaque state data for this image.
    148148     * @param   pszFilename     New name of the image file. Guaranteed to be available and
    149149     *                          unchanged during the lifetime of this image.
    150150     */
    151     DECLR3CALLBACKMEMBER(int, pfnRename, (void *pvBackendData, const char *pszFilename));
     151    DECLR3CALLBACKMEMBER(int, pfnRename, (void *pBackendData, const char *pszFilename));
    152152
    153153    /**
     
    155155     *
    156156     * @returns VBox status code.
    157      * @param   pvBackendData   Opaque state data for this image.
     157     * @param   pBackendData    Opaque state data for this image.
    158158     * @param   fDelete         If true, delete the image from the host disk.
    159159     */
    160     DECLR3CALLBACKMEMBER(int, pfnClose, (void *pvBackendData, bool fDelete));
     160    DECLR3CALLBACKMEMBER(int, pfnClose, (void *pBackendData, bool fDelete));
    161161
    162162    /**
     
    166166     * @returns VBox status code.
    167167     * @returns VERR_VD_BLOCK_FREE if this image contains no data for this block.
    168      * @param   pvBackendData   Opaque state data for this image.
     168     * @param   pBackendData    Opaque state data for this image.
    169169     * @param   uOffset         Offset to start reading from.
    170170     * @param   pvBuf           Where to store the read bits.
     
    172172     * @param   pcbActuallyRead Pointer to returned number of bytes read.
    173173     */
    174     DECLR3CALLBACKMEMBER(int, pfnRead, (void *pvBackendData, uint64_t uOffset, void *pvBuf,
     174    DECLR3CALLBACKMEMBER(int, pfnRead, (void *pBackendData, uint64_t uOffset, void *pvBuf,
    175175                                        size_t cbRead, size_t *pcbActuallyRead));
    176176
     
    186186     *          but it works with arbitrary block sizes, especially when the image
    187187     *          stack uses different block sizes.
    188      * @param   pvBackendData   Opaque state data for this image.
     188     * @param   pBackendData    Opaque state data for this image.
    189189     * @param   uOffset         Offset to start writing to.
    190190     * @param   pvBuf           Where to retrieve the written bits.
     
    203203     *                          of the VD_WRITE_* flags.
    204204     */
    205     DECLR3CALLBACKMEMBER(int, pfnWrite, (void *pvBackendData, uint64_t uOffset,
     205    DECLR3CALLBACKMEMBER(int, pfnWrite, (void *pBackendData, uint64_t uOffset,
    206206                                         const void *pvBuf, size_t cbWrite,
    207207                                         size_t *pcbWriteProcess, size_t *pcbPreRead,
     
    212212     *
    213213     * @returns VBox status code.
    214      * @param   pvBackendData   Opaque state data for this image.
    215      */
    216     DECLR3CALLBACKMEMBER(int, pfnFlush, (void *pvBackendData));
     214     * @param   pBackendData    Opaque state data for this image.
     215     */
     216    DECLR3CALLBACKMEMBER(int, pfnFlush, (void *pBackendData));
    217217
    218218    /**
     
    220220     *
    221221     * @returns version of disk image.
    222      * @param   pvBackendData   Opaque state data for this image.
    223      */
    224     DECLR3CALLBACKMEMBER(unsigned, pfnGetVersion, (void *pvBackendData));
     222     * @param   pBackendData    Opaque state data for this image.
     223     */
     224    DECLR3CALLBACKMEMBER(unsigned, pfnGetVersion, (void *pBackendData));
    225225
    226226    /**
     
    228228     *
    229229     * @returns size of disk image in bytes.
    230      * @param   pvBackendData   Opaque state data for this image.
    231      */
    232     DECLR3CALLBACKMEMBER(uint64_t, pfnGetSize, (void *pvBackendData));
     230     * @param   pBackendData    Opaque state data for this image.
     231     */
     232    DECLR3CALLBACKMEMBER(uint64_t, pfnGetSize, (void *pBackendData));
    233233
    234234    /**
     
    236236     *
    237237     * @returns size of disk image in bytes.
    238      * @param   pvBackendData   Opaque state data for this image.
    239      */
    240     DECLR3CALLBACKMEMBER(uint64_t, pfnGetFileSize, (void *pvBackendData));
     238     * @param   pBackendData    Opaque state data for this image.
     239     */
     240    DECLR3CALLBACKMEMBER(uint64_t, pfnGetFileSize, (void *pBackendData));
    241241
    242242    /**
     
    245245     * @returns VBox status code.
    246246     * @returns VERR_VD_GEOMETRY_NOT_SET if no geometry present in the image.
    247      * @param   pvBackendData   Opaque state data for this image.
     247     * @param   pBackendData    Opaque state data for this image.
    248248     * @param   pPCHSGeometry   Where to store the geometry. Not NULL.
    249249     */
    250     DECLR3CALLBACKMEMBER(int, pfnGetPCHSGeometry, (void *pvBackendData, PPDMMEDIAGEOMETRY pPCHSGeometry));
     250    DECLR3CALLBACKMEMBER(int, pfnGetPCHSGeometry, (void *pBackendData, PVDGEOMETRY pPCHSGeometry));
    251251
    252252    /**
     
    255255     *
    256256     * @returns VBox status code.
    257      * @param   pvBackendData   Opaque state data for this image.
     257     * @param   pBackendData    Opaque state data for this image.
    258258     * @param   pPCHSGeometry   Where to load the geometry from. Not NULL.
    259259     */
    260     DECLR3CALLBACKMEMBER(int, pfnSetPCHSGeometry, (void *pvBackendData, PCPDMMEDIAGEOMETRY pPCHSGeometry));
     260    DECLR3CALLBACKMEMBER(int, pfnSetPCHSGeometry, (void *pBackendData, PCVDGEOMETRY pPCHSGeometry));
    261261
    262262    /**
     
    265265     * @returns VBox status code.
    266266     * @returns VERR_VD_GEOMETRY_NOT_SET if no geometry present in the image.
    267      * @param   pvBackendData   Opaque state data for this image.
     267     * @param   pBackendData    Opaque state data for this image.
    268268     * @param   pLCHSGeometry   Where to store the geometry. Not NULL.
    269269     */
    270     DECLR3CALLBACKMEMBER(int, pfnGetLCHSGeometry, (void *pvBackendData, PPDMMEDIAGEOMETRY pLCHSGeometry));
     270    DECLR3CALLBACKMEMBER(int, pfnGetLCHSGeometry, (void *pBackendData,  PVDGEOMETRY pLCHSGeometry));
    271271
    272272    /**
     
    275275     *
    276276     * @returns VBox status code.
    277      * @param   pvBackendData   Opaque state data for this image.
     277     * @param   pBackendData    Opaque state data for this image.
    278278     * @param   pLCHSGeometry   Where to load the geometry from. Not NULL.
    279279     */
    280     DECLR3CALLBACKMEMBER(int, pfnSetLCHSGeometry, (void *pvBackendData, PCPDMMEDIAGEOMETRY pLCHSGeometry));
     280    DECLR3CALLBACKMEMBER(int, pfnSetLCHSGeometry, (void *pBackendData,  PCVDGEOMETRY pLCHSGeometry));
    281281
    282282    /**
     
    284284     *
    285285     * @returns image flags of disk image.
    286      * @param   pvBackendData   Opaque state data for this image.
    287      */
    288     DECLR3CALLBACKMEMBER(unsigned, pfnGetImageFlags, (void *pvBackendData));
     286     * @param   pBackendData    Opaque state data for this image.
     287     */
     288    DECLR3CALLBACKMEMBER(unsigned, pfnGetImageFlags, (void *pBackendData));
    289289
    290290    /**
     
    292292     *
    293293     * @returns open flags of disk image.
    294      * @param   pvBackendData   Opaque state data for this image.
    295      */
    296     DECLR3CALLBACKMEMBER(unsigned, pfnGetOpenFlags, (void *pvBackendData));
     294     * @param   pBackendData    Opaque state data for this image.
     295     */
     296    DECLR3CALLBACKMEMBER(unsigned, pfnGetOpenFlags, (void *pBackendData));
    297297
    298298    /**
     
    301301     *
    302302     * @returns VBox status code.
    303      * @param   pvBackendData   Opaque state data for this image.
     303     * @param   pBackendData    Opaque state data for this image.
    304304     * @param   uOpenFlags      New open flags for this image.
    305305     */
    306     DECLR3CALLBACKMEMBER(int, pfnSetOpenFlags, (void *pvBackendData, unsigned uOpenFlags));
     306    DECLR3CALLBACKMEMBER(int, pfnSetOpenFlags, (void *pBackendData, unsigned uOpenFlags));
    307307
    308308    /**
     
    310310     *
    311311     * @returns VBox status code.
    312      * @param   pvBackendData   Opaque state data for this image.
     312     * @param   pBackendData    Opaque state data for this image.
    313313     * @param   pszComment      Where to store the comment.
    314314     * @param   cbComment       Size of the comment buffer.
    315315     */
    316     DECLR3CALLBACKMEMBER(int, pfnGetComment, (void *pvBackendData, char *pszComment, size_t cbComment));
     316    DECLR3CALLBACKMEMBER(int, pfnGetComment, (void *pBackendData, char *pszComment, size_t cbComment));
    317317
    318318    /**
     
    320320     *
    321321     * @returns VBox status code.
    322      * @param   pvBackendData   Opaque state data for this image.
     322     * @param   pBackendData    Opaque state data for this image.
    323323     * @param   pszComment      Where to get the comment from. NULL resets comment.
    324324     *                          The comment is silently truncated if the image format
    325325     *                          limit is exceeded.
    326326     */
    327     DECLR3CALLBACKMEMBER(int, pfnSetComment, (void *pvBackendData, const char *pszComment));
     327    DECLR3CALLBACKMEMBER(int, pfnSetComment, (void *pBackendData, const char *pszComment));
    328328
    329329    /**
     
    331331     *
    332332     * @returns VBox status code.
    333      * @param   pvBackendData   Opaque state data for this image.
     333     * @param   pBackendData    Opaque state data for this image.
    334334     * @param   pUuid           Where to store the image UUID.
    335335     */
    336     DECLR3CALLBACKMEMBER(int, pfnGetUuid, (void *pvBackendData, PRTUUID pUuid));
     336    DECLR3CALLBACKMEMBER(int, pfnGetUuid, (void *pBackendData, PRTUUID pUuid));
    337337
    338338    /**
     
    340340     *
    341341     * @returns VBox status code.
    342      * @param   pvBackendData   Opaque state data for this image.
     342     * @param   pBackendData    Opaque state data for this image.
    343343     * @param   pUuid           Where to get the image UUID from.
    344344     */
    345     DECLR3CALLBACKMEMBER(int, pfnSetUuid, (void *pvBackendData, PCRTUUID pUuid));
     345    DECLR3CALLBACKMEMBER(int, pfnSetUuid, (void *pBackendData, PCRTUUID pUuid));
    346346
    347347    /**
     
    349349     *
    350350     * @returns VBox status code.
    351      * @param   pvBackendData   Opaque state data for this image.
     351     * @param   pBackendData    Opaque state data for this image.
    352352     * @param   pUuid           Where to store the image modification UUID.
    353353     */
    354     DECLR3CALLBACKMEMBER(int, pfnGetModificationUuid, (void *pvBackendData, PRTUUID pUuid));
     354    DECLR3CALLBACKMEMBER(int, pfnGetModificationUuid, (void *pBackendData, PRTUUID pUuid));
    355355
    356356    /**
     
    358358     *
    359359     * @returns VBox status code.
    360      * @param   pvBackendData   Opaque state data for this image.
     360     * @param   pBackendData    Opaque state data for this image.
    361361     * @param   pUuid           Where to get the image modification UUID from.
    362362     */
    363     DECLR3CALLBACKMEMBER(int, pfnSetModificationUuid, (void *pvBackendData, PCRTUUID pUuid));
     363    DECLR3CALLBACKMEMBER(int, pfnSetModificationUuid, (void *pBackendData, PCRTUUID pUuid));
    364364
    365365    /**
     
    367367     *
    368368     * @returns VBox status code.
    369      * @param   pvBackendData   Opaque state data for this image.
     369     * @param   pBackendData    Opaque state data for this image.
    370370     * @param   pUuid           Where to store the parent image UUID.
    371371     */
    372     DECLR3CALLBACKMEMBER(int, pfnGetParentUuid, (void *pvBackendData, PRTUUID pUuid));
     372    DECLR3CALLBACKMEMBER(int, pfnGetParentUuid, (void *pBackendData, PRTUUID pUuid));
    373373
    374374    /**
     
    376376     *
    377377     * @returns VBox status code.
    378      * @param   pvBackendData   Opaque state data for this image.
     378     * @param   pBackendData    Opaque state data for this image.
    379379     * @param   pUuid           Where to get the parent image UUID from.
    380380     */
    381     DECLR3CALLBACKMEMBER(int, pfnSetParentUuid, (void *pvBackendData, PCRTUUID pUuid));
     381    DECLR3CALLBACKMEMBER(int, pfnSetParentUuid, (void *pBackendData, PCRTUUID pUuid));
    382382
    383383    /**
     
    385385     *
    386386     * @returns VBox status code.
    387      * @param   pvBackendData   Opaque state data for this image.
     387     * @param   pBackendData    Opaque state data for this image.
    388388     * @param   pUuid           Where to store the parent image modification UUID.
    389389     */
    390     DECLR3CALLBACKMEMBER(int, pfnGetParentModificationUuid, (void *pvBackendData, PRTUUID pUuid));
     390    DECLR3CALLBACKMEMBER(int, pfnGetParentModificationUuid, (void *pBackendData, PRTUUID pUuid));
    391391
    392392    /**
     
    394394     *
    395395     * @returns VBox status code.
    396      * @param   pvBackendData   Opaque state data for this image.
     396     * @param   pBackendData    Opaque state data for this image.
    397397     * @param   pUuid           Where to get the parent image modification UUID from.
    398398     */
    399     DECLR3CALLBACKMEMBER(int, pfnSetParentModificationUuid, (void *pvBackendData, PCRTUUID pUuid));
     399    DECLR3CALLBACKMEMBER(int, pfnSetParentModificationUuid, (void *pBackendData, PCRTUUID pUuid));
    400400
    401401    /**
    402402     * Dump information about a disk image.
    403403     *
    404      * @param   pvBackendData   Opaque state data for this image.
    405      */
    406     DECLR3CALLBACKMEMBER(void, pfnDump, (void *pvBackendData));
    407 
    408     /**
    409      * Get a time stamp of a disk image.
    410      *
    411      * @returns VBox status code.
    412      * @param   pvBackendData   Opaque state data for this image.
     404     * @param   pBackendData    Opaque state data for this image.
     405     */
     406    DECLR3CALLBACKMEMBER(void, pfnDump, (void *pBackendData));
     407
     408    /**
     409     * Get a time stamp of a disk image. May be NULL.
     410     *
     411     * @returns VBox status code.
     412     * @param   pBackendData    Opaque state data for this image.
    413413     * @param   pTimeStamp      Where to store the time stamp.
    414414     */
    415     DECLR3CALLBACKMEMBER(int, pfnGetTimeStamp, (void *pvBackendData, PRTTIMESPEC pTimeStamp));
    416 
    417     /**
    418      * Get the parent time stamp of a disk image.
    419      *
    420      * @returns VBox status code.
    421      * @param   pvBackendData   Opaque state data for this image.
     415    DECLR3CALLBACKMEMBER(int, pfnGetTimeStamp, (void *pBackendData, PRTTIMESPEC pTimeStamp));
     416
     417    /**
     418     * Get the parent time stamp of a disk image. May be NULL.
     419     *
     420     * @returns VBox status code.
     421     * @param   pBackendData    Opaque state data for this image.
    422422     * @param   pTimeStamp      Where to store the time stamp.
    423423     */
    424     DECLR3CALLBACKMEMBER(int, pfnGetParentTimeStamp, (void *pvBackendData, PRTTIMESPEC pTimeStamp));
    425 
    426     /**
    427      * Set the parent time stamp of a disk image.
    428      *
    429      * @returns VBox status code.
    430      * @param   pvBackendData   Opaque state data for this image.
     424    DECLR3CALLBACKMEMBER(int, pfnGetParentTimeStamp, (void *pBackendData, PRTTIMESPEC pTimeStamp));
     425
     426    /**
     427     * Set the parent time stamp of a disk image. May be NULL.
     428     *
     429     * @returns VBox status code.
     430     * @param   pBackendData    Opaque state data for this image.
    431431     * @param   pTimeStamp      Where to get the time stamp from.
    432432     */
    433     DECLR3CALLBACKMEMBER(int, pfnSetParentTimeStamp, (void *pvBackendData, PCRTTIMESPEC pTimeStamp));
    434 
    435     /**
    436      * Get the relative path to parent image.
    437      *
    438      * @returns VBox status code.
    439      * @param   pvBackendData     Opaque state data for this image.
     433    DECLR3CALLBACKMEMBER(int, pfnSetParentTimeStamp, (void *pBackendData, PCRTTIMESPEC pTimeStamp));
     434
     435    /**
     436     * Get the relative path to parent image. May be NULL.
     437     *
     438     * @returns VBox status code.
     439     * @param   pBackendData      Opaque state data for this image.
    440440     * @param   pszParentFilename Where to store the path.
    441441     */
    442     DECLR3CALLBACKMEMBER(int, pfnGetParentFilename, (void *pvBackendData, char **ppszParentFilename));
    443 
    444     /**
    445      * Set the relative path to parent image.
    446      *
    447      * @returns VBox status code.
    448      * @param   pvBackendData     Opaque state data for this image.
     442    DECLR3CALLBACKMEMBER(int, pfnGetParentFilename, (void *pBackendData, char **ppszParentFilename));
     443
     444    /**
     445     * Set the relative path to parent image. May be NULL.
     446     *
     447     * @returns VBox status code.
     448     * @param   pBackendData      Opaque state data for this image.
    449449     * @param   pszParentFilename Where to get the path from.
    450450     */
    451     DECLR3CALLBACKMEMBER(int, pfnSetParentFilename, (void *pvBackendData, const char *pszParentFilename));
     451    DECLR3CALLBACKMEMBER(int, pfnSetParentFilename, (void *pBackendData, const char *pszParentFilename));
    452452
    453453    /**
     
    456456     * @returns true if asynchronous I/O is supported
    457457     *          false otherwise.
    458      * @param   pvBackendData    Opaque state data for this image.
    459      */
    460     DECLR3CALLBACKMEMBER(bool, pfnIsAsyncIOSupported, (void *pvBackendData));
     458     * @param   pBackendData     Opaque state data for this image.
     459     */
     460    DECLR3CALLBACKMEMBER(bool, pfnIsAsyncIOSupported, (void *pBackendData));
    461461
    462462    /**
     
    464464     *
    465465     * @returns VBox status code.
    466      * @param   pvBackendData   Opaque state data for this image.
     466     * @param   pBackendData    Opaque state data for this image.
    467467     * @param   uOffset         The offset of the virtual disk to read from.
    468468     * @param   cbRead          How many bytes to read.
     
    470470     * @param   pcbActuallyRead Pointer to returned number of bytes read.
    471471     */
    472     DECLR3CALLBACKMEMBER(int, pfnAsyncRead, (void *pvBackendData, uint64_t uOffset, size_t cbRead,
     472    DECLR3CALLBACKMEMBER(int, pfnAsyncRead, (void *pBackendData, uint64_t uOffset, size_t cbRead,
    473473                                             PVDIOCTX pIoCtx, size_t *pcbActuallyRead));
    474474
     
    477477     *
    478478     * @returns VBox status code.
    479      * @param   pvBackendData   Opaque state data for this image.
     479     * @param   pBackendData    Opaque state data for this image.
    480480     * @param   uOffset         The offset of the virtual disk to write to.
    481481     * @param   cbWrite         How many bytes to write.
     
    494494     *                          of the VD_WRITE_* flags.
    495495     */
    496     DECLR3CALLBACKMEMBER(int, pfnAsyncWrite, (void *pvBackendData, uint64_t uOffset, size_t cbWrite,
     496    DECLR3CALLBACKMEMBER(int, pfnAsyncWrite, (void *pBackendData, uint64_t uOffset, size_t cbWrite,
    497497                                              PVDIOCTX pIoCtx,
    498498                                              size_t *pcbWriteProcess, size_t *pcbPreRead,
     
    503503     *
    504504     * @returns VBox status code.
    505      * @param   pvBackendData   Opaque state data for this image.
     505     * @param   pBackendData    Opaque state data for this image.
    506506     * @param   pIoCtx          I/O context associated with this request.
    507507     */
    508     DECLR3CALLBACKMEMBER(int, pfnAsyncFlush, (void *pvBackendData, PVDIOCTX pIoCtx));
     508    DECLR3CALLBACKMEMBER(int, pfnAsyncFlush, (void *pBackendData, PVDIOCTX pIoCtx));
    509509
    510510    /** Returns a human readable hard disk location string given a
     
    527527     * @returns VBox status code.
    528528     * @returns VERR_NOT_SUPPORTED if this image cannot be compacted yet.
    529      * @param   pvBackendData   Opaque state data for this image.
     529     * @param   pBackendData    Opaque state data for this image.
    530530     * @param   uPercentStart   Starting value for progress percentage.
    531531     * @param   uPercentSpan    Span for varying progress percentage.
     
    534534     * @param   pVDIfsOperation Pointer to the per-operation VD interface list.
    535535     */
    536     DECLR3CALLBACKMEMBER(int, pfnCompact, (void *pvBackendData,
     536    DECLR3CALLBACKMEMBER(int, pfnCompact, (void *pBackendData,
    537537                                           unsigned uPercentStart, unsigned uPercentSpan,
    538538                                           PVDINTERFACE pVDIfsDisk,
     
    546546     * @returns VBox status code.
    547547     * @returns VERR_NOT_SUPPORTED if this image cannot be compacted yet.
    548      * @param   pvBackendData   Opaque state data for this image.
     548     * @param   pBackendData    Opaque state data for this image.
    549549     * @param   cbSize          New size of the image.
    550550     * @param   pPCHSGeometry   Pointer to the new physical disk geometry <= (16383,16,63). Not NULL.
     
    556556     * @param   pVDIfsOperation Pointer to the per-operation VD interface list.
    557557     */
    558     DECLR3CALLBACKMEMBER(int, pfnResize, (void *pvBackendData,
     558    DECLR3CALLBACKMEMBER(int, pfnResize, (void *pBackendData,
    559559                                          uint64_t cbSize,
    560                                           PCPDMMEDIAGEOMETRY pPCHSGeometry,
    561                                           PCPDMMEDIAGEOMETRY pLCHSGeometry,
     560                                          PCVDGEOMETRY pPCHSGeometry,
     561                                          PCVDGEOMETRY pLCHSGeometry,
    562562                                          unsigned uPercentStart, unsigned uPercentSpan,
    563563                                          PVDINTERFACE pVDIfsDisk,
  • trunk/include/VBox/VBoxHDD.h

    r32431 r32536  
    3030#include <iprt/string.h>
    3131#include <iprt/mem.h>
     32#include <iprt/file.h>
    3233#include <iprt/net.h>
    3334#include <iprt/sg.h>
     
    3536#include <VBox/types.h>
    3637#include <VBox/err.h>
    37 #include <VBox/pdmifs.h>
    3838
    3939RT_C_DECLS_BEGIN
     
    166166 * used for querying information, and nothing else. */
    167167#define VD_OPEN_FLAGS_INFO          RT_BIT(3)
    168 /** Open image for asynchronous access.
    169  *  Only available if VD_CAP_ASYNC_IO is set
    170  *  Check with VDIsAsynchonousIoSupported wether
    171  *  asynchronous I/O is really supported for this file.  */
     168/** Open image for asynchronous access. Only available if VD_CAP_ASYNC_IO is
     169 * set. Check with VDIsAsynchonousIoSupported whether asynchronous I/O is
     170 * really supported for this file.  */
    172171#define VD_OPEN_FLAGS_ASYNC_IO      RT_BIT(4)
    173172/** Allow sharing of the image for writable images. May be ignored if the
     
    177176#define VD_OPEN_FLAGS_MASK          (VD_OPEN_FLAGS_NORMAL | VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_HONOR_ZEROES | VD_OPEN_FLAGS_HONOR_SAME | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE)
    178177/** @}*/
     178
     179/**
     180 * Helper functions to handle open flags.
     181 */
     182
     183/**
     184 * Translate VD_OPEN_FLAGS_* to RTFile open flags.
     185 *
     186 * @return  RTFile open flags.
     187 * @param   uOpenFlags      VD_OPEN_FLAGS_* open flags.
     188 * @param   fCreate         Flag that the file should be created.
     189 */
     190DECLINLINE(uint32_t) VDOpenFlagsToFileOpenFlags(unsigned uOpenFlags, bool fCreate)
     191{
     192    AssertMsg(!((uOpenFlags & VD_OPEN_FLAGS_READONLY) && fCreate), ("Image can't be opened readonly while being created\n"));
     193
     194    uint32_t fOpen = 0;
     195
     196    if (RT_UNLIKELY(uOpenFlags & VD_OPEN_FLAGS_READONLY))
     197        fOpen |= RTFILE_O_READ | RTFILE_O_DENY_NONE;
     198    else
     199    {
     200        fOpen |= RTFILE_O_READWRITE;
     201
     202        if (RT_UNLIKELY(uOpenFlags & VD_OPEN_FLAGS_SHAREABLE))
     203            fOpen |= RTFILE_O_DENY_NONE;
     204        else
     205            fOpen |= RTFILE_O_DENY_WRITE;
     206    }
     207
     208    if (RT_UNLIKELY(fCreate))
     209        fOpen |= RTFILE_O_CREATE | RTFILE_O_NOT_CONTENT_INDEXED;
     210    else
     211        fOpen |= RTFILE_O_OPEN;
     212
     213    return fOpen;
     214}
    179215
    180216
     
    203239 * the appropriate interface. */
    204240#define VD_CAP_TCPNET               RT_BIT(8)
     241/** The backend supports VFS (virtual filesystem) functionality since it uses
     242 * VDINTERFACEIO exclusively for all file operations. */
     243#define VD_CAP_VFS                  RT_BIT(9)
    205244/** @}*/
    206245
     
    422461     * @return  VBox status code.
    423462     * @param   pvUser          The opaque data passed on container creation.
    424      * @param   pszFormat       Error message format string.
    425      * @param   ...             Error message arguments.
    426      */
    427     DECLR3CALLBACKMEMBER(int, pfnMessage, (void *pvUser, const char *pszFormat, ...));
     463     * @param   pszFormat       Message format string.
     464     * @param   va              Message arguments.
     465     */
     466    DECLR3CALLBACKMEMBER(int, pfnMessage, (void *pvUser, const char *pszFormat, va_list va));
    428467
    429468} VDINTERFACEERROR, *PVDINTERFACEERROR;
     
    466505typedef FNVDCOMPLETED *PFNVDCOMPLETED;
    467506
    468 /** Open the storage readonly. */
    469 #define VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY  RT_BIT(0)
    470 /** Create the storage backend if it doesn't exist. */
    471 #define VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE    RT_BIT(1)
    472 /** Don't write lock the opened file. */
    473 #define VD_INTERFACEASYNCIO_OPEN_FLAGS_DONT_LOCK RT_BIT(2)
    474 
    475507/**
    476508 * Support interface for asynchronous I/O
     
    496528     * @param   pvUser          The opaque data passed on container creation.
    497529     * @param   pszLocation     Name of the location to open.
    498      * @param   uOpenFlags      Flags for opening the backend.
    499      *                          See VD_INTERFACEASYNCIO_OPEN_FLAGS_* #defines
     530     * @param   fOpen           Flags for opening the backend.
     531     *                          See RTFILE_O_* #defines, inventing another set
     532     *                          of open flags is not worth the mapping effort.
    500533     * @param   pfnCompleted    The callback which is called whenever a task
    501534     *                          completed. The backend has to pass the user data
     
    507540     */
    508541    DECLR3CALLBACKMEMBER(int, pfnOpen, (void *pvUser, const char *pszLocation,
    509                                         unsigned uOpenFlags,
     542                                        uint32_t fOpen,
    510543                                        PFNVDCOMPLETED pfnCompleted,
    511544                                        PVDINTERFACE pVDIfsDisk,
     
    549582     * @param   pStorage        The storage handle to use.
    550583     * @param   uOffset         The offset to start from.
    551      * @param   cbWrite         How many bytes to write.
    552      * @param   pvBuf           Pointer to the bits need to be written.
     584     * @param   pvBuffer        Pointer to the bits need to be written.
     585     * @param   cbBuffer        How many bytes to write.
    553586     * @param   pcbWritten      Where to store how many bytes where actually written.
    554587     */
    555588    DECLR3CALLBACKMEMBER(int, pfnWriteSync, (void *pvUser, void *pStorage, uint64_t uOffset,
    556                                              size_t cbWrite, const void *pvBuf, size_t *pcbWritten));
     589                                             const void *pvBuffer, size_t cbBuffer, size_t *pcbWritten));
    557590
    558591    /**
     
    563596     * @param   pStorage        The storage handle to use.
    564597     * @param   uOffset         The offset to start from.
    565      * @param   cbRead          How many bytes to read.
    566      * @param   pvBuf           Where to store the read bits.
     598     * @param   pvBuffer        Where to store the read bits.
     599     * @param   cbBuffer        How many bytes to read.
    567600     * @param   pcbRead         Where to store how many bytes where actually read.
    568601     */
    569602    DECLR3CALLBACKMEMBER(int, pfnReadSync, (void *pvUser, void *pStorage, uint64_t uOffset,
    570                                             size_t cbRead, void *pvBuf, size_t *pcbRead));
     603                                            void *pvBuffer, size_t cbBuffer, size_t *pcbRead));
    571604
    572605    /**
    573606     * Flush data to the storage backend.
    574607     *
    575      * @return  VBox statis code.
     608     * @return  VBox status code.
    576609     * @param   pvUser          The opaque data passed on container creation.
    577610     * @param   pStorage        The storage handle to flush.
     
    618651     * Initiates a async flush request.
    619652     *
    620      * @return  VBox statis code.
     653     * @return  VBox status code.
    621654     * @param   pvUser          The opaque data passed on container creation.
    622655     * @param   pStorage        The storage handle to flush.
     
    11411174     * @return  iprt status code.
    11421175     * @param   Sock        Socket descriptor.
    1143      * @param   pSgBuf      Scatter/gather buffer to write data to socket.
    1144      */
    1145     DECLR3CALLBACKMEMBER(int, pfnSgWrite, (VDSOCKET Sock, PCRTSGBUF pSgBuf));
     1176     * @param   pSgBuffer   Scatter/gather buffer to write data to socket.
     1177     */
     1178    DECLR3CALLBACKMEMBER(int, pfnSgWrite, (VDSOCKET Sock, PCRTSGBUF pSgBuffer));
    11461179
    11471180    /**
     
    11721205     * @return  iprt status code.
    11731206     * @param   Sock        Socket descriptor.
    1174      * @param   pSgBuf      Scatter/gather buffer to write data to socket.
     1207     * @param   pSgBuffer   Scatter/gather buffer to write data to socket.
    11751208     * @param   pcbWritten  Number of bytes written.
    11761209     */
    1177     DECLR3CALLBACKMEMBER(int, pfnSgWriteNB, (VDSOCKET Sock, PRTSGBUF pSgBuf, size_t *pcbWritten));
     1210    DECLR3CALLBACKMEMBER(int, pfnSgWriteNB, (VDSOCKET Sock, PRTSGBUF pSgBuffer, size_t *pcbWritten));
    11781211
    11791212    /**
     
    12881321     * @param   uOffset         Offset of first reading byte from start of disk.
    12891322     *                          Must be aligned to a sector boundary.
    1290      * @param   pvBuf           Pointer to buffer for reading data.
    1291      * @param   cbRead          Number of bytes to read.
     1323     * @param   pvBuffer        Pointer to buffer for reading data.
     1324     * @param   cbBuffer        Number of bytes to read.
    12921325     *                          Must be aligned to a sector boundary.
    12931326     */
    1294     DECLR3CALLBACKMEMBER(int, pfnParentRead, (void *pvUser, uint64_t uOffset, void *pvBuf, size_t cbRead));
     1327    DECLR3CALLBACKMEMBER(int, pfnParentRead, (void *pvUser, uint64_t uOffset, void *pvBuffer, size_t cbBuffer));
    12951328
    12961329} VDINTERFACEPARENTSTATE, *PVDINTERFACEPARENTSTATE;
     
    14981531 *          VINF_SUCCESS if everything was successful and the transfer can continue.
    14991532 *          VERR_VD_ASYNC_IO_IN_PROGRESS if there is another data transfer pending.
    1500  * @param   pvBackendData   The opaque backend data.
     1533 * @param   pBackendData    The opaque backend data.
    15011534 * @param   pIoCtx          I/O context associated with this request.
    15021535 * @param   pvUser          Opaque user data passed during a read/write request.
    15031536 * @param   rcReq           Status code for the completed request.
    15041537 */
    1505 typedef DECLCALLBACK(int) FNVDXFERCOMPLETED(void *pvBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq);
     1538typedef DECLCALLBACK(int) FNVDXFERCOMPLETED(void *pBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq);
    15061539/** Pointer to FNVDXFERCOMPLETED() */
    15071540typedef FNVDXFERCOMPLETED *PFNVDXFERCOMPLETED;
     
    15141547
    15151548/**
    1516  * Support interface for I/O
    1517  *
    1518  * Per-image. Required.
     1549 * Support interface for file I/O
     1550 *
     1551 * Per-image. Optional as input, always passed to backends.
    15191552 */
    15201553typedef struct VDINTERFACEIO
     
    15361569     * @param   pvUser          The opaque data passed on container creation.
    15371570     * @param   pszLocation     Name of the location to open.
    1538      * @param   uOpenFlags      Flags for opening the backend.
    1539      *                          See VD_INTERFACEASYNCIO_OPEN_FLAGS_* #defines
     1571     * @param   fOpen           Flags for opening the backend.
     1572     *                          See RTFILE_O_* #defines, inventing another set
     1573     *                          of open flags is not worth the mapping effort.
    15401574     * @param   ppStorage       Where to store the storage handle.
    15411575     */
    15421576    DECLR3CALLBACKMEMBER(int, pfnOpen, (void *pvUser, const char *pszLocation,
    1543                                         unsigned uOpenFlags, PPVDIOSTORAGE ppStorage));
     1577                                        uint32_t fOpen, PPVDIOSTORAGE ppStorage));
    15441578
    15451579    /**
     
    15511585     */
    15521586    DECLR3CALLBACKMEMBER(int, pfnClose, (void *pvUser, PVDIOSTORAGE pStorage));
     1587
     1588    /**
     1589     * Delete callback.
     1590     *
     1591     * @return  VBox status code.
     1592     * @param   pvUser          The opaque data passed on container creation.
     1593     * @param   pcszFilename    Name of the file to delete.
     1594     */
     1595    DECLR3CALLBACKMEMBER(int, pfnDelete, (void *pvUser, const char *pcszFilename));
     1596
     1597    /**
     1598     * Move callback.
     1599     *
     1600     * @return  VBox status code.
     1601     * @param   pvUser          The opaque data passed on container creation.
     1602     * @param   pcszSrc         The path to the source file.
     1603     * @param   pcszDst         The path to the destination file.
     1604     *                          This file will be created.
     1605     * @param   fMove           A combination of the RTFILEMOVE_* flags.
     1606     */
     1607    DECLR3CALLBACKMEMBER(int, pfnMove, (void *pvUser, const char *pcszSrc, const char *pcszDst, unsigned fMove));
     1608
     1609    /**
     1610     * Returns the free space on a disk.
     1611     *
     1612     * @return  VBox status code.
     1613     * @param   pvUser          The opaque data passed on container creation.
     1614     * @param   pcszFilename    Name of a file to identify the disk.
     1615     * @param   pcbFreeSpace    Where to store the free space of the disk.
     1616     */
     1617    DECLR3CALLBACKMEMBER(int, pfnGetFreeSpace, (void *pvUser, const char *pcszFilename, int64_t *pcbFreeSpace));
     1618
     1619    /**
     1620     * Returns the last modification timestamp of a file.
     1621     *
     1622     * @return  VBox status code.
     1623     * @param   pvUser          The opaque data passed on container creation.
     1624     * @param   pcszFilename    Name of a file to identify the disk.
     1625     * @param   pModificationTime   Where to store the timestamp of the file.
     1626     */
     1627    DECLR3CALLBACKMEMBER(int, pfnGetModificationTime, (void *pvUser, const char *pcszFilename, PRTTIMESPEC pModificationTime));
    15531628
    15541629    /**
     
    15821657     * @param   pStorage        The storage handle to use.
    15831658     * @param   uOffset         The offset to start from.
    1584      * @param   cbWrite         How many bytes to write.
    1585      * @param   pvBuf           Pointer to the bits need to be written.
     1659     * @param   pvBuffer        Pointer to the bits need to be written.
     1660     * @param   cbBuffer        How many bytes to write.
    15861661     * @param   pcbWritten      Where to store how many bytes where actually written.
    15871662     *
     
    15911666     */
    15921667    DECLR3CALLBACKMEMBER(int, pfnWriteSync, (void *pvUser, PVDIOSTORAGE pStorage, uint64_t uOffset,
    1593                                              size_t cbWrite, const void *pvBuf, size_t *pcbWritten));
     1668                                             const void *pvBuffer, size_t cbBuffer, size_t *pcbWritten));
    15941669
    15951670    /**
     
    16001675     * @param   pStorage        The storage handle to use.
    16011676     * @param   uOffset         The offset to start from.
    1602      * @param   cbRead          How many bytes to read.
    1603      * @param   pvBuf           Where to store the read bits.
     1677     * @param   pvBuffer        Where to store the read bits.
     1678     * @param   cbBuffer        How many bytes to read.
    16041679     * @param   pcbRead         Where to store how many bytes where actually read.
    16051680     *
     
    16071682     */
    16081683    DECLR3CALLBACKMEMBER(int, pfnReadSync, (void *pvUser, PVDIOSTORAGE pStorage, uint64_t uOffset,
    1609                                             size_t cbRead, void *pvBuf, size_t *pcbRead));
     1684                                            void *pvBuffer, size_t cbBuffer, size_t *pcbRead));
    16101685
    16111686    /**
     
    16601735     * @param   pStorage       The storage handle.
    16611736     * @param   uOffset        Offset to start reading from.
    1662      * @param   pvBuf          Where to store the data.
    1663      * @param   cbRead         How many bytes to read.
     1737     * @param   pvBuffer       Where to store the data.
     1738     * @param   cbBuffer       How many bytes to read.
    16641739     * @param   pIoCtx         The I/O context which triggered the read.
    16651740     * @param   ppMetaXfer     Where to store the metadata transfer handle on success.
     
    16681743     */
    16691744    DECLR3CALLBACKMEMBER(int, pfnReadMetaAsync, (void *pvUser, PVDIOSTORAGE pStorage,
    1670                                                  uint64_t uOffset, void *pvBuf,
    1671                                                  size_t cbRead, PVDIOCTX pIoCtx,
     1745                                                 uint64_t uOffset, void *pvBuffer,
     1746                                                 size_t cbBuffer, PVDIOCTX pIoCtx,
    16721747                                                 PPVDMETAXFER ppMetaXfer,
    16731748                                                 PFNVDXFERCOMPLETED pfnComplete,
     
    16811756     * @param   pStorage       The storage handle.
    16821757     * @param   uOffset        Offset to start writing to.
    1683      * @param   pvBuf          Written data.
    1684      * @param   cbWrite        How many bytes to write.
     1758     * @param   pvBuffer       Written data.
     1759     * @param   cbBuffer       How many bytes to write.
    16851760     * @param   pIoCtx         The I/O context which triggered the write.
    16861761     * @param   pfnCompleted   Completion callback.
     
    16881763     */
    16891764    DECLR3CALLBACKMEMBER(int, pfnWriteMetaAsync, (void *pvUser, PVDIOSTORAGE pStorage,
    1690                                                   uint64_t uOffset, void *pvBuf,
    1691                                                   size_t cbWrite, PVDIOCTX pIoCtx,
     1765                                                  uint64_t uOffset, void *pvBuffer,
     1766                                                  size_t cbBuffer, PVDIOCTX pIoCtx,
    16921767                                                  PFNVDXFERCOMPLETED pfnComplete,
    16931768                                                  void *pvCompleteUser));
     
    17241799     * @param  pvUser          The opaque user data passed on container creation.
    17251800     * @param  pIoCtx          I/O context to copy the data to.
    1726      * @param  pvBuf           Buffer to copy.
    1727      * @param  cbBuf           Number of bytes to copy.
     1801     * @param  pvBuffer        Buffer to copy.
     1802     * @param  cbBuffer        Number of bytes to copy.
    17281803     */
    17291804    DECLR3CALLBACKMEMBER(size_t, pfnIoCtxCopyTo, (void *pvUser, PVDIOCTX pIoCtx,
    1730                                                   void *pvBuf, size_t cbBuf));
     1805                                                  void *pvBuffer, size_t cbBuffer));
    17311806
    17321807    /**
     
    17361811     * @param  pvUser          The opaque user data passed on container creation.
    17371812     * @param  pIoCtx          I/O context to copy the data from.
    1738      * @param  pvBuf           Destination buffer.
    1739      * @param  cbBuf           Number of bytes to copy.
     1813     * @param  pvBuffer        Destination buffer.
     1814     * @param  cbBuffer        Number of bytes to copy.
    17401815     */
    17411816    DECLR3CALLBACKMEMBER(size_t, pfnIoCtxCopyFrom, (void *pvUser, PVDIOCTX pIoCtx,
    1742                                                     void *pvBuf, size_t cbBuf));
     1817                                                    void *pvBuffer, size_t cbBuffer));
    17431818
    17441819    /**
     
    18091884
    18101885/**
     1886 * Request completion callback for the async read/write API.
     1887 */
     1888typedef void (FNVDASYNCTRANSFERCOMPLETE) (void *pvUser1, void *pvUser2, int rcReq);
     1889/** Pointer to a transfer compelte callback. */
     1890typedef FNVDASYNCTRANSFERCOMPLETE *PFNVDASYNCTRANSFERCOMPLETE;
     1891
     1892/**
     1893 * Disk geometry.
     1894 */
     1895typedef struct VDGEOMETRY
     1896{
     1897    /** Number of cylinders. */
     1898    uint32_t    cCylinders;
     1899    /** Number of heads. */
     1900    uint32_t    cHeads;
     1901    /** Number of sectors. */
     1902    uint32_t    cSectors;
     1903} VDGEOMETRY;
     1904
     1905/** Pointer to disk geometry. */
     1906typedef VDGEOMETRY *PVDGEOMETRY;
     1907/** Pointer to constant disk geometry. */
     1908typedef const VDGEOMETRY *PCVDGEOMETRY;
     1909
     1910/**
    18111911 * VBox HDD Container main structure.
    18121912 */
     
    18171917
    18181918/**
    1819  * Request completion callback for the async read/write API.
    1820  */
    1821 typedef void (FNVDASYNCTRANSFERCOMPLETE) (void *pvUser1, void *pvUser2, int rcReq);
    1822 /** Pointer to a transfer compelte callback. */
    1823 typedef FNVDASYNCTRANSFERCOMPLETE *PFNVDASYNCTRANSFERCOMPLETE;
    1824 
    1825 /**
    18261919 * Initializes HDD backends.
    18271920 *
     
    18801973 *
    18811974 * @return  VBox status code.
     1975 *          VINF_SUCCESS if a plugin was found.
     1976 *                       ppszFormat contains the string which can be used as backend name.
     1977 *          VERR_NOT_SUPPORTED if no backend was found.
    18821978 * @param   pVDIfsDisk      Pointer to the per-disk VD interface list.
     1979 * @param   pVDIfsImage     Pointer to the per-image VD interface list.
    18831980 * @param   pszFilename     Name of the image file for which the backend is queried.
    18841981 * @param   ppszFormat      Receives pointer of the UTF-8 string which contains the format name.
    18851982 *                          The returned pointer must be freed using RTStrFree().
    18861983 */
    1887 VBOXDDU_DECL(int) VDGetFormat(PVDINTERFACE pVDIfsDisk, const char *pszFilename, char **ppszFormat);
     1984VBOXDDU_DECL(int) VDGetFormat(PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
     1985                              const char *pszFilename, char **ppszFormat);
    18881986
    18891987/**
     
    19452043                               const char *pszFilename, uint64_t cbSize,
    19462044                               unsigned uImageFlags, const char *pszComment,
    1947                                PCPDMMEDIAGEOMETRY pPCHSGeometry,
    1948                                PCPDMMEDIAGEOMETRY pLCHSGeometry,
     2045                               PCVDGEOMETRY pPCHSGeometry,
     2046                               PCVDGEOMETRY pLCHSGeometry,
    19492047                               PCRTUUID pUuid, unsigned uOpenFlags,
    19502048                               PVDINTERFACE pVDIfsImage,
     
    20912189 */
    20922190VBOXDDU_DECL(int) VDResize(PVBOXHDD pDisk, uint64_t cbSize,
    2093                            PCPDMMEDIAGEOMETRY pPCHSGeometry,
    2094                            PCPDMMEDIAGEOMETRY pLCHSGeometry,
     2191                           PCVDGEOMETRY pPCHSGeometry,
     2192                           PCVDGEOMETRY pLCHSGeometry,
    20952193                           PVDINTERFACE pVDIfsOperation);
    20962194
     
    21342232 * @param   uOffset         Offset of first reading byte from start of disk.
    21352233 *                          Must be aligned to a sector boundary.
    2136  * @param   pvBuf           Pointer to buffer for reading data.
    2137  * @param   cbRead          Number of bytes to read.
     2234 * @param   pvBuffer        Pointer to buffer for reading data.
     2235 * @param   cbBuffer        Number of bytes to read.
    21382236 *                          Must be aligned to a sector boundary.
    21392237 */
    2140 VBOXDDU_DECL(int) VDRead(PVBOXHDD pDisk, uint64_t uOffset, void *pvBuf, size_t cbRead);
     2238VBOXDDU_DECL(int) VDRead(PVBOXHDD pDisk, uint64_t uOffset, void *pvBuffer, size_t cbBuffer);
    21412239
    21422240/**
     
    21482246 * @param   uOffset         Offset of first writing byte from start of disk.
    21492247 *                          Must be aligned to a sector boundary.
    2150  * @param   pvBuf           Pointer to buffer for writing data.
    2151  * @param   cbWrite         Number of bytes to write.
     2248 * @param   pvBuffer        Pointer to buffer for writing data.
     2249 * @param   cbBuffer        Number of bytes to write.
    21522250 *                          Must be aligned to a sector boundary.
    21532251 */
    2154 VBOXDDU_DECL(int) VDWrite(PVBOXHDD pDisk, uint64_t uOffset, const void *pvBuf, size_t cbWrite);
     2252VBOXDDU_DECL(int) VDWrite(PVBOXHDD pDisk, uint64_t uOffset, const void *pvBuffer, size_t cbBuffer);
    21552253
    21562254/**
     
    22112309 */
    22122310VBOXDDU_DECL(int) VDGetPCHSGeometry(PVBOXHDD pDisk, unsigned nImage,
    2213                                     PPDMMEDIAGEOMETRY pPCHSGeometry);
     2311                                    PVDGEOMETRY pPCHSGeometry);
    22142312
    22152313/**
     
    22232321 */
    22242322VBOXDDU_DECL(int) VDSetPCHSGeometry(PVBOXHDD pDisk, unsigned nImage,
    2225                                     PCPDMMEDIAGEOMETRY pPCHSGeometry);
     2323                                    PCVDGEOMETRY pPCHSGeometry);
    22262324
    22272325/**
     
    22362334 */
    22372335VBOXDDU_DECL(int) VDGetLCHSGeometry(PVBOXHDD pDisk, unsigned nImage,
    2238                                     PPDMMEDIAGEOMETRY pLCHSGeometry);
     2336                                    PVDGEOMETRY pLCHSGeometry);
    22392337
    22402338/**
     
    22482346 */
    22492347VBOXDDU_DECL(int) VDSetLCHSGeometry(PVBOXHDD pDisk, unsigned nImage,
    2250                                     PCPDMMEDIAGEOMETRY pLCHSGeometry);
     2348                                    PCVDGEOMETRY pLCHSGeometry);
    22512349
    22522350/**
  • trunk/include/VBox/err.h

    r32370 r32536  
    12471247/** VHD: Invalid image file header. */
    12481248#define VERR_VD_VHD_INVALID_HEADER                  (-3260)
     1249/** Parallels HDD: Invalid image file header. */
     1250#define VERR_VD_PARALLELS_INVALID_HEADER            (-3265)
     1251/** DMG: Invalid image file header. */
     1252#define VERR_VD_DMG_INVALID_HEADER                  (-3267)
    12491253/** Raw: Invalid image file header. */
    12501254#define VERR_VD_RAW_INVALID_HEADER                  (-3270)
  • trunk/include/VBox/log.h

    r31860 r32536  
    172172    /** The internal networking transport driver group. */
    173173    LOG_GROUP_DRV_INTNET,
    174     /** iSCSI Initiator driver group. */
    175     LOG_GROUP_DRV_ISCSI,
    176     /** iSCSI TCP transport driver group. */
    177     LOG_GROUP_DRV_ISCSI_TRANSPORT_TCP,
    178174    /** ISO (CD/DVD) media driver group. */
    179175    LOG_GROUP_DRV_ISO,
     
    326322    /** iSCSI virtual disk backend. */
    327323    LOG_GROUP_VD_ISCSI,
     324    /** Parallels HDD virtual disk backend. */
     325    LOG_GROUP_VD_PARALLELS,
    328326    /** Raw virtual disk backend. */
    329327    LOG_GROUP_VD_RAW,
     
    421419    "DRV_HOST_SERIAL", \
    422420    "DRV_INTNET",   \
    423     "DRV_ISCSI",    \
    424     "DRV_ISCSI_TRANSPORT_TCP", \
    425421    "DRV_ISO",      \
    426422    "DRV_KBD_QUEUE", \
     
    498494    "VD",           \
    499495    "VD_ISCSI",     \
     496    "VD_PARALLELS", \
    500497    "VD_RAW",       \
    501498    "VD_VDI",       \
  • trunk/src/VBox/Devices/Makefile.kmk

    r32471 r32536  
    7575else
    7676 VBoxDDU_SDKS.win        = WINPSDK
    77 endif
    78 ifdef VBOX_WITH_NEW_IO_CODE
    79  VBoxDDU_DEFS           += VBOX_WITH_NEW_IO_CODE
    8077endif
    8178VBoxDDU_SOURCES          = \
  • trunk/src/VBox/Devices/Storage/DMGHDDCore.cpp

    r32500 r32536  
    2323#include <VBox/log.h>
    2424#include <VBox/err.h>
    25 #include <iprt/file.h>
    2625#include <iprt/assert.h>
    2726#include <iprt/asm.h>
     
    293292typedef struct DMGIMAGE
    294293{
     294    /** Image name.
     295     * Kept around for logging and delete-on-close purposes. */
     296    const char         *pszFilename;
     297    /** Storage handle. */
     298    PVDIOSTORAGE        pStorage;
     299    /** I/O interface. */
     300    PVDINTERFACE        pInterfaceIO;
     301    /** Async I/O interface callbacks. */
     302    PVDINTERFACEIO      pInterfaceIOCallbacks;
     303
    295304    /** Pointer to the per-disk VD interface list. */
    296305    PVDINTERFACE        pVDIfsDisk;
     
    298307    PVDINTERFACE        pVDIfsImage;
    299308
    300     /** Storage handle. */
    301     PVDIOSTORAGE        pStorage;
    302     /** Size of the image. */
    303     uint64_t            cbFile;
    304     /** I/O interface. */
    305     PVDINTERFACE        pInterfaceIO;
    306     /** Async I/O interface callbacks. */
    307     PVDINTERFACEIO      pInterfaceIOCallbacks;
    308309    /** Error callback. */
    309310    PVDINTERFACE        pInterfaceError;
    310311    /** Opaque data for error callback. */
    311312    PVDINTERFACEERROR   pInterfaceErrorCallbacks;
     313
    312314    /** Flags the image was opened with. */
    313315    uint32_t            uOpenFlags;
    314316    /** Image flags. */
    315317    unsigned            uImageFlags;
    316     /** The filename.
    317      * Kept around for logging and delete-on-close purposes. */
    318     const char         *pszFilename;
     318    /** Total size of the virtual image. */
     319    uint64_t            cbSize;
     320    /** Size of the image. */
     321    uint64_t            cbFile;
     322    /** Physical geometry of this image. */
     323    VDGEOMETRY          PCHSGeometry;
     324    /** Logical geometry of this image. */
     325    VDGEOMETRY          LCHSGeometry;
     326
    319327    /** The resources.
    320328     * A lazy bird ASSUME there are only two arrays in the resource-fork section in
     
    324332    VBOXUDIF            Ftr;
    325333
    326     /** Total size of the virtual image. */
    327     uint64_t            cbSize;
    328     /** Physical geometry of this image. */
    329     PDMMEDIAGEOMETRY    PCHSGeometry;
    330     /** Logical geometry of this image. */
    331     PDMMEDIAGEOMETRY    LCHSGeometry;
    332334    /** First extent in the list. */
    333335    PDMGEXTENT          pExtentFirst;
     
    388390
    389391/*******************************************************************************
     392*   Static Variables                                                           *
     393*******************************************************************************/
     394
     395/** NULL-terminated array of supported file extensions. */
     396static const char *const s_apszDmgFileExtensions[] =
     397{
     398    "dmg",
     399    NULL
     400};
     401
     402/*******************************************************************************
    390403*   Internal Functions                                                         *
    391404*******************************************************************************/
     
    403416 * Internal: signal an error to the frontend.
    404417 */
    405 DECLINLINE(int) dmgError(PDMGIMAGE pImage, int rc, RT_SRC_POS_DECL,
     418DECLINLINE(int) dmgError(PDMGIMAGE pThis, int rc, RT_SRC_POS_DECL,
    406419                         const char *pszFormat, ...)
    407420{
    408421    va_list va;
    409422    va_start(va, pszFormat);
    410     if (pImage->pInterfaceError)
    411         pImage->pInterfaceErrorCallbacks->pfnError(pImage->pInterfaceError->pvUser, rc, RT_SRC_POS_ARGS,
    412                                                    pszFormat, va);
     423    if (pThis->pInterfaceError)
     424        pThis->pInterfaceErrorCallbacks->pfnError(pThis->pInterfaceError->pvUser, rc, RT_SRC_POS_ARGS,
     425                                                  pszFormat, va);
    413426    va_end(va);
    414427    return rc;
    415428}
    416429
    417 static int dmgFileOpen(PDMGIMAGE pImage, bool fReadonly, bool fCreate)
    418 {
    419     AssertMsg(!(fReadonly && fCreate), ("Image can't be opened readonly while being created\n"));
    420 
    421     unsigned uOpenFlags = fReadonly ? VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY : 0;
    422 
    423     if (fCreate)
    424         uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE;
    425 
    426     return pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser,
    427                                                   pImage->pszFilename,
    428                                                   uOpenFlags,
    429                                                   &pImage->pStorage);
    430 }
    431 
    432 static int dmgFileClose(PDMGIMAGE pImage)
     430/**
     431 * Internal: signal an informational message to the frontend.
     432 */
     433DECLINLINE(int) dmgMessage(PDMGIMAGE pThis, const char *pszFormat, ...)
    433434{
    434435    int rc = VINF_SUCCESS;
    435 
    436     if (pImage->pStorage)
    437         rc = pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser,
    438                                                      pImage->pStorage);
    439 
    440     pImage->pStorage = NULL;
    441 
    442     return rc;
    443 }
    444 
    445 static int dmgFileFlushSync(PDMGIMAGE pImage)
    446 {
    447     return pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser,
    448                                                        pImage->pStorage);
    449 }
    450 
    451 static int dmgFileGetSize(PDMGIMAGE pImage, uint64_t *pcbSize)
    452 {
    453     return pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser,
    454                                                      pImage->pStorage,
    455                                                      pcbSize);
    456 }
    457 
    458 static int dmgFileSetSize(PDMGIMAGE pImage, uint64_t cbSize)
    459 {
    460     return pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser,
    461                                                      pImage->pStorage,
    462                                                      cbSize);
    463 }
    464 
    465 static int dmgFileWriteSync(PDMGIMAGE pImage, uint64_t off, const void *pcvBuf, size_t cbWrite, size_t *pcbWritten)
    466 {
    467     return pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser,
    468                                                        pImage->pStorage,
    469                                                        off, cbWrite, pcvBuf,
    470                                                        pcbWritten);
    471 }
    472 
    473 static int dmgFileReadSync(PDMGIMAGE pImage, uint64_t off, void *pvBuf, size_t cbRead, size_t *pcbRead)
    474 {
    475     return pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser,
    476                                                       pImage->pStorage,
    477                                                       off, cbRead, pvBuf,
    478                                                       pcbRead);
    479 }
    480 
    481 static bool dmgFileOpened(PDMGIMAGE pImage)
    482 {
    483     return pImage->pStorage != NULL;
    484 }
     436    va_list va;
     437    va_start(va, pszFormat);
     438    if (pThis->pInterfaceError)
     439        rc = pThis->pInterfaceErrorCallbacks->pfnMessage(pThis->pInterfaceError->pvUser,
     440                                                         pszFormat, va);
     441    va_end(va);
     442    return rc;
     443}
     444
     445
     446DECLINLINE(int) dmgFileOpen(PDMGIMAGE pThis, const char *pszFilename,
     447                            uint32_t fOpen)
     448{
     449    return pThis->pInterfaceIOCallbacks->pfnOpen(pThis->pInterfaceIO->pvUser,
     450                                                 pszFilename, fOpen,
     451                                                 &pThis->pStorage);
     452}
     453
     454DECLINLINE(int) dmgFileClose(PDMGIMAGE pThis)
     455{
     456    return pThis->pInterfaceIOCallbacks->pfnClose(pThis->pInterfaceIO->pvUser,
     457                                                  pThis->pStorage);
     458}
     459
     460DECLINLINE(int) dmgFileDelete(PDMGIMAGE pThis, const char *pszFilename)
     461{
     462    return pThis->pInterfaceIOCallbacks->pfnDelete(pThis->pInterfaceIO->pvUser,
     463                                                   pszFilename);
     464}
     465
     466DECLINLINE(int) dmgFileMove(PDMGIMAGE pThis, const char *pszSrc,
     467                            const char *pszDst, unsigned fMove)
     468{
     469    return pThis->pInterfaceIOCallbacks->pfnMove(pThis->pInterfaceIO->pvUser,
     470                                                 pszSrc, pszDst, fMove);
     471}
     472
     473DECLINLINE(int) dmgFileGetFreeSpace(PDMGIMAGE pThis, const char *pszFilename,
     474                                    int64_t *pcbFree)
     475{
     476    return pThis->pInterfaceIOCallbacks->pfnGetFreeSpace(pThis->pInterfaceIO->pvUser,
     477                                                         pszFilename, pcbFree);
     478}
     479
     480DECLINLINE(int) dmgFileGetSize(PDMGIMAGE pThis, uint64_t *pcbSize)
     481{
     482    return pThis->pInterfaceIOCallbacks->pfnGetSize(pThis->pInterfaceIO->pvUser,
     483                                                    pThis->pStorage, pcbSize);
     484}
     485
     486DECLINLINE(int) dmgFileSetSize(PDMGIMAGE pThis, uint64_t cbSize)
     487{
     488    return pThis->pInterfaceIOCallbacks->pfnSetSize(pThis->pInterfaceIO->pvUser,
     489                                                    pThis->pStorage, cbSize);
     490}
     491
     492DECLINLINE(int) dmgFileWriteSync(PDMGIMAGE pThis, uint64_t uOffset,
     493                                 const void *pvBuffer, size_t cbBuffer,
     494                                 size_t *pcbWritten)
     495{
     496    return pThis->pInterfaceIOCallbacks->pfnWriteSync(pThis->pInterfaceIO->pvUser,
     497                                                      pThis->pStorage, uOffset,
     498                                                      pvBuffer, cbBuffer, pcbWritten);
     499}
     500
     501DECLINLINE(int) dmgFileReadSync(PDMGIMAGE pThis, uint64_t uOffset,
     502                                void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
     503{
     504    return pThis->pInterfaceIOCallbacks->pfnReadSync(pThis->pInterfaceIO->pvUser,
     505                                                     pThis->pStorage, uOffset,
     506                                                     pvBuffer, cbBuffer, pcbRead);
     507}
     508
     509DECLINLINE(int) dmgFileFlushSync(PDMGIMAGE pThis)
     510{
     511    return pThis->pInterfaceIOCallbacks->pfnFlushSync(pThis->pInterfaceIO->pvUser,
     512                                                      pThis->pStorage);
     513}
     514
    485515
    486516/**
     
    712742
    713743
    714 /** @copydoc VBOXHDDBACKEND::pfnClose */
    715 static DECLCALLBACK(int) vboxdmgClose(void *pvBackendData, bool fDelete)
    716 {
    717     PDMGIMAGE pThis = (PDMGIMAGE)pvBackendData;
    718 
    719     if (dmgFileOpened(pThis))
    720     {
    721         /*
    722          * If writable, flush changes, fix checksums, ++.
    723          */
    724         /** @todo writable images. */
    725 
    726         /*
    727          * Close the file.
    728          */
    729         dmgFileClose(pThis);
    730     }
    731 
    732     /*
    733      * Delete the file if requested, then free the remaining resources.
    734      */
     744/**
     745 * Internal. Flush image data to disk.
     746 */
     747static int dmgFlushImage(PDMGIMAGE pThis)
     748{
    735749    int rc = VINF_SUCCESS;
    736     if (fDelete)
    737         rc = RTFileDelete(pThis->pszFilename);
    738 
    739     for (unsigned iRsrc = 0; iRsrc < RT_ELEMENTS(pThis->aRsrcs); iRsrc++)
    740         for (unsigned i = 0; i < pThis->aRsrcs[iRsrc].cEntries; i++)
     750
     751    if (   pThis->pStorage
     752        && !(pThis->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     753    {
     754        /* @todo handle writable files, update checksums etc. */
     755    }
     756
     757    return rc;
     758}
     759
     760
     761/**
     762 * Internal. Free all allocated space for representing an image except pThis,
     763 * and optionally delete the image from disk.
     764 */
     765static int dmgFreeImage(PDMGIMAGE pThis, bool fDelete)
     766{
     767    int rc = VINF_SUCCESS;
     768
     769    /* Freeing a never allocated image (e.g. because the open failed) is
     770     * not signalled as an error. After all nothing bad happens. */
     771    if (pThis)
     772    {
     773        if (pThis->pStorage)
    741774        {
    742             if (pThis->aRsrcs[iRsrc].aEntries[i].pbData)
     775            /* No point updating the file that is deleted anyway. */
     776            if (!fDelete)
     777                dmgFlushImage(pThis);
     778
     779            dmgFileClose(pThis);
     780            pThis->pStorage = NULL;
     781        }
     782
     783        for (unsigned iRsrc = 0; iRsrc < RT_ELEMENTS(pThis->aRsrcs); iRsrc++)
     784            for (unsigned i = 0; i < pThis->aRsrcs[iRsrc].cEntries; i++)
    743785            {
    744                 RTMemFree(pThis->aRsrcs[iRsrc].aEntries[i].pbData);
    745                 pThis->aRsrcs[iRsrc].aEntries[i].pbData = NULL;
     786                if (pThis->aRsrcs[iRsrc].aEntries[i].pbData)
     787                {
     788                    RTMemFree(pThis->aRsrcs[iRsrc].aEntries[i].pbData);
     789                    pThis->aRsrcs[iRsrc].aEntries[i].pbData = NULL;
     790                }
     791                if (pThis->aRsrcs[iRsrc].aEntries[i].pszName)
     792                {
     793                    RTMemFree(pThis->aRsrcs[iRsrc].aEntries[i].pszName);
     794                    pThis->aRsrcs[iRsrc].aEntries[i].pszName = NULL;
     795                }
     796                if (pThis->aRsrcs[iRsrc].aEntries[i].pszCFName)
     797                {
     798                    RTMemFree(pThis->aRsrcs[iRsrc].aEntries[i].pszCFName);
     799                    pThis->aRsrcs[iRsrc].aEntries[i].pszCFName = NULL;
     800                }
    746801            }
    747             if (pThis->aRsrcs[iRsrc].aEntries[i].pszName)
    748             {
    749                 RTMemFree(pThis->aRsrcs[iRsrc].aEntries[i].pszName);
    750                 pThis->aRsrcs[iRsrc].aEntries[i].pszName = NULL;
    751             }
    752             if (pThis->aRsrcs[iRsrc].aEntries[i].pszCFName)
    753             {
    754                 RTMemFree(pThis->aRsrcs[iRsrc].aEntries[i].pszCFName);
    755                 pThis->aRsrcs[iRsrc].aEntries[i].pszCFName = NULL;
    756             }
    757         }
    758     RTMemFree(pThis);
    759 
     802
     803        if (fDelete && pThis->pszFilename)
     804            dmgFileDelete(pThis, pThis->pszFilename);
     805    }
     806
     807    LogFlowFunc(("returns %Rrc\n", rc));
    760808    return rc;
    761809}
     
    12781326                break;
    12791327            default:
    1280                 rc = VERR_VD_GEN_INVALID_HEADER;
     1328                rc = VERR_VD_DMG_INVALID_HEADER;
    12811329                break;
    12821330        }
     
    12931341
    12941342/**
    1295  * Worker for vboxdmgOpen that reads in and validates all the necessary
     1343 * Worker for dmgOpen that reads in and validates all the necessary
    12961344 * structures from the image.
    1297  *
    1298  * This worker is really just a construct to avoid gotos and do-break-while-zero
    1299  * uglyness.
    13001345 *
    13011346 * @returns VBox status code.
    13021347 * @param   pThis       The DMG instance data.
    1303  */
    1304 static int vboxdmgOpenWorker(PDMGIMAGE pThis)
    1305 {
     1348 * @param   uOpenFlags  Flags for defining the open type.
     1349 */
     1350static int dmgOpenImage(PDMGIMAGE pThis, unsigned uOpenFlags)
     1351{
     1352    pThis->uOpenFlags  = uOpenFlags;
     1353
     1354    pThis->pInterfaceError = VDInterfaceGet(pThis->pVDIfsDisk, VDINTERFACETYPE_ERROR);
     1355    if (pThis->pInterfaceError)
     1356        pThis->pInterfaceErrorCallbacks = VDGetInterfaceError(pThis->pInterfaceError);
     1357
     1358    /* Get I/O interface. */
     1359    pThis->pInterfaceIO = VDInterfaceGet(pThis->pVDIfsImage, VDINTERFACETYPE_IO);
     1360    AssertPtrReturn(pThis->pInterfaceIO, VERR_INVALID_PARAMETER);
     1361    pThis->pInterfaceIOCallbacks = VDGetInterfaceIO(pThis->pInterfaceIO);
     1362    AssertPtrReturn(pThis->pInterfaceIOCallbacks, VERR_INVALID_PARAMETER);
     1363
     1364    int rc = dmgFileOpen(pThis, pThis->pszFilename,
     1365                         VDOpenFlagsToFileOpenFlags(uOpenFlags,
     1366                                                    false /* fCreate */));
     1367    if (RT_FAILURE(rc))
     1368    {
     1369        /* Do NOT signal an appropriate error here, as the VD layer has the
     1370         * choice of retrying the open if it failed. */
     1371        return rc;
     1372    }
     1373
    13061374    /*
    13071375     * Read the footer.
    13081376     */
    1309     int rc = dmgFileGetSize(pThis, &pThis->cbFile);
     1377    rc = dmgFileGetSize(pThis, &pThis->cbFile);
    13101378    if (RT_FAILURE(rc))
    13111379        return rc;
    13121380    if (pThis->cbFile < 1024)
    1313         return VERR_VD_GEN_INVALID_HEADER;
     1381        return VERR_VD_DMG_INVALID_HEADER;
    13141382    rc = dmgFileReadSync(pThis, pThis->cbFile - sizeof(pThis->Ftr), &pThis->Ftr, sizeof(pThis->Ftr), NULL);
    13151383    if (RT_FAILURE(rc))
     
    13211389     */
    13221390    if (pThis->Ftr.u32Magic != VBOXUDIF_MAGIC)
    1323         return VERR_VD_GEN_INVALID_HEADER;
     1391        return VERR_VD_DMG_INVALID_HEADER;
    13241392    if (pThis->Ftr.u32Version != VBOXUDIF_VER_CURRENT)
    1325         return VERR_VD_GEN_INVALID_HEADER;
     1393        return VERR_VD_DMG_INVALID_HEADER;
    13261394    if (pThis->Ftr.cbFooter != sizeof(pThis->Ftr))
    1327         return VERR_VD_GEN_INVALID_HEADER;
     1395        return VERR_VD_DMG_INVALID_HEADER;
    13281396
    13291397    if (!vboxdmgUdifFtrIsValid(&pThis->Ftr, pThis->cbFile - sizeof(pThis->Ftr)))
    13301398    {
    13311399        VBOXDMG_PRINTF(("Bad DMG: '%s' cbFile=%RTfoff\n", pThis->pszFilename, pThis->cbFile));
    1332         return VERR_VD_GEN_INVALID_HEADER;
     1400        return VERR_VD_DMG_INVALID_HEADER;
    13331401    }
    13341402
     
    13601428                    if (pRsrcBlkx->aEntries[idxBlkx].cbData < sizeof(VBOXBLKX))
    13611429                    {
    1362                         rc = VERR_VD_GEN_INVALID_HEADER;
     1430                        rc = VERR_VD_DMG_INVALID_HEADER;
    13631431                        break;
    13641432                    }
     
    13791447                        rc = vboxdmgBlkxParse(pThis, pBlkx);
    13801448                    else
    1381                         rc = VERR_VD_GEN_INVALID_HEADER;
     1449                        rc = VERR_VD_DMG_INVALID_HEADER;
    13821450
    13831451                    if (RT_FAILURE(rc))
     
    13891457            }
    13901458            else
    1391                 rc = VERR_VD_GEN_INVALID_HEADER;
     1459                rc = VERR_VD_DMG_INVALID_HEADER;
    13921460        }
    13931461        else
     
    14001468    }
    14011469    RTMemFree(pszXml);
     1470
    14021471    if (RT_FAILURE(rc))
    1403         return rc;
    1404 
    1405 
    1406     return VINF_SUCCESS;
    1407 }
    1408 
     1472        dmgFreeImage(pThis, false);
     1473    return rc;
     1474}
     1475
     1476
     1477/** @copydoc VBOXHDDBACKEND::pfnCheckIfValid */
     1478static int dmgCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk,
     1479                           PVDINTERFACE pVDIfsImage)
     1480{
     1481    LogFlowFunc(("pszFilename=\"%s\" pVDIfsDisk=%#p pVDIfsImage=%#p\n", pszFilename, pVDIfsDisk, pVDIfsImage));
     1482    int rc;
     1483    PVDIOSTORAGE pStorage;
     1484    uint64_t cbFile, offFtr = 0;
     1485    VBOXUDIF Ftr;
     1486
     1487    /* Get I/O interface. */
     1488    PVDINTERFACE pInterfaceIO = VDInterfaceGet(pVDIfsImage, VDINTERFACETYPE_IO);
     1489    AssertPtrReturn(pInterfaceIO, VERR_INVALID_PARAMETER);
     1490    PVDINTERFACEIO pInterfaceIOCallbacks = VDGetInterfaceIO(pInterfaceIO);
     1491    AssertPtrReturn(pInterfaceIOCallbacks, VERR_INVALID_PARAMETER);
     1492
     1493    /*
     1494     * Open the file and read the footer.
     1495     */
     1496    rc = pInterfaceIOCallbacks->pfnOpen(pInterfaceIO->pvUser, pszFilename,
     1497                                        VDOpenFlagsToFileOpenFlags(VD_OPEN_FLAGS_READONLY,
     1498                                                                   false /* fCreate */),
     1499                                        &pStorage);
     1500    if (RT_SUCCESS(rc))
     1501        rc = pInterfaceIOCallbacks->pfnGetSize(pInterfaceIO->pvUser, pStorage,
     1502                                               &cbFile);
     1503    if (RT_SUCCESS(rc))
     1504    {
     1505        offFtr = cbFile - sizeof(Ftr);
     1506        rc = pInterfaceIOCallbacks->pfnReadSync(pInterfaceIO->pvUser, pStorage,
     1507                                                offFtr, &Ftr, sizeof(Ftr), NULL);
     1508    }
     1509    else
     1510    {
     1511        pInterfaceIOCallbacks->pfnClose(pInterfaceIO->pvUser, pStorage);
     1512        rc = VERR_VD_DMG_INVALID_HEADER;
     1513    }
     1514    if (RT_SUCCESS(rc))
     1515    {
     1516        vboxdmgUdifFtrFile2HostEndian(&Ftr);
     1517
     1518        /*
     1519         * Do we recognize this stuff? Does it look valid?
     1520         */
     1521        if (    Ftr.u32Magic    == VBOXUDIF_MAGIC
     1522            &&  Ftr.u32Version  == VBOXUDIF_VER_CURRENT
     1523            &&  Ftr.cbFooter    == sizeof(Ftr))
     1524        {
     1525            if (vboxdmgUdifFtrIsValid(&Ftr, offFtr))
     1526                rc = VINF_SUCCESS;
     1527            else
     1528            {
     1529                VBOXDMG_PRINTF(("Bad DMG: '%s' offFtr=%RTfoff\n", pszFilename, offFtr));
     1530                rc = VERR_VD_DMG_INVALID_HEADER;
     1531            }
     1532        }
     1533        else
     1534            rc = VERR_VD_DMG_INVALID_HEADER;
     1535    }
     1536
     1537    pInterfaceIOCallbacks->pfnClose(pInterfaceIO->pvUser, pStorage);
     1538
     1539    LogFlowFunc(("returns %Rrc\n", rc));
     1540    return rc;
     1541}
    14091542
    14101543/** @copydoc VBOXHDDBACKEND::pfnOpen */
    1411 static DECLCALLBACK(int) dmgOpen(const char *pszFilename, unsigned fOpenFlags,
    1412                                  PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
    1413                                  void **ppvBackendData)
    1414 {
     1544static int dmgOpen(const char *pszFilename, unsigned uOpenFlags,
     1545                   PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
     1546                   void **ppBackendData)
     1547{
     1548    LogFlowFunc(("pszFilename=\"%s\" uOpenFlags=%#x pVDIfsDisk=%#p pVDIfsImage=%#p ppBackendData=%#p\n", pszFilename, uOpenFlags, pVDIfsDisk, pVDIfsImage, ppBackendData));
     1549    int rc = VINF_SUCCESS;
     1550    PDMGIMAGE pThis;
     1551
     1552    /* Check open flags. All valid flags are (in principle) supported. */
     1553    if (uOpenFlags & ~VD_OPEN_FLAGS_MASK)
     1554    {
     1555        rc = VERR_INVALID_PARAMETER;
     1556        goto out;
     1557    }
     1558
     1559    /* Check remaining arguments. */
     1560    if (   !VALID_PTR(pszFilename)
     1561        || !*pszFilename)
     1562    {
     1563        rc = VERR_INVALID_PARAMETER;
     1564        goto out;
     1565    }
     1566
    14151567    /*
    14161568     * Reject combinations we don't currently support.
     
    14201572     * have validate what it passes thru to us.
    14211573     */
    1422     if (!(fOpenFlags & VD_OPEN_FLAGS_READONLY))
    1423         return VERR_NOT_SUPPORTED;
     1574    if (!(uOpenFlags & VD_OPEN_FLAGS_READONLY))
     1575    {
     1576        rc = VERR_NOT_SUPPORTED;
     1577        goto out;
     1578    }
    14241579
    14251580    /*
     
    14271582     * then hand it over to a worker function that does all the rest.
    14281583     */
    1429     PDMGIMAGE pThis = (PDMGIMAGE)RTMemAllocZ(sizeof(*pThis));
     1584    pThis = (PDMGIMAGE)RTMemAllocZ(sizeof(*pThis));
    14301585    if (!pThis)
    1431         return VERR_NO_MEMORY;
    1432     pThis->uOpenFlags  = fOpenFlags;
     1586    {
     1587        rc = VERR_NO_MEMORY;
     1588        goto out;
     1589    }
     1590
    14331591    pThis->pszFilename = pszFilename;
    14341592    pThis->pStorage    = NULL;
     
    14361594    pThis->pVDIfsImage = pVDIfsImage;
    14371595
    1438     pThis->pInterfaceError = VDInterfaceGet(pThis->pVDIfsDisk, VDINTERFACETYPE_ERROR);
    1439     if (pThis->pInterfaceError)
    1440         pThis->pInterfaceErrorCallbacks = VDGetInterfaceError(pThis->pInterfaceError);
    1441 
    1442     /* Try to get I/O interface. */
    1443     pThis->pInterfaceIO = VDInterfaceGet(pThis->pVDIfsImage, VDINTERFACETYPE_IO);
    1444     AssertPtr(pThis->pInterfaceIO);
    1445     pThis->pInterfaceIOCallbacks = VDGetInterfaceIO(pThis->pInterfaceIO);
    1446     AssertPtr(pThis->pInterfaceIOCallbacks);
    1447 
    1448     int rc = dmgFileOpen(pThis, (fOpenFlags & VD_OPEN_FLAGS_READONLY ? true : false),
    1449                          false);
    1450     if (RT_SUCCESS(rc))
    1451     {
    1452         rc = vboxdmgOpenWorker(pThis);
    1453         if (RT_SUCCESS(rc))
    1454         {
    1455             *ppvBackendData = pThis;
    1456             return rc;
    1457         }
    1458     }
    1459 
    1460     /* We failed, let the close method clean up. */
    1461     vboxdmgClose(pThis, false /* fDelete */);
    1462     return rc;
    1463 }
    1464 
    1465 
    1466 /** @copydoc VBOXHDDBACKEND::pfnCheckIfValid */
    1467 static DECLCALLBACK(int) dmgCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk)
    1468 {
    1469     /*
    1470      * Open the file and read the footer.
    1471      */
    1472     RTFILE hFile;
    1473     int rc = RTFileOpen(&hFile, pszFilename, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
    1474     if (RT_FAILURE(rc))
    1475         return rc;
    1476 
    1477     VBOXUDIF Ftr;
    1478     uint64_t offFtr;
    1479     rc = RTFileSeek(hFile, -(RTFOFF)sizeof(Ftr), RTFILE_SEEK_END, &offFtr);
    1480     if (RT_SUCCESS(rc))
    1481     {
    1482         rc = RTFileRead(hFile, &Ftr, sizeof(Ftr), NULL);
    1483         if (RT_SUCCESS(rc))
    1484         {
    1485             vboxdmgUdifFtrFile2HostEndian(&Ftr);
    1486 
    1487             /*
    1488              * Do we recognize this stuff? Does it look valid?
    1489              */
    1490             if (    Ftr.u32Magic    == VBOXUDIF_MAGIC
    1491                 &&  Ftr.u32Version  == VBOXUDIF_VER_CURRENT
    1492                 &&  Ftr.cbFooter    == sizeof(Ftr))
    1493             {
    1494                 if (vboxdmgUdifFtrIsValid(&Ftr, offFtr))
    1495                     rc = VINF_SUCCESS;
    1496                 else
    1497                 {
    1498                     VBOXDMG_PRINTF(("Bad DMG: '%s' offFtr=%RTfoff\n", pszFilename, offFtr));
    1499                     rc = VERR_VD_GEN_INVALID_HEADER;
    1500                 }
    1501 
    1502             }
    1503             else
    1504                 rc = VERR_VD_GEN_INVALID_HEADER;
    1505         }
    1506     }
    1507 
    1508     RTFileClose(hFile);
     1596    rc = dmgOpenImage(pThis, uOpenFlags);
     1597  if (RT_SUCCESS(rc))
     1598        *ppBackendData = pThis;
     1599    else
     1600        RTMemFree(pThis);
     1601
     1602out:
     1603    LogFlowFunc(("returns %Rrc (pBackendData=%#p)\n", rc, *ppBackendData));
    15091604    return rc;
    15101605}
     
    15131608static int dmgCreate(const char *pszFilename, uint64_t cbSize,
    15141609                     unsigned uImageFlags, const char *pszComment,
    1515                      PCPDMMEDIAGEOMETRY pPCHSGeometry,
    1516                      PCPDMMEDIAGEOMETRY pLCHSGeometry, PCRTUUID pUuid,
    1517                      unsigned uOpenFlags, unsigned uPercentStart,
    1518                      unsigned uPercentSpan, PVDINTERFACE pVDIfsDisk,
    1519                      PVDINTERFACE pVDIfsImage, PVDINTERFACE pVDIfsOperation,
    1520                      void **ppBackendData)
    1521 {
    1522     LogFlowFunc(("pszFilename=\"%s\" cbSize=%llu uImageFlags=%#x pszComment=\"%s\" pPCHSGeometry=%#p pLCHSGeometry=%#p Uuid=%RTuuid uOpenFlags=%#x uPercentStart=%u uPercentSpan=%u pVDIfsDisk=%#p pVDIfsImage=%#p pVDIfsOperation=%#p ppBackendData=%#p",
    1523                  pszFilename, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, ppBackendData));
    1524     return VERR_NOT_SUPPORTED;
     1610                     PCVDGEOMETRY pPCHSGeometry, PCVDGEOMETRY pLCHSGeometry,
     1611                     PCRTUUID pUuid, unsigned uOpenFlags,
     1612                     unsigned uPercentStart, unsigned uPercentSpan,
     1613                     PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
     1614                     PVDINTERFACE pVDIfsOperation, void **ppBackendData)
     1615{
     1616    LogFlowFunc(("pszFilename=\"%s\" cbSize=%llu uImageFlags=%#x pszComment=\"%s\" pPCHSGeometry=%#p pLCHSGeometry=%#p Uuid=%RTuuid uOpenFlags=%#x uPercentStart=%u uPercentSpan=%u pVDIfsDisk=%#p pVDIfsImage=%#p pVDIfsOperation=%#p ppBackendData=%#p", pszFilename, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, ppBackendData));
     1617    int rc = VERR_NOT_SUPPORTED;
     1618
     1619    LogFlowFunc(("returns %Rrc\n", rc));
     1620    return rc;
    15251621}
    15261622
     
    15391635{
    15401636    LogFlowFunc(("pBackendData=%#p fDelete=%d\n", pBackendData, fDelete));
    1541     PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
    1542     int rc = VINF_SUCCESS;
    1543 
    1544     /* Freeing a never allocated image (e.g. because the open failed) is
    1545      * not signalled as an error. After all nothing bad happens. */
    1546     if (pImage)
    1547         vboxdmgClose(pImage, fDelete);
     1637    PDMGIMAGE pThis = (PDMGIMAGE)pBackendData;
     1638    int rc;
     1639
     1640    rc = dmgFreeImage(pThis, fDelete);
     1641    RTMemFree(pThis);
    15481642
    15491643    LogFlowFunc(("returns %Rrc\n", rc));
     
    15561650{
    15571651    LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n", pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead));
    1558     PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     1652    PDMGIMAGE pThis = (PDMGIMAGE)pBackendData;
    15591653    PDMGEXTENT pExtent = NULL;
    15601654    int rc = VINF_SUCCESS;
    15611655
    1562     Assert(pImage);
     1656    AssertPtr(pThis);
    15631657    Assert(uOffset % 512 == 0);
    15641658    Assert(cbToRead % 512 == 0);
    15651659
    1566     if (   uOffset + cbToRead > pImage->cbSize
     1660    if (   uOffset + cbToRead > pThis->cbSize
    15671661        || cbToRead == 0)
    15681662    {
     
    15711665    }
    15721666
    1573     pExtent = dmgExtentGetFromOffset(pImage, uOffset);
     1667    pExtent = dmgExtentGetFromOffset(pThis, uOffset);
    15741668
    15751669    if (pExtent)
     
    15841678            case DMGEXTENTTYPE_RAW:
    15851679            {
    1586                 rc = dmgFileReadSync(pImage, pExtent->offFileStart + offExtentRel, pvBuf, cbToRead, NULL);
     1680                rc = dmgFileReadSync(pThis, pExtent->offFileStart + offExtentRel, pvBuf, cbToRead, NULL);
    15871681                break;
    15881682            }
     
    16141708    LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n",
    16151709                 pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));
    1616     PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     1710    PDMGIMAGE pThis = (PDMGIMAGE)pBackendData;
    16171711    int rc = VERR_NOT_IMPLEMENTED;
    16181712
    1619     Assert(pImage);
     1713    AssertPtr(pThis);
    16201714    Assert(uOffset % 512 == 0);
    16211715    Assert(cbToWrite % 512 == 0);
    16221716
    1623     if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     1717    if (pThis->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    16241718    {
    16251719        rc = VERR_VD_IMAGE_READ_ONLY;
     
    16381732{
    16391733    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    1640     PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
    1641     int rc = VINF_SUCCESS;
    1642 
    1643     AssertMsgFailed(("Not implemented\n"));
     1734    PDMGIMAGE pThis = (PDMGIMAGE)pBackendData;
     1735    int rc;
     1736
     1737    AssertPtr(pThis);
     1738
     1739    rc = dmgFlushImage(pThis);
     1740
    16441741    LogFlowFunc(("returns %Rrc\n", rc));
    16451742    return rc;
     
    16501747{
    16511748    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    1652     PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
    1653 
    1654     Assert(pImage);
    1655 
    1656     if (pImage)
     1749    PDMGIMAGE pThis = (PDMGIMAGE)pBackendData;
     1750
     1751    AssertPtr(pThis);
     1752
     1753    if (pThis)
    16571754        return 1;
    16581755    else
     
    16641761{
    16651762    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    1666     PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
    1667 
    1668     Assert(pImage);
    1669 
    1670     if (pImage)
    1671         return pImage->cbSize;
    1672     else
    1673         return 0;
     1763    PDMGIMAGE pThis = (PDMGIMAGE)pBackendData;
     1764    uint64_t cb = 0;
     1765
     1766    AssertPtr(pThis);
     1767
     1768    if (pThis && pThis->pStorage)
     1769        cb = pThis->cbSize;
     1770
     1771    LogFlowFunc(("returns %llu\n", cb));
     1772    return cb;
    16741773}
    16751774
     
    16781777{
    16791778    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    1680     PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     1779    PDMGIMAGE pThis = (PDMGIMAGE)pBackendData;
    16811780    uint64_t cb = 0;
    16821781
    1683     Assert(pImage);
    1684 
    1685     if (pImage)
     1782    AssertPtr(pThis);
     1783
     1784    if (pThis)
    16861785    {
    16871786        uint64_t cbFile;
    1688         if (dmgFileOpened(pImage))
     1787        if (pThis->pStorage)
    16891788        {
    1690             int rc = dmgFileGetSize(pImage, &cbFile);
     1789            int rc = dmgFileGetSize(pThis, &cbFile);
    16911790            if (RT_SUCCESS(rc))
    1692                 cb += cbFile;
     1791                cb = cbFile;
    16931792        }
    16941793    }
     
    16991798
    17001799/** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */
    1701 static int dmgGetPCHSGeometry(void *pBackendData,
    1702                               PPDMMEDIAGEOMETRY pPCHSGeometry)
     1800static int dmgGetPCHSGeometry(void *pBackendData, PVDGEOMETRY pPCHSGeometry)
    17031801{
    17041802    LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry));
    1705     PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     1803    PDMGIMAGE pThis = (PDMGIMAGE)pBackendData;
    17061804    int rc;
    17071805
    1708     Assert(pImage);
    1709 
    1710     if (pImage)
    1711     {
    1712         if (pImage->PCHSGeometry.cCylinders)
     1806    AssertPtr(pThis);
     1807
     1808    if (pThis)
     1809    {
     1810        if (pThis->PCHSGeometry.cCylinders)
    17131811        {
    1714             *pPCHSGeometry = pImage->PCHSGeometry;
     1812            *pPCHSGeometry = pThis->PCHSGeometry;
    17151813            rc = VINF_SUCCESS;
    17161814        }
     
    17261824
    17271825/** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */
    1728 static int dmgSetPCHSGeometry(void *pBackendData,
    1729                               PCPDMMEDIAGEOMETRY pPCHSGeometry)
     1826static int dmgSetPCHSGeometry(void *pBackendData, PCVDGEOMETRY pPCHSGeometry)
    17301827{
    17311828    LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n",
    17321829                 pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
    1733     PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     1830    PDMGIMAGE pThis = (PDMGIMAGE)pBackendData;
    17341831    int rc;
    17351832
    1736     Assert(pImage);
    1737 
    1738     if (pImage)
    1739     {
    1740         if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     1833    AssertPtr(pThis);
     1834
     1835    if (pThis)
     1836    {
     1837        if (pThis->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    17411838        {
    17421839            rc = VERR_VD_IMAGE_READ_ONLY;
     
    17441841        }
    17451842
    1746         pImage->PCHSGeometry = *pPCHSGeometry;
     1843        pThis->PCHSGeometry = *pPCHSGeometry;
    17471844        rc = VINF_SUCCESS;
    17481845    }
     
    17561853
    17571854/** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */
    1758 static int dmgGetLCHSGeometry(void *pBackendData,
    1759                               PPDMMEDIAGEOMETRY pLCHSGeometry)
     1855static int dmgGetLCHSGeometry(void *pBackendData, PVDGEOMETRY pLCHSGeometry)
    17601856{
    17611857     LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry));
    1762     PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     1858    PDMGIMAGE pThis = (PDMGIMAGE)pBackendData;
    17631859    int rc;
    17641860
    1765     Assert(pImage);
    1766 
    1767     if (pImage)
    1768     {
    1769         if (pImage->LCHSGeometry.cCylinders)
     1861    AssertPtr(pThis);
     1862
     1863    if (pThis)
     1864    {
     1865        if (pThis->LCHSGeometry.cCylinders)
    17701866        {
    1771             *pLCHSGeometry = pImage->LCHSGeometry;
     1867            *pLCHSGeometry = pThis->LCHSGeometry;
    17721868            rc = VINF_SUCCESS;
    17731869        }
     
    17831879
    17841880/** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */
    1785 static int dmgSetLCHSGeometry(void *pBackendData,
    1786                                PCPDMMEDIAGEOMETRY pLCHSGeometry)
     1881static int dmgSetLCHSGeometry(void *pBackendData, PCVDGEOMETRY pLCHSGeometry)
    17871882{
    17881883    LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n",
    17891884                 pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
    1790     PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     1885    PDMGIMAGE pThis = (PDMGIMAGE)pBackendData;
    17911886    int rc;
    17921887
    1793     Assert(pImage);
    1794 
    1795     if (pImage)
    1796     {
    1797         if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     1888    AssertPtr(pThis);
     1889
     1890    if (pThis)
     1891    {
     1892        if (pThis->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    17981893        {
    17991894            rc = VERR_VD_IMAGE_READ_ONLY;
     
    18011896        }
    18021897
    1803         pImage->LCHSGeometry = *pLCHSGeometry;
     1898        pThis->LCHSGeometry = *pLCHSGeometry;
    18041899        rc = VINF_SUCCESS;
    18051900    }
     
    18161911{
    18171912    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    1818     PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     1913    PDMGIMAGE pThis = (PDMGIMAGE)pBackendData;
    18191914    unsigned uImageFlags;
    18201915
    1821     Assert(pImage);
    1822 
    1823     if (pImage)
    1824         uImageFlags = pImage->uImageFlags;
     1916    AssertPtr(pThis);
     1917
     1918    if (pThis)
     1919        uImageFlags = pThis->uImageFlags;
    18251920    else
    18261921        uImageFlags = 0;
     
    18341929{
    18351930    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    1836     PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     1931    PDMGIMAGE pThis = (PDMGIMAGE)pBackendData;
    18371932    unsigned uOpenFlags;
    18381933
    1839     Assert(pImage);
    1840 
    1841     if (pImage)
    1842         uOpenFlags = pImage->uOpenFlags;
     1934    AssertPtr(pThis);
     1935
     1936    if (pThis)
     1937        uOpenFlags = pThis->uOpenFlags;
    18431938    else
    18441939        uOpenFlags = 0;
     
    18521947{
    18531948    LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags));
    1854     PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     1949    PDMGIMAGE pThis = (PDMGIMAGE)pBackendData;
    18551950    int rc;
    18561951
    18571952    /* Image must be opened and the new flags must be valid. Just readonly and
    18581953     * info flags are supported. */
    1859     if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO)))
     1954    if (!pThis || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO || VD_OPEN_FLAGS_SHAREABLE)))
    18601955    {
    18611956        rc = VERR_INVALID_PARAMETER;
     
    18631958    }
    18641959
    1865 #if 0
    18661960    /* Implement this operation via reopening the image. */
    1867     rawFreeImage(pImage, false);
    1868     rc = rawOpenImage(pImage, uOpenFlags);
    1869 #endif
     1961    rc = dmgFreeImage(pThis, false);
     1962    if (RT_FAILURE(rc))
     1963        goto out;
     1964    rc = dmgOpenImage(pThis, uOpenFlags);
    18701965
    18711966out:
     
    18791974{
    18801975    LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment));
    1881     PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     1976    PDMGIMAGE pThis = (PDMGIMAGE)pBackendData;
    18821977    int rc;
    18831978
    1884     Assert(pImage);
    1885 
    1886     if (pImage)
    1887     {
    1888         if (pszComment)
    1889             *pszComment = '\0';
    1890         rc = VINF_SUCCESS;
    1891     }
    1892     else
    1893         rc = VERR_VD_NOT_OPENED;
    1894 
    1895     LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment));
    1896     return rc;
    1897 }
    1898 
    1899 /** @copydoc VBOXHDDBACKEND::pfnSetComment */
    1900 static int dmgSetComment(void *pBackendData, const char *pszComment)
    1901 {
    1902     LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment));
    1903     PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
    1904     int rc;
    1905 
    1906     Assert(pImage);
    1907 
    1908     if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    1909     {
    1910         rc = VERR_VD_IMAGE_READ_ONLY;
    1911         goto out;
    1912     }
    1913 
    1914     if (pImage)
     1979    AssertPtr(pThis);
     1980
     1981    if (pThis)
    19151982        rc = VERR_NOT_SUPPORTED;
    19161983    else
    19171984        rc = VERR_VD_NOT_OPENED;
    19181985
    1919 out:
    1920     LogFlowFunc(("returns %Rrc\n", rc));
    1921     return rc;
    1922 }
    1923 
    1924 /** @copydoc VBOXHDDBACKEND::pfnGetUuid */
    1925 static int dmgGetUuid(void *pBackendData, PRTUUID pUuid)
    1926 {
    1927     LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
    1928     PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     1986    LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment));
     1987    return rc;
     1988}
     1989
     1990/** @copydoc VBOXHDDBACKEND::pfnSetComment */
     1991static int dmgSetComment(void *pBackendData, const char *pszComment)
     1992{
     1993    LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment));
     1994    PDMGIMAGE pThis = (PDMGIMAGE)pBackendData;
    19291995    int rc;
    19301996
    1931     Assert(pImage);
    1932 
    1933     if (pImage)
     1997    AssertPtr(pThis);
     1998
     1999    if (pThis->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     2000    {
     2001        rc = VERR_VD_IMAGE_READ_ONLY;
     2002        goto out;
     2003    }
     2004
     2005    if (pThis)
    19342006        rc = VERR_NOT_SUPPORTED;
    19352007    else
    19362008        rc = VERR_VD_NOT_OPENED;
    19372009
     2010out:
     2011    LogFlowFunc(("returns %Rrc\n", rc));
     2012    return rc;
     2013}
     2014
     2015/** @copydoc VBOXHDDBACKEND::pfnGetUuid */
     2016static int dmgGetUuid(void *pBackendData, PRTUUID pUuid)
     2017{
     2018    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
     2019    PDMGIMAGE pThis = (PDMGIMAGE)pBackendData;
     2020    int rc;
     2021
     2022    AssertPtr(pThis);
     2023
     2024    if (pThis)
     2025        rc = VERR_NOT_SUPPORTED;
     2026    else
     2027        rc = VERR_VD_NOT_OPENED;
     2028
    19382029    LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
    19392030    return rc;
     
    19442035{
    19452036    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
    1946     PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     2037    PDMGIMAGE pThis = (PDMGIMAGE)pBackendData;
    19472038    int rc;
    19482039
    19492040    LogFlowFunc(("%RTuuid\n", pUuid));
    1950     Assert(pImage);
    1951 
    1952     if (pImage)
    1953     {
    1954         if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     2041    AssertPtr(pThis);
     2042
     2043    if (pThis)
     2044    {
     2045        if (!(pThis->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    19552046            rc = VERR_NOT_SUPPORTED;
    19562047        else
     
    19682059{
    19692060    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
    1970     PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     2061    PDMGIMAGE pThis = (PDMGIMAGE)pBackendData;
    19712062    int rc;
    19722063
    1973     Assert(pImage);
    1974 
    1975     if (pImage)
     2064    AssertPtr(pThis);
     2065
     2066    if (pThis)
    19762067        rc = VERR_NOT_SUPPORTED;
    19772068    else
     
    19862077{
    19872078    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
    1988     PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     2079    PDMGIMAGE pThis = (PDMGIMAGE)pBackendData;
    19892080    int rc;
    19902081
    1991     Assert(pImage);
    1992 
    1993     if (pImage)
    1994     {
    1995         if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     2082    AssertPtr(pThis);
     2083
     2084    if (pThis)
     2085    {
     2086        if (!(pThis->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    19962087            rc = VERR_NOT_SUPPORTED;
    19972088        else
     
    20092100{
    20102101    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
    2011     PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     2102    PDMGIMAGE pThis = (PDMGIMAGE)pBackendData;
    20122103    int rc;
    20132104
    2014     Assert(pImage);
    2015 
    2016     if (pImage)
     2105    AssertPtr(pThis);
     2106
     2107    if (pThis)
    20172108        rc = VERR_NOT_SUPPORTED;
    20182109    else
     
    20272118{
    20282119    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
    2029     PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     2120    PDMGIMAGE pThis = (PDMGIMAGE)pBackendData;
    20302121    int rc;
    20312122
    2032     Assert(pImage);
    2033 
    2034     if (pImage)
    2035     {
    2036         if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     2123    AssertPtr(pThis);
     2124
     2125    if (pThis)
     2126    {
     2127        if (!(pThis->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    20372128            rc = VERR_NOT_SUPPORTED;
    20382129        else
     
    20502141{
    20512142    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
    2052     PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     2143    PDMGIMAGE pThis = (PDMGIMAGE)pBackendData;
    20532144    int rc;
    20542145
    2055     Assert(pImage);
    2056 
    2057     if (pImage)
     2146    AssertPtr(pThis);
     2147
     2148    if (pThis)
    20582149        rc = VERR_NOT_SUPPORTED;
    20592150    else
     
    20682159{
    20692160    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
    2070     PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
     2161    PDMGIMAGE pThis = (PDMGIMAGE)pBackendData;
    20712162    int rc;
    20722163
    2073     Assert(pImage);
    2074 
    2075     if (pImage)
    2076     {
    2077         if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     2164    AssertPtr(pThis);
     2165
     2166    if (pThis)
     2167    {
     2168        if (!(pThis->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    20782169            rc = VERR_NOT_SUPPORTED;
    20792170        else
     
    20902181static void dmgDump(void *pBackendData)
    20912182{
    2092     PDMGIMAGE pImage = (PDMGIMAGE)pBackendData;
    2093 
    2094     Assert(pImage);
    2095     if (pImage)
    2096     {
    2097         pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n",
    2098                     pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors,
    2099                     pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors,
    2100                     pImage->cbSize / 512);
    2101     }
    2102 }
    2103 
    2104 static int dmgGetTimeStamp(void *pvBackendData, PRTTIMESPEC pTimeStamp)
    2105 {
    2106     int rc = VERR_NOT_IMPLEMENTED;
    2107     LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
    2108     return rc;
    2109 }
    2110 
    2111 static int dmgGetParentTimeStamp(void *pvBackendData, PRTTIMESPEC pTimeStamp)
    2112 {
    2113     int rc = VERR_NOT_IMPLEMENTED;
    2114     LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
    2115     return rc;
    2116 }
    2117 
    2118 static int dmgSetParentTimeStamp(void *pvBackendData, PCRTTIMESPEC pTimeStamp)
    2119 {
    2120     int rc = VERR_NOT_IMPLEMENTED;
    2121     LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
    2122     return rc;
    2123 }
    2124 
    2125 static int dmgGetParentFilename(void *pvBackendData, char **ppszParentFilename)
    2126 {
    2127     int rc = VERR_NOT_IMPLEMENTED;
    2128     LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
    2129     return rc;
    2130 }
    2131 
    2132 static int dmgSetParentFilename(void *pvBackendData, const char *pszParentFilename)
    2133 {
    2134     int rc = VERR_NOT_IMPLEMENTED;
    2135     LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
    2136     return rc;
     2183    PDMGIMAGE pThis = (PDMGIMAGE)pBackendData;
     2184
     2185    AssertPtr(pThis);
     2186    if (pThis)
     2187    {
     2188        dmgMessage(pThis, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n",
     2189                    pThis->PCHSGeometry.cCylinders, pThis->PCHSGeometry.cHeads, pThis->PCHSGeometry.cSectors,
     2190                    pThis->LCHSGeometry.cCylinders, pThis->LCHSGeometry.cHeads, pThis->LCHSGeometry.cSectors,
     2191                    pThis->cbSize / 512);
     2192    }
    21372193}
    21382194
     
    21452201    sizeof(VBOXHDDBACKEND),
    21462202    /* uBackendCaps */
    2147     VD_CAP_FILE,
     2203    VD_CAP_FILE | VD_CAP_VFS,
    21482204    /* papszFileExtensions */
    2149     NULL,
     2205    s_apszDmgFileExtensions,
    21502206    /* paConfigInfo */
    21512207    NULL,
     
    22112267    dmgDump,
    22122268    /* pfnGetTimeStamp */
    2213     dmgGetTimeStamp,
     2269    NULL,
    22142270    /* pfnGetParentTimeStamp */
    2215     dmgGetParentTimeStamp,
     2271    NULL,
    22162272    /* pfnSetParentTimeStamp */
    2217     dmgSetParentTimeStamp,
     2273    NULL,
    22182274    /* pfnGetParentFilename */
    2219     dmgGetParentFilename,
     2275    NULL,
    22202276    /* pfnSetParentFilename */
    2221     dmgSetParentFilename,
     2277    NULL,
    22222278    /* pfnIsAsyncIOSupported */
    22232279    NULL,
     
    22372293    NULL
    22382294};
    2239 
  • trunk/src/VBox/Devices/Storage/DrvVD.cpp

    r32430 r32536  
    332332
    333333static DECLCALLBACK(int) drvvdAsyncIOOpen(void *pvUser, const char *pszLocation,
    334                                           unsigned uOpenFlags,
     334                                          uint32_t fOpen,
    335335                                          PFNVDCOMPLETED pfnCompleted,
    336336                                          PVDINTERFACE pVDIfsDisk,
     
    360360            if (RT_SUCCESS(rc))
    361361            {
    362                 uint32_t fFlags =    uOpenFlags & VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY
     362                uint32_t fFlags =    (fOpen & RTFILE_O_ACCESS_MASK) == RTFILE_O_READ
    363363                                   ? PDMACEP_FILE_FLAGS_READ_ONLY | PDMACEP_FILE_FLAGS_CACHING
    364364                                   : 0;
    365365                if (pThis->fShareable)
    366366                {
    367                     Assert(uOpenFlags & VD_INTERFACEASYNCIO_OPEN_FLAGS_DONT_LOCK);
     367                    Assert((fOpen & RTFILE_O_DENY_MASK) == RTFILE_O_DENY_NONE);
    368368
    369369                    fFlags |= PDMACEP_FILE_FLAGS_DONT_LOCK;
     
    406406
    407407static DECLCALLBACK(int) drvvdAsyncIOReadSync(void *pvUser, void *pStorage, uint64_t uOffset,
    408                                               size_t cbRead, void *pvBuf, size_t *pcbRead)
     408                                              void *pvBuf, size_t cbRead, size_t *pcbRead)
    409409{
    410410    PVBOXDISK pThis = (PVBOXDISK)pvUser;
     
    438438
    439439static DECLCALLBACK(int) drvvdAsyncIOWriteSync(void *pvUser, void *pStorage, uint64_t uOffset,
    440                                                size_t cbWrite, const void *pvBuf, size_t *pcbWritten)
     440                                               const void *pvBuf, size_t cbWrite, size_t *pcbWritten)
    441441{
    442442    PVBOXDISK pThis = (PVBOXDISK)pvUser;
     
    14451445    int rc = VINF_SUCCESS;
    14461446
    1447     LogFlow(("%s: off=%#llx pvBuf=%p cbRead=%d\n", __FUNCTION__,
    1448              off, pvBuf, cbRead));
     1447    LogFlowFunc(("off=%#llx pvBuf=%p cbRead=%d\n", off, pvBuf, cbRead));
    14491448    PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
    14501449
     
    14861485        Log2(("%s: off=%#llx pvBuf=%p cbRead=%d %.*Rhxd\n", __FUNCTION__,
    14871486              off, pvBuf, cbRead, cbRead, pvBuf));
    1488     LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
     1487    LogFlowFunc(("returns %Rrc\n", rc));
    14891488    return rc;
    14901489}
     
    14951494                                    size_t cbWrite)
    14961495{
    1497     LogFlow(("%s: off=%#llx pvBuf=%p cbWrite=%d\n", __FUNCTION__,
    1498              off, pvBuf, cbWrite));
     1496    LogFlowFunc(("off=%#llx pvBuf=%p cbWrite=%d\n", off, pvBuf, cbWrite));
    14991497    PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
    15001498    Log2(("%s: off=%#llx pvBuf=%p cbWrite=%d %.*Rhxd\n", __FUNCTION__,
     
    15091507
    15101508    int rc = VDWrite(pThis->pDisk, off, pvBuf, cbWrite);
    1511     LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
     1509    LogFlowFunc(("returns %Rrc\n", rc));
    15121510    return rc;
    15131511}
     
    15161514static DECLCALLBACK(int) drvvdFlush(PPDMIMEDIA pInterface)
    15171515{
    1518     LogFlow(("%s:\n", __FUNCTION__));
     1516    LogFlowFunc(("\n"));
    15191517    PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
    15201518    int rc = VDFlush(pThis->pDisk);
    1521     LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
     1519    LogFlowFunc(("returns %Rrc\n", rc));
    15221520    return rc;
    15231521}
     
    15281526                                    void *pvUser)
    15291527{
    1530     LogFlow(("%s:\n", __FUNCTION__));
     1528    LogFlowFunc(("\n"));
    15311529    PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
    15321530    int rc = VINF_SUCCESS;
     
    15571555    rc2 = RTSemFastMutexRelease(pThis->MergeCompleteMutex);
    15581556    AssertRC(rc2);
    1559     LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
     1557    LogFlowFunc(("returns %Rrc\n", rc));
    15601558    return rc;
    15611559}
     
    15641562static DECLCALLBACK(uint64_t) drvvdGetSize(PPDMIMEDIA pInterface)
    15651563{
    1566     LogFlow(("%s:\n", __FUNCTION__));
     1564    LogFlowFunc(("\n"));
    15671565    PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
    15681566    uint64_t cb = VDGetSize(pThis->pDisk, VD_LAST_IMAGE);
    1569     LogFlow(("%s: returns %#llx (%llu)\n", __FUNCTION__, cb, cb));
     1567    LogFlowFunc(("returns %#llx (%llu)\n", cb, cb));
    15701568    return cb;
    15711569}
     
    15741572static DECLCALLBACK(bool) drvvdIsReadOnly(PPDMIMEDIA pInterface)
    15751573{
    1576     LogFlow(("%s:\n", __FUNCTION__));
     1574    LogFlowFunc(("\n"));
    15771575    PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
    15781576    bool f = VDIsReadOnly(pThis->pDisk);
    1579     LogFlow(("%s: returns %d\n", __FUNCTION__, f));
     1577    LogFlowFunc(("returns %d\n", f));
    15801578    return f;
    15811579}
     
    15851583                                                  PPDMMEDIAGEOMETRY pPCHSGeometry)
    15861584{
    1587     LogFlow(("%s:\n", __FUNCTION__));
     1585    LogFlowFunc(("\n"));
    15881586    PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
    1589     int rc = VDGetPCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, pPCHSGeometry);
    1590     if (RT_FAILURE(rc))
    1591     {
    1592         Log(("%s: geometry not available.\n", __FUNCTION__));
     1587    VDGEOMETRY geo;
     1588    int rc = VDGetPCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, &geo);
     1589    if (RT_SUCCESS(rc))
     1590    {
     1591        pPCHSGeometry->cCylinders = geo.cCylinders;
     1592        pPCHSGeometry->cHeads = geo.cHeads;
     1593        pPCHSGeometry->cSectors = geo.cSectors;
     1594    }
     1595    else
     1596    {
     1597        LogFunc(("geometry not available.\n"));
    15931598        rc = VERR_PDM_GEOMETRY_NOT_SET;
    15941599    }
    1595     LogFlow(("%s: returns %Rrc (CHS=%d/%d/%d)\n", __FUNCTION__,
    1596              rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
     1600    LogFlowFunc(("returns %Rrc (CHS=%d/%d/%d)\n",
     1601                 rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
    15971602    return rc;
    15981603}
     
    16021607                                                  PCPDMMEDIAGEOMETRY pPCHSGeometry)
    16031608{
    1604     LogFlow(("%s: CHS=%d/%d/%d\n", __FUNCTION__,
    1605              pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
     1609    LogFlowFunc(("CHS=%d/%d/%d\n",
     1610                 pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
    16061611    PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
    1607     int rc = VDSetPCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, pPCHSGeometry);
     1612    VDGEOMETRY geo;
     1613    geo.cCylinders = pPCHSGeometry->cCylinders;
     1614    geo.cHeads = pPCHSGeometry->cHeads;
     1615    geo.cSectors = pPCHSGeometry->cSectors;
     1616    int rc = VDSetPCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, &geo);
    16081617    if (rc == VERR_VD_GEOMETRY_NOT_SET)
    16091618        rc = VERR_PDM_GEOMETRY_NOT_SET;
    1610     LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
     1619    LogFlowFunc(("returns %Rrc\n", rc));
    16111620    return rc;
    16121621}
     
    16161625                                                  PPDMMEDIAGEOMETRY pLCHSGeometry)
    16171626{
    1618     LogFlow(("%s:\n", __FUNCTION__));
     1627    LogFlowFunc(("\n"));
    16191628    PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
    1620     int rc = VDGetLCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, pLCHSGeometry);
    1621     if (RT_FAILURE(rc))
    1622     {
    1623         Log(("%s: geometry not available.\n", __FUNCTION__));
     1629    VDGEOMETRY geo;
     1630    int rc = VDGetLCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, &geo);
     1631    if (RT_SUCCESS(rc))
     1632    {
     1633        pLCHSGeometry->cCylinders = geo.cCylinders;
     1634        pLCHSGeometry->cHeads = geo.cHeads;
     1635        pLCHSGeometry->cSectors = geo.cSectors;
     1636    }
     1637    else
     1638    {
     1639        LogFunc(("geometry not available.\n"));
    16241640        rc = VERR_PDM_GEOMETRY_NOT_SET;
    16251641    }
    1626     LogFlow(("%s: returns %Rrc (CHS=%d/%d/%d)\n", __FUNCTION__,
    1627              rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
     1642    LogFlowFunc(("returns %Rrc (CHS=%d/%d/%d)\n",
     1643                 rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
    16281644    return rc;
    16291645}
     
    16331649                                                  PCPDMMEDIAGEOMETRY pLCHSGeometry)
    16341650{
    1635     LogFlow(("%s: CHS=%d/%d/%d\n", __FUNCTION__,
    1636              pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
     1651    LogFlowFunc(("CHS=%d/%d/%d\n",
     1652                 pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
    16371653    PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
    1638     int rc = VDSetLCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, pLCHSGeometry);
     1654    VDGEOMETRY geo;
     1655    geo.cCylinders = pLCHSGeometry->cCylinders;
     1656    geo.cHeads = pLCHSGeometry->cHeads;
     1657    geo.cSectors = pLCHSGeometry->cSectors;
     1658    int rc = VDSetLCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, &geo);
    16391659    if (rc == VERR_VD_GEOMETRY_NOT_SET)
    16401660        rc = VERR_PDM_GEOMETRY_NOT_SET;
    1641     LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
     1661    LogFlowFunc(("returns %Rrc\n", rc));
    16421662    return rc;
    16431663}
     
    16461666static DECLCALLBACK(int) drvvdGetUuid(PPDMIMEDIA pInterface, PRTUUID pUuid)
    16471667{
    1648     LogFlow(("%s:\n", __FUNCTION__));
     1668    LogFlowFunc(("\n"));
    16491669    PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
    16501670    int rc = VDGetUuid(pThis->pDisk, 0, pUuid);
    1651     LogFlow(("%s: returns %Rrc ({%RTuuid})\n", __FUNCTION__, rc, pUuid));
     1671    LogFlowFunc(("returns %Rrc ({%RTuuid})\n", rc, pUuid));
    16521672    return rc;
    16531673}
     
    16701690                                        size_t cbRead, void *pvUser)
    16711691{
    1672      LogFlow(("%s: uOffset=%#llx paSeg=%#p cSeg=%u cbRead=%d\n pvUser=%#p", __FUNCTION__,
    1673              uOffset, paSeg, cSeg, cbRead, pvUser));
     1692    LogFlowFunc(("uOffset=%#llx paSeg=%#p cSeg=%u cbRead=%d\n pvUser=%#p",
     1693                 uOffset, paSeg, cSeg, cbRead, pvUser));
    16741694    PVBOXDISK pThis = PDMIMEDIAASYNC_2_VBOXDISK(pInterface);
    16751695
     
    16781698    int rc = VDAsyncRead(pThis->pDisk, uOffset, cbRead, paSeg, cSeg,
    16791699                         drvvdAsyncReqComplete, pThis, pvUser);
    1680     LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
     1700    LogFlowFunc(("returns %Rrc\n", rc));
    16811701    return rc;
    16821702}
     
    16861706                                         size_t cbWrite, void *pvUser)
    16871707{
    1688      LogFlow(("%s: uOffset=%#llx paSeg=%#p cSeg=%u cbWrite=%d pvUser=%#p\n", __FUNCTION__,
    1689              uOffset, paSeg, cSeg, cbWrite, pvUser));
     1708    LogFlowFunc(("uOffset=%#llx paSeg=%#p cSeg=%u cbWrite=%d pvUser=%#p\n",
     1709                 uOffset, paSeg, cSeg, cbWrite, pvUser));
    16901710    PVBOXDISK pThis = PDMIMEDIAASYNC_2_VBOXDISK(pInterface);
    16911711
     
    16941714    int rc = VDAsyncWrite(pThis->pDisk, uOffset, cbWrite, paSeg, cSeg,
    16951715                          drvvdAsyncReqComplete, pThis, pvUser);
    1696     LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
     1716    LogFlowFunc(("returns %Rrc\n", rc));
    16971717    return rc;
    16981718}
     
    17001720static DECLCALLBACK(int) drvvdStartFlush(PPDMIMEDIAASYNC pInterface, void *pvUser)
    17011721{
    1702      LogFlow(("%s: pvUser=%#p\n", __FUNCTION__, pvUser));
     1722    LogFlowFunc(("pvUser=%#p\n", pvUser));
    17031723    PVBOXDISK pThis = PDMIMEDIAASYNC_2_VBOXDISK(pInterface);
    17041724    int rc = VDAsyncFlush(pThis->pDisk, drvvdAsyncReqComplete, pThis, pvUser);
    1705     LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
     1725    LogFlowFunc(("returns %Rrc\n", rc));
    17061726    return rc;
    17071727}
     
    17651785static DECLCALLBACK(void) drvvdPowerOff(PPDMDRVINS pDrvIns)
    17661786{
    1767     LogFlow(("%s:\n", __FUNCTION__));
     1787    LogFlowFunc(("\n"));
    17681788    PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
    17691789
     
    17911811static DECLCALLBACK(void) drvvdResume(PPDMDRVINS pDrvIns)
    17921812{
    1793     LogFlow(("%s:\n", __FUNCTION__));
     1813    LogFlowFunc(("\n"));
    17941814    PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
    17951815    drvvdSetWritable(pThis);
     
    18141834static DECLCALLBACK(void) drvvdSuspend(PPDMDRVINS pDrvIns)
    18151835{
    1816     LogFlow(("%s:\n", __FUNCTION__));
     1836    LogFlowFunc(("\n"));
    18171837    PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
    18181838    drvvdSetReadonly(pThis);
     
    18301850static DECLCALLBACK(void) drvvdPowerOn(PPDMDRVINS pDrvIns)
    18311851{
    1832     LogFlow(("%s:\n", __FUNCTION__));
     1852    LogFlowFunc(("\n"));
    18331853    PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
    18341854    drvvdSetWritable(pThis);
     
    18411861static DECLCALLBACK(void) drvvdReset(PPDMDRVINS pDrvIns)
    18421862{
    1843     LogFlow(("%s:\n", __FUNCTION__));
     1863    LogFlowFunc(("\n"));
    18441864    PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
    18451865
     
    18581878{
    18591879    PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
    1860     LogFlow(("%s:\n", __FUNCTION__));
     1880    LogFlowFunc(("\n"));
    18611881    PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
    18621882
     
    19021922                                        uint32_t fFlags)
    19031923{
    1904     LogFlow(("%s:\n", __FUNCTION__));
     1924    LogFlowFunc(("\n"));
    19051925    PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
    19061926    int rc = VINF_SUCCESS;
     
    23552375        if (RT_SUCCESS(rc))
    23562376        {
    2357             Log(("%s: %d - Opened '%s' in %s mode\n", __FUNCTION__,
    2358                  iLevel, pszName,
    2359                  VDIsReadOnly(pThis->pDisk) ? "read-only" : "read-write"));
     2377            LogFunc(("%d - Opened '%s' in %s mode\n",
     2378                     iLevel, pszName,
     2379                     VDIsReadOnly(pThis->pDisk) ? "read-only" : "read-write"));
    23602380            if (  VDIsReadOnly(pThis->pDisk)
    23612381                && !fReadOnly
     
    24352455    }
    24362456
    2437     LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
     2457    LogFlowFunc(("returns %Rrc\n", rc));
    24382458    return rc;
    24392459}
  • trunk/src/VBox/Devices/Storage/ISCSIHDDCore.cpp

    r32442 r32536  
    3030#include <iprt/assert.h>
    3131#include <iprt/uuid.h>
    32 #include <iprt/file.h>
    3332#include <iprt/string.h>
    3433#include <iprt/asm.h>
     
    339338    SCSIXFER        enmXfer;
    340339    /** Length of command block. */
    341     size_t          cbCmd;
     340    size_t          cbCDB;
    342341    /** Length of Initiator2Target data buffer. */
    343342    size_t          cbI2TData;
     
    350349    uint8_t         status;
    351350    /** Pointer to command block. */
    352     void           *pvCmd;
     351    void           *pvCDB;
    353352    /** Pointer to sense buffer. */
    354353    void           *pvSense;
     
    376375    PSCSIREQ        pScsiReq;
    377376    /** The CDB. */
    378     uint8_t         abCDB[10];
     377    uint8_t         abCDB[16];
    379378    /** The sense buffer. */
    380379    uint8_t         abSense[96];
     
    720719    va_end(va);
    721720#endif
     721    return rc;
     722}
     723
     724/**
     725 * Internal: signal an informational message to the frontend.
     726 */
     727DECLINLINE(int) iscsiMessage(PISCSIIMAGE pImage, const char *pszFormat, ...)
     728{
     729    int rc = VINF_SUCCESS;
     730    va_list va;
     731    va_start(va, pszFormat);
     732    if (pImage->pInterfaceError)
     733        rc = pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser,
     734                                                          pszFormat, va);
     735    va_end(va);
    722736    return rc;
    723737}
     
    17511765    Assert(pRequest->enmXfer != SCSIXFER_TO_FROM_TARGET);   /**< @todo not yet supported, would require AHS. */
    17521766    Assert(pRequest->cbI2TData <= 0xffffff);    /* larger transfers would require R2T support. */
    1753     Assert(pRequest->cbCmd <= 16);      /* would cause buffer overrun below. */
     1767    Assert(pRequest->cbCDB <= 16);      /* would cause buffer overrun below. */
    17541768
    17551769    /* If not in normal state, then the transport connection was dropped. Try
     
    17891803    aReqBHS[6] = RT_H2N_U32(pImage->CmdSN);
    17901804    aReqBHS[7] = RT_H2N_U32(pImage->ExpStatSN);
    1791     memcpy(aReqBHS + 8, pRequest->pvCmd, pRequest->cbCmd);
     1805    memcpy(aReqBHS + 8, pRequest->pvCDB, pRequest->cbCDB);
    17921806    pImage->CmdSN++;
    17931807
     
    26312645    paReqBHS[6] = RT_H2N_U32(pImage->CmdSN);
    26322646    paReqBHS[7] = RT_H2N_U32(pImage->ExpStatSN);
    2633     memcpy(paReqBHS + 8, pScsiReq->pvCmd, pScsiReq->cbCmd);
     2647    memcpy(paReqBHS + 8, pScsiReq->pvCDB, pScsiReq->cbCDB);
    26342648
    26352649    pIScsiPDU->CmdSN = pImage->CmdSN;
     
    36053619 * delete the image from disk.
    36063620 */
    3607 static void iscsiFreeImage(PISCSIIMAGE pImage, bool fDelete)
    3608 {
    3609     Assert(pImage);
     3621static int iscsiFreeImage(PISCSIIMAGE pImage, bool fDelete)
     3622{
     3623    int rc = VINF_SUCCESS;
    36103624    Assert(!fDelete); /* This MUST be false, the flag isn't supported. */
    36113625
    3612     if (pImage->Mutex != NIL_RTSEMMUTEX)
    3613     {
    3614         /* Detaching only makes sense when the mutex is there. Otherwise the
    3615          * failure happened long before we could attach to the target. */
    3616         iscsiExecSync(pImage, iscsiDetach, pImage);
    3617         RTSemMutexDestroy(pImage->Mutex);
    3618         pImage->Mutex = NIL_RTSEMMUTEX;
    3619     }
    3620     if (pImage->hThreadIo != NIL_RTTHREAD)
    3621     {
    3622         int rc;
    3623 
    3624         ASMAtomicXchgBool(&pImage->fRunning, false);
    3625         rc = iscsiIoThreadPoke(pImage);
    3626         AssertRC(rc);
    3627 
    3628         /* Wait for the thread to terminate. */
    3629         rc = RTThreadWait(pImage->hThreadIo, RT_INDEFINITE_WAIT, NULL);
    3630         AssertRC(rc);
    3631     }
    3632     /* Destroy the socket. */
    3633     if (pImage->Socket != NIL_VDSOCKET)
    3634     {
    3635         pImage->pInterfaceNetCallbacks->pfnSocketDestroy(pImage->Socket);
    3636     }
    3637     if (pImage->MutexReqQueue != NIL_RTSEMMUTEX)
    3638     {
    3639         RTSemMutexDestroy(pImage->MutexReqQueue);
    3640         pImage->MutexReqQueue = NIL_RTSEMMUTEX;
    3641     }
    3642     if (pImage->pszTargetName)
    3643     {
    3644         RTMemFree(pImage->pszTargetName);
    3645         pImage->pszTargetName = NULL;
    3646     }
    3647     if (pImage->pszInitiatorName)
    3648     {
    3649         if (pImage->fAutomaticInitiatorName)
    3650             RTStrFree(pImage->pszInitiatorName);
    3651         else
    3652             RTMemFree(pImage->pszInitiatorName);
    3653         pImage->pszInitiatorName = NULL;
    3654     }
    3655     if (pImage->pszInitiatorUsername)
    3656     {
    3657         RTMemFree(pImage->pszInitiatorUsername);
    3658         pImage->pszInitiatorUsername = NULL;
    3659     }
    3660     if (pImage->pbInitiatorSecret)
    3661     {
    3662         RTMemFree(pImage->pbInitiatorSecret);
    3663         pImage->pbInitiatorSecret = NULL;
    3664     }
    3665     if (pImage->pszTargetUsername)
    3666     {
    3667         RTMemFree(pImage->pszTargetUsername);
    3668         pImage->pszTargetUsername = NULL;
    3669     }
    3670     if (pImage->pbTargetSecret)
    3671     {
    3672         RTMemFree(pImage->pbTargetSecret);
    3673         pImage->pbTargetSecret = NULL;
    3674     }
    3675     if (pImage->pvRecvPDUBuf)
    3676     {
    3677         RTMemFree(pImage->pvRecvPDUBuf);
    3678         pImage->pvRecvPDUBuf = NULL;
    3679     }
     3626    /* Freeing a never allocated image (e.g. because the open failed) is
     3627     * not signalled as an error. After all nothing bad happens. */
     3628    if (pImage)
     3629    {
     3630        if (pImage->Mutex != NIL_RTSEMMUTEX)
     3631        {
     3632            /* Detaching only makes sense when the mutex is there. Otherwise the
     3633             * failure happened long before we could attach to the target. */
     3634            iscsiExecSync(pImage, iscsiDetach, pImage);
     3635            RTSemMutexDestroy(pImage->Mutex);
     3636            pImage->Mutex = NIL_RTSEMMUTEX;
     3637        }
     3638        if (pImage->hThreadIo != NIL_RTTHREAD)
     3639        {
     3640            ASMAtomicXchgBool(&pImage->fRunning, false);
     3641            rc = iscsiIoThreadPoke(pImage);
     3642            AssertRC(rc);
     3643
     3644            /* Wait for the thread to terminate. */
     3645            rc = RTThreadWait(pImage->hThreadIo, RT_INDEFINITE_WAIT, NULL);
     3646            AssertRC(rc);
     3647        }
     3648        /* Destroy the socket. */
     3649        if (pImage->Socket != NIL_VDSOCKET)
     3650        {
     3651            pImage->pInterfaceNetCallbacks->pfnSocketDestroy(pImage->Socket);
     3652        }
     3653        if (pImage->MutexReqQueue != NIL_RTSEMMUTEX)
     3654        {
     3655            RTSemMutexDestroy(pImage->MutexReqQueue);
     3656            pImage->MutexReqQueue = NIL_RTSEMMUTEX;
     3657        }
     3658        if (pImage->pszTargetName)
     3659        {
     3660            RTMemFree(pImage->pszTargetName);
     3661            pImage->pszTargetName = NULL;
     3662        }
     3663        if (pImage->pszInitiatorName)
     3664        {
     3665            if (pImage->fAutomaticInitiatorName)
     3666                RTStrFree(pImage->pszInitiatorName);
     3667            else
     3668                RTMemFree(pImage->pszInitiatorName);
     3669            pImage->pszInitiatorName = NULL;
     3670        }
     3671        if (pImage->pszInitiatorUsername)
     3672        {
     3673            RTMemFree(pImage->pszInitiatorUsername);
     3674            pImage->pszInitiatorUsername = NULL;
     3675        }
     3676        if (pImage->pbInitiatorSecret)
     3677        {
     3678            RTMemFree(pImage->pbInitiatorSecret);
     3679            pImage->pbInitiatorSecret = NULL;
     3680        }
     3681        if (pImage->pszTargetUsername)
     3682        {
     3683            RTMemFree(pImage->pszTargetUsername);
     3684            pImage->pszTargetUsername = NULL;
     3685        }
     3686        if (pImage->pbTargetSecret)
     3687        {
     3688            RTMemFree(pImage->pbTargetSecret);
     3689            pImage->pbTargetSecret = NULL;
     3690        }
     3691        if (pImage->pvRecvPDUBuf)
     3692        {
     3693            RTMemFree(pImage->pvRecvPDUBuf);
     3694            pImage->pvRecvPDUBuf = NULL;
     3695        }
     3696    }
     3697
     3698    LogFlowFunc(("returns %Rrc\n", rc));
     3699    return rc;
    36803700}
    36813701
     
    39994019     * Inquire available LUNs - purely dummy request.
    40004020     */
    4001     uint8_t cdb_rlun[12];
     4021    uint8_t CDB_rlun[12];
    40024022    uint8_t rlundata[16];
    4003     cdb_rlun[0] = SCSI_REPORT_LUNS;
    4004     cdb_rlun[1] = 0;        /* reserved */
    4005     cdb_rlun[2] = 0;        /* reserved */
    4006     cdb_rlun[3] = 0;        /* reserved */
    4007     cdb_rlun[4] = 0;        /* reserved */
    4008     cdb_rlun[5] = 0;        /* reserved */
    4009     cdb_rlun[6] = sizeof(rlundata) >> 24;
    4010     cdb_rlun[7] = (sizeof(rlundata) >> 16) & 0xff;
    4011     cdb_rlun[8] = (sizeof(rlundata) >> 8) & 0xff;
    4012     cdb_rlun[9] = sizeof(rlundata) & 0xff;
    4013     cdb_rlun[10] = 0;       /* reserved */
    4014     cdb_rlun[11] = 0;       /* control */
     4023    CDB_rlun[0] = SCSI_REPORT_LUNS;
     4024    CDB_rlun[1] = 0;        /* reserved */
     4025    CDB_rlun[2] = 0;        /* reserved */
     4026    CDB_rlun[3] = 0;        /* reserved */
     4027    CDB_rlun[4] = 0;        /* reserved */
     4028    CDB_rlun[5] = 0;        /* reserved */
     4029    CDB_rlun[6] = sizeof(rlundata) >> 24;
     4030    CDB_rlun[7] = (sizeof(rlundata) >> 16) & 0xff;
     4031    CDB_rlun[8] = (sizeof(rlundata) >> 8) & 0xff;
     4032    CDB_rlun[9] = sizeof(rlundata) & 0xff;
     4033    CDB_rlun[10] = 0;       /* reserved */
     4034    CDB_rlun[11] = 0;       /* control */
    40154035
    40164036    DataSeg.pvSeg = rlundata;
     
    40184038
    40194039    sr.enmXfer = SCSIXFER_FROM_TARGET;
    4020     sr.cbCmd = sizeof(cdb_rlun);
    4021     sr.pvCmd = cdb_rlun;
     4040    sr.cbCDB = sizeof(CDB_rlun);
     4041    sr.pvCDB = CDB_rlun;
    40224042    sr.cbI2TData = 0;
    40234043    sr.paI2TSegs = NULL;
     
    40394059     * Inquire device characteristics - no tapes, scanners etc., please.
    40404060     */
    4041     uint8_t cdb_inq[6];
    4042     cdb_inq[0] = SCSI_INQUIRY;
    4043     cdb_inq[1] = 0;         /* reserved */
    4044     cdb_inq[2] = 0;         /* reserved */
    4045     cdb_inq[3] = 0;         /* reserved */
    4046     cdb_inq[4] = sizeof(data8);
    4047     cdb_inq[5] = 0;         /* control */
     4061    uint8_t CDB_inq[6];
     4062    CDB_inq[0] = SCSI_INQUIRY;
     4063    CDB_inq[1] = 0;         /* reserved */
     4064    CDB_inq[2] = 0;         /* reserved */
     4065    CDB_inq[3] = 0;         /* reserved */
     4066    CDB_inq[4] = sizeof(data8);
     4067    CDB_inq[5] = 0;         /* control */
    40484068
    40494069    DataSeg.pvSeg = data8;
     
    40514071
    40524072    sr.enmXfer = SCSIXFER_FROM_TARGET;
    4053     sr.cbCmd = sizeof(cdb_inq);
    4054     sr.pvCmd = cdb_inq;
     4073    sr.cbCDB = sizeof(CDB_inq);
     4074    sr.pvCDB = CDB_inq;
    40554075    sr.cbI2TData = 0;
    40564076    sr.paI2TSegs = NULL;
     
    40994119     */
    41004120
    4101     uint8_t cdb_ms[6];
     4121    uint8_t CDB_ms[6];
    41024122    uint8_t data4[4];
    4103     cdb_ms[0] = SCSI_MODE_SENSE_6;
    4104     cdb_ms[1] = 0;          /* dbd=0/reserved */
    4105     cdb_ms[2] = 0x3f;       /* pc=0/page code=0x3f, ask for all pages */
    4106     cdb_ms[3] = 0;          /* subpage code=0, return everything in page_0 format */
    4107     cdb_ms[4] = sizeof(data4); /* allocation length=4 */
    4108     cdb_ms[5] = 0;          /* control */
     4123    CDB_ms[0] = SCSI_MODE_SENSE_6;
     4124    CDB_ms[1] = 0;          /* dbd=0/reserved */
     4125    CDB_ms[2] = 0x3f;       /* pc=0/page code=0x3f, ask for all pages */
     4126    CDB_ms[3] = 0;          /* subpage code=0, return everything in page_0 format */
     4127    CDB_ms[4] = sizeof(data4); /* allocation length=4 */
     4128    CDB_ms[5] = 0;          /* control */
    41094129
    41104130    DataSeg.pvSeg = data4;
     
    41124132
    41134133    sr.enmXfer = SCSIXFER_FROM_TARGET;
    4114     sr.cbCmd = sizeof(cdb_ms);
    4115     sr.pvCmd = cdb_ms;
     4134    sr.cbCDB = sizeof(CDB_ms);
     4135    sr.pvCDB = CDB_ms;
    41164136    sr.cbI2TData = 0;
    41174137    sr.paI2TSegs = NULL;
     
    41414161     * Determine sector size and capacity of the volume immediately.
    41424162     */
    4143     uint8_t cdb_cap[16];
     4163    uint8_t CDB_cap[16];
    41444164
    41454165    RT_ZERO(data12);
    4146     RT_ZERO(cdb_cap);
    4147     cdb_cap[0] = SCSI_SERVICE_ACTION_IN_16;
    4148     cdb_cap[1] = SCSI_SVC_ACTION_IN_READ_CAPACITY_16;   /* subcommand */
    4149     cdb_cap[10+3] = sizeof(data12);                     /* allocation length (dword) */
     4166    RT_ZERO(CDB_cap);
     4167    CDB_cap[0] = SCSI_SERVICE_ACTION_IN_16;
     4168    CDB_cap[1] = SCSI_SVC_ACTION_IN_READ_CAPACITY_16;   /* subcommand */
     4169    CDB_cap[10+3] = sizeof(data12);                     /* allocation length (dword) */
    41504170
    41514171    DataSeg.pvSeg = data12;
     
    41534173
    41544174    sr.enmXfer = SCSIXFER_FROM_TARGET;
    4155     sr.cbCmd = sizeof(cdb_cap);
    4156     sr.pvCmd = cdb_cap;
     4175    sr.cbCDB = sizeof(CDB_cap);
     4176    sr.pvCDB = CDB_cap;
    41574177    sr.cbI2TData = 0;
    41584178    sr.paI2TSegs = NULL;
     
    41824202    else
    41834203    {
    4184         uint8_t cdb_capfb[10];
     4204        uint8_t CDB_capfb[10];
    41854205
    41864206        RT_ZERO(data8);
    4187         cdb_capfb[0] = SCSI_READ_CAPACITY;
    4188         cdb_capfb[1] = 0;   /* reserved */
    4189         cdb_capfb[2] = 0;   /* reserved */
    4190         cdb_capfb[3] = 0;   /* reserved */
    4191         cdb_capfb[4] = 0;   /* reserved */
    4192         cdb_capfb[5] = 0;   /* reserved */
    4193         cdb_capfb[6] = 0;   /* reserved */
    4194         cdb_capfb[7] = 0;   /* reserved */
    4195         cdb_capfb[8] = 0;   /* reserved */
    4196         cdb_capfb[9] = 0;   /* control */
     4207        CDB_capfb[0] = SCSI_READ_CAPACITY;
     4208        CDB_capfb[1] = 0;   /* reserved */
     4209        CDB_capfb[2] = 0;   /* reserved */
     4210        CDB_capfb[3] = 0;   /* reserved */
     4211        CDB_capfb[4] = 0;   /* reserved */
     4212        CDB_capfb[5] = 0;   /* reserved */
     4213        CDB_capfb[6] = 0;   /* reserved */
     4214        CDB_capfb[7] = 0;   /* reserved */
     4215        CDB_capfb[8] = 0;   /* reserved */
     4216        CDB_capfb[9] = 0;   /* control */
    41974217
    41984218        DataSeg.pvSeg = data8;
     
    42004220
    42014221        sr.enmXfer = SCSIXFER_FROM_TARGET;
    4202         sr.cbCmd = sizeof(cdb_capfb);
    4203         sr.pvCmd = cdb_capfb;
     4222        sr.cbCDB = sizeof(CDB_capfb);
     4223        sr.pvCDB = CDB_capfb;
    42044224        sr.cbI2TData = 0;
    42054225        sr.paI2TSegs = NULL;
     
    42554275
    42564276    sr.enmXfer = SCSIXFER_FROM_TARGET;
    4257     sr.cbCmd = sizeof(aCDBModeSense6);
    4258     sr.pvCmd = aCDBModeSense6;
     4277    sr.cbCDB = sizeof(aCDBModeSense6);
     4278    sr.pvCDB = aCDBModeSense6;
    42594279    sr.cbI2TData = 0;
    42604280    sr.paI2TSegs = NULL;
     
    43004320
    43014321            sr.enmXfer = SCSIXFER_TO_TARGET;
    4302             sr.cbCmd = sizeof(aCDBCaching);
    4303             sr.pvCmd = aCDBCaching;
     4322            sr.cbCDB = sizeof(aCDBCaching);
     4323            sr.pvCDB = aCDBCaching;
    43044324            sr.cbI2TData = DataSeg.cbSeg;
    43054325            sr.paI2TSegs = &DataSeg;
     
    43434363
    43444364/** @copydoc VBOXHDDBACKEND::pfnCheckIfValid */
    4345 static int iscsiCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk)
     4365static int iscsiCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk,
     4366                             PVDINTERFACE pVDIfsImage)
    43464367{
    43474368    LogFlowFunc(("pszFilename=\"%s\"\n", pszFilename));
     
    43494370    /* iSCSI images can't be checked for validity this way, as the filename
    43504371     * just can't supply enough configuration information. */
    4351     int rc = VERR_VD_ISCSI_INVALID_HEADER;
     4372    int rc = VERR_NOT_SUPPORTED;
    43524373
    43534374    LogFlowFunc(("returns %Rrc\n", rc));
    43544375    return rc;
    43554376}
    4356 
    43574377
    43584378/** @copydoc VBOXHDDBACKEND::pfnOpen */
     
    44094429        *ppBackendData = pImage;
    44104430    }
     4431    else
     4432        RTMemFree(pImage);
    44114433
    44124434out:
     
    44154437}
    44164438
    4417 
    44184439/** @copydoc VBOXHDDBACKEND::pfnCreate */
    44194440static int iscsiCreate(const char *pszFilename, uint64_t cbSize,
    44204441                       unsigned uImageFlags, const char *pszComment,
    4421                        PCPDMMEDIAGEOMETRY pPCHSGeometry,
    4422                        PCPDMMEDIAGEOMETRY pLCHSGeometry, PCRTUUID pUuid,
    4423                        unsigned uOpenFlags, unsigned uPercentStart,
    4424                        unsigned uPercentSpan, PVDINTERFACE pVDIfsDisk,
    4425                        PVDINTERFACE pVDIfsImage, PVDINTERFACE pVDIfsOperation,
    4426                        void **ppBackendData)
     4442                       PCVDGEOMETRY pPCHSGeometry, PCVDGEOMETRY pLCHSGeometry,
     4443                       PCRTUUID pUuid, unsigned uOpenFlags,
     4444                       unsigned uPercentStart, unsigned uPercentSpan,
     4445                       PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
     4446                       PVDINTERFACE pVDIfsOperation, void **ppBackendData)
    44274447{
    44284448    LogFlowFunc(("pszFilename=\"%s\" cbSize=%llu uImageFlags=%#x pszComment=\"%s\" pPCHSGeometry=%#p pLCHSGeometry=%#p Uuid=%RTuuid uOpenFlags=%#x uPercentStart=%u uPercentSpan=%u pVDIfsDisk=%#p pVDIfsImage=%#p pVDIfsOperation=%#p ppBackendData=%#p", pszFilename, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, ppBackendData));
     
    44334453}
    44344454
    4435 
    4436 /** @copydoc VBOXHDDBACKEND::pfnRename */
    4437 static int iscsiRename(void *pBackendData, const char *pszFilename)
    4438 {
    4439     LogFlowFunc(("pBackendData=%#p pszFilename=%#p\n", pBackendData, pszFilename));
    4440     int rc = VERR_NOT_SUPPORTED;
     4455/** @copydoc VBOXHDDBACKEND::pfnClose */
     4456static int iscsiClose(void *pBackendData, bool fDelete)
     4457{
     4458    LogFlowFunc(("pBackendData=%#p fDelete=%d\n", pBackendData, fDelete));
     4459    PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
     4460    int rc;
     4461
     4462    Assert(!fDelete);   /* This flag is unsupported. */
     4463
     4464    rc = iscsiFreeImage(pImage, fDelete);
     4465    RTMemFree(pImage);
    44414466
    44424467    LogFlowFunc(("returns %Rrc\n", rc));
    44434468    return rc;
    44444469}
    4445 
    4446 
    4447 /** @copydoc VBOXHDDBACKEND::pfnClose */
    4448 static int iscsiClose(void *pBackendData, bool fDelete)
    4449 {
    4450     LogFlowFunc(("pBackendData=%#p fDelete=%d\n", pBackendData, fDelete));
    4451     PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
    4452     int rc = VINF_SUCCESS;
    4453 
    4454     Assert(!fDelete);   /* This flag is unsupported. */
    4455 
    4456     /* Freeing a never allocated image (e.g. because the open failed) is
    4457      * not signalled as an error. After all nothing bad happens. */
    4458     if (pImage)
    4459         iscsiFreeImage(pImage, fDelete);
    4460 
    4461     LogFlowFunc(("returns %Rrc\n", rc));
    4462     return rc;
    4463 }
    4464 
    44654470
    44664471/** @copydoc VBOXHDDBACKEND::pfnRead */
     
    44984503    SCSIREQ sr;
    44994504    RTSGSEG T2ISeg;
    4500     uint8_t cdb[10];
     4505    size_t cbCDB;
     4506    uint8_t abCDB[16];
    45014507    uint8_t sense[96];
    45024508
    4503     cdb[0] = SCSI_READ_10;
    4504     cdb[1] = 0;         /* reserved */
    4505     cdb[2] = (lba >> 24) & 0xff;
    4506     cdb[3] = (lba >> 16) & 0xff;
    4507     cdb[4] = (lba >> 8) & 0xff;
    4508     cdb[5] = lba & 0xff;
    4509     cdb[6] = 0;         /* reserved */
    4510     cdb[7] = (tls >> 8) & 0xff;
    4511     cdb[8] = tls & 0xff;
    4512     cdb[9] = 0;         /* control */
     4509    if (pImage->cVolume < _4G)
     4510    {
     4511        cbCDB = 10;
     4512        abCDB[0] = SCSI_READ_10;
     4513        abCDB[1] = 0;       /* reserved */
     4514        abCDB[2] = (lba >> 24) & 0xff;
     4515        abCDB[3] = (lba >> 16) & 0xff;
     4516        abCDB[4] = (lba >> 8) & 0xff;
     4517        abCDB[5] = lba & 0xff;
     4518        abCDB[6] = 0;       /* reserved */
     4519        abCDB[7] = (tls >> 8) & 0xff;
     4520        abCDB[8] = tls & 0xff;
     4521        abCDB[9] = 0;       /* control */
     4522    }
     4523    else
     4524    {
     4525        cbCDB = 16;
     4526        abCDB[0] = SCSI_READ_16;
     4527        abCDB[1] = 0;       /* reserved */
     4528        abCDB[2] = (lba >> 56) & 0xff;
     4529        abCDB[3] = (lba >> 48) & 0xff;
     4530        abCDB[4] = (lba >> 40) & 0xff;
     4531        abCDB[5] = (lba >> 32) & 0xff;
     4532        abCDB[6] = (lba >> 24) & 0xff;
     4533        abCDB[7] = (lba >> 16) & 0xff;
     4534        abCDB[8] = (lba >> 8) & 0xff;
     4535        abCDB[9] = lba & 0xff;
     4536        abCDB[10] = 0;      /* tls unused */
     4537        abCDB[11] = 0;      /* tls unused */
     4538        abCDB[12] = (tls >> 8) & 0xff;
     4539        abCDB[13] = tls & 0xff;
     4540        abCDB[14] = 0;      /* reserved */
     4541        abCDB[15] = 0;      /* reserved */
     4542    }
    45134543
    45144544    T2ISeg.pvSeg = pvBuf;
     
    45164546
    45174547    sr.enmXfer   = SCSIXFER_FROM_TARGET;
    4518     sr.cbCmd     = sizeof(cdb);
    4519     sr.pvCmd     = cdb;
     4548    sr.cbCDB     = cbCDB;
     4549    sr.pvCDB     = abCDB;
    45204550    sr.cbI2TData = 0;
    45214551    sr.paI2TSegs = NULL;
     
    45414571}
    45424572
    4543 
    45444573/** @copydoc VBOXHDDBACKEND::pfnWrite */
    45454574static int iscsiWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf,
     
    45784607    SCSIREQ sr;
    45794608    RTSGSEG I2TSeg;
    4580     uint8_t cdb[10];
     4609    size_t cbCDB;
     4610    uint8_t abCDB[16];
    45814611    uint8_t sense[96];
    45824612
    4583     cdb[0] = SCSI_WRITE_10;
    4584     cdb[1] = 0;         /* reserved */
    4585     cdb[2] = (lba >> 24) & 0xff;
    4586     cdb[3] = (lba >> 16) & 0xff;
    4587     cdb[4] = (lba >> 8) & 0xff;
    4588     cdb[5] = lba & 0xff;
    4589     cdb[6] = 0;         /* reserved */
    4590     cdb[7] = (tls >> 8) & 0xff;
    4591     cdb[8] = tls & 0xff;
    4592     cdb[9] = 0;         /* control */
     4613    if (pImage->cVolume < _4G)
     4614    {
     4615        cbCDB = 10;
     4616        abCDB[0] = SCSI_WRITE_10;
     4617        abCDB[1] = 0;       /* reserved */
     4618        abCDB[2] = (lba >> 24) & 0xff;
     4619        abCDB[3] = (lba >> 16) & 0xff;
     4620        abCDB[4] = (lba >> 8) & 0xff;
     4621        abCDB[5] = lba & 0xff;
     4622        abCDB[6] = 0;       /* reserved */
     4623        abCDB[7] = (tls >> 8) & 0xff;
     4624        abCDB[8] = tls & 0xff;
     4625        abCDB[9] = 0;       /* control */
     4626    }
     4627    else
     4628    {
     4629        cbCDB = 16;
     4630        abCDB[0] = SCSI_WRITE_16;
     4631        abCDB[1] = 0;       /* reserved */
     4632        abCDB[2] = (lba >> 56) & 0xff;
     4633        abCDB[3] = (lba >> 48) & 0xff;
     4634        abCDB[4] = (lba >> 40) & 0xff;
     4635        abCDB[5] = (lba >> 32) & 0xff;
     4636        abCDB[6] = (lba >> 24) & 0xff;
     4637        abCDB[7] = (lba >> 16) & 0xff;
     4638        abCDB[8] = (lba >> 8) & 0xff;
     4639        abCDB[9] = lba & 0xff;
     4640        abCDB[10] = 0;      /* tls unused */
     4641        abCDB[11] = 0;      /* tls unused */
     4642        abCDB[12] = (tls >> 8) & 0xff;
     4643        abCDB[13] = tls & 0xff;
     4644        abCDB[14] = 0;      /* reserved */
     4645        abCDB[15] = 0;      /* reserved */
     4646    }
    45934647
    45944648    I2TSeg.pvSeg = (void *)pvBuf;
     
    45964650
    45974651    sr.enmXfer              = SCSIXFER_TO_TARGET;
    4598     sr.cbCmd                = sizeof(cdb);
    4599     sr.pvCmd                = cdb;
     4652    sr.cbCDB                = cbCDB;
     4653    sr.pvCDB                = abCDB;
    46004654    sr.cbI2TData            = cbToWrite;
    46014655    sr.paI2TSegs            = &I2TSeg;
     
    46214675}
    46224676
    4623 
    46244677/** @copydoc VBOXHDDBACKEND::pfnFlush */
    46254678static int iscsiFlush(void *pBackendData)
     
    46324685
    46334686    SCSIREQ sr;
    4634     uint8_t cdb[10];
     4687    uint8_t abCDB[10];
    46354688    uint8_t sense[96];
    46364689
    4637     cdb[0] = SCSI_SYNCHRONIZE_CACHE;
    4638     cdb[1] = 0;         /* reserved */
    4639     cdb[2] = 0;         /* LBA 0 */
    4640     cdb[3] = 0;         /* LBA 0 */
    4641     cdb[4] = 0;         /* LBA 0 */
    4642     cdb[5] = 0;         /* LBA 0 */
    4643     cdb[6] = 0;         /* reserved */
    4644     cdb[7] = 0;         /* transfer everything to disk */
    4645     cdb[8] = 0;         /* transfer everything to disk */
    4646     cdb[9] = 0;         /* control */
     4690    abCDB[0] = SCSI_SYNCHRONIZE_CACHE;
     4691    abCDB[1] = 0;       /* reserved */
     4692    abCDB[2] = 0;       /* LBA 0 */
     4693    abCDB[3] = 0;       /* LBA 0 */
     4694    abCDB[4] = 0;       /* LBA 0 */
     4695    abCDB[5] = 0;       /* LBA 0 */
     4696    abCDB[6] = 0;       /* reserved */
     4697    abCDB[7] = 0;       /* transfer everything to disk */
     4698    abCDB[8] = 0;       /* transfer everything to disk */
     4699    abCDB[9] = 0;       /* control */
    46474700
    46484701    sr.enmXfer   = SCSIXFER_NONE;
    4649     sr.cbCmd     = sizeof(cdb);
    4650     sr.pvCmd     = cdb;
     4702    sr.cbCDB     = sizeof(abCDB);
     4703    sr.pvCDB     = abCDB;
    46514704    sr.cbI2TData = 0;
    46524705    sr.paI2TSegs = NULL;
     
    46654718}
    46664719
    4667 
    46684720/** @copydoc VBOXHDDBACKEND::pfnGetVersion */
    46694721static unsigned iscsiGetVersion(void *pBackendData)
     
    46774729    return 0;
    46784730}
    4679 
    46804731
    46814732/** @copydoc VBOXHDDBACKEND::pfnGetSize */
     
    46934744}
    46944745
    4695 
    46964746/** @copydoc VBOXHDDBACKEND::pfnGetFileSize */
    46974747static uint64_t iscsiGetFileSize(void *pBackendData)
     
    47094759}
    47104760
    4711 
    47124761/** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */
    4713 static int iscsiGetPCHSGeometry(void *pBackendData,
    4714                                 PPDMMEDIAGEOMETRY pPCHSGeometry)
     4762static int iscsiGetPCHSGeometry(void *pBackendData, PVDGEOMETRY pPCHSGeometry)
    47154763{
    47164764    LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry));
     
    47294777}
    47304778
    4731 
    47324779/** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */
    4733 static int iscsiSetPCHSGeometry(void *pBackendData,
    4734                                 PCPDMMEDIAGEOMETRY pPCHSGeometry)
     4780static int iscsiSetPCHSGeometry(void *pBackendData, PCVDGEOMETRY pPCHSGeometry)
    47354781{
    47364782    LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
     
    47574803}
    47584804
    4759 
    47604805/** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */
    4761 static int iscsiGetLCHSGeometry(void *pBackendData,
    4762                                 PPDMMEDIAGEOMETRY pLCHSGeometry)
     4806static int iscsiGetLCHSGeometry(void *pBackendData, PVDGEOMETRY pLCHSGeometry)
    47634807{
    47644808    LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry));
     
    47774821}
    47784822
     4823/** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */
     4824static int iscsiSetLCHSGeometry(void *pBackendData, PCVDGEOMETRY pLCHSGeometry)
     4825{
     4826    LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
     4827    PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
     4828    int rc;
     4829
     4830    Assert(pImage);
     4831
     4832    if (pImage)
     4833    {
     4834        if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     4835        {
     4836            rc = VERR_VD_IMAGE_READ_ONLY;
     4837            goto out;
     4838        }
     4839        rc = VERR_VD_GEOMETRY_NOT_SET;
     4840    }
     4841    else
     4842        rc = VERR_VD_NOT_OPENED;
     4843
     4844out:
     4845    LogFlowFunc(("returns %Rrc\n", rc));
     4846    return rc;
     4847}
    47794848
    47804849/** @copydoc VBOXHDDBACKEND::pfnGetImageFlags */
     
    47934862    return uImageFlags;
    47944863}
    4795 
    47964864
    47974865/** @copydoc VBOXHDDBACKEND::pfnGetOpenFlags */
     
    48134881}
    48144882
    4815 
    48164883/** @copydoc VBOXHDDBACKEND::pfnSetOpenFlags */
    48174884static int iscsiSetOpenFlags(void *pBackendData, unsigned uOpenFlags)
     
    48234890    /* Image must be opened and the new flags must be valid. Just readonly and
    48244891     * info flags are supported. */
    4825     if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO)))
     4892    if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE)))
    48264893    {
    48274894        rc = VERR_INVALID_PARAMETER;
     
    48504917}
    48514918
    4852 
    4853 /** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */
    4854 static int iscsiSetLCHSGeometry(void *pBackendData,
    4855                                 PCPDMMEDIAGEOMETRY pLCHSGeometry)
    4856 {
    4857     LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
    4858     PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
    4859     int rc;
    4860 
    4861     Assert(pImage);
    4862 
    4863     if (pImage)
    4864     {
    4865         if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    4866         {
    4867             rc = VERR_VD_IMAGE_READ_ONLY;
    4868             goto out;
    4869         }
    4870         rc = VERR_VD_GEOMETRY_NOT_SET;
    4871     }
    4872     else
    4873         rc = VERR_VD_NOT_OPENED;
    4874 
    4875 out:
    4876     LogFlowFunc(("returns %Rrc\n", rc));
    4877     return rc;
    4878 }
    4879 
    4880 
    48814919/** @copydoc VBOXHDDBACKEND::pfnGetComment */
    48824920static int iscsiGetComment(void *pBackendData, char *pszComment,
     
    48984936}
    48994937
    4900 
    49014938/** @copydoc VBOXHDDBACKEND::pfnSetComment */
    49024939static int iscsiSetComment(void *pBackendData, const char *pszComment)
     
    49224959}
    49234960
    4924 
    49254961/** @copydoc VBOXHDDBACKEND::pfnGetUuid */
    49264962static int iscsiGetUuid(void *pBackendData, PRTUUID pUuid)
     
    49414977}
    49424978
    4943 
    49444979/** @copydoc VBOXHDDBACKEND::pfnSetUuid */
    49454980static int iscsiSetUuid(void *pBackendData, PCRTUUID pUuid)
     
    49665001}
    49675002
    4968 
    49695003/** @copydoc VBOXHDDBACKEND::pfnGetModificationUuid */
    49705004static int iscsiGetModificationUuid(void *pBackendData, PRTUUID pUuid)
     
    49855019}
    49865020
    4987 
    49885021/** @copydoc VBOXHDDBACKEND::pfnSetModificationUuid */
    49895022static int iscsiSetModificationUuid(void *pBackendData, PCRTUUID pUuid)
     
    50105043}
    50115044
    5012 
    50135045/** @copydoc VBOXHDDBACKEND::pfnGetParentUuid */
    50145046static int iscsiGetParentUuid(void *pBackendData, PRTUUID pUuid)
     
    50295061}
    50305062
    5031 
    50325063/** @copydoc VBOXHDDBACKEND::pfnSetParentUuid */
    50335064static int iscsiSetParentUuid(void *pBackendData, PCRTUUID pUuid)
     
    50545085}
    50555086
    5056 
    50575087/** @copydoc VBOXHDDBACKEND::pfnGetParentModificationUuid */
    50585088static int iscsiGetParentModificationUuid(void *pBackendData, PRTUUID pUuid)
     
    50735103}
    50745104
    5075 
    50765105/** @copydoc VBOXHDDBACKEND::pfnSetParentModificationUuid */
    50775106static int iscsiSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid)
     
    50985127}
    50995128
    5100 
    51015129/** @copydoc VBOXHDDBACKEND::pfnDump */
    51025130static void iscsiDump(void *pBackendData)
     
    51085136    {
    51095137        /** @todo put something useful here */
    5110         pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: cVolume=%u\n", pImage->cVolume);
    5111     }
    5112 }
    5113 
    5114 
    5115 /** @copydoc VBOXHDDBACKEND::pfnGetTimeStamp */
    5116 static int iscsiGetTimeStamp(void *pBackendData, PRTTIMESPEC pTimeStamp)
    5117 {
    5118     LogFlowFunc(("pBackendData=%#p pTimeStamp=%#p\n", pBackendData, pTimeStamp));
     5138        iscsiMessage(pImage, "Header: cVolume=%u\n", pImage->cVolume);
     5139    }
     5140}
     5141
     5142/** @copydoc VBOXHDDBACKEND::pfnIsAsyncIOSupported */
     5143static bool iscsiIsAsyncIOSupported(void *pBackendData)
     5144{
    51195145    PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
    5120     int rc = VERR_NOT_SUPPORTED;
    5121 
    5122     Assert(pImage);
    5123     NOREF(pImage);
    5124 
    5125     LogFlowFunc(("returns %Rrc\n", rc));
    5126     return rc;
    5127 }
    5128 
    5129 
    5130 /** @copydoc VBOXHDDBACKEND::pfnGetParentTimeStamp */
    5131 static int iscsiGetParentTimeStamp(void *pBackendData, PRTTIMESPEC pTimeStamp)
    5132 {
    5133     LogFlowFunc(("pBackendData=%#p pTimeStamp=%#p\n", pBackendData, pTimeStamp));
     5146    return pImage->fCmdQueuingSupported;
     5147}
     5148
     5149/** @copydoc VBOXHDDBACKEND::pfnAsyncRead */
     5150static int iscsiAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbToRead,
     5151                          PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
     5152{
     5153    LogFlowFunc(("pBackendData=%p uOffset=%#llx pIoCtx=%#p cbToRead=%u pcbActuallyRead=%p\n",
     5154                 pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead));
    51345155    PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
    5135     int rc = VERR_NOT_SUPPORTED;
    5136 
    5137     Assert(pImage);
    5138     NOREF(pImage);
    5139 
    5140     LogFlowFunc(("returns %Rrc\n", rc));
    5141     return rc;
    5142 }
    5143 
    5144 
    5145 /** @copydoc VBOXHDDBACKEND::pfnSetParentTimeStamp */
    5146 static int iscsiSetParentTimeStamp(void *pBackendData, PCRTTIMESPEC pTimeStamp)
    5147 {
    5148     LogFlowFunc(("pBackendData=%#p pTimeStamp=%#p\n", pBackendData, pTimeStamp));
    5149     PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
    5150     int rc = VERR_NOT_SUPPORTED;
    5151 
    5152     Assert(pImage);
    5153     NOREF(pImage);
    5154 
    5155     LogFlowFunc(("returns %Rrc\n", rc));
    5156     return rc;
    5157 }
    5158 
    5159 
    5160 /** @copydoc VBOXHDDBACKEND::pfnGetParentFilename */
    5161 static int iscsiGetParentFilename(void *pBackendData, char **ppszParentFilename)
    5162 {
    5163     LogFlowFunc(("pBackendData=%#p ppszParentFilename=%#p\n", pBackendData, ppszParentFilename));
    5164     PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
    5165     int rc = VERR_NOT_SUPPORTED;
    5166 
    5167     Assert(pImage);
    5168     NOREF(pImage);
    5169 
    5170     LogFlowFunc(("returns %Rrc\n", rc));
    5171     return rc;
    5172 }
    5173 
    5174 
    5175 /** @copydoc VBOXHDDBACKEND::pfnSetParentFilename */
    5176 static int iscsiSetParentFilename(void *pBackendData, const char *pszParentFilename)
    5177 {
    5178     LogFlowFunc(("pBackendData=%#p pszParentFilename=%s\n", pBackendData, pszParentFilename));
    5179     PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
    5180     int rc = VERR_NOT_SUPPORTED;
    5181 
    5182     Assert(pImage);
    5183     NOREF(pImage);
    5184 
    5185     LogFlowFunc(("returns %Rrc\n", rc));
    5186     return rc;
    5187 }
    5188 
    5189 /** @copydoc VBOXHDDBACKEND::pfnComposeLocation */
    5190 static int iscsiComposeLocation(PVDINTERFACE pConfig, char **pszLocation)
    5191 {
    5192     char *pszTarget  = NULL;
    5193     char *pszLUN     = NULL;
    5194     char *pszAddress = NULL;
    5195     int rc = VDCFGQueryStringAlloc(VDGetInterfaceConfig(pConfig), pConfig->pvUser, "TargetName", &pszTarget);
    5196     if (RT_SUCCESS(rc))
    5197     {
    5198         rc = VDCFGQueryStringAlloc(VDGetInterfaceConfig(pConfig), pConfig->pvUser, "LUN", &pszLUN);
    5199         if (RT_SUCCESS(rc))
    5200         {
    5201             rc = VDCFGQueryStringAlloc(VDGetInterfaceConfig(pConfig), pConfig->pvUser, "TargetAddress", &pszAddress);
    5202             if (RT_SUCCESS(rc))
    5203             {
    5204                 if (RTStrAPrintf(pszLocation, "iscsi://%s/%s/%s",
    5205                                  pszAddress, pszTarget, pszLUN) < 0)
    5206                     rc = VERR_NO_MEMORY;
    5207             }
    5208         }
    5209     }
    5210     RTMemFree(pszTarget);
    5211     RTMemFree(pszLUN);
    5212     RTMemFree(pszAddress);
    5213     return rc;
    5214 }
    5215 
    5216 /** @copydoc VBOXHDDBACKEND::pfnComposeName */
    5217 static int iscsiComposeName(PVDINTERFACE pConfig, char **pszName)
    5218 {
    5219     char *pszTarget  = NULL;
    5220     char *pszLUN     = NULL;
    5221     char *pszAddress = NULL;
    5222     int rc = VDCFGQueryStringAlloc(VDGetInterfaceConfig(pConfig), pConfig->pvUser, "TargetName", &pszTarget);
    5223     if (RT_SUCCESS(rc))
    5224     {
    5225         rc = VDCFGQueryStringAlloc(VDGetInterfaceConfig(pConfig), pConfig->pvUser, "LUN", &pszLUN);
    5226         if (RT_SUCCESS(rc))
    5227         {
    5228             rc = VDCFGQueryStringAlloc(VDGetInterfaceConfig(pConfig), pConfig->pvUser, "TargetAddress", &pszAddress);
    5229             if (RT_SUCCESS(rc))
    5230             {
    5231                 /** @todo think about a nicer looking location scheme for iSCSI */
    5232                 if (RTStrAPrintf(pszName, "%s/%s/%s",
    5233                                  pszAddress, pszTarget, pszLUN) < 0)
    5234                     rc = VERR_NO_MEMORY;
    5235             }
    5236         }
    5237     }
    5238     RTMemFree(pszTarget);
    5239     RTMemFree(pszLUN);
    5240     RTMemFree(pszAddress);
    5241 
    5242     return rc;
    5243 }
    5244 
    5245 static bool iscsiIsAsyncIOSupported(void *pvBackendData)
    5246 {
    5247     PISCSIIMAGE pImage = (PISCSIIMAGE)pvBackendData;
    5248     return pImage->fCmdQueuingSupported;
    5249 }
    5250 
    5251 static int iscsiAsyncRead(void *pvBackendData, uint64_t uOffset, size_t cbToRead,
    5252                           PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
    5253 {
    5254     PISCSIIMAGE pImage = (PISCSIIMAGE)pvBackendData;
    52555156    int rc = VINF_SUCCESS;
    5256 
    5257     LogFlowFunc(("pBackendData=%p uOffset=%#llx pIoCtx=%#p cbToRead=%u pcbActuallyRead=%p\n",
    5258                      pvBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead));
    52595157
    52605158    if (uOffset + cbToRead > pImage->cbSize)
     
    52835181            uint16_t tls;
    52845182            uint8_t *pbCDB = &pReqAsync->abCDB[0];
     5183            size_t cbCDB;
    52855184
    52865185            lba = uOffset / pImage->cbSector;
     
    52975196            pReqAsync->rcSense       = VERR_READ_ERROR;
    52985197
    5299             pbCDB[0] = SCSI_READ_10;
    5300             pbCDB[1] = 0;         /* reserved */
    5301             pbCDB[2] = (lba >> 24) & 0xff;
    5302             pbCDB[3] = (lba >> 16) & 0xff;
    5303             pbCDB[4] = (lba >> 8) & 0xff;
    5304             pbCDB[5] = lba & 0xff;
    5305             pbCDB[6] = 0;         /* reserved */
    5306             pbCDB[7] = (tls >> 8) & 0xff;
    5307             pbCDB[8] = tls & 0xff;
    5308             pbCDB[9] = 0;         /* control */
     5198            if (pImage->cVolume < _4G)
     5199            {
     5200                cbCDB = 10;
     5201                pbCDB[0] = SCSI_READ_10;
     5202                pbCDB[1] = 0;       /* reserved */
     5203                pbCDB[2] = (lba >> 24) & 0xff;
     5204                pbCDB[3] = (lba >> 16) & 0xff;
     5205                pbCDB[4] = (lba >> 8) & 0xff;
     5206                pbCDB[5] = lba & 0xff;
     5207                pbCDB[6] = 0;       /* reserved */
     5208                pbCDB[7] = (tls >> 8) & 0xff;
     5209                pbCDB[8] = tls & 0xff;
     5210                pbCDB[9] = 0;       /* control */
     5211            }
     5212            else
     5213            {
     5214                cbCDB = 16;
     5215                pbCDB[0] = SCSI_READ_16;
     5216                pbCDB[1] = 0;       /* reserved */
     5217                pbCDB[2] = (lba >> 56) & 0xff;
     5218                pbCDB[3] = (lba >> 48) & 0xff;
     5219                pbCDB[4] = (lba >> 40) & 0xff;
     5220                pbCDB[5] = (lba >> 32) & 0xff;
     5221                pbCDB[6] = (lba >> 24) & 0xff;
     5222                pbCDB[7] = (lba >> 16) & 0xff;
     5223                pbCDB[8] = (lba >> 8) & 0xff;
     5224                pbCDB[9] = lba & 0xff;
     5225                pbCDB[10] = 0;      /* tls unused */
     5226                pbCDB[11] = 0;      /* tls unused */
     5227                pbCDB[12] = (tls >> 8) & 0xff;
     5228                pbCDB[13] = tls & 0xff;
     5229                pbCDB[14] = 0;      /* reserved */
     5230                pbCDB[15] = 0;      /* reserved */
     5231            }
    53095232
    53105233            pReq->enmXfer = SCSIXFER_FROM_TARGET;
    5311             pReq->cbCmd   = sizeof(pReqAsync->abCDB);
    5312             pReq->pvCmd   = pReqAsync->abCDB;
     5234            pReq->cbCDB   = cbCDB;
     5235            pReq->pvCDB   = pReqAsync->abCDB;
    53135236            pReq->cbI2TData = 0;
    53145237            pReq->paI2TSegs = NULL;
     
    53435266}
    53445267
    5345 static int iscsiAsyncWrite(void *pvBackendData, uint64_t uOffset, size_t cbToWrite,
     5268/** @copydoc VBOXHDDBACKEND::pfnAsyncWrite */
     5269static int iscsiAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite,
    53465270                           PVDIOCTX pIoCtx,
    53475271                           size_t *pcbWriteProcess, size_t *pcbPreRead,
    53485272                           size_t *pcbPostRead, unsigned fWrite)
    53495273{
    5350     PISCSIIMAGE pImage = (PISCSIIMAGE)pvBackendData;
     5274    LogFlowFunc(("pBackendData=%p uOffset=%llu pIoCtx=%#p cbToWrite=%u pcbWriteProcess=%p pcbPreRead=%p pcbPostRead=%p fWrite=%u\n",
     5275                 pBackendData, uOffset, pIoCtx, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead, fWrite));
     5276    PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
    53515277    int rc = VINF_SUCCESS;
    5352 
    5353     LogFlowFunc(("pBackendData=%p uOffset=%llu pIoCtx=%#p cbToWrite=%u pcbWriteProcess=%p pcbPreRead=%p pcbPostRead=%p fWrite=%u\n",
    5354                  pvBackendData, uOffset, pIoCtx, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead, fWrite));
    53555278
    53565279    AssertPtr(pImage);
     
    53835306            uint16_t tls;
    53845307            uint8_t *pbCDB = &pReqAsync->abCDB[0];
     5308            size_t cbCDB;
    53855309
    53865310            lba = uOffset / pImage->cbSector;
     
    53975321            pReqAsync->rcSense       = VERR_WRITE_ERROR;
    53985322
    5399             pbCDB[0] = SCSI_WRITE_10;
    5400             pbCDB[1] = 0;         /* reserved */
    5401             pbCDB[2] = (lba >> 24) & 0xff;
    5402             pbCDB[3] = (lba >> 16) & 0xff;
    5403             pbCDB[4] = (lba >> 8) & 0xff;
    5404             pbCDB[5] = lba & 0xff;
    5405             pbCDB[6] = 0;         /* reserved */
    5406             pbCDB[7] = (tls >> 8) & 0xff;
    5407             pbCDB[8] = tls & 0xff;
    5408             pbCDB[9] = 0;         /* control */
     5323            if (pImage->cVolume < _4G)
     5324            {
     5325                cbCDB = 10;
     5326                pbCDB[0] = SCSI_WRITE_10;
     5327                pbCDB[1] = 0;       /* reserved */
     5328                pbCDB[2] = (lba >> 24) & 0xff;
     5329                pbCDB[3] = (lba >> 16) & 0xff;
     5330                pbCDB[4] = (lba >> 8) & 0xff;
     5331                pbCDB[5] = lba & 0xff;
     5332                pbCDB[6] = 0;       /* reserved */
     5333                pbCDB[7] = (tls >> 8) & 0xff;
     5334                pbCDB[8] = tls & 0xff;
     5335                pbCDB[9] = 0;       /* control */
     5336            }
     5337            else
     5338            {
     5339                cbCDB = 16;
     5340                pbCDB[0] = SCSI_WRITE_16;
     5341                pbCDB[1] = 0;       /* reserved */
     5342                pbCDB[2] = (lba >> 56) & 0xff;
     5343                pbCDB[3] = (lba >> 48) & 0xff;
     5344                pbCDB[4] = (lba >> 40) & 0xff;
     5345                pbCDB[5] = (lba >> 32) & 0xff;
     5346                pbCDB[6] = (lba >> 24) & 0xff;
     5347                pbCDB[7] = (lba >> 16) & 0xff;
     5348                pbCDB[8] = (lba >> 8) & 0xff;
     5349                pbCDB[9] = lba & 0xff;
     5350                pbCDB[10] = 0;      /* tls unused */
     5351                pbCDB[11] = 0;      /* tls unused */
     5352                pbCDB[12] = (tls >> 8) & 0xff;
     5353                pbCDB[13] = tls & 0xff;
     5354                pbCDB[14] = 0;      /* reserved */
     5355                pbCDB[15] = 0;      /* reserved */
     5356            }
    54095357
    54105358            pReq->enmXfer = SCSIXFER_TO_TARGET;
    5411             pReq->cbCmd   = sizeof(pReqAsync->abCDB);
    5412             pReq->pvCmd   = pReqAsync->abCDB;
     5359            pReq->cbCDB   = cbCDB;
     5360            pReq->pvCDB   = pReqAsync->abCDB;
    54135361            pReq->cbI2TData = cbToWrite;
    54145362            pReq->paI2TSegs = &pReqAsync->aSegs[0];
     
    54435391}
    54445392
    5445 static int iscsiAsyncFlush(void *pvBackendData, PVDIOCTX pIoCtx)
    5446 {
    5447     PISCSIIMAGE pImage = (PISCSIIMAGE)pvBackendData;
     5393/** @copydoc VBOXHDDBACKEND::pfnAsyncFlush */
     5394static int iscsiAsyncFlush(void *pBackendData, PVDIOCTX pIoCtx)
     5395{
     5396    LogFlowFunc(("pBackendData=%p pIoCtx=%#p\n", pBackendData, pIoCtx));
     5397    PISCSIIMAGE pImage = (PISCSIIMAGE)pBackendData;
    54485398    int rc = VINF_SUCCESS;
    5449 
    5450     LogFlowFunc(("pvBackendData=%p pIoCtx=%#p\n", pvBackendData, pIoCtx));
    54515399
    54525400    PSCSIREQASYNC pReqAsync = (PSCSIREQASYNC)RTMemAllocZ(sizeof(SCSIREQASYNC));
     
    54755423
    54765424            pReq->enmXfer = SCSIXFER_NONE;
    5477             pReq->cbCmd   = sizeof(pReqAsync->abCDB);
    5478             pReq->pvCmd   = pReqAsync->abCDB;
     5425            pReq->cbCDB   = 10;
     5426            pReq->pvCDB   = pReqAsync->abCDB;
    54795427            pReq->cbI2TData = 0;
    54805428            pReq->paI2TSegs = NULL;
     
    55035451
    55045452    LogFlowFunc(("returns rc=%Rrc\n", rc));
     5453    return rc;
     5454}
     5455
     5456/** @copydoc VBOXHDDBACKEND::pfnComposeLocation */
     5457static int iscsiComposeLocation(PVDINTERFACE pConfig, char **pszLocation)
     5458{
     5459    char *pszTarget  = NULL;
     5460    char *pszLUN     = NULL;
     5461    char *pszAddress = NULL;
     5462    int rc = VDCFGQueryStringAlloc(VDGetInterfaceConfig(pConfig), pConfig->pvUser, "TargetName", &pszTarget);
     5463    if (RT_SUCCESS(rc))
     5464    {
     5465        rc = VDCFGQueryStringAlloc(VDGetInterfaceConfig(pConfig), pConfig->pvUser, "LUN", &pszLUN);
     5466        if (RT_SUCCESS(rc))
     5467        {
     5468            rc = VDCFGQueryStringAlloc(VDGetInterfaceConfig(pConfig), pConfig->pvUser, "TargetAddress", &pszAddress);
     5469            if (RT_SUCCESS(rc))
     5470            {
     5471                if (RTStrAPrintf(pszLocation, "iscsi://%s/%s/%s",
     5472                                 pszAddress, pszTarget, pszLUN) < 0)
     5473                    rc = VERR_NO_MEMORY;
     5474            }
     5475        }
     5476    }
     5477    RTMemFree(pszTarget);
     5478    RTMemFree(pszLUN);
     5479    RTMemFree(pszAddress);
     5480    return rc;
     5481}
     5482
     5483/** @copydoc VBOXHDDBACKEND::pfnComposeName */
     5484static int iscsiComposeName(PVDINTERFACE pConfig, char **pszName)
     5485{
     5486    char *pszTarget  = NULL;
     5487    char *pszLUN     = NULL;
     5488    char *pszAddress = NULL;
     5489    int rc = VDCFGQueryStringAlloc(VDGetInterfaceConfig(pConfig), pConfig->pvUser, "TargetName", &pszTarget);
     5490    if (RT_SUCCESS(rc))
     5491    {
     5492        rc = VDCFGQueryStringAlloc(VDGetInterfaceConfig(pConfig), pConfig->pvUser, "LUN", &pszLUN);
     5493        if (RT_SUCCESS(rc))
     5494        {
     5495            rc = VDCFGQueryStringAlloc(VDGetInterfaceConfig(pConfig), pConfig->pvUser, "TargetAddress", &pszAddress);
     5496            if (RT_SUCCESS(rc))
     5497            {
     5498                /** @todo think about a nicer looking location scheme for iSCSI */
     5499                if (RTStrAPrintf(pszName, "%s/%s/%s",
     5500                                 pszAddress, pszTarget, pszLUN) < 0)
     5501                    rc = VERR_NO_MEMORY;
     5502            }
     5503        }
     5504    }
     5505    RTMemFree(pszTarget);
     5506    RTMemFree(pszLUN);
     5507    RTMemFree(pszAddress);
     5508
    55055509    return rc;
    55065510}
     
    55285532    iscsiCreate,
    55295533    /* pfnRename */
    5530     iscsiRename,
     5534    NULL,
    55315535    /* pfnClose */
    55325536    iscsiClose,
     
    55805584    iscsiDump,
    55815585    /* pfnGetTimeStamp */
    5582     iscsiGetTimeStamp,
     5586    NULL,
    55835587    /* pfnGetParentTimeStamp */
    5584     iscsiGetParentTimeStamp,
     5588    NULL,
    55855589    /* pfnSetParentTimeStamp */
    5586     iscsiSetParentTimeStamp,
     5590    NULL,
    55875591    /* pfnGetParentFilename */
    5588     iscsiGetParentFilename,
     5592    NULL,
    55895593    /* pfnSetParentFilename */
    5590     iscsiSetParentFilename,
     5594    NULL,
    55915595    /* pfnIsAsyncIOSupported */
    55925596    iscsiIsAsyncIOSupported,
  • trunk/src/VBox/Devices/Storage/ParallelsHDDCore.cpp

    r31776 r32536  
    1717 */
    1818
    19 #define LOG_GROUP LOG_GROUP_VD_VMDK /** @todo: Logging group */
     19#define LOG_GROUP LOG_GROUP_VD_PARALLELS
    2020#include <VBox/VBoxHDD-Plugin.h>
    2121#include <VBox/err.h>
     
    2323#include <VBox/log.h>
    2424#include <iprt/assert.h>
    25 #include <iprt/alloc.h>
     25#include <iprt/mem.h>
    2626#include <iprt/uuid.h>
    27 #include <iprt/file.h>
    2827#include <iprt/path.h>
    2928#include <iprt/string.h>
     
    6059typedef struct PARALLELSIMAGE
    6160{
     61    /** Image file name. */
     62    const char         *pszFilename;
     63    /** Opaque storage handle. */
     64    PVDIOSTORAGE        pStorage;
     65
     66    /** I/O interface. */
     67    PVDINTERFACE        pInterfaceIO;
     68    /** I/O interface callbacks. */
     69    PVDINTERFACEIO      pInterfaceIOCallbacks;
     70
    6271    /** Pointer to the per-disk VD interface list. */
    6372    PVDINTERFACE        pVDIfsDisk;
     
    6877    /** Error interface callbacks. */
    6978    PVDINTERFACEERROR   pInterfaceErrorCallbacks;
    70 #ifdef VBOX_WITH_NEW_IO_CODE
    71     /** Async I/O interface. */
    72     PVDINTERFACE        pInterfaceIO;
    73     /** Async I/O interface callbacks. */
    74     PVDINTERFACEIO      pInterfaceIOCallbacks;
    75 #endif
    76 
    77     /** Image file name. */
    78     const char         *pszFilename;
    79 #ifndef VBOX_WITH_NEW_IO_CODE
    80     /** File descriptor. */
    81     RTFILE              File;
    82 #else
    83     /** Opaque storage handle. */
    84     PVDIOSTORAGE        pStorage;
    85 #endif
    86     /** Open flags passed by VBoxHD layer. */
     79
     80    /** Open flags passed by VBoxHDD layer. */
    8781    unsigned            uOpenFlags;
    8882    /** Image flags defined during creation or determined during open. */
     
    9084    /** Total size of the image. */
    9185    uint64_t            cbSize;
     86
    9287    /** Physical geometry of this image. */
    93     PDMMEDIAGEOMETRY    PCHSGeometry;
     88    VDGEOMETRY          PCHSGeometry;
    9489    /** Logical geometry of this image. */
    95     PDMMEDIAGEOMETRY    LCHSGeometry;
     90    VDGEOMETRY          LCHSGeometry;
     91
    9692    /** Pointer to the allocation bitmap. */
    9793    uint32_t           *pAllocationBitmap;
     
    134130}
    135131
    136 static int parallelsFileOpen(PPARALLELSIMAGE pImage, bool fReadonly, bool fCreate)
     132/**
     133 * Internal: signal an informational message to the frontend.
     134 */
     135DECLINLINE(int) parallelsMessage(PPARALLELSIMAGE pImage, const char *pszFormat, ...)
    137136{
    138137    int rc = VINF_SUCCESS;
    139 
    140     AssertMsg(!(fReadonly && fCreate), ("Image can't be opened readonly while being created\n"));
    141 
    142 #ifndef VBOX_WITH_NEW_IO_CODE
    143     uint32_t fOpen = fReadonly ? RTFILE_O_READ      | RTFILE_O_DENY_NONE
    144                                : RTFILE_O_READWRITE | RTFILE_O_DENY_WRITE;
    145 
    146     if (fCreate)
    147         fOpen |= RTFILE_O_CREATE;
    148     else
    149         fOpen |= RTFILE_O_OPEN;
    150 
    151     rc = RTFileOpen(&pImage->File, pImage->pszFilename, fOpen);
    152 #else
    153     unsigned uOpenFlags = fReadonly ? VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY : 0;
    154 
    155     if (fCreate)
    156         uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE;
    157 
    158     rc = pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser,
    159                                                 pImage->pszFilename,
    160                                                 uOpenFlags,
    161                                                 &pImage->pStorage);
    162 #endif
    163 
    164     return rc;
    165 }
    166 
    167 static int parallelsFileClose(PPARALLELSIMAGE pImage)
     138    va_list va;
     139    va_start(va, pszFormat);
     140    if (pImage->pInterfaceError && pImage->pInterfaceErrorCallbacks)
     141        rc = pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser,
     142                                                          pszFormat, va);
     143    va_end(va);
     144    return rc;
     145}
     146
     147
     148DECLINLINE(int) parallelsFileOpen(PPARALLELSIMAGE pImage, const char *pszFilename,
     149                                  uint32_t fOpen)
     150{
     151    return pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser,
     152                                                  pszFilename, fOpen,
     153                                                  &pImage->pStorage);
     154}
     155
     156DECLINLINE(int) parallelsFileClose(PPARALLELSIMAGE pImage)
     157{
     158    return pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser,
     159                                                   pImage->pStorage);
     160}
     161
     162DECLINLINE(int) parallelsFileDelete(PPARALLELSIMAGE pImage, const char *pszFilename)
     163{
     164    return pImage->pInterfaceIOCallbacks->pfnDelete(pImage->pInterfaceIO->pvUser,
     165                                                    pszFilename);
     166}
     167
     168DECLINLINE(int) parallelsFileMove(PPARALLELSIMAGE pImage, const char *pszSrc,
     169                                  const char *pszDst, unsigned fMove)
     170{
     171    return pImage->pInterfaceIOCallbacks->pfnMove(pImage->pInterfaceIO->pvUser,
     172                                                  pszSrc, pszDst, fMove);
     173}
     174
     175DECLINLINE(int) parallelsFileGetSize(PPARALLELSIMAGE pImage, uint64_t *pcbSize)
     176{
     177    return pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser,
     178                                                     pImage->pStorage, pcbSize);
     179}
     180
     181DECLINLINE(int) parallelsFileSetSize(PPARALLELSIMAGE pImage, uint64_t cbSize)
     182{
     183    return pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser,
     184                                                     pImage->pStorage, cbSize);
     185}
     186
     187DECLINLINE(int) parallelsFileWriteSync(PPARALLELSIMAGE pImage, uint64_t uOffset,
     188                                       const void *pvBuffer, size_t cbBuffer,
     189                                       size_t *pcbWritten)
     190{
     191    return pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser,
     192                                                       pImage->pStorage, uOffset,
     193                                                       pvBuffer, cbBuffer, pcbWritten);
     194}
     195
     196DECLINLINE(int) parallelsFileReadSync(PPARALLELSIMAGE pImage, uint64_t uOffset,
     197                                      void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
     198{
     199    return pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser,
     200                                                      pImage->pStorage, uOffset,
     201                                                      pvBuffer, cbBuffer, pcbRead);
     202}
     203
     204DECLINLINE(int) parallelsFileFlushSync(PPARALLELSIMAGE pImage)
     205{
     206    return pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser,
     207                                                       pImage->pStorage);
     208}
     209
     210DECLINLINE(int) parallelsFileReadUserAsync(PPARALLELSIMAGE pImage, uint64_t uOffset,
     211                                           PVDIOCTX pIoCtx, size_t cbRead)
     212{
     213    return pImage->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser,
     214                                                           pImage->pStorage,
     215                                                           uOffset, pIoCtx,
     216                                                           cbRead);
     217}
     218
     219DECLINLINE(int) parallelsFileWriteUserAsync(PPARALLELSIMAGE pImage, uint64_t uOffset,
     220                                            PVDIOCTX pIoCtx, size_t cbWrite,
     221                                            PFNVDXFERCOMPLETED pfnComplete,
     222                                            void *pvCompleteUser)
     223{
     224    return pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser,
     225                                                            pImage->pStorage,
     226                                                            uOffset, pIoCtx,
     227                                                            cbWrite,
     228                                                            pfnComplete,
     229                                                            pvCompleteUser);
     230}
     231
     232DECLINLINE(int) parallelsFileWriteMetaAsync(PPARALLELSIMAGE pImage, uint64_t uOffset,
     233                                            void *pvBuffer, size_t cbBuffer,
     234                                            PVDIOCTX pIoCtx,
     235                                            PFNVDXFERCOMPLETED pfnComplete,
     236                                            void *pvCompleteUser)
     237{
     238    return pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pImage->pInterfaceIO->pvUser,
     239                                                            pImage->pStorage,
     240                                                            uOffset, pvBuffer,
     241                                                            cbBuffer, pIoCtx,
     242                                                            pfnComplete,
     243                                                            pvCompleteUser);
     244}
     245
     246DECLINLINE(int) parallelsFileFlushAsync(PPARALLELSIMAGE pImage, PVDIOCTX pIoCtx,
     247                                        PFNVDXFERCOMPLETED pfnComplete,
     248                                        void *pvCompleteUser)
     249{
     250    return pImage->pInterfaceIOCallbacks->pfnFlushAsync(pImage->pInterfaceIO->pvUser,
     251                                                        pImage->pStorage,
     252                                                        pIoCtx, pfnComplete,
     253                                                        pvCompleteUser);
     254}
     255
     256
     257/**
     258 * Internal. Flush image data to disk.
     259 */
     260static int parallelsFlushImage(PPARALLELSIMAGE pImage)
    168261{
    169262    int rc = VINF_SUCCESS;
    170263
    171 #ifndef VBOX_WITH_NEW_IO_CODE
    172     if (pImage->File != NIL_RTFILE)
    173         rc = RTFileClose(pImage->File);
    174 
    175     pImage->File = NIL_RTFILE;
    176 #else
    177     rc = pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser,
    178                                                  pImage->pStorage);
    179 
    180     pImage->pStorage = NULL;
    181 #endif
    182 
    183     return rc;
    184 }
    185 
    186 static int parallelsFileFlushSync(PPARALLELSIMAGE pImage)
    187 {
    188     int rc = VINF_SUCCESS;
    189 
    190 #ifndef VBOX_WITH_NEW_IO_CODE
    191     rc = RTFileFlush(pImage->File);
    192 #else
    193     rc = pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser,
    194                                                      pImage->pStorage);
    195 #endif
    196 
    197     return rc;
    198 }
    199 
    200 static int parallelsFileGetSize(PPARALLELSIMAGE pImage, uint64_t *pcbSize)
    201 {
    202     int rc = VINF_SUCCESS;
    203 
    204 #ifndef VBOX_WITH_NEW_IO_CODE
    205     rc = RTFileGetSize(pImage->File, pcbSize);
    206 #else
    207     rc = pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser,
    208                                                    pImage->pStorage, pcbSize);
    209 #endif
    210 
    211     return rc;
    212 
    213 }
    214 
    215 static int parallelsFileSetSize(PPARALLELSIMAGE pImage, uint64_t cbSize)
    216 {
    217     int rc = VINF_SUCCESS;
    218 
    219 #ifndef VBOX_WITH_NEW_IO_CODE
    220     rc = RTFileSetSize(pImage->File, cbSize);
    221 #else
    222     rc = pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser,
    223                                                    pImage->pStorage,
    224                                                    cbSize);
    225 #endif
    226 
    227     return rc;
    228 }
    229 
    230 
    231 static int parallelsFileWriteSync(PPARALLELSIMAGE pImage, uint64_t off, const void *pcvBuf, size_t cbWrite, size_t *pcbWritten)
    232 {
    233     int rc = VINF_SUCCESS;
    234 
    235 #ifndef VBOX_WITH_NEW_IO_CODE
    236     rc = RTFileWriteAt(pImage->File, off, pcvBuf, cbWrite, pcbWritten);
    237 #else
    238     rc = pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser,
    239                                                      pImage->pStorage,
    240                                                      off, cbWrite, pcvBuf,
    241                                                      pcbWritten);
    242 #endif
    243 
    244     return rc;
    245 }
    246 
    247 static int parallelsFileReadSync(PPARALLELSIMAGE pImage, uint64_t off, void *pvBuf, size_t cbRead, size_t *pcbRead)
    248 {
    249     int rc = VINF_SUCCESS;
    250 
    251 #ifndef VBOX_WITH_NEW_IO_CODE
    252     rc = RTFileReadAt(pImage->File, off, pvBuf, cbRead, pcbRead);
    253 #else
    254     rc = pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser,
    255                                                     pImage->pStorage,
    256                                                     off, cbRead, pvBuf,
    257                                                     pcbRead);
    258 #endif
    259 
    260     return rc;
    261 }
    262 
    263 static bool parallelsFileOpened(PPARALLELSIMAGE pImage)
    264 {
    265 #ifndef VBOX_WITH_NEW_IO_CODE
    266     return pImage->File != NIL_RTFILE;
    267 #else
    268     return pImage->pStorage != NULL;
    269 #endif
    270 }
    271 
    272 static int parallelsOpenImage(PPARALLELSIMAGE pImage, unsigned uOpenFlags)
    273 {
    274     int rc = VINF_SUCCESS;
    275     ParallelsHeader parallelsHeader;
    276 
    277     /* Try to get error interface. */
    278     pImage->pInterfaceError = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ERROR);
    279     if (pImage->pInterfaceError)
    280         pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError);
    281 
    282 #ifdef VBOX_WITH_NEW_IO_CODE
    283     /* Try to get async I/O interface. */
    284     pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsImage, VDINTERFACETYPE_IO);
    285     AssertPtr(pImage->pInterfaceIO);
    286     pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO);
    287     AssertPtr(pImage->pInterfaceIOCallbacks);
    288 #endif
    289 
    290     rc = parallelsFileOpen(pImage, !!(uOpenFlags & VD_OPEN_FLAGS_READONLY), false);
    291     if (RT_FAILURE(rc))
    292         goto out;
    293 
    294     rc = parallelsFileGetSize(pImage, &pImage->cbFileCurrent);
    295     if (RT_FAILURE(rc))
    296         goto out;
    297     AssertMsg(pImage->cbFileCurrent % 512 == 0, ("File size is not a multiple of 512\n"));
    298 
    299     rc = parallelsFileReadSync(pImage, 0, &parallelsHeader, sizeof(parallelsHeader), NULL);
    300     if (RT_FAILURE(rc))
    301         goto out;
    302 
    303     if (memcmp(parallelsHeader.HeaderIdentifier, PARALLELS_HEADER_MAGIC, 16))
    304     {
    305         /* Check if the file has hdd as extension. It is a fixed size raw image then. */
    306         char *pszExtension = RTPathExt(pImage->pszFilename);
    307         if (strcmp(pszExtension, ".hdd"))
    308         {
    309             rc = VERR_VD_GEN_INVALID_HEADER;
    310             goto out;
    311         }
    312 
    313         /* This is a fixed size image. */
    314         pImage->uImageFlags |= VD_IMAGE_FLAGS_FIXED;
    315         pImage->cbSize = pImage->cbFileCurrent;
    316 
    317         pImage->PCHSGeometry.cHeads     = 16;
    318         pImage->PCHSGeometry.cSectors   = 63;
    319         uint64_t cCylinders = pImage->cbSize / (512 * pImage->PCHSGeometry.cSectors * pImage->PCHSGeometry.cHeads);
    320         pImage->PCHSGeometry.cCylinders = (uint32_t)cCylinders;
    321     }
    322     else
    323     {
    324         if (parallelsHeader.uVersion != PARALLELS_DISK_VERSION)
    325         {
    326             rc = VERR_NOT_SUPPORTED;
    327             goto out;
    328         }
    329 
    330         if (parallelsHeader.cEntriesInAllocationBitmap > (1 << 30))
    331         {
    332             rc = VERR_NOT_SUPPORTED;
    333             goto out;
    334         }
    335 
    336         Log(("cSectors=%u\n", parallelsHeader.cSectors));
    337         pImage->cbSize = ((uint64_t)parallelsHeader.cSectors) * 512;
    338         pImage->uImageFlags = VD_IMAGE_FLAGS_NONE;
    339         pImage->cAllocationBitmapEntries = parallelsHeader.cEntriesInAllocationBitmap;
    340         pImage->pAllocationBitmap = (uint32_t *)RTMemAllocZ((uint32_t)pImage->cAllocationBitmapEntries * sizeof(uint32_t));
    341         if (!pImage->pAllocationBitmap)
    342         {
    343             rc = VERR_NO_MEMORY;
    344             goto out;
    345         }
    346 
    347         rc = parallelsFileReadSync(pImage, sizeof(ParallelsHeader),
    348                                    pImage->pAllocationBitmap,
    349                                    pImage->cAllocationBitmapEntries * sizeof(uint32_t),
    350                                    NULL);
    351         if (RT_FAILURE(rc))
    352             goto out;
    353 
    354         pImage->PCHSGeometry.cCylinders = parallelsHeader.cCylinders;
    355         pImage->PCHSGeometry.cHeads     = parallelsHeader.cHeads;
    356         pImage->PCHSGeometry.cSectors   = parallelsHeader.cSectorsPerTrack;
    357     }
    358 
    359 out:
    360     LogFlowFunc(("returns %Rrc\n", rc));
    361     return rc;
    362 }
    363 
    364 static int parallelsFlushImage(PPARALLELSIMAGE pImage)
    365 {
    366     LogFlowFunc(("pImage=#%p\n", pImage));
    367     int rc = VINF_SUCCESS;
     264    if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     265        return VINF_SUCCESS;
    368266
    369267    if (   !(pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED)
     
    387285}
    388286
    389 static void parallelsFreeImage(PPARALLELSIMAGE pImage, bool fDelete)
    390 {
    391     (void)parallelsFlushImage(pImage);
    392 
    393     if (pImage->pAllocationBitmap)
    394         RTMemFree(pImage->pAllocationBitmap);
    395 
    396     if (parallelsFileOpened(pImage))
    397         parallelsFileClose(pImage);
    398 }
     287/**
     288 * Internal. Free all allocated space for representing an image except pImage,
     289 * and optionally delete the image from disk.
     290 */
     291static int parallelsFreeImage(PPARALLELSIMAGE pImage, bool fDelete)
     292{
     293    int rc = VINF_SUCCESS;
     294
     295    /* Freeing a never allocated image (e.g. because the open failed) is
     296     * not signalled as an error. After all nothing bad happens. */
     297    if (pImage)
     298    {
     299        if (pImage->pStorage)
     300        {
     301            /* No point updating the file that is deleted anyway. */
     302            if (!fDelete)
     303                parallelsFlushImage(pImage);
     304
     305            parallelsFileClose(pImage);
     306            pImage->pStorage = NULL;
     307        }
     308
     309        if (pImage->pAllocationBitmap)
     310        {
     311            RTMemFree(pImage->pAllocationBitmap);
     312            pImage->pAllocationBitmap = NULL;
     313        }
     314
     315        if (fDelete && pImage->pszFilename)
     316            parallelsFileDelete(pImage, pImage->pszFilename);
     317    }
     318
     319    return rc;
     320}
     321
     322static int parallelsOpenImage(PPARALLELSIMAGE pImage, unsigned uOpenFlags)
     323{
     324    int rc = VINF_SUCCESS;
     325    ParallelsHeader parallelsHeader;
     326
     327    /* Try to get error interface. */
     328    pImage->pInterfaceError = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ERROR);
     329    if (pImage->pInterfaceError)
     330        pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError);
     331
     332    /* Get I/O interface. */
     333    pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsImage, VDINTERFACETYPE_IO);
     334    AssertPtrReturn(pImage->pInterfaceIO, VERR_INVALID_PARAMETER);
     335    pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO);
     336    AssertPtrReturn(pImage->pInterfaceIOCallbacks, VERR_INVALID_PARAMETER);
     337
     338    rc = parallelsFileOpen(pImage, pImage->pszFilename,
     339                           VDOpenFlagsToFileOpenFlags(uOpenFlags,
     340                                                      false /* fCreate */));
     341    if (RT_FAILURE(rc))
     342        goto out;
     343
     344    rc = parallelsFileGetSize(pImage, &pImage->cbFileCurrent);
     345    if (RT_FAILURE(rc))
     346        goto out;
     347    AssertMsg(pImage->cbFileCurrent % 512 == 0, ("File size is not a multiple of 512\n"));
     348
     349    rc = parallelsFileReadSync(pImage, 0, &parallelsHeader, sizeof(parallelsHeader), NULL);
     350    if (RT_FAILURE(rc))
     351        goto out;
     352
     353    if (memcmp(parallelsHeader.HeaderIdentifier, PARALLELS_HEADER_MAGIC, 16))
     354    {
     355        /* Check if the file has hdd as extension. It is a fixed size raw image then. */
     356        char *pszExtension = RTPathExt(pImage->pszFilename);
     357        if (strcmp(pszExtension, ".hdd"))
     358        {
     359            rc = VERR_VD_PARALLELS_INVALID_HEADER;
     360            goto out;
     361        }
     362
     363        /* This is a fixed size image. */
     364        pImage->uImageFlags |= VD_IMAGE_FLAGS_FIXED;
     365        pImage->cbSize = pImage->cbFileCurrent;
     366
     367        pImage->PCHSGeometry.cHeads     = 16;
     368        pImage->PCHSGeometry.cSectors   = 63;
     369        uint64_t cCylinders = pImage->cbSize / (512 * pImage->PCHSGeometry.cSectors * pImage->PCHSGeometry.cHeads);
     370        pImage->PCHSGeometry.cCylinders = (uint32_t)cCylinders;
     371    }
     372    else
     373    {
     374        if (parallelsHeader.uVersion != PARALLELS_DISK_VERSION)
     375        {
     376            rc = VERR_NOT_SUPPORTED;
     377            goto out;
     378        }
     379
     380        if (parallelsHeader.cEntriesInAllocationBitmap > (1 << 30))
     381        {
     382            rc = VERR_NOT_SUPPORTED;
     383            goto out;
     384        }
     385
     386        Log(("cSectors=%u\n", parallelsHeader.cSectors));
     387        pImage->cbSize = ((uint64_t)parallelsHeader.cSectors) * 512;
     388        pImage->uImageFlags = VD_IMAGE_FLAGS_NONE;
     389        pImage->cAllocationBitmapEntries = parallelsHeader.cEntriesInAllocationBitmap;
     390        pImage->pAllocationBitmap = (uint32_t *)RTMemAllocZ((uint32_t)pImage->cAllocationBitmapEntries * sizeof(uint32_t));
     391        if (!pImage->pAllocationBitmap)
     392        {
     393            rc = VERR_NO_MEMORY;
     394            goto out;
     395        }
     396
     397        rc = parallelsFileReadSync(pImage, sizeof(ParallelsHeader),
     398                                   pImage->pAllocationBitmap,
     399                                   pImage->cAllocationBitmapEntries * sizeof(uint32_t),
     400                                   NULL);
     401        if (RT_FAILURE(rc))
     402            goto out;
     403
     404        pImage->PCHSGeometry.cCylinders = parallelsHeader.cCylinders;
     405        pImage->PCHSGeometry.cHeads     = parallelsHeader.cHeads;
     406        pImage->PCHSGeometry.cSectors   = parallelsHeader.cSectorsPerTrack;
     407    }
     408
     409out:
     410    LogFlowFunc(("returns %Rrc\n", rc));
     411    return rc;
     412}
     413
    399414
    400415/** @copydoc VBOXHDDBACKEND::pfnCheckIfValid */
    401 static int parallelsCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk)
    402 {
    403     RTFILE File;
     416static int parallelsCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk,
     417                                 PVDINTERFACE pVDIfsImage)
     418{
     419    int rc;
     420    PVDIOSTORAGE pStorage;
    404421    ParallelsHeader parallelsHeader;
    405     int rc;
    406 
    407     rc = RTFileOpen(&File, pszFilename, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
     422
     423    /* Get I/O interface. */
     424    PVDINTERFACE pInterfaceIO = VDInterfaceGet(pVDIfsImage, VDINTERFACETYPE_IO);
     425    AssertPtrReturn(pInterfaceIO, VERR_INVALID_PARAMETER);
     426    PVDINTERFACEIO pInterfaceIOCallbacks = VDGetInterfaceIO(pInterfaceIO);
     427    AssertPtrReturn(pInterfaceIOCallbacks, VERR_INVALID_PARAMETER);
     428
     429    rc = pInterfaceIOCallbacks->pfnOpen(pInterfaceIO->pvUser, pszFilename,
     430                                        VDOpenFlagsToFileOpenFlags(VD_OPEN_FLAGS_READONLY,
     431                                                                   false /* fCreate */),
     432                                        &pStorage);
    408433    if (RT_FAILURE(rc))
    409         return VERR_VD_GEN_INVALID_HEADER;
    410 
    411     rc = RTFileReadAt(File, 0, &parallelsHeader, sizeof(ParallelsHeader), NULL);
    412     if (RT_FAILURE(rc))
    413     {
    414         rc = VERR_VD_GEN_INVALID_HEADER;
    415     }
    416     else
     434        return rc;
     435
     436    rc = pInterfaceIOCallbacks->pfnReadSync(pInterfaceIO->pvUser, pStorage,
     437                                            0, &parallelsHeader,
     438                                            sizeof(ParallelsHeader), NULL);
     439    if (RT_SUCCESS(rc))
    417440    {
    418441        if (   !memcmp(parallelsHeader.HeaderIdentifier, PARALLELS_HEADER_MAGIC, 16)
     
    432455            char *pszExtension;
    433456
    434             rc = RTFileGetSize(File, &cbFile);
     457            rc = pInterfaceIOCallbacks->pfnGetSize(pInterfaceIO->pvUser, pStorage,
     458                                                   &cbFile);
    435459            if (RT_FAILURE(rc) || ((cbFile % 512) != 0))
    436460            {
    437                 RTFileClose(File);
    438                 return VERR_VD_GEN_INVALID_HEADER;
     461                pInterfaceIOCallbacks->pfnClose(pInterfaceIO->pvUser, pStorage);
     462                return VERR_VD_PARALLELS_INVALID_HEADER;
    439463            }
    440464
    441465            pszExtension = RTPathExt(pszFilename);
    442466            if (!pszExtension || strcmp(pszExtension, ".hdd"))
    443                 rc = VERR_VD_GEN_INVALID_HEADER;
     467                rc = VERR_VD_PARALLELS_INVALID_HEADER;
    444468            else
    445469                rc = VINF_SUCCESS;
     
    447471    }
    448472
    449     RTFileClose(File);
     473    pInterfaceIOCallbacks->pfnClose(pInterfaceIO->pvUser, pStorage);
    450474    return rc;
    451475}
     
    469493    /* Check remaining arguments. */
    470494    if (   !VALID_PTR(pszFilename)
    471         || !*pszFilename
    472         || strchr(pszFilename, '"'))
     495        || !*pszFilename)
    473496    {
    474497        rc = VERR_INVALID_PARAMETER;
     
    476499    }
    477500
     501    /** @todo r=klaus why this duplicate check, async is not claimed... */
    478502    if (uOpenFlags & VD_OPEN_FLAGS_ASYNC_IO)
    479503    {
     
    489513    }
    490514
    491 #ifndef VBOX_WITH_NEW_IO_CODE
    492     pImage->File = NIL_RTFILE;
    493 #else
     515    pImage->pszFilename = pszFilename;
    494516    pImage->pStorage = NULL;
    495 #endif
    496     pImage->fAllocationBitmapChanged = false;
    497     pImage->pszFilename = pszFilename;
    498517    pImage->pVDIfsDisk = pVDIfsDisk;
    499518    pImage->pVDIfsImage = pVDIfsImage;
     519    pImage->fAllocationBitmapChanged = false;
    500520
    501521    rc = parallelsOpenImage(pImage, uOpenFlags);
    502522    if (RT_SUCCESS(rc))
    503523        *ppBackendData = pImage;
     524    else
     525        RTMemFree(pImage);
    504526
    505527out:
     
    511533static int parallelsCreate(const char *pszFilename, uint64_t cbSize,
    512534                           unsigned uImageFlags, const char *pszComment,
    513                            PCPDMMEDIAGEOMETRY pPCHSGeometry,
    514                            PCPDMMEDIAGEOMETRY pLCHSGeometry, PCRTUUID pUuid,
     535                           PCVDGEOMETRY pPCHSGeometry,
     536                           PCVDGEOMETRY pLCHSGeometry, PCRTUUID pUuid,
    515537                           unsigned uOpenFlags, unsigned uPercentStart,
    516538                           unsigned uPercentSpan, PVDINTERFACE pVDIfsDisk,
    517                            PVDINTERFACE pVDIfsImage, PVDINTERFACE pVDIfsOperation,
    518                            void **ppBackendData)
     539                           PVDINTERFACE pVDIfsImage,
     540                           PVDINTERFACE pVDIfsOperation, void **ppBackendData)
    519541{
    520542    LogFlowFunc(("pszFilename=\"%s\" cbSize=%llu uImageFlags=%#x pszComment=\"%s\" pPCHSGeometry=%#p pLCHSGeometry=%#p Uuid=%RTuuid uOpenFlags=%#x uPercentStart=%u uPercentSpan=%u pVDIfsDisk=%#p pVDIfsImage=%#p pVDIfsOperation=%#p ppBackendData=%#p", pszFilename, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, ppBackendData));
    521     return VERR_NOT_IMPLEMENTED;
     543    int rc = VERR_NOT_IMPLEMENTED;
     544
     545    LogFlowFunc(("returns %Rrc\n", rc));
     546    return rc;
    522547}
    523548
     
    526551{
    527552    LogFlowFunc(("pBackendData=%#p pszFilename=%#p\n", pBackendData, pszFilename));
    528     return VERR_NOT_IMPLEMENTED;
     553    int rc = VINF_SUCCESS;
     554    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
     555
     556    /* Check arguments. */
     557    if (   !pImage
     558        || !pszFilename
     559        || !*pszFilename)
     560    {
     561        rc = VERR_INVALID_PARAMETER;
     562        goto out;
     563    }
     564
     565    /* Close the image. */
     566    rc = parallelsFreeImage(pImage, false);
     567    if (RT_FAILURE(rc))
     568        goto out;
     569
     570    /* Rename the file. */
     571    rc = parallelsFileMove(pImage, pImage->pszFilename, pszFilename, 0);
     572    if (RT_FAILURE(rc))
     573    {
     574        /* The move failed, try to reopen the original image. */
     575        int rc2 = parallelsOpenImage(pImage, pImage->uOpenFlags);
     576        if (RT_FAILURE(rc2))
     577            rc = rc2;
     578
     579        goto out;
     580    }
     581
     582    /* Update pImage with the new information. */
     583    pImage->pszFilename = pszFilename;
     584
     585    /* Open the old image with new name. */
     586    rc = parallelsOpenImage(pImage, pImage->uOpenFlags);
     587    if (RT_FAILURE(rc))
     588        goto out;
     589
     590out:
     591    LogFlowFunc(("returns %Rrc\n", rc));
     592    return rc;
    529593}
    530594
     
    534598    LogFlowFunc(("pBackendData=%#p fDelete=%d\n", pBackendData, fDelete));
    535599    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    536     int rc = VINF_SUCCESS;
    537 
    538     /* Freeing a never allocated image (e.g. because the open failed) is
    539      * not signalled as an error. After all nothing bad happens. */
    540     if (pImage)
    541         parallelsFreeImage(pImage, fDelete);
     600    int rc;
     601
     602    rc = parallelsFreeImage(pImage, fDelete);
     603    RTMemFree(pImage);
    542604
    543605    LogFlowFunc(("returns %Rrc\n", rc));
     
    547609/** @copydoc VBOXHDDBACKEND::pfnRead */
    548610static int parallelsRead(void *pBackendData, uint64_t uOffset, void *pvBuf,
    549                          size_t cbToRead, size_t *pcbActuallyRead)
    550 {
    551     LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n", pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead));
     611                         size_t cbBuf, size_t *pcbActuallyRead)
     612{
     613    LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbBuf=%zu pcbActuallyRead=%#p\n", pBackendData, uOffset, pvBuf, cbBuf, pcbActuallyRead));
     614    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    552615    int rc = VINF_SUCCESS;
    553     PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    554616    uint64_t uSector;
    555617    uint64_t uOffsetInFile;
    556618    uint32_t iIndexInAllocationTable;
    557619
    558     Assert(pImage);
     620    AssertPtr(pImage);
    559621    Assert(uOffset % 512 == 0);
    560     Assert(cbToRead % 512 == 0);
     622    Assert(cbBuf % 512 == 0);
    561623
    562624    if (pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED)
    563625    {
    564         rc = parallelsFileReadSync(pImage, uOffset,
    565                                    pvBuf, cbToRead, NULL);
     626        rc = parallelsFileReadSync(pImage, uOffset, pvBuf, cbBuf, NULL);
    566627    }
    567628    else
     
    573634        uSector = uSector % pImage->PCHSGeometry.cSectors;
    574635
    575         cbToRead = RT_MIN(cbToRead, (pImage->PCHSGeometry.cSectors - uSector)*512);
     636        cbBuf = RT_MIN(cbBuf, (pImage->PCHSGeometry.cSectors - uSector)*512);
    576637
    577638        if (pImage->pAllocationBitmap[iIndexInAllocationTable] == 0)
     
    582643        {
    583644            uOffsetInFile = (pImage->pAllocationBitmap[iIndexInAllocationTable] + uSector) * 512;
    584             rc = parallelsFileReadSync(pImage, uOffsetInFile,
    585                                        pvBuf, cbToRead, NULL);
    586         }
    587     }
    588 
    589     *pcbActuallyRead = cbToRead;
    590 
     645            rc = parallelsFileReadSync(pImage, uOffsetInFile, pvBuf, cbBuf, NULL);
     646        }
     647    }
     648
     649    if (RT_SUCCESS(rc))
     650    {
     651        if (pcbActuallyRead)
     652            *pcbActuallyRead = cbBuf;
     653
     654        Log2(("parallelsRead: off=%#llx pvBuf=%p cbBuf=%d\n"
     655                "%.*Rhxd\n",
     656                uOffset, pvBuf, cbBuf, cbBuf, pvBuf));
     657    }
     658
     659out:
    591660    LogFlowFunc(("returns %Rrc\n", rc));
    592661    return rc;
     
    595664/** @copydoc VBOXHDDBACKEND::pfnWrite */
    596665static int parallelsWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf,
    597                           size_t cbToWrite, size_t *pcbWriteProcess,
     666                          size_t cbBuf, size_t *pcbWriteProcess,
    598667                          size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite)
    599668{
    600     LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p\n", pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess));
     669    LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbBuf=%zu pcbWriteProcess=%#p\n", pBackendData, uOffset, pvBuf, cbBuf, pcbWriteProcess));
     670    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    601671    int rc = VINF_SUCCESS;
    602     PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    603672    uint64_t uSector;
    604673    uint64_t uOffsetInFile;
    605674    uint32_t iIndexInAllocationTable;
    606675
    607     Assert(pImage);
     676    AssertPtr(pImage);
    608677    Assert(uOffset % 512 == 0);
    609     Assert(cbToWrite % 512 == 0);
     678    Assert(cbBuf % 512 == 0);
    610679
    611680    if (pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED)
    612681    {
    613         rc = parallelsFileWriteSync(pImage, uOffset,
    614                                     pvBuf, cbToWrite, NULL);
     682        rc = parallelsFileWriteSync(pImage, uOffset, pvBuf, cbBuf, NULL);
    615683    }
    616684    else
     
    622690        uSector = uSector % pImage->PCHSGeometry.cSectors;
    623691
    624         cbToWrite = RT_MIN(cbToWrite, (pImage->PCHSGeometry.cSectors - uSector)*512);
     692        cbBuf = RT_MIN(cbBuf, (pImage->PCHSGeometry.cSectors - uSector)*512);
    625693
    626694        if (pImage->pAllocationBitmap[iIndexInAllocationTable] == 0)
     
    635703
    636704            if (!pNewBlock)
    637                 return VERR_NO_MEMORY;
     705            {
     706                rc = VERR_NO_MEMORY;
     707                goto out;
     708            }
    638709
    639710            uOffsetInFile = (uint64_t)pImage->pAllocationBitmap[iIndexInAllocationTable] * 512;
    640711            memcpy(pNewBlock + (uOffset - ((uint64_t)iIndexInAllocationTable * pImage->PCHSGeometry.cSectors * 512)),
    641                    pvBuf, cbToWrite);
     712                   pvBuf, cbBuf);
    642713
    643714            /*
    644715             * Write the new block at the current end of the file.
    645716             */
    646             rc = parallelsFileWriteSync(pImage, uOffsetInFile,
    647                                         pNewBlock,
    648                                         pImage->PCHSGeometry.cSectors * 512, NULL);
     717            rc = parallelsFileWriteSync(pImage, uOffsetInFile, pNewBlock,
     718                                        pImage->PCHSGeometry.cSectors * 512,
     719                                        NULL);
    649720
    650721            RTMemFree(pNewBlock);
     
    653724        {
    654725            uOffsetInFile = (pImage->pAllocationBitmap[iIndexInAllocationTable] + uSector) * 512;
    655             rc = parallelsFileWriteSync(pImage, uOffsetInFile,
    656                                         pvBuf, cbToWrite, NULL);
    657         }
    658     }
    659 
    660     *pcbWriteProcess = cbToWrite;
    661 
    662     LogFlowFunc(("returns %Rrc\n", rc));
    663     return rc;
    664 }
    665 
     726            rc = parallelsFileWriteSync(pImage, uOffsetInFile, pvBuf, cbBuf, NULL);
     727        }
     728    }
     729
     730    if (pcbWriteProcess)
     731        *pcbWriteProcess = cbBuf;
     732
     733    /* Stay on the safe side. Do not run the risk of confusing the higher
     734     * level, as that can be pretty lethal to image consistency. */
     735    *pcbPreRead = 0;
     736    *pcbPostRead = 0;
     737
     738out:
     739    LogFlowFunc(("returns %Rrc\n", rc));
     740    return rc;
     741}
     742
     743/** @copydoc VBOXHDDBACKEND::pfnFlush */
    666744static int parallelsFlush(void *pBackendData)
    667745{
    668746    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    669747    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    670     int rc = VINF_SUCCESS;
    671 
    672     Assert(pImage);
     748    int rc;
     749
     750    AssertPtr(pImage);
    673751
    674752    rc = parallelsFlushImage(pImage);
     
    684762    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    685763
    686     Assert(pImage);
     764    AssertPtr(pImage);
    687765
    688766    if (pImage)
     
    697775    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    698776    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    699 
    700     Assert(pImage);
    701 
    702     if (pImage)
    703         return pImage->cbSize;
    704     else
    705         return 0;
     777    uint64_t cb = 0;
     778
     779    AssertPtr(pImage);
     780
     781    if (pImage && pImage->pStorage)
     782        cb = pImage->cbSize;
     783
     784    LogFlowFunc(("returns %llu\n", cb));
     785    return cb;
    706786}
    707787
     
    713793    uint64_t cb = 0;
    714794
    715     Assert(pImage);
    716 
    717     if (pImage)
    718     {
    719         if (parallelsFileOpened(pImage))
    720             cb = pImage->cbFileCurrent;
    721     }
     795    AssertPtr(pImage);
     796
     797    if (pImage && pImage->pStorage)
     798        cb = pImage->cbFileCurrent;
    722799
    723800    LogFlowFunc(("returns %lld\n", cb));
     
    727804/** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */
    728805static int parallelsGetPCHSGeometry(void *pBackendData,
    729                                     PPDMMEDIAGEOMETRY pPCHSGeometry)
     806                                    PVDGEOMETRY pPCHSGeometry)
    730807{
    731808    LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry));
     
    733810    int rc;
    734811
    735     Assert(pImage);
     812    AssertPtr(pImage);
    736813
    737814    if (pImage)
     
    754831/** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */
    755832static int parallelsSetPCHSGeometry(void *pBackendData,
    756                                     PCPDMMEDIAGEOMETRY pPCHSGeometry)
     833                                    PCVDGEOMETRY pPCHSGeometry)
    757834{
    758835    LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
     
    760837    int rc;
    761838
    762     Assert(pImage);
     839    AssertPtr(pImage);
    763840
    764841    if (pImage)
     
    783860/** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */
    784861static int parallelsGetLCHSGeometry(void *pBackendData,
    785                                     PPDMMEDIAGEOMETRY pLCHSGeometry)
     862                                    PVDGEOMETRY pLCHSGeometry)
    786863{
    787864    LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry));
     
    789866    int rc;
    790867
    791     Assert(pImage);
     868    AssertPtr(pImage);
    792869
    793870    if (pImage)
     
    810887/** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */
    811888static int parallelsSetLCHSGeometry(void *pBackendData,
    812                                     PCPDMMEDIAGEOMETRY pLCHSGeometry)
     889                                    PCVDGEOMETRY pLCHSGeometry)
    813890{
    814891    LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
     
    816893    int rc;
    817894
    818     Assert(pImage);
     895    AssertPtr(pImage);
    819896
    820897    if (pImage)
     
    844921    unsigned uImageFlags;
    845922
    846     Assert(pImage);
     923    AssertPtr(pImage);
    847924
    848925    if (pImage)
     
    862939    unsigned uOpenFlags;
    863940
    864     Assert(pImage);
     941    AssertPtr(pImage);
    865942
    866943    if (pImage)
     
    882959    /* Image must be opened and the new flags must be valid. Just readonly and
    883960     * info flags are supported. */
     961    /** @todo r=klaus add VD_OPEN_FLAGS_ASYNC_IO when async io has been tested */
    884962    if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_SHAREABLE)))
    885963    {
     
    889967
    890968    /* Implement this operation via reopening the image. */
    891     parallelsFreeImage(pImage, false);
     969    parallelsFreeImage(pImage, true);
    892970    rc = parallelsOpenImage(pImage, uOpenFlags);
    893971
     
    905983    int rc;
    906984
    907     Assert(pImage);
    908 
    909     if (pImage)
    910     {
     985    AssertPtr(pImage);
     986
     987    if (pImage)
    911988        rc = VERR_NOT_SUPPORTED;
    912     }
    913989    else
    914990        rc = VERR_VD_NOT_OPENED;
     
    9251001    int rc;
    9261002
    927     Assert(pImage);
     1003    AssertPtr(pImage);
    9281004
    9291005    if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     
    9341010
    9351011    if (pImage)
    936         rc = VINF_SUCCESS;
     1012        rc = VERR_NOT_SUPPORTED;
    9371013    else
    9381014        rc = VERR_VD_NOT_OPENED;
     
    9501026    int rc;
    9511027
    952     Assert(pImage);
    953 
    954     if (pImage)
    955     {
     1028    AssertPtr(pImage);
     1029
     1030    if (pImage)
    9561031        rc = VERR_NOT_SUPPORTED;
    957     }
    9581032    else
    9591033        rc = VERR_VD_NOT_OPENED;
     
    9701044    int rc;
    9711045
    972     LogFlowFunc(("%RTuuid\n", pUuid));
    973     Assert(pImage);
     1046    AssertPtr(pImage);
    9741047
    9751048    if (pImage)
    9761049    {
    9771050        if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    978         {
    9791051            rc = VERR_NOT_SUPPORTED;
    980         }
    9811052        else
    9821053            rc = VERR_VD_IMAGE_READ_ONLY;
     
    9961067    int rc;
    9971068
    998     Assert(pImage);
    999 
    1000     if (pImage)
    1001     {
     1069    AssertPtr(pImage);
     1070
     1071    if (pImage)
    10021072        rc = VERR_NOT_SUPPORTED;
    1003     }
    10041073    else
    10051074        rc = VERR_VD_NOT_OPENED;
     
    10161085    int rc;
    10171086
    1018     Assert(pImage);
     1087    AssertPtr(pImage);
    10191088
    10201089    if (pImage)
    10211090    {
    10221091        if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    1023         {
    10241092            rc = VERR_NOT_SUPPORTED;
    1025         }
    10261093        else
    10271094            rc = VERR_VD_IMAGE_READ_ONLY;
     
    10411108    int rc;
    10421109
    1043     Assert(pImage);
    1044 
    1045     if (pImage)
    1046     {
    1047         rc = VINF_SUCCESS;
    1048     }
     1110    AssertPtr(pImage);
     1111
     1112    if (pImage)
     1113        rc = VERR_NOT_SUPPORTED;
    10491114    else
    10501115        rc = VERR_VD_NOT_OPENED;
     
    10611126    int rc;
    10621127
    1063     Assert(pImage);
     1128    AssertPtr(pImage);
    10641129
    10651130    if (pImage)
    10661131    {
    10671132        if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    1068         {
    10691133            rc = VERR_NOT_SUPPORTED;
    1070         }
    10711134        else
    10721135            rc = VERR_VD_IMAGE_READ_ONLY;
     
    10861149    int rc;
    10871150
    1088     Assert(pImage);
    1089 
    1090     if (pImage)
    1091     {
     1151    AssertPtr(pImage);
     1152
     1153    if (pImage)
    10921154        rc = VERR_NOT_SUPPORTED;
    1093     }
    10941155    else
    10951156        rc = VERR_VD_NOT_OPENED;
     
    11061167    int rc;
    11071168
    1108     Assert(pImage);
     1169    AssertPtr(pImage);
    11091170
    11101171    if (pImage)
    11111172    {
    11121173        if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    1113         {
    11141174            rc = VERR_NOT_SUPPORTED;
    1115         }
    11161175        else
    11171176            rc = VERR_VD_IMAGE_READ_ONLY;
     
    11291188    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    11301189
    1131     Assert(pImage);
    1132     if (pImage)
    1133     {
    1134         pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u\n",
     1190    AssertPtr(pImage);
     1191    if (pImage)
     1192    {
     1193        parallelsMessage(pImage, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u\n",
    11351194                    pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors,
    11361195                    pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors);
     
    11381197}
    11391198
    1140 
    1141 static int parallelsGetTimeStamp(void *pvBackendData, PRTTIMESPEC pTimeStamp)
    1142 {
    1143     int rc = VERR_NOT_IMPLEMENTED;
    1144     LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
    1145     return rc;
    1146 }
    1147 
    1148 static int parallelsGetParentTimeStamp(void *pvBackendData, PRTTIMESPEC pTimeStamp)
    1149 {
    1150     int rc = VERR_NOT_IMPLEMENTED;
    1151     LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
    1152     return rc;
    1153 }
    1154 
    1155 static int parallelsSetParentTimeStamp(void *pvBackendData, PCRTTIMESPEC pTimeStamp)
    1156 {
    1157     int rc = VERR_NOT_IMPLEMENTED;
    1158     LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
    1159     return rc;
    1160 }
    1161 
    1162 static int parallelsGetParentFilename(void *pvBackendData, char **ppszParentFilename)
    1163 {
    1164     int rc = VERR_NOT_IMPLEMENTED;
    1165     LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
    1166     return rc;
    1167 }
    1168 
    1169 static int parallelsSetParentFilename(void *pvBackendData, const char *pszParentFilename)
    1170 {
    1171     int rc = VERR_NOT_IMPLEMENTED;
    1172     LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
    1173     return rc;
    1174 }
    1175 
    1176 static bool parallelsIsAsyncIOSupported(void *pvBackendData)
     1199/** @copydoc VBOXHDDBACKEND::pfnIsAsyncIOSupported */
     1200static bool parallelsIsAsyncIOSupported(void *pBackendData)
    11771201{
    11781202#if 0 /** @todo: Remove when tested */
     
    11831207}
    11841208
    1185 static int parallelsAsyncRead(void *pvBackendData, uint64_t uOffset, size_t cbToRead,
     1209/** @copydoc VBOXHDDBACKEND::pfnAsyncRead */
     1210static int parallelsAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbToRead,
    11861211                              PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
    11871212{
    1188     LogFlowFunc(("pvBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n",
    1189                  pvBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead));
     1213    LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n",
     1214                 pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead));
    11901215    int rc = VINF_SUCCESS;
    1191     PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pvBackendData;
     1216    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    11921217    uint64_t uSector;
    11931218    uint64_t uOffsetInFile;
    11941219    uint32_t iIndexInAllocationTable;
    11951220
    1196     Assert(pImage);
     1221    AssertPtr(pImage);
    11971222    Assert(uOffset % 512 == 0);
    11981223    Assert(cbToRead % 512 == 0);
     
    12001225    if (pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED)
    12011226    {
    1202         rc = pImage->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser,
    1203                                                              pImage->pStorage,
    1204                                                              uOffset, pIoCtx, cbToRead);
     1227        rc = parallelsFileReadUserAsync(pImage, uOffset, pIoCtx, cbToRead);
    12051228    }
    12061229    else
     
    12211244        {
    12221245            uOffsetInFile = (pImage->pAllocationBitmap[iIndexInAllocationTable] + uSector) * 512;
    1223             rc = pImage->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser,
    1224                                                                  pImage->pStorage,
    1225                                                                  uOffsetInFile, pIoCtx, cbToRead);
     1246            rc = parallelsFileReadUserAsync(pImage, uOffsetInFile, pIoCtx, cbToRead);
    12261247        }
    12271248    }
     
    12331254}
    12341255
    1235 static int parallelsAsyncWrite(void *pvBackendData, uint64_t uOffset, size_t cbToWrite,
     1256/** @copydoc VBOXHDDBACKEND::pfnAsyncWrite */
     1257static int parallelsAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite,
    12361258                               PVDIOCTX pIoCtx,
    12371259                               size_t *pcbWriteProcess, size_t *pcbPreRead,
    12381260                               size_t *pcbPostRead, unsigned fWrite)
    12391261{
    1240     LogFlowFunc(("pvBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p\n",
    1241                  pvBackendData, uOffset, pIoCtx, cbToWrite, pcbWriteProcess));
     1262    LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p\n",
     1263                 pBackendData, uOffset, pIoCtx, cbToWrite, pcbWriteProcess));
    12421264    int rc = VINF_SUCCESS;
    1243     PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pvBackendData;
     1265    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    12441266    uint64_t uSector;
    12451267    uint64_t uOffsetInFile;
    12461268    uint32_t iIndexInAllocationTable;
    12471269
    1248     Assert(pImage);
     1270    AssertPtr(pImage);
    12491271    Assert(uOffset % 512 == 0);
    12501272    Assert(cbToWrite % 512 == 0);
     
    12521274    if (pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED)
    12531275    {
    1254         rc = pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser,
    1255                                                               pImage->pStorage,
    1256                                                               uOffset, pIoCtx, cbToWrite,
    1257                                                               NULL, NULL);
     1276        rc = parallelsFileWriteUserAsync(pImage, uOffset, pIoCtx, cbToWrite, NULL, NULL);
    12581277    }
    12591278    else
     
    12901309             * Write the new block at the current end of the file.
    12911310             */
    1292             rc = pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser,
    1293                                                                   pImage->pStorage,
    1294                                                                   uOffsetInFile, pIoCtx, cbToWrite,
    1295                                                                   NULL, NULL);
     1311            rc = parallelsFileWriteUserAsync(pImage, uOffsetInFile, pIoCtx, cbToWrite, NULL, NULL);
    12961312            if (RT_SUCCESS(rc) || (rc == VERR_VD_ASYNC_IO_IN_PROGRESS))
    12971313            {
    12981314                /* Write the changed allocation bitmap entry. */
    12991315                /** @todo: Error handling. */
    1300                 rc = pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pImage->pInterfaceIO->pvUser,
    1301                                                                       pImage->pStorage,
    1302                                                                       sizeof(ParallelsHeader) + iIndexInAllocationTable * sizeof(uint32_t),
    1303                                                                       &pImage->pAllocationBitmap[iIndexInAllocationTable],
    1304                                                                       sizeof(uint32_t),
    1305                                                                       pIoCtx,
    1306                                                                       NULL, NULL);
     1316                rc = parallelsFileWriteMetaAsync(pImage,
     1317                                                 sizeof(ParallelsHeader) + iIndexInAllocationTable * sizeof(uint32_t),
     1318                                                 &pImage->pAllocationBitmap[iIndexInAllocationTable],
     1319                                                 sizeof(uint32_t), pIoCtx,
     1320                                                 NULL, NULL);
    13071321            }
    13081322        }
     
    13101324        {
    13111325            uOffsetInFile = (pImage->pAllocationBitmap[iIndexInAllocationTable] + uSector) * 512;
    1312             rc = pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser,
    1313                                                                   pImage->pStorage,
    1314                                                                   uOffsetInFile, pIoCtx, cbToWrite,
    1315                                                                   NULL, NULL);
     1326            rc = parallelsFileWriteUserAsync(pImage, uOffsetInFile, pIoCtx, cbToWrite, NULL, NULL);
    13161327        }
    13171328    }
     
    13241335}
    13251336
    1326 static int parallelsAsyncFlush(void *pvBackendData, PVDIOCTX pIoCtx)
     1337/** @copydoc VBOXHDDBACKEND::pfnAsyncFlush */
     1338static int parallelsAsyncFlush(void *pBackendData, PVDIOCTX pIoCtx)
    13271339{
    13281340    int rc = VINF_SUCCESS;
    1329     PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pvBackendData;
     1341    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    13301342
    13311343    LogFlowFunc(("pImage=#%p\n", pImage));
    13321344
    13331345    /* Flush the file, everything is up to date already. */
    1334     rc = pImage->pInterfaceIOCallbacks->pfnFlushAsync(pImage->pInterfaceIO->pvUser,
    1335                                                       pImage->pStorage, pIoCtx,
    1336                                                       NULL, NULL);
    1337 
    1338     LogFlowFunc(("returns %Rrc\n", rc));
    1339     return rc;
    1340 }
     1346    rc = parallelsFileFlushAsync(pImage, pIoCtx, NULL, NULL);
     1347
     1348    LogFlowFunc(("returns %Rrc\n", rc));
     1349    return rc;
     1350}
     1351
    13411352
    13421353VBOXHDDBACKEND g_ParallelsBackend =
     
    13471358    sizeof(VBOXHDDBACKEND),
    13481359    /* uBackendCaps */
    1349     VD_CAP_FILE | VD_CAP_ASYNC,
     1360    VD_CAP_FILE | VD_CAP_ASYNC | VD_CAP_VFS,
    13501361    /* papszFileExtensions */
    13511362    s_apszParallelsFileExtensions,
     
    14131424    parallelsDump,
    14141425    /* pfnGetTimeStamp */
    1415     parallelsGetTimeStamp,
     1426    NULL,
    14161427    /* pfnGetParentTimeStamp */
    1417     parallelsGetParentTimeStamp,
     1428    NULL,
    14181429    /* pfnSetParentTimeStamp */
    1419     parallelsSetParentTimeStamp,
     1430    NULL,
    14201431    /* pfnGetParentFilename */
    1421     parallelsGetParentFilename,
     1432    NULL,
    14221433    /* pfnSetParentFilename */
    1423     parallelsSetParentFilename,
     1434    NULL,
    14241435    /* pfnIsAsyncIOSupported */
    14251436    parallelsIsAsyncIOSupported,
     
    14391450    NULL
    14401451};
    1441 
  • trunk/src/VBox/Devices/Storage/RawHDDCore.cpp

    r31776 r32536  
    2626#include <iprt/assert.h>
    2727#include <iprt/alloc.h>
    28 #include <iprt/file.h>
    2928
    3029
     
    3837typedef struct RAWIMAGE
    3938{
    40     /** Base image name. */
     39    /** Image name. */
    4140    const char       *pszFilename;
    42 #ifndef VBOX_WITH_NEW_IO_CODE
    43     /** File descriptor. */
    44     RTFILE            File;
    45 #else
    4641    /** Storage handle. */
    4742    PVDIOSTORAGE      pStorage;
     
    5045    /** Async I/O interface callbacks. */
    5146    PVDINTERFACEIO    pInterfaceIOCallbacks;
    52 #endif
    5347
    5448    /** Pointer to the per-disk VD interface list. */
     
    6963    uint64_t          cbSize;
    7064    /** Physical geometry of this image. */
    71     PDMMEDIAGEOMETRY  PCHSGeometry;
     65    VDGEOMETRY        PCHSGeometry;
    7266    /** Logical geometry of this image. */
    73     PDMMEDIAGEOMETRY  LCHSGeometry;
     67    VDGEOMETRY        LCHSGeometry;
    7468
    7569} RAWIMAGE, *PRAWIMAGE;
     
    8276static const char *const s_apszRawFileExtensions[] =
    8377{
    84     /** @todo At the monment this backend doesn't claim any extensions, but it might
     78    /** @todo At the moment this backend doesn't claim any extensions, but it might
    8579     * be useful to add a few later. However this needs careful testing, as the
    8680     * CheckIfValid function never returns success. */
     
    9185*   Internal Functions                                                         *
    9286*******************************************************************************/
    93 
    94 static int rawFlushImage(PRAWIMAGE pImage);
    95 static void rawFreeImage(PRAWIMAGE pImage, bool fDelete);
    96 
    9787
    9888/**
     
    111101}
    112102
    113 static int rawFileOpen(PRAWIMAGE pImage, bool fReadonly, bool fCreate)
     103/**
     104 * Internal: signal an informational message to the frontend.
     105 */
     106DECLINLINE(int) rawMessage(PRAWIMAGE pImage, const char *pszFormat, ...)
    114107{
    115108    int rc = VINF_SUCCESS;
    116 
    117     AssertMsg(!(fReadonly && fCreate), ("Image can't be opened readonly while being created\n"));
    118 
    119 #ifndef VBOX_WITH_NEW_IO_CODE
    120     uint32_t fOpen = fReadonly ? RTFILE_O_READ      | RTFILE_O_DENY_NONE
    121                                : RTFILE_O_READWRITE | RTFILE_O_DENY_WRITE;
    122 
    123     if (fCreate)
    124         fOpen |= RTFILE_O_CREATE;
    125     else
    126         fOpen |= RTFILE_O_OPEN;
    127 
    128     rc = RTFileOpen(&pImage->File, pImage->pszFilename, fOpen);
    129 #else
    130     unsigned uOpenFlags = fReadonly ? VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY : 0;
    131 
    132     if (fCreate)
    133         uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE;
    134 
    135     rc = pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser,
    136                                                 pImage->pszFilename,
    137                                                 uOpenFlags,
    138                                                 &pImage->pStorage);
    139 #endif
    140 
    141     return rc;
    142 }
    143 
    144 static int rawFileClose(PRAWIMAGE pImage)
     109    va_list va;
     110    va_start(va, pszFormat);
     111    if (pImage->pInterfaceError)
     112        rc = pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser,
     113                                                          pszFormat, va);
     114    va_end(va);
     115    return rc;
     116}
     117
     118
     119DECLINLINE(int) rawFileOpen(PRAWIMAGE pImage, const char *pszFilename,
     120                            uint32_t fOpen)
     121{
     122    return pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser,
     123                                                  pszFilename, fOpen,
     124                                                  &pImage->pStorage);
     125}
     126
     127DECLINLINE(int) rawFileClose(PRAWIMAGE pImage)
     128{
     129    return pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser,
     130                                                   pImage->pStorage);
     131}
     132
     133DECLINLINE(int) rawFileDelete(PRAWIMAGE pImage, const char *pszFilename)
     134{
     135    return pImage->pInterfaceIOCallbacks->pfnDelete(pImage->pInterfaceIO->pvUser,
     136                                                    pszFilename);
     137}
     138
     139DECLINLINE(int) rawFileMove(PRAWIMAGE pImage, const char *pszSrc,
     140                            const char *pszDst, unsigned fMove)
     141{
     142    return pImage->pInterfaceIOCallbacks->pfnMove(pImage->pInterfaceIO->pvUser,
     143                                                  pszSrc, pszDst, fMove);
     144}
     145
     146DECLINLINE(int) rawFileGetFreeSpace(PRAWIMAGE pImage, const char *pszFilename,
     147                                    int64_t *pcbFree)
     148{
     149    return pImage->pInterfaceIOCallbacks->pfnGetFreeSpace(pImage->pInterfaceIO->pvUser,
     150                                                          pszFilename, pcbFree);
     151}
     152
     153DECLINLINE(int) rawFileGetSize(PRAWIMAGE pImage, uint64_t *pcbSize)
     154{
     155    return pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser,
     156                                                     pImage->pStorage, pcbSize);
     157}
     158
     159DECLINLINE(int) rawFileSetSize(PRAWIMAGE pImage, uint64_t cbSize)
     160{
     161    return pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser,
     162                                                     pImage->pStorage, cbSize);
     163}
     164
     165DECLINLINE(int) rawFileWriteSync(PRAWIMAGE pImage, uint64_t uOffset,
     166                                 const void *pvBuffer, size_t cbBuffer,
     167                                 size_t *pcbWritten)
     168{
     169    return pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser,
     170                                                       pImage->pStorage, uOffset,
     171                                                       pvBuffer, cbBuffer, pcbWritten);
     172}
     173
     174DECLINLINE(int) rawFileReadSync(PRAWIMAGE pImage, uint64_t uOffset,
     175                                void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
     176{
     177    return pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser,
     178                                                      pImage->pStorage, uOffset,
     179                                                      pvBuffer, cbBuffer, pcbRead);
     180}
     181
     182DECLINLINE(int) rawFileFlushSync(PRAWIMAGE pImage)
     183{
     184    return pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser,
     185                                                       pImage->pStorage);
     186}
     187
     188DECLINLINE(int) rawFileReadUserAsync(PRAWIMAGE pImage, uint64_t uOffset,
     189                                     PVDIOCTX pIoCtx, size_t cbRead)
     190{
     191    return pImage->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser,
     192                                                           pImage->pStorage,
     193                                                           uOffset, pIoCtx,
     194                                                           cbRead);
     195}
     196
     197DECLINLINE(int) rawFileWriteUserAsync(PRAWIMAGE pImage, uint64_t uOffset,
     198                                      PVDIOCTX pIoCtx, size_t cbWrite,
     199                                      PFNVDXFERCOMPLETED pfnComplete,
     200                                      void *pvCompleteUser)
     201{
     202    return pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser,
     203                                                            pImage->pStorage,
     204                                                            uOffset, pIoCtx,
     205                                                            cbWrite,
     206                                                            pfnComplete,
     207                                                            pvCompleteUser);
     208}
     209
     210DECLINLINE(int) rawFileFlushAsync(PRAWIMAGE pImage, PVDIOCTX pIoCtx,
     211                                  PFNVDXFERCOMPLETED pfnComplete,
     212                                  void *pvCompleteUser)
     213{
     214    return pImage->pInterfaceIOCallbacks->pfnFlushAsync(pImage->pInterfaceIO->pvUser,
     215                                                        pImage->pStorage,
     216                                                        pIoCtx, pfnComplete,
     217                                                        pvCompleteUser);
     218}
     219
     220
     221/**
     222 * Internal. Flush image data to disk.
     223 */
     224static int rawFlushImage(PRAWIMAGE pImage)
    145225{
    146226    int rc = VINF_SUCCESS;
    147227
    148 #ifndef VBOX_WITH_NEW_IO_CODE
    149     if (pImage->File != NIL_RTFILE)
    150         rc = RTFileClose(pImage->File);
    151 
    152     pImage->File = NIL_RTFILE;
    153 #else
    154     if (pImage->pStorage)
    155         rc = pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser,
    156                                                      pImage->pStorage);
    157 
    158     pImage->pStorage = NULL;
    159 #endif
    160 
    161     return rc;
    162 }
    163 
    164 static int rawFileFlushSync(PRAWIMAGE pImage)
     228    if (   pImage->pStorage
     229        && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     230        rc = rawFileFlushSync(pImage);
     231
     232    return rc;
     233}
     234
     235/**
     236 * Internal. Free all allocated space for representing an image except pImage,
     237 * and optionally delete the image from disk.
     238 */
     239static int rawFreeImage(PRAWIMAGE pImage, bool fDelete)
    165240{
    166241    int rc = VINF_SUCCESS;
    167242
    168 #ifndef VBOX_WITH_NEW_IO_CODE
    169     rc = RTFileFlush(pImage->File);
    170 #else
    171     rc = pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser,
    172                                                      pImage->pStorage);
    173 #endif
    174 
    175     return rc;
    176 }
    177 
    178 static int rawFileGetSize(PRAWIMAGE pImage, uint64_t *pcbSize)
    179 {
    180     int rc = VINF_SUCCESS;
    181 
    182 #ifndef VBOX_WITH_NEW_IO_CODE
    183     rc = RTFileGetSize(pImage->File, pcbSize);
    184 #else
    185     rc = pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser,
    186                                                    pImage->pStorage,
    187                                                    pcbSize);
    188 #endif
    189 
    190     return rc;
    191 
    192 }
    193 
    194 static int rawFileSetSize(PRAWIMAGE pImage, uint64_t cbSize)
    195 {
    196     int rc = VINF_SUCCESS;
    197 
    198 #ifndef VBOX_WITH_NEW_IO_CODE
    199     rc = RTFileSetSize(pImage->File, cbSize);
    200 #else
    201     rc = pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser,
    202                                                    pImage->pStorage,
    203                                                    cbSize);
    204 #endif
    205 
    206     return rc;
    207 }
    208 
    209 
    210 static int rawFileWriteSync(PRAWIMAGE pImage, uint64_t off, const void *pcvBuf, size_t cbWrite, size_t *pcbWritten)
    211 {
    212     int rc = VINF_SUCCESS;
    213 
    214 #ifndef VBOX_WITH_NEW_IO_CODE
    215     rc = RTFileWriteAt(pImage->File, off, pcvBuf, cbWrite, pcbWritten);
    216 #else
    217     rc = pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser,
    218                                                      pImage->pStorage,
    219                                                      off, cbWrite, pcvBuf,
    220                                                      pcbWritten);
    221 #endif
    222 
    223     return rc;
    224 }
    225 
    226 static int rawFileReadSync(PRAWIMAGE pImage, uint64_t off, void *pvBuf, size_t cbRead, size_t *pcbRead)
    227 {
    228     int rc = VINF_SUCCESS;
    229 
    230 #ifndef VBOX_WITH_NEW_IO_CODE
    231     rc = RTFileReadAt(pImage->File, off, pvBuf, cbRead, pcbRead);
    232 #else
    233     rc = pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser,
    234                                                     pImage->pStorage,
    235                                                     off, cbRead, pvBuf,
    236                                                     pcbRead);
    237 #endif
    238 
    239     return rc;
    240 }
    241 
    242 static bool rawFileOpened(PRAWIMAGE pImage)
    243 {
    244 #ifndef VBOX_WITH_NEW_IO_CODE
    245     return pImage->File != NIL_RTFILE;
    246 #else
    247     return pImage->pStorage != NULL;
    248 #endif
     243    /* Freeing a never allocated image (e.g. because the open failed) is
     244     * not signalled as an error. After all nothing bad happens. */
     245    if (pImage)
     246    {
     247        if (pImage->pStorage)
     248        {
     249            /* No point updating the file that is deleted anyway. */
     250            if (!fDelete)
     251                rawFlushImage(pImage);
     252
     253            rawFileClose(pImage);
     254            pImage->pStorage = NULL;
     255        }
     256
     257        if (fDelete && pImage->pszFilename)
     258            rawFileDelete(pImage, pImage->pszFilename);
     259    }
     260
     261    LogFlowFunc(("returns %Rrc\n", rc));
     262    return rc;
    249263}
    250264
     
    256270    int rc;
    257271
    258     if (uOpenFlags & VD_OPEN_FLAGS_ASYNC_IO)
    259         return VERR_NOT_SUPPORTED;
    260 
    261272    pImage->uOpenFlags = uOpenFlags;
    262273
     
    265276        pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError);
    266277
    267 #ifdef VBOX_WITH_NEW_IO_CODE
    268     /* Try to get I/O interface. */
     278    /* Get I/O interface. */
    269279    pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsImage, VDINTERFACETYPE_IO);
    270     AssertPtr(pImage->pInterfaceIO);
     280    AssertPtrReturn(pImage->pInterfaceIO, VERR_INVALID_PARAMETER);
    271281    pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO);
    272     AssertPtr(pImage->pInterfaceIOCallbacks);
    273 #endif
     282    AssertPtrReturn(pImage->pInterfaceIOCallbacks, VERR_INVALID_PARAMETER);
    274283
    275284    /*
    276285     * Open the image.
    277286     */
    278     rc = rawFileOpen(pImage, !!(uOpenFlags & VD_OPEN_FLAGS_READONLY), false);
     287    rc = rawFileOpen(pImage, pImage->pszFilename,
     288                     VDOpenFlagsToFileOpenFlags(uOpenFlags,
     289                                                false /* fCreate */));
    279290    if (RT_FAILURE(rc))
    280291    {
     
    305316static int rawCreateImage(PRAWIMAGE pImage, uint64_t cbSize,
    306317                          unsigned uImageFlags, const char *pszComment,
    307                           PCPDMMEDIAGEOMETRY pPCHSGeometry,
    308                           PCPDMMEDIAGEOMETRY pLCHSGeometry,
     318                          PCVDGEOMETRY pPCHSGeometry,
     319                          PCVDGEOMETRY pLCHSGeometry, unsigned uOpenFlags,
    309320                          PFNVDPROGRESS pfnProgress, void *pvUser,
    310321                          unsigned uPercentStart, unsigned uPercentSpan)
     
    324335
    325336    pImage->uImageFlags = uImageFlags;
     337
     338    pImage->uOpenFlags = uOpenFlags & ~VD_OPEN_FLAGS_READONLY;
     339
     340    pImage->uImageFlags = uImageFlags;
    326341    pImage->PCHSGeometry = *pPCHSGeometry;
    327342    pImage->LCHSGeometry = *pLCHSGeometry;
     
    331346        pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError);
    332347
    333 #ifdef VBOX_WITH_NEW_IO_CODE
    334     /* Try to get async I/O interface. */
     348    /* Get I/O interface. */
    335349    pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsImage, VDINTERFACETYPE_IO);
    336     AssertPtr(pImage->pInterfaceIO);
     350    AssertPtrReturn(pImage->pInterfaceIO, VERR_INVALID_PARAMETER);
    337351    pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO);
    338     AssertPtr(pImage->pInterfaceIOCallbacks);
    339 #endif
     352    AssertPtrReturn(pImage->pInterfaceIOCallbacks, VERR_INVALID_PARAMETER);
    340353
    341354    /* Create image file. */
    342     rc = rawFileOpen(pImage, false, true);
     355    rc = rawFileOpen(pImage, pImage->pszFilename,
     356                     VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags,
     357                                                true /* fCreate */));
    343358    if (RT_FAILURE(rc))
    344359    {
     
    349364    /* Check the free space on the disk and leave early if there is not
    350365     * sufficient space available. */
    351     rc = RTFsQuerySizes(pImage->pszFilename, NULL, &cbFree, NULL, NULL);
     366    rc = rawFileGetFreeSpace(pImage, pImage->pszFilename, &cbFree);
    352367    if (RT_SUCCESS(rc) /* ignore errors */ && ((uint64_t)cbFree < cbSize))
    353368    {
     
    417432}
    418433
    419 /**
    420  * Internal. Free all allocated space for representing an image, and optionally
    421  * delete the image from disk.
    422  */
    423 static void rawFreeImage(PRAWIMAGE pImage, bool fDelete)
    424 {
    425     Assert(pImage);
    426 
    427     if (rawFileOpened(pImage))
    428     {
    429         if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    430             rawFlushImage(pImage);
    431         rawFileClose(pImage);
    432     }
    433     if (fDelete && pImage->pszFilename)
    434         RTFileDelete(pImage->pszFilename);
    435 }
    436 
    437 /**
    438  * Internal. Flush image data to disk.
    439  */
    440 static int rawFlushImage(PRAWIMAGE pImage)
    441 {
    442     int rc = VINF_SUCCESS;
    443 
    444     if (   rawFileOpened(pImage)
    445         && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    446         rc = rawFileFlushSync(pImage);
    447 
    448     return rc;
    449 }
    450 
    451434
    452435/** @copydoc VBOXHDDBACKEND::pfnCheckIfValid */
    453 static int rawCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk)
     436static int rawCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk,
     437                           PVDINTERFACE pVDIfsImage)
    454438{
    455439    LogFlowFunc(("pszFilename=\"%s\"\n", pszFilename));
     
    464448
    465449    /* Always return failure, to avoid opening everything as a raw image. */
    466     rc = VERR_VD_RAW_INVALID_HEADER;
     450    rc = VERR_NOT_SUPPORTED;
    467451
    468452out:
     
    503487    }
    504488    pImage->pszFilename = pszFilename;
    505 #ifndef VBOX_WITH_NEW_IO_CODE
    506     pImage->File = NIL_RTFILE;
    507 #else
    508489    pImage->pStorage = NULL;
    509 #endif
    510490    pImage->pVDIfsDisk = pVDIfsDisk;
    511491    pImage->pVDIfsImage = pVDIfsImage;
     
    525505static int rawCreate(const char *pszFilename, uint64_t cbSize,
    526506                     unsigned uImageFlags, const char *pszComment,
    527                      PCPDMMEDIAGEOMETRY pPCHSGeometry,
    528                      PCPDMMEDIAGEOMETRY pLCHSGeometry, PCRTUUID pUuid,
    529                      unsigned uOpenFlags, unsigned uPercentStart,
    530                      unsigned uPercentSpan, PVDINTERFACE pVDIfsDisk,
    531                      PVDINTERFACE pVDIfsImage, PVDINTERFACE pVDIfsOperation,
    532                      void **ppBackendData)
     507                     PCVDGEOMETRY pPCHSGeometry, PCVDGEOMETRY pLCHSGeometry,
     508                     PCRTUUID pUuid, unsigned uOpenFlags,
     509                     unsigned uPercentStart, unsigned uPercentSpan,
     510                     PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
     511                     PVDINTERFACE pVDIfsOperation, void **ppBackendData)
    533512{
    534513    LogFlowFunc(("pszFilename=\"%s\" cbSize=%llu uImageFlags=%#x pszComment=\"%s\" pPCHSGeometry=%#p pLCHSGeometry=%#p Uuid=%RTuuid uOpenFlags=%#x uPercentStart=%u uPercentSpan=%u pVDIfsDisk=%#p pVDIfsImage=%#p pVDIfsOperation=%#p ppBackendData=%#p", pszFilename, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, ppBackendData));
     
    573552    }
    574553    pImage->pszFilename = pszFilename;
    575 #ifndef VBOX_WITH_NEW_IO_CODE
    576     pImage->File = NIL_RTFILE;
    577 #else
    578554    pImage->pStorage = NULL;
    579 #endif
    580555    pImage->pVDIfsDisk = pVDIfsDisk;
    581556    pImage->pVDIfsImage = pVDIfsImage;
    582557
    583558    rc = rawCreateImage(pImage, cbSize, uImageFlags, pszComment,
    584                         pPCHSGeometry, pLCHSGeometry,
     559                        pPCHSGeometry, pLCHSGeometry, uOpenFlags,
    585560                        pfnProgress, pvUser, uPercentStart, uPercentSpan);
    586561    if (RT_SUCCESS(rc))
     
    612587{
    613588    LogFlowFunc(("pBackendData=%#p pszFilename=%#p\n", pBackendData, pszFilename));
    614     int rc = VERR_NOT_IMPLEMENTED;
    615 
     589    int rc = VINF_SUCCESS;
     590    PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
     591
     592    /* Check arguments. */
     593    if (   !pImage
     594        || !pszFilename
     595        || !*pszFilename)
     596    {
     597        rc = VERR_INVALID_PARAMETER;
     598        goto out;
     599    }
     600
     601    /* Close the image. */
     602    rc = rawFreeImage(pImage, false);
     603    if (RT_FAILURE(rc))
     604        goto out;
     605
     606    /* Rename the file. */
     607    rc = rawFileMove(pImage, pImage->pszFilename, pszFilename, 0);
     608    if (RT_FAILURE(rc))
     609    {
     610        /* The move failed, try to reopen the original image. */
     611        int rc2 = rawOpenImage(pImage, pImage->uOpenFlags);
     612        if (RT_FAILURE(rc2))
     613            rc = rc2;
     614
     615        goto out;
     616    }
     617
     618    /* Update pImage with the new information. */
     619    pImage->pszFilename = pszFilename;
     620
     621    /* Open the old image with new name. */
     622    rc = rawOpenImage(pImage, pImage->uOpenFlags);
     623    if (RT_FAILURE(rc))
     624        goto out;
     625
     626out:
    616627    LogFlowFunc(("returns %Rrc\n", rc));
    617628    return rc;
     
    623634    LogFlowFunc(("pBackendData=%#p fDelete=%d\n", pBackendData, fDelete));
    624635    PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
    625     int rc = VINF_SUCCESS;
    626 
    627     /* Freeing a never allocated image (e.g. because the open failed) is
    628      * not signalled as an error. After all nothing bad happens. */
    629     if (pImage)
    630     {
    631         rawFreeImage(pImage, fDelete);
    632         RTMemFree(pImage);
    633     }
     636    int rc;
     637
     638    rc = rawFreeImage(pImage, fDelete);
     639    RTMemFree(pImage);
    634640
    635641    LogFlowFunc(("returns %Rrc\n", rc));
     
    645651    int rc;
    646652
    647     Assert(pImage);
     653    AssertPtr(pImage);
    648654    Assert(uOffset % 512 == 0);
    649655    Assert(cbToRead % 512 == 0);
     
    673679    int rc;
    674680
    675     Assert(pImage);
     681    AssertPtr(pImage);
    676682    Assert(uOffset % 512 == 0);
    677683    Assert(cbToWrite % 512 == 0);
     
    717723    PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
    718724
    719     Assert(pImage);
     725    AssertPtr(pImage);
    720726
    721727    if (pImage)
     
    730736    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
    731737    PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
    732 
    733     Assert(pImage);
    734 
    735     if (pImage)
    736         return pImage->cbSize;
    737     else
    738         return 0;
     738    uint64_t cb = 0;
     739
     740    AssertPtr(pImage);
     741
     742    if (pImage && pImage->pStorage)
     743        cb = pImage->cbSize;
     744
     745    LogFlowFunc(("returns %llu\n", cb));
     746    return cb;
    739747}
    740748
     
    746754    uint64_t cb = 0;
    747755
    748     Assert(pImage);
     756    AssertPtr(pImage);
    749757
    750758    if (pImage)
    751759    {
    752760        uint64_t cbFile;
    753         if (rawFileOpened(pImage))
     761        if (pImage->pStorage)
    754762        {
    755763            int rc = rawFileGetSize(pImage, &cbFile);
     
    765773/** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */
    766774static int rawGetPCHSGeometry(void *pBackendData,
    767                               PPDMMEDIAGEOMETRY pPCHSGeometry)
     775                              PVDGEOMETRY pPCHSGeometry)
    768776{
    769777    LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry));
     
    771779    int rc;
    772780
    773     Assert(pImage);
     781    AssertPtr(pImage);
    774782
    775783    if (pImage)
     
    792800/** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */
    793801static int rawSetPCHSGeometry(void *pBackendData,
    794                               PCPDMMEDIAGEOMETRY pPCHSGeometry)
     802                              PCVDGEOMETRY pPCHSGeometry)
    795803{
    796804    LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
     
    798806    int rc;
    799807
    800     Assert(pImage);
     808    AssertPtr(pImage);
    801809
    802810    if (pImage)
     
    821829/** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */
    822830static int rawGetLCHSGeometry(void *pBackendData,
    823                               PPDMMEDIAGEOMETRY pLCHSGeometry)
     831                              PVDGEOMETRY pLCHSGeometry)
    824832{
    825833     LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry));
     
    827835    int rc;
    828836
    829     Assert(pImage);
     837    AssertPtr(pImage);
    830838
    831839    if (pImage)
     
    848856/** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */
    849857static int rawSetLCHSGeometry(void *pBackendData,
    850                                PCPDMMEDIAGEOMETRY pLCHSGeometry)
     858                               PCVDGEOMETRY pLCHSGeometry)
    851859{
    852860    LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
     
    854862    int rc;
    855863
    856     Assert(pImage);
     864    AssertPtr(pImage);
    857865
    858866    if (pImage)
     
    882890    unsigned uImageFlags;
    883891
    884     Assert(pImage);
     892    AssertPtr(pImage);
    885893
    886894    if (pImage)
     
    900908    unsigned uOpenFlags;
    901909
    902     Assert(pImage);
     910    AssertPtr(pImage);
    903911
    904912    if (pImage)
     
    920928    /* Image must be opened and the new flags must be valid. Just readonly and
    921929     * info flags are supported. */
    922     if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO)))
     930    if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE)))
    923931    {
    924932        rc = VERR_INVALID_PARAMETER;
     
    927935
    928936    /* Implement this operation via reopening the image. */
    929     rawFreeImage(pImage, false);
     937    rc = rawFreeImage(pImage, false);
     938    if (RT_FAILURE(rc))
     939        goto out;
    930940    rc = rawOpenImage(pImage, uOpenFlags);
    931941
     
    943953    int rc;
    944954
    945     Assert(pImage);
    946 
    947     if (pImage)
    948     {
    949         if (pszComment)
    950             *pszComment = '\0';
    951         rc = VINF_SUCCESS;
    952     }
     955    AssertPtr(pImage);
     956
     957    if (pImage)
     958        rc = VERR_NOT_SUPPORTED;
    953959    else
    954960        rc = VERR_VD_NOT_OPENED;
     
    965971    int rc;
    966972
    967     Assert(pImage);
     973    AssertPtr(pImage);
    968974
    969975    if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     
    990996    int rc;
    991997
    992     Assert(pImage);
     998    AssertPtr(pImage);
    993999
    9941000    if (pImage)
     
    10091015
    10101016    LogFlowFunc(("%RTuuid\n", pUuid));
    1011     Assert(pImage);
     1017    AssertPtr(pImage);
    10121018
    10131019    if (pImage)
     
    10321038    int rc;
    10331039
    1034     Assert(pImage);
     1040    AssertPtr(pImage);
    10351041
    10361042    if (pImage)
     
    10501056    int rc;
    10511057
    1052     Assert(pImage);
     1058    AssertPtr(pImage);
    10531059
    10541060    if (pImage)
     
    10731079    int rc;
    10741080
    1075     Assert(pImage);
     1081    AssertPtr(pImage);
    10761082
    10771083    if (pImage)
     
    10911097    int rc;
    10921098
    1093     Assert(pImage);
     1099    AssertPtr(pImage);
    10941100
    10951101    if (pImage)
     
    11141120    int rc;
    11151121
    1116     Assert(pImage);
     1122    AssertPtr(pImage);
    11171123
    11181124    if (pImage)
     
    11321138    int rc;
    11331139
    1134     Assert(pImage);
     1140    AssertPtr(pImage);
    11351141
    11361142    if (pImage)
     
    11531159    PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
    11541160
    1155     Assert(pImage);
    1156     if (pImage)
    1157     {
    1158         pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n",
     1161    AssertPtr(pImage);
     1162    if (pImage)
     1163    {
     1164        rawMessage(pImage, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n",
    11591165                    pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors,
    11601166                    pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors,
     
    11631169}
    11641170
    1165 static int rawGetTimeStamp(void *pvBackendData, PRTTIMESPEC pTimeStamp)
    1166 {
    1167     int rc = VERR_NOT_IMPLEMENTED;
    1168     LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
    1169     return rc;
    1170 }
    1171 
    1172 static int rawGetParentTimeStamp(void *pvBackendData, PRTTIMESPEC pTimeStamp)
    1173 {
    1174     int rc = VERR_NOT_IMPLEMENTED;
    1175     LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
    1176     return rc;
    1177 }
    1178 
    1179 static int rawSetParentTimeStamp(void *pvBackendData, PCRTTIMESPEC pTimeStamp)
    1180 {
    1181     int rc = VERR_NOT_IMPLEMENTED;
    1182     LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
    1183     return rc;
    1184 }
    1185 
    1186 static int rawGetParentFilename(void *pvBackendData, char **ppszParentFilename)
    1187 {
    1188     int rc = VERR_NOT_IMPLEMENTED;
    1189     LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
    1190     return rc;
    1191 }
    1192 
    1193 static int rawSetParentFilename(void *pvBackendData, const char *pszParentFilename)
    1194 {
    1195     int rc = VERR_NOT_IMPLEMENTED;
    1196     LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
    1197     return rc;
    1198 }
    1199 
    1200 static bool rawIsAsyncIOSupported(void *pvBackendData)
     1171/** @copydoc VBOXHDDBACKEND::pfnIsAsyncIOSupported */
     1172static bool rawIsAsyncIOSupported(void *pBackendData)
    12011173{
    12021174    return true;
    12031175}
    12041176
    1205 static int rawAsyncRead(void *pvBackendData, uint64_t uOffset, size_t cbRead,
     1177/** @copydoc VBOXHDDBACKEND::pfnAsyncRead */
     1178static int rawAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbRead,
    12061179                        PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
    12071180{
    12081181    int rc = VINF_SUCCESS;
    1209     PRAWIMAGE pImage = (PRAWIMAGE)pvBackendData;
    1210 
    1211     rc = pImage->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser,
    1212                                                          pImage->pStorage,
    1213                                                          uOffset, pIoCtx, cbRead);
     1182    PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
     1183
     1184    rc = rawFileReadUserAsync(pImage, uOffset, pIoCtx, cbRead);
    12141185    if (RT_SUCCESS(rc))
    12151186        *pcbActuallyRead = cbRead;
     
    12181189}
    12191190
    1220 static int rawAsyncWrite(void *pvBackendData, uint64_t uOffset, size_t cbWrite,
     1191/** @copydoc VBOXHDDBACKEND::pfnAsyncWrite */
     1192static int rawAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbWrite,
    12211193                         PVDIOCTX pIoCtx,
    12221194                         size_t *pcbWriteProcess, size_t *pcbPreRead,
     
    12241196{
    12251197    int rc = VINF_SUCCESS;
    1226     PRAWIMAGE pImage = (PRAWIMAGE)pvBackendData;
    1227 
    1228     rc = pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser,
    1229                                                          pImage->pStorage,
    1230                                                          uOffset, pIoCtx, cbWrite,
    1231                                                          NULL, NULL);
    1232 
     1198    PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
     1199
     1200    rc = rawFileWriteUserAsync(pImage, uOffset, pIoCtx, cbWrite, NULL, NULL);
    12331201    if (RT_SUCCESS(rc))
    12341202    {
     
    12411209}
    12421210
    1243 static int rawAsyncFlush(void *pvBackendData, PVDIOCTX pIoCtx)
    1244 {
    1245     int rc = VERR_NOT_IMPLEMENTED;
    1246     LogFlowFunc(("returns %Rrc\n", rc));
    1247     return rc;
    1248 }
     1211/** @copydoc VBOXHDDBACKEND::pfnAsyncFlush */
     1212static int rawAsyncFlush(void *pBackendData, PVDIOCTX pIoCtx)
     1213{
     1214    int rc = VINF_SUCCESS;
     1215    PRAWIMAGE pImage = (PRAWIMAGE)pBackendData;
     1216
     1217    if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     1218        rc = rawFileFlushAsync(pImage, pIoCtx, NULL, NULL);
     1219
     1220    return rc;
     1221}
     1222
    12491223
    12501224VBOXHDDBACKEND g_RawBackend =
     
    12551229    sizeof(VBOXHDDBACKEND),
    12561230    /* uBackendCaps */
    1257     VD_CAP_CREATE_FIXED | VD_CAP_FILE | VD_CAP_ASYNC,
     1231    VD_CAP_CREATE_FIXED | VD_CAP_FILE | VD_CAP_ASYNC | VD_CAP_VFS,
    12581232    /* papszFileExtensions */
    12591233    s_apszRawFileExtensions,
     
    13211295    rawDump,
    13221296    /* pfnGetTimeStamp */
    1323     rawGetTimeStamp,
     1297    NULL,
    13241298    /* pfnGetParentTimeStamp */
    1325     rawGetParentTimeStamp,
     1299    NULL,
    13261300    /* pfnSetParentTimeStamp */
    1327     rawSetParentTimeStamp,
     1301    NULL,
    13281302    /* pfnGetParentFilename */
    1329     rawGetParentFilename,
     1303    NULL,
    13301304    /* pfnSetParentFilename */
    1331     rawSetParentFilename,
     1305    NULL,
    13321306    /* pfnIsAsyncIOSupported */
    13331307    rawIsAsyncIOSupported,
     
    13471321    NULL
    13481322};
    1349 
  • trunk/src/VBox/Devices/Storage/VBoxHDD.cpp

    r32520 r32536  
    7777    char            *pszFilename;
    7878    /** Data managed by the backend which keeps the actual info. */
    79     void            *pvBackendData;
     79    void            *pBackendData;
    8080    /** Cached sanitized image flags. */
    8181    unsigned        uImageFlags;
     
    110110    char            *pszFilename;
    111111    /** Data managed by the backend which keeps the actual info. */
    112     void            *pvBackendData;
     112    void            *pBackendData;
    113113    /** Cached sanitized image flags. */
    114114    unsigned        uImageFlags;
     
    151151    uint64_t            cbSize;
    152152    /** Cached PCHS geometry for this disk. */
    153     PDMMEDIAGEOMETRY    PCHSGeometry;
     153    VDGEOMETRY          PCHSGeometry;
    154154    /** Cached LCHS geometry for this disk. */
    155     PDMMEDIAGEOMETRY    LCHSGeometry;
     155    VDGEOMETRY          LCHSGeometry;
    156156
    157157    /** Pointer to list of VD interfaces, per-disk. */
     
    167167    PVDINTERFACETHREADSYNC pInterfaceThreadSyncCallbacks;
    168168
    169     /** I/O interface for the disk. */
    170     VDINTERFACE         VDIIO;
    171     /** I/O interface callback table for the images. */
     169    /** I/O interface callback table for the images (self-provided default
     170     * implementation supporting both sync and async file operations). */
    172171    VDINTERFACEIO       VDIIOCallbacks;
    173172
     
    707706    AssertPtr(pcbRead);
    708707
    709     rc = pCache->Backend->pfnRead(pCache->pvBackendData, uOffset, pvBuf,
     708    rc = pCache->Backend->pfnRead(pCache->pBackendData, uOffset, pvBuf,
    710709                                  cbRead, pcbRead);
    711710
     
    737736
    738737    if (pcbWritten)
    739         rc = pCache->Backend->pfnWrite(pCache->pvBackendData, uOffset, pcvBuf,
     738        rc = pCache->Backend->pfnWrite(pCache->pBackendData, uOffset, pcvBuf,
    740739                                       cbWrite, pcbWritten);
    741740    else
     
    745744        do
    746745        {
    747             rc = pCache->Backend->pfnWrite(pCache->pvBackendData, uOffset, pcvBuf,
     746            rc = pCache->Backend->pfnWrite(pCache->pBackendData, uOffset, pcvBuf,
    748747                                           cbWrite, &cbWritten);
    749748            uOffset += cbWritten;
     
    776775     * If the block is not allocated read from override chain if present.
    777776     */
    778     rc = pImage->Backend->pfnRead(pImage->pvBackendData,
     777    rc = pImage->Backend->pfnRead(pImage->pBackendData,
    779778                                  uOffset, pvBuf, cbThisRead,
    780779                                  &cbThisRead);
     
    786785             pCurrImage = pCurrImage->pPrev)
    787786        {
    788             rc = pCurrImage->Backend->pfnRead(pCurrImage->pvBackendData,
     787            rc = pCurrImage->Backend->pfnRead(pCurrImage->pBackendData,
    789788                                              uOffset, pvBuf, cbThisRead,
    790789                                              &cbThisRead);
     
    848847             * If the block is not allocated read from override chain if present.
    849848             */
    850             rc = pImage->Backend->pfnRead(pImage->pvBackendData,
     849            rc = pImage->Backend->pfnRead(pImage->pBackendData,
    851850                                          uOffset, pvBuf, cbThisRead,
    852851                                          &cbThisRead);
     
    858857                     pCurrImage = pCurrImage->pPrev)
    859858                {
    860                     rc = pCurrImage->Backend->pfnRead(pCurrImage->pvBackendData,
     859                    rc = pCurrImage->Backend->pfnRead(pCurrImage->pBackendData,
    861860                                                      uOffset, pvBuf, cbThisRead,
    862861                                                      &cbThisRead);
     
    11981197         * If the block is not allocated read from override chain if present.
    11991198         */
    1200         rc = pCurrImage->Backend->pfnAsyncRead(pCurrImage->pvBackendData,
     1199        rc = pCurrImage->Backend->pfnAsyncRead(pCurrImage->pBackendData,
    12011200                                               uOffset, cbThisRead,
    12021201                                               pIoCtx, &cbThisRead);
     
    12081207                 pCurrImage = pCurrImage->pPrev)
    12091208            {
    1210                 rc = pCurrImage->Backend->pfnAsyncRead(pCurrImage->pvBackendData,
     1209                rc = pCurrImage->Backend->pfnAsyncRead(pCurrImage->pBackendData,
    12111210                                                       uOffset, cbThisRead,
    12121211                                                       pIoCtx, &cbThisRead);
     
    12751274
    12761275            RTUuidCreate(&Uuid);
    1277             pDisk->pLast->Backend->pfnSetModificationUuid(pDisk->pLast->pvBackendData,
     1276            pDisk->pLast->Backend->pfnSetModificationUuid(pDisk->pLast->pBackendData,
    12781277                                                          &Uuid);
    12791278
    12801279            if (pDisk->pCache)
    1281                 pDisk->pCache->Backend->pfnSetModificationUuid(pDisk->pCache->pvBackendData,
     1280                pDisk->pCache->Backend->pfnSetModificationUuid(pDisk->pCache->pBackendData,
    12821281                                                               &Uuid);
    12831282        }
     
    13011300
    13021301        if (!(pDisk->uModified & VD_IMAGE_MODIFIED_DISABLE_UUID_UPDATE))
    1303             pDisk->pLast->Backend->pfnFlush(pDisk->pLast->pvBackendData);
     1302            pDisk->pLast->Backend->pfnFlush(pDisk->pLast->pBackendData);
    13041303    }
    13051304}
     
    13791378
    13801379    /* Write the full block to the virtual disk. */
    1381     rc = pImage->Backend->pfnWrite(pImage->pvBackendData,
     1380    rc = pImage->Backend->pfnWrite(pImage->pBackendData,
    13821381                                   uOffset - cbPreRead, pvTmp,
    13831382                                   cbPreRead + cbThisWrite + cbPostRead,
     
    14611460
    14621461    /* Write the full block to the virtual disk. */
    1463     rc = pImage->Backend->pfnWrite(pImage->pvBackendData,
     1462    rc = pImage->Backend->pfnWrite(pImage->pBackendData,
    14641463                                   uOffset - cbPreRead, pvTmp,
    14651464                                   cbPreRead + cbThisWrite + cbPostRead,
     
    15001499        fWrite =   (pImage->uOpenFlags & VD_OPEN_FLAGS_HONOR_SAME)
    15011500                 ? 0 : VD_WRITE_NO_ALLOC;
    1502         rc = pImage->Backend->pfnWrite(pImage->pvBackendData, uOffsetCur, pcvBufCur,
     1501        rc = pImage->Backend->pfnWrite(pImage->pBackendData, uOffsetCur, pcvBufCur,
    15031502                                       cbThisWrite, &cbThisWrite, &cbPreRead,
    15041503                                       &cbPostRead, fWrite);
     
    16191618        /* Write the full block to the virtual disk. */
    16201619        vdIoCtxChildReset(pIoCtxDst);
    1621         rc = pImage->Backend->pfnAsyncWrite(pImage->pvBackendData,
     1620        rc = pImage->Backend->pfnAsyncWrite(pImage->pBackendData,
    16221621                                            uOffset - cbPreRead,
    16231622                                            cbPreRead + cbThisWrite + cbPostRead,
     
    17141713    /* Write the full block to the virtual disk. */
    17151714    RTSgBufReset(&pIoCtx->SgBuf);
    1716     rc = pImage->Backend->pfnAsyncWrite(pImage->pvBackendData,
     1715    rc = pImage->Backend->pfnAsyncWrite(pImage->pBackendData,
    17171716                                        pIoCtx->uOffset - cbPreRead,
    17181717                                        cbPreRead + cbThisWrite + cbPostRead,
     
    18331832        fWrite =   (pImage->uOpenFlags & VD_OPEN_FLAGS_HONOR_SAME)
    18341833                 ? 0 : VD_WRITE_NO_ALLOC;
    1835         rc = pImage->Backend->pfnAsyncWrite(pImage->pvBackendData, uOffset,
     1834        rc = pImage->Backend->pfnAsyncWrite(pImage->pBackendData, uOffset,
    18361835                                            cbThisWrite, pIoCtx,
    18371836                                            &cbThisWrite, &cbPreRead,
     
    19701969
    19711970    vdResetModifiedFlag(pDisk);
    1972     rc = pImage->Backend->pfnAsyncFlush(pImage->pvBackendData, pIoCtx);
     1971    rc = pImage->Backend->pfnAsyncFlush(pImage->pBackendData, pIoCtx);
    19731972    if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
    19741973        rc = VINF_SUCCESS;
     
    22212220 * VD async I/O interface open callback.
    22222221 */
    2223 static int vdAsyncIOOpen(void *pvUser, const char *pszLocation, unsigned uOpenFlags,
     2222static int vdAsyncIOOpen(void *pvUser, const char *pszLocation, uint32_t fOpen,
    22242223                         PFNVDCOMPLETED pfnCompleted, PVDINTERFACE pVDIfsDisk,
    22252224                         void **ppStorage)
     
    22312230
    22322231    pStorage->pfnCompleted = pfnCompleted;
    2233 
    2234     uint32_t fOpen = 0;
    2235 
    2236     if (uOpenFlags & VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY)
    2237         fOpen |= RTFILE_O_READ | RTFILE_O_DENY_NONE;
    2238     else
    2239     {
    2240         fOpen |= RTFILE_O_READWRITE;
    2241 
    2242         if (uOpenFlags & VD_INTERFACEASYNCIO_OPEN_FLAGS_DONT_LOCK)
    2243             fOpen |= RTFILE_O_DENY_NONE;
    2244         else
    2245             fOpen |= RTFILE_O_DENY_WRITE;
    2246     }
    2247 
    2248     if (uOpenFlags & VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE)
    2249         fOpen |= RTFILE_O_CREATE;
    2250     else
    2251         fOpen |= RTFILE_O_OPEN;
    22522232
    22532233    /* Open the file. */
     
    22992279 */
    23002280static int vdAsyncIOWriteSync(void *pvUser, void *pvStorage, uint64_t uOffset,
    2301                              size_t cbWrite, const void *pvBuf, size_t *pcbWritten)
     2281                              const void *pvBuf, size_t cbWrite, size_t *pcbWritten)
    23022282{
    23032283    PVDIASYNCIOSTORAGE pStorage = (PVDIASYNCIOSTORAGE)pvStorage;
     
    23102290 */
    23112291static int vdAsyncIOReadSync(void *pvUser, void *pvStorage, uint64_t uOffset,
    2312                              size_t cbRead, void *pvBuf, size_t *pcbRead)
     2292                             void *pvBuf, size_t cbRead, size_t *pcbRead)
    23132293{
    23142294    PVDIASYNCIOSTORAGE pStorage = (PVDIASYNCIOSTORAGE)pvStorage;
     
    25132493    {
    25142494        RTCritSectEnter(&pDisk->CritSect);
    2515         rc = pfnComplete(pIoStorage->pImage->pvBackendData, pIoCtx, pvUser, rcReq);
     2495        rc = pfnComplete(pIoStorage->pImage->pBackendData, pIoCtx, pvUser, rcReq);
    25162496        RTCritSectLeave(&pDisk->CritSect);
    25172497    }
     
    25792559        {
    25802560            RTCritSectEnter(&pDisk->CritSect);
    2581             rc = pfnComplete(pIoStorage->pImage->pvBackendData, pIoCtx, pvUser, rcReq);
     2561            rc = pfnComplete(pIoStorage->pImage->pBackendData, pIoCtx, pvUser, rcReq);
    25822562            RTCritSectLeave(&pDisk->CritSect);
    25832563        }
     
    26972677}
    26982678
     2679static int vdIODelete(void *pvUser, const char *pcszFilename)
     2680{
     2681    return RTFileDelete(pcszFilename);
     2682}
     2683
     2684static int vdIOMove(void *pvUser, const char *pcszSrc, const char *pcszDst, unsigned fMove)
     2685{
     2686    return RTFileMove(pcszSrc, pcszDst, fMove);
     2687}
     2688
     2689static int vdIOGetFreeSpace(void *pvUser, const char *pcszFilename, int64_t *pcbFreeSpace)
     2690{
     2691    return RTFsQuerySizes(pcszFilename, NULL, pcbFreeSpace, NULL, NULL);
     2692}
     2693
     2694static int vdIOGetModificationTime(void *pvUser, const char *pcszFilename, PRTTIMESPEC pModificationTime)
     2695{
     2696    RTFSOBJINFO info;
     2697    int rc = RTPathQueryInfo(pcszFilename, &info, RTFSOBJATTRADD_NOTHING);
     2698    if (RT_SUCCESS(rc))
     2699        *pModificationTime = info.ModificationTime;
     2700    return rc;
     2701}
     2702
    26992703static int vdIOGetSize(void *pvUser, PVDIOSTORAGE pIoStorage,
    27002704                       uint64_t *pcbSize)
     
    27202724
    27212725static int vdIOWriteSync(void *pvUser, PVDIOSTORAGE pIoStorage, uint64_t uOffset,
    2722                          size_t cbWrite, const void *pvBuf, size_t *pcbWritten)
     2726                         const void *pvBuf, size_t cbWrite, size_t *pcbWritten)
    27232727{
    27242728    PVDIMAGE pImage = (PVDIMAGE)pvUser;
     
    27272731    return pDisk->pInterfaceAsyncIOCallbacks->pfnWriteSync(pDisk->pInterfaceAsyncIO->pvUser,
    27282732                                                           pIoStorage->u.pStorage,
    2729                                                            uOffset, cbWrite, pvBuf,
     2733                                                           uOffset, pvBuf, cbWrite,
    27302734                                                           pcbWritten);
    27312735}
    27322736
    27332737static int vdIOReadSync(void *pvUser, PVDIOSTORAGE pIoStorage, uint64_t uOffset,
    2734                         size_t cbRead, void *pvBuf, size_t *pcbRead)
     2738                        void *pvBuf, size_t cbRead, size_t *pcbRead)
    27352739{
    27362740    PVDIMAGE pImage = (PVDIMAGE)pvUser;
     
    27392743    return pDisk->pInterfaceAsyncIOCallbacks->pfnReadSync(pDisk->pInterfaceAsyncIO->pvUser,
    27402744                                                          pIoStorage->u.pStorage,
    2741                                                           uOffset, cbRead, pvBuf,
     2745                                                          uOffset, pvBuf, cbRead,
    27422746                                                          pcbRead);
    27432747}
     
    32473251 */
    32483252static int vdIOOpenLimited(void *pvUser, const char *pszLocation,
    3249                            unsigned uOpenFlags, PPVDIOSTORAGE ppIoStorage)
     3253                           uint32_t fOpen, PPVDIOSTORAGE ppIoStorage)
    32503254{
    32513255    int rc = VINF_SUCCESS;
     
    32543258    if (!pIoStorage)
    32553259        return VERR_NO_MEMORY;
    3256 
    3257     uint32_t fOpen = 0;
    3258 
    3259     if (uOpenFlags & VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY)
    3260         fOpen |= RTFILE_O_READ      | RTFILE_O_DENY_NONE;
    3261     else
    3262         fOpen |= RTFILE_O_READWRITE | RTFILE_O_DENY_WRITE;
    3263 
    3264     if (uOpenFlags & VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE)
    3265         fOpen |= RTFILE_O_CREATE;
    3266     else
    3267         fOpen |= RTFILE_O_OPEN;
    32683260
    32693261    rc = RTFileOpen(&pIoStorage->u.hFile, pszLocation, fOpen);
     
    32853277}
    32863278
     3279static int vdIODeleteLimited(void *pvUser, const char *pcszFilename)
     3280{
     3281    return RTFileDelete(pcszFilename);
     3282}
     3283
     3284static int vdIOMoveLimited(void *pvUser, const char *pcszSrc, const char *pcszDst, unsigned fMove)
     3285{
     3286    return RTFileMove(pcszSrc, pcszDst, fMove);
     3287}
     3288
     3289static int vdIOGetFreeSpaceLimited(void *pvUser, const char *pcszFilename, int64_t *pcbFreeSpace)
     3290{
     3291    return RTFsQuerySizes(pcszFilename, NULL, pcbFreeSpace, NULL, NULL);
     3292}
     3293
     3294static int vdIOGetModificationTimeLimited(void *pvUser, const char *pcszFilename, PRTTIMESPEC pModificationTime)
     3295{
     3296    RTFSOBJINFO info;
     3297    int rc = RTPathQueryInfo(pcszFilename, &info, RTFSOBJATTRADD_NOTHING);
     3298    if (RT_SUCCESS(rc))
     3299        *pModificationTime = info.ModificationTime;
     3300    return rc;
     3301}
     3302
    32873303static int vdIOGetSizeLimited(void *pvUser, PVDIOSTORAGE pIoStorage,
    32883304                       uint64_t *pcbSize)
     
    32983314
    32993315static int vdIOWriteSyncLimited(void *pvUser, PVDIOSTORAGE pIoStorage, uint64_t uOffset,
    3300                          size_t cbWrite, const void *pvBuf, size_t *pcbWritten)
     3316                         const void *pvBuf, size_t cbWrite, size_t *pcbWritten)
    33013317{
    33023318    return RTFileWriteAt(pIoStorage->u.hFile, uOffset, pvBuf, cbWrite, pcbWritten);
     
    33043320
    33053321static int vdIOReadSyncLimited(void *pvUser, PVDIOSTORAGE pIoStorage, uint64_t uOffset,
    3306                         size_t cbRead, void *pvBuf, size_t *pcbRead)
     3322                        void *pvBuf, size_t cbRead, size_t *pcbRead)
    33073323{
    33083324    return RTFileReadAt(pIoStorage->u.hFile, uOffset, pvBuf, cbRead, pcbRead);
     
    33183334 * internal: send output to the log (unconditionally).
    33193335 */
    3320 int vdLogMessage(void *pvUser, const char *pszFormat, ...)
     3336int vdLogMessage(void *pvUser, const char *pszFormat, va_list args)
    33213337{
    33223338    NOREF(pvUser);
    3323     va_list args;
    3324     va_start(args, pszFormat);
    3325     RTLogPrintf(pszFormat, args);
    3326     va_end(args);
     3339    RTLogPrintfV(pszFormat, args);
    33273340    return VINF_SUCCESS;
     3341}
     3342
     3343DECLINLINE(int) vdMessageWrapper(PVBOXHDD pDisk, const char *pszFormat, ...)
     3344{
     3345    va_list va;
     3346    va_start(va, pszFormat);
     3347    int rc = pDisk->pInterfaceErrorCallbacks->pfnMessage(pDisk->pInterfaceError->pvUser,
     3348                                                         pszFormat, va);
     3349    va_end(va);
     3350    return rc;
    33283351}
    33293352
     
    35923615            pDisk->VDIIOCallbacks.pfnOpen                = vdIOOpen;
    35933616            pDisk->VDIIOCallbacks.pfnClose               = vdIOClose;
     3617            pDisk->VDIIOCallbacks.pfnDelete              = vdIODelete;
     3618            pDisk->VDIIOCallbacks.pfnMove                = vdIOMove;
     3619            pDisk->VDIIOCallbacks.pfnGetFreeSpace        = vdIOGetFreeSpace;
     3620            pDisk->VDIIOCallbacks.pfnGetModificationTime = vdIOGetModificationTime;
    35943621            pDisk->VDIIOCallbacks.pfnGetSize             = vdIOGetSize;
    35953622            pDisk->VDIIOCallbacks.pfnSetSize             = vdIOSetSize;
     
    36523679 *          VERR_NOT_SUPPORTED if no backend was found.
    36533680 * @param   pVDIfsDisk      Pointer to the per-disk VD interface list.
     3681 * @param   pVDIfsImage     Pointer to the per-image VD interface list.
    36543682 * @param   pszFilename     Name of the image file for which the backend is queried.
    36553683 * @param   ppszFormat      Receives pointer of the UTF-8 string which contains the format name.
    36563684 *                          The returned pointer must be freed using RTStrFree().
    36573685 */
    3658 VBOXDDU_DECL(int) VDGetFormat(PVDINTERFACE pVDIfsDisk, const char *pszFilename, char **ppszFormat)
     3686VBOXDDU_DECL(int) VDGetFormat(PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
     3687                              const char *pszFilename, char **ppszFormat)
    36593688{
    36603689    int rc = VERR_NOT_SUPPORTED;
     
    36743703        VDInit();
    36753704
    3676     VDIIOCallbacks.cbSize            = sizeof(VDINTERFACEIO);
    3677     VDIIOCallbacks.enmInterface      = VDINTERFACETYPE_IO;
    3678     VDIIOCallbacks.pfnOpen           = vdIOOpenLimited;
    3679     VDIIOCallbacks.pfnClose          = vdIOCloseLimited;
    3680     VDIIOCallbacks.pfnGetSize        = vdIOGetSizeLimited;
    3681     VDIIOCallbacks.pfnSetSize        = vdIOSetSizeLimited;
    3682     VDIIOCallbacks.pfnReadSync       = vdIOReadSyncLimited;
    3683     VDIIOCallbacks.pfnWriteSync      = vdIOWriteSyncLimited;
    3684     VDIIOCallbacks.pfnFlushSync      = vdIOFlushSyncLimited;
    3685     VDIIOCallbacks.pfnReadUserAsync  = NULL;
    3686     VDIIOCallbacks.pfnWriteUserAsync = NULL;
    3687     VDIIOCallbacks.pfnReadMetaAsync  = NULL;
    3688     VDIIOCallbacks.pfnWriteMetaAsync = NULL;
    3689     VDIIOCallbacks.pfnFlushAsync     = NULL;
    3690     rc = VDInterfaceAdd(&VDIIO, "VD_IO", VDINTERFACETYPE_IO,
    3691                         &VDIIOCallbacks, NULL, &pVDIfsDisk);
    3692     AssertRC(rc);
     3705    if (!VDInterfaceGet(pVDIfsImage, VDINTERFACETYPE_IO))
     3706    {
     3707        VDIIOCallbacks.cbSize                    = sizeof(VDINTERFACEIO);
     3708        VDIIOCallbacks.enmInterface              = VDINTERFACETYPE_IO;
     3709        VDIIOCallbacks.pfnOpen                   = vdIOOpenLimited;
     3710        VDIIOCallbacks.pfnClose                  = vdIOCloseLimited;
     3711        VDIIOCallbacks.pfnDelete                 = vdIODeleteLimited;
     3712        VDIIOCallbacks.pfnMove                   = vdIOMoveLimited;
     3713        VDIIOCallbacks.pfnGetFreeSpace           = vdIOGetFreeSpaceLimited;
     3714        VDIIOCallbacks.pfnGetModificationTime    = vdIOGetModificationTimeLimited;
     3715        VDIIOCallbacks.pfnGetSize                = vdIOGetSizeLimited;
     3716        VDIIOCallbacks.pfnSetSize                = vdIOSetSizeLimited;
     3717        VDIIOCallbacks.pfnReadSync               = vdIOReadSyncLimited;
     3718        VDIIOCallbacks.pfnWriteSync              = vdIOWriteSyncLimited;
     3719        VDIIOCallbacks.pfnFlushSync              = vdIOFlushSyncLimited;
     3720        VDIIOCallbacks.pfnReadUserAsync          = NULL;
     3721        VDIIOCallbacks.pfnWriteUserAsync         = NULL;
     3722        VDIIOCallbacks.pfnReadMetaAsync          = NULL;
     3723        VDIIOCallbacks.pfnWriteMetaAsync         = NULL;
     3724        VDIIOCallbacks.pfnFlushAsync             = NULL;
     3725        rc = VDInterfaceAdd(&VDIIO, "VD_IO", VDINTERFACETYPE_IO,
     3726                            &VDIIOCallbacks, NULL, &pVDIfsImage);
     3727        AssertRC(rc);
     3728    }
    36933729
    36943730    /* Find the backend supporting this file format. */
     
    36973733        if (g_apBackends[i]->pfnCheckIfValid)
    36983734        {
    3699             rc = g_apBackends[i]->pfnCheckIfValid(pszFilename, pVDIfsDisk);
     3735            rc = g_apBackends[i]->pfnCheckIfValid(pszFilename, pVDIfsDisk,
     3736                                                  pVDIfsImage);
    37003737            if (    RT_SUCCESS(rc)
    37013738                /* The correct backend has been found, but there is a small
     
    37083745                     && rc != VERR_VD_ISCSI_INVALID_HEADER
    37093746                     && rc != VERR_VD_VHD_INVALID_HEADER
    3710                      && rc != VERR_VD_RAW_INVALID_HEADER))
     3747                     && rc != VERR_VD_RAW_INVALID_HEADER
     3748                     && rc != VERR_VD_DMG_INVALID_HEADER))
    37113749            {
    37123750                /* Copy the name into the new string. */
     
    37323770            if (g_apCacheBackends[i]->pfnProbe)
    37333771            {
    3734                 rc = g_apCacheBackends[i]->pfnProbe(pszFilename, pVDIfsDisk);
     3772                rc = g_apCacheBackends[i]->pfnProbe(pszFilename, pVDIfsDisk,
     3773                                                    pVDIfsImage);
    37353774                if (    RT_SUCCESS(rc)
    37363775                    ||  (rc != VERR_VD_GEN_INVALID_HEADER))
     
    38323871        }
    38333872
    3834         /* Set up the I/O interface. */
    3835         rc = VDInterfaceAdd(&pImage->VDIIO, "VD_IO", VDINTERFACETYPE_IO,
    3836                             &pDisk->VDIIOCallbacks, pImage, &pImage->pVDIfsImage);
    3837         AssertRC(rc);
     3873        /* Set up the I/O interface if necessary. */
     3874        if (!VDInterfaceGet(pVDIfsImage, VDINTERFACETYPE_IO))
     3875        {
     3876            rc = VDInterfaceAdd(&pImage->VDIIO, "VD_IO", VDINTERFACETYPE_IO,
     3877                                &pDisk->VDIIOCallbacks, pImage,
     3878                                &pImage->pVDIfsImage);
     3879            AssertRC(rc);
     3880        }
    38383881
    38393882        pImage->uOpenFlags = uOpenFlags & VD_OPEN_FLAGS_HONOR_SAME;
     
    38423885                                      pDisk->pVDIfsDisk,
    38433886                                      pImage->pVDIfsImage,
    3844                                       &pImage->pvBackendData);
     3887                                      &pImage->pBackendData);
    38453888        /* If the open in read-write mode failed, retry in read-only mode. */
    38463889        if (RT_FAILURE(rc))
     
    38573900                                               pDisk->pVDIfsDisk,
    38583901                                               pImage->pVDIfsImage,
    3859                                                &pImage->pvBackendData);
     3902                                               &pImage->pBackendData);
    38603903            if (RT_FAILURE(rc))
    38613904            {
     
    38773920         * and diff images, so this must be corrected here. */
    38783921        unsigned uImageFlags;
    3879         uImageFlags = pImage->Backend->pfnGetImageFlags(pImage->pvBackendData);
     3922        uImageFlags = pImage->Backend->pfnGetImageFlags(pImage->pBackendData);
    38803923        if (RT_FAILURE(rc))
    38813924            uImageFlags = VD_IMAGE_FLAGS_NONE;
     
    39063949        RTUUID parentUuid;
    39073950        RTUuidClear(&parentUuid);
    3908         rc2 = pImage->Backend->pfnGetParentUuid(pImage->pvBackendData, &parentUuid);
     3951        rc2 = pImage->Backend->pfnGetParentUuid(pImage->pBackendData, &parentUuid);
    39093952        if (RT_SUCCESS(rc2) && !RTUuidIsNull(&parentUuid))
    39103953            uImageFlags |= VD_IMAGE_FLAGS_DIFF;
     
    39203963
    39213964        /* Cache disk information. */
    3922         pDisk->cbSize = pImage->Backend->pfnGetSize(pImage->pvBackendData);
     3965        pDisk->cbSize = pImage->Backend->pfnGetSize(pImage->pBackendData);
    39233966
    39243967        /* Cache PCHS geometry. */
    3925         rc2 = pImage->Backend->pfnGetPCHSGeometry(pImage->pvBackendData,
     3968        rc2 = pImage->Backend->pfnGetPCHSGeometry(pImage->pBackendData,
    39263969                                                  &pDisk->PCHSGeometry);
    39273970        if (RT_FAILURE(rc2))
     
    39403983
    39413984        /* Cache LCHS geometry. */
    3942         rc2 = pImage->Backend->pfnGetLCHSGeometry(pImage->pvBackendData,
     3985        rc2 = pImage->Backend->pfnGetLCHSGeometry(pImage->pBackendData,
    39433986                                                  &pDisk->LCHSGeometry);
    39443987        if (RT_FAILURE(rc2))
     
    39594002            /* Switch previous image to read-only mode. */
    39604003            unsigned uOpenFlagsPrevImg;
    3961             uOpenFlagsPrevImg = pDisk->pLast->Backend->pfnGetOpenFlags(pDisk->pLast->pvBackendData);
     4004            uOpenFlagsPrevImg = pDisk->pLast->Backend->pfnGetOpenFlags(pDisk->pLast->pBackendData);
    39624005            if (!(uOpenFlagsPrevImg & VD_OPEN_FLAGS_READONLY))
    39634006            {
    39644007                uOpenFlagsPrevImg |= VD_OPEN_FLAGS_READONLY;
    3965                 rc = pDisk->pLast->Backend->pfnSetOpenFlags(pDisk->pLast->pvBackendData, uOpenFlagsPrevImg);
     4008                rc = pDisk->pLast->Backend->pfnSetOpenFlags(pDisk->pLast->pBackendData, uOpenFlagsPrevImg);
    39664009            }
    39674010        }
     
    39774020        {
    39784021            /* Error detected, but image opened. Close image. */
    3979             rc2 = pImage->Backend->pfnClose(pImage->pvBackendData, false);
     4022            rc2 = pImage->Backend->pfnClose(pImage->pBackendData, false);
    39804023            AssertRC(rc2);
    3981             pImage->pvBackendData = NULL;
     4024            pImage->pBackendData = NULL;
    39824025        }
    39834026    } while (0);
     
    40794122                                      pDisk->pVDIfsDisk,
    40804123                                      pCache->pVDIfsCache,
    4081                                       &pCache->pvBackendData);
     4124                                      &pCache->pBackendData);
    40824125        /* If the open in read-write mode failed, retry in read-only mode. */
    40834126        if (RT_FAILURE(rc))
     
    40944137                                               pDisk->pVDIfsDisk,
    40954138                                               pCache->pVDIfsCache,
    4096                                                &pCache->pvBackendData);
     4139                                               &pCache->pBackendData);
    40974140            if (RT_FAILURE(rc))
    40984141            {
     
    41154158        RTUUID UuidImage, UuidCache;
    41164159
    4117         rc = pCache->Backend->pfnGetModificationUuid(pCache->pvBackendData,
     4160        rc = pCache->Backend->pfnGetModificationUuid(pCache->pBackendData,
    41184161                                                     &UuidCache);
    41194162        if (RT_SUCCESS(rc))
    41204163        {
    4121             rc = pDisk->pLast->Backend->pfnGetModificationUuid(pDisk->pLast->pvBackendData,
     4164            rc = pDisk->pLast->Backend->pfnGetModificationUuid(pDisk->pLast->pBackendData,
    41224165                                                               &UuidImage);
    41234166            if (RT_SUCCESS(rc))
     
    41474190        {
    41484191            /* Error detected, but image opened. Close image. */
    4149             rc2 = pCache->Backend->pfnClose(pCache->pvBackendData, false);
     4192            rc2 = pCache->Backend->pfnClose(pCache->pBackendData, false);
    41504193            AssertRC(rc2);
    4151             pCache->pvBackendData = NULL;
     4194            pCache->pBackendData = NULL;
    41524195        }
    41534196    } while (0);
     
    41934236                               const char *pszFilename, uint64_t cbSize,
    41944237                               unsigned uImageFlags, const char *pszComment,
    4195                                PCPDMMEDIAGEOMETRY pPCHSGeometry,
    4196                                PCPDMMEDIAGEOMETRY pLCHSGeometry,
     4238                               PCVDGEOMETRY pPCHSGeometry,
     4239                               PCVDGEOMETRY pLCHSGeometry,
    41974240                               PCRTUUID pUuid, unsigned uOpenFlags,
    41984241                               PVDINTERFACE pVDIfsImage,
     
    42904333        pImage->pVDIfsImage = pVDIfsImage;
    42914334
    4292         /* Set up the I/O interface. */
    4293         rc = VDInterfaceAdd(&pImage->VDIIO, "VD_IO", VDINTERFACETYPE_IO,
    4294                             &pDisk->VDIIOCallbacks, pImage, &pImage->pVDIfsImage);
    4295         AssertRC(rc);
     4335        /* Set up the I/O interface if necessary. */
     4336        if (!VDInterfaceGet(pVDIfsImage, VDINTERFACETYPE_IO))
     4337        {
     4338            rc = VDInterfaceAdd(&pImage->VDIIO, "VD_IO", VDINTERFACETYPE_IO,
     4339                                &pDisk->VDIIOCallbacks, pImage,
     4340                                &pImage->pVDIfsImage);
     4341            AssertRC(rc);
     4342        }
    42964343
    42974344        rc = vdFindBackend(pszBackend, &pImage->Backend);
     
    43294376                                        pImage->pVDIfsImage,
    43304377                                        pVDIfsOperation,
    4331                                         &pImage->pvBackendData);
     4378                                        &pImage->pBackendData);
    43324379
    43334380        if (RT_SUCCESS(rc))
     
    43574404        {
    43584405            /* Cache disk information. */
    4359             pDisk->cbSize = pImage->Backend->pfnGetSize(pImage->pvBackendData);
     4406            pDisk->cbSize = pImage->Backend->pfnGetSize(pImage->pBackendData);
    43604407
    43614408            /* Cache PCHS geometry. */
    4362             rc2 = pImage->Backend->pfnGetPCHSGeometry(pImage->pvBackendData,
     4409            rc2 = pImage->Backend->pfnGetPCHSGeometry(pImage->pBackendData,
    43634410                                                      &pDisk->PCHSGeometry);
    43644411            if (RT_FAILURE(rc2))
     
    43774424
    43784425            /* Cache LCHS geometry. */
    4379             rc2 = pImage->Backend->pfnGetLCHSGeometry(pImage->pvBackendData,
     4426            rc2 = pImage->Backend->pfnGetLCHSGeometry(pImage->pBackendData,
    43804427                                                      &pDisk->LCHSGeometry);
    43814428            if (RT_FAILURE(rc2))
     
    44004447        {
    44014448            /* Error detected, but image opened. Close and delete image. */
    4402             rc2 = pImage->Backend->pfnClose(pImage->pvBackendData, true);
     4449            rc2 = pImage->Backend->pfnClose(pImage->pBackendData, true);
    44034450            AssertRC(rc2);
    4404             pImage->pvBackendData = NULL;
     4451            pImage->pBackendData = NULL;
    44054452        }
    44064453    } while (0);
     
    45394586        pImage->pVDIfsImage = pVDIfsImage;
    45404587
    4541         /* Set up the I/O interface. */
    4542         rc = VDInterfaceAdd(&pImage->VDIIO, "VD_IO", VDINTERFACETYPE_IO,
    4543                             &pDisk->VDIIOCallbacks, pImage, &pImage->pVDIfsImage);
    4544         AssertRC(rc);
     4588        /* Set up the I/O interface if necessary. */
     4589        if (!VDInterfaceGet(pVDIfsImage, VDINTERFACETYPE_IO))
     4590        {
     4591            rc = VDInterfaceAdd(&pImage->VDIIO, "VD_IO", VDINTERFACETYPE_IO,
     4592                                &pDisk->VDIIOCallbacks, pImage,
     4593                                &pImage->pVDIfsImage);
     4594            AssertRC(rc);
     4595        }
    45454596
    45464597        /* Create UUID if the caller didn't specify one. */
     
    45694620                                        pImage->pVDIfsImage,
    45704621                                        pVDIfsOperation,
    4571                                         &pImage->pvBackendData);
     4622                                        &pImage->pBackendData);
    45724623
    45734624        if (RT_SUCCESS(rc))
     
    45824633            /* Switch previous image to read-only mode. */
    45834634            unsigned uOpenFlagsPrevImg;
    4584             uOpenFlagsPrevImg = pDisk->pLast->Backend->pfnGetOpenFlags(pDisk->pLast->pvBackendData);
     4635            uOpenFlagsPrevImg = pDisk->pLast->Backend->pfnGetOpenFlags(pDisk->pLast->pBackendData);
    45854636            if (!(uOpenFlagsPrevImg & VD_OPEN_FLAGS_READONLY))
    45864637            {
    45874638                uOpenFlagsPrevImg |= VD_OPEN_FLAGS_READONLY;
    4588                 rc = pDisk->pLast->Backend->pfnSetOpenFlags(pDisk->pLast->pvBackendData, uOpenFlagsPrevImg);
     4639                rc = pDisk->pLast->Backend->pfnSetOpenFlags(pDisk->pLast->pBackendData, uOpenFlagsPrevImg);
    45894640            }
    45904641
     
    46064657            {
    46074658                Uuid = *pParentUuid;
    4608                 pImage->Backend->pfnSetParentUuid(pImage->pvBackendData, &Uuid);
     4659                pImage->Backend->pfnSetParentUuid(pImage->pBackendData, &Uuid);
    46094660            }
    46104661            else
    46114662            {
    4612                 rc2 = pDisk->pLast->Backend->pfnGetUuid(pDisk->pLast->pvBackendData,
     4663                rc2 = pDisk->pLast->Backend->pfnGetUuid(pDisk->pLast->pBackendData,
    46134664                                                        &Uuid);
    46144665                if (RT_SUCCESS(rc2))
    4615                     pImage->Backend->pfnSetParentUuid(pImage->pvBackendData, &Uuid);
     4666                    pImage->Backend->pfnSetParentUuid(pImage->pBackendData, &Uuid);
    46164667            }
    4617             rc2 = pDisk->pLast->Backend->pfnGetModificationUuid(pDisk->pLast->pvBackendData,
     4668            rc2 = pDisk->pLast->Backend->pfnGetModificationUuid(pDisk->pLast->pBackendData,
    46184669                                                                &Uuid);
    46194670            if (RT_SUCCESS(rc2))
    4620                 pImage->Backend->pfnSetParentModificationUuid(pImage->pvBackendData,
     4671                pImage->Backend->pfnSetParentModificationUuid(pImage->pBackendData,
    46214672                                                              &Uuid);
    4622             rc2 = pDisk->pLast->Backend->pfnGetTimeStamp(pDisk->pLast->pvBackendData,
    4623                                                          &ts);
    4624             if (RT_SUCCESS(rc2))
    4625                 pImage->Backend->pfnSetParentTimeStamp(pImage->pvBackendData, &ts);
    4626 
    4627             rc2 = pImage->Backend->pfnSetParentFilename(pImage->pvBackendData, pDisk->pLast->pszFilename);
     4673            if (pDisk->pLast->Backend->pfnGetTimeStamp)
     4674                rc2 = pDisk->pLast->Backend->pfnGetTimeStamp(pDisk->pLast->pBackendData,
     4675                                                             &ts);
     4676            else
     4677                rc = VERR_NOT_IMPLEMENTED;
     4678            if (RT_SUCCESS(rc2) && pImage->Backend->pfnSetParentTimeStamp)
     4679                pImage->Backend->pfnSetParentTimeStamp(pImage->pBackendData, &ts);
     4680
     4681            if (pImage->Backend->pfnSetParentFilename)
     4682                rc2 = pImage->Backend->pfnSetParentFilename(pImage->pBackendData, pDisk->pLast->pszFilename);
    46284683        }
    46294684
     
    46384693        {
    46394694            /* Error detected, but image opened. Close and delete image. */
    4640             rc2 = pImage->Backend->pfnClose(pImage->pvBackendData, true);
     4695            rc2 = pImage->Backend->pfnClose(pImage->pBackendData, true);
    46414696            AssertRC(rc2);
    4642             pImage->pvBackendData = NULL;
     4697            pImage->pBackendData = NULL;
    46434698        }
    46444699    } while (0);
     
    48054860                                        pCache->pVDIfsCache,
    48064861                                        pVDIfsOperation,
    4807                                         &pCache->pvBackendData);
     4862                                        &pCache->pBackendData);
    48084863
    48094864        if (RT_SUCCESS(rc))
     
    48264881
    48274882            /* Set same modification Uuid as the last image. */
    4828             rc = pDisk->pLast->Backend->pfnGetModificationUuid(pDisk->pLast->pvBackendData,
     4883            rc = pDisk->pLast->Backend->pfnGetModificationUuid(pDisk->pLast->pBackendData,
    48294884                                                               &UuidModification);
    48304885            if (RT_SUCCESS(rc))
    48314886            {
    4832                 rc = pCache->Backend->pfnSetModificationUuid(pCache->pvBackendData,
     4887                rc = pCache->Backend->pfnSetModificationUuid(pCache->pBackendData,
    48334888                                                             &UuidModification);
    48344889            }
     
    48464901        {
    48474902            /* Error detected, but image opened. Close and delete image. */
    4848             rc2 = pCache->Backend->pfnClose(pCache->pvBackendData, true);
     4903            rc2 = pCache->Backend->pfnClose(pCache->pBackendData, true);
    48494904            AssertRC(rc2);
    4850             pCache->pvBackendData = NULL;
     4905            pCache->pBackendData = NULL;
    48514906        }
    48524907    } while (0);
     
    49314986
    49324987        /* Make sure destination image is writable. */
    4933         unsigned uOpenFlags = pImageTo->Backend->pfnGetOpenFlags(pImageTo->pvBackendData);
     4988        unsigned uOpenFlags = pImageTo->Backend->pfnGetOpenFlags(pImageTo->pBackendData);
    49344989        if (uOpenFlags & VD_OPEN_FLAGS_READONLY)
    49354990        {
    49364991            uOpenFlags &= ~VD_OPEN_FLAGS_READONLY;
    4937             rc = pImageTo->Backend->pfnSetOpenFlags(pImageTo->pvBackendData,
     4992            rc = pImageTo->Backend->pfnSetOpenFlags(pImageTo->pBackendData,
    49384993                                                    uOpenFlags);
    49394994            if (RT_FAILURE(rc))
     
    49424997
    49434998        /* Get size of destination image. */
    4944         uint64_t cbSize = pImageTo->Backend->pfnGetSize(pImageTo->pvBackendData);
     4999        uint64_t cbSize = pImageTo->Backend->pfnGetSize(pImageTo->pBackendData);
    49455000        rc2 = vdThreadFinishWrite(pDisk);
    49465001        AssertRC(rc2);
     
    49735028                fLockWrite = true;
    49745029
    4975                 rc = pImageTo->Backend->pfnRead(pImageTo->pvBackendData,
     5030                rc = pImageTo->Backend->pfnRead(pImageTo->pBackendData,
    49765031                                                uOffset, pvBuf, cbThisRead,
    49775032                                                &cbThisRead);
     
    49865041                         pCurrImage = pCurrImage->pPrev)
    49875042                    {
    4988                         rc = pCurrImage->Backend->pfnRead(pCurrImage->pvBackendData,
     5043                        rc = pCurrImage->Backend->pfnRead(pCurrImage->pBackendData,
    49895044                                                          uOffset, pvBuf,
    49905045                                                          cbThisRead,
     
    50475102
    50485103                /* We need to open the image in read/write mode. */
    5049                 uOpenFlags = pImageChild->Backend->pfnGetOpenFlags(pImageChild->pvBackendData);
     5104                uOpenFlags = pImageChild->Backend->pfnGetOpenFlags(pImageChild->pBackendData);
    50505105
    50515106                if (uOpenFlags  & VD_OPEN_FLAGS_READONLY)
    50525107                {
    50535108                    uOpenFlags  &= ~VD_OPEN_FLAGS_READONLY;
    5054                     rc = pImageChild->Backend->pfnSetOpenFlags(pImageChild->pvBackendData,
     5109                    rc = pImageChild->Backend->pfnSetOpenFlags(pImageChild->pBackendData,
    50555110                                                               uOpenFlags);
    50565111                    if (RT_FAILURE(rc))
     
    50865141                     pCurrImage = pCurrImage->pPrev)
    50875142                {
    5088                     rc = pCurrImage->Backend->pfnRead(pCurrImage->pvBackendData,
     5143                    rc = pCurrImage->Backend->pfnRead(pCurrImage->pBackendData,
    50895144                                                      uOffset, pvBuf,
    50905145                                                      cbThisRead, &cbThisRead);
     
    51425197            if (pImageFrom->pPrev)
    51435198            {
    5144                 rc = pImageFrom->pPrev->Backend->pfnGetUuid(pImageFrom->pPrev->pvBackendData,
     5199                rc = pImageFrom->pPrev->Backend->pfnGetUuid(pImageFrom->pPrev->pBackendData,
    51455200                                                            &Uuid);
    51465201                AssertRC(rc);
     
    51485203            else
    51495204                RTUuidClear(&Uuid);
    5150             rc = pImageTo->Backend->pfnSetParentUuid(pImageTo->pvBackendData,
     5205            rc = pImageTo->Backend->pfnSetParentUuid(pImageTo->pBackendData,
    51515206                                                     &Uuid);
    51525207            AssertRC(rc);
     
    51575212            if (pImageFrom->pNext)
    51585213            {
    5159                 rc = pImageTo->Backend->pfnGetUuid(pImageTo->pvBackendData,
     5214                rc = pImageTo->Backend->pfnGetUuid(pImageTo->pBackendData,
    51605215                                                   &Uuid);
    51615216                AssertRC(rc);
    51625217
    5163                 rc = pImageFrom->Backend->pfnSetParentUuid(pImageFrom->pNext->pvBackendData,
     5218                rc = pImageFrom->Backend->pfnSetParentUuid(pImageFrom->pNext->pBackendData,
    51645219                                                           &Uuid);
    51655220                AssertRC(rc);
     
    51785233                pTmp = pImg->pPrev;
    51795234            vdRemoveImageFromList(pDisk, pImg);
    5180             pImg->Backend->pfnClose(pImg->pvBackendData, true);
     5235            pImg->Backend->pfnClose(pImg->pBackendData, true);
    51815236            RTMemFree(pImg->pszFilename);
    51825237            RTMemFree(pImg);
     
    51875242        if (pImageTo != pDisk->pLast)
    51885243        {
    5189             uOpenFlags = pImageTo->Backend->pfnGetOpenFlags(pImageTo->pvBackendData);
     5244            uOpenFlags = pImageTo->Backend->pfnGetOpenFlags(pImageTo->pBackendData);
    51905245            uOpenFlags |= VD_OPEN_FLAGS_READONLY;
    5191             rc = pImageTo->Backend->pfnSetOpenFlags(pImageTo->pvBackendData,
     5246            rc = pImageTo->Backend->pfnSetOpenFlags(pImageTo->pBackendData,
    51925247                                                    uOpenFlags);
    51935248            if (RT_FAILURE(rc))
     
    52045259            && pImageChild != pDisk->pLast)
    52055260        {
    5206             uOpenFlags = pImageChild->Backend->pfnGetOpenFlags(pImageChild->pvBackendData);
     5261            uOpenFlags = pImageChild->Backend->pfnGetOpenFlags(pImageChild->pBackendData);
    52075262            uOpenFlags |= VD_OPEN_FLAGS_READONLY;
    5208             rc = pImageChild->Backend->pfnSetOpenFlags(pImageChild->pvBackendData,
     5263            rc = pImageChild->Backend->pfnSetOpenFlags(pImageChild->pBackendData,
    52095264                                                       uOpenFlags);
    52105265            if (RT_FAILURE(rc))
     
    53125367        if (pDiskFrom == pDiskTo)
    53135368        {
    5314             /* Rename only works when backends are the same. */
     5369            /* Rename only works when backends are the same, are file based
     5370             * and the rename method is implemented. */
    53155371            if (    fMoveByRename
    5316                 &&  !RTStrICmp(pszBackend, pImageFrom->Backend->pszBackendName))
     5372                &&  !RTStrICmp(pszBackend, pImageFrom->Backend->pszBackendName)
     5373                &&  pImageFrom->Backend->uBackendCaps & VD_CAP_FILE
     5374                &&  pImageFrom->Backend->pfnRename)
    53175375            {
    53185376                rc2 = vdThreadFinishRead(pDiskFrom);
     
    53235381                AssertRC(rc2);
    53245382                fLockWriteFrom = true;
    5325                 rc = pImageFrom->Backend->pfnRename(pImageFrom->pvBackendData, pszFilename ? pszFilename : pImageFrom->pszFilename);
     5383                rc = pImageFrom->Backend->pfnRename(pImageFrom->pBackendData, pszFilename ? pszFilename : pImageFrom->pszFilename);
    53265384                break;
    53275385            }
     
    53395397
    53405398        uint64_t cbSizeFrom;
    5341         cbSizeFrom = pImageFrom->Backend->pfnGetSize(pImageFrom->pvBackendData);
     5399        cbSizeFrom = pImageFrom->Backend->pfnGetSize(pImageFrom->pBackendData);
    53425400        if (cbSizeFrom == 0)
    53435401        {
     
    53465404        }
    53475405
    5348         PDMMEDIAGEOMETRY PCHSGeometryFrom = {0, 0, 0};
    5349         PDMMEDIAGEOMETRY LCHSGeometryFrom = {0, 0, 0};
    5350         pImageFrom->Backend->pfnGetPCHSGeometry(pImageFrom->pvBackendData, &PCHSGeometryFrom);
    5351         pImageFrom->Backend->pfnGetLCHSGeometry(pImageFrom->pvBackendData, &LCHSGeometryFrom);
     5406        VDGEOMETRY PCHSGeometryFrom = {0, 0, 0};
     5407        VDGEOMETRY LCHSGeometryFrom = {0, 0, 0};
     5408        pImageFrom->Backend->pfnGetPCHSGeometry(pImageFrom->pBackendData, &PCHSGeometryFrom);
     5409        pImageFrom->Backend->pfnGetLCHSGeometry(pImageFrom->pBackendData, &LCHSGeometryFrom);
    53525410
    53535411        RTUUID ImageUuid, ImageModificationUuid;
     
    53615419        else
    53625420        {
    5363             rc = pImageFrom->Backend->pfnGetUuid(pImageFrom->pvBackendData, &ImageUuid);
     5421            rc = pImageFrom->Backend->pfnGetUuid(pImageFrom->pBackendData, &ImageUuid);
    53645422            if (RT_FAILURE(rc))
    53655423                RTUuidCreate(&ImageUuid);
    53665424        }
    5367         rc = pImageFrom->Backend->pfnGetModificationUuid(pImageFrom->pvBackendData, &ImageModificationUuid);
     5425        rc = pImageFrom->Backend->pfnGetModificationUuid(pImageFrom->pBackendData, &ImageModificationUuid);
    53685426        if (RT_FAILURE(rc))
    53695427            RTUuidClear(&ImageModificationUuid);
    53705428
    53715429        char szComment[1024];
    5372         rc = pImageFrom->Backend->pfnGetComment(pImageFrom->pvBackendData, szComment, sizeof(szComment));
     5430        rc = pImageFrom->Backend->pfnGetComment(pImageFrom->pBackendData, szComment, sizeof(szComment));
    53735431        if (RT_FAILURE(rc))
    53745432            szComment[0] = '\0';
     
    53775435
    53785436        unsigned uOpenFlagsFrom;
    5379         uOpenFlagsFrom = pImageFrom->Backend->pfnGetOpenFlags(pImageFrom->pvBackendData);
     5437        uOpenFlagsFrom = pImageFrom->Backend->pfnGetOpenFlags(pImageFrom->pBackendData);
    53805438
    53815439        rc2 = vdThreadFinishRead(pDiskFrom);
     
    54405498
    54415499                if (RT_SUCCESS(rc) && !RTUuidIsNull(&ImageUuid))
    5442                      pDiskTo->pLast->Backend->pfnSetUuid(pDiskTo->pLast->pvBackendData, &ImageUuid);
     5500                     pDiskTo->pLast->Backend->pfnSetUuid(pDiskTo->pLast->pBackendData, &ImageUuid);
    54435501            }
    54445502            if (RT_FAILURE(rc))
     
    54565514
    54575515            uint64_t cbSizeTo;
    5458             cbSizeTo = pImageTo->Backend->pfnGetSize(pImageTo->pvBackendData);
     5516            cbSizeTo = pImageTo->Backend->pfnGetSize(pImageTo->pBackendData);
    54595517            if (cbSizeTo == 0)
    54605518            {
     
    55665624             * backend might not provide a valid modification UUID. */
    55675625            if (!RTUuidIsNull(&ImageModificationUuid))
    5568                 pImageTo->Backend->pfnSetModificationUuid(pImageTo->pvBackendData, &ImageModificationUuid);
     5626                pImageTo->Backend->pfnSetModificationUuid(pImageTo->pBackendData, &ImageModificationUuid);
    55695627        }
    55705628    } while (0);
     
    55845642
    55855643        /* Close and delete image. */
    5586         rc2 = pImageTo->Backend->pfnClose(pImageTo->pvBackendData, true);
    5587         AssertRC(rc2);
    5588         pImageTo->pvBackendData = NULL;
     5644        rc2 = pImageTo->Backend->pfnClose(pImageTo->pBackendData, true);
     5645        AssertRC(rc2);
     5646        pImageTo->pBackendData = NULL;
    55895647
    55905648        /* Free remaining resources. */
     
    57115769        fLockWrite = true;
    57125770
    5713         rc = pImage->Backend->pfnCompact(pImage->pvBackendData,
     5771        rc = pImage->Backend->pfnCompact(pImage->pBackendData,
    57145772                                         0, 99,
    57155773                                         pDisk->pVDIfsDisk,
     
    57585816 */
    57595817VBOXDDU_DECL(int) VDResize(PVBOXHDD pDisk, uint64_t cbSize,
    5760                            PCPDMMEDIAGEOMETRY pPCHSGeometry,
    5761                            PCPDMMEDIAGEOMETRY pLCHSGeometry,
     5818                           PCVDGEOMETRY pPCHSGeometry,
     5819                           PCVDGEOMETRY pLCHSGeometry,
    57625820                           PVDINTERFACE pVDIfsOperation)
    57635821{
     5822    /** @todo r=klaus resizing was designed to be part of VDCopy, so having a separate function is not desirable. */
    57645823    int rc = VINF_SUCCESS;
    57655824    int rc2;
     
    58125871        fLockWrite = true;
    58135872
    5814         PDMMEDIAGEOMETRY PCHSGeometryOld;
    5815         PDMMEDIAGEOMETRY LCHSGeometryOld;
    5816         PCPDMMEDIAGEOMETRY pPCHSGeometryNew;
    5817         PCPDMMEDIAGEOMETRY pLCHSGeometryNew;
     5873        VDGEOMETRY PCHSGeometryOld;
     5874        VDGEOMETRY LCHSGeometryOld;
     5875        PCVDGEOMETRY pPCHSGeometryNew;
     5876        PCVDGEOMETRY pLCHSGeometryNew;
    58185877
    58195878        if (pPCHSGeometry->cCylinders == 0)
    58205879        {
    58215880            /* Auto-detect marker, calculate new value ourself. */
    5822             rc = pImage->Backend->pfnGetPCHSGeometry(pImage->pvBackendData, &PCHSGeometryOld);
     5881            rc = pImage->Backend->pfnGetPCHSGeometry(pImage->pBackendData, &PCHSGeometryOld);
    58235882            if (RT_SUCCESS(rc) && (PCHSGeometryOld.cCylinders != 0))
    58245883                PCHSGeometryOld.cCylinders = RT_MIN(cbSize / 512 / PCHSGeometryOld.cHeads / PCHSGeometryOld.cSectors, 16383);
     
    58345893        {
    58355894            /* Auto-detect marker, calculate new value ourself. */
    5836             rc = pImage->Backend->pfnGetLCHSGeometry(pImage->pvBackendData, &LCHSGeometryOld);
     5895            rc = pImage->Backend->pfnGetLCHSGeometry(pImage->pBackendData, &LCHSGeometryOld);
    58375896            if (RT_SUCCESS(rc) && (LCHSGeometryOld.cCylinders != 0))
    58385897                LCHSGeometryOld.cCylinders = cbSize / 512 / LCHSGeometryOld.cHeads / LCHSGeometryOld.cSectors;
     
    58465905
    58475906        if (RT_SUCCESS(rc))
    5848             rc = pImage->Backend->pfnResize(pImage->pvBackendData,
    5849                                             cbSize * _1M,
     5907            rc = pImage->Backend->pfnResize(pImage->pBackendData,
     5908                                            cbSize,
    58505909                                            pPCHSGeometryNew,
    58515910                                            pLCHSGeometryNew,
     
    59145973            break;
    59155974        }
    5916         unsigned uOpenFlags = pImage->Backend->pfnGetOpenFlags(pImage->pvBackendData);
     5975        unsigned uOpenFlags = pImage->Backend->pfnGetOpenFlags(pImage->pBackendData);
    59175976        /* Remove image from list of opened images. */
    59185977        vdRemoveImageFromList(pDisk, pImage);
    59195978        /* Close (and optionally delete) image. */
    5920         rc = pImage->Backend->pfnClose(pImage->pvBackendData, fDelete);
     5979        rc = pImage->Backend->pfnClose(pImage->pBackendData, fDelete);
    59215980        /* Free remaining resources related to the image. */
    59225981        RTStrFree(pImage->pszFilename);
     
    59325991        if (!(uOpenFlags & VD_OPEN_FLAGS_READONLY))
    59335992        {
    5934             uOpenFlags = pImage->Backend->pfnGetOpenFlags(pImage->pvBackendData);
     5993            uOpenFlags = pImage->Backend->pfnGetOpenFlags(pImage->pBackendData);
    59355994            uOpenFlags &= ~ VD_OPEN_FLAGS_READONLY;
    5936             rc = pImage->Backend->pfnSetOpenFlags(pImage->pvBackendData, uOpenFlags);
     5995            rc = pImage->Backend->pfnSetOpenFlags(pImage->pBackendData, uOpenFlags);
    59375996        }
    59385997
    59395998        /* Cache disk information. */
    5940         pDisk->cbSize = pImage->Backend->pfnGetSize(pImage->pvBackendData);
     5999        pDisk->cbSize = pImage->Backend->pfnGetSize(pImage->pBackendData);
    59416000
    59426001        /* Cache PCHS geometry. */
    5943         rc2 = pImage->Backend->pfnGetPCHSGeometry(pImage->pvBackendData,
     6002        rc2 = pImage->Backend->pfnGetPCHSGeometry(pImage->pBackendData,
    59446003                                                 &pDisk->PCHSGeometry);
    59456004        if (RT_FAILURE(rc2))
     
    59586017
    59596018        /* Cache LCHS geometry. */
    5960         rc2 = pImage->Backend->pfnGetLCHSGeometry(pImage->pvBackendData,
     6019        rc2 = pImage->Backend->pfnGetLCHSGeometry(pImage->pBackendData,
    59616020                                                  &pDisk->LCHSGeometry);
    59626021        if (RT_FAILURE(rc2))
     
    60166075        pDisk->pCache = NULL;
    60176076
    6018         pCache->Backend->pfnClose(pCache->pvBackendData, fDelete);
     6077        pCache->Backend->pfnClose(pCache->pBackendData, fDelete);
    60196078        if (pCache->pszFilename)
    60206079            RTStrFree(pCache->pszFilename);
     
    60596118        if (pCache)
    60606119        {
    6061             rc2 = pCache->Backend->pfnClose(pCache->pvBackendData, false);
     6120            rc2 = pCache->Backend->pfnClose(pCache->pBackendData, false);
    60626121            if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
    60636122                rc = rc2;
     
    60756134            vdRemoveImageFromList(pDisk, pImage);
    60766135            /* Close image. */
    6077             rc2 = pImage->Backend->pfnClose(pImage->pvBackendData, false);
     6136            rc2 = pImage->Backend->pfnClose(pImage->pBackendData, false);
    60786137            if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
    60796138                rc = rc2;
     
    62456304
    62466305        vdResetModifiedFlag(pDisk);
    6247         rc = pImage->Backend->pfnFlush(pImage->pvBackendData);
     6306        rc = pImage->Backend->pfnFlush(pImage->pBackendData);
    62486307
    62496308        if (   RT_SUCCESS(rc)
    62506309            && pDisk->pCache)
    6251             rc = pDisk->pCache->Backend->pfnFlush(pDisk->pCache->pvBackendData);
     6310            rc = pDisk->pCache->Backend->pfnFlush(pDisk->pCache->pBackendData);
    62526311    } while (0);
    62536312
     
    63266385
    63276386        unsigned uOpenFlags;
    6328         uOpenFlags = pDisk->pLast->Backend->pfnGetOpenFlags(pDisk->pLast->pvBackendData);
     6387        uOpenFlags = pDisk->pLast->Backend->pfnGetOpenFlags(pDisk->pLast->pBackendData);
    63296388        fReadOnly = !!(uOpenFlags & VD_OPEN_FLAGS_READONLY);
    63306389    } while (0);
     
    63676426        PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage);
    63686427        AssertPtrBreakStmt(pImage, cbSize = 0);
    6369         cbSize = pImage->Backend->pfnGetSize(pImage->pvBackendData);
     6428        cbSize = pImage->Backend->pfnGetSize(pImage->pBackendData);
    63706429    } while (0);
    63716430
     
    64076466        PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage);
    64086467        AssertPtrBreakStmt(pImage, cbSize = 0);
    6409         cbSize = pImage->Backend->pfnGetFileSize(pImage->pvBackendData);
     6468        cbSize = pImage->Backend->pfnGetFileSize(pImage->pBackendData);
    64106469    } while (0);
    64116470
     
    64316490 */
    64326491VBOXDDU_DECL(int) VDGetPCHSGeometry(PVBOXHDD pDisk, unsigned nImage,
    6433                                     PPDMMEDIAGEOMETRY pPCHSGeometry)
     6492                                    PVDGEOMETRY pPCHSGeometry)
    64346493{
    64356494    int rc = VINF_SUCCESS;
     
    64666525        }
    64676526        else
    6468             rc = pImage->Backend->pfnGetPCHSGeometry(pImage->pvBackendData,
     6527            rc = pImage->Backend->pfnGetPCHSGeometry(pImage->pBackendData,
    64696528                                                     pPCHSGeometry);
    64706529    } while (0);
     
    64766535    }
    64776536
    6478     LogFlowFunc(("%s: %Rrc (PCHS=%u/%u/%u)\n", __FUNCTION__, rc,
     6537    LogFlowFunc(("%Rrc (PCHS=%u/%u/%u)\n", rc,
    64796538                 pDisk->PCHSGeometry.cCylinders, pDisk->PCHSGeometry.cHeads,
    64806539                 pDisk->PCHSGeometry.cSectors));
     
    64956554 */
    64966555VBOXDDU_DECL(int) VDSetPCHSGeometry(PVBOXHDD pDisk, unsigned nImage,
    6497                                     PCPDMMEDIAGEOMETRY pPCHSGeometry)
     6556                                    PCVDGEOMETRY pPCHSGeometry)
    64986557{
    64996558    int rc = VINF_SUCCESS;
     
    65376596                 * of updating an image which could be opened in read-only mode
    65386597                 * right now. */
    6539                 rc = pImage->Backend->pfnSetPCHSGeometry(pImage->pvBackendData,
     6598                rc = pImage->Backend->pfnSetPCHSGeometry(pImage->pBackendData,
    65406599                                                         pPCHSGeometry);
    65416600
    65426601                /* Cache new geometry values in any case. */
    6543                 rc2 = pImage->Backend->pfnGetPCHSGeometry(pImage->pvBackendData,
     6602                rc2 = pImage->Backend->pfnGetPCHSGeometry(pImage->pBackendData,
    65446603                                                          &pDisk->PCHSGeometry);
    65456604                if (RT_FAILURE(rc2))
     
    65596618        else
    65606619        {
    6561             PDMMEDIAGEOMETRY PCHS;
    6562             rc = pImage->Backend->pfnGetPCHSGeometry(pImage->pvBackendData,
     6620            VDGEOMETRY PCHS;
     6621            rc = pImage->Backend->pfnGetPCHSGeometry(pImage->pBackendData,
    65636622                                                     &PCHS);
    65646623            if (    RT_FAILURE(rc)
     
    65726631                 * of updating an image which could be opened in read-only mode
    65736632                 * right now. */
    6574                 rc = pImage->Backend->pfnSetPCHSGeometry(pImage->pvBackendData,
     6633                rc = pImage->Backend->pfnSetPCHSGeometry(pImage->pBackendData,
    65756634                                                         pPCHSGeometry);
    65766635            }
     
    65996658 */
    66006659VBOXDDU_DECL(int) VDGetLCHSGeometry(PVBOXHDD pDisk, unsigned nImage,
    6601                                     PPDMMEDIAGEOMETRY pLCHSGeometry)
     6660                                    PVDGEOMETRY pLCHSGeometry)
    66026661{
    66036662    int rc = VINF_SUCCESS;
     
    66346693        }
    66356694        else
    6636             rc = pImage->Backend->pfnGetLCHSGeometry(pImage->pvBackendData,
     6695            rc = pImage->Backend->pfnGetLCHSGeometry(pImage->pBackendData,
    66376696                                                     pLCHSGeometry);
    66386697    } while (0);
     
    66636722 */
    66646723VBOXDDU_DECL(int) VDSetLCHSGeometry(PVBOXHDD pDisk, unsigned nImage,
    6665                                     PCPDMMEDIAGEOMETRY pLCHSGeometry)
     6724                                    PCVDGEOMETRY pLCHSGeometry)
    66666725{
    66676726    int rc = VINF_SUCCESS;
     
    67056764                 * of updating an image which could be opened in read-only mode
    67066765                 * right now. */
    6707                 rc = pImage->Backend->pfnSetLCHSGeometry(pImage->pvBackendData,
     6766                rc = pImage->Backend->pfnSetLCHSGeometry(pImage->pBackendData,
    67086767                                                         pLCHSGeometry);
    67096768
    67106769                /* Cache new geometry values in any case. */
    6711                 rc2 = pImage->Backend->pfnGetLCHSGeometry(pImage->pvBackendData,
     6770                rc2 = pImage->Backend->pfnGetLCHSGeometry(pImage->pBackendData,
    67126771                                                          &pDisk->LCHSGeometry);
    67136772                if (RT_FAILURE(rc2))
     
    67276786        else
    67286787        {
    6729             PDMMEDIAGEOMETRY LCHS;
    6730             rc = pImage->Backend->pfnGetLCHSGeometry(pImage->pvBackendData,
     6788            VDGEOMETRY LCHS;
     6789            rc = pImage->Backend->pfnGetLCHSGeometry(pImage->pBackendData,
    67316790                                                     &LCHS);
    67326791            if (    RT_FAILURE(rc)
     
    67406799                 * of updating an image which could be opened in read-only mode
    67416800                 * right now. */
    6742                 rc = pImage->Backend->pfnSetLCHSGeometry(pImage->pvBackendData,
     6801                rc = pImage->Backend->pfnSetLCHSGeometry(pImage->pBackendData,
    67436802                                                         pLCHSGeometry);
    67446803            }
     
    67926851        AssertPtrBreakStmt(pImage, rc = VERR_VD_IMAGE_NOT_FOUND);
    67936852
    6794         *puVersion = pImage->Backend->pfnGetVersion(pImage->pvBackendData);
     6853        *puVersion = pImage->Backend->pfnGetVersion(pImage->pBackendData);
    67956854    } while (0);
    67966855
     
    69427001        AssertPtrBreakStmt(pImage, rc = VERR_VD_IMAGE_NOT_FOUND);
    69437002
    6944         *puOpenFlags = pImage->Backend->pfnGetOpenFlags(pImage->pvBackendData);
     7003        *puOpenFlags = pImage->Backend->pfnGetOpenFlags(pImage->pBackendData);
    69457004    } while (0);
    69467005
     
    69927051        AssertPtrBreakStmt(pImage, rc = VERR_VD_IMAGE_NOT_FOUND);
    69937052
    6994         rc = pImage->Backend->pfnSetOpenFlags(pImage->pvBackendData,
     7053        rc = pImage->Backend->pfnSetOpenFlags(pImage->pBackendData,
    69957054                                              uOpenFlags);
    69967055    } while (0);
     
    71147173        AssertPtrBreakStmt(pImage, rc = VERR_VD_IMAGE_NOT_FOUND);
    71157174
    7116         rc = pImage->Backend->pfnGetComment(pImage->pvBackendData, pszComment,
     7175        rc = pImage->Backend->pfnGetComment(pImage->pBackendData, pszComment,
    71177176                                            cbComment);
    71187177    } while (0);
     
    71647223        AssertPtrBreakStmt(pImage, rc = VERR_VD_IMAGE_NOT_FOUND);
    71657224
    7166         rc = pImage->Backend->pfnSetComment(pImage->pvBackendData, pszComment);
     7225        rc = pImage->Backend->pfnSetComment(pImage->pBackendData, pszComment);
    71677226    } while (0);
    71687227
     
    72127271        AssertPtrBreakStmt(pImage, rc = VERR_VD_IMAGE_NOT_FOUND);
    72137272
    7214         rc = pImage->Backend->pfnGetUuid(pImage->pvBackendData, pUuid);
     7273        rc = pImage->Backend->pfnGetUuid(pImage->pBackendData, pUuid);
    72157274    } while (0);
    72167275
     
    72657324            pUuid = &Uuid;
    72667325        }
    7267         rc = pImage->Backend->pfnSetUuid(pImage->pvBackendData, pUuid);
     7326        rc = pImage->Backend->pfnSetUuid(pImage->pBackendData, pUuid);
    72687327    } while (0);
    72697328
     
    73127371        AssertPtrBreakStmt(pImage, rc = VERR_VD_IMAGE_NOT_FOUND);
    73137372
    7314         rc = pImage->Backend->pfnGetModificationUuid(pImage->pvBackendData,
     7373        rc = pImage->Backend->pfnGetModificationUuid(pImage->pBackendData,
    73157374                                                     pUuid);
    73167375    } while (0);
     
    73677426            pUuid = &Uuid;
    73687427        }
    7369         rc = pImage->Backend->pfnSetModificationUuid(pImage->pvBackendData,
     7428        rc = pImage->Backend->pfnSetModificationUuid(pImage->pBackendData,
    73707429                                                     pUuid);
    73717430    } while (0);
     
    74167475        AssertPtrBreakStmt(pImage, rc = VERR_VD_IMAGE_NOT_FOUND);
    74177476
    7418         rc = pImage->Backend->pfnGetParentUuid(pImage->pvBackendData, pUuid);
     7477        rc = pImage->Backend->pfnGetParentUuid(pImage->pBackendData, pUuid);
    74197478    } while (0);
    74207479
     
    74707529            pUuid = &Uuid;
    74717530        }
    7472         rc = pImage->Backend->pfnSetParentUuid(pImage->pvBackendData, pUuid);
     7531        rc = pImage->Backend->pfnSetParentUuid(pImage->pBackendData, pUuid);
    74737532    } while (0);
    74747533
     
    75007559        AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
    75017560
    7502         int (*pfnMessage)(void *, const char *, ...) = NULL;
    7503         void *pvUser = pDisk->pInterfaceError->pvUser;
    7504 
    7505         if (pDisk->pInterfaceErrorCallbacks && VALID_PTR(pDisk->pInterfaceErrorCallbacks->pfnMessage))
    7506             pfnMessage = pDisk->pInterfaceErrorCallbacks->pfnMessage;
    7507         else
    7508         {
     7561        if (!pDisk->pInterfaceErrorCallbacks || !VALID_PTR(pDisk->pInterfaceErrorCallbacks->pfnMessage))
    75097562            pDisk->pInterfaceErrorCallbacks->pfnMessage = vdLogMessage;
    7510             pfnMessage = vdLogMessage;
    7511         }
    75127563
    75137564        rc2 = vdThreadStartRead(pDisk);
     
    75157566        fLockRead = true;
    75167567
    7517         pfnMessage(pvUser, "--- Dumping VD Disk, Images=%u\n", pDisk->cImages);
     7568        vdMessageWrapper(pDisk, "--- Dumping VD Disk, Images=%u\n", pDisk->cImages);
    75187569        for (PVDIMAGE pImage = pDisk->pBase; pImage; pImage = pImage->pNext)
    75197570        {
    7520             pfnMessage(pvUser, "Dumping VD image \"%s\" (Backend=%s)\n",
    7521                        pImage->pszFilename, pImage->Backend->pszBackendName);
    7522             pImage->Backend->pfnDump(pImage->pvBackendData);
     7571            vdMessageWrapper(pDisk, "Dumping VD image \"%s\" (Backend=%s)\n",
     7572                             pImage->pszFilename, pImage->Backend->pszBackendName);
     7573            pImage->Backend->pfnDump(pImage->pBackendData);
    75237574        }
    75247575    } while (0);
     
    75667617
    75677618        if (pImage->Backend->uBackendCaps & VD_CAP_ASYNC)
    7568             *pfAIOSupported = pImage->Backend->pfnIsAsyncIOSupported(pImage->pvBackendData);
     7619            *pfAIOSupported = pImage->Backend->pfnIsAsyncIOSupported(pImage->pBackendData);
    75697620        else
    75707621            *pfAIOSupported = false;
  • trunk/src/VBox/Devices/Storage/VCICacheCore.cpp

    r32370 r32536  
    3434
    3535/**
    36  * Raw image data structure.
     36 * VCI image data structure.
    3737 */
    3838typedef struct VCICACHE
     
    8181*******************************************************************************/
    8282
    83 static int vciFlushImage(PVCICACHE pImage);
    84 static void vciFreeImage(PVCICACHE pImage, bool fDelete);
    85 
    86 
    8783/**
    8884 * Internal: signal an error to the frontend.
     
    10096}
    10197
    102 static int vciFileOpen(PVCICACHE pImage, bool fReadonly, bool fCreate)
     98/**
     99 * Internal: signal an informational message to the frontend.
     100 */
     101DECLINLINE(int) vciMessage(PVCICACHE pImage, const char *pszFormat, ...)
    103102{
    104103    int rc = VINF_SUCCESS;
    105 
    106     AssertMsg(!(fReadonly && fCreate), ("Image can't be opened readonly while being created\n"));
    107 
    108     unsigned uOpenFlags = fReadonly ? VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY : 0;
    109 
    110     if (fCreate)
    111         uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE;
    112 
    113     rc = pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser,
    114                                                 pImage->pszFilename,
    115                                                 uOpenFlags,
    116                                                 &pImage->pStorage);
    117 
    118     return rc;
    119 }
    120 
    121 static int vciFileClose(PVCICACHE pImage)
    122 {
    123     int rc = VINF_SUCCESS;
    124 
    125     if (pImage->pStorage)
    126         rc = pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser,
    127                                                      pImage->pStorage);
    128 
    129     pImage->pStorage = NULL;
    130 
    131     return rc;
    132 }
    133 
    134 static int vciFileFlushSync(PVCICACHE pImage)
     104    va_list va;
     105    va_start(va, pszFormat);
     106    if (pImage->pInterfaceError)
     107        rc = pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser,
     108                                                          pszFormat, va);
     109    va_end(va);
     110    return rc;
     111}
     112
     113
     114DECLINLINE(int) vciFileOpen(PVCICACHE pImage, const char *pszFilename,
     115                            uint32_t fOpen)
     116{
     117    return pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser,
     118                                                  pszFilename, fOpen,
     119                                                  &pImage->pStorage);
     120}
     121
     122DECLINLINE(int) vciFileClose(PVCICACHE pImage)
     123{
     124    return pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser,
     125                                                   pImage->pStorage);
     126}
     127
     128DECLINLINE(int) vciFileDelete(PVCICACHE pImage, const char *pszFilename)
     129{
     130    return pImage->pInterfaceIOCallbacks->pfnDelete(pImage->pInterfaceIO->pvUser,
     131                                                    pszFilename);
     132}
     133
     134DECLINLINE(int) vciFileMove(PVCICACHE pImage, const char *pszSrc,
     135                            const char *pszDst, unsigned fMove)
     136{
     137    return pImage->pInterfaceIOCallbacks->pfnMove(pImage->pInterfaceIO->pvUser,
     138                                                  pszSrc, pszDst, fMove);
     139}
     140
     141DECLINLINE(int) vciFileGetFreeSpace(PVCICACHE pImage, const char *pszFilename,
     142                                    int64_t *pcbFree)
     143{
     144    return pImage->pInterfaceIOCallbacks->pfnGetFreeSpace(pImage->pInterfaceIO->pvUser,
     145                                                          pszFilename, pcbFree);
     146}
     147
     148DECLINLINE(int) vciFileGetSize(PVCICACHE pImage, uint64_t *pcbSize)
     149{
     150    return pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser,
     151                                                     pImage->pStorage, pcbSize);
     152}
     153
     154DECLINLINE(int) vciFileSetSize(PVCICACHE pImage, uint64_t cbSize)
     155{
     156    return pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser,
     157                                                     pImage->pStorage, cbSize);
     158}
     159
     160DECLINLINE(int) vciFileWriteSync(PVCICACHE pImage, uint64_t uOffset,
     161                                 const void *pvBuffer, size_t cbBuffer,
     162                                 size_t *pcbWritten)
     163{
     164    return pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser,
     165                                                       pImage->pStorage, uOffset,
     166                                                       pvBuffer, cbBuffer, pcbWritten);
     167}
     168
     169DECLINLINE(int) vciFileReadSync(PVCICACHE pImage, uint64_t uOffset,
     170                                void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
     171{
     172    return pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser,
     173                                                      pImage->pStorage, uOffset,
     174                                                      pvBuffer, cbBuffer, pcbRead);
     175}
     176
     177DECLINLINE(int) vciFileFlushSync(PVCICACHE pImage)
    135178{
    136179    return pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser,
     
    138181}
    139182
    140 static int vciFileGetSize(PVCICACHE pImage, uint64_t *pcbSize)
    141 {
    142     return pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser,
    143                                                      pImage->pStorage,
    144                                                      pcbSize);
    145 }
    146 
    147 static int vciFileSetSize(PVCICACHE pImage, uint64_t cbSize)
    148 {
    149     return pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser,
    150                                                      pImage->pStorage,
    151                                                      cbSize);
    152 }
    153 
    154 
    155 static int vciFileWriteSync(PVCICACHE pImage, uint64_t off, const void *pcvBuf, size_t cbWrite, size_t *pcbWritten)
    156 {
    157     return pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser,
    158                                                        pImage->pStorage,
    159                                                        off, cbWrite, pcvBuf,
    160                                                        pcbWritten);
    161 }
    162 
    163 static int vciFileReadSync(PVCICACHE pImage, uint64_t off, void *pvBuf, size_t cbRead, size_t *pcbRead)
    164 {
    165     return pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser,
    166                                                       pImage->pStorage,
    167                                                       off, cbRead, pvBuf,
    168                                                       pcbRead);
    169 }
    170 
    171 static bool vciFileOpened(PVCICACHE pImage)
    172 {
    173     return pImage->pStorage != NULL;
     183DECLINLINE(int) vciFileReadUserAsync(PVCICACHE pImage, uint64_t uOffset,
     184                                     PVDIOCTX pIoCtx, size_t cbRead)
     185{
     186    return pImage->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser,
     187                                                           pImage->pStorage,
     188                                                           uOffset, pIoCtx,
     189                                                           cbRead);
     190}
     191
     192DECLINLINE(int) vciFileWriteUserAsync(PVCICACHE pImage, uint64_t uOffset,
     193                                      PVDIOCTX pIoCtx, size_t cbWrite,
     194                                      PFNVDXFERCOMPLETED pfnComplete,
     195                                      void *pvCompleteUser)
     196{
     197    return pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser,
     198                                                            pImage->pStorage,
     199                                                            uOffset, pIoCtx,
     200                                                            cbWrite,
     201                                                            pfnComplete,
     202                                                            pvCompleteUser);
     203}
     204
     205DECLINLINE(int) vciFileFlushAsync(PVCICACHE pImage, PVDIOCTX pIoCtx,
     206                                  PFNVDXFERCOMPLETED pfnComplete,
     207                                  void *pvCompleteUser)
     208{
     209    return pImage->pInterfaceIOCallbacks->pfnFlushAsync(pImage->pInterfaceIO->pvUser,
     210                                                        pImage->pStorage,
     211                                                        pIoCtx, pfnComplete,
     212                                                        pvCompleteUser);
     213}
     214
     215
     216/**
     217 * Internal. Flush image data to disk.
     218 */
     219static int vciFlushImage(PVCICACHE pImage)
     220{
     221    int rc = VINF_SUCCESS;
     222
     223    if (   pImage->pStorage
     224        && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     225        rc = vciFileFlushSync(pImage);
     226
     227    return rc;
     228}
     229
     230/**
     231 * Internal. Free all allocated space for representing an image except pImage,
     232 * and optionally delete the image from disk.
     233 */
     234static int vciFreeImage(PVCICACHE pImage, bool fDelete)
     235{
     236    int rc = VINF_SUCCESS;
     237
     238    /* Freeing a never allocated image (e.g. because the open failed) is
     239     * not signalled as an error. After all nothing bad happens. */
     240    if (pImage)
     241    {
     242        if (pImage->pStorage)
     243        {
     244            /* No point updating the file that is deleted anyway. */
     245            if (!fDelete)
     246                vciFlushImage(pImage);
     247
     248            vciFileClose(pImage);
     249            pImage->pStorage = NULL;
     250        }
     251
     252        if (fDelete && pImage->pszFilename)
     253            vciFileDelete(pImage, pImage->pszFilename);
     254    }
     255
     256    LogFlowFunc(("returns %Rrc\n", rc));
     257    return rc;
    174258}
    175259
     
    181265    int rc;
    182266
    183     if (uOpenFlags & VD_OPEN_FLAGS_ASYNC_IO)
    184         return VERR_NOT_SUPPORTED;
    185 
    186267    pImage->uOpenFlags = uOpenFlags;
    187268
     
    190271        pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError);
    191272
    192 #ifdef VBOX_WITH_NEW_IO_CODE
    193     /* Try to get I/O interface. */
     273    /* Get I/O interface. */
    194274    pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsImage, VDINTERFACETYPE_IO);
    195     AssertPtr(pImage->pInterfaceIO);
     275    AssertPtrReturn(pImage->pInterfaceIO, VERR_INVALID_PARAMETER);
    196276    pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO);
    197     AssertPtr(pImage->pInterfaceIOCallbacks);
    198 #endif
     277    AssertPtrReturn(pImage->pInterfaceIOCallbacks, VERR_INVALID_PARAMETER);
    199278
    200279    /*
    201280     * Open the image.
    202281     */
    203     rc = vciFileOpen(pImage, !!(uOpenFlags & VD_OPEN_FLAGS_READONLY), false);
     282    rc = vciFileOpen(pImage, pImage->pszFilename,
     283                     VDOpenFlagsToFileOpenFlags(uOpenFlags,
     284                                                false /* fCreate */));
    204285    if (RT_FAILURE(rc))
    205286    {
     
    230311static int vciCreateImage(PVCICACHE pImage, uint64_t cbSize,
    231312                          unsigned uImageFlags, const char *pszComment,
    232                           PFNVDPROGRESS pfnProgress, void *pvUser,
    233                           unsigned uPercentStart, unsigned uPercentSpan)
     313                          unsigned uOpenFlags, PFNVDPROGRESS pfnProgress,
     314                          void *pvUser, unsigned uPercentStart,
     315                          unsigned uPercentSpan)
    234316{
    235317    int rc;
     
    241323    if (uImageFlags & VD_IMAGE_FLAGS_DIFF)
    242324    {
    243         rc = vciError(pImage, VERR_VD_RAW_INVALID_TYPE, RT_SRC_POS, N_("Raw: cannot create diff image '%s'"), pImage->pszFilename);
     325        rc = vciError(pImage, VERR_VD_RAW_INVALID_TYPE, RT_SRC_POS, N_("VCI: cannot create diff image '%s'"), pImage->pszFilename);
    244326        goto out;
    245327    }
     
    247329
    248330    pImage->uImageFlags = uImageFlags;
     331
     332    pImage->uOpenFlags = uOpenFlags & ~VD_OPEN_FLAGS_READONLY;
    249333
    250334    pImage->pInterfaceError = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ERROR);
     
    252336        pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError);
    253337
    254 #ifdef VBOX_WITH_NEW_IO_CODE
    255     /* Try to get async I/O interface. */
     338    /* Get I/O interface. */
    256339    pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsImage, VDINTERFACETYPE_IO);
    257     AssertPtr(pImage->pInterfaceIO);
     340    AssertPtrReturn(pImage->pInterfaceIO, VERR_INVALID_PARAMETER);
    258341    pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO);
    259     AssertPtr(pImage->pInterfaceIOCallbacks);
    260 #endif
     342    AssertPtrReturn(pImage->pInterfaceIOCallbacks, VERR_INVALID_PARAMETER);
    261343
    262344    /* Create image file. */
    263     rc = vciFileOpen(pImage, false, true);
     345    rc = vciFileOpen(pImage, pImage->pszFilename,
     346                     VDOpenFlagsToFileOpenFlags(uOpenFlags & ~VD_OPEN_FLAGS_READONLY,
     347                                                true /* fCreate */));
    264348    if (RT_FAILURE(rc))
    265349    {
    266         rc = vciError(pImage, rc, RT_SRC_POS, N_("Raw: cannot create image '%s'"), pImage->pszFilename);
     350        rc = vciError(pImage, rc, RT_SRC_POS, N_("VCI: cannot create image '%s'"), pImage->pszFilename);
    267351        goto out;
    268352    }
     
    270354    /* Check the free space on the disk and leave early if there is not
    271355     * sufficient space available. */
    272     rc = RTFsQuerySizes(pImage->pszFilename, NULL, &cbFree, NULL, NULL);
     356    rc = vciFileGetFreeSpace(pImage, pImage->pszFilename, &cbFree);
    273357    if (RT_SUCCESS(rc) /* ignore errors */ && ((uint64_t)cbFree < cbSize))
    274358    {
    275         rc = vciError(pImage, VERR_DISK_FULL, RT_SRC_POS, N_("Raw: disk would overflow creating image '%s'"), pImage->pszFilename);
     359        rc = vciError(pImage, VERR_DISK_FULL, RT_SRC_POS, N_("VCI: disk would overflow creating image '%s'"), pImage->pszFilename);
    276360        goto out;
    277361    }
     
    282366    if (RT_FAILURE(rc))
    283367    {
    284         rc = vciError(pImage, rc, RT_SRC_POS, N_("Raw: setting image size failed for '%s'"), pImage->pszFilename);
     368        rc = vciError(pImage, rc, RT_SRC_POS, N_("VCI: setting image size failed for '%s'"), pImage->pszFilename);
    285369        goto out;
    286370    }
     
    306390        if (RT_FAILURE(rc))
    307391        {
    308             rc = vciError(pImage, rc, RT_SRC_POS, N_("Raw: writing block failed for '%s'"), pImage->pszFilename);
     392            rc = vciError(pImage, rc, RT_SRC_POS, N_("VCI: writing block failed for '%s'"), pImage->pszFilename);
    309393            goto out;
    310394        }
     
    338422}
    339423
    340 /**
    341  * Internal. Free all allocated space for representing an image, and optionally
    342  * delete the image from disk.
    343  */
    344 static void vciFreeImage(PVCICACHE pImage, bool fDelete)
    345 {
    346     Assert(pImage);
    347 
    348     if (vciFileOpened(pImage))
    349     {
    350         if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    351             vciFlushImage(pImage);
    352         vciFileClose(pImage);
    353     }
    354     if (fDelete && pImage->pszFilename)
    355         RTFileDelete(pImage->pszFilename);
    356 }
    357 
    358 /**
    359  * Internal. Flush image data to disk.
    360  */
    361 static int vciFlushImage(PVCICACHE pImage)
    362 {
    363     int rc = VINF_SUCCESS;
    364 
    365     if (   vciFileOpened(pImage)
    366         && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    367         rc = vciFileFlushSync(pImage);
    368 
    369     return rc;
    370 }
    371 
    372424
    373425/** @copydoc VDCACHEBACKEND::pfnProbe */
    374 static int vciProbe(const char *pszFilename, PVDINTERFACE pVDIfsDisk)
     426static int vciProbe(const char *pszFilename, PVDINTERFACE pVDIfsCache,
     427                    PVDINTERFACE pVDIfsImage)
    375428{
    376429    LogFlowFunc(("pszFilename=\"%s\"\n", pszFilename));
     
    395448static int vciOpen(const char *pszFilename, unsigned uOpenFlags,
    396449                   PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
    397                    void **ppvBackendData)
    398 {
    399     LogFlowFunc(("pszFilename=\"%s\" uOpenFlags=%#x pVDIfsDisk=%#p pVDIfsImage=%#p ppvBackendData=%#p\n", pszFilename, uOpenFlags, pVDIfsDisk, pVDIfsImage, ppvBackendData));
     450                   void **ppBackendData)
     451{
     452    LogFlowFunc(("pszFilename=\"%s\" uOpenFlags=%#x pVDIfsDisk=%#p pVDIfsImage=%#p ppBackendData=%#p\n", pszFilename, uOpenFlags, pVDIfsDisk, pVDIfsImage, ppBackendData));
    400453    int rc;
    401454    PVCICACHE pImage;
     
    424477    }
    425478    pImage->pszFilename = pszFilename;
    426     pImage->pStorage    = NULL;
    427     pImage->pVDIfsDisk  = pVDIfsDisk;
     479    pImage->pStorage = NULL;
     480    pImage->pVDIfsDisk = pVDIfsDisk;
    428481    pImage->pVDIfsImage = pVDIfsImage;
    429482
    430483    rc = vciOpenImage(pImage, uOpenFlags);
    431484    if (RT_SUCCESS(rc))
    432         *ppvBackendData = pImage;
     485        *ppBackendData = pImage;
    433486    else
    434487        RTMemFree(pImage);
    435488
    436489out:
    437     LogFlowFunc(("returns %Rrc (pvBackendData=%#p)\n", rc, *ppvBackendData));
     490    LogFlowFunc(("returns %Rrc (pBackendData=%#p)\n", rc, *ppBackendData));
    438491    return rc;
    439492}
     
    442495static int vciCreate(const char *pszFilename, uint64_t cbSize,
    443496                     unsigned uImageFlags, const char *pszComment,
    444                      PCRTUUID pUuid,
    445                      unsigned uOpenFlags, unsigned uPercentStart,
    446                      unsigned uPercentSpan, PVDINTERFACE pVDIfsDisk,
    447                      PVDINTERFACE pVDIfsImage, PVDINTERFACE pVDIfsOperation,
    448                      void **ppvBackendData)
    449 {
    450     LogFlowFunc(("pszFilename=\"%s\" cbSize=%llu uImageFlags=%#x pszComment=\"%s\" Uuid=%RTuuid uOpenFlags=%#x uPercentStart=%u uPercentSpan=%u pVDIfsDisk=%#p pVDIfsImage=%#p pVDIfsOperation=%#p ppvBackendData=%#p",
    451                  pszFilename, cbSize, uImageFlags, pszComment, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, ppvBackendData));
     497                     PCRTUUID pUuid, unsigned uOpenFlags,
     498                     unsigned uPercentStart, unsigned uPercentSpan,
     499                     PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
     500                     PVDINTERFACE pVDIfsOperation, void **ppBackendData)
     501{
     502    LogFlowFunc(("pszFilename=\"%s\" cbSize=%llu uImageFlags=%#x pszComment=\"%s\" Uuid=%RTuuid uOpenFlags=%#x uPercentStart=%u uPercentSpan=%u pVDIfsDisk=%#p pVDIfsImage=%#p pVDIfsOperation=%#p ppBackendData=%#p",
     503                 pszFilename, cbSize, uImageFlags, pszComment, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, ppBackendData));
    452504    int rc;
    453505    PVCICACHE pImage;
     
    488540    }
    489541    pImage->pszFilename = pszFilename;
    490     pImage->pStorage    = NULL;
    491     pImage->pVDIfsDisk  = pVDIfsDisk;
     542    pImage->pStorage = NULL;
     543    pImage->pVDIfsDisk = pVDIfsDisk;
    492544    pImage->pVDIfsImage = pVDIfsImage;
    493545
    494     rc = vciCreateImage(pImage, cbSize, uImageFlags, pszComment,
     546    rc = vciCreateImage(pImage, cbSize, uImageFlags, pszComment, uOpenFlags,
    495547                        pfnProgress, pvUser, uPercentStart, uPercentSpan);
    496548    if (RT_SUCCESS(rc))
     
    508560            }
    509561        }
    510         *ppvBackendData = pImage;
     562        *ppBackendData = pImage;
    511563    }
    512564    else
     
    514566
    515567out:
    516     LogFlowFunc(("returns %Rrc (pvBackendData=%#p)\n", rc, *ppvBackendData));
     568    LogFlowFunc(("returns %Rrc (pBackendData=%#p)\n", rc, *ppBackendData));
    517569    return rc;
    518570}
    519571
    520572/** @copydoc VDCACHEBACKEND::pfnClose */
    521 static int vciClose(void *pvBackendData, bool fDelete)
    522 {
    523     LogFlowFunc(("pvBackendData=%#p fDelete=%d\n", pvBackendData, fDelete));
    524     PVCICACHE pImage = (PVCICACHE)pvBackendData;
    525     int rc = VINF_SUCCESS;
    526 
    527     /* Freeing a never allocated image (e.g. because the open failed) is
    528      * not signalled as an error. After all nothing bad happens. */
    529     if (pImage)
    530     {
    531         vciFreeImage(pImage, fDelete);
    532         RTMemFree(pImage);
    533     }
     573static int vciClose(void *pBackendData, bool fDelete)
     574{
     575    LogFlowFunc(("pBackendData=%#p fDelete=%d\n", pBackendData, fDelete));
     576    PVCICACHE pImage = (PVCICACHE)pBackendData;
     577    int rc;
     578
     579    rc = vciFreeImage(pImage, fDelete);
     580    RTMemFree(pImage);
    534581
    535582    LogFlowFunc(("returns %Rrc\n", rc));
     
    538585
    539586/** @copydoc VDCACHEBACKEND::pfnRead */
    540 static int vciRead(void *pvBackendData, uint64_t uOffset, void *pvBuf,
     587static int vciRead(void *pBackendData, uint64_t uOffset, void *pvBuf,
    541588                   size_t cbToRead, size_t *pcbActuallyRead)
    542589{
    543     LogFlowFunc(("pvBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n", pvBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead));
    544     PVCICACHE pImage = (PVCICACHE)pvBackendData;
    545     int rc;
    546 
    547     Assert(pImage);
     590    LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n", pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead));
     591    PVCICACHE pImage = (PVCICACHE)pBackendData;
     592    int rc;
     593
     594    AssertPtr(pImage);
    548595    Assert(uOffset % 512 == 0);
    549596    Assert(cbToRead % 512 == 0);
     
    565612
    566613/** @copydoc VDCACHEBACKEND::pfnWrite */
    567 static int vciWrite(void *pvBackendData, uint64_t uOffset, const void *pvBuf,
     614static int vciWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf,
    568615                    size_t cbToWrite, size_t *pcbWriteProcess)
    569616{
    570     LogFlowFunc(("pvBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p\n",
    571                  pvBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess));
    572     PVCICACHE pImage = (PVCICACHE)pvBackendData;
    573     int rc;
    574 
    575     Assert(pImage);
     617    LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p\n",
     618                 pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess));
     619    PVCICACHE pImage = (PVCICACHE)pBackendData;
     620    int rc;
     621
     622    AssertPtr(pImage);
    576623    Assert(uOffset % 512 == 0);
    577624    Assert(cbToWrite % 512 == 0);
     
    600647
    601648/** @copydoc VDCACHEBACKEND::pfnFlush */
    602 static int vciFlush(void *pvBackendData)
    603 {
    604     LogFlowFunc(("pvBackendData=%#p\n", pvBackendData));
    605     PVCICACHE pImage = (PVCICACHE)pvBackendData;
     649static int vciFlush(void *pBackendData)
     650{
     651    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     652    PVCICACHE pImage = (PVCICACHE)pBackendData;
    606653    int rc;
    607654
     
    612659
    613660/** @copydoc VDCACHEBACKEND::pfnGetVersion */
    614 static unsigned vciGetVersion(void *pvBackendData)
    615 {
    616     LogFlowFunc(("pvBackendData=%#p\n", pvBackendData));
    617     PVCICACHE pImage = (PVCICACHE)pvBackendData;
    618 
    619     Assert(pImage);
     661static unsigned vciGetVersion(void *pBackendData)
     662{
     663    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     664    PVCICACHE pImage = (PVCICACHE)pBackendData;
     665
     666    AssertPtr(pImage);
    620667
    621668    if (pImage)
     
    626673
    627674/** @copydoc VDCACHEBACKEND::pfnGetSize */
    628 static uint64_t vciGetSize(void *pvBackendData)
    629 {
    630     LogFlowFunc(("pvBackendData=%#p\n", pvBackendData));
    631     PVCICACHE pImage = (PVCICACHE)pvBackendData;
    632 
    633     Assert(pImage);
     675static uint64_t vciGetSize(void *pBackendData)
     676{
     677    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     678    PVCICACHE pImage = (PVCICACHE)pBackendData;
     679    uint64_t cb = 0;
     680
     681    AssertPtr(pImage);
     682
     683    if (pImage && pImage->pStorage)
     684        cb = pImage->cbSize;
     685
     686    LogFlowFunc(("returns %llu\n", cb));
     687    return cb;
     688}
     689
     690/** @copydoc VDCACHEBACKEND::pfnGetFileSize */
     691static uint64_t vciGetFileSize(void *pBackendData)
     692{
     693    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     694    PVCICACHE pImage = (PVCICACHE)pBackendData;
     695    uint64_t cb = 0;
     696
     697    AssertPtr(pImage);
    634698
    635699    if (pImage)
    636         return pImage->cbSize;
    637     else
    638         return 0;
    639 }
    640 
    641 /** @copydoc VDCACHEBACKEND::pfnGetFileSize */
    642 static uint64_t vciGetFileSize(void *pvBackendData)
    643 {
    644     LogFlowFunc(("pvBackendData=%#p\n", pvBackendData));
    645     PVCICACHE pImage = (PVCICACHE)pvBackendData;
    646     uint64_t cb = 0;
    647 
    648     Assert(pImage);
    649 
    650     if (pImage)
    651700    {
    652701        uint64_t cbFile;
    653         if (vciFileOpened(pImage))
     702        if (pImage->pStorage)
    654703        {
    655704            int rc = vciFileGetSize(pImage, &cbFile);
    656705            if (RT_SUCCESS(rc))
    657                 cb += cbFile;
     706                cb = cbFile;
    658707        }
    659708    }
     
    664713
    665714/** @copydoc VDCACHEBACKEND::pfnGetImageFlags */
    666 static unsigned vciGetImageFlags(void *pvBackendData)
    667 {
    668     LogFlowFunc(("pvBackendData=%#p\n", pvBackendData));
    669     PVCICACHE pImage = (PVCICACHE)pvBackendData;
     715static unsigned vciGetImageFlags(void *pBackendData)
     716{
     717    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     718    PVCICACHE pImage = (PVCICACHE)pBackendData;
    670719    unsigned uImageFlags;
    671720
    672     Assert(pImage);
     721    AssertPtr(pImage);
    673722
    674723    if (pImage)
     
    682731
    683732/** @copydoc VDCACHEBACKEND::pfnGetOpenFlags */
    684 static unsigned vciGetOpenFlags(void *pvBackendData)
    685 {
    686     LogFlowFunc(("pvBackendData=%#p\n", pvBackendData));
    687     PVCICACHE pImage = (PVCICACHE)pvBackendData;
     733static unsigned vciGetOpenFlags(void *pBackendData)
     734{
     735    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     736    PVCICACHE pImage = (PVCICACHE)pBackendData;
    688737    unsigned uOpenFlags;
    689738
    690     Assert(pImage);
     739    AssertPtr(pImage);
    691740
    692741    if (pImage)
     
    700749
    701750/** @copydoc VDCACHEBACKEND::pfnSetOpenFlags */
    702 static int vciSetOpenFlags(void *pvBackendData, unsigned uOpenFlags)
    703 {
    704     LogFlowFunc(("pvBackendData=%#p\n uOpenFlags=%#x", pvBackendData, uOpenFlags));
    705     PVCICACHE pImage = (PVCICACHE)pvBackendData;
     751static int vciSetOpenFlags(void *pBackendData, unsigned uOpenFlags)
     752{
     753    LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags));
     754    PVCICACHE pImage = (PVCICACHE)pBackendData;
    706755    int rc;
    707756
     
    715764
    716765    /* Implement this operation via reopening the image. */
    717     vciFreeImage(pImage, false);
     766    rc = vciFreeImage(pImage, false);
     767    if (RT_FAILURE(rc))
     768        goto out;
    718769    rc = vciOpenImage(pImage, uOpenFlags);
    719770
     
    724775
    725776/** @copydoc VDCACHEBACKEND::pfnGetComment */
    726 static int vciGetComment(void *pvBackendData, char *pszComment,
     777static int vciGetComment(void *pBackendData, char *pszComment,
    727778                          size_t cbComment)
    728779{
    729     LogFlowFunc(("pvBackendData=%#p pszComment=%#p cbComment=%zu\n", pvBackendData, pszComment, cbComment));
    730     PVCICACHE pImage = (PVCICACHE)pvBackendData;
    731     int rc;
    732 
    733     Assert(pImage);
    734 
    735     if (pImage)
    736     {
    737         if (pszComment)
    738             *pszComment = '\0';
    739         rc = VINF_SUCCESS;
    740     }
    741     else
    742         rc = VERR_VD_NOT_OPENED;
    743 
    744     LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment));
    745     return rc;
    746 }
    747 
    748 /** @copydoc VDCACHEBACKEND::pfnSetComment */
    749 static int vciSetComment(void *pvBackendData, const char *pszComment)
    750 {
    751     LogFlowFunc(("pvBackendData=%#p pszComment=\"%s\"\n", pvBackendData, pszComment));
    752     PVCICACHE pImage = (PVCICACHE)pvBackendData;
    753     int rc;
    754 
    755     Assert(pImage);
    756 
    757     if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    758     {
    759         rc = VERR_VD_IMAGE_READ_ONLY;
    760         goto out;
    761     }
     780    LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment));
     781    PVCICACHE pImage = (PVCICACHE)pBackendData;
     782    int rc;
     783
     784    AssertPtr(pImage);
    762785
    763786    if (pImage)
     
    766789        rc = VERR_VD_NOT_OPENED;
    767790
    768 out:
    769     LogFlowFunc(("returns %Rrc\n", rc));
    770     return rc;
    771 }
    772 
    773 /** @copydoc VDCACHEBACKEND::pfnGetUuid */
    774 static int vciGetUuid(void *pvBackendData, PRTUUID pUuid)
    775 {
    776     LogFlowFunc(("pvBackendData=%#p pUuid=%#p\n", pvBackendData, pUuid));
    777     PVCICACHE pImage = (PVCICACHE)pvBackendData;
    778     int rc;
    779 
    780     Assert(pImage);
     791    LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment));
     792    return rc;
     793}
     794
     795/** @copydoc VDCACHEBACKEND::pfnSetComment */
     796static int vciSetComment(void *pBackendData, const char *pszComment)
     797{
     798    LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment));
     799    PVCICACHE pImage = (PVCICACHE)pBackendData;
     800    int rc;
     801
     802    AssertPtr(pImage);
     803
     804    if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     805    {
     806        rc = VERR_VD_IMAGE_READ_ONLY;
     807        goto out;
     808    }
    781809
    782810    if (pImage)
     
    785813        rc = VERR_VD_NOT_OPENED;
    786814
     815out:
     816    LogFlowFunc(("returns %Rrc\n", rc));
     817    return rc;
     818}
     819
     820/** @copydoc VDCACHEBACKEND::pfnGetUuid */
     821static int vciGetUuid(void *pBackendData, PRTUUID pUuid)
     822{
     823    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
     824    PVCICACHE pImage = (PVCICACHE)pBackendData;
     825    int rc;
     826
     827    AssertPtr(pImage);
     828
     829    if (pImage)
     830        rc = VERR_NOT_SUPPORTED;
     831    else
     832        rc = VERR_VD_NOT_OPENED;
     833
    787834    LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
    788835    return rc;
     
    790837
    791838/** @copydoc VDCACHEBACKEND::pfnSetUuid */
    792 static int vciSetUuid(void *pvBackendData, PCRTUUID pUuid)
    793 {
    794     LogFlowFunc(("pvBackendData=%#p Uuid=%RTuuid\n", pvBackendData, pUuid));
    795     PVCICACHE pImage = (PVCICACHE)pvBackendData;
     839static int vciSetUuid(void *pBackendData, PCRTUUID pUuid)
     840{
     841    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
     842    PVCICACHE pImage = (PVCICACHE)pBackendData;
    796843    int rc;
    797844
    798845    LogFlowFunc(("%RTuuid\n", pUuid));
    799     Assert(pImage);
     846    AssertPtr(pImage);
    800847
    801848    if (pImage)
     
    814861
    815862/** @copydoc VDCACHEBACKEND::pfnGetModificationUuid */
    816 static int vciGetModificationUuid(void *pvBackendData, PRTUUID pUuid)
    817 {
    818     LogFlowFunc(("pvBackendData=%#p pUuid=%#p\n", pvBackendData, pUuid));
    819     PVCICACHE pImage = (PVCICACHE)pvBackendData;
    820     int rc;
    821 
    822     Assert(pImage);
     863static int vciGetModificationUuid(void *pBackendData, PRTUUID pUuid)
     864{
     865    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
     866    PVCICACHE pImage = (PVCICACHE)pBackendData;
     867    int rc;
     868
     869    AssertPtr(pImage);
    823870
    824871    if (pImage)
     
    832879
    833880/** @copydoc VDCACHEBACKEND::pfnSetModificationUuid */
    834 static int vciSetModificationUuid(void *pvBackendData, PCRTUUID pUuid)
    835 {
    836     LogFlowFunc(("pvBackendData=%#p Uuid=%RTuuid\n", pvBackendData, pUuid));
    837     PVCICACHE pImage = (PVCICACHE)pvBackendData;
    838     int rc;
    839 
    840     Assert(pImage);
     881static int vciSetModificationUuid(void *pBackendData, PCRTUUID pUuid)
     882{
     883    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
     884    PVCICACHE pImage = (PVCICACHE)pBackendData;
     885    int rc;
     886
     887    AssertPtr(pImage);
    841888
    842889    if (pImage)
     
    855902
    856903/** @copydoc VDCACHEBACKEND::pfnDump */
    857 static void vciDump(void *pvBackendData)
    858 {
    859     NOREF(pvBackendData);
    860 }
    861 
    862 static int vciAsyncRead(void *pvBackendData, uint64_t uOffset, size_t cbRead,
     904static void vciDump(void *pBackendData)
     905{
     906    NOREF(pBackendData);
     907}
     908
     909/** @copydoc VDCACHEBACKEND::pfnAsyncRead */
     910static int vciAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbRead,
    863911                        PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
    864912{
    865913    int rc = VINF_SUCCESS;
    866     PVCICACHE pImage = (PVCICACHE)pvBackendData;
    867 
    868     rc = pImage->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser,
    869                                                          pImage->pStorage,
    870                                                          uOffset, pIoCtx, cbRead);
     914    PVCICACHE pImage = (PVCICACHE)pBackendData;
     915
     916    rc = vciFileReadUserAsync(pImage, uOffset, pIoCtx, cbRead);
    871917    if (RT_SUCCESS(rc))
    872918        *pcbActuallyRead = cbRead;
     
    875921}
    876922
    877 static int vciAsyncWrite(void *pvBackendData, uint64_t uOffset, size_t cbWrite,
     923/** @copydoc VDCACHEBACKEND::pfnAsyncWrite */
     924static int vciAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbWrite,
    878925                         PVDIOCTX pIoCtx, size_t *pcbWriteProcess)
    879926{
    880927    int rc = VINF_SUCCESS;
    881     PVCICACHE pImage = (PVCICACHE)pvBackendData;
    882 
    883     rc = pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser,
    884                                                          pImage->pStorage,
    885                                                          uOffset, pIoCtx, cbWrite,
    886                                                          NULL, NULL);
    887 
     928    PVCICACHE pImage = (PVCICACHE)pBackendData;
     929
     930    rc = vciFileWriteUserAsync(pImage, uOffset, pIoCtx, cbWrite, NULL, NULL);
    888931    if (RT_SUCCESS(rc))
    889932        *pcbWriteProcess = cbWrite;
     
    892935}
    893936
    894 static int vciAsyncFlush(void *pvBackendData, PVDIOCTX pIoCtx)
    895 {
    896     int rc = VERR_NOT_IMPLEMENTED;
    897     LogFlowFunc(("returns %Rrc\n", rc));
    898     return rc;
    899 }
     937/** @copydoc VDCACHEBACKEND::pfnAsyncFlush */
     938static int vciAsyncFlush(void *pBackendData, PVDIOCTX pIoCtx)
     939{
     940    int rc = VINF_SUCCESS;
     941    PVCICACHE pImage = (PVCICACHE)pBackendData;
     942
     943    if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     944        rc = vciFileFlushAsync(pImage, pIoCtx, NULL, NULL);
     945
     946    return rc;
     947}
     948
    900949
    901950VDCACHEBACKEND g_VciCacheBackend =
  • trunk/src/VBox/Devices/Storage/VDICore.h

    r32388 r32536  
    55
    66/*
    7  * Copyright (C) 2006-2009 Oracle Corporation
     7 * Copyright (C) 2006-2010 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2222*   Header Files                                                               *
    2323*******************************************************************************/
    24 #ifndef VBOX_VDICORE_VD
    2524#include <VBox/VBoxHDD.h>
    26 #else /* VBOX_VDICORE_VD */
    27 #include <VBox/VBoxHDD.h>
    28 #endif /* VBOX_VDICORE_VD */
     25#ifndef VBOX_VDICORE_VD
    2926#include <VBox/pdm.h>
     27#endif /* !VBOX_VDICORE_VD */
    3028#include <VBox/mm.h>
    3129#include <VBox/err.h>
     
    3533#include <iprt/assert.h>
    3634#include <iprt/uuid.h>
    37 #include <iprt/file.h>
    3835#include <iprt/string.h>
    3936#include <iprt/asm.h>
     
    192189    /** Image comment. (UTF-8) */
    193190    char            szComment[VDI_IMAGE_COMMENT_SIZE];
    194     /** Offset of Blocks array from the begining of image file.
     191    /** Offset of blocks array from the begining of image file.
    195192     * Should be sector-aligned for HDD access optimization. */
    196193    uint32_t        offBlocks;
     
    241238} VDIHEADER, *PVDIHEADER;
    242239
     240/**
     241 * File alignment boundary for both the block array and data area. Should be
     242 * at least the size of a physical sector on disk for performance reasons.
     243 * With the growing market share of disks with 4K sectors this needs to be
     244 * bumped, and maybe again later. */
     245#define VDI_DATA_ALIGN _4K
     246
    243247/** Block 'pointer'. */
    244248typedef uint32_t    VDIIMAGEBLOCKPOINTER;
     
    555559    struct VDIIMAGEDESC    *pNext;
    556560#endif /* !VBOX_VDICORE_VD */
    557 #ifndef VBOX_WITH_NEW_IO_CODE
    558     /** File handle. */
    559     RTFILE                  File;
    560 #else
    561561    /** Opaque storage handle. */
    562562    PVDIOSTORAGE            pStorage;
    563 #endif
    564563#ifndef VBOX_VDICORE_VD
    565564    /** True if the image is operating in readonly mode. */
     
    568567    unsigned                fOpen;
    569568#else /* VBOX_VDICORE_VD */
    570     /** Image open flags, VD__OPEN_FLAGS_*. */
     569    /** Image open flags, VD_OPEN_FLAGS_*. */
    571570    unsigned                uOpenFlags;
    572571#endif /* VBOX_VDICORE_VD */
     
    610609    const char             *pszFilename;
    611610    /** Physical geometry of this image (never actually stored). */
    612     PDMMEDIAGEOMETRY        PCHSGeometry;
     611    VDGEOMETRY              PCHSGeometry;
    613612    /** Pointer to the per-disk VD interface list. */
    614613    PVDINTERFACE            pVDIfsDisk;
     
    619618    /** Error interface callback table. */
    620619    PVDINTERFACEERROR       pInterfaceErrorCallbacks;
    621 # ifdef VBOX_WITH_NEW_IO_CODE
    622620    /** I/O interface. */
    623621    PVDINTERFACE            pInterfaceIO;
    624622    /** I/O interface callbacks. */
    625623    PVDINTERFACEIO          pInterfaceIOCallbacks;
    626 # endif
    627624#endif /* VBOX_VDICORE_VD */
    628625} VDIIMAGEDESC, *PVDIIMAGEDESC;
     
    673670    bool            fHonorZeroWrites;
    674671
     672#ifndef VBOX_VDICORE_VD
    675673    /** The media interface. */
    676674    PDMIMEDIA       IMedia;
    677675    /** Pointer to the driver instance. */
    678676    PPDMDRVINS      pDrvIns;
     677#endif /* !VBOX_VDICORE_VD */
    679678};
    680679
  • trunk/src/VBox/Devices/Storage/VDIHDDCore.cpp

    r32431 r32536  
    2828#include <iprt/assert.h>
    2929#include <iprt/uuid.h>
    30 #include <iprt/file.h>
    3130#include <iprt/string.h>
    3231#include <iprt/asm.h>
     
    5857static int  vdiUpdateHeader(PVDIIMAGEDESC pImage);
    5958static int  vdiUpdateBlockInfo(PVDIIMAGEDESC pImage, unsigned uBlock);
    60 static void vdiFreeImage(PVDIIMAGEDESC pImage, bool fDelete);
    6159static int  vdiUpdateHeaderAsync(PVDIIMAGEDESC pImage, PVDIOCTX pIoCtx);
    6260static int  vdiUpdateBlockInfoAsync(PVDIIMAGEDESC pImage, unsigned uBlock, PVDIOCTX pIoCtx);
     
    7876}
    7977
    80 
    81 static int vdiFileOpen(PVDIIMAGEDESC pImage, bool fReadonly, bool fShareable,
    82                        bool fCreate)
     78/**
     79 * Internal: signal an informational message to the frontend.
     80 */
     81DECLINLINE(int) vdiMessage(PVDIIMAGEDESC pImage, const char *pszFormat, ...)
    8382{
    8483    int rc = VINF_SUCCESS;
    85 
    86     AssertMsg(!(fReadonly && fCreate), ("Image can't be opened readonly while being created\n"));
    87 
    88 #ifndef VBOX_WITH_NEW_IO_CODE
    89     uint32_t fDeny = fReadonly | fShareable ? RTFILE_O_DENY_NONE : RTFILE_O_DENY_WRITE;
    90     uint32_t fOpen = fReadonly ? RTFILE_O_READ : RTFILE_O_READWRITE;
    91     fOpen |= fDeny;
    92 
    93     if (fCreate)
    94         fOpen |= RTFILE_O_CREATE;
    95     else
    96         fOpen |= RTFILE_O_OPEN;
    97 
    98     rc = RTFileOpen(&pImage->File, pImage->pszFilename, fOpen);
    99 #else
    100     unsigned uOpenFlags = fReadonly ? VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY : 0;
    101 
    102     if (fCreate)
    103         uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE;
    104 
    105     if (fShareable)
    106         uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_DONT_LOCK;
    107 
    108     rc = pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser,
    109                                                 pImage->pszFilename,
    110                                                 uOpenFlags,
    111                                                 &pImage->pStorage);
    112 #endif
    113 
    114     return rc;
    115 }
    116 
    117 static int vdiFileClose(PVDIIMAGEDESC pImage)
    118 {
    119     int rc = VINF_SUCCESS;
    120 
    121 #ifndef VBOX_WITH_NEW_IO_CODE
    122     if (pImage->File != NIL_RTFILE)
    123         rc = RTFileClose(pImage->File);
    124 
    125     pImage->File = NIL_RTFILE;
    126 #else
    127     rc = pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser,
    128                                                  pImage->pStorage);
    129 
    130     pImage->pStorage = NULL;
    131 #endif
    132 
    133     return rc;
    134 }
    135 
    136 static 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     rc = pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser,
    144                                                      pImage->pStorage);
    145 #endif
    146 
    147     return rc;
    148 }
    149 
    150 static int vdiFileGetSize(PVDIIMAGEDESC pImage, uint64_t *pcbSize)
    151 {
    152     int rc = VINF_SUCCESS;
    153 
    154 #ifndef VBOX_WITH_NEW_IO_CODE
    155     rc = RTFileGetSize(pImage->File, pcbSize);
    156 #else
    157     rc = pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser,
    158                                                    pImage->pStorage,
    159                                                    pcbSize);
    160 #endif
    161 
    162     return rc;
    163 }
    164 
    165 static int vdiFileSetSize(PVDIIMAGEDESC pImage, uint64_t cbSize)
    166 {
    167     int rc = VINF_SUCCESS;
    168 
    169 #ifndef VBOX_WITH_NEW_IO_CODE
    170     rc = RTFileSetSize(pImage->File, cbSize);
    171 #else
    172     rc = pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser,
    173                                                    pImage->pStorage,
    174                                                    cbSize);
    175 #endif
    176 
    177     return rc;
    178 }
    179 
    180 static int vdiFileWriteSync(PVDIIMAGEDESC pImage, uint64_t off, const void *pcvBuf, size_t cbWrite, size_t *pcbWritten)
    181 {
    182     int rc = VINF_SUCCESS;
    183 
    184 #ifndef VBOX_WITH_NEW_IO_CODE
    185     rc = RTFileWriteAt(pImage->File, off, pcvBuf, cbWrite, pcbWritten);
    186 #else
    187     rc = pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser,
    188                                                      pImage->pStorage,
    189                                                      off, cbWrite, pcvBuf,
    190                                                      pcbWritten);
    191 #endif
    192 
    193     return rc;
    194 }
    195 
    196 static int vdiFileReadSync(PVDIIMAGEDESC pImage, uint64_t off, void *pvBuf, size_t cbRead, size_t *pcbRead)
    197 {
    198     int rc = VINF_SUCCESS;
    199 
    200 #ifndef VBOX_WITH_NEW_IO_CODE
    201     rc = RTFileReadAt(pImage->File, off, pvBuf, cbRead, pcbRead);
    202 #else
    203     rc = pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser,
    204                                                     pImage->pStorage,
    205                                                     off, cbRead, pvBuf,
    206                                                     pcbRead);
    207 #endif
    208 
    209     return rc;
    210 }
    211 
    212 static int vdiFileWriteMetaAsync(PVDIIMAGEDESC pImage, uint64_t off, void *pcvBuf, size_t cbWrite,
    213                                  PVDIOCTX pIoCtx)
     84    va_list va;
     85    va_start(va, pszFormat);
     86    if (pImage->pInterfaceError && pImage->pInterfaceErrorCallbacks)
     87        rc = pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser,
     88                                                          pszFormat, va);
     89    va_end(va);
     90    return rc;
     91}
     92
     93
     94DECLINLINE(int) vdiFileOpen(PVDIIMAGEDESC pImage, const char *pszFilename,
     95                            uint32_t fOpen)
     96{
     97    return pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser,
     98                                                  pszFilename, fOpen,
     99                                                  &pImage->pStorage);
     100}
     101
     102DECLINLINE(int) vdiFileClose(PVDIIMAGEDESC pImage)
     103{
     104    return pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser,
     105                                                   pImage->pStorage);
     106}
     107
     108DECLINLINE(int) vdiFileDelete(PVDIIMAGEDESC pImage, const char *pszFilename)
     109{
     110    return pImage->pInterfaceIOCallbacks->pfnDelete(pImage->pInterfaceIO->pvUser,
     111                                                    pszFilename);
     112}
     113
     114DECLINLINE(int) vdiFileMove(PVDIIMAGEDESC pImage, const char *pszSrc,
     115                            const char *pszDst, unsigned fMove)
     116{
     117    return pImage->pInterfaceIOCallbacks->pfnMove(pImage->pInterfaceIO->pvUser,
     118                                                  pszSrc, pszDst, fMove);
     119}
     120
     121DECLINLINE(int) vdiFileGetFreeSpace(PVDIIMAGEDESC pImage, const char *pszFilename,
     122                                    int64_t *pcbFree)
     123{
     124    return pImage->pInterfaceIOCallbacks->pfnGetFreeSpace(pImage->pInterfaceIO->pvUser,
     125                                                          pszFilename, pcbFree);
     126}
     127
     128DECLINLINE(int) vdiFileGetSize(PVDIIMAGEDESC pImage, uint64_t *pcbSize)
     129{
     130    return pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser,
     131                                                     pImage->pStorage, pcbSize);
     132}
     133
     134DECLINLINE(int) vdiFileSetSize(PVDIIMAGEDESC pImage, uint64_t cbSize)
     135{
     136    return pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser,
     137                                                     pImage->pStorage, cbSize);
     138}
     139
     140DECLINLINE(int) vdiFileWriteSync(PVDIIMAGEDESC pImage, uint64_t uOffset,
     141                                 const void *pvBuffer, size_t cbBuffer,
     142                                 size_t *pcbWritten)
     143{
     144    return pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser,
     145                                                       pImage->pStorage, uOffset,
     146                                                       pvBuffer, cbBuffer, pcbWritten);
     147}
     148
     149DECLINLINE(int) vdiFileReadSync(PVDIIMAGEDESC pImage, uint64_t uOffset,
     150                                void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
     151{
     152    return pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser,
     153                                                      pImage->pStorage, uOffset,
     154                                                      pvBuffer, cbBuffer, pcbRead);
     155}
     156
     157DECLINLINE(int) vdiFileFlushSync(PVDIIMAGEDESC pImage)
     158{
     159    return pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser,
     160                                                       pImage->pStorage);
     161}
     162
     163DECLINLINE(int) vdiFileReadUserAsync(PVDIIMAGEDESC pImage, uint64_t uOffset,
     164                                     PVDIOCTX pIoCtx, size_t cbRead)
     165{
     166    return pImage->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser,
     167                                                           pImage->pStorage,
     168                                                           uOffset, pIoCtx,
     169                                                           cbRead);
     170}
     171
     172DECLINLINE(int) vdiFileWriteUserAsync(PVDIIMAGEDESC pImage, uint64_t uOffset,
     173                                      PVDIOCTX pIoCtx, size_t cbWrite,
     174                                      PFNVDXFERCOMPLETED pfnComplete,
     175                                      void *pvCompleteUser)
     176{
     177    return pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser,
     178                                                            pImage->pStorage,
     179                                                            uOffset, pIoCtx,
     180                                                            cbWrite,
     181                                                            pfnComplete,
     182                                                            pvCompleteUser);
     183}
     184
     185DECLINLINE(int) vdiFileWriteMetaAsync(PVDIIMAGEDESC pImage, uint64_t uOffset,
     186                                      void *pvBuffer, size_t cbBuffer,
     187                                      PVDIOCTX pIoCtx,
     188                                      PFNVDXFERCOMPLETED pfnComplete,
     189                                      void *pvCompleteUser)
    214190{
    215191    return pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pImage->pInterfaceIO->pvUser,
    216192                                                            pImage->pStorage,
    217                                                             off, pcvBuf, cbWrite, pIoCtx,
    218                                                             NULL, NULL);
    219 }
    220 
    221 static int vdiFileReadMetaAsync(PVDIIMAGEDESC pImage, uint64_t off, void *pvBuf, size_t cbRead,
    222                                 PVDIOCTX pIoCtx)
    223 {
    224     return pImage->pInterfaceIOCallbacks->pfnReadMetaAsync(pImage->pInterfaceIO->pvUser,
    225                                                            pImage->pStorage,
    226                                                            off, pvBuf, cbRead, pIoCtx,
    227                                                            NULL, NULL, NULL);
    228 }
    229 
    230 static bool vdiFileOpened(PVDIIMAGEDESC pImage)
    231 {
    232 #ifndef VBOX_WITH_NEW_IO_CODE
    233     return pImage->File != NIL_RTFILE;
    234 #else
    235     return pImage->pStorage != NULL;
    236 #endif
    237 }
    238 
    239 static int vdiFileFlushAsync(PVDIIMAGEDESC pImage, PVDIOCTX pIoCtx)
     193                                                            uOffset, pvBuffer,
     194                                                            cbBuffer, pIoCtx,
     195                                                            pfnComplete,
     196                                                            pvCompleteUser);
     197}
     198
     199DECLINLINE(int) vdiFileFlushAsync(PVDIIMAGEDESC pImage, PVDIOCTX pIoCtx,
     200                                  PFNVDXFERCOMPLETED pfnComplete,
     201                                  void *pvCompleteUser)
    240202{
    241203    return pImage->pInterfaceIOCallbacks->pfnFlushAsync(pImage->pInterfaceIO->pvUser,
    242                                                         pImage->pStorage, pIoCtx,
    243                                                         NULL, NULL);
    244 }
    245 
     204                                                        pImage->pStorage,
     205                                                        pIoCtx, pfnComplete,
     206                                                        pvCompleteUser);
     207}
     208
     209DECLINLINE(size_t) vdiFileIoCtxSet(PVDIIMAGEDESC pImage, PVDIOCTX pIoCtx,
     210                                   int ch, size_t cbSet)
     211{
     212    return pImage->pInterfaceIOCallbacks->pfnIoCtxSet(pImage->pInterfaceIO->pvUser,
     213                                                      pIoCtx, ch, cbSet);
     214}
     215
     216
     217/**
     218 * Internal: Flush the image file to disk.
     219 */
     220static void vdiFlushImage(PVDIIMAGEDESC pImage)
     221{
     222    if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     223    {
     224        /* Save header. */
     225        int rc = vdiUpdateHeader(pImage);
     226        AssertMsgRC(rc, ("vdiUpdateHeader() failed, filename=\"%s\", rc=%Rrc\n",
     227                         pImage->pszFilename, rc));
     228        vdiFileFlushSync(pImage);
     229    }
     230}
     231
     232/**
     233 * Internal: Free all allocated space for representing an image, and optionally
     234 * delete the image from disk.
     235 */
     236static int vdiFreeImage(PVDIIMAGEDESC pImage, bool fDelete)
     237{
     238    int rc = VINF_SUCCESS;
     239
     240    /* Freeing a never allocated image (e.g. because the open failed) is
     241     * not signalled as an error. After all nothing bad happens. */
     242    if (pImage)
     243    {
     244        if (pImage->pStorage)
     245        {
     246            /* No point updating the file that is deleted anyway. */
     247            if (!fDelete)
     248                vdiFlushImage(pImage);
     249
     250            vdiFileClose(pImage);
     251            pImage->pStorage = NULL;
     252        }
     253
     254        if (pImage->paBlocks)
     255        {
     256            RTMemFree(pImage->paBlocks);
     257            pImage->paBlocks = NULL;
     258        }
     259
     260        if (fDelete && pImage->pszFilename)
     261            vdiFileDelete(pImage, pImage->pszFilename);
     262    }
     263
     264    LogFlowFunc(("returns %Rrc\n", rc));
     265    return rc;
     266}
    246267
    247268/**
     
    260281    return uNumber == 1 ? uPower2 : 0;
    261282}
    262 
    263283
    264284/**
     
    360380
    361381    /* Init offsets. */
    362     pHeader->u.v1.offBlocks = RT_ALIGN_32(sizeof(VDIPREHEADER) + sizeof(VDIHEADER1), VDI_GEOMETRY_SECTOR_SIZE);
    363     pHeader->u.v1.offData = RT_ALIGN_32(pHeader->u.v1.offBlocks + (pHeader->u.v1.cBlocks * sizeof(VDIIMAGEBLOCKPOINTER)), VDI_GEOMETRY_SECTOR_SIZE);
     382    pHeader->u.v1.offBlocks = RT_ALIGN_32(sizeof(VDIPREHEADER) + sizeof(VDIHEADER1), VDI_DATA_ALIGN);
     383    pHeader->u.v1.offData = RT_ALIGN_32(pHeader->u.v1.offBlocks + (pHeader->u.v1.cBlocks * sizeof(VDIIMAGEBLOCKPOINTER)), VDI_DATA_ALIGN);
    364384
    365385    /* Init uuids. */
     
    517537static int vdiCreateImage(PVDIIMAGEDESC pImage, uint64_t cbSize,
    518538                          unsigned uImageFlags, const char *pszComment,
    519                           PCPDMMEDIAGEOMETRY pPCHSGeometry,
    520                           PCPDMMEDIAGEOMETRY pLCHSGeometry, PCRTUUID pUuid,
     539                          PCVDGEOMETRY pPCHSGeometry,
     540                          PCVDGEOMETRY pLCHSGeometry, PCRTUUID pUuid,
    521541                          unsigned uOpenFlags, PFNVDPROGRESS pfnProgress,
    522542                          void *pvUser, unsigned uPercentStart,
     
    542562        pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError);
    543563
    544 #ifdef VBOX_WITH_NEW_IO_CODE
    545     /* Try to get I/O interface. */
     564    /* Get I/O interface. */
    546565    pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsImage, VDINTERFACETYPE_IO);
    547     AssertPtr(pImage->pInterfaceIO);
     566    AssertPtrReturn(pImage->pInterfaceIO, VERR_INVALID_PARAMETER);
    548567    pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO);
    549     AssertPtr(pImage->pInterfaceIOCallbacks);
    550 #endif
     568    AssertPtrReturn(pImage->pInterfaceIOCallbacks, VERR_INVALID_PARAMETER);
    551569
    552570    vdiInitPreHeader(&pImage->PreHeader);
     
    586604
    587605    /* Create image file. */
    588     rc = vdiFileOpen(pImage, false /* fReadonly */,
    589                      !!(uOpenFlags & VD_OPEN_FLAGS_SHAREABLE),
    590                      true /* fCreate */);
     606    rc = vdiFileOpen(pImage, pImage->pszFilename,
     607                     VDOpenFlagsToFileOpenFlags(uOpenFlags & ~VD_OPEN_FLAGS_READONLY,
     608                                                true /* fCreate */));
    591609    if (RT_FAILURE(rc))
    592610    {
     
    602620        /* Check the free space on the disk and leave early if there is not
    603621         * sufficient space available. */
    604         RTFOFF cbFree = 0;
    605         rc = RTFsQuerySizes(pImage->pszFilename, NULL, &cbFree, NULL, NULL);
     622        int64_t cbFree = 0;
     623        rc = vdiFileGetFreeSpace(pImage, pImage->pszFilename, &cbFree);
    606624        if (RT_SUCCESS(rc) /* ignore errors */ && ((uint64_t)cbFree < cbTotal))
    607625        {
     
    645663
    646664    /* Write header. */
    647     rc = vdiFileWriteSync(pImage, sizeof(pImage->PreHeader), &pImage->Header.u.v1plus, sizeof(pImage->Header.u.v1plus), NULL);
     665    rc = vdiFileWriteSync(pImage, sizeof(pImage->PreHeader),
     666                          &pImage->Header.u.v1plus,
     667                          sizeof(pImage->Header.u.v1plus), NULL);
    648668    if (RT_FAILURE(rc))
    649669    {
     
    652672    }
    653673
    654     rc = vdiFileWriteSync(pImage, pImage->offStartBlocks,
    655                           pImage->paBlocks,
     674    rc = vdiFileWriteSync(pImage, pImage->offStartBlocks, pImage->paBlocks,
    656675                          getImageBlocks(&pImage->Header) * sizeof(VDIIMAGEBLOCKPOINTER),
    657676                          NULL);
     
    730749        pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError);
    731750
    732 #ifdef VBOX_WITH_NEW_IO_CODE
    733     /* Try to get I/O interface. */
     751    /* Get I/O interface. */
    734752    pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsImage, VDINTERFACETYPE_IO);
    735     AssertPtr(pImage->pInterfaceIO);
     753    AssertPtrReturn(pImage->pInterfaceIO, VERR_INVALID_PARAMETER);
    736754    pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO);
    737     AssertPtr(pImage->pInterfaceIOCallbacks);
    738 #endif
     755    AssertPtrReturn(pImage->pInterfaceIOCallbacks, VERR_INVALID_PARAMETER);
    739756
    740757    /*
    741758     * Open the image.
    742759     */
    743     rc = vdiFileOpen(pImage,
    744                      !!(uOpenFlags & VD_OPEN_FLAGS_READONLY),
    745                      !!(uOpenFlags & VD_OPEN_FLAGS_SHAREABLE),
    746                      false /* fCreate */);
     760    rc = vdiFileOpen(pImage, pImage->pszFilename,
     761                     VDOpenFlagsToFileOpenFlags(uOpenFlags, false /* fCreate */));
    747762    if (RT_FAILURE(rc))
    748763    {
     
    753768
    754769    /* Read pre-header. */
    755     rc = vdiFileReadSync(pImage, 0, &pImage->PreHeader, sizeof(pImage->PreHeader),
    756                          NULL);
     770    rc = vdiFileReadSync(pImage, 0, &pImage->PreHeader, sizeof(pImage->PreHeader), NULL);
    757771    if (RT_FAILURE(rc))
    758772    {
     
    807821            {
    808822                /* Read the actual VDI 1.1+ header completely. */
    809                 rc = vdiFileReadSync(pImage, sizeof(pImage->PreHeader), &pImage->Header.u.v1plus, sizeof(pImage->Header.u.v1plus), NULL);
     823                rc = vdiFileReadSync(pImage, sizeof(pImage->PreHeader),
     824                                     &pImage->Header.u.v1plus,
     825                                     sizeof(pImage->Header.u.v1plus), NULL);
    810826                if (RT_FAILURE(rc))
    811827                {
     
    858874    {
    859875        case 0:
    860             rc = vdiFileWriteSync(pImage, sizeof(VDIPREHEADER), &pImage->Header.u.v0, sizeof(pImage->Header.u.v0), NULL);
     876            rc = vdiFileWriteSync(pImage, sizeof(VDIPREHEADER),
     877                                  &pImage->Header.u.v0, sizeof(pImage->Header.u.v0),
     878                                  NULL);
    861879            break;
    862880        case 1:
    863881            if (pImage->Header.u.v1plus.cbHeader < sizeof(pImage->Header.u.v1plus))
    864                 rc = vdiFileWriteSync(pImage, sizeof(VDIPREHEADER), &pImage->Header.u.v1, sizeof(pImage->Header.u.v1), NULL);
     882                rc = vdiFileWriteSync(pImage, sizeof(VDIPREHEADER),
     883                                      &pImage->Header.u.v1, sizeof(pImage->Header.u.v1),
     884                                      NULL);
    865885            else
    866                 rc = vdiFileWriteSync(pImage, sizeof(VDIPREHEADER), &pImage->Header.u.v1plus, sizeof(pImage->Header.u.v1plus), NULL);
     886                rc = vdiFileWriteSync(pImage, sizeof(VDIPREHEADER),
     887                                      &pImage->Header.u.v1plus, sizeof(pImage->Header.u.v1plus),
     888                                      NULL);
    867889            break;
    868890        default:
     
    884906        case 0:
    885907            rc = vdiFileWriteMetaAsync(pImage, sizeof(VDIPREHEADER),
    886                                        &pImage->Header.u.v0, sizeof(pImage->Header.u.v0),
    887                                        pIoCtx);
    888 
     908                                       &pImage->Header.u.v0,
     909                                       sizeof(pImage->Header.u.v0),
     910                                       pIoCtx, NULL, NULL);
    889911            break;
    890912        case 1:
    891913            if (pImage->Header.u.v1plus.cbHeader < sizeof(pImage->Header.u.v1plus))
    892914                rc = vdiFileWriteMetaAsync(pImage, sizeof(VDIPREHEADER),
    893                                            &pImage->Header.u.v1, sizeof(pImage->Header.u.v1),
    894                                            pIoCtx);
     915                                           &pImage->Header.u.v1,
     916                                           sizeof(pImage->Header.u.v1),
     917                                           pIoCtx, NULL, NULL);
    895918            else
    896919                rc = vdiFileWriteMetaAsync(pImage, sizeof(VDIPREHEADER),
    897                                            &pImage->Header.u.v1plus, sizeof(pImage->Header.u.v1plus),
    898                                            pIoCtx);
     920                                           &pImage->Header.u.v1plus,
     921                                           sizeof(pImage->Header.u.v1plus),
     922                                           pIoCtx, NULL, NULL);
    899923            break;
    900924        default:
     
    917941    {
    918942        /* write only one block pointer. */
    919         rc = vdiFileWriteSync(pImage,
    920                               pImage->offStartBlocks + uBlock * sizeof(VDIIMAGEBLOCKPOINTER),
    921                               &pImage->paBlocks[uBlock],
    922                               sizeof(VDIIMAGEBLOCKPOINTER),
     943        rc = vdiFileWriteSync(pImage, pImage->offStartBlocks + uBlock * sizeof(VDIIMAGEBLOCKPOINTER),
     944                              &pImage->paBlocks[uBlock], sizeof(VDIIMAGEBLOCKPOINTER),
    923945                              NULL);
    924946        AssertMsgRC(rc, ("vdiUpdateBlockInfo failed to update block=%u, filename=\"%s\", rc=%Rrc\n",
     
    943965                                   &pImage->paBlocks[uBlock],
    944966                                   sizeof(VDIIMAGEBLOCKPOINTER),
    945                                    pIoCtx);
     967                                   pIoCtx, NULL, NULL);
    946968        AssertMsg(RT_SUCCESS(rc) || rc == VERR_VD_ASYNC_IO_IN_PROGRESS,
    947969                  ("vdiUpdateBlockInfo failed to update block=%u, filename=\"%s\", rc=%Rrc\n",
     
    949971    }
    950972    return rc;
    951 }
    952 
    953 /**
    954  * Internal: Flush the image file to disk.
    955  */
    956 static void vdiFlushImage(PVDIIMAGEDESC pImage)
    957 {
    958     if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    959     {
    960         /* Save header. */
    961         int rc = vdiUpdateHeader(pImage);
    962         AssertMsgRC(rc, ("vdiUpdateHeader() failed, filename=\"%s\", rc=%Rrc\n",
    963                          pImage->pszFilename, rc));
    964         vdiFileFlushSync(pImage);
    965     }
    966973}
    967974
     
    980987                  ("vdiUpdateHeaderAsync() failed, filename=\"%s\", rc=%Rrc\n",
    981988                  pImage->pszFilename, rc));
    982         rc = vdiFileFlushAsync(pImage, pIoCtx);
     989        rc = vdiFileFlushAsync(pImage, pIoCtx, NULL, NULL);
    983990        AssertMsg(RT_SUCCESS(rc) || rc == VERR_VD_ASYNC_IO_IN_PROGRESS,
    984991                  ("Flushing data to disk failed rc=%Rrc\n", rc));
     
    988995}
    989996
    990 /**
    991  * Internal: Free all allocated space for representing an image, and optionally
    992  * delete the image from disk.
    993  */
    994 static void vdiFreeImage(PVDIIMAGEDESC pImage, bool fDelete)
    995 {
    996     AssertPtr(pImage);
    997 
    998     if (vdiFileOpened(pImage))
    999     {
    1000         vdiFlushImage(pImage);
    1001         vdiFileClose(pImage);
    1002     }
    1003     if (pImage->paBlocks)
    1004     {
    1005         RTMemFree(pImage->paBlocks);
    1006         pImage->paBlocks = NULL;
    1007     }
    1008     if (fDelete && pImage->pszFilename)
    1009         RTFileDelete(pImage->pszFilename);
    1010 }
    1011 
    1012997
    1013998/** @copydoc VBOXHDDBACKEND::pfnCheckIfValid */
    1014 static int vdiCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk)
     999static int vdiCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk,
     1000                           PVDINTERFACE pVDIfsImage)
    10151001{
    10161002    LogFlowFunc(("pszFilename=\"%s\"\n", pszFilename));
     
    10321018    }
    10331019    pImage->pszFilename = pszFilename;
    1034 #ifndef VBOX_WITH_NEW_IO_CODE
    1035     pImage->File = NIL_RTFILE;
    1036 #else
    10371020    pImage->pStorage = NULL;
    1038 #endif
    10391021    pImage->paBlocks = NULL;
    10401022    pImage->pVDIfsDisk = pVDIfsDisk;
    1041     /* For the async I/O interface which is normally retrieved from the image interface list. */
    1042     pImage->pVDIfsImage = pVDIfsDisk;
     1023    pImage->pVDIfsImage = pVDIfsImage;
    10431024
    10441025    rc = vdiOpenImage(pImage, VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_READONLY);
     
    10821063    }
    10831064    pImage->pszFilename = pszFilename;
    1084 #ifndef VBOX_WITH_NEW_IO_CODE
    1085     pImage->File = NIL_RTFILE;
    1086 #else
    10871065    pImage->pStorage = NULL;
    1088 #endif
    10891066    pImage->paBlocks = NULL;
    10901067    pImage->pVDIfsDisk = pVDIfsDisk;
     
    11031080static int vdiCreate(const char *pszFilename, uint64_t cbSize,
    11041081                     unsigned uImageFlags, const char *pszComment,
    1105                      PCPDMMEDIAGEOMETRY pPCHSGeometry,
    1106                      PCPDMMEDIAGEOMETRY pLCHSGeometry, PCRTUUID pUuid,
    1107                      unsigned uOpenFlags, unsigned uPercentStart,
    1108                      unsigned uPercentSpan, PVDINTERFACE pVDIfsDisk,
    1109                      PVDINTERFACE pVDIfsImage, PVDINTERFACE pVDIfsOperation,
    1110                      void **ppBackendData)
     1082                     PCVDGEOMETRY pPCHSGeometry, PCVDGEOMETRY pLCHSGeometry,
     1083                     PCRTUUID pUuid, unsigned uOpenFlags,
     1084                     unsigned uPercentStart, unsigned uPercentSpan,
     1085                     PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
     1086                     PVDINTERFACE pVDIfsOperation, void **ppBackendData)
    11111087{
    11121088    LogFlowFunc(("pszFilename=\"%s\" cbSize=%llu uImageFlags=%#x pszComment=\"%s\" pPCHSGeometry=%#p pLCHSGeometry=%#p Uuid=%RTuuid uOpenFlags=%#x uPercentStart=%u uPercentSpan=%u pVDIfsDisk=%#p pVDIfsImage=%#p pVDIfsOperation=%#p ppBackendData=%#p", pszFilename, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, ppBackendData));
     
    11341110    }
    11351111
    1136     /* Check size. Maximum 2PB-3M (to be on the safe side). No tricks with
    1137      * adjusting the 1M block size so far, which would extend the size. */
     1112    /* Check size. Maximum 4PB-3M. No tricks with adjusting the 1M block size
     1113     * so far, which would extend the size. */
     1114    cbSize = RT_ALIGN_64(cbSize, _1M);
    11381115    if (    !cbSize
    11391116        ||  cbSize >= _1P * 2 - _1M * 3)
     
    11611138    }
    11621139    pImage->pszFilename = pszFilename;
    1163 #ifndef VBOX_WITH_NEW_IO_CODE
    1164     pImage->File = NIL_RTFILE;
    1165 #else
    11661140    pImage->pStorage = NULL;
    1167 #endif
    11681141    pImage->paBlocks = NULL;
    11691142    pImage->pVDIfsDisk = pVDIfsDisk;
     
    11821155            rc = vdiOpenImage(pImage, uOpenFlags);
    11831156            if (RT_FAILURE(rc))
     1157            {
     1158                RTMemFree(pImage);
    11841159                goto out;
     1160            }
    11851161        }
    11861162        *ppBackendData = pImage;
     
    12151191
    12161192    /* Rename the file. */
    1217     rc = RTFileMove(pImage->pszFilename, pszFilename, 0);
     1193    rc = vdiFileMove(pImage, pImage->pszFilename, pszFilename, 0);
    12181194    if (RT_FAILURE(rc))
    12191195    {
     
    12441220    LogFlowFunc(("pBackendData=%#p fDelete=%d\n", pBackendData, fDelete));
    12451221    PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData;
    1246     int rc = VINF_SUCCESS;
    1247 
    1248     /* Freeing a never allocated image (e.g. because the open failed) is
    1249      * not signalled as an error. After all nothing bad happens. */
    1250     if (pImage)
    1251     {
    1252         vdiFreeImage(pImage, fDelete);
    1253         RTMemFree(pImage);
    1254     }
     1222    int rc;
     1223
     1224    rc = vdiFreeImage(pImage, fDelete);
     1225    RTMemFree(pImage);
    12551226
    12561227    LogFlowFunc(("returns %Rrc\n", rc));
     
    13401311    /* No size check here, will do that later.  For dynamic images which are
    13411312     * not multiples of the block size in length, this would prevent writing to
    1342      * the last grain. */
     1313     * the last block. */
    13431314
    13441315    /* Calculate starting block number and offset inside it. */
     
    14811452    {
    14821453        uint64_t cbFile;
    1483         if (vdiFileOpened(pImage))
     1454        if (pImage->pStorage)
    14841455        {
    14851456            int rc = vdiFileGetSize(pImage, &cbFile);
     
    14941465
    14951466/** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */
    1496 static int vdiGetPCHSGeometry(void *pBackendData,
    1497                               PPDMMEDIAGEOMETRY pPCHSGeometry)
     1467static int vdiGetPCHSGeometry(void *pBackendData, PVDGEOMETRY pPCHSGeometry)
    14981468{
    14991469    LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry));
     
    15211491
    15221492/** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */
    1523 static int vdiSetPCHSGeometry(void *pBackendData,
    1524                               PCPDMMEDIAGEOMETRY pPCHSGeometry)
     1493static int vdiSetPCHSGeometry(void *pBackendData, PCVDGEOMETRY pPCHSGeometry)
    15251494{
    15261495    LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
     
    15501519
    15511520/** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */
    1552 static int vdiGetLCHSGeometry(void *pBackendData,
    1553                               PPDMMEDIAGEOMETRY pLCHSGeometry)
     1521static int vdiGetLCHSGeometry(void *pBackendData, PVDGEOMETRY pLCHSGeometry)
    15541522{
    15551523    LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry));
     
    15861554
    15871555/** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */
    1588 static int vdiSetLCHSGeometry(void *pBackendData,
    1589                               PCPDMMEDIAGEOMETRY pLCHSGeometry)
     1556static int vdiSetLCHSGeometry(void *pBackendData, PCVDGEOMETRY pLCHSGeometry)
    15901557{
    15911558    LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
     
    16791646    /* Implement this operation via reopening the image. */
    16801647    pszFilename = pImage->pszFilename;
    1681     vdiFreeImage(pImage, false);
     1648    rc = vdiFreeImage(pImage, false);
     1649    if (RT_FAILURE(rc))
     1650        goto out;
    16821651    rc = vdiOpenImage(pImage, uOpenFlags);
    16831652
     
    19861955    PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData;
    19871956
    1988 #ifndef VBOX_WITH_NEW_IO_CODE
    1989     pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Dumping VDI image \"%s\" mode=%s uOpenFlags=%X File=%08X\n",
    1990                 pImage->pszFilename,
    1991                 (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) ? "r/o" : "r/w",
    1992                 pImage->uOpenFlags,
    1993                 pImage->File);
    1994 #else
    1995     pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Dumping VDI image \"%s\" mode=%s uOpenFlags=%X File=%#p\n",
     1957    vdiMessage(pImage, "Dumping VDI image \"%s\" mode=%s uOpenFlags=%X File=%#p\n",
    19961958                pImage->pszFilename,
    19971959                (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) ? "r/o" : "r/w",
    19981960                pImage->uOpenFlags,
    19991961                pImage->pStorage);
    2000 #endif
    2001     pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: Version=%08X Type=%X Flags=%X Size=%llu\n",
     1962    vdiMessage(pImage, "Header: Version=%08X Type=%X Flags=%X Size=%llu\n",
    20021963                pImage->PreHeader.u32Version,
    20031964                getImageType(&pImage->Header),
    20041965                getImageFlags(&pImage->Header),
    20051966                getImageDiskSize(&pImage->Header));
    2006     pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: cbBlock=%u cbBlockExtra=%u cBlocks=%u cBlocksAllocated=%u\n",
     1967    vdiMessage(pImage, "Header: cbBlock=%u cbBlockExtra=%u cBlocks=%u cBlocksAllocated=%u\n",
    20071968                getImageBlockSize(&pImage->Header),
    20081969                getImageExtraBlockSize(&pImage->Header),
    20091970                getImageBlocks(&pImage->Header),
    20101971                getImageBlocksAllocated(&pImage->Header));
    2011     pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: offBlocks=%u offData=%u\n",
     1972    vdiMessage(pImage, "Header: offBlocks=%u offData=%u\n",
    20121973                getImageBlocksOffset(&pImage->Header),
    20131974                getImageDataOffset(&pImage->Header));
    20141975    PVDIDISKGEOMETRY pg = getImageLCHSGeometry(&pImage->Header);
    20151976    if (pg)
    2016         pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: Geometry: C/H/S=%u/%u/%u cbSector=%u\n",
     1977        vdiMessage(pImage, "Header: Geometry: C/H/S=%u/%u/%u cbSector=%u\n",
    20171978                    pg->cCylinders, pg->cHeads, pg->cSectors, pg->cbSector);
    2018     pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: uuidCreation={%RTuuid}\n", getImageCreationUUID(&pImage->Header));
    2019     pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: uuidModification={%RTuuid}\n", getImageModificationUUID(&pImage->Header));
    2020     pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: uuidParent={%RTuuid}\n", getImageParentUUID(&pImage->Header));
     1979    vdiMessage(pImage, "Header: uuidCreation={%RTuuid}\n", getImageCreationUUID(&pImage->Header));
     1980    vdiMessage(pImage, "Header: uuidModification={%RTuuid}\n", getImageModificationUUID(&pImage->Header));
     1981    vdiMessage(pImage, "Header: uuidParent={%RTuuid}\n", getImageParentUUID(&pImage->Header));
    20211982    if (GET_MAJOR_HEADER_VERSION(&pImage->Header) >= 1)
    2022         pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: uuidParentModification={%RTuuid}\n", getImageParentModificationUUID(&pImage->Header));
    2023     pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Image:  fFlags=%08X offStartBlocks=%u offStartData=%u\n",
     1983        vdiMessage(pImage, "Header: uuidParentModification={%RTuuid}\n", getImageParentModificationUUID(&pImage->Header));
     1984    vdiMessage(pImage, "Image:  fFlags=%08X offStartBlocks=%u offStartData=%u\n",
    20241985                pImage->uImageFlags, pImage->offStartBlocks, pImage->offStartData);
    2025     pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Image:  uBlockMask=%08X cbTotalBlockData=%u uShiftOffset2Index=%u offStartBlockData=%u\n",
     1986    vdiMessage(pImage, "Image:  uBlockMask=%08X cbTotalBlockData=%u uShiftOffset2Index=%u offStartBlockData=%u\n",
    20261987                pImage->uBlockMask,
    20271988                pImage->cbTotalBlockData,
     
    20412002    if (cBlocksNotFree != getImageBlocksAllocated(&pImage->Header))
    20422003    {
    2043         pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "!! WARNING: %u blocks actually allocated (cBlocksAllocated=%u) !!\n",
     2004        vdiMessage(pImage, "!! WARNING: %u blocks actually allocated (cBlocksAllocated=%u) !!\n",
    20442005                cBlocksNotFree, getImageBlocksAllocated(&pImage->Header));
    20452006    }
    20462007    if (cBadBlocks)
    20472008    {
    2048         pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "!! WARNING: %u bad blocks found !!\n",
     2009        vdiMessage(pImage, "!! WARNING: %u bad blocks found !!\n",
    20492010                cBadBlocks);
    20502011    }
    20512012}
    20522013
    2053 static int vdiGetTimeStamp(void *pBackendData, PRTTIMESPEC pTimeStamp)
    2054 {
    2055     int rc = VERR_NOT_IMPLEMENTED;
    2056     LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
    2057     return rc;
    2058 }
    2059 
    2060 static int vdiGetParentTimeStamp(void *pBackendData, PRTTIMESPEC pTimeStamp)
    2061 {
    2062     int rc = VERR_NOT_IMPLEMENTED;
    2063     LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
    2064     return rc;
    2065 }
    2066 
    2067 static int vdiSetParentTimeStamp(void *pBackendData, PCRTTIMESPEC pTimeStamp)
    2068 {
    2069     int rc = VERR_NOT_IMPLEMENTED;
    2070     LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
    2071     return rc;
    2072 }
    2073 
    2074 static int vdiGetParentFilename(void *pBackendData, char **ppszParentFilename)
    2075 {
    2076     int rc = VERR_NOT_IMPLEMENTED;
    2077     LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
    2078     return rc;
    2079 }
    2080 
    2081 static int vdiSetParentFilename(void *pBackendData, const char *pszParentFilename)
    2082 {
    2083     int rc = VERR_NOT_IMPLEMENTED;
    2084     LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
    2085     return rc;
    2086 }
    2087 
    20882014static bool vdiIsAsyncIOSupported(void *pBackendData)
    20892015{
     
    20912017}
    20922018
    2093 static int vdiAsyncRead(void *pvBackendData, uint64_t uOffset, size_t cbToRead,
     2019static int vdiAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbToRead,
    20942020                        PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
    20952021{
    2096     LogFlowFunc(("pvBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n",
    2097                  pvBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead));
    2098     PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pvBackendData;
     2022    LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n",
     2023                 pBackendData, uOffset, pIoCtx, cbToRead, pcbActuallyRead));
     2024    PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData;
    20992025    unsigned uBlock;
    21002026    unsigned offRead;
     
    21272053        size_t cbSet;
    21282054
    2129         cbSet = pImage->pInterfaceIOCallbacks->pfnIoCtxSet(pImage->pInterfaceIO->pvUser,
    2130                                                            pIoCtx, 0, cbToRead);
     2055        cbSet = vdiFileIoCtxSet(pImage, pIoCtx, 0, cbToRead);
    21312056        Assert(cbSet == cbToRead);
    21322057
     
    21382063        uint64_t u64Offset = (uint64_t)pImage->paBlocks[uBlock] * pImage->cbTotalBlockData
    21392064                           + (pImage->offStartData + pImage->offStartBlockData + offRead);
    2140         rc = pImage->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser,
    2141                                                              pImage->pStorage,
    2142                                                              u64Offset,
    2143                                                              pIoCtx, cbToRead);
     2065        rc = vdiFileReadUserAsync(pImage, u64Offset, pIoCtx, cbToRead);
    21442066    }
    21452067
     
    21522074}
    21532075
    2154 static int vdiAsyncWrite(void *pvBackendData, uint64_t uOffset, size_t cbToWrite,
     2076static int vdiAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbToWrite,
    21552077                         PVDIOCTX pIoCtx,
    21562078                         size_t *pcbWriteProcess, size_t *pcbPreRead,
    21572079                         size_t *pcbPostRead, unsigned fWrite)
    21582080{
    2159     LogFlowFunc(("pvBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n",
    2160                  pvBackendData, uOffset, pIoCtx, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));
    2161     PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pvBackendData;
     2081    LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n",
     2082                 pBackendData, uOffset, pIoCtx, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));
     2083    PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData;
    21622084    unsigned uBlock;
    21632085    unsigned offWrite;
     
    21822104    /* No size check here, will do that later.  For dynamic images which are
    21832105     * not multiples of the block size in length, this would prevent writing to
    2184      * the last grain. */
     2106     * the last block. */
    21852107
    21862108    /* Calculate starting block number and offset inside it. */
     
    22242146                uint64_t u64Offset = (uint64_t)cBlocksAllocated * pImage->cbTotalBlockData
    22252147                                   + (pImage->offStartData + pImage->offStartBlockData);
    2226                 rc = pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser,
    2227                                                                       pImage->pStorage,
    2228                                                                       u64Offset,
    2229                                                                       pIoCtx, cbToWrite,
    2230                                                                       NULL, NULL);
     2148                rc = vdiFileWriteUserAsync(pImage, u64Offset, pIoCtx, cbToWrite, NULL, NULL);
    22312149                if (RT_UNLIKELY(RT_FAILURE_NP(rc) && (rc != VERR_VD_ASYNC_IO_IN_PROGRESS)))
    22322150                    goto out;
     
    22552173            uint64_t u64Offset = (uint64_t)pImage->paBlocks[uBlock] * pImage->cbTotalBlockData
    22562174                               + (pImage->offStartData + pImage->offStartBlockData + offWrite);
    2257             rc = pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser,
    2258                                                                   pImage->pStorage,
    2259                                                                   u64Offset,
    2260                                                                   pIoCtx, cbToWrite,
    2261                                                                   NULL, NULL);
     2175            rc = vdiFileWriteUserAsync(pImage, u64Offset, pIoCtx, cbToWrite, NULL, NULL);
    22622176        }
    22632177    } while (0);
     
    22712185}
    22722186
    2273 static int vdiAsyncFlush(void *pvBackendData, PVDIOCTX pIoCtx)
    2274 {
    2275     LogFlowFunc(("pBackendData=%#p\n", pvBackendData));
    2276     PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pvBackendData;
     2187static int vdiAsyncFlush(void *pBackendData, PVDIOCTX pIoCtx)
     2188{
     2189    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     2190    PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData;
    22772191    int rc = VINF_SUCCESS;
    22782192
     
    24972411        /* Truncate the image to the proper size to finish compacting. */
    24982412        rc = vdiFileSetSize(pImage,
    2499                            (uint64_t)uBlockUsedPos * pImage->cbTotalBlockData
    2500                            + (pImage->offStartData + pImage->offStartBlockData));
     2413                              (uint64_t)uBlockUsedPos * pImage->cbTotalBlockData
     2414                            + pImage->offStartData + pImage->offStartBlockData);
    25012415    } while (0);
    25022416
     
    25212435/** @copydoc VBOXHDDBACKEND::pfnResize */
    25222436static int vdiResize(void *pBackendData, uint64_t cbSize,
    2523                      PCPDMMEDIAGEOMETRY pPCHSGeometry, PCPDMMEDIAGEOMETRY pLCHSGeometry,
     2437                     PCVDGEOMETRY pPCHSGeometry, PCVDGEOMETRY pLCHSGeometry,
    25242438                     unsigned uPercentStart, unsigned uPercentSpan,
    25252439                     PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
     
    25472461     * very old images.
    25482462     */
     2463    /** @todo implement making the image smaller, it is the responsibility of
     2464     * the user to know what he's doing. */
    25492465    if (   cbSize < getImageDiskSize(&pImage->Header)
    25502466        || GET_MAJOR_HEADER_VERSION(&pImage->Header) == 0
     
    25602476        uint32_t cBlocksOld      = getImageBlocks(&pImage->Header);           /** < Number of blocks before the resize. */
    25612477        uint64_t cbBlockspaceNew = cBlocksNew * sizeof(VDIIMAGEBLOCKPOINTER); /** < Required space for the block array after the resize. */
    2562         uint64_t offStartDataNew = RT_ALIGN_32(pImage->offStartBlocks + cbBlockspaceNew, VDI_GEOMETRY_SECTOR_SIZE); /** < New start offset for block data after the resize */
     2478        uint64_t offStartDataNew = RT_ALIGN_32(pImage->offStartBlocks + cbBlockspaceNew, VDI_DATA_ALIGN); /** < New start offset for block data after the resize */
    25632479
    25642480        if (   pImage->offStartData != offStartDataNew
    25652481            && cBlocksAllocated > 0)
    25662482        {
    2567             /* Calculate how many sectors nee to be relocated. */
     2483            /* Calculate how many sectors need to be relocated. */
    25682484            uint64_t cbOverlapping = offStartDataNew - pImage->offStartData;
    25692485            unsigned cBlocksReloc = cbOverlapping / getImageBlockSize(&pImage->Header);
     
    25712487                cBlocksReloc++;
    25722488
     2489            /* Since only full blocks can be relocated the new data start is
     2490             * determined by moving it block by block. */
    25732491            cBlocksReloc = RT_MIN(cBlocksReloc, cBlocksAllocated);
    25742492            offStartDataNew = pImage->offStartData;
     
    27302648    /* uBackendCaps */
    27312649      VD_CAP_UUID | VD_CAP_CREATE_FIXED | VD_CAP_CREATE_DYNAMIC
    2732     | VD_CAP_DIFF | VD_CAP_FILE | VD_CAP_ASYNC,
     2650    | VD_CAP_DIFF | VD_CAP_FILE | VD_CAP_ASYNC | VD_CAP_VFS,
    27332651    /* papszFileExtensions */
    27342652    s_apszVdiFileExtensions,
     
    27962714    vdiDump,
    27972715    /* pfnGetTimeStamp */
    2798     vdiGetTimeStamp,
     2716    NULL,
    27992717    /* pfnGetParentTimeStamp */
    2800     vdiGetParentTimeStamp,
     2718    NULL,
    28012719    /* pfnSetParentTimeStamp */
    2802     vdiSetParentTimeStamp,
     2720    NULL,
    28032721    /* pfnGetParentFilename */
    2804     vdiGetParentFilename,
     2722    NULL,
    28052723    /* pfnSetParentFilename */
    2806     vdiSetParentFilename,
     2724    NULL,
    28072725    /* pfnIsAsyncIOSupported */
    28082726    vdiIsAsyncIOSupported,
  • trunk/src/VBox/Devices/Storage/VHDHDDCore.cpp

    r31921 r32536  
    2929#include <iprt/mem.h>
    3030#include <iprt/uuid.h>
    31 #include <iprt/file.h>
    3231#include <iprt/path.h>
    3332#include <iprt/string.h>
    34 #include <iprt/rand.h>
    3533
    3634#define VHD_RELATIVE_MAX_PATH 512
     
    125123typedef struct VHDIMAGE
    126124{
    127     /** Base image name. */
     125    /** Image file name. */
    128126    const char      *pszFilename;
    129 #ifndef VBOX_WITH_NEW_IO_CODE
    130     /** Descriptor file if applicable. */
    131     RTFILE          File;
    132 #else
    133     /** storage handle. */
     127    /** Opaque storage handle. */
    134128    PVDIOSTORAGE    pStorage;
     129
    135130    /** I/O interface. */
    136131    PVDINTERFACE    pInterfaceIO;
    137132    /** I/O interface callbacks. */
    138133    PVDINTERFACEIO  pInterfaceIOCallbacks;
    139 #endif
    140134
    141135    /** Pointer to the per-disk VD interface list. */
     
    148142    PVDINTERFACEERROR pInterfaceErrorCallbacks;
    149143
    150     /** Open flags passed by VBoxHD layer. */
     144    /** Open flags passed by VBoxHDD layer. */
    151145    unsigned        uOpenFlags;
    152146    /** Image flags defined during creation or determined during open. */
     
    154148    /** Total size of the image. */
    155149    uint64_t        cbSize;
    156     /** Original size of the image. */
    157     uint64_t        cbOrigSize;
     150
    158151    /** Physical geometry of this image. */
    159     PDMMEDIAGEOMETRY    PCHSGeometry;
     152    VDGEOMETRY      PCHSGeometry;
    160153    /** Logical geometry of this image. */
    161     PDMMEDIAGEOMETRY    LCHSGeometry;
     154    VDGEOMETRY      LCHSGeometry;
     155
    162156    /** Image UUID. */
    163157    RTUUID          ImageUuid;
    164158    /** Parent image UUID. */
    165159    RTUUID          ParentUuid;
     160
    166161    /** Parent's time stamp at the time of image creation. */
    167162    uint32_t        u32ParentTimeStamp;
    168163    /** Relative path to the parent image. */
    169164    char            *pszParentFilename;
    170     /** File size on the host disk (including all headers). */
    171     uint64_t        FileSize;
     165
    172166    /** The Block Allocation Table. */
    173167    uint32_t        *pBlockAllocationTable;
    174168    /** Number of entries in the table. */
    175169    uint32_t        cBlockAllocationTableEntries;
     170
    176171    /** Size of one data block. */
    177172    uint32_t        cbDataBlock;
     
    256251*******************************************************************************/
    257252
    258 static int vhdFlush(void *pBackendData);
    259 static int vhdLoadDynamicDisk(PVHDIMAGE pImage, uint64_t uDynamicDiskHeaderOffset);
    260 
    261 static int vhdFileOpen(PVHDIMAGE pImage, bool fReadonly, bool fShareable,
    262                        bool fCreate)
     253/**
     254 * Internal: signal an error to the frontend.
     255 */
     256DECLINLINE(int) vhdError(PVHDIMAGE pImage, int rc, RT_SRC_POS_DECL,
     257                         const char *pszFormat, ...)
     258{
     259    va_list va;
     260    va_start(va, pszFormat);
     261    if (pImage->pInterfaceError && pImage->pInterfaceErrorCallbacks)
     262        pImage->pInterfaceErrorCallbacks->pfnError(pImage->pInterfaceError->pvUser, rc, RT_SRC_POS_ARGS,
     263                                                   pszFormat, va);
     264    va_end(va);
     265    return rc;
     266}
     267
     268/**
     269 * Internal: signal an informational message to the frontend.
     270 */
     271DECLINLINE(int) vhdMessage(PVHDIMAGE pImage, const char *pszFormat, ...)
    263272{
    264273    int rc = VINF_SUCCESS;
    265 
    266     AssertMsg(!(fReadonly && fCreate), ("Image can't be opened readonly while being created\n"));
    267 
    268 #ifndef VBOX_WITH_NEW_IO_CODE
    269     uint32_t fDeny = fReadonly | fShareable ? RTFILE_O_DENY_NONE : RTFILE_O_DENY_WRITE;
    270     uint32_t fOpen = fReadonly ? RTFILE_O_READ : RTFILE_O_READWRITE;
    271     fOpen |= fDeny;
    272 
    273     if (fCreate)
    274         fOpen |= RTFILE_O_CREATE;
    275     else
    276         fOpen |= RTFILE_O_OPEN;
    277 
    278     rc = RTFileOpen(&pImage->File, pImage->pszFilename, fOpen);
    279 #else
    280     unsigned uOpenFlags = fReadonly ? VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY : 0;
    281 
    282     if (fCreate)
    283         uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE;
    284 
    285     if (fShareable)
    286         uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_DONT_LOCK;
    287 
    288     rc = pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser,
    289                                                 pImage->pszFilename,
    290                                                 uOpenFlags,
    291                                                 &pImage->pStorage);
    292 #endif
    293 
    294     return rc;
    295 }
    296 
    297 static int vhdFileClose(PVHDIMAGE pImage)
    298 {
    299     int rc = VINF_SUCCESS;
    300 
    301 #ifndef VBOX_WITH_NEW_IO_CODE
    302     if (pImage->File != NIL_RTFILE)
    303         rc = RTFileClose(pImage->File);
    304 
    305     pImage->File = NIL_RTFILE;
    306 #else
    307     rc = pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser,
    308                                                  pImage->pStorage);
    309     pImage->pStorage = NULL;
    310 #endif
    311 
    312     return rc;
    313 }
    314 
    315 static int vhdFileFlushSync(PVHDIMAGE pImage)
    316 {
    317     int rc = VINF_SUCCESS;
    318 
    319 #ifndef VBOX_WITH_NEW_IO_CODE
    320     rc = RTFileFlush(pImage->File);
    321 #else
    322     rc = pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser,
    323                                                      pImage->pStorage);
    324 #endif
    325 
    326     return rc;
    327 }
    328 
    329 static int vhdFileGetSize(PVHDIMAGE pImage, uint64_t *pcbSize)
    330 {
    331     int rc = VINF_SUCCESS;
    332 
    333 #ifndef VBOX_WITH_NEW_IO_CODE
    334     rc = RTFileGetSize(pImage->File, pcbSize);
    335 #else
    336     rc = pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser,
    337                                                    pImage->pStorage,
    338                                                    pcbSize);
    339 #endif
    340 
    341     return rc;
    342 
    343 }
    344 
    345 static int vhdFileSetSize(PVHDIMAGE pImage, uint64_t cbSize)
    346 {
    347     int rc = VINF_SUCCESS;
    348 
    349 #ifndef VBOX_WITH_NEW_IO_CODE
    350     rc = RTFileSetSize(pImage->File, cbSize);
    351 #else
    352     rc = pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser,
    353                                                    pImage->pStorage,
    354                                                    cbSize);
    355 #endif
    356 
    357     return rc;
    358 }
    359 
    360 
    361 static int vhdFileWriteSync(PVHDIMAGE pImage, uint64_t off, const void *pcvBuf, size_t cbWrite, size_t *pcbWritten)
    362 {
    363     int rc = VINF_SUCCESS;
    364 
    365 #ifndef VBOX_WITH_NEW_IO_CODE
    366     rc = RTFileWriteAt(pImage->File, off, pcvBuf, cbWrite, pcbWritten);
    367 #else
    368     rc = pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser,
    369                                                      pImage->pStorage,
    370                                                      off, cbWrite, pcvBuf,
    371                                                      pcbWritten);
    372 #endif
    373 
    374     return rc;
    375 }
    376 
    377 static int vhdFileReadSync(PVHDIMAGE pImage, uint64_t off, void *pvBuf, size_t cbRead, size_t *pcbRead)
    378 {
    379     int rc = VINF_SUCCESS;
    380 
    381 #ifndef VBOX_WITH_NEW_IO_CODE
    382     rc = RTFileReadAt(pImage->File, off, pvBuf, cbRead, pcbRead);
    383 #else
    384     rc = pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser,
    385                                                     pImage->pStorage,
    386                                                     off, cbRead, pvBuf,
    387                                                     pcbRead);
    388 #endif
    389 
    390     return rc;
    391 }
    392 
    393 static bool vhdFileOpened(PVHDIMAGE pImage)
    394 {
    395 #ifndef VBOX_WITH_NEW_IO_CODE
    396     return pImage->File != NIL_RTFILE;
    397 #else
    398     return pImage->pStorage != NULL;
    399 #endif
    400 }
    401 
    402 /* 946684800 is a number of seconds between 1/1/1970 and 1/1/2000 */
    403 #define VHD_TO_UNIX_EPOCH_SECONDS UINT64_C(946684800)
    404 
    405 static uint32_t vhdRtTime2VhdTime(PCRTTIMESPEC pRtTimeStamp)
    406 {
    407     uint64_t u64Seconds = RTTimeSpecGetSeconds(pRtTimeStamp);
    408     return (uint32_t)(u64Seconds - VHD_TO_UNIX_EPOCH_SECONDS);
    409 }
    410 
    411 static void vhdTime2RtTime(PRTTIMESPEC pRtTimeStamp, uint32_t u32VhdTimeStamp)
    412 {
    413     RTTimeSpecSetSeconds(pRtTimeStamp, VHD_TO_UNIX_EPOCH_SECONDS + u32VhdTimeStamp);
    414 }
    415 
    416 /**
    417  * Internal: Allocates the block bitmap rounding up to the next 32bit or 64bit boundary.
    418  *           Can be freed with RTMemFree. The memory is zeroed.
    419  */
    420 DECLINLINE(uint8_t *)vhdBlockBitmapAllocate(PVHDIMAGE pImage)
    421 {
    422 #ifdef RT_ARCH_AMD64
    423     return (uint8_t *)RTMemAllocZ(pImage->cbDataBlockBitmap + 8);
    424 #else
    425     return (uint8_t *)RTMemAllocZ(pImage->cbDataBlockBitmap + 4);
    426 #endif
    427 }
     274    va_list va;
     275    va_start(va, pszFormat);
     276    if (pImage->pInterfaceError && pImage->pInterfaceErrorCallbacks)
     277        rc = pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser,
     278                                                          pszFormat, va);
     279    va_end(va);
     280    return rc;
     281}
     282
     283
     284DECLINLINE(int) vhdFileOpen(PVHDIMAGE pImage, const char *pszFilename,
     285                            uint32_t fOpen)
     286{
     287    return pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser,
     288                                                  pszFilename, fOpen,
     289                                                  &pImage->pStorage);
     290}
     291
     292DECLINLINE(int) vhdFileClose(PVHDIMAGE pImage)
     293{
     294    return pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser,
     295                                                   pImage->pStorage);
     296}
     297
     298DECLINLINE(int) vhdFileDelete(PVHDIMAGE pImage, const char *pszFilename)
     299{
     300    return pImage->pInterfaceIOCallbacks->pfnDelete(pImage->pInterfaceIO->pvUser,
     301                                                    pszFilename);
     302}
     303
     304DECLINLINE(int) vhdFileMove(PVHDIMAGE pImage, const char *pszSrc,
     305                            const char *pszDst, unsigned fMove)
     306{
     307    return pImage->pInterfaceIOCallbacks->pfnMove(pImage->pInterfaceIO->pvUser,
     308                                                  pszSrc, pszDst, fMove);
     309}
     310
     311DECLINLINE(int) vhdFileGetFreeSpace(PVHDIMAGE pImage, const char *pszFilename,
     312                                    int64_t *pcbFree)
     313{
     314    return pImage->pInterfaceIOCallbacks->pfnGetFreeSpace(pImage->pInterfaceIO->pvUser,
     315                                                          pszFilename, pcbFree);
     316}
     317
     318DECLINLINE(int) vhdFileGetModificationTime(PVHDIMAGE pImage,
     319                                           const char *pszFilename,
     320                                           PRTTIMESPEC pModificationTime)
     321{
     322    return pImage->pInterfaceIOCallbacks->pfnGetModificationTime(pImage->pInterfaceIO->pvUser,
     323                                                                 pszFilename,
     324                                                                 pModificationTime);
     325}
     326
     327DECLINLINE(int) vhdFileGetSize(PVHDIMAGE pImage, uint64_t *pcbSize)
     328{
     329    return pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser,
     330                                                     pImage->pStorage, pcbSize);
     331}
     332
     333DECLINLINE(int) vhdFileSetSize(PVHDIMAGE pImage, uint64_t cbSize)
     334{
     335    return pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser,
     336                                                     pImage->pStorage, cbSize);
     337}
     338
     339DECLINLINE(int) vhdFileWriteSync(PVHDIMAGE pImage, uint64_t uOffset,
     340                                 const void *pvBuffer, size_t cbBuffer,
     341                                 size_t *pcbWritten)
     342{
     343    return pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser,
     344                                                       pImage->pStorage, uOffset,
     345                                                       pvBuffer, cbBuffer, pcbWritten);
     346}
     347
     348DECLINLINE(int) vhdFileReadSync(PVHDIMAGE pImage, uint64_t uOffset,
     349                                void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
     350{
     351    return pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser,
     352                                                      pImage->pStorage, uOffset,
     353                                                      pvBuffer, cbBuffer, pcbRead);
     354}
     355
     356DECLINLINE(int) vhdFileFlushSync(PVHDIMAGE pImage)
     357{
     358    return pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser,
     359                                                       pImage->pStorage);
     360}
     361
     362DECLINLINE(int) vhdFileReadUserAsync(PVHDIMAGE pImage, uint64_t uOffset,
     363                                     PVDIOCTX pIoCtx, size_t cbRead)
     364{
     365    return pImage->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser,
     366                                                           pImage->pStorage,
     367                                                           uOffset, pIoCtx,
     368                                                           cbRead);
     369}
     370
     371DECLINLINE(int) vhdFileWriteUserAsync(PVHDIMAGE pImage, uint64_t uOffset,
     372                                      PVDIOCTX pIoCtx, size_t cbWrite,
     373                                      PFNVDXFERCOMPLETED pfnComplete,
     374                                      void *pvCompleteUser)
     375{
     376    return pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser,
     377                                                            pImage->pStorage,
     378                                                            uOffset, pIoCtx,
     379                                                            cbWrite,
     380                                                            pfnComplete,
     381                                                            pvCompleteUser);
     382}
     383
     384DECLINLINE(int) vhdFileReadMetaAsync(PVHDIMAGE pImage, uint64_t uOffset,
     385                                     void *pvBuffer, size_t cbBuffer,
     386                                     PVDIOCTX pIoCtx, PPVDMETAXFER ppMetaXfer,
     387                                     PFNVDXFERCOMPLETED pfnComplete,
     388                                     void *pvCompleteUser)
     389{
     390    return pImage->pInterfaceIOCallbacks->pfnReadMetaAsync(pImage->pInterfaceIO->pvUser,
     391                                                           pImage->pStorage,
     392                                                           uOffset, pvBuffer,
     393                                                           cbBuffer, pIoCtx,
     394                                                           ppMetaXfer,
     395                                                           pfnComplete,
     396                                                           pvCompleteUser);
     397}
     398
     399DECLINLINE(int) vhdFileWriteMetaAsync(PVHDIMAGE pImage, uint64_t uOffset,
     400                                      void *pvBuffer, size_t cbBuffer,
     401                                      PVDIOCTX pIoCtx,
     402                                      PFNVDXFERCOMPLETED pfnComplete,
     403                                      void *pvCompleteUser)
     404{
     405    return pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pImage->pInterfaceIO->pvUser,
     406                                                            pImage->pStorage,
     407                                                            uOffset, pvBuffer,
     408                                                            cbBuffer, pIoCtx,
     409                                                            pfnComplete,
     410                                                            pvCompleteUser);
     411}
     412
     413DECLINLINE(int) vhdFileFlushAsync(PVHDIMAGE pImage, PVDIOCTX pIoCtx,
     414                                  PFNVDXFERCOMPLETED pfnComplete,
     415                                  void *pvCompleteUser)
     416{
     417    return pImage->pInterfaceIOCallbacks->pfnFlushAsync(pImage->pInterfaceIO->pvUser,
     418                                                        pImage->pStorage,
     419                                                        pIoCtx, pfnComplete,
     420                                                        pvCompleteUser);
     421}
     422
     423DECLINLINE(void) vhdFileMetaXferRelease(PVHDIMAGE pImage, PVDMETAXFER pMetaXfer)
     424{
     425    pImage->pInterfaceIOCallbacks->pfnMetaXferRelease(pImage->pInterfaceIO->pvUser,
     426                                                      pMetaXfer);
     427}
     428
    428429
    429430/**
     
    438439}
    439440
    440 static int vhdFilenameToUtf16(const char *pszFilename, uint16_t *pu16Buf, uint32_t cbBufSize, uint32_t *pcbActualSize, bool fBigEndian)
     441/**
     442 * Internal: Convert filename to UTF16 with appropriate endianness.
     443 */
     444static int vhdFilenameToUtf16(const char *pszFilename, uint16_t *pu16Buf,
     445                              uint32_t cbBufSize, uint32_t *pcbActualSize,
     446                              bool fBigEndian)
    441447{
    442448    int      rc;
     
    535541            goto out;
    536542    }
    537     rc = vhdFileWriteSync(pImage, RT_BE2H_U64(pLocator->u64DataOffset), pvBuf,
    538                           RT_BE2H_U32(pLocator->u32DataSpace) * VHD_SECTOR_SIZE, NULL);
     543    rc = vhdFileWriteSync(pImage, RT_BE2H_U64(pLocator->u64DataOffset),
     544                          pvBuf, RT_BE2H_U32(pLocator->u32DataSpace) * VHD_SECTOR_SIZE,
     545                          NULL);
    539546
    540547out:
    541548    if (pvBuf)
    542549        RTMemTmpFree(pvBuf);
    543     return rc;
    544 }
    545 
    546 /**
    547  * Internal: Update the VHD footer.
    548  */
    549 static int vhdUpdateFooter(PVHDIMAGE pImage)
    550 {
    551     int rc = VINF_SUCCESS;
    552 
    553     /* Update fields which can change. */
    554     pImage->vhdFooterCopy.CurSize              = RT_H2BE_U64(pImage->cbSize);
    555     pImage->vhdFooterCopy.DiskGeometryCylinder = RT_H2BE_U16(pImage->PCHSGeometry.cCylinders);
    556     pImage->vhdFooterCopy.DiskGeometryHeads    = pImage->PCHSGeometry.cHeads;
    557     pImage->vhdFooterCopy.DiskGeometrySectors  = pImage->PCHSGeometry.cSectors;
    558 
    559     pImage->vhdFooterCopy.Checksum = 0;
    560     pImage->vhdFooterCopy.Checksum = RT_H2BE_U32(vhdChecksum(&pImage->vhdFooterCopy, sizeof(VHDFooter)));
    561 
    562     if (pImage->pBlockAllocationTable)
    563         rc = vhdFileWriteSync(pImage, 0, &pImage->vhdFooterCopy, sizeof(VHDFooter), NULL);
    564 
    565     if (RT_SUCCESS(rc))
    566         rc = vhdFileWriteSync(pImage, pImage->uCurrentEndOfFile, &pImage->vhdFooterCopy, sizeof(VHDFooter), NULL);
    567 
    568550    return rc;
    569551}
     
    612594                rc = vhdLocatorUpdate(pImage, &ddh.ParentLocatorEntry[i], pImage->pszParentFilename);
    613595                if (RT_FAILURE(rc))
    614                     goto out;
     596                    return rc;
    615597            }
    616598            else
     
    630612    ddh.Checksum = RT_H2BE_U32(vhdChecksum(&ddh, sizeof(ddh)));
    631613    rc = vhdFileWriteSync(pImage, pImage->u64DataOffset, &ddh, sizeof(ddh), NULL);
    632     if (RT_FAILURE(rc))
    633         return rc;
    634 
    635     /* Update the VHD footer. */
    636     rc = vhdUpdateFooter(pImage);
    637 
    638 out:
    639     return rc;
     614    return rc;
     615}
     616
     617/**
     618 * Internal: Update the VHD footer.
     619 */
     620static int vhdUpdateFooter(PVHDIMAGE pImage)
     621{
     622    int rc = VINF_SUCCESS;
     623
     624    /* Update fields which can change. */
     625    pImage->vhdFooterCopy.CurSize              = RT_H2BE_U64(pImage->cbSize);
     626    pImage->vhdFooterCopy.DiskGeometryCylinder = RT_H2BE_U16(pImage->PCHSGeometry.cCylinders);
     627    pImage->vhdFooterCopy.DiskGeometryHeads    = pImage->PCHSGeometry.cHeads;
     628    pImage->vhdFooterCopy.DiskGeometrySectors  = pImage->PCHSGeometry.cSectors;
     629
     630    pImage->vhdFooterCopy.Checksum = 0;
     631    pImage->vhdFooterCopy.Checksum = RT_H2BE_U32(vhdChecksum(&pImage->vhdFooterCopy, sizeof(VHDFooter)));
     632
     633    if (pImage->pBlockAllocationTable)
     634        rc = vhdFileWriteSync(pImage, 0, &pImage->vhdFooterCopy,
     635                              sizeof(VHDFooter), NULL);
     636
     637    if (RT_SUCCESS(rc))
     638        rc = vhdFileWriteSync(pImage, pImage->uCurrentEndOfFile,
     639                              &pImage->vhdFooterCopy, sizeof(VHDFooter), NULL);
     640
     641    return rc;
     642}
     643
     644/**
     645 * Internal. Flush image data to disk.
     646 */
     647static int vhdFlushImage(PVHDIMAGE pImage)
     648{
     649    int rc = VINF_SUCCESS;
     650
     651    if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     652        return VINF_SUCCESS;
     653
     654    if (pImage->pBlockAllocationTable)
     655    {
     656        /*
     657         * This is an expanding image. Write the BAT and copy of the disk footer.
     658         */
     659        size_t   cbBlockAllocationTableToWrite = pImage->cBlockAllocationTableEntries * sizeof(uint32_t);
     660        uint32_t *pBlockAllocationTableToWrite = (uint32_t *)RTMemAllocZ(cbBlockAllocationTableToWrite);
     661
     662        if (!pBlockAllocationTableToWrite)
     663            return VERR_NO_MEMORY;
     664
     665        /*
     666         * The BAT entries have to be stored in big endian format.
     667         */
     668        for (unsigned i = 0; i < pImage->cBlockAllocationTableEntries; i++)
     669            pBlockAllocationTableToWrite[i] = RT_H2BE_U32(pImage->pBlockAllocationTable[i]);
     670
     671        /*
     672         * Write the block allocation table after the copy of the disk footer and the dynamic disk header.
     673         */
     674        vhdFileWriteSync(pImage, pImage->uBlockAllocationTableOffset,
     675                         pBlockAllocationTableToWrite,
     676                         cbBlockAllocationTableToWrite, NULL);
     677        if (pImage->fDynHdrNeedsUpdate)
     678            rc = vhdDynamicHeaderUpdate(pImage);
     679        RTMemFree(pBlockAllocationTableToWrite);
     680    }
     681
     682    if (RT_SUCCESS(rc))
     683        rc = vhdUpdateFooter(pImage);
     684
     685    if (RT_SUCCESS(rc))
     686        rc = vhdFileFlushSync(pImage);
     687
     688    return rc;
     689}
     690
     691/**
     692 * Internal. Free all allocated space for representing an image except pImage,
     693 * and optionally delete the image from disk.
     694 */
     695static int vhdFreeImage(PVHDIMAGE pImage, bool fDelete)
     696{
     697    int rc = VINF_SUCCESS;
     698
     699    /* Freeing a never allocated image (e.g. because the open failed) is
     700     * not signalled as an error. After all nothing bad happens. */
     701    if (pImage)
     702    {
     703        if (pImage->pStorage)
     704        {
     705            /* No point updating the file that is deleted anyway. */
     706            if (!fDelete)
     707                vhdFlushImage(pImage);
     708
     709            vhdFileClose(pImage);
     710            pImage->pStorage = NULL;
     711        }
     712
     713        if (pImage->pszParentFilename)
     714        {
     715            RTStrFree(pImage->pszParentFilename);
     716            pImage->pszParentFilename = NULL;
     717        }
     718        if (pImage->pBlockAllocationTable)
     719        {
     720            RTMemFree(pImage->pBlockAllocationTable);
     721            pImage->pBlockAllocationTable = NULL;
     722        }
     723        if (pImage->pu8Bitmap)
     724        {
     725            RTMemFree(pImage->pu8Bitmap);
     726            pImage->pu8Bitmap = NULL;
     727        }
     728
     729        if (fDelete && pImage->pszFilename)
     730            rc = vhdFileDelete(pImage, pImage->pszFilename);
     731    }
     732
     733    LogFlowFunc(("returns %Rrc\n", rc));
     734    return rc;
     735}
     736
     737/* 946684800 is the number of seconds between 1/1/1970 and 1/1/2000 */
     738#define VHD_TO_UNIX_EPOCH_SECONDS UINT64_C(946684800)
     739
     740static uint32_t vhdRtTime2VhdTime(PCRTTIMESPEC pRtTimeStamp)
     741{
     742    uint64_t u64Seconds = RTTimeSpecGetSeconds(pRtTimeStamp);
     743    return (uint32_t)(u64Seconds - VHD_TO_UNIX_EPOCH_SECONDS);
     744}
     745
     746static void vhdTime2RtTime(PRTTIMESPEC pRtTimeStamp, uint32_t u32VhdTimeStamp)
     747{
     748    RTTimeSpecSetSeconds(pRtTimeStamp, VHD_TO_UNIX_EPOCH_SECONDS + u32VhdTimeStamp);
     749}
     750
     751/**
     752 * Internal: Allocates the block bitmap rounding up to the next 32bit or 64bit boundary.
     753 *           Can be freed with RTMemFree. The memory is zeroed.
     754 */
     755DECLINLINE(uint8_t *)vhdBlockBitmapAllocate(PVHDIMAGE pImage)
     756{
     757#ifdef RT_ARCH_AMD64
     758    return (uint8_t *)RTMemAllocZ(pImage->cbDataBlockBitmap + 8);
     759#else
     760    return (uint8_t *)RTMemAllocZ(pImage->cbDataBlockBitmap + 4);
     761#endif
    640762}
    641763
     
    671793            if (uStatus == VHDIMAGEEXPAND_STEP_SUCCESS)
    672794            {
    673                 rc = pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pImage->pInterfaceIO->pvUser,
    674                                                                       pImage->pStorage,
    675                                                                       pImage->uBlockAllocationTableOffset + pExpand->idxBatAllocated * sizeof(uint32_t),
    676                                                                       &pImage->pBlockAllocationTable[pExpand->idxBatAllocated], sizeof(uint32_t), pIoCtx,
    677                                                                      NULL, NULL);
     795                rc = vhdFileWriteMetaAsync(pImage,
     796                                             pImage->uBlockAllocationTableOffset
     797                                           + pExpand->idxBatAllocated * sizeof(uint32_t),
     798                                           &pImage->pBlockAllocationTable[pExpand->idxBatAllocated],
     799                                           sizeof(uint32_t), pIoCtx, NULL, NULL);
    678800                fIoInProgress |= rc == VERR_VD_ASYNC_IO_IN_PROGRESS;
    679801            }
     
    683805         * fill up the free space making it impossible to add the footer)
    684806         * and add the footer at the right place again. */
    685         rc = pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser,
    686                                                        pImage->pStorage,
    687                                                        pExpand->cbEofOld + sizeof(VHDFooter));
     807        rc = vhdFileSetSize(pImage, pExpand->cbEofOld + sizeof(VHDFooter));
    688808        AssertRC(rc);
    689809
    690810        pImage->uCurrentEndOfFile = pExpand->cbEofOld;
    691         rc = pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pImage->pInterfaceIO->pvUser,
    692                                                               pImage->pStorage,
    693                                                               pImage->uCurrentEndOfFile,
    694                                                               &pImage->vhdFooterCopy, sizeof(VHDFooter), pIoCtx,
    695                                                               NULL, NULL);
     811        rc = vhdFileWriteMetaAsync(pImage, pImage->uCurrentEndOfFile,
     812                                   &pImage->vhdFooterCopy, sizeof(VHDFooter),
     813                                   pIoCtx, NULL, NULL);
    696814        fIoInProgress |= rc == VERR_VD_ASYNC_IO_IN_PROGRESS;
    697815    }
     
    700818}
    701819
    702 static int vhdAsyncExpansionStepCompleted(void *pvBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq, unsigned iStep)
    703 {
    704    PVHDIMAGE pImage = (PVHDIMAGE)pvBackendData;
     820static int vhdAsyncExpansionStepCompleted(void *pBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq, unsigned iStep)
     821{
     822   PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    705823   PVHDIMAGEEXPAND pExpand = (PVHDIMAGEEXPAND)pvUser;
    706824
    707    LogFlowFunc(("pvBackendData=%#p pIoCtx=%#p pvUser=%#p rcReq=%Rrc iStep=%u\n",
    708                 pvBackendData, pIoCtx, pvUser, rcReq, iStep));
     825   LogFlowFunc(("pBackendData=%#p pIoCtx=%#p pvUser=%#p rcReq=%Rrc iStep=%u\n",
     826                pBackendData, pIoCtx, pvUser, rcReq, iStep));
    709827
    710828   if (RT_SUCCESS(rcReq))
     
    719837}
    720838
    721 static int vhdAsyncExpansionDataBlockBitmapComplete(void *pvBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq)
    722 {
    723     return vhdAsyncExpansionStepCompleted(pvBackendData, pIoCtx, pvUser, rcReq, VHDIMAGEEXPAND_BLOCKBITMAP_STATUS_SHIFT);
    724 }
    725 
    726 static int vhdAsyncExpansionDataComplete(void *pvBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq)
    727 {
    728     return vhdAsyncExpansionStepCompleted(pvBackendData, pIoCtx, pvUser, rcReq, VHDIMAGEEXPAND_USERBLOCK_STATUS_SHIFT);
    729 }
    730 
    731 static int vhdAsyncExpansionBatUpdateComplete(void *pvBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq)
    732 {
    733     return vhdAsyncExpansionStepCompleted(pvBackendData, pIoCtx, pvUser, rcReq, VHDIMAGEEXPAND_BAT_STATUS_SHIFT);
    734 }
    735 
    736 static int vhdAsyncExpansionFooterUpdateComplete(void *pvBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq)
    737 {
    738     return vhdAsyncExpansionStepCompleted(pvBackendData, pIoCtx, pvUser, rcReq, VHDIMAGEEXPAND_FOOTER_STATUS_SHIFT);
     839static int vhdAsyncExpansionDataBlockBitmapComplete(void *pBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq)
     840{
     841    return vhdAsyncExpansionStepCompleted(pBackendData, pIoCtx, pvUser, rcReq, VHDIMAGEEXPAND_BLOCKBITMAP_STATUS_SHIFT);
     842}
     843
     844static int vhdAsyncExpansionDataComplete(void *pBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq)
     845{
     846    return vhdAsyncExpansionStepCompleted(pBackendData, pIoCtx, pvUser, rcReq, VHDIMAGEEXPAND_USERBLOCK_STATUS_SHIFT);
     847}
     848
     849static int vhdAsyncExpansionBatUpdateComplete(void *pBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq)
     850{
     851    return vhdAsyncExpansionStepCompleted(pBackendData, pIoCtx, pvUser, rcReq, VHDIMAGEEXPAND_BAT_STATUS_SHIFT);
     852}
     853
     854static int vhdAsyncExpansionFooterUpdateComplete(void *pBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq)
     855{
     856    return vhdAsyncExpansionStepCompleted(pBackendData, pIoCtx, pvUser, rcReq, VHDIMAGEEXPAND_FOOTER_STATUS_SHIFT);
     857}
     858
     859static int vhdLoadDynamicDisk(PVHDIMAGE pImage, uint64_t uDynamicDiskHeaderOffset)
     860{
     861    VHDDynamicDiskHeader vhdDynamicDiskHeader;
     862    int rc = VINF_SUCCESS;
     863    uint32_t *pBlockAllocationTable;
     864    uint64_t uBlockAllocationTableOffset;
     865    unsigned i = 0;
     866
     867    Log(("Open a dynamic disk.\n"));
     868
     869    /*
     870     * Read the dynamic disk header.
     871     */
     872    rc = vhdFileReadSync(pImage, uDynamicDiskHeaderOffset,
     873                         &vhdDynamicDiskHeader, sizeof(VHDDynamicDiskHeader),
     874                         NULL);
     875    if (!memcmp(vhdDynamicDiskHeader.Cookie, VHD_DYNAMIC_DISK_HEADER_COOKIE, VHD_DYNAMIC_DISK_HEADER_COOKIE_SIZE))
     876        return VERR_INVALID_PARAMETER;
     877
     878    pImage->cbDataBlock = RT_BE2H_U32(vhdDynamicDiskHeader.BlockSize);
     879    LogFlowFunc(("BlockSize=%u\n", pImage->cbDataBlock));
     880    pImage->cBlockAllocationTableEntries = RT_BE2H_U32(vhdDynamicDiskHeader.MaxTableEntries);
     881    LogFlowFunc(("MaxTableEntries=%lu\n", pImage->cBlockAllocationTableEntries));
     882    AssertMsg(!(pImage->cbDataBlock % VHD_SECTOR_SIZE), ("%s: Data block size is not a multiple of %!\n", __FUNCTION__, VHD_SECTOR_SIZE));
     883
     884    pImage->cSectorsPerDataBlock = pImage->cbDataBlock / VHD_SECTOR_SIZE;
     885    LogFlowFunc(("SectorsPerDataBlock=%u\n", pImage->cSectorsPerDataBlock));
     886
     887    /*
     888     * Every block starts with a bitmap indicating which sectors are valid and which are not.
     889     * We store the size of it to be able to calculate the real offset.
     890     */
     891    pImage->cbDataBlockBitmap = pImage->cSectorsPerDataBlock / 8;
     892    pImage->cDataBlockBitmapSectors = pImage->cbDataBlockBitmap / VHD_SECTOR_SIZE;
     893    /* Round up to full sector size */
     894    if (pImage->cbDataBlockBitmap % VHD_SECTOR_SIZE > 0)
     895        pImage->cDataBlockBitmapSectors++;
     896    LogFlowFunc(("cbDataBlockBitmap=%u\n", pImage->cbDataBlockBitmap));
     897    LogFlowFunc(("cDataBlockBitmapSectors=%u\n", pImage->cDataBlockBitmapSectors));
     898
     899    pImage->pu8Bitmap = vhdBlockBitmapAllocate(pImage);
     900    if (!pImage->pu8Bitmap)
     901        return VERR_NO_MEMORY;
     902
     903    pBlockAllocationTable = (uint32_t *)RTMemAllocZ(pImage->cBlockAllocationTableEntries * sizeof(uint32_t));
     904    if (!pBlockAllocationTable)
     905        return VERR_NO_MEMORY;
     906
     907    /*
     908     * Read the table.
     909     */
     910    uBlockAllocationTableOffset = RT_BE2H_U64(vhdDynamicDiskHeader.TableOffset);
     911    LogFlowFunc(("uBlockAllocationTableOffset=%llu\n", uBlockAllocationTableOffset));
     912    pImage->uBlockAllocationTableOffset = uBlockAllocationTableOffset;
     913    rc = vhdFileReadSync(pImage, uBlockAllocationTableOffset,
     914                         pBlockAllocationTable,
     915                         pImage->cBlockAllocationTableEntries * sizeof(uint32_t),
     916                         NULL);
     917
     918    /*
     919     * Because the offset entries inside the allocation table are stored big endian
     920     * we need to convert them into host endian.
     921     */
     922    pImage->pBlockAllocationTable = (uint32_t *)RTMemAllocZ(pImage->cBlockAllocationTableEntries * sizeof(uint32_t));
     923    if (!pImage->pBlockAllocationTable)
     924        return VERR_NO_MEMORY;
     925
     926    for (i = 0; i < pImage->cBlockAllocationTableEntries; i++)
     927        pImage->pBlockAllocationTable[i] = RT_BE2H_U32(pBlockAllocationTable[i]);
     928
     929    RTMemFree(pBlockAllocationTable);
     930
     931    if (pImage->uImageFlags & VD_IMAGE_FLAGS_DIFF)
     932        memcpy(pImage->ParentUuid.au8, vhdDynamicDiskHeader.ParentUuid, sizeof(pImage->ParentUuid));
     933
     934    return rc;
    739935}
    740936
     
    750946        pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError);
    751947
    752 #ifdef VBOX_WITH_NEW_IO_CODE
    753     /* Try to get async I/O interface. */
     948    /* Get I/O interface. */
    754949    pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsImage, VDINTERFACETYPE_IO);
    755     AssertPtr(pImage->pInterfaceIO);
     950    AssertPtrReturn(pImage->pInterfaceIO, VERR_INVALID_PARAMETER);
    756951    pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO);
    757     AssertPtr(pImage->pInterfaceIOCallbacks);
    758 #endif
     952    AssertPtrReturn(pImage->pInterfaceIOCallbacks, VERR_INVALID_PARAMETER);
    759953
    760954    /*
    761955     * Open the image.
    762956     */
    763     int rc = vhdFileOpen(pImage, !!(uOpenFlags & VD_OPEN_FLAGS_READONLY),
    764                          !!(uOpenFlags & VD_OPEN_FLAGS_SHAREABLE), false);
     957    int rc = vhdFileOpen(pImage, pImage->pszFilename,
     958                         VDOpenFlagsToFileOpenFlags(uOpenFlags,
     959                                                    false /* fCreate */));
    765960    if (RT_FAILURE(rc))
    766961    {
     
    771966
    772967    rc = vhdFileGetSize(pImage, &FileSize);
    773     pImage->FileSize = FileSize;
    774968    pImage->uCurrentEndOfFile = FileSize - sizeof(VHDFooter);
    775969
    776     rc = vhdFileReadSync(pImage, pImage->uCurrentEndOfFile, &vhdFooter, sizeof(VHDFooter), NULL);
     970    rc = vhdFileReadSync(pImage, pImage->uCurrentEndOfFile,
     971                         &vhdFooter, sizeof(VHDFooter), NULL);
    777972    if (memcmp(vhdFooter.Cookie, VHD_FOOTER_COOKIE, VHD_FOOTER_COOKIE_SIZE) != 0)
    778973        return VERR_VD_VHD_INVALID_HEADER;
     
    8261021        rc = vhdLoadDynamicDisk(pImage, pImage->u64DataOffset);
    8271022
    828     return rc;
    829 }
    830 
    831 static int vhdOpen(const char *pszFilename, unsigned uOpenFlags,
    832                    PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
    833                    void **ppvBackendData)
    834 {
    835     int rc = VINF_SUCCESS;
    836     PVHDIMAGE pImage;
    837 
    838     /* Check open flags. All valid flags are supported. */
    839     if (uOpenFlags & ~VD_OPEN_FLAGS_MASK)
    840     {
    841         rc = VERR_INVALID_PARAMETER;
    842         return rc;
    843     }
    844 
    845     pImage = (PVHDIMAGE)RTMemAllocZ(sizeof(VHDIMAGE));
    846     if (!pImage)
    847     {
    848         rc = VERR_NO_MEMORY;
    849         return rc;
    850     }
    851     pImage->pszFilename = pszFilename;
    852 #ifndef VBOX_WITH_NEW_IO_CODE
    853     pImage->File = NIL_RTFILE;
    854 #else
    855     pImage->pStorage = NULL;
    856 #endif
    857     pImage->pVDIfsDisk = pVDIfsDisk;
    858     pImage->pVDIfsImage = pVDIfsImage;
    859 
    860     rc = vhdOpenImage(pImage, uOpenFlags);
    861     if (RT_SUCCESS(rc))
    862         *ppvBackendData = pImage;
    863     return rc;
    864 }
    865 
    866 static int vhdLoadDynamicDisk(PVHDIMAGE pImage, uint64_t uDynamicDiskHeaderOffset)
    867 {
    868     VHDDynamicDiskHeader vhdDynamicDiskHeader;
    869     int rc = VINF_SUCCESS;
    870     uint32_t *pBlockAllocationTable;
    871     uint64_t uBlockAllocationTableOffset;
    872     unsigned i = 0;
    873 
    874     Log(("Open a dynamic disk.\n"));
    875 
    876     /*
    877      * Read the dynamic disk header.
    878      */
    879     rc = vhdFileReadSync(pImage, uDynamicDiskHeaderOffset, &vhdDynamicDiskHeader, sizeof(VHDDynamicDiskHeader), NULL);
    880     if (memcmp(vhdDynamicDiskHeader.Cookie, VHD_DYNAMIC_DISK_HEADER_COOKIE, VHD_DYNAMIC_DISK_HEADER_COOKIE_SIZE) != 0)
    881         return VERR_INVALID_PARAMETER;
    882 
    883     pImage->cbDataBlock = RT_BE2H_U32(vhdDynamicDiskHeader.BlockSize);
    884     LogFlowFunc(("BlockSize=%u\n", pImage->cbDataBlock));
    885     pImage->cBlockAllocationTableEntries = RT_BE2H_U32(vhdDynamicDiskHeader.MaxTableEntries);
    886     LogFlowFunc(("MaxTableEntries=%lu\n", pImage->cBlockAllocationTableEntries));
    887     AssertMsg(!(pImage->cbDataBlock % VHD_SECTOR_SIZE), ("%s: Data block size is not a multiple of %!\n", __FUNCTION__, VHD_SECTOR_SIZE));
    888 
    889     pImage->cSectorsPerDataBlock = pImage->cbDataBlock / VHD_SECTOR_SIZE;
    890     LogFlowFunc(("SectorsPerDataBlock=%u\n", pImage->cSectorsPerDataBlock));
    891 
    892     /*
    893      * Every block starts with a bitmap indicating which sectors are valid and which are not.
    894      * We store the size of it to be able to calculate the real offset.
    895      */
    896     pImage->cbDataBlockBitmap = pImage->cSectorsPerDataBlock / 8;
    897     pImage->cDataBlockBitmapSectors = pImage->cbDataBlockBitmap / VHD_SECTOR_SIZE;
    898     /* Round up to full sector size */
    899     if (pImage->cbDataBlockBitmap % VHD_SECTOR_SIZE > 0)
    900         pImage->cDataBlockBitmapSectors++;
    901     LogFlowFunc(("cbDataBlockBitmap=%u\n", pImage->cbDataBlockBitmap));
    902     LogFlowFunc(("cDataBlockBitmapSectors=%u\n", pImage->cDataBlockBitmapSectors));
    903 
    904     pImage->pu8Bitmap = vhdBlockBitmapAllocate(pImage);
    905     if (!pImage->pu8Bitmap)
    906         return VERR_NO_MEMORY;
    907 
    908     pBlockAllocationTable = (uint32_t *)RTMemAllocZ(pImage->cBlockAllocationTableEntries * sizeof(uint32_t));
    909     if (!pBlockAllocationTable)
    910         return VERR_NO_MEMORY;
    911 
    912     /*
    913      * Read the table.
    914      */
    915     uBlockAllocationTableOffset = RT_BE2H_U64(vhdDynamicDiskHeader.TableOffset);
    916     LogFlowFunc(("uBlockAllocationTableOffset=%llu\n", uBlockAllocationTableOffset));
    917     pImage->uBlockAllocationTableOffset = uBlockAllocationTableOffset;
    918     rc = vhdFileReadSync(pImage, uBlockAllocationTableOffset, pBlockAllocationTable, pImage->cBlockAllocationTableEntries * sizeof(uint32_t), NULL);
    919 
    920     /*
    921      * Because the offset entries inside the allocation table are stored big endian
    922      * we need to convert them into host endian.
    923      */
    924     pImage->pBlockAllocationTable = (uint32_t *)RTMemAllocZ(pImage->cBlockAllocationTableEntries * sizeof(uint32_t));
    925     if (!pImage->pBlockAllocationTable)
    926         return VERR_NO_MEMORY;
    927 
    928     for (i = 0; i < pImage->cBlockAllocationTableEntries; i++)
    929         pImage->pBlockAllocationTable[i] = RT_BE2H_U32(pBlockAllocationTable[i]);
    930 
    931     RTMemFree(pBlockAllocationTable);
    932 
    933     if (pImage->uImageFlags & VD_IMAGE_FLAGS_DIFF)
    934         memcpy(pImage->ParentUuid.au8, vhdDynamicDiskHeader.ParentUuid, sizeof(pImage->ParentUuid));
    935 
    936     return rc;
    937 }
    938 
    939 static int vhdCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk)
    940 {
    941     int rc = VINF_SUCCESS;
    942     RTFILE File;
    943     uint64_t cbFile;
    944     VHDFooter vhdFooter;
    945 
    946     rc = RTFileOpen(&File, pszFilename, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
    9471023    if (RT_FAILURE(rc))
    948         return VERR_VD_VHD_INVALID_HEADER;
    949 
    950     rc = RTFileGetSize(File, &cbFile);
    951     if (RT_FAILURE(rc))
    952     {
    953         RTFileClose(File);
    954         return VERR_VD_VHD_INVALID_HEADER;
    955     }
    956 
    957     rc = RTFileReadAt(File, cbFile - sizeof(VHDFooter), &vhdFooter, sizeof(VHDFooter), NULL);
    958     if (RT_FAILURE(rc) || (memcmp(vhdFooter.Cookie, VHD_FOOTER_COOKIE, VHD_FOOTER_COOKIE_SIZE) != 0))
    959         rc = VERR_VD_VHD_INVALID_HEADER;
    960     else
    961         rc = VINF_SUCCESS;
    962 
    963     RTFileClose(File);
    964 
    965     return rc;
    966 }
    967 
    968 static unsigned vhdGetVersion(void *pBackendData)
    969 {
    970     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    971 
    972     AssertPtr(pImage);
    973 
    974     if (pImage)
    975         return 1; /**< @todo use correct version */
    976     else
    977         return 0;
    978 }
    979 
    980 static int vhdGetPCHSGeometry(void *pBackendData, PPDMMEDIAGEOMETRY pPCHSGeometry)
    981 {
    982     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    983     int rc;
    984 
    985     AssertPtr(pImage);
    986 
    987     if (pImage)
    988     {
    989         if (pImage->PCHSGeometry.cCylinders)
    990         {
    991             *pPCHSGeometry = pImage->PCHSGeometry;
    992             rc = VINF_SUCCESS;
    993         }
    994         else
    995             rc = VERR_VD_GEOMETRY_NOT_SET;
    996     }
    997     else
    998         rc = VERR_VD_NOT_OPENED;
    999 
    1000     LogFlowFunc(("returned %Rrc (CHS=%u/%u/%u)\n", rc, pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors));
    1001     return rc;
    1002 }
    1003 
    1004 static int vhdSetPCHSGeometry(void *pBackendData, PCPDMMEDIAGEOMETRY pPCHSGeometry)
    1005 {
    1006     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1007     int rc;
    1008 
    1009     AssertPtr(pImage);
    1010 
    1011     if (pImage)
    1012     {
    1013         if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    1014         {
    1015             rc = VERR_VD_IMAGE_READ_ONLY;
    1016             goto out;
    1017         }
    1018 
    1019         pImage->PCHSGeometry = *pPCHSGeometry;
    1020         rc = VINF_SUCCESS;
    1021     }
    1022     else
    1023         rc = VERR_VD_NOT_OPENED;
    1024 
    1025 out:
    1026     LogFlowFunc(("returned %Rrc\n", rc));
    1027     return rc;
    1028 }
    1029 
    1030 static int vhdGetLCHSGeometry(void *pBackendData, PPDMMEDIAGEOMETRY pLCHSGeometry)
    1031 {
    1032     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1033     int rc;
    1034 
    1035     AssertPtr(pImage);
    1036 
    1037     if (pImage)
    1038     {
    1039         if (pImage->LCHSGeometry.cCylinders)
    1040         {
    1041             *pLCHSGeometry = pImage->LCHSGeometry;
    1042             rc = VINF_SUCCESS;
    1043         }
    1044         else
    1045             rc = VERR_VD_GEOMETRY_NOT_SET;
    1046     }
    1047     else
    1048         rc = VERR_VD_NOT_OPENED;
    1049 
    1050     LogFlowFunc(("returned %Rrc (CHS=%u/%u/%u)\n", rc, pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors));
    1051     return rc;
    1052 }
    1053 
    1054 static int vhdSetLCHSGeometry(void *pBackendData, PCPDMMEDIAGEOMETRY pLCHSGeometry)
    1055 {
    1056     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1057     int rc;
    1058 
    1059     AssertPtr(pImage);
    1060 
    1061     if (pImage)
    1062     {
    1063         if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    1064         {
    1065             rc = VERR_VD_IMAGE_READ_ONLY;
    1066             goto out;
    1067         }
    1068 
    1069         pImage->LCHSGeometry = *pLCHSGeometry;
    1070         rc = VINF_SUCCESS;
    1071     }
    1072     else
    1073         rc = VERR_VD_NOT_OPENED;
    1074 
    1075 out:
    1076     LogFlowFunc(("returned %Rrc\n", rc));
    1077     return rc;
    1078 }
    1079 
    1080 static unsigned vhdGetImageFlags(void *pBackendData)
    1081 {
    1082     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1083     unsigned uImageFlags;
    1084 
    1085     AssertPtr(pImage);
    1086 
    1087     if (pImage)
    1088         uImageFlags = pImage->uImageFlags;
    1089     else
    1090         uImageFlags = 0;
    1091 
    1092     LogFlowFunc(("returned %#x\n", uImageFlags));
    1093     return uImageFlags;
    1094 }
    1095 
    1096 static unsigned vhdGetOpenFlags(void *pBackendData)
    1097 {
    1098     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1099     unsigned uOpenFlags;
    1100 
    1101     AssertPtr(pImage);
    1102 
    1103     if (pImage)
    1104         uOpenFlags = pImage->uOpenFlags;
    1105     else
    1106         uOpenFlags = 0;
    1107 
    1108     LogFlowFunc(("returned %#x\n", uOpenFlags));
    1109     return uOpenFlags;
    1110 }
    1111 
    1112 static int vhdSetOpenFlags(void *pBackendData, unsigned uOpenFlags)
    1113 {
    1114     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1115     int rc;
    1116 
    1117     /* Image must be opened and the new flags must be valid. Just readonly and
    1118      * info flags are supported. */
    1119     if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_SHAREABLE  | VD_OPEN_FLAGS_ASYNC_IO)))
    1120     {
    1121         rc = VERR_INVALID_PARAMETER;
    1122         goto out;
    1123     }
    1124 
    1125     rc = vhdFlush(pImage);
    1126     if (RT_FAILURE(rc))
    1127         goto out;
    1128     vhdFileClose(pImage);
    1129     pImage->uOpenFlags = uOpenFlags;
    1130     rc = vhdFileOpen(pImage, !!(uOpenFlags & VD_OPEN_FLAGS_READONLY),
    1131                      !!(uOpenFlags & VD_OPEN_FLAGS_SHAREABLE), false);
    1132 
    1133 out:
    1134     LogFlowFunc(("returned %Rrc\n", rc));
    1135     return rc;
    1136 }
    1137 
    1138 static int vhdRename(void *pBackendData, const char *pszFilename)
    1139 {
    1140     LogFlowFunc(("pBackendData=%#p pszFilename=%#p\n", pBackendData, pszFilename));
    1141 
    1142     int rc = VINF_SUCCESS;
    1143     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1144 
    1145     /* Check arguments. */
    1146     if (   !pImage
    1147         || !pszFilename
    1148         || !*pszFilename)
    1149     {
    1150         rc = VERR_INVALID_PARAMETER;
    1151         goto out;
    1152     }
    1153 
    1154     /* Close the file. vhdFreeImage would additionally free pImage. */
    1155     vhdFlush(pImage);
    1156     vhdFileClose(pImage);
    1157 
    1158     /* Rename the file. */
    1159     rc = RTFileMove(pImage->pszFilename, pszFilename, 0);
    1160     if (RT_FAILURE(rc))
    1161     {
    1162         /* The move failed, try to reopen the original image. */
    1163         int rc2 = vhdOpenImage(pImage, pImage->uOpenFlags);
    1164         if (RT_FAILURE(rc2))
    1165             rc = rc2;
    1166 
    1167         goto out;
    1168     }
    1169 
    1170     /* Update pImage with the new information. */
    1171     pImage->pszFilename = pszFilename;
    1172 
    1173     /* Open the new image. */
    1174     rc = vhdOpenImage(pImage, pImage->uOpenFlags);
    1175     if (RT_FAILURE(rc))
    1176         goto out;
    1177 
    1178 out:
    1179     LogFlowFunc(("returns %Rrc\n", rc));
    1180     return rc;
    1181 }
    1182 
    1183 static void vhdFreeImageMemory(PVHDIMAGE pImage)
    1184 {
    1185     if (pImage->pszParentFilename)
    1186     {
    1187         RTStrFree(pImage->pszParentFilename);
    1188         pImage->pszParentFilename = NULL;
    1189     }
    1190     if (pImage->pBlockAllocationTable)
    1191     {
    1192         RTMemFree(pImage->pBlockAllocationTable);
    1193         pImage->pBlockAllocationTable = NULL;
    1194     }
    1195     if (pImage->pu8Bitmap)
    1196     {
    1197         RTMemFree(pImage->pu8Bitmap);
    1198         pImage->pu8Bitmap = NULL;
    1199     }
    1200     RTMemFree(pImage);
    1201 }
    1202 
    1203 static int vhdFreeImage(PVHDIMAGE pImage)
    1204 {
    1205     int rc = VINF_SUCCESS;
    1206 
    1207     /* Freeing a never allocated image (e.g. because the open failed) is
    1208      * not signalled as an error. After all nothing bad happens. */
    1209     if (pImage)
    1210     {
    1211         vhdFlush(pImage);
    1212         vhdFileClose(pImage);
    1213         vhdFreeImageMemory(pImage);
    1214     }
    1215 
    1216     LogFlowFunc(("returned %Rrc\n", rc));
    1217     return rc;
    1218 }
    1219 
    1220 static int vhdClose(void *pBackendData, bool fDelete)
    1221 {
    1222     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1223     int rc = VINF_SUCCESS;
    1224 
    1225     /* Freeing a never allocated image (e.g. because the open failed) is
    1226      * not signalled as an error. After all nothing bad happens. */
    1227     if (pImage)
    1228     {
    1229         if (fDelete)
    1230         {
    1231             /* No point in updating the file that is deleted anyway. */
    1232             vhdFileClose(pImage);
    1233             RTFileDelete(pImage->pszFilename);
    1234             vhdFreeImageMemory(pImage);
    1235         }
    1236         else
    1237             rc = vhdFreeImage(pImage);
    1238     }
    1239 
    1240     LogFlowFunc(("returned %Rrc\n", rc));
     1024        vhdFreeImage(pImage, false);
    12411025    return rc;
    12421026}
     
    12801064
    12811065    return !ASMBitTestAndSet(puBitmap, iBitInByte);
    1282 }
    1283 
    1284 static int vhdRead(void *pBackendData, uint64_t uOffset, void *pvBuf, size_t cbRead, size_t *pcbActuallyRead)
    1285 {
    1286     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1287     int rc = VINF_SUCCESS;
    1288 
    1289     LogFlowFunc(("pBackendData=%p uOffset=%#llx pvBuf=%p cbRead=%u pcbActuallyRead=%p\n", pBackendData, uOffset, pvBuf, cbRead, pcbActuallyRead));
    1290 
    1291     if (uOffset + cbRead > pImage->cbSize)
    1292         return VERR_INVALID_PARAMETER;
    1293 
    1294     /*
    1295      * If we have a dynamic disk image, we need to find the data block and sector to read.
    1296      */
    1297     if (pImage->pBlockAllocationTable)
    1298     {
    1299         /*
    1300          * Get the data block first.
    1301          */
    1302         uint32_t cBlockAllocationTableEntry = (uOffset / VHD_SECTOR_SIZE) / pImage->cSectorsPerDataBlock;
    1303         uint32_t cBATEntryIndex = (uOffset / VHD_SECTOR_SIZE) % pImage->cSectorsPerDataBlock;
    1304         uint64_t uVhdOffset;
    1305 
    1306         LogFlowFunc(("cBlockAllocationTableEntry=%u cBatEntryIndex=%u\n", cBlockAllocationTableEntry, cBATEntryIndex));
    1307         LogFlowFunc(("BlockAllocationEntry=%u\n", pImage->pBlockAllocationTable[cBlockAllocationTableEntry]));
    1308 
    1309         /*
    1310          * If the block is not allocated the content of the entry is ~0
    1311          */
    1312         if (pImage->pBlockAllocationTable[cBlockAllocationTableEntry] == ~0U)
    1313         {
    1314             /* Return block size as read. */
    1315             *pcbActuallyRead = RT_MIN(cbRead, pImage->cSectorsPerDataBlock * VHD_SECTOR_SIZE);
    1316             return VERR_VD_BLOCK_FREE;
    1317         }
    1318 
    1319         uVhdOffset = ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry] + pImage->cDataBlockBitmapSectors + cBATEntryIndex) * VHD_SECTOR_SIZE;
    1320         LogFlowFunc(("uVhdOffset=%llu cbRead=%u\n", uVhdOffset, cbRead));
    1321 
    1322         /*
    1323          * Clip read range to remain in this data block.
    1324          */
    1325         cbRead = RT_MIN(cbRead, (pImage->cbDataBlock - (cBATEntryIndex * VHD_SECTOR_SIZE)));
    1326 
    1327         /* Read in the block's bitmap. */
    1328         rc = vhdFileReadSync(pImage,
    1329                              ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE,
    1330                              pImage->pu8Bitmap, pImage->cbDataBlockBitmap, NULL);
    1331         if (RT_SUCCESS(rc))
    1332         {
    1333             uint32_t cSectors = 0;
    1334 
    1335             if (vhdBlockBitmapSectorContainsData(pImage, cBATEntryIndex))
    1336             {
    1337                 cBATEntryIndex++;
    1338                 cSectors = 1;
    1339 
    1340                 /*
    1341                  * The first sector being read is marked dirty, read as much as we
    1342                  * can from child. Note that only sectors that are marked dirty
    1343                  * must be read from child.
    1344                  */
    1345                 while (   (cSectors < (cbRead / VHD_SECTOR_SIZE))
    1346                        && vhdBlockBitmapSectorContainsData(pImage, cBATEntryIndex))
    1347                 {
    1348                     cBATEntryIndex++;
    1349                     cSectors++;
    1350                 }
    1351 
    1352                 cbRead = cSectors * VHD_SECTOR_SIZE;
    1353 
    1354                 LogFlowFunc(("uVhdOffset=%llu cbRead=%u\n", uVhdOffset, cbRead));
    1355                 rc = vhdFileReadSync(pImage, uVhdOffset, pvBuf, cbRead, NULL);
    1356             }
    1357             else
    1358             {
    1359                 /*
    1360                  * The first sector being read is marked clean, so we should read from
    1361                  * our parent instead, but only as much as there are the following
    1362                  * clean sectors, because the block may still contain dirty sectors
    1363                  * further on. We just need to compute the number of clean sectors
    1364                  * and pass it to our caller along with the notification that they
    1365                  * should be read from the parent.
    1366                  */
    1367                 cBATEntryIndex++;
    1368                 cSectors = 1;
    1369 
    1370                 while (   (cSectors < (cbRead / VHD_SECTOR_SIZE))
    1371                        && !vhdBlockBitmapSectorContainsData(pImage, cBATEntryIndex))
    1372                 {
    1373                     cBATEntryIndex++;
    1374                     cSectors++;
    1375                 }
    1376 
    1377                 cbRead = cSectors * VHD_SECTOR_SIZE;
    1378                 Log(("%s: Sectors free: uVhdOffset=%llu cbRead=%u\n", __FUNCTION__, uVhdOffset, cbRead));
    1379                 rc = VERR_VD_BLOCK_FREE;
    1380             }
    1381         }
    1382         else
    1383             AssertMsgFailed(("Reading block bitmap failed rc=%Rrc\n", rc));
    1384     }
    1385     else
    1386     {
    1387         rc = vhdFileReadSync(pImage, uOffset, pvBuf, cbRead, NULL);
    1388     }
    1389 
    1390     if (pcbActuallyRead)
    1391         *pcbActuallyRead = cbRead;
    1392 
    1393     Log2(("vhdRead: off=%#llx pvBuf=%p cbRead=%d\n"
    1394             "%.*Rhxd\n",
    1395             uOffset, pvBuf, cbRead, cbRead, pvBuf));
    1396 
    1397     return rc;
    1398 }
    1399 
    1400 static int vhdWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf, size_t cbToWrite, size_t *pcbWriteProcess, size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite)
    1401 {
    1402     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1403     int rc = VINF_SUCCESS;
    1404 
    1405     LogFlowFunc(("pBackendData=%p uOffset=%llu pvBuf=%p cbToWrite=%u pcbWriteProcess=%p pcbPreRead=%p pcbPostRead=%p fWrite=%u\n",
    1406              pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead, fWrite));
    1407 
    1408     AssertPtr(pImage);
    1409     Assert(uOffset % VHD_SECTOR_SIZE == 0);
    1410     Assert(cbToWrite % VHD_SECTOR_SIZE == 0);
    1411 
    1412     if (pImage->pBlockAllocationTable)
    1413     {
    1414         /*
    1415          * Get the data block first.
    1416          */
    1417         uint32_t cSector = uOffset / VHD_SECTOR_SIZE;
    1418         uint32_t cBlockAllocationTableEntry = cSector / pImage->cSectorsPerDataBlock;
    1419         uint32_t cBATEntryIndex = cSector % pImage->cSectorsPerDataBlock;
    1420         uint64_t uVhdOffset;
    1421 
    1422         /*
    1423          * Clip write range.
    1424          */
    1425         cbToWrite = RT_MIN(cbToWrite, (pImage->cbDataBlock - (cBATEntryIndex * VHD_SECTOR_SIZE)));
    1426 
    1427         /*
    1428          * If the block is not allocated the content of the entry is ~0
    1429          * and we need to allocate a new block. Note that while blocks are
    1430          * allocated with a relatively big granularity, each sector has its
    1431          * own bitmap entry, indicating whether it has been written or not.
    1432          * So that means for the purposes of the higher level that the
    1433          * granularity is invisible. This means there's no need to return
    1434          * VERR_VD_BLOCK_FREE unless the block hasn't been allocated yet.
    1435          */
    1436         if (pImage->pBlockAllocationTable[cBlockAllocationTableEntry] == ~0U)
    1437         {
    1438             /* Check if the block allocation should be suppressed. */
    1439             if (fWrite & VD_WRITE_NO_ALLOC)
    1440             {
    1441                 *pcbPreRead = cBATEntryIndex * VHD_SECTOR_SIZE;
    1442                 *pcbPostRead = pImage->cSectorsPerDataBlock * VHD_SECTOR_SIZE - cbToWrite - *pcbPreRead;
    1443 
    1444                 if (pcbWriteProcess)
    1445                     *pcbWriteProcess = cbToWrite;
    1446                 return VERR_VD_BLOCK_FREE;
    1447             }
    1448 
    1449             size_t  cbNewBlock = pImage->cbDataBlock + (pImage->cDataBlockBitmapSectors * VHD_SECTOR_SIZE);
    1450             uint8_t *pNewBlock = (uint8_t *)RTMemAllocZ(cbNewBlock);
    1451 
    1452             if (!pNewBlock)
    1453                 return VERR_NO_MEMORY;
    1454 
    1455             /*
    1456              * Write the new block at the current end of the file.
    1457              */
    1458             rc = vhdFileWriteSync(pImage, pImage->uCurrentEndOfFile, pNewBlock, cbNewBlock, NULL);
    1459             AssertRC(rc);
    1460 
    1461             /*
    1462              * Set the new end of the file and link the new block into the BAT.
    1463              */
    1464             pImage->pBlockAllocationTable[cBlockAllocationTableEntry] = pImage->uCurrentEndOfFile / VHD_SECTOR_SIZE;
    1465             pImage->uCurrentEndOfFile += cbNewBlock;
    1466             RTMemFree(pNewBlock);
    1467 
    1468             /* Write the updated BAT and the footer to remain in a consistent state. */
    1469             rc = vhdFlush(pImage);
    1470             AssertRC(rc);
    1471         }
    1472 
    1473         /*
    1474          * Calculate the real offset in the file.
    1475          */
    1476         uVhdOffset = ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry] + pImage->cDataBlockBitmapSectors + cBATEntryIndex) * VHD_SECTOR_SIZE;
    1477 
    1478         /* Write data. */
    1479         vhdFileWriteSync(pImage, uVhdOffset, pvBuf, cbToWrite, NULL);
    1480 
    1481         /* Read in the block's bitmap. */
    1482         rc = vhdFileReadSync(pImage,
    1483             ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE,
    1484             pImage->pu8Bitmap, pImage->cbDataBlockBitmap, NULL);
    1485         if (RT_SUCCESS(rc))
    1486         {
    1487             bool fChanged = false;
    1488 
    1489             /* Set the bits for all sectors having been written. */
    1490             for (uint32_t iSector = 0; iSector < (cbToWrite / VHD_SECTOR_SIZE); iSector++)
    1491             {
    1492                 fChanged |= vhdBlockBitmapSectorSet(pImage, pImage->pu8Bitmap, cBATEntryIndex);
    1493                 cBATEntryIndex++;
    1494             }
    1495 
    1496             if (fChanged)
    1497             {
    1498                 /* Write the bitmap back. */
    1499                 rc = vhdFileWriteSync(pImage,
    1500                                       ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE,
    1501                                       pImage->pu8Bitmap, pImage->cbDataBlockBitmap, NULL);
    1502             }
    1503         }
    1504     }
    1505     else
    1506     {
    1507         rc = vhdFileWriteSync(pImage, uOffset, pvBuf, cbToWrite, NULL);
    1508     }
    1509 
    1510     if (pcbWriteProcess)
    1511         *pcbWriteProcess = cbToWrite;
    1512 
    1513     /* Stay on the safe side. Do not run the risk of confusing the higher
    1514      * level, as that can be pretty lethal to image consistency. */
    1515     *pcbPreRead = 0;
    1516     *pcbPostRead = 0;
    1517 
    1518     return rc;
    1519 }
    1520 
    1521 static int vhdFlush(void *pBackendData)
    1522 {
    1523     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1524 
    1525     if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    1526         return VINF_SUCCESS;
    1527 
    1528     if (pImage->pBlockAllocationTable)
    1529     {
    1530         /*
    1531          * This is an expanding image. Write the BAT and copy of the disk footer.
    1532          */
    1533         size_t   cbBlockAllocationTableToWrite = pImage->cBlockAllocationTableEntries * sizeof(uint32_t);
    1534         uint32_t *pBlockAllocationTableToWrite = (uint32_t *)RTMemAllocZ(cbBlockAllocationTableToWrite);
    1535 
    1536         if (!pBlockAllocationTableToWrite)
    1537             return VERR_NO_MEMORY;
    1538 
    1539         /*
    1540          * The BAT entries have to be stored in big endian format.
    1541          */
    1542         for (unsigned i = 0; i < pImage->cBlockAllocationTableEntries; i++)
    1543             pBlockAllocationTableToWrite[i] = RT_H2BE_U32(pImage->pBlockAllocationTable[i]);
    1544 
    1545         /*
    1546          * Write the block allocation table after the copy of the disk footer and the dynamic disk header.
    1547          */
    1548         vhdFileWriteSync(pImage, pImage->uBlockAllocationTableOffset, pBlockAllocationTableToWrite, cbBlockAllocationTableToWrite, NULL);
    1549         if (pImage->fDynHdrNeedsUpdate)
    1550             vhdDynamicHeaderUpdate(pImage);
    1551         RTMemFree(pBlockAllocationTableToWrite);
    1552     }
    1553 
    1554     vhdUpdateFooter(pImage);
    1555 
    1556     int rc = vhdFileFlushSync(pImage);
    1557 
    1558     return rc;
    1559 }
    1560 
    1561 static uint64_t vhdGetSize(void *pBackendData)
    1562 {
    1563     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1564 
    1565     AssertPtr(pImage);
    1566 
    1567     if (pImage)
    1568     {
    1569         Log(("%s: cbSize=%llu\n", __FUNCTION__, pImage->cbSize));
    1570         return pImage->cbSize;
    1571     }
    1572     else
    1573         return 0;
    1574 }
    1575 
    1576 static uint64_t vhdGetFileSize(void *pBackendData)
    1577 {
    1578     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1579 
    1580     AssertPtr(pImage);
    1581 
    1582     if (pImage)
    1583     {
    1584         uint64_t cb;
    1585         int rc = vhdFileGetSize(pImage, &cb);
    1586         if (RT_SUCCESS(rc))
    1587             return cb;
    1588         else
    1589             return 0;
    1590     }
    1591     else
    1592         return 0;
    1593 }
    1594 
    1595 static int vhdGetUuid(void *pBackendData, PRTUUID pUuid)
    1596 {
    1597     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1598     int rc;
    1599 
    1600     AssertPtr(pImage);
    1601 
    1602     if (pImage)
    1603     {
    1604         *pUuid = pImage->ImageUuid;
    1605         rc = VINF_SUCCESS;
    1606     }
    1607     else
    1608         rc = VERR_VD_NOT_OPENED;
    1609     LogFlowFunc(("returned %Rrc (%RTuuid)\n", rc, pUuid));
    1610     return rc;
    1611 }
    1612 
    1613 static int vhdSetUuid(void *pBackendData, PCRTUUID pUuid)
    1614 {
    1615     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1616     int rc;
    1617 
    1618     LogFlowFunc(("Uuid=%RTuuid\n", pUuid));
    1619     AssertPtr(pImage);
    1620 
    1621     if (pImage)
    1622     {
    1623         pImage->ImageUuid = *pUuid;
    1624         /* Update the footer copy. It will get written to disk when the image is closed. */
    1625         memcpy(&pImage->vhdFooterCopy.UniqueID, pUuid, 16);
    1626         /* Update checksum. */
    1627         pImage->vhdFooterCopy.Checksum = 0;
    1628         pImage->vhdFooterCopy.Checksum = RT_H2BE_U32(vhdChecksum(&pImage->vhdFooterCopy, sizeof(VHDFooter)));
    1629 
    1630         /* Need to update the dynamic disk header to update the disk footer copy at the beginning. */
    1631         if (!(pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED))
    1632             pImage->fDynHdrNeedsUpdate = true;
    1633         rc = VINF_SUCCESS;
    1634     }
    1635     else
    1636         rc = VERR_VD_NOT_OPENED;
    1637     LogFlowFunc(("returned %Rrc\n", rc));
    1638     return rc;
    1639 }
    1640 
    1641 static int vhdGetComment(void *pBackendData, char *pszComment, size_t cbComment)
    1642 {
    1643     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1644     int rc;
    1645 
    1646     AssertPtr(pImage);
    1647 
    1648     if (pImage)
    1649     {
    1650         rc = VERR_NOT_SUPPORTED;
    1651     }
    1652     else
    1653         rc = VERR_VD_NOT_OPENED;
    1654 
    1655     LogFlowFunc(("returned %Rrc comment='%s'\n", rc, pszComment));
    1656     return rc;
    1657 }
    1658 
    1659 static int vhdSetComment(void *pBackendData, const char *pszComment)
    1660 {
    1661     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1662     int rc;
    1663 
    1664     LogFlowFunc(("pszComment='%s'\n", pszComment));
    1665     AssertPtr(pImage);
    1666 
    1667     if (pImage)
    1668     {
    1669         /**@todo: implement */
    1670         rc = VINF_SUCCESS;
    1671     }
    1672     else
    1673         rc = VERR_VD_NOT_OPENED;
    1674 
    1675     LogFlowFunc(("returned %Rrc\n", rc));
    1676     return rc;
    1677 }
    1678 
    1679 static int vhdGetModificationUuid(void *pBackendData, PRTUUID pUuid)
    1680 {
    1681     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1682     int rc;
    1683 
    1684     AssertPtr(pImage);
    1685 
    1686     if (pImage)
    1687     {
    1688         rc = VERR_NOT_SUPPORTED;
    1689     }
    1690     else
    1691         rc = VERR_VD_NOT_OPENED;
    1692     LogFlowFunc(("returned %Rrc (%RTuuid)\n", rc, pUuid));
    1693     return rc;
    1694 }
    1695 
    1696 static int vhdSetModificationUuid(void *pBackendData, PCRTUUID pUuid)
    1697 {
    1698     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1699     int rc;
    1700 
    1701     LogFlowFunc(("Uuid=%RTuuid\n", pUuid));
    1702     AssertPtr(pImage);
    1703 
    1704     if (pImage)
    1705     {
    1706         rc = VINF_SUCCESS;
    1707     }
    1708     else
    1709         rc = VERR_VD_NOT_OPENED;
    1710     LogFlowFunc(("returned %Rrc\n", rc));
    1711     return rc;
    1712 }
    1713 
    1714 static int vhdGetParentUuid(void *pBackendData, PRTUUID pUuid)
    1715 {
    1716     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1717     int rc;
    1718 
    1719     AssertPtr(pImage);
    1720 
    1721     if (pImage)
    1722     {
    1723         *pUuid = pImage->ParentUuid;
    1724         rc = VINF_SUCCESS;
    1725     }
    1726     else
    1727         rc = VERR_VD_NOT_OPENED;
    1728     LogFlowFunc(("returned %Rrc (%RTuuid)\n", rc, pUuid));
    1729     return rc;
    1730 }
    1731 
    1732 static int vhdSetParentUuid(void *pBackendData, PCRTUUID pUuid)
    1733 {
    1734     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1735     int rc = VINF_SUCCESS;
    1736 
    1737     LogFlowFunc((" %RTuuid\n", pUuid));
    1738     AssertPtr(pImage);
    1739 
    1740     if (pImage && vhdFileOpened(pImage))
    1741     {
    1742         if (!(pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED))
    1743         {
    1744             pImage->ParentUuid = *pUuid;
    1745             pImage->fDynHdrNeedsUpdate = true;
    1746         }
    1747         else
    1748             rc = VERR_NOT_SUPPORTED;
    1749     }
    1750     else
    1751         rc = VERR_VD_NOT_OPENED;
    1752     LogFlowFunc(("returned %Rrc\n", rc));
    1753     return rc;
    1754 }
    1755 
    1756 static int vhdGetParentModificationUuid(void *pBackendData, PRTUUID pUuid)
    1757 {
    1758     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1759     int rc;
    1760 
    1761     AssertPtr(pImage);
    1762 
    1763     if (pImage)
    1764     {
    1765         rc = VERR_NOT_SUPPORTED;
    1766     }
    1767     else
    1768         rc = VERR_VD_NOT_OPENED;
    1769     LogFlowFunc(("returned %Rrc (%RTuuid)\n", rc, pUuid));
    1770     return rc;
    1771 }
    1772 
    1773 static int vhdSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid)
    1774 {
    1775     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    1776     int rc;
    1777 
    1778     LogFlowFunc(("%RTuuid\n", pUuid));
    1779     AssertPtr(pImage);
    1780 
    1781     if (pImage)
    1782     {
    1783         rc = VINF_SUCCESS;
    1784     }
    1785     else
    1786         rc = VERR_VD_NOT_OPENED;
    1787     LogFlowFunc(("returned %Rrc\n", rc));
    1788     return rc;
    17891066}
    17901067
     
    18411118}
    18421119
    1843 
    1844 /**
    1845  * Internal: signal an error to the frontend.
    1846  */
    1847 DECLINLINE(int) vhdError(PVHDIMAGE pImage, int rc, RT_SRC_POS_DECL,
    1848                          const char *pszFormat, ...)
    1849 {
    1850     va_list va;
    1851     va_start(va, pszFormat);
    1852     if (pImage->pInterfaceError && pImage->pInterfaceErrorCallbacks)
    1853         pImage->pInterfaceErrorCallbacks->pfnError(pImage->pInterfaceError->pvUser, rc, RT_SRC_POS_ARGS,
    1854                                                    pszFormat, va);
    1855     va_end(va);
    1856     return rc;
    1857 }
    18581120
    18591121static uint32_t vhdAllocateParentLocators(PVHDIMAGE pImage, VHDDynamicDiskHeader *pDDH, uint64_t u64Offset)
     
    19341196        return vhdError(pImage, VERR_NO_MEMORY, RT_SRC_POS, N_("VHD: cannot set the file size for '%s'"), pImage->pszFilename);
    19351197
    1936     rc = vhdFileWriteSync(pImage, 0, pvTmp, pImage->uCurrentEndOfFile + sizeof(VHDFooter), NULL);
     1198    rc = vhdFileWriteSync(pImage, 0, pvTmp,
     1199                          pImage->uCurrentEndOfFile + sizeof(VHDFooter), NULL);
    19371200    if (RT_FAILURE(rc))
    19381201    {
     
    19541217    DynamicDiskHeader.Checksum = RT_H2BE_U32(vhdChecksum(&DynamicDiskHeader, sizeof(DynamicDiskHeader)));
    19551218
    1956     rc = vhdFileWriteSync(pImage, sizeof(VHDFooter), &DynamicDiskHeader, sizeof(DynamicDiskHeader), NULL);
     1219    rc = vhdFileWriteSync(pImage, sizeof(VHDFooter), &DynamicDiskHeader,
     1220                          sizeof(DynamicDiskHeader), NULL);
    19571221    if (RT_FAILURE(rc))
    19581222        return vhdError(pImage, rc, RT_SRC_POS, N_("VHD: cannot write dynamic disk header to image '%s'"), pImage->pszFilename);
    19591223
    19601224    /* Write BAT. */
    1961     rc = vhdFileWriteSync(pImage, pImage->uBlockAllocationTableOffset, pImage->pBlockAllocationTable,
    1962                           pImage->cBlockAllocationTableEntries * sizeof(uint32_t), NULL);
     1225    rc = vhdFileWriteSync(pImage, pImage->uBlockAllocationTableOffset,
     1226                          pImage->pBlockAllocationTable,
     1227                          pImage->cBlockAllocationTableEntries * sizeof(uint32_t),
     1228                          NULL);
    19631229    if (RT_FAILURE(rc))
    19641230        return vhdError(pImage, rc, RT_SRC_POS, N_("VHD: cannot write BAT to image '%s'"), pImage->pszFilename);
     
    19721238static int vhdCreateImage(PVHDIMAGE pImage, uint64_t cbSize,
    19731239                          unsigned uImageFlags, const char *pszComment,
    1974                           PCPDMMEDIAGEOMETRY pPCHSGeometry,
    1975                           PCPDMMEDIAGEOMETRY pLCHSGeometry, PCRTUUID pUuid,
     1240                          PCVDGEOMETRY pPCHSGeometry,
     1241                          PCVDGEOMETRY pLCHSGeometry, PCRTUUID pUuid,
    19761242                          unsigned uOpenFlags,
    19771243                          PFNVDPROGRESS pfnProgress, void *pvUser,
     
    19891255        pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError);
    19901256
    1991     rc = vhdFileOpen(pImage, false /* fReadonly */,
    1992                      !!(uOpenFlags & VD_OPEN_FLAGS_SHAREABLE),
    1993                      true /* fCreate */);
     1257    rc = vhdFileOpen(pImage, pImage->pszFilename,
     1258                     VDOpenFlagsToFileOpenFlags(uOpenFlags & ~VD_OPEN_FLAGS_READONLY,
     1259                                                true /* fCreate */));
    19941260    if (RT_FAILURE(rc))
    19951261        return vhdError(pImage, rc, RT_SRC_POS, N_("VHD: cannot create image '%s'"), pImage->pszFilename);
     
    20791345
    20801346    /* Store the footer */
    2081     rc = vhdFileWriteSync(pImage, pImage->uCurrentEndOfFile, &Footer, sizeof(Footer), NULL);
     1347    rc = vhdFileWriteSync(pImage, pImage->uCurrentEndOfFile, &Footer,
     1348                          sizeof(Footer), NULL);
    20821349    if (RT_FAILURE(rc))
    20831350    {
     
    20981365    }
    20991366
    2100     if (pfnProgress)
     1367out:
     1368    if (RT_SUCCESS(rc) && pfnProgress)
    21011369        pfnProgress(pvUser, uPercentStart + uPercentSpan);
    21021370
     1371    if (RT_FAILURE(rc))
     1372        vhdFreeImage(pImage, rc != VERR_ALREADY_EXISTS);
     1373    return rc;
     1374}
     1375
     1376
     1377/** @copydoc VBOXHDDBACKEND::pfnCheckIfValid */
     1378static int vhdCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk,
     1379                           PVDINTERFACE pVDIfsImage)
     1380{
     1381    LogFlowFunc(("pszFilename=\"%s\" pVDIfsDisk=%#p pVDIfsImage=%#p\n", pszFilename, pVDIfsDisk, pVDIfsImage));
     1382    int rc;
     1383    PVDIOSTORAGE pStorage;
     1384    uint64_t cbFile;
     1385    VHDFooter vhdFooter;
     1386
     1387    /* Get I/O interface. */
     1388    PVDINTERFACE pInterfaceIO = VDInterfaceGet(pVDIfsImage, VDINTERFACETYPE_IO);
     1389    AssertPtrReturn(pInterfaceIO, VERR_INVALID_PARAMETER);
     1390    PVDINTERFACEIO pInterfaceIOCallbacks = VDGetInterfaceIO(pInterfaceIO);
     1391    AssertPtrReturn(pInterfaceIOCallbacks, VERR_INVALID_PARAMETER);
     1392
     1393    rc = pInterfaceIOCallbacks->pfnOpen(pInterfaceIO->pvUser, pszFilename,
     1394                                        VDOpenFlagsToFileOpenFlags(VD_OPEN_FLAGS_READONLY,
     1395                                                                   false /* fCreate */),
     1396                                        &pStorage);
     1397    if (RT_FAILURE(rc))
     1398        goto out;
     1399
     1400    rc = pInterfaceIOCallbacks->pfnGetSize(pInterfaceIO->pvUser, pStorage,
     1401                                           &cbFile);
     1402    if (RT_FAILURE(rc))
     1403    {
     1404        pInterfaceIOCallbacks->pfnClose(pInterfaceIO->pvUser, pStorage);
     1405        rc = VERR_VD_VHD_INVALID_HEADER;
     1406        goto out;
     1407    }
     1408
     1409    rc = pInterfaceIOCallbacks->pfnReadSync(pInterfaceIO->pvUser, pStorage,
     1410                                            cbFile - sizeof(VHDFooter),
     1411                                            &vhdFooter, sizeof(VHDFooter), NULL);
     1412    if (RT_FAILURE(rc) || (memcmp(vhdFooter.Cookie, VHD_FOOTER_COOKIE, VHD_FOOTER_COOKIE_SIZE) != 0))
     1413        rc = VERR_VD_VHD_INVALID_HEADER;
     1414    else
     1415        rc = VINF_SUCCESS;
     1416
     1417    pInterfaceIOCallbacks->pfnClose(pInterfaceIO->pvUser, pStorage);
     1418
    21031419out:
    2104     return rc;
    2105 }
    2106 
     1420    LogFlowFunc(("returns %Rrc\n", rc));
     1421    return rc;
     1422}
     1423
     1424/** @copydoc VBOXHDDBACKEND::pfnOpen */
     1425static int vhdOpen(const char *pszFilename, unsigned uOpenFlags,
     1426                   PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
     1427                   void **ppBackendData)
     1428{
     1429    LogFlowFunc(("pszFilename=\"%s\" uOpenFlags=%#x pVDIfsDisk=%#p pVDIfsImage=%#p ppBackendData=%#p\n", pszFilename, uOpenFlags, pVDIfsDisk, pVDIfsImage, ppBackendData));
     1430    int rc = VINF_SUCCESS;
     1431    PVHDIMAGE pImage;
     1432
     1433    /* Check open flags. All valid flags are supported. */
     1434    if (uOpenFlags & ~VD_OPEN_FLAGS_MASK)
     1435    {
     1436        rc = VERR_INVALID_PARAMETER;
     1437        goto out;
     1438    }
     1439
     1440    /* Check remaining arguments. */
     1441    if (   !VALID_PTR(pszFilename)
     1442        || !*pszFilename)
     1443    {
     1444        rc = VERR_INVALID_PARAMETER;
     1445        goto out;
     1446    }
     1447
     1448    pImage = (PVHDIMAGE)RTMemAllocZ(sizeof(VHDIMAGE));
     1449    if (!pImage)
     1450    {
     1451        rc = VERR_NO_MEMORY;
     1452        goto out;
     1453    }
     1454
     1455    pImage->pszFilename = pszFilename;
     1456    pImage->pStorage = NULL;
     1457    pImage->pVDIfsDisk = pVDIfsDisk;
     1458    pImage->pVDIfsImage = pVDIfsImage;
     1459
     1460    rc = vhdOpenImage(pImage, uOpenFlags);
     1461    if (RT_SUCCESS(rc))
     1462        *ppBackendData = pImage;
     1463    else
     1464        RTMemFree(pImage);
     1465
     1466out:
     1467    LogFlowFunc(("returns %Rrc (pBackendData=%#p)\n", rc, *ppBackendData));
     1468    return rc;
     1469}
     1470
     1471/** @copydoc VBOXHDDBACKEND::pfnCreate */
    21071472static int vhdCreate(const char *pszFilename, uint64_t cbSize,
    21081473                     unsigned uImageFlags, const char *pszComment,
    2109                      PCPDMMEDIAGEOMETRY pPCHSGeometry,
    2110                      PCPDMMEDIAGEOMETRY pLCHSGeometry, PCRTUUID pUuid,
    2111                      unsigned uOpenFlags, unsigned uPercentStart,
    2112                      unsigned uPercentSpan, PVDINTERFACE pVDIfsDisk,
    2113                      PVDINTERFACE pVDIfsImage, PVDINTERFACE pVDIfsOperation,
    2114                      void **ppvBackendData)
    2115 {
     1474                     PCVDGEOMETRY pPCHSGeometry, PCVDGEOMETRY pLCHSGeometry,
     1475                     PCRTUUID pUuid, unsigned uOpenFlags,
     1476                     unsigned uPercentStart, unsigned uPercentSpan,
     1477                     PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
     1478                     PVDINTERFACE pVDIfsOperation, void **ppBackendData)
     1479{
     1480    LogFlowFunc(("pszFilename=\"%s\" cbSize=%llu uImageFlags=%#x pszComment=\"%s\" pPCHSGeometry=%#p pLCHSGeometry=%#p Uuid=%RTuuid uOpenFlags=%#x uPercentStart=%u uPercentSpan=%u pVDIfsDisk=%#p pVDIfsImage=%#p pVDIfsOperation=%#p ppBackendData=%#p", pszFilename, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, ppBackendData));
    21161481    int rc = VINF_SUCCESS;
    21171482    PVHDIMAGE pImage;
     
    21461511    }
    21471512    pImage->pszFilename = pszFilename;
    2148 #ifndef VBOX_WITH_NEW_IO_CODE
    2149     pImage->File = NIL_RTFILE;
    2150 #else
    21511513    pImage->pStorage = NULL;
    2152 #endif
    21531514    pImage->pVDIfsDisk = pVDIfsDisk;
    21541515    pImage->pVDIfsImage = pVDIfsImage;
    21551516
    2156 #ifdef VBOX_WITH_NEW_IO_CODE
    2157     /* Try to get I/O interface. */
     1517    /* Get I/O interface. */
    21581518    pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsImage, VDINTERFACETYPE_IO);
    2159     AssertPtr(pImage->pInterfaceIO);
     1519    AssertPtrReturn(pImage->pInterfaceIO, VERR_INVALID_PARAMETER);
    21601520    pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO);
    2161     AssertPtr(pImage->pInterfaceIOCallbacks);
    2162 #endif
     1521    AssertPtrReturn(pImage->pInterfaceIOCallbacks, VERR_INVALID_PARAMETER);
    21631522
    21641523    rc = vhdCreateImage(pImage, cbSize, uImageFlags, pszComment,
     
    21721531        if (uOpenFlags & VD_OPEN_FLAGS_READONLY)
    21731532        {
    2174             vhdClose(pImage, false);
     1533            vhdFreeImage(pImage, false);
    21751534            rc = vhdOpenImage(pImage, uOpenFlags);
    21761535            if (RT_FAILURE(rc))
     1536            {
     1537                RTMemFree(pImage);
    21771538                goto out;
     1539            }
    21781540        }
    2179         *ppvBackendData = pImage;
    2180     }
     1541        *ppBackendData = pImage;
     1542    }
     1543    else
     1544        RTMemFree(pImage);
     1545
    21811546out:
    2182     LogFlowFunc(("returned %Rrc\n", rc));
    2183     return rc;
    2184 }
    2185 
    2186 static void vhdDump(void *pBackendData)
    2187 {
    2188     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    2189 
    2190     AssertPtr(pImage);
    2191     if (pImage)
    2192     {
    2193         pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n",
    2194                     pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors,
    2195                     pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors,
    2196                     VHD_SECTOR_SIZE);
    2197         pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: uuidCreation={%RTuuid}\n", &pImage->ImageUuid);
    2198         pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: uuidParent={%RTuuid}\n", &pImage->ParentUuid);
    2199     }
    2200 }
    2201 
    2202 
    2203 static int vhdGetTimeStamp(void *pvBackendData, PRTTIMESPEC pTimeStamp)
    2204 {
     1547    LogFlowFunc(("returns %Rrc\n", rc));
     1548    return rc;
     1549}
     1550
     1551/** @copydoc VBOXHDDBACKEND::pfnRename */
     1552static int vhdRename(void *pBackendData, const char *pszFilename)
     1553{
     1554    LogFlowFunc(("pBackendData=%#p pszFilename=%#p\n", pBackendData, pszFilename));
    22051555    int rc = VINF_SUCCESS;
    2206     PVHDIMAGE pImage = (PVHDIMAGE)pvBackendData;
    2207 
    2208     AssertPtr(pImage);
    2209     if (pImage)
    2210     {
    2211         RTFSOBJINFO info;
    2212 
    2213 #ifndef VBOX_WITH_NEW_IO_CODE
    2214         rc = RTFileQueryInfo(pImage->File, &info, RTFSOBJATTRADD_NOTHING);
    2215 #else
    2216         /* Interface doesn't provide such a feature. */
    2217         RTFILE File;
    2218         rc = RTFileOpen(&File, pImage->pszFilename, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
    2219         if (RT_SUCCESS(rc))
    2220         {
    2221             rc = RTFileQueryInfo(File, &info, RTFSOBJATTRADD_NOTHING);
    2222             RTFileClose(File);
    2223         }
    2224 #endif
    2225 
    2226         *pTimeStamp = info.ModificationTime;
    2227     }
    2228     else
    2229         rc = VERR_VD_NOT_OPENED;
    2230     LogFlowFunc(("returned %Rrc\n", rc));
    2231     return rc;
    2232 }
    2233 
    2234 static int vhdGetParentTimeStamp(void *pvBackendData, PRTTIMESPEC pTimeStamp)
    2235 {
     1556    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     1557
     1558    /* Check arguments. */
     1559    if (   !pImage
     1560        || !pszFilename
     1561        || !*pszFilename)
     1562    {
     1563        rc = VERR_INVALID_PARAMETER;
     1564        goto out;
     1565    }
     1566
     1567    /* Close the image. */
     1568    rc = vhdFreeImage(pImage, false);
     1569    if (RT_FAILURE(rc))
     1570        goto out;
     1571
     1572    /* Rename the file. */
     1573    rc = vhdFileMove(pImage, pImage->pszFilename, pszFilename, 0);
     1574    if (RT_FAILURE(rc))
     1575    {
     1576        /* The move failed, try to reopen the original image. */
     1577        int rc2 = vhdOpenImage(pImage, pImage->uOpenFlags);
     1578        if (RT_FAILURE(rc2))
     1579            rc = rc2;
     1580
     1581        goto out;
     1582    }
     1583
     1584    /* Update pImage with the new information. */
     1585    pImage->pszFilename = pszFilename;
     1586
     1587    /* Open the old file with new name. */
     1588    rc = vhdOpenImage(pImage, pImage->uOpenFlags);
     1589    if (RT_FAILURE(rc))
     1590        goto out;
     1591
     1592out:
     1593    LogFlowFunc(("returns %Rrc\n", rc));
     1594    return rc;
     1595}
     1596
     1597/** @copydoc VBOXHDDBACKEND::pfnClose */
     1598static int vhdClose(void *pBackendData, bool fDelete)
     1599{
     1600    LogFlowFunc(("pBackendData=%#p fDelete=%d\n", pBackendData, fDelete));
     1601    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     1602    int rc;
     1603
     1604    rc = vhdFreeImage(pImage, fDelete);
     1605    RTMemFree(pImage);
     1606
     1607    LogFlowFunc(("returns %Rrc\n", rc));
     1608    return rc;
     1609}
     1610
     1611/** @copydoc VBOXHDDBACKEND::pfnRead */
     1612static int vhdRead(void *pBackendData, uint64_t uOffset, void *pvBuf,
     1613                   size_t cbBuf, size_t *pcbActuallyRead)
     1614{
     1615    LogFlowFunc(("pBackendData=%p uOffset=%#llx pvBuf=%p cbBuf=%u pcbActuallyRead=%p\n", pBackendData, uOffset, pvBuf, cbBuf, pcbActuallyRead));
     1616    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    22361617    int rc = VINF_SUCCESS;
    2237     PVHDIMAGE pImage = (PVHDIMAGE)pvBackendData;
    2238 
    2239     AssertPtr(pImage);
    2240     if (pImage)
    2241         vhdTime2RtTime(pTimeStamp, pImage->u32ParentTimeStamp);
    2242     else
    2243         rc = VERR_VD_NOT_OPENED;
    2244     LogFlowFunc(("returned %Rrc\n", rc));
    2245     return rc;
    2246 }
    2247 
    2248 static int vhdSetParentTimeStamp(void *pvBackendData, PCRTTIMESPEC pTimeStamp)
    2249 {
    2250     int rc = VINF_SUCCESS;
    2251     PVHDIMAGE pImage = (PVHDIMAGE)pvBackendData;
    2252 
    2253     AssertPtr(pImage);
    2254     if (pImage)
    2255     {
    2256         if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    2257             rc = VERR_VD_IMAGE_READ_ONLY;
    2258         else
    2259         {
    2260             pImage->u32ParentTimeStamp = vhdRtTime2VhdTime(pTimeStamp);
    2261             pImage->fDynHdrNeedsUpdate = true;
    2262         }
    2263     }
    2264     else
    2265         rc = VERR_VD_NOT_OPENED;
    2266     LogFlowFunc(("returned %Rrc\n", rc));
    2267     return rc;
    2268 }
    2269 
    2270 static int vhdGetParentFilename(void *pvBackendData, char **ppszParentFilename)
    2271 {
    2272     int rc = VINF_SUCCESS;
    2273     PVHDIMAGE pImage = (PVHDIMAGE)pvBackendData;
    2274 
    2275     AssertPtr(pImage);
    2276     if (pImage)
    2277         *ppszParentFilename = RTStrDup(pImage->pszParentFilename);
    2278     else
    2279         rc = VERR_VD_NOT_OPENED;
    2280     LogFlowFunc(("returned %Rrc\n", rc));
    2281     return rc;
    2282 }
    2283 
    2284 static int vhdSetParentFilename(void *pvBackendData, const char *pszParentFilename)
    2285 {
    2286     int rc = VINF_SUCCESS;
    2287     PVHDIMAGE pImage = (PVHDIMAGE)pvBackendData;
    2288 
    2289     AssertPtr(pImage);
    2290     if (pImage)
    2291     {
    2292         if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    2293             rc = VERR_VD_IMAGE_READ_ONLY;
    2294         else
    2295         {
    2296             if (pImage->pszParentFilename)
    2297                 RTStrFree(pImage->pszParentFilename);
    2298             pImage->pszParentFilename = RTStrDup(pszParentFilename);
    2299             if (!pImage->pszParentFilename)
    2300                 rc = VERR_NO_MEMORY;
    2301             else
    2302                 pImage->fDynHdrNeedsUpdate = true;
    2303         }
    2304     }
    2305     else
    2306         rc = VERR_VD_NOT_OPENED;
    2307     LogFlowFunc(("returned %Rrc\n", rc));
    2308     return rc;
    2309 }
    2310 
    2311 static bool vhdIsAsyncIOSupported(void *pvBackendData)
    2312 {
    2313     return true;
    2314 }
    2315 
    2316 static int vhdAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbRead,
    2317                         PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
    2318 {
    2319     PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    2320     int rc = VINF_SUCCESS;
    2321 
    2322     LogFlowFunc(("pBackendData=%p uOffset=%#llx pIoCtx=%#p cbRead=%u pcbActuallyRead=%p\n", pBackendData, uOffset, pIoCtx, cbRead, pcbActuallyRead));
    2323 
    2324     if (uOffset + cbRead > pImage->cbSize)
    2325         return VERR_INVALID_PARAMETER;
     1618
     1619    if (uOffset + cbBuf > pImage->cbSize)
     1620    {
     1621        rc = VERR_INVALID_PARAMETER;
     1622        goto out;
     1623    }
    23261624
    23271625    /*
     
    23461644        {
    23471645            /* Return block size as read. */
    2348             *pcbActuallyRead = RT_MIN(cbRead, pImage->cSectorsPerDataBlock * VHD_SECTOR_SIZE);
    2349             return VERR_VD_BLOCK_FREE;
     1646            *pcbActuallyRead = RT_MIN(cbBuf, pImage->cSectorsPerDataBlock * VHD_SECTOR_SIZE);
     1647            rc = VERR_VD_BLOCK_FREE;
     1648            goto out;
    23501649        }
    23511650
    23521651        uVhdOffset = ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry] + pImage->cDataBlockBitmapSectors + cBATEntryIndex) * VHD_SECTOR_SIZE;
    2353         LogFlowFunc(("uVhdOffset=%llu cbRead=%u\n", uVhdOffset, cbRead));
     1652        LogFlowFunc(("uVhdOffset=%llu cbBuf=%u\n", uVhdOffset, cbBuf));
    23541653
    23551654        /*
    23561655         * Clip read range to remain in this data block.
    23571656         */
    2358         cbRead = RT_MIN(cbRead, (pImage->cbDataBlock - (cBATEntryIndex * VHD_SECTOR_SIZE)));
     1657        cbBuf = RT_MIN(cbBuf, (pImage->cbDataBlock - (cBATEntryIndex * VHD_SECTOR_SIZE)));
    23591658
    23601659        /* Read in the block's bitmap. */
    2361         PVDMETAXFER pMetaXfer;
    2362         rc = pImage->pInterfaceIOCallbacks->pfnReadMetaAsync(pImage->pInterfaceIO->pvUser,
    2363                                                              pImage->pStorage,
    2364                                                              ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE,
    2365                                                              pImage->pu8Bitmap, pImage->cbDataBlockBitmap, pIoCtx, &pMetaXfer,
    2366                                                              NULL, NULL);
    2367 
     1660        rc = vhdFileReadSync(pImage,
     1661                             ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE,
     1662                             pImage->pu8Bitmap, pImage->cbDataBlockBitmap,
     1663                             NULL);
    23681664        if (RT_SUCCESS(rc))
    23691665        {
    23701666            uint32_t cSectors = 0;
    23711667
    2372             pImage->pInterfaceIOCallbacks->pfnMetaXferRelease(pImage->pInterfaceIO->pvUser, pMetaXfer);
    23731668            if (vhdBlockBitmapSectorContainsData(pImage, cBATEntryIndex))
    23741669            {
     
    23811676                 * must be read from child.
    23821677                 */
    2383                 while (   (cSectors < (cbRead / VHD_SECTOR_SIZE))
     1678                while (   (cSectors < (cbBuf / VHD_SECTOR_SIZE))
    23841679                       && vhdBlockBitmapSectorContainsData(pImage, cBATEntryIndex))
    23851680                {
     
    23881683                }
    23891684
    2390                 cbRead = cSectors * VHD_SECTOR_SIZE;
    2391 
    2392                 LogFlowFunc(("uVhdOffset=%llu cbRead=%u\n", uVhdOffset, cbRead));
    2393                 rc = pImage->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser,
    2394                                                                      pImage->pStorage,
    2395                                                                      uVhdOffset, pIoCtx, cbRead);
     1685                cbBuf = cSectors * VHD_SECTOR_SIZE;
     1686
     1687                LogFlowFunc(("uVhdOffset=%llu cbBuf=%u\n", uVhdOffset, cbBuf));
     1688                rc = vhdFileReadSync(pImage, uVhdOffset, pvBuf, cbBuf, NULL);
    23961689            }
    23971690            else
     
    24081701                cSectors = 1;
    24091702
     1703                while (   (cSectors < (cbBuf / VHD_SECTOR_SIZE))
     1704                       && !vhdBlockBitmapSectorContainsData(pImage, cBATEntryIndex))
     1705                {
     1706                    cBATEntryIndex++;
     1707                    cSectors++;
     1708                }
     1709
     1710                cbBuf = cSectors * VHD_SECTOR_SIZE;
     1711                LogFunc(("Sectors free: uVhdOffset=%llu cbBuf=%u\n", uVhdOffset, cbBuf));
     1712                rc = VERR_VD_BLOCK_FREE;
     1713            }
     1714        }
     1715        else
     1716            AssertMsgFailed(("Reading block bitmap failed rc=%Rrc\n", rc));
     1717    }
     1718    else
     1719    {
     1720        rc = vhdFileReadSync(pImage, uOffset, pvBuf, cbBuf, NULL);
     1721    }
     1722
     1723    if (RT_SUCCESS(rc))
     1724    {
     1725        if (pcbActuallyRead)
     1726            *pcbActuallyRead = cbBuf;
     1727
     1728        Log2(("vhdRead: off=%#llx pvBuf=%p cbBuf=%d\n"
     1729                "%.*Rhxd\n",
     1730                uOffset, pvBuf, cbBuf, cbBuf, pvBuf));
     1731    }
     1732
     1733out:
     1734    LogFlowFunc(("returns %Rrc\n", rc));
     1735    return rc;
     1736}
     1737
     1738/** @copydoc VBOXHDDBACKEND::pfnWrite */
     1739static int vhdWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf,
     1740                    size_t cbBuf, size_t *pcbWriteProcess,
     1741                    size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite)
     1742{
     1743    LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbBuf=%zu pcbWriteProcess=%#p\n", pBackendData, uOffset, pvBuf, cbBuf, pcbWriteProcess));
     1744    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     1745    int rc = VINF_SUCCESS;
     1746
     1747    LogFlowFunc(("pBackendData=%p uOffset=%llu pvBuf=%p cbBuf=%u pcbWriteProcess=%p pcbPreRead=%p pcbPostRead=%p fWrite=%u\n",
     1748             pBackendData, uOffset, pvBuf, cbBuf, pcbWriteProcess, pcbPreRead, pcbPostRead, fWrite));
     1749
     1750    AssertPtr(pImage);
     1751    Assert(uOffset % VHD_SECTOR_SIZE == 0);
     1752    Assert(cbBuf % VHD_SECTOR_SIZE == 0);
     1753
     1754    if (pImage->pBlockAllocationTable)
     1755    {
     1756        /*
     1757         * Get the data block first.
     1758         */
     1759        uint32_t cSector = uOffset / VHD_SECTOR_SIZE;
     1760        uint32_t cBlockAllocationTableEntry = cSector / pImage->cSectorsPerDataBlock;
     1761        uint32_t cBATEntryIndex = cSector % pImage->cSectorsPerDataBlock;
     1762        uint64_t uVhdOffset;
     1763
     1764        /*
     1765         * Clip write range.
     1766         */
     1767        cbBuf = RT_MIN(cbBuf, (pImage->cbDataBlock - (cBATEntryIndex * VHD_SECTOR_SIZE)));
     1768
     1769        /*
     1770         * If the block is not allocated the content of the entry is ~0
     1771         * and we need to allocate a new block. Note that while blocks are
     1772         * allocated with a relatively big granularity, each sector has its
     1773         * own bitmap entry, indicating whether it has been written or not.
     1774         * So that means for the purposes of the higher level that the
     1775         * granularity is invisible. This means there's no need to return
     1776         * VERR_VD_BLOCK_FREE unless the block hasn't been allocated yet.
     1777         */
     1778        if (pImage->pBlockAllocationTable[cBlockAllocationTableEntry] == ~0U)
     1779        {
     1780            /* Check if the block allocation should be suppressed. */
     1781            if (fWrite & VD_WRITE_NO_ALLOC)
     1782            {
     1783                *pcbPreRead = cBATEntryIndex * VHD_SECTOR_SIZE;
     1784                *pcbPostRead = pImage->cSectorsPerDataBlock * VHD_SECTOR_SIZE - cbBuf - *pcbPreRead;
     1785
     1786                if (pcbWriteProcess)
     1787                    *pcbWriteProcess = cbBuf;
     1788                rc = VERR_VD_BLOCK_FREE;
     1789                goto out;
     1790            }
     1791
     1792            size_t  cbNewBlock = pImage->cbDataBlock + (pImage->cDataBlockBitmapSectors * VHD_SECTOR_SIZE);
     1793            uint8_t *pNewBlock = (uint8_t *)RTMemAllocZ(cbNewBlock);
     1794
     1795            if (!pNewBlock)
     1796            {
     1797                rc = VERR_NO_MEMORY;
     1798                goto out;
     1799            }
     1800
     1801            /*
     1802             * Write the new block at the current end of the file.
     1803             */
     1804            rc = vhdFileWriteSync(pImage, pImage->uCurrentEndOfFile,
     1805                                  pNewBlock, cbNewBlock, NULL);
     1806            AssertRC(rc);
     1807
     1808            /*
     1809             * Set the new end of the file and link the new block into the BAT.
     1810             */
     1811            pImage->pBlockAllocationTable[cBlockAllocationTableEntry] = pImage->uCurrentEndOfFile / VHD_SECTOR_SIZE;
     1812            pImage->uCurrentEndOfFile += cbNewBlock;
     1813            RTMemFree(pNewBlock);
     1814
     1815            /* Write the updated BAT and the footer to remain in a consistent state. */
     1816            rc = vhdFlushImage(pImage);
     1817            AssertRC(rc);
     1818        }
     1819
     1820        /*
     1821         * Calculate the real offset in the file.
     1822         */
     1823        uVhdOffset = ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry] + pImage->cDataBlockBitmapSectors + cBATEntryIndex) * VHD_SECTOR_SIZE;
     1824
     1825        /* Write data. */
     1826        vhdFileWriteSync(pImage, uVhdOffset, pvBuf, cbBuf, NULL);
     1827
     1828        /* Read in the block's bitmap. */
     1829        rc = vhdFileReadSync(pImage,
     1830                             ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE,
     1831                             pImage->pu8Bitmap, pImage->cbDataBlockBitmap,
     1832                             NULL);
     1833        if (RT_SUCCESS(rc))
     1834        {
     1835            bool fChanged = false;
     1836
     1837            /* Set the bits for all sectors having been written. */
     1838            for (uint32_t iSector = 0; iSector < (cbBuf / VHD_SECTOR_SIZE); iSector++)
     1839            {
     1840                fChanged |= vhdBlockBitmapSectorSet(pImage, pImage->pu8Bitmap, cBATEntryIndex);
     1841                cBATEntryIndex++;
     1842            }
     1843
     1844            if (fChanged)
     1845            {
     1846                /* Write the bitmap back. */
     1847                rc = vhdFileWriteSync(pImage,
     1848                                      ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE,
     1849                                      pImage->pu8Bitmap, pImage->cbDataBlockBitmap,
     1850                                      NULL);
     1851            }
     1852        }
     1853    }
     1854    else
     1855    {
     1856        rc = vhdFileWriteSync(pImage, uOffset, pvBuf, cbBuf, NULL);
     1857    }
     1858
     1859    if (pcbWriteProcess)
     1860        *pcbWriteProcess = cbBuf;
     1861
     1862    /* Stay on the safe side. Do not run the risk of confusing the higher
     1863     * level, as that can be pretty lethal to image consistency. */
     1864    *pcbPreRead = 0;
     1865    *pcbPostRead = 0;
     1866
     1867out:
     1868    LogFlowFunc(("returns %Rrc\n", rc));
     1869    return rc;
     1870}
     1871
     1872/** @copydoc VBOXHDDBACKEND::pfnFlush */
     1873static int vhdFlush(void *pBackendData)
     1874{
     1875    LogFlowFunc(("pBackendData=%#p", pBackendData));
     1876    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     1877    int rc;
     1878
     1879    rc = vhdFlushImage(pImage);
     1880    LogFlowFunc(("returns %Rrc\n", rc));
     1881    return rc;
     1882}
     1883
     1884/** @copydoc VBOXHDDBACKEND::pfnGetVersion */
     1885static unsigned vhdGetVersion(void *pBackendData)
     1886{
     1887    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     1888    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     1889    unsigned ver = 0;
     1890
     1891    AssertPtr(pImage);
     1892
     1893    if (pImage)
     1894        ver = 1; /**< @todo use correct version */
     1895
     1896    LogFlowFunc(("returns %u\n", ver));
     1897    return ver;
     1898}
     1899
     1900/** @copydoc VBOXHDDBACKEND::pfnGetSize */
     1901static uint64_t vhdGetSize(void *pBackendData)
     1902{
     1903    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     1904    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     1905    uint64_t cb = 0;
     1906
     1907    AssertPtr(pImage);
     1908
     1909    if (pImage && pImage->pStorage)
     1910        cb = pImage->cbSize;
     1911
     1912    LogFlowFunc(("returns %llu\n", cb));
     1913    return cb;
     1914}
     1915
     1916/** @copydoc VBOXHDDBACKEND::pfnGetFileSize */
     1917static uint64_t vhdGetFileSize(void *pBackendData)
     1918{
     1919    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     1920    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     1921    uint64_t cb = 0;
     1922
     1923    AssertPtr(pImage);
     1924
     1925    if (pImage && pImage->pStorage)
     1926        cb = pImage->uCurrentEndOfFile + sizeof(VHDFooter);
     1927
     1928    LogFlowFunc(("returns %lld\n", cb));
     1929    return cb;
     1930}
     1931
     1932/** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */
     1933static int vhdGetPCHSGeometry(void *pBackendData, PVDGEOMETRY pPCHSGeometry)
     1934{
     1935    LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry));
     1936    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     1937    int rc;
     1938
     1939    AssertPtr(pImage);
     1940
     1941    if (pImage)
     1942    {
     1943        if (pImage->PCHSGeometry.cCylinders)
     1944        {
     1945            *pPCHSGeometry = pImage->PCHSGeometry;
     1946            rc = VINF_SUCCESS;
     1947        }
     1948        else
     1949            rc = VERR_VD_GEOMETRY_NOT_SET;
     1950    }
     1951    else
     1952        rc = VERR_VD_NOT_OPENED;
     1953
     1954    LogFlowFunc(("returns %Rrc (CHS=%u/%u/%u)\n", rc, pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors));
     1955    return rc;
     1956}
     1957
     1958/** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */
     1959static int vhdSetPCHSGeometry(void *pBackendData, PCVDGEOMETRY pPCHSGeometry)
     1960{
     1961    LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
     1962    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     1963    int rc;
     1964
     1965    AssertPtr(pImage);
     1966
     1967    if (pImage)
     1968    {
     1969        if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     1970        {
     1971            rc = VERR_VD_IMAGE_READ_ONLY;
     1972            goto out;
     1973        }
     1974
     1975        pImage->PCHSGeometry = *pPCHSGeometry;
     1976        rc = VINF_SUCCESS;
     1977    }
     1978    else
     1979        rc = VERR_VD_NOT_OPENED;
     1980
     1981out:
     1982    LogFlowFunc(("returns %Rrc\n", rc));
     1983    return rc;
     1984}
     1985
     1986/** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */
     1987static int vhdGetLCHSGeometry(void *pBackendData, PVDGEOMETRY pLCHSGeometry)
     1988{
     1989LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry));
     1990    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     1991    int rc;
     1992
     1993    AssertPtr(pImage);
     1994
     1995    if (pImage)
     1996    {
     1997        if (pImage->LCHSGeometry.cCylinders)
     1998        {
     1999            *pLCHSGeometry = pImage->LCHSGeometry;
     2000            rc = VINF_SUCCESS;
     2001        }
     2002        else
     2003            rc = VERR_VD_GEOMETRY_NOT_SET;
     2004    }
     2005    else
     2006        rc = VERR_VD_NOT_OPENED;
     2007
     2008    LogFlowFunc(("returns %Rrc (CHS=%u/%u/%u)\n", rc, pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors));
     2009    return rc;
     2010}
     2011
     2012/** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */
     2013static int vhdSetLCHSGeometry(void *pBackendData, PCVDGEOMETRY pLCHSGeometry)
     2014{
     2015    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2016    int rc;
     2017
     2018    AssertPtr(pImage);
     2019
     2020    if (pImage)
     2021    {
     2022        if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     2023        {
     2024            rc = VERR_VD_IMAGE_READ_ONLY;
     2025            goto out;
     2026        }
     2027
     2028        pImage->LCHSGeometry = *pLCHSGeometry;
     2029        rc = VINF_SUCCESS;
     2030    }
     2031    else
     2032        rc = VERR_VD_NOT_OPENED;
     2033
     2034out:
     2035    LogFlowFunc(("returns %Rrc\n", rc));
     2036    return rc;
     2037}
     2038
     2039/** @copydoc VBOXHDDBACKEND::pfnGetImageFlags */
     2040static unsigned vhdGetImageFlags(void *pBackendData)
     2041{
     2042    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     2043    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2044    unsigned uImageFlags;
     2045
     2046    AssertPtr(pImage);
     2047
     2048    if (pImage)
     2049        uImageFlags = pImage->uImageFlags;
     2050    else
     2051        uImageFlags = 0;
     2052
     2053    LogFlowFunc(("returns %#x\n", uImageFlags));
     2054    return uImageFlags;
     2055}
     2056
     2057/** @copydoc VBOXHDDBACKEND::pfnGetOpenFlags */
     2058static unsigned vhdGetOpenFlags(void *pBackendData)
     2059{
     2060    LogFlowFunc(("pBackendData=%#p\n", pBackendData));
     2061    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2062    unsigned uOpenFlags;
     2063
     2064    AssertPtr(pImage);
     2065
     2066    if (pImage)
     2067        uOpenFlags = pImage->uOpenFlags;
     2068    else
     2069        uOpenFlags = 0;
     2070
     2071    LogFlowFunc(("returns %#x\n", uOpenFlags));
     2072    return uOpenFlags;
     2073}
     2074
     2075/** @copydoc VBOXHDDBACKEND::pfnSetOpenFlags */
     2076static int vhdSetOpenFlags(void *pBackendData, unsigned uOpenFlags)
     2077{
     2078    LogFlowFunc(("pBackendData=%#p\n uOpenFlags=%#x", pBackendData, uOpenFlags));
     2079    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2080    int rc;
     2081
     2082    /* Image must be opened and the new flags must be valid. Just readonly and
     2083     * info flags are supported. */
     2084    if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE)))
     2085    {
     2086        rc = VERR_INVALID_PARAMETER;
     2087        goto out;
     2088    }
     2089
     2090    /* Implement this operation via reopening the image. */
     2091    rc = vhdFreeImage(pImage, false);
     2092    if (RT_FAILURE(rc))
     2093        goto out;
     2094    rc = vhdOpenImage(pImage, uOpenFlags);
     2095
     2096out:
     2097    LogFlowFunc(("returns %Rrc\n", rc));
     2098    return rc;
     2099}
     2100
     2101/** @copydoc VBOXHDDBACKEND::pfnGetComment */
     2102static int vhdGetComment(void *pBackendData, char *pszComment,
     2103                         size_t cbComment)
     2104{
     2105    LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment));
     2106    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2107    int rc;
     2108
     2109    AssertPtr(pImage);
     2110
     2111    if (pImage)
     2112        rc = VERR_NOT_SUPPORTED;
     2113    else
     2114        rc = VERR_VD_NOT_OPENED;
     2115
     2116    LogFlowFunc(("returns %Rrc comment='%s'\n", rc, pszComment));
     2117    return rc;
     2118}
     2119
     2120/** @copydoc VBOXHDDBACKEND::pfnSetComment */
     2121static int vhdSetComment(void *pBackendData, const char *pszComment)
     2122{
     2123    LogFlowFunc(("pBackendData=%#p pszComment=\"%s\"\n", pBackendData, pszComment));
     2124    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2125    int rc;
     2126
     2127    AssertPtr(pImage);
     2128
     2129    if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     2130    {
     2131        rc = VERR_VD_IMAGE_READ_ONLY;
     2132        goto out;
     2133    }
     2134
     2135    if (pImage)
     2136        rc = VERR_NOT_SUPPORTED;
     2137    else
     2138        rc = VERR_VD_NOT_OPENED;
     2139
     2140out:
     2141    LogFlowFunc(("returns %Rrc\n", rc));
     2142    return rc;
     2143}
     2144
     2145/** @copydoc VBOXHDDBACKEND::pfnGetUuid */
     2146static int vhdGetUuid(void *pBackendData, PRTUUID pUuid)
     2147{
     2148    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
     2149    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2150    int rc;
     2151
     2152    AssertPtr(pImage);
     2153
     2154    if (pImage)
     2155    {
     2156        *pUuid = pImage->ImageUuid;
     2157        rc = VINF_SUCCESS;
     2158    }
     2159    else
     2160        rc = VERR_VD_NOT_OPENED;
     2161
     2162    LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
     2163    return rc;
     2164}
     2165
     2166/** @copydoc VBOXHDDBACKEND::pfnSetUuid */
     2167static int vhdSetUuid(void *pBackendData, PCRTUUID pUuid)
     2168{
     2169    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
     2170    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2171    int rc;
     2172
     2173    AssertPtr(pImage);
     2174
     2175    if (pImage)
     2176    {
     2177        if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     2178        {
     2179            pImage->ImageUuid = *pUuid;
     2180            /* Update the footer copy. It will get written to disk when the image is closed. */
     2181            memcpy(&pImage->vhdFooterCopy.UniqueID, pUuid, 16);
     2182            /* Update checksum. */
     2183            pImage->vhdFooterCopy.Checksum = 0;
     2184            pImage->vhdFooterCopy.Checksum = RT_H2BE_U32(vhdChecksum(&pImage->vhdFooterCopy, sizeof(VHDFooter)));
     2185
     2186            /* Need to update the dynamic disk header to update the disk footer copy at the beginning. */
     2187            if (!(pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED))
     2188                pImage->fDynHdrNeedsUpdate = true;
     2189            rc = VINF_SUCCESS;
     2190        }
     2191        else
     2192            rc = VERR_VD_IMAGE_READ_ONLY;
     2193    }
     2194    else
     2195        rc = VERR_VD_NOT_OPENED;
     2196
     2197    LogFlowFunc(("returns %Rrc\n", rc));
     2198    return rc;
     2199}
     2200
     2201/** @copydoc VBOXHDDBACKEND::pfnGetModificationUuid */
     2202static int vhdGetModificationUuid(void *pBackendData, PRTUUID pUuid)
     2203{
     2204    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
     2205    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2206    int rc;
     2207
     2208    AssertPtr(pImage);
     2209
     2210    if (pImage)
     2211        rc = VERR_NOT_SUPPORTED;
     2212    else
     2213        rc = VERR_VD_NOT_OPENED;
     2214
     2215    LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
     2216    return rc;
     2217}
     2218
     2219/** @copydoc VBOXHDDBACKEND::pfnSetModificationUuid */
     2220static int vhdSetModificationUuid(void *pBackendData, PCRTUUID pUuid)
     2221{
     2222    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
     2223    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2224    int rc;
     2225
     2226    AssertPtr(pImage);
     2227
     2228    if (pImage)
     2229    {
     2230        if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     2231            rc = VERR_NOT_SUPPORTED;
     2232        else
     2233            rc = VERR_VD_IMAGE_READ_ONLY;
     2234    }
     2235    else
     2236        rc = VERR_VD_NOT_OPENED;
     2237
     2238    LogFlowFunc(("returns %Rrc\n", rc));
     2239    return rc;
     2240}
     2241
     2242/** @copydoc VBOXHDDBACKEND::pfnGetParentUuid */
     2243static int vhdGetParentUuid(void *pBackendData, PRTUUID pUuid)
     2244{
     2245    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
     2246    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2247    int rc;
     2248
     2249    AssertPtr(pImage);
     2250
     2251    if (pImage)
     2252    {
     2253        *pUuid = pImage->ParentUuid;
     2254        rc = VINF_SUCCESS;
     2255    }
     2256    else
     2257        rc = VERR_VD_NOT_OPENED;
     2258
     2259    LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
     2260    return rc;
     2261}
     2262
     2263/** @copydoc VBOXHDDBACKEND::pfnSetParentUuid */
     2264static int vhdSetParentUuid(void *pBackendData, PCRTUUID pUuid)
     2265{
     2266    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
     2267    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2268    int rc = VINF_SUCCESS;
     2269
     2270    AssertPtr(pImage);
     2271
     2272    if (pImage && pImage->pStorage)
     2273    {
     2274        if (!(pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED))
     2275        {
     2276            pImage->ParentUuid = *pUuid;
     2277            pImage->fDynHdrNeedsUpdate = true;
     2278        }
     2279        else
     2280            rc = VERR_VD_IMAGE_READ_ONLY;
     2281    }
     2282    else
     2283        rc = VERR_VD_NOT_OPENED;
     2284
     2285    LogFlowFunc(("returns %Rrc\n", rc));
     2286    return rc;
     2287}
     2288
     2289/** @copydoc VBOXHDDBACKEND::pfnGetParentModificationUuid */
     2290static int vhdGetParentModificationUuid(void *pBackendData, PRTUUID pUuid)
     2291{
     2292    LogFlowFunc(("pBackendData=%#p pUuid=%#p\n", pBackendData, pUuid));
     2293    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2294    int rc;
     2295
     2296    AssertPtr(pImage);
     2297
     2298    if (pImage)
     2299        rc = VERR_NOT_SUPPORTED;
     2300    else
     2301        rc = VERR_VD_NOT_OPENED;
     2302
     2303    LogFlowFunc(("returns %Rrc (%RTuuid)\n", rc, pUuid));
     2304    return rc;
     2305}
     2306
     2307/** @copydoc VBOXHDDBACKEND::pfnSetParentModificationUuid */
     2308static int vhdSetParentModificationUuid(void *pBackendData, PCRTUUID pUuid)
     2309{
     2310    LogFlowFunc(("pBackendData=%#p Uuid=%RTuuid\n", pBackendData, pUuid));
     2311    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2312    int rc;
     2313
     2314    AssertPtr(pImage);
     2315
     2316    if (pImage)
     2317    {
     2318        if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     2319            rc = VERR_NOT_SUPPORTED;
     2320        else
     2321            rc = VERR_VD_IMAGE_READ_ONLY;
     2322    }
     2323    else
     2324        rc = VERR_VD_NOT_OPENED;
     2325
     2326    LogFlowFunc(("returns %Rrc\n", rc));
     2327    return rc;
     2328}
     2329
     2330/** @copydoc VBOXHDDBACKEND::pfnDump */
     2331static void vhdDump(void *pBackendData)
     2332{
     2333    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2334
     2335    AssertPtr(pImage);
     2336    if (pImage)
     2337    {
     2338        vhdMessage(pImage, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n",
     2339                    pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors,
     2340                    pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors,
     2341                    VHD_SECTOR_SIZE);
     2342        vhdMessage(pImage, "Header: uuidCreation={%RTuuid}\n", &pImage->ImageUuid);
     2343        vhdMessage(pImage, "Header: uuidParent={%RTuuid}\n", &pImage->ParentUuid);
     2344    }
     2345}
     2346
     2347/** @copydoc VBOXHDDBACKEND::pfnGetTimestamp */
     2348static int vhdGetTimeStamp(void *pBackendData, PRTTIMESPEC pTimeStamp)
     2349{
     2350    int rc = VINF_SUCCESS;
     2351    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2352
     2353    AssertPtr(pImage);
     2354
     2355    if (pImage)
     2356        rc = vhdFileGetModificationTime(pImage, pImage->pszFilename, pTimeStamp);
     2357    else
     2358        rc = VERR_VD_NOT_OPENED;
     2359
     2360    LogFlowFunc(("returns %Rrc\n", rc));
     2361    return rc;
     2362}
     2363
     2364/** @copydoc VBOXHDDBACKEND::pfnGetParentTimeStamp */
     2365static int vhdGetParentTimeStamp(void *pBackendData, PRTTIMESPEC pTimeStamp)
     2366{
     2367    int rc = VINF_SUCCESS;
     2368    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2369
     2370    AssertPtr(pImage);
     2371
     2372    if (pImage)
     2373        vhdTime2RtTime(pTimeStamp, pImage->u32ParentTimeStamp);
     2374    else
     2375        rc = VERR_VD_NOT_OPENED;
     2376
     2377    LogFlowFunc(("returns %Rrc\n", rc));
     2378    return rc;
     2379}
     2380
     2381/** @copydoc VBOXHDDBACKEND::pfnSetParentTimeStamp */
     2382static int vhdSetParentTimeStamp(void *pBackendData, PCRTTIMESPEC pTimeStamp)
     2383{
     2384    int rc = VINF_SUCCESS;
     2385    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2386
     2387    AssertPtr(pImage);
     2388    if (pImage)
     2389    {
     2390        if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     2391            rc = VERR_VD_IMAGE_READ_ONLY;
     2392        else
     2393        {
     2394            pImage->u32ParentTimeStamp = vhdRtTime2VhdTime(pTimeStamp);
     2395            pImage->fDynHdrNeedsUpdate = true;
     2396        }
     2397    }
     2398    else
     2399        rc = VERR_VD_NOT_OPENED;
     2400
     2401    LogFlowFunc(("returns %Rrc\n", rc));
     2402    return rc;
     2403}
     2404
     2405/** @copydoc VBOXHDDBACKEND::pfnGetParentFilename */
     2406static int vhdGetParentFilename(void *pBackendData, char **ppszParentFilename)
     2407{
     2408    int rc = VINF_SUCCESS;
     2409    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2410
     2411    AssertPtr(pImage);
     2412    if (pImage)
     2413        *ppszParentFilename = RTStrDup(pImage->pszParentFilename);
     2414    else
     2415        rc = VERR_VD_NOT_OPENED;
     2416
     2417    LogFlowFunc(("returns %Rrc\n", rc));
     2418    return rc;
     2419}
     2420
     2421/** @copydoc VBOXHDDBACKEND::pfnSetParentFilename */
     2422static int vhdSetParentFilename(void *pBackendData, const char *pszParentFilename)
     2423{
     2424    int rc = VINF_SUCCESS;
     2425    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2426
     2427    AssertPtr(pImage);
     2428    if (pImage)
     2429    {
     2430        if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     2431            rc = VERR_VD_IMAGE_READ_ONLY;
     2432        else
     2433        {
     2434            if (pImage->pszParentFilename)
     2435                RTStrFree(pImage->pszParentFilename);
     2436            pImage->pszParentFilename = RTStrDup(pszParentFilename);
     2437            if (!pImage->pszParentFilename)
     2438                rc = VERR_NO_MEMORY;
     2439            else
     2440                pImage->fDynHdrNeedsUpdate = true;
     2441        }
     2442    }
     2443    else
     2444        rc = VERR_VD_NOT_OPENED;
     2445
     2446    LogFlowFunc(("returns %Rrc\n", rc));
     2447    return rc;
     2448}
     2449
     2450/** @copydoc VBOXHDDBACKEND::pfnIsAsyncIOSupported */
     2451static bool vhdIsAsyncIOSupported(void *pBackendData)
     2452{
     2453    return true;
     2454}
     2455
     2456/** @copydoc VBOXHDDBACKEND::pfnAsyncRead */
     2457static int vhdAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbRead,
     2458                        PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
     2459{
     2460    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
     2461    int rc = VINF_SUCCESS;
     2462
     2463    LogFlowFunc(("pBackendData=%p uOffset=%#llx pIoCtx=%#p cbRead=%u pcbActuallyRead=%p\n", pBackendData, uOffset, pIoCtx, cbRead, pcbActuallyRead));
     2464
     2465    if (uOffset + cbRead > pImage->cbSize)
     2466        return VERR_INVALID_PARAMETER;
     2467
     2468    /*
     2469     * If we have a dynamic disk image, we need to find the data block and sector to read.
     2470     */
     2471    if (pImage->pBlockAllocationTable)
     2472    {
     2473        /*
     2474         * Get the data block first.
     2475         */
     2476        uint32_t cBlockAllocationTableEntry = (uOffset / VHD_SECTOR_SIZE) / pImage->cSectorsPerDataBlock;
     2477        uint32_t cBATEntryIndex = (uOffset / VHD_SECTOR_SIZE) % pImage->cSectorsPerDataBlock;
     2478        uint64_t uVhdOffset;
     2479
     2480        LogFlowFunc(("cBlockAllocationTableEntry=%u cBatEntryIndex=%u\n", cBlockAllocationTableEntry, cBATEntryIndex));
     2481        LogFlowFunc(("BlockAllocationEntry=%u\n", pImage->pBlockAllocationTable[cBlockAllocationTableEntry]));
     2482
     2483        /*
     2484         * If the block is not allocated the content of the entry is ~0
     2485         */
     2486        if (pImage->pBlockAllocationTable[cBlockAllocationTableEntry] == ~0U)
     2487        {
     2488            /* Return block size as read. */
     2489            *pcbActuallyRead = RT_MIN(cbRead, pImage->cSectorsPerDataBlock * VHD_SECTOR_SIZE);
     2490            return VERR_VD_BLOCK_FREE;
     2491        }
     2492
     2493        uVhdOffset = ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry] + pImage->cDataBlockBitmapSectors + cBATEntryIndex) * VHD_SECTOR_SIZE;
     2494        LogFlowFunc(("uVhdOffset=%llu cbRead=%u\n", uVhdOffset, cbRead));
     2495
     2496        /*
     2497         * Clip read range to remain in this data block.
     2498         */
     2499        cbRead = RT_MIN(cbRead, (pImage->cbDataBlock - (cBATEntryIndex * VHD_SECTOR_SIZE)));
     2500
     2501        /* Read in the block's bitmap. */
     2502        PVDMETAXFER pMetaXfer;
     2503        rc = vhdFileReadMetaAsync(pImage,
     2504                                  ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE,
     2505                                  pImage->pu8Bitmap, pImage->cbDataBlockBitmap,
     2506                                  pIoCtx, &pMetaXfer, NULL, NULL);
     2507
     2508        if (RT_SUCCESS(rc))
     2509        {
     2510            uint32_t cSectors = 0;
     2511
     2512            vhdFileMetaXferRelease(pImage, pMetaXfer);
     2513            if (vhdBlockBitmapSectorContainsData(pImage, cBATEntryIndex))
     2514            {
     2515                cBATEntryIndex++;
     2516                cSectors = 1;
     2517
     2518                /*
     2519                 * The first sector being read is marked dirty, read as much as we
     2520                 * can from child. Note that only sectors that are marked dirty
     2521                 * must be read from child.
     2522                 */
     2523                while (   (cSectors < (cbRead / VHD_SECTOR_SIZE))
     2524                       && vhdBlockBitmapSectorContainsData(pImage, cBATEntryIndex))
     2525                {
     2526                    cBATEntryIndex++;
     2527                    cSectors++;
     2528                }
     2529
     2530                cbRead = cSectors * VHD_SECTOR_SIZE;
     2531
     2532                LogFlowFunc(("uVhdOffset=%llu cbRead=%u\n", uVhdOffset, cbRead));
     2533                rc = vhdFileReadUserAsync(pImage, uVhdOffset, pIoCtx, cbRead);
     2534            }
     2535            else
     2536            {
     2537                /*
     2538                 * The first sector being read is marked clean, so we should read from
     2539                 * our parent instead, but only as much as there are the following
     2540                 * clean sectors, because the block may still contain dirty sectors
     2541                 * further on. We just need to compute the number of clean sectors
     2542                 * and pass it to our caller along with the notification that they
     2543                 * should be read from the parent.
     2544                 */
     2545                cBATEntryIndex++;
     2546                cSectors = 1;
     2547
    24102548                while (   (cSectors < (cbRead / VHD_SECTOR_SIZE))
    24112549                       && !vhdBlockBitmapSectorContainsData(pImage, cBATEntryIndex))
     
    24162554
    24172555                cbRead = cSectors * VHD_SECTOR_SIZE;
    2418                 Log(("%s: Sectors free: uVhdOffset=%llu cbRead=%u\n", __FUNCTION__, uVhdOffset, cbRead));
     2556                LogFunc(("Sectors free: uVhdOffset=%llu cbRead=%u\n", uVhdOffset, cbRead));
    24192557                rc = VERR_VD_BLOCK_FREE;
    24202558            }
     
    24252563    else
    24262564    {
    2427         rc = pImage->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser,
    2428                                                              pImage->pStorage,
    2429                                                              uOffset, pIoCtx, cbRead);
     2565        rc = vhdFileReadUserAsync(pImage, uOffset, pIoCtx, cbRead);
    24302566    }
    24312567
     
    24372573}
    24382574
     2575/** @copydoc VBOXHDDBACKEND::pfnAsyncWrite */
    24392576static int vhdAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbWrite,
    24402577                         PVDIOCTX pIoCtx,
     
    25122649                 * Start with the sector bitmap.
    25132650                 */
    2514                 rc = pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pImage->pInterfaceIO->pvUser,
    2515                                                                       pImage->pStorage,
    2516                                                                       pImage->uCurrentEndOfFile,
    2517                                                                       pExpand->au8Bitmap, pImage->cbDataBlockBitmap, pIoCtx,
    2518                                                                       vhdAsyncExpansionDataBlockBitmapComplete, pExpand);
     2651                rc = vhdFileWriteMetaAsync(pImage, pImage->uCurrentEndOfFile,
     2652                                           pExpand->au8Bitmap,
     2653                                           pImage->cbDataBlockBitmap, pIoCtx,
     2654                                           vhdAsyncExpansionDataBlockBitmapComplete,
     2655                                           pExpand);
    25192656                if (RT_SUCCESS(rc))
    25202657                    VHDIMAGEEXPAND_STATUS_SET(pExpand->fFlags, VHDIMAGEEXPAND_BLOCKBITMAP_STATUS_SHIFT, VHDIMAGEEXPAND_STEP_SUCCESS);
     
    25342671                 * Write the new block at the current end of the file.
    25352672                 */
    2536                 rc = pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser,
    2537                                                                       pImage->pStorage,
    2538                                                                       pImage->uCurrentEndOfFile + pImage->cbDataBlockBitmap,
    2539                                                                       pIoCtx, cbWrite,
    2540                                                                       vhdAsyncExpansionDataComplete, pExpand);
     2673                rc = vhdFileWriteUserAsync(pImage,
     2674                                           pImage->uCurrentEndOfFile + pImage->cbDataBlockBitmap,
     2675                                           pIoCtx, cbWrite,
     2676                                           vhdAsyncExpansionDataComplete,
     2677                                           pExpand);
    25412678                if (RT_SUCCESS(rc))
    25422679                    VHDIMAGEEXPAND_STATUS_SET(pExpand->fFlags, VHDIMAGEEXPAND_USERBLOCK_STATUS_SHIFT, VHDIMAGEEXPAND_STEP_SUCCESS);
     
    25542691                 * Write entry in the BAT.
    25552692                 */
    2556                 rc = pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pImage->pInterfaceIO->pvUser,
    2557                                                                       pImage->pStorage,
    2558                                                                       pImage->uBlockAllocationTableOffset + cBlockAllocationTableEntry * sizeof(uint32_t),
    2559                                                                       &pExpand->idxBlockBe, sizeof(uint32_t), pIoCtx,
    2560                                                                       vhdAsyncExpansionBatUpdateComplete, pExpand);
     2693                rc = vhdFileWriteMetaAsync(pImage,
     2694                                           pImage->uBlockAllocationTableOffset + cBlockAllocationTableEntry * sizeof(uint32_t),
     2695                                           &pExpand->idxBlockBe,
     2696                                           sizeof(uint32_t), pIoCtx,
     2697                                           vhdAsyncExpansionBatUpdateComplete,
     2698                                           pExpand);
    25612699                if (RT_SUCCESS(rc))
    25622700                    VHDIMAGEEXPAND_STATUS_SET(pExpand->fFlags, VHDIMAGEEXPAND_BAT_STATUS_SHIFT, VHDIMAGEEXPAND_STEP_SUCCESS);
     
    25772715
    25782716                /* Update the footer. */
    2579                 rc = pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pImage->pInterfaceIO->pvUser,
    2580                                                                       pImage->pStorage,
    2581                                                                       pImage->uCurrentEndOfFile,
    2582                                                                       &pImage->vhdFooterCopy, sizeof(VHDFooter), pIoCtx,
    2583                                                                       vhdAsyncExpansionFooterUpdateComplete, pExpand);
     2717                rc = vhdFileWriteMetaAsync(pImage, pImage->uCurrentEndOfFile,
     2718                                           &pImage->vhdFooterCopy,
     2719                                           sizeof(VHDFooter), pIoCtx,
     2720                                           vhdAsyncExpansionFooterUpdateComplete,
     2721                                           pExpand);
    25842722                if (RT_SUCCESS(rc))
    25852723                    VHDIMAGEEXPAND_STATUS_SET(pExpand->fFlags, VHDIMAGEEXPAND_FOOTER_STATUS_SHIFT, VHDIMAGEEXPAND_STEP_SUCCESS);
     
    26082746            /* Read in the block's bitmap. */
    26092747            PVDMETAXFER pMetaXfer;
    2610             rc = pImage->pInterfaceIOCallbacks->pfnReadMetaAsync(pImage->pInterfaceIO->pvUser,
    2611                                                                  pImage->pStorage,
    2612                                                                  ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE,
    2613                                                                  pImage->pu8Bitmap, pImage->cbDataBlockBitmap, pIoCtx, &pMetaXfer,
    2614                                                                 NULL, NULL);
     2748            rc = vhdFileReadMetaAsync(pImage,
     2749                                      ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE,
     2750                                      pImage->pu8Bitmap,
     2751                                      pImage->cbDataBlockBitmap, pIoCtx,
     2752                                      &pMetaXfer, NULL, NULL);
    26152753            if (RT_SUCCESS(rc))
    26162754            {
    2617                 pImage->pInterfaceIOCallbacks->pfnMetaXferRelease(pImage->pInterfaceIO->pvUser, pMetaXfer);
     2755                vhdFileMetaXferRelease(pImage, pMetaXfer);
    26182756
    26192757                /* Write data. */
    2620                 rc = pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser,
    2621                                                                       pImage->pStorage,
    2622                                                                       uVhdOffset, pIoCtx, cbWrite,
    2623                                                                       NULL, NULL);
     2758                rc = vhdFileWriteUserAsync(pImage, uVhdOffset, pIoCtx, cbWrite,
     2759                                           NULL, NULL);
    26242760                if (RT_SUCCESS(rc) || rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
    26252761                {
     
    26452781                         * to rollback anything here.
    26462782                         */
    2647                         rc = pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pImage->pInterfaceIO->pvUser,
    2648                                                                               pImage->pStorage,
    2649                                                                               ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE,
    2650                                                                               pImage->pu8Bitmap, pImage->cbDataBlockBitmap, pIoCtx,
    2651                                                                              NULL, NULL);
     2783                        rc = vhdFileWriteMetaAsync(pImage,
     2784                                                   ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE,
     2785                                                   pImage->pu8Bitmap,
     2786                                                   pImage->cbDataBlockBitmap,
     2787                                                   pIoCtx, NULL, NULL);
    26522788                    }
    26532789                }
     
    26572793    else
    26582794    {
    2659         rc = pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser,
    2660                                                               pImage->pStorage,
    2661                                                               uOffset, pIoCtx, cbWrite,
    2662                                                               NULL, NULL);
     2795        rc = vhdFileWriteUserAsync(pImage, uOffset, pIoCtx, cbWrite, NULL, NULL);
    26632796    }
    26642797
     
    26742807}
    26752808
    2676 static int vhdAsyncFlush(void *pvBackendData, PVDIOCTX pIoCtx)
    2677 {
    2678     PVHDIMAGE pImage = (PVHDIMAGE)pvBackendData;
     2809/** @copydoc VBOXHDDBACKEND::pfnAsyncFlush */
     2810static int vhdAsyncFlush(void *pBackendData, PVDIOCTX pIoCtx)
     2811{
     2812    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    26792813
    26802814    /* No need to write anything here. Data is always updated on a write. */
    2681     return pImage->pInterfaceIOCallbacks->pfnFlushAsync(pImage->pInterfaceIO->pvUser,
    2682                                                         pImage->pStorage, pIoCtx,
    2683                                                         NULL, NULL);
    2684 }
    2685 
     2815    return vhdFileFlushAsync(pImage, pIoCtx, NULL, NULL);
     2816}
    26862817
    26872818/** @copydoc VBOXHDDBACKEND::pfnResize */
    2688 static int vhdResize(void *pvBackendData, uint64_t cbSize,
    2689                      PCPDMMEDIAGEOMETRY pPCHSGeometry, PCPDMMEDIAGEOMETRY pLCHSGeometry,
     2819static int vhdResize(void *pBackendData, uint64_t cbSize,
     2820                     PCVDGEOMETRY pPCHSGeometry, PCVDGEOMETRY pLCHSGeometry,
    26902821                     unsigned uPercentStart, unsigned uPercentSpan,
    26912822                     PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
    26922823                     PVDINTERFACE pVDIfsOperation)
    26932824{
    2694     PVHDIMAGE pImage = (PVHDIMAGE)pvBackendData;
     2825    PVHDIMAGE pImage = (PVHDIMAGE)pBackendData;
    26952826    int rc = VINF_SUCCESS;
    26962827
     
    28783009    VD_CAP_UUID | VD_CAP_DIFF | VD_CAP_FILE |
    28793010    VD_CAP_CREATE_FIXED | VD_CAP_CREATE_DYNAMIC |
    2880     VD_CAP_ASYNC,
     3011    VD_CAP_ASYNC | VD_CAP_VFS,
    28813012    /* papszFileExtensions */
    28823013    s_apszVhdFileExtensions,
  • trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp

    r32195 r32536  
    11/* $Id$ */
    22/** @file
    3  * VMDK Disk image, Core Code.
     3 * VMDK disk image, core code.
    44 */
    55
     
    2727#include <iprt/alloc.h>
    2828#include <iprt/uuid.h>
    29 #include <iprt/file.h>
    3029#include <iprt/path.h>
    3130#include <iprt/string.h>
     
    142141    uint32_t cbSize;
    143142    uint32_t uType;
    144 } VMDKMARKER;
     143} VMDKMARKER, *PVMDKMARKER;
    145144#pragma pack()
    146145
     
    229228    /** File open flags for consistency checking. */
    230229    unsigned         fOpen;
    231     /** File handle. */
    232     RTFILE           File;
    233     /** Handle for asnychronous access if requested.*/
     230    /** Flag whether this file has been opened for async I/O. */
     231    bool             fAsyncIO;
     232    /** Handle for sync/async file abstraction.*/
    234233    PVDIOSTORAGE     pStorage;
    235     /** Flag whether to use File or pStorage. */
    236     bool             fAsyncIO;
    237234    /** Reference counter. */
    238235    unsigned         uReferences;
    239236    /** Flag whether the file should be deleted on last close. */
    240237    bool             fDelete;
    241     /** Pointer to the image we belong to. */
     238    /** Pointer to the image we belong to (for debugging purposes). */
    242239    PVMDKIMAGE       pImage;
    243240    /** Pointer to next file descriptor. */
     
    404401typedef struct VMDKIMAGE
    405402{
     403    /** Image name. */
     404    const char      *pszFilename;
     405    /** Descriptor file if applicable. */
     406    PVMDKFILE       pFile;
     407    /** I/O interface. */
     408    PVDINTERFACE    pInterfaceIO;
     409    /** I/O interface callbacks. */
     410    PVDINTERFACEIO  pInterfaceIOCallbacks;
     411
     412    /** Pointer to the per-disk VD interface list. */
     413    PVDINTERFACE    pVDIfsDisk;
     414    /** Pointer to the per-image VD interface list. */
     415    PVDINTERFACE    pVDIfsImage;
     416
     417    /** Error interface. */
     418    PVDINTERFACE    pInterfaceError;
     419    /** Error interface callbacks. */
     420    PVDINTERFACEERROR pInterfaceErrorCallbacks;
     421
    406422    /** Pointer to the image extents. */
    407423    PVMDKEXTENT     pExtents;
     
    412428    PVMDKFILE       pFiles;
    413429
    414     /** Base image name. */
    415     const char      *pszFilename;
    416     /** Descriptor file if applicable. */
    417     PVMDKFILE       pFile;
    418 
    419     /** Pointer to the per-disk VD interface list. */
    420     PVDINTERFACE    pVDIfsDisk;
    421     /** Pointer to the per-image VD interface list. */
    422     PVDINTERFACE    pVDIfsImage;
    423 
    424     /** Error interface. */
    425     PVDINTERFACE    pInterfaceError;
    426     /** Error interface callbacks. */
    427     PVDINTERFACEERROR pInterfaceErrorCallbacks;
    428 
    429     /** I/O interface. */
    430     PVDINTERFACE    pInterfaceIO;
    431     /** I/O interface callbacks. */
    432     PVDINTERFACEIO  pInterfaceIOCallbacks;
    433430    /**
    434431     * Pointer to an array of segment entries for async I/O.
     
    448445    uint64_t        cbSize;
    449446    /** Physical geometry of this image. */
    450     PDMMEDIAGEOMETRY   PCHSGeometry;
     447    VDGEOMETRY      PCHSGeometry;
    451448    /** Logical geometry of this image. */
    452     PDMMEDIAGEOMETRY   LCHSGeometry;
     449    VDGEOMETRY      LCHSGeometry;
    453450    /** Image UUID. */
    454451    RTUUID          ImageUuid;
     
    474471typedef struct VMDKINFLATESTATE
    475472{
     473    /* Image this operation relates to. */
     474    PVMDKIMAGE pImage;
    476475    /* File where the data is stored. */
    477     PVMDKFILE File;
     476    PVMDKFILE pFile;
    478477    /* Total size of the data to read. */
    479478    size_t cbSize;
     
    487486typedef struct VMDKDEFLATESTATE
    488487{
     488    /* Image this operation relates to. */
     489    PVMDKIMAGE pImage;
    489490    /* File where the data is to be stored. */
    490     PVMDKFILE File;
     491    PVMDKFILE pFile;
    491492    /* Offset in the file to write at. */
    492493    uint64_t uFileOffset;
     
    520521
    521522/*******************************************************************************
    522  *   Static Variables                                                           *
    523  *******************************************************************************/
     523*   Static Variables                                                           *
     524*******************************************************************************/
    524525
    525526/** NULL-terminated array of supported file extensions. */
     
    542543static int vmdkFlushImage(PVMDKIMAGE pImage);
    543544static int vmdkSetImageComment(PVMDKIMAGE pImage, const char *pszComment);
    544 static void vmdkFreeImage(PVMDKIMAGE pImage, bool fDelete);
    545 
    546 static int vmdkAllocGrainAsyncComplete(void *pvBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq);
     545static int vmdkFreeImage(PVMDKIMAGE pImage, bool fDelete);
     546
     547static int vmdkAllocGrainAsyncComplete(void *pBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq);
    547548
    548549/**
     
    562563
    563564/**
     565 * Internal: signal an informational message to the frontend.
     566 */
     567DECLINLINE(int) vmdkMessage(PVMDKIMAGE pImage, const char *pszFormat, ...)
     568{
     569    int rc = VINF_SUCCESS;
     570    va_list va;
     571    va_start(va, pszFormat);
     572    if (pImage->pInterfaceError && pImage->pInterfaceErrorCallbacks)
     573        rc = pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser,
     574                                                          pszFormat, va);
     575    va_end(va);
     576    return rc;
     577}
     578
     579/**
    564580 * Internal: open a file (using a file descriptor cache to ensure each file
    565581 * is only opened once - anything else can cause locking problems).
    566582 */
    567583static int vmdkFileOpen(PVMDKIMAGE pImage, PVMDKFILE *ppVmdkFile,
    568                         const char *pszFilename, unsigned fOpen, bool fAsyncIO)
     584                        const char *pszFilename, uint32_t fOpen, bool fAsyncIO)
    569585{
    570586    int rc = VINF_SUCCESS;
     
    602618    }
    603619    pVmdkFile->fOpen = fOpen;
    604 
    605 #ifndef VBOX_WITH_NEW_IO_CODE
    606     if ((pImage->uOpenFlags & VD_OPEN_FLAGS_ASYNC_IO) && (fAsyncIO))
    607     {
    608         rc = pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser,
    609                                                          pszFilename,
    610                                                          pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY
    611                                                            ? VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY
    612                                                            : 0,
    613                                                          NULL,
    614                                                          pImage->pVDIfsDisk,
    615                                                          &pVmdkFile->pStorage);
    616         pVmdkFile->fAsyncIO = true;
    617     }
    618     else
    619     {
    620         rc = RTFileOpen(&pVmdkFile->File, pszFilename, fOpen);
    621         pVmdkFile->fAsyncIO = false;
    622     }
    623 #else
    624     unsigned uOpenFlags = 0;
    625 
    626     if ((fOpen & RTFILE_O_ACCESS_MASK) == RTFILE_O_READ)
    627         uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY;
    628     if ((fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_CREATE)
    629         uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE;
    630     if ((fOpen & RTFILE_O_DENY_MASK) == RTFILE_O_DENY_NONE)
    631         uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_DONT_LOCK;
     620    pVmdkFile->fAsyncIO = fAsyncIO;
    632621
    633622    rc = pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser,
    634                                                 pszFilename,
    635                                                 uOpenFlags,
     623                                                pszFilename, fOpen,
    636624                                                &pVmdkFile->pStorage);
    637 #endif
    638625    if (RT_SUCCESS(rc))
    639626    {
     
    685672            pImage->pFiles = pNext;
    686673
    687 #ifndef VBOX_WITH_NEW_IO_CODE
    688         if (pVmdkFile->fAsyncIO)
    689         {
    690             rc = pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser,
    691                                                               pVmdkFile->pStorage);
    692         }
    693         else
    694         {
    695             rc = RTFileClose(pVmdkFile->File);
    696         }
    697 #else
    698674        rc = pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser,
    699675                                                     pVmdkFile->pStorage);
    700 #endif
    701676        if (RT_SUCCESS(rc) && pVmdkFile->fDelete)
    702             rc = RTFileDelete(pVmdkFile->pszFilename);
     677            rc = pImage->pInterfaceIOCallbacks->pfnDelete(pImage->pInterfaceIO->pvUser,
     678                                                          pVmdkFile->pszFilename);
    703679        RTStrFree((char *)(void *)pVmdkFile->pszFilename);
    704680        RTMemFree(pVmdkFile);
     
    710686
    711687/**
    712  * Internal: read from a file distinguishing between async and normal operation
     688 * Internal: rename a file (sync)
    713689 */
    714 DECLINLINE(int) vmdkFileReadAt(PVMDKFILE pVmdkFile,
    715                                uint64_t uOffset, void *pvBuf,
    716                                size_t cbToRead, size_t *pcbRead)
    717 {
    718     PVMDKIMAGE pImage = pVmdkFile->pImage;
    719 
    720 #ifndef VBOX_WITH_NEW_IO_CODE
    721     if (pVmdkFile->fAsyncIO)
    722         return pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser,
    723                                                           pVmdkFile->pStorage, uOffset,
    724                                                           cbToRead, pvBuf, pcbRead);
    725     else
    726         return RTFileReadAt(pVmdkFile->File, uOffset, pvBuf, cbToRead, pcbRead);
    727 #else
     690DECLINLINE(int) vmdkFileMove(PVMDKIMAGE pImage, const char *pszSrc,
     691                             const char *pszDst, unsigned fMove)
     692{
     693    return pImage->pInterfaceIOCallbacks->pfnMove(pImage->pInterfaceIO->pvUser,
     694                                                  pszSrc, pszDst, fMove);
     695}
     696
     697/**
     698 * Internal: get the size of a file (sync/async)
     699 */
     700DECLINLINE(int) vmdkFileGetSize(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile,
     701                                uint64_t *pcbSize)
     702{
     703    return pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser,
     704                                                     pVmdkFile->pStorage,
     705                                                     pcbSize);
     706}
     707
     708/**
     709 * Internal: set the size of a file (sync/async)
     710 */
     711DECLINLINE(int) vmdkFileSetSize(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile,
     712                                uint64_t cbSize)
     713{
     714    return pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser,
     715                                                     pVmdkFile->pStorage,
     716                                                     cbSize);
     717}
     718
     719/**
     720 * Internal: read from a file (sync)
     721 */
     722DECLINLINE(int) vmdkFileReadSync(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile,
     723                                 uint64_t uOffset, void *pvBuf,
     724                                 size_t cbToRead, size_t *pcbRead)
     725{
    728726    return pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser,
    729727                                                      pVmdkFile->pStorage, uOffset,
    730                                                       cbToRead, pvBuf, pcbRead);
    731 #endif
     728                                                      pvBuf, cbToRead, pcbRead);
    732729}
    733730
    734731/**
    735  * Internal: write to a file distinguishing between async and normal operation
     732 * Internal: write to a file (sync)
    736733 */
    737 DECLINLINE(int) vmdkFileWriteAt(PVMDKFILE pVmdkFile,
    738                                 uint64_t uOffset, const void *pvBuf,
    739                                 size_t cbToWrite, size_t *pcbWritten)
    740 {
    741     PVMDKIMAGE pImage = pVmdkFile->pImage;
    742 
    743 #ifndef VBOX_WITH_NEW_IO_CODE
    744     if (pVmdkFile->fAsyncIO)
    745         return pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser,
    746                                                                 pVmdkFile->pStorage, uOffset,
    747                                                                 cbToWrite, pvBuf, pcbWritten);
    748     else
    749         return RTFileWriteAt(pVmdkFile->File, uOffset, pvBuf, cbToWrite, pcbWritten);
    750 #else
    751         return pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser,
    752                                                                 pVmdkFile->pStorage, uOffset,
    753                                                                 cbToWrite, pvBuf, pcbWritten);
    754 #endif
     734DECLINLINE(int) vmdkFileWriteSync(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile,
     735                                  uint64_t uOffset, const void *pvBuf,
     736                                  size_t cbToWrite, size_t *pcbWritten)
     737{
     738    return pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser,
     739                                                       pVmdkFile->pStorage, uOffset,
     740                                                       pvBuf, cbToWrite, pcbWritten);
    755741}
    756742
    757743/**
    758  * Internal: get the size of a file distinguishing beween async and normal operation
     744 * Internal: flush a file (sync)
    759745 */
    760 DECLINLINE(int) vmdkFileGetSize(PVMDKFILE pVmdkFile, uint64_t *pcbSize)
    761 {
    762     PVMDKIMAGE pImage = pVmdkFile->pImage;
    763 
    764 #ifndef VBOX_WITH_NEW_IO_CODE
    765     if (pVmdkFile->fAsyncIO)
    766     {
    767         return pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser,
    768                                                               pVmdkFile->pStorage,
    769                                                               pcbSize);
    770     }
    771     else
    772         return RTFileGetSize(pVmdkFile->File, pcbSize);
    773 #else
    774     return pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser,
    775                                                             pVmdkFile->pStorage,
    776                                                             pcbSize);
    777 #endif
    778 }
    779 
    780 /**
    781  * Internal: set the size of a file distinguishing beween async and normal operation
    782  */
    783 DECLINLINE(int) vmdkFileSetSize(PVMDKFILE pVmdkFile, uint64_t cbSize)
    784 {
    785     PVMDKIMAGE pImage = pVmdkFile->pImage;
    786 
    787 #ifndef VBOX_WITH_NEW_IO_CODE
    788     if (pVmdkFile->fAsyncIO)
    789     {
    790         return pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser,
    791                                                               pVmdkFile->pStorage,
    792                                                               cbSize);
    793     }
    794     else
    795         return RTFileSetSize(pVmdkFile->File, cbSize);
    796 #else
    797     return pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser,
    798                                                           pVmdkFile->pStorage,
    799                                                           cbSize);
    800 #endif
    801 }
    802 
    803 /**
    804  * Internal: flush a file distinguishing between async and normal operation
    805  */
    806 DECLINLINE(int) vmdkFileFlush(PVMDKFILE pVmdkFile)
    807 {
    808     PVMDKIMAGE pImage = pVmdkFile->pImage;
    809 
    810 #ifndef VBOX_WITH_NEW_IO_CODE
    811     if (pVmdkFile->fAsyncIO)
    812         return pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser,
    813                                                            pVmdkFile->pStorage);
    814     else
    815         return RTFileFlush(pVmdkFile->File);
    816 #else
     746DECLINLINE(int) vmdkFileFlush(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile)
     747{
    817748    return pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser,
    818749                                                       pVmdkFile->pStorage);
    819 #endif
    820 }
    821 
    822 
    823 DECLINLINE(int) vmdkFileFlushAsync(PVMDKFILE pVmdkFile, PVDIOCTX pIoCtx)
    824 {
    825     PVMDKIMAGE pImage = pVmdkFile->pImage;
    826 
     750}
     751
     752/**
     753 * Internal: read user data (async)
     754 */
     755DECLINLINE(int) vmdkFileReadUserAsync(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile,
     756                                      uint64_t uOffset, PVDIOCTX pIoCtx,
     757                                      size_t cbRead)
     758{
     759    return pImage->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser,
     760                                                           pVmdkFile->pStorage,
     761                                                           uOffset, pIoCtx,
     762                                                           cbRead);
     763}
     764
     765/**
     766 * Internal: write user data (async)
     767 */
     768DECLINLINE(int) vmdkFileWriteUserAsync(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile,
     769                                       uint64_t uOffset, PVDIOCTX pIoCtx,
     770                                       size_t cbWrite,
     771                                       PFNVDXFERCOMPLETED pfnComplete,
     772                                       void *pvCompleteUser)
     773{
     774    return pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser,
     775                                                            pVmdkFile->pStorage,
     776                                                            uOffset, pIoCtx,
     777                                                            cbWrite,
     778                                                            pfnComplete,
     779                                                            pvCompleteUser);
     780}
     781
     782/**
     783 * Internal: read metadata (async)
     784 */
     785DECLINLINE(int) vmdkFileReadMetaAsync(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile,
     786                                      uint64_t uOffset, void *pvBuffer,
     787                                      size_t cbBuffer, PVDIOCTX pIoCtx,
     788                                      PPVDMETAXFER ppMetaXfer,
     789                                      PFNVDXFERCOMPLETED pfnComplete,
     790                                      void *pvCompleteUser)
     791{
     792    return pImage->pInterfaceIOCallbacks->pfnReadMetaAsync(pImage->pInterfaceIO->pvUser,
     793                                                           pVmdkFile->pStorage,
     794                                                           uOffset, pvBuffer,
     795                                                           cbBuffer, pIoCtx,
     796                                                           ppMetaXfer,
     797                                                           pfnComplete,
     798                                                           pvCompleteUser);
     799}
     800
     801/**
     802 * Internal: write metadata (async)
     803 */
     804DECLINLINE(int) vmdkFileWriteMetaAsync(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile,
     805                                       uint64_t uOffset, void *pvBuffer,
     806                                       size_t cbBuffer, PVDIOCTX pIoCtx,
     807                                       PFNVDXFERCOMPLETED pfnComplete,
     808                                       void *pvCompleteUser)
     809{
     810    return pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pImage->pInterfaceIO->pvUser,
     811                                                            pVmdkFile->pStorage,
     812                                                            uOffset, pvBuffer,
     813                                                            cbBuffer, pIoCtx,
     814                                                            pfnComplete,
     815                                                            pvCompleteUser);
     816}
     817
     818/**
     819 * Internal: releases a metadata transfer handle (async)
     820 */
     821DECLINLINE(void) vmdkFileMetaXferRelease(PVMDKIMAGE pImage, PVDMETAXFER pMetaXfer)
     822{
     823    pImage->pInterfaceIOCallbacks->pfnMetaXferRelease(pImage->pInterfaceIO->pvUser,
     824                                                      pMetaXfer);
     825}
     826
     827/**
     828 * Internal: flush a file (async)
     829 */
     830DECLINLINE(int) vmdkFileFlushAsync(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile,
     831                                   PVDIOCTX pIoCtx)
     832{
    827833    return pImage->pInterfaceIOCallbacks->pfnFlushAsync(pImage->pInterfaceIO->pvUser,
    828834                                                        pVmdkFile->pStorage, pIoCtx,
    829835                                                        NULL, NULL);
     836}
     837
     838/**
     839 * Internal: sets the buffer to a specific byte (async)
     840 */
     841DECLINLINE(int) vmdkFileIoCtxSet(PVMDKIMAGE pImage, PVDIOCTX pIoCtx,
     842                                 int ch, size_t cbSet)
     843{
     844    return pImage->pInterfaceIOCallbacks->pfnIoCtxSet(pImage->pInterfaceIO->pvUser,
     845                                                      pIoCtx, ch, cbSet);
    830846}
    831847
     
    845861    }
    846862    cbBuf = RT_MIN(cbBuf, pInflateState->cbSize);
    847     int rc = vmdkFileReadAt(pInflateState->File, pInflateState->uFileOffset, pvBuf, cbBuf, NULL);
     863    int rc = vmdkFileReadSync(pInflateState->pImage, pInflateState->pFile,
     864                              pInflateState->uFileOffset, pvBuf, cbBuf, NULL);
    848865    if (RT_FAILURE(rc))
    849866        return rc;
     
    860877 * distinguishing between async and normal operation
    861878 */
    862 DECLINLINE(int) vmdkFileInflateAt(PVMDKFILE pVmdkFile,
    863                                   uint64_t uOffset, void *pvBuf,
    864                                   size_t cbToRead, unsigned uMarker,
    865                                   uint64_t *puLBA, uint32_t *pcbMarkerData)
     879DECLINLINE(int) vmdkFileInflateSync(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile,
     880                                    uint64_t uOffset, void *pvBuf,
     881                                    size_t cbToRead, unsigned uMarker,
     882                                    uint64_t *puLBA, uint32_t *pcbMarkerData)
    866883{
    867884    if (pVmdkFile->fAsyncIO)
     
    882899        if (uMarker == VMDK_MARKER_IGNORE)
    883900            cbMarker -= sizeof(Marker.uType);
    884         rc = vmdkFileReadAt(pVmdkFile, uOffset, &Marker, cbMarker, NULL);
     901        rc = vmdkFileReadSync(pImage, pVmdkFile, uOffset, &Marker, cbMarker, NULL);
    885902        if (RT_FAILURE(rc))
    886903            return rc;
     
    924941            }
    925942        }
    926         InflateState.File = pVmdkFile;
     943        InflateState.pImage = pImage;
     944        InflateState.pFile = pVmdkFile;
    927945        InflateState.cbSize = cbComp;
    928946        InflateState.uFileOffset = uCompOffset;
     
    959977    if (!cbBuf)
    960978        return VINF_SUCCESS;
    961     int rc = vmdkFileWriteAt(pDeflateState->File, pDeflateState->uFileOffset, pvBuf, cbBuf, NULL);
     979    int rc = vmdkFileWriteSync(pDeflateState->pImage, pDeflateState->pFile,
     980                               pDeflateState->uFileOffset, pvBuf, cbBuf, NULL);
    962981    if (RT_FAILURE(rc))
    963982        return rc;
     
    971990 * distinguishing between async and normal operation
    972991 */
    973 DECLINLINE(int) vmdkFileDeflateAt(PVMDKFILE pVmdkFile,
    974                                   uint64_t uOffset, const void *pvBuf,
    975                                   size_t cbToWrite, unsigned uMarker,
    976                                   uint64_t uLBA, uint32_t *pcbMarkerData)
     992DECLINLINE(int) vmdkFileDeflateSync(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile,
     993                                    uint64_t uOffset, const void *pvBuf,
     994                                    size_t cbToWrite, unsigned uMarker,
     995                                    uint64_t uLBA, uint32_t *pcbMarkerData)
    977996{
    978997    if (pVmdkFile->fAsyncIO)
     
    10021021            return VERR_NOT_IMPLEMENTED;
    10031022        }
    1004         DeflateState.File = pVmdkFile;
     1023        DeflateState.pImage = pImage;
     1024        DeflateState.pFile = pVmdkFile;
    10051025        DeflateState.uFileOffset = uCompOffset;
    10061026        DeflateState.iOffset = -1;
     
    10281048             */
    10291049            uint64_t cbOld;
    1030             rc = vmdkFileGetSize(pVmdkFile, &cbOld);
     1050            rc = vmdkFileGetSize(pImage, pVmdkFile, &cbOld);
    10311051            if (RT_FAILURE(rc))
    10321052                return rc;
    10331053
    10341054            if (cbOld != DeflateState.uFileOffset)
    1035                 rc = vmdkFileSetSize(pVmdkFile, DeflateState.uFileOffset);
     1055                rc = vmdkFileSetSize(pImage, pVmdkFile, DeflateState.uFileOffset);
    10361056
    10371057            if (uMarker == VMDK_MARKER_IGNORE)
     
    10391059                /* Compressed grain marker. */
    10401060                Marker.cbSize = RT_H2LE_U32(DeflateState.iOffset);
    1041                 rc = vmdkFileWriteAt(pVmdkFile, uOffset, &Marker, 12, NULL);
     1061                rc = vmdkFileWriteSync(pImage, pVmdkFile, uOffset, &Marker, 12, NULL);
    10421062                if (RT_FAILURE(rc))
    10431063                    return rc;
     
    10701090        pImage->pFiles = pVmdkFile->pNext;
    10711091
    1072         if (pImage->uOpenFlags & VD_OPEN_FLAGS_ASYNC_IO)
    1073             rc2 = pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser,
    1074                                                                pVmdkFile->pStorage);
    1075         else
    1076             rc2 = vmdkFileClose(pImage, &pVmdkFile, pVmdkFile->fDelete);
     1092        rc2 = vmdkFileClose(pImage, &pVmdkFile, pVmdkFile->fDelete);
    10771093
    10781094        if (RT_SUCCESS(rc))
     
    11731189}
    11741190
    1175 static int vmdkReadGrainDirectory(PVMDKEXTENT pExtent)
     1191static int vmdkReadGrainDirectory(PVMDKIMAGE pImage, PVMDKEXTENT pExtent)
    11761192{
    11771193    int rc = VINF_SUCCESS;
     
    11921208    /* The VMDK 1.1 spec talks about compressed grain directories, but real
    11931209     * life files don't have them. The spec is wrong in creative ways. */
    1194     rc = vmdkFileReadAt(pExtent->pFile, VMDK_SECTOR2BYTE(pExtent->uSectorGD),
    1195                         pGD, cbGD, NULL);
     1210    rc = vmdkFileReadSync(pImage, pExtent->pFile,
     1211                          VMDK_SECTOR2BYTE(pExtent->uSectorGD),
     1212                          pGD, cbGD, NULL);
    11961213    AssertRC(rc);
    11971214    if (RT_FAILURE(rc))
    11981215    {
    1199         rc = vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: could not read grain directory in '%s': %Rrc"), pExtent->pszFullname);
     1216        rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not read grain directory in '%s': %Rrc"), pExtent->pszFullname);
    12001217        goto out;
    12011218    }
     
    12141231        /* The VMDK 1.1 spec talks about compressed grain directories, but real
    12151232         * life files don't have them. The spec is wrong in creative ways. */
    1216         rc = vmdkFileReadAt(pExtent->pFile, VMDK_SECTOR2BYTE(pExtent->uSectorRGD),
    1217                             pRGD, cbGD, NULL);
     1233        rc = vmdkFileReadSync(pImage, pExtent->pFile,
     1234                              VMDK_SECTOR2BYTE(pExtent->uSectorRGD),
     1235                              pRGD, cbGD, NULL);
    12181236        AssertRC(rc);
    12191237        if (RT_FAILURE(rc))
    12201238        {
    1221             rc = vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: could not read redundant grain directory in '%s'"), pExtent->pszFullname);
     1239            rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not read redundant grain directory in '%s'"), pExtent->pszFullname);
    12221240            goto out;
    12231241        }
     
    12561274                RTMemTmpFree(pTmpGT1);
    12571275                RTMemTmpFree(pTmpGT2);
    1258                 rc = vmdkError(pExtent->pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: inconsistent references to grain directory in '%s'"), pExtent->pszFullname);
     1276                rc = vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: inconsistent references to grain directory in '%s'"), pExtent->pszFullname);
    12591277                goto out;
    12601278            }
    12611279            /* The VMDK 1.1 spec talks about compressed grain tables, but real
    12621280             * life files don't have them. The spec is wrong in creative ways. */
    1263             rc = vmdkFileReadAt(pExtent->pFile, VMDK_SECTOR2BYTE(*pGDTmp),
    1264                                 pTmpGT1, cbGT, NULL);
     1281            rc = vmdkFileReadSync(pImage, pExtent->pFile,
     1282                                  VMDK_SECTOR2BYTE(*pGDTmp),
     1283                                  pTmpGT1, cbGT, NULL);
    12651284            if (RT_FAILURE(rc))
    12661285            {
    1267                 rc = vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error reading grain table in '%s'"), pExtent->pszFullname);
     1286                rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error reading grain table in '%s'"), pExtent->pszFullname);
    12681287                RTMemTmpFree(pTmpGT1);
    12691288                RTMemTmpFree(pTmpGT2);
     
    12721291            /* The VMDK 1.1 spec talks about compressed grain tables, but real
    12731292             * life files don't have them. The spec is wrong in creative ways. */
    1274             rc = vmdkFileReadAt(pExtent->pFile, VMDK_SECTOR2BYTE(*pRGDTmp),
    1275                                 pTmpGT2, cbGT, NULL);
     1293            rc = vmdkFileReadSync(pImage, pExtent->pFile,
     1294                                  VMDK_SECTOR2BYTE(*pRGDTmp),
     1295                                  pTmpGT2, cbGT, NULL);
    12761296            if (RT_FAILURE(rc))
    12771297            {
    1278                 rc = vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error reading backup grain table in '%s'"), pExtent->pszFullname);
     1298                rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error reading backup grain table in '%s'"), pExtent->pszFullname);
    12791299                RTMemTmpFree(pTmpGT1);
    12801300                RTMemTmpFree(pTmpGT2);
     
    12851305                RTMemTmpFree(pTmpGT1);
    12861306                RTMemTmpFree(pTmpGT2);
    1287                 rc = vmdkError(pExtent->pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: inconsistency between grain table and backup grain table in '%s'"), pExtent->pszFullname);
     1307                rc = vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: inconsistency between grain table and backup grain table in '%s'"), pExtent->pszFullname);
    12881308                goto out;
    12891309            }
     
    12951315    }
    12961316
    1297     if (pExtent->pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
     1317    if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
    12981318    {
    12991319        uint32_t uLastGrainWritten = 0;
     
    13141334            /* The VMDK 1.1 spec talks about compressed grain tables, but real
    13151335             * life files don't have them. The spec is wrong in creative ways. */
    1316             rc = vmdkFileReadAt(pExtent->pFile, VMDK_SECTOR2BYTE(*pGDTmp),
    1317                                 pTmpGT, cbGT, NULL);
     1336            rc = vmdkFileReadSync(pImage, pExtent->pFile,
     1337                                  VMDK_SECTOR2BYTE(*pGDTmp),
     1338                                  pTmpGT, cbGT, NULL);
    13181339            if (RT_FAILURE(rc))
    13191340            {
    1320                 rc = vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error reading grain table in '%s'"), pExtent->pszFullname);
     1341                rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error reading grain table in '%s'"), pExtent->pszFullname);
    13211342                RTMemTmpFree(pTmpGT);
    13221343                goto out;
     
    13341355                if (uLastGrainSector && uLastGrainSector >= uGTTmp)
    13351356                {
    1336                     rc = vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: grain table in '%s' contains a violation of the ordering assumptions"), pExtent->pszFullname);
     1357                    rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: grain table in '%s' contains a violation of the ordering assumptions"), pExtent->pszFullname);
    13371358                    RTMemTmpFree(pTmpGT);
    13381359                    goto out;
     
    13561377            uint64_t uLBA = 0;
    13571378            uint32_t cbMarker = 0;
    1358             rc = vmdkFileInflateAt(pExtent->pFile, VMDK_SECTOR2BYTE(uLastGrainSector),
    1359                                    pExtent->pvGrain, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain), VMDK_MARKER_IGNORE, &uLBA, &cbMarker);
     1379            rc = vmdkFileInflateSync(pImage, pExtent->pFile, VMDK_SECTOR2BYTE(uLastGrainSector),
     1380                                     pExtent->pvGrain, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain), VMDK_MARKER_IGNORE, &uLBA, &cbMarker);
    13601381            if (RT_FAILURE(rc))
    13611382                goto out;
     
    13751396}
    13761397
    1377 static int vmdkCreateGrainDirectory(PVMDKEXTENT pExtent, uint64_t uStartSector,
    1378                                     bool fPreAlloc)
     1398static int vmdkCreateGrainDirectory(PVMDKIMAGE pImage, PVMDKEXTENT pExtent,
     1399                                    uint64_t uStartSector, bool fPreAlloc)
    13791400{
    13801401    int rc = VINF_SUCCESS;
     
    14061427    pExtent->pRGD = pRGD;
    14071428
    1408     cbOverhead = RT_ALIGN_64(VMDK_SECTOR2BYTE(uStartSector) + 2 * (cbGDRounded + cbGTRounded), VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain));
    1409     /* For streamOptimized extents put the end-of-stream marker at the end. */
    1410     if (pExtent->pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
    1411         rc = vmdkFileSetSize(pExtent->pFile, cbOverhead + 512);
     1429    if (uStartSector != VMDK_GD_AT_END)
     1430    {
     1431        cbOverhead = RT_ALIGN_64(VMDK_SECTOR2BYTE(uStartSector) + 2 * (cbGDRounded + cbGTRounded), VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain));
     1432        /* For streamOptimized extents put the end-of-stream marker at the end. */
     1433        if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
     1434            rc = vmdkFileSetSize(pImage, pExtent->pFile, cbOverhead + 512);
     1435        else
     1436            rc = vmdkFileSetSize(pImage, pExtent->pFile, cbOverhead);
     1437        if (RT_FAILURE(rc))
     1438            goto out;
     1439        pExtent->uSectorRGD = uStartSector;
     1440        pExtent->uSectorGD = uStartSector + VMDK_BYTE2SECTOR(cbGDRounded + cbGTRounded);
     1441    }
    14121442    else
    1413         rc = vmdkFileSetSize(pExtent->pFile, cbOverhead);
    1414     if (RT_FAILURE(rc))
    1415         goto out;
    1416     pExtent->uSectorRGD = uStartSector;
    1417     pExtent->uSectorGD = uStartSector + VMDK_BYTE2SECTOR(cbGDRounded + cbGTRounded);
     1443    {
     1444        cbOverhead =  VMDK_SECTOR2BYTE(uStartSector);
     1445        pExtent->uSectorRGD = uStartSector;
     1446        pExtent->uSectorGD = uStartSector;
     1447    }
    14181448
    14191449    if (fPreAlloc)
     
    14281458            uGTSectorLE = RT_H2LE_U64(uOffsetSectors);
    14291459            /* Write the redundant grain directory entry to disk. */
    1430             rc = vmdkFileWriteAt(pExtent->pFile,
    1431                                  VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + i * sizeof(uGTSectorLE),
    1432                                  &uGTSectorLE, sizeof(uGTSectorLE), NULL);
     1460            rc = vmdkFileWriteSync(pImage, pExtent->pFile,
     1461                                   VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + i * sizeof(uGTSectorLE),
     1462                                   &uGTSectorLE, sizeof(uGTSectorLE), NULL);
    14331463            if (RT_FAILURE(rc))
    14341464            {
    1435                 rc = vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write new redundant grain directory entry in '%s'"), pExtent->pszFullname);
     1465                rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write new redundant grain directory entry in '%s'"), pExtent->pszFullname);
    14361466                goto out;
    14371467            }
     
    14451475            uGTSectorLE = RT_H2LE_U64(uOffsetSectors);
    14461476            /* Write the grain directory entry to disk. */
    1447             rc = vmdkFileWriteAt(pExtent->pFile,
    1448                                  VMDK_SECTOR2BYTE(pExtent->uSectorGD) + i * sizeof(uGTSectorLE),
    1449                                  &uGTSectorLE, sizeof(uGTSectorLE), NULL);
     1477            rc = vmdkFileWriteSync(pImage, pExtent->pFile,
     1478                                   VMDK_SECTOR2BYTE(pExtent->uSectorGD) + i * sizeof(uGTSectorLE),
     1479                                   &uGTSectorLE, sizeof(uGTSectorLE), NULL);
    14501480            if (RT_FAILURE(rc))
    14511481            {
    1452                 rc = vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write new grain directory entry in '%s'"), pExtent->pszFullname);
     1482                rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write new grain directory entry in '%s'"), pExtent->pszFullname);
    14531483                goto out;
    14541484            }
     
    14591489
    14601490    /* streamOptimized extents need a grain decompress buffer. */
    1461     if (pExtent->pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
     1491    if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
    14621492    {
    14631493        pExtent->pvGrain = RTMemAlloc(VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain));
     
    20432073
    20442074static int vmdkDescSetPCHSGeometry(PVMDKIMAGE pImage,
    2045                                    PCPDMMEDIAGEOMETRY pPCHSGeometry)
     2075                                   PCVDGEOMETRY pPCHSGeometry)
    20462076{
    20472077    int rc = vmdkDescDDBSetU32(pImage, &pImage->Descriptor,
     
    20622092
    20632093static int vmdkDescSetLCHSGeometry(PVMDKIMAGE pImage,
    2064                                    PCPDMMEDIAGEOMETRY pLCHSGeometry)
     2094                                   PCVDGEOMETRY pLCHSGeometry)
    20652095{
    20662096    int rc = vmdkDescDDBSetU32(pImage, &pImage->Descriptor,
     
    25652595    if (RT_SUCCESS(rc))
    25662596    {
    2567         rc = vmdkFileWriteAt(pDescFile, uOffset, pszDescriptor, cbLimit ? cbLimit : offDescriptor, NULL);
     2597        rc = vmdkFileWriteSync(pImage, pDescFile, uOffset, pszDescriptor, cbLimit ? cbLimit : offDescriptor, NULL);
    25682598        if (RT_FAILURE(rc))
    25692599            rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error writing descriptor in '%s'"), pImage->pszFilename);
     
    25722602    if (RT_SUCCESS(rc) && !cbLimit)
    25732603    {
    2574         rc = vmdkFileSetSize(pDescFile, offDescriptor);
     2604        rc = vmdkFileSetSize(pImage, pDescFile, offDescriptor);
    25752605        if (RT_FAILURE(rc))
    25762606            rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error truncating descriptor in '%s'"), pImage->pszFilename);
     
    26682698    if (RT_SUCCESS(rc))
    26692699    {
    2670         rc = vmdkFileWriteAt(pDescFile, uOffset, pszDescriptor, cbLimit ? cbLimit : offDescriptor, NULL);
     2700        rc = vmdkFileWriteSync(pImage, pDescFile, uOffset, pszDescriptor, cbLimit ? cbLimit : offDescriptor, NULL);
    26712701        if (RT_FAILURE(rc))
    26722702            rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error writing descriptor in '%s'"), pImage->pszFilename);
     
    26752705    if (RT_SUCCESS(rc) && !cbLimit)
    26762706    {
    2677         rc = vmdkFileSetSize(pDescFile, offDescriptor);
     2707        rc = vmdkFileSetSize(pImage, pDescFile, offDescriptor);
    26782708        if (RT_FAILURE(rc))
    26792709            rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error truncating descriptor in '%s'"), pImage->pszFilename);
     
    27252755    uint64_t cSectorsPerGDE;
    27262756
    2727     int rc = vmdkFileReadAt(pExtent->pFile, 0, &Header, sizeof(Header), NULL);
     2757    int rc = vmdkFileReadSync(pImage, pExtent->pFile, 0, &Header, sizeof(Header), NULL);
    27282758    AssertRC(rc);
    27292759    if (RT_FAILURE(rc))
     
    27422772         * VMware reality. Theory and practice have very little in common. */
    27432773        uint64_t cbSize;
    2744         rc = vmdkFileGetSize(pExtent->pFile, &cbSize);
     2774        rc = vmdkFileGetSize(pImage, pExtent->pFile, &cbSize);
    27452775        AssertRC(rc);
    27462776        if (RT_FAILURE(rc))
     
    27502780        }
    27512781        cbSize = RT_ALIGN_64(cbSize, 512);
    2752         rc = vmdkFileReadAt(pExtent->pFile, cbSize - 2*512, &Header, sizeof(Header), NULL);
     2782        rc = vmdkFileReadSync(pImage, pExtent->pFile, cbSize - 2*512, &Header, sizeof(Header), NULL);
    27532783        AssertRC(rc);
    27542784        if (RT_FAILURE(rc))
     
    28322862     * area (flat images only). If not, it means the image is at least
    28332863     * truncated, or even seriously garbled. */
    2834     rc = vmdkFileGetSize(pExtent->pFile, &cbExtentSize);
     2864    rc = vmdkFileGetSize(pImage, pExtent->pFile, &cbExtentSize);
    28352865    if (RT_FAILURE(rc))
    28362866    {
     
    28682898    }
    28692899
    2870     rc = vmdkReadGrainDirectory(pExtent);
     2900    rc = vmdkReadGrainDirectory(pImage, pExtent);
    28712901
    28722902out:
     
    28802910 * Internal: write/update the metadata for a sparse extent.
    28812911 */
    2882 static int vmdkWriteMetaSparseExtent(PVMDKEXTENT pExtent, uint64_t uOffset)
     2912static int vmdkWriteMetaSparseExtent(PVMDKIMAGE pImage, PVMDKEXTENT pExtent,
     2913                                     uint64_t uOffset)
    28832914{
    28842915    SparseExtentHeader Header;
     
    28902921    if (pExtent->pRGD)
    28912922        Header.flags |= RT_H2LE_U32(RT_BIT(1));
    2892     if (pExtent->pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
     2923    if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
    28932924        Header.flags |= RT_H2LE_U32(RT_BIT(16) | RT_BIT(17));
    28942925    Header.capacity = RT_H2LE_U64(pExtent->cSectors);
     
    29312962    Header.compressAlgorithm = RT_H2LE_U16(pExtent->uCompression);
    29322963
    2933     int rc = vmdkFileWriteAt(pExtent->pFile, uOffset, &Header, sizeof(Header), NULL);
     2964    int rc = vmdkFileWriteSync(pImage, pExtent->pFile, uOffset, &Header, sizeof(Header), NULL);
    29342965    AssertRC(rc);
    29352966    if (RT_FAILURE(rc))
    2936         rc = vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error writing extent header in '%s'"), pExtent->pszFullname);
     2967        rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error writing extent header in '%s'"), pExtent->pszFullname);
    29372968    return rc;
    29382969}
     
    29522983    if (pExtent->pRGD)
    29532984        Header.flags |= RT_H2LE_U32(RT_BIT(1));
    2954     if (pExtent->pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
     2985    if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
    29552986        Header.flags |= RT_H2LE_U32(RT_BIT(16) | RT_BIT(17));
    29562987    Header.capacity = RT_H2LE_U64(pExtent->cSectors);
     
    29933024    Header.compressAlgorithm = RT_H2LE_U16(pExtent->uCompression);
    29943025
    2995     int rc = pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pImage->pInterfaceIO->pvUser,
    2996                                                               pExtent->pFile->pStorage,
    2997                                                               uOffset, &Header, sizeof(Header),
    2998                                                               pIoCtx, NULL, NULL);
     3026    int rc = vmdkFileWriteMetaAsync(pImage, pExtent->pFile,
     3027                                    uOffset, &Header, sizeof(Header),
     3028                                    pIoCtx, NULL, NULL);
    29993029    if (RT_FAILURE(rc) && (rc != VERR_VD_ASYNC_IO_IN_PROGRESS))
    3000         rc = vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error writing extent header in '%s'"), pExtent->pszFullname);
     3030        rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error writing extent header in '%s'"), pExtent->pszFullname);
    30013031    return rc;
    30023032}
     
    30133043    uint64_t cSectorsPerGDE;
    30143044
    3015     int rc = vmdkFileReadAt(pExtent->pFile, 0, &Header, sizeof(Header), NULL);
     3045    int rc = vmdkFileReadSync(pImage, pExtent->pFile, 0, &Header, sizeof(Header), NULL);
    30163046    AssertRC(rc);
    30173047    if (RT_FAILURE(rc))
     
    30603090    pExtent->fUncleanShutdown = !!Header.uncleanShutdown;
    30613091
    3062     rc = vmdkReadGrainDirectory(pExtent);
     3092    rc = vmdkReadGrainDirectory(pImage, pExtent);
    30633093
    30643094out:
     
    31743204
    31753205/**
    3176  * Internal: Translate the VBoxHDD open flags to RTFile open flags.
    3177  */
    3178 static uint32_t vmdkFileOpenFlags(unsigned uOpenFlags)
    3179 {
    3180     uint32_t fDeny =   uOpenFlags & (VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_SHAREABLE)
    3181                      ? RTFILE_O_DENY_NONE
    3182                      : RTFILE_O_DENY_WRITE;
    3183     uint32_t fOpen =   uOpenFlags & VD_OPEN_FLAGS_READONLY
    3184                      ? RTFILE_O_READ
    3185                      : RTFILE_O_READWRITE;
    3186     fOpen |= RTFILE_O_OPEN | fDeny;
    3187     return fOpen;
    3188 }
    3189 
    3190 /**
    31913206 * Internal: Open an image, constructing all necessary data structures.
    31923207 */
     
    32053220        pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError);
    32063221
    3207     /* Try to get async I/O interface. */
     3222    /* Get I/O interface. */
    32083223    pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsImage, VDINTERFACETYPE_IO);
    3209     if (pImage->pInterfaceIO)
    3210         pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO);
     3224    AssertPtrReturn(pImage->pInterfaceIO, VERR_INVALID_PARAMETER);
     3225    pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO);
     3226    AssertPtrReturn(pImage->pInterfaceIOCallbacks, VERR_INVALID_PARAMETER);
    32113227
    32123228    /*
     
    32183234
    32193235    rc = vmdkFileOpen(pImage, &pFile, pImage->pszFilename,
    3220                       vmdkFileOpenFlags(uOpenFlags), false);
     3236                      VDOpenFlagsToFileOpenFlags(uOpenFlags, false /* fCreate */),
     3237                      false /* fAsyncIO */);
    32213238    if (RT_FAILURE(rc))
    32223239    {
     
    32283245
    32293246    /* Read magic (if present). */
    3230     rc = vmdkFileReadAt(pFile, 0, &u32Magic, sizeof(u32Magic), NULL);
     3247    rc = vmdkFileReadSync(pImage, pFile, 0, &u32Magic, sizeof(u32Magic), NULL);
    32313248    if (RT_FAILURE(rc))
    32323249    {
     
    32823299            goto out;
    32833300        }
    3284         rc = vmdkFileReadAt(pExtent->pFile,
    3285                             VMDK_SECTOR2BYTE(pExtent->uDescriptorSector),
    3286                             pExtent->pDescData,
    3287                             VMDK_SECTOR2BYTE(pExtent->cDescriptorSectors), NULL);
     3301        rc = vmdkFileReadSync(pImage, pExtent->pFile,
     3302                              VMDK_SECTOR2BYTE(pExtent->uDescriptorSector),
     3303                              pExtent->pDescData,
     3304                              VMDK_SECTOR2BYTE(pExtent->cDescriptorSectors), NULL);
    32883305        AssertRC(rc);
    32893306        if (RT_FAILURE(rc))
     
    33163333         * and will result in the correct "truncated read" error handling. */
    33173334        uint64_t cbFileSize;
    3318         rc = vmdkFileGetSize(pFile, &cbFileSize);
     3335        rc = vmdkFileGetSize(pImage, pFile, &cbFileSize);
    33193336        if (RT_FAILURE(rc))
    33203337            goto out;
     
    33353352
    33363353        size_t cbRead;
    3337         rc = vmdkFileReadAt(pImage->pFile, 0, pImage->pDescData,
    3338                             RT_MIN(pImage->cbDescAlloc, cbFileSize),
    3339                             &cbRead);
     3354        rc = vmdkFileReadSync(pImage, pImage->pFile, 0, pImage->pDescData,
     3355                              RT_MIN(pImage->cbDescAlloc, cbFileSize),
     3356                              &cbRead);
    33403357        if (RT_FAILURE(rc))
    33413358        {
     
    34333450                case VMDKETYPE_HOSTED_SPARSE:
    34343451                    rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname,
    3435                                       vmdkFileOpenFlags(uOpenFlags), false);
     3452                                      VDOpenFlagsToFileOpenFlags(uOpenFlags,
     3453                                                                 false /* fCreate */),
     3454                                      false /* fAsyncIO */);
    34363455                    if (RT_FAILURE(rc))
    34373456                    {
     
    34583477                case VMDKETYPE_FLAT:
    34593478                    rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname,
    3460                                       vmdkFileOpenFlags(uOpenFlags), true);
     3479                                      VDOpenFlagsToFileOpenFlags(uOpenFlags,
     3480                                                                 false /* fCreate */),
     3481                                      true /* fAsyncIO */);
    34613482                    if (RT_FAILURE(rc))
    34623483                    {
     
    35393560
    35403561/**
    3541  * Internal: Translate the VBoxHDD open flags to RTFile open/create flags.
    3542  */
    3543 static uint32_t vmdkFileCreateFlags(unsigned uOpenFlags)
    3544 {
    3545     uint32_t fDeny =   uOpenFlags & VD_OPEN_FLAGS_SHAREABLE
    3546                      ? RTFILE_O_DENY_NONE
    3547                      : RTFILE_O_DENY_WRITE;
    3548     uint32_t fOpen = RTFILE_O_READWRITE | RTFILE_O_NOT_CONTENT_INDEXED;
    3549     fOpen |= RTFILE_O_CREATE | fDeny;
    3550     return fOpen;
    3551 }
    3552 
    3553 /**
    35543562 * Internal: create VMDK images for raw disk/partition access.
    35553563 */
     
    35703578        /* Create raw disk descriptor file. */
    35713579        rc = vmdkFileOpen(pImage, &pImage->pFile, pImage->pszFilename,
    3572                           vmdkFileCreateFlags(pImage->uOpenFlags), false);
     3580                          VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags,
     3581                                                     true /* fCreate */),
     3582                          false /* fAsyncIO */);
    35733583        if (RT_FAILURE(rc))
    35743584            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pImage->pszFilename);
     
    35933603        /* Open flat image, the raw disk. */
    35943604        rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname,
    3595                           vmdkFileOpenFlags(pImage->uOpenFlags & ~VD_OPEN_FLAGS_READONLY),
    3596                           false);
     3605                          VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags & ~VD_OPEN_FLAGS_READONLY,
     3606                                                     false /* fCreate */),
     3607                          false /* fAsyncIO */);
    35973608        if (RT_FAILURE(rc))
    35983609            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not open raw disk file '%s'"), pExtent->pszFullname);
     
    36303641        /* Create raw partition descriptor file. */
    36313642        rc = vmdkFileOpen(pImage, &pImage->pFile, pImage->pszFilename,
    3632                           vmdkFileCreateFlags(pImage->uOpenFlags), false);
     3643                          VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags,
     3644                                                     true /* fCreate */),
     3645                          false /* fAsyncIO */);
    36333646        if (RT_FAILURE(rc))
    36343647            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pImage->pszFilename);
     
    37043717                /* Create partition table flat image. */
    37053718                rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname,
    3706                                   vmdkFileCreateFlags(pImage->uOpenFlags),
    3707                                   false);
     3719                                  VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags,
     3720                                                             true /* fCreate */),
     3721                                  false /* fAsyncIO */);
    37083722                if (RT_FAILURE(rc))
    37093723                    return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new partition data file '%s'"), pExtent->pszFullname);
    3710                 rc = vmdkFileWriteAt(pExtent->pFile,
    3711                                      VMDK_SECTOR2BYTE(uPartOffset),
    3712                                      pPart->pvPartitionData,
    3713                                      pPart->cbData, NULL);
     3724                rc = vmdkFileWriteSync(pImage, pExtent->pFile,
     3725                                       VMDK_SECTOR2BYTE(uPartOffset),
     3726                                       pPart->pvPartitionData,
     3727                                       pPart->cbData, NULL);
    37143728                if (RT_FAILURE(rc))
    37153729                    return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not write partition data to '%s'"), pExtent->pszFullname);
     
    37393753                    /* Open flat image, the raw partition. */
    37403754                    rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname,
    3741                                       vmdkFileOpenFlags(pImage->uOpenFlags & ~VD_OPEN_FLAGS_READONLY),
    3742                                       false);
     3755                                      VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags & ~VD_OPEN_FLAGS_READONLY,
     3756                                                                 false /* fCreate */),
     3757                                      false /* fAsyncIO */);
    37433758                    if (RT_FAILURE(rc))
    37443759                        return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not open raw partition file '%s'"), pExtent->pszFullname);
     
    38123827    {
    38133828        rc = vmdkFileOpen(pImage, &pImage->pFile, pImage->pszFilename,
    3814                           vmdkFileCreateFlags(pImage->uOpenFlags), false);
     3829                          VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags,
     3830                                                     true /* fCreate */),
     3831                          false /* fAsyncIO */);
    38153832        if (RT_FAILURE(rc))
    38163833            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new sparse descriptor file '%s'"), pImage->pszFilename);
     
    38813898        /* Create file for extent. */
    38823899        rc = vmdkFileOpen(pImage, &pExtent->pFile, pExtent->pszFullname,
    3883                           vmdkFileCreateFlags(pImage->uOpenFlags), false);
     3900                          VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags,
     3901                                                     true /* fCreate */),
     3902                          false /* fAsyncIO */);
    38843903        if (RT_FAILURE(rc))
    38853904            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pExtent->pszFullname);
    38863905        if (uImageFlags & VD_IMAGE_FLAGS_FIXED)
    38873906        {
    3888             rc = vmdkFileSetSize(pExtent->pFile, cbExtent);
     3907            rc = vmdkFileSetSize(pImage, pExtent->pFile, cbExtent);
    38893908            if (RT_FAILURE(rc))
    38903909                return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not set size of new file '%s'"), pExtent->pszFullname);
     
    39093928                unsigned cbChunk = (unsigned)RT_MIN(cbExtent, cbBuf);
    39103929
    3911                 rc = vmdkFileWriteAt(pExtent->pFile, uOff, pvBuf, cbChunk, NULL);
     3930                rc = vmdkFileWriteSync(pImage, pExtent->pFile, uOff, pvBuf, cbChunk, NULL);
    39123931                if (RT_FAILURE(rc))
    39133932                {
     
    39463965            uint64_t cSectorsPerGDE, cSectorsPerGD;
    39473966            pExtent->enmType = VMDKETYPE_HOSTED_SPARSE;
    3948             pExtent->cSectors = VMDK_BYTE2SECTOR(RT_ALIGN_64(cbExtent, 65536));
    3949             pExtent->cSectorsPerGrain = VMDK_BYTE2SECTOR(65536);
     3967            pExtent->cSectors = VMDK_BYTE2SECTOR(RT_ALIGN_64(cbExtent, _64K));
     3968            pExtent->cSectorsPerGrain = VMDK_BYTE2SECTOR(_64K);
    39503969            pExtent->cGTEntries = 512;
    39513970            cSectorsPerGDE = pExtent->cGTEntries * pExtent->cSectorsPerGrain;
     
    39793998        {
    39803999            /* fPreAlloc should never be false because VMware can't use such images. */
    3981             rc = vmdkCreateGrainDirectory(pExtent,
     4000            rc = vmdkCreateGrainDirectory(pImage, pExtent,
    39824001                                          RT_MAX(  pExtent->uDescriptorSector
    39834002                                                 + pExtent->cDescriptorSectors,
     
    40364055static int vmdkCreateImage(PVMDKIMAGE pImage, uint64_t cbSize,
    40374056                           unsigned uImageFlags, const char *pszComment,
    4038                            PCPDMMEDIAGEOMETRY pPCHSGeometry,
    4039                            PCPDMMEDIAGEOMETRY pLCHSGeometry, PCRTUUID pUuid,
     4057                           PCVDGEOMETRY pPCHSGeometry,
     4058                           PCVDGEOMETRY pLCHSGeometry, PCRTUUID pUuid,
    40404059                           PFNVDPROGRESS pfnProgress, void *pvUser,
    40414060                           unsigned uPercentStart, unsigned uPercentSpan)
     
    40504069        pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError);
    40514070
    4052     /* Try to get async I/O interface. */
     4071    /* Get I/O interface. */
    40534072    pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsImage, VDINTERFACETYPE_IO);
    4054     if (pImage->pInterfaceIO)
    4055         pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO);
     4073    AssertPtrReturn(pImage->pInterfaceIO, VERR_INVALID_PARAMETER);
     4074    pImage->pInterfaceIOCallbacks = VDGetInterfaceIO(pImage->pInterfaceIO);
     4075    AssertPtrReturn(pImage->pInterfaceIOCallbacks, VERR_INVALID_PARAMETER);
    40564076
    40574077    rc = vmdkCreateDescriptor(pImage, pImage->pDescData, pImage->cbDescAlloc,
     
    40824102
    40834103    if (RT_FAILURE(rc))
    4084 
    40854104        goto out;
    40864105
     
    42124231 * delete the image from disk.
    42134232 */
    4214 static void vmdkFreeImage(PVMDKIMAGE pImage, bool fDelete)
    4215 {
    4216     AssertPtr(pImage);
    4217 
    4218     if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
    4219     {
    4220         /* Mark all extents as clean. */
    4221         for (unsigned i = 0; i < pImage->cExtents; i++)
    4222         {
    4223             if ((   pImage->pExtents[i].enmType == VMDKETYPE_HOSTED_SPARSE
     4233static int vmdkFreeImage(PVMDKIMAGE pImage, bool fDelete)
     4234{
     4235    int rc = VINF_SUCCESS;
     4236
     4237    /* Freeing a never allocated image (e.g. because the open failed) is
     4238     * not signalled as an error. After all nothing bad happens. */
     4239    if (pImage)
     4240    {
     4241        if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     4242        {
     4243            /* Mark all extents as clean. */
     4244            for (unsigned i = 0; i < pImage->cExtents; i++)
     4245            {
     4246                if (   (   pImage->pExtents[i].enmType == VMDKETYPE_HOSTED_SPARSE
    42244247#ifdef VBOX_WITH_VMDK_ESX
    4225                  || pImage->pExtents[i].enmType == VMDKETYPE_ESX_SPARSE
     4248                        || pImage->pExtents[i].enmType == VMDKETYPE_ESX_SPARSE
    42264249#endif /* VBOX_WITH_VMDK_ESX */
    4227                 )
    4228                 &&  pImage->pExtents[i].fUncleanShutdown)
    4229             {
    4230                 pImage->pExtents[i].fUncleanShutdown = false;
    4231                 pImage->pExtents[i].fMetaDirty = true;
     4250                       )
     4251                    && pImage->pExtents[i].fUncleanShutdown)
     4252                {
     4253                    pImage->pExtents[i].fUncleanShutdown = false;
     4254                    pImage->pExtents[i].fMetaDirty = true;
     4255                }
    42324256            }
    42334257        }
    4234     }
    4235     (void)vmdkFlushImage(pImage);
    4236 
    4237     if (pImage->pExtents != NULL)
    4238     {
    4239         for (unsigned i = 0 ; i < pImage->cExtents; i++)
    4240             vmdkFreeExtentData(pImage, &pImage->pExtents[i], fDelete);
    4241         RTMemFree(pImage->pExtents);
    4242         pImage->pExtents = NULL;
    4243     }
    4244     pImage->cExtents = 0;
    4245     if (pImage->pFile != NULL)
    4246         vmdkFileClose(pImage, &pImage->pFile, fDelete);
    4247     vmdkFileCheckAllClose(pImage);
    4248     if (pImage->pGTCache)
    4249     {
    4250         RTMemFree(pImage->pGTCache);
    4251         pImage->pGTCache = NULL;
    4252     }
    4253     if (pImage->pDescData)
    4254     {
    4255         RTMemFree(pImage->pDescData);
    4256         pImage->pDescData = NULL;
    4257     }
     4258        vmdkFlushImage(pImage);
     4259
     4260        if (pImage->pExtents != NULL)
     4261        {
     4262            for (unsigned i = 0 ; i < pImage->cExtents; i++)
     4263                vmdkFreeExtentData(pImage, &pImage->pExtents[i], fDelete);
     4264            RTMemFree(pImage->pExtents);
     4265            pImage->pExtents = NULL;
     4266        }
     4267        pImage->cExtents = 0;
     4268        if (pImage->pFile != NULL)
     4269            vmdkFileClose(pImage, &pImage->pFile, fDelete);
     4270        vmdkFileCheckAllClose(pImage);
     4271
     4272        if (pImage->pGTCache)
     4273        {
     4274            RTMemFree(pImage->pGTCache);
     4275            pImage->pGTCache = NULL;
     4276        }
     4277        if (pImage->pDescData)
     4278        {
     4279            RTMemFree(pImage->pDescData);
     4280            pImage->pDescData = NULL;
     4281        }
     4282    }
     4283
     4284    LogFlowFunc(("returns %Rrc\n", rc));
     4285    return rc;
    42584286}
    42594287
     
    42824310            {
    42834311                case VMDKETYPE_HOSTED_SPARSE:
    4284                     rc = vmdkWriteMetaSparseExtent(pExtent, 0);
     4312                    rc = vmdkWriteMetaSparseExtent(pImage, pExtent, 0);
    42854313                    if (RT_FAILURE(rc))
    42864314                        goto out;
     
    42884316                    {
    42894317                        uint64_t cbSize;
    4290                         rc = vmdkFileGetSize(pExtent->pFile, &cbSize);
     4318                        rc = vmdkFileGetSize(pImage, pExtent->pFile, &cbSize);
    42914319                        if (RT_FAILURE(rc))
    42924320                            goto out;
    42934321                        cbSize = RT_ALIGN_64(cbSize, 512);
    4294                         rc = vmdkWriteMetaSparseExtent(pExtent, cbSize - 2*512);
     4322                        rc = vmdkWriteMetaSparseExtent(pImage, pExtent, cbSize - 2*512);
    42954323                        if (RT_FAILURE(rc))
    42964324                            goto out;
     
    43254353                    && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    43264354                    && !(pExtent->pszBasename[0] == RTPATH_SLASH))
    4327                     rc = vmdkFileFlush(pExtent->pFile);
     4355                    rc = vmdkFileFlush(pImage, pExtent->pFile);
    43284356                break;
    43294357            case VMDKETYPE_ZERO:
     
    43944422                    && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    43954423                    && !(pExtent->pszBasename[0] == RTPATH_SLASH))
    4396                     rc = vmdkFileFlushAsync(pExtent->pFile, pIoCtx);
     4424                    rc = vmdkFileFlushAsync(pImage, pExtent->pFile, pIoCtx);
    43974425                break;
    43984426            case VMDKETYPE_ZERO:
     
    44524480 * number in the extent.
    44534481 */
    4454 static int vmdkGetSector(PVMDKGTCACHE pCache, PVMDKEXTENT pExtent,
     4482static int vmdkGetSector(PVMDKIMAGE pImage, PVMDKEXTENT pExtent,
    44554483                         uint64_t uSector, uint64_t *puExtentSector)
    44564484{
     4485    PVMDKGTCACHE pCache = pImage->pGTCache;
    44574486    uint64_t uGDIndex, uGTSector, uGTBlock;
    44584487    uint32_t uGTHash, uGTBlockIndex;
     
    44804509    {
    44814510        /* Cache miss, fetch data from disk. */
    4482         rc = vmdkFileReadAt(pExtent->pFile,
    4483                             VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
    4484                             aGTDataTmp, sizeof(aGTDataTmp), NULL);
     4511        rc = vmdkFileReadSync(pImage, pExtent->pFile,
     4512                              VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
     4513                              aGTDataTmp, sizeof(aGTDataTmp), NULL);
    44854514        if (RT_FAILURE(rc))
    4486             return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot read grain table entry in '%s'"), pExtent->pszFullname);
     4515            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot read grain table entry in '%s'"), pExtent->pszFullname);
    44874516        pGTCacheEntry->uExtent = pExtent->uExtent;
    44884517        pGTCacheEntry->uGTBlock = uGTBlock;
     
    45044533 */
    45054534static int vmdkGetSectorAsync(PVMDKIMAGE pImage, PVDIOCTX pIoCtx,
    4506                               PVMDKGTCACHE pCache, PVMDKEXTENT pExtent,
    4507                               uint64_t uSector, uint64_t *puExtentSector)
    4508 {
     4535                              PVMDKEXTENT pExtent, uint64_t uSector,
     4536                              uint64_t *puExtentSector)
     4537{
     4538    PVMDKGTCACHE pCache = pImage->pGTCache;
    45094539    uint64_t uGDIndex, uGTSector, uGTBlock;
    45104540    uint32_t uGTHash, uGTBlockIndex;
     
    45354565        /* Cache miss, fetch data from disk. */
    45364566        PVDMETAXFER pMetaXfer;
    4537         rc = pImage->pInterfaceIOCallbacks->pfnReadMetaAsync(pImage->pInterfaceIO->pvUser,
    4538                                                              pExtent->pFile->pStorage,
    4539                                                              VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
    4540                                                              aGTDataTmp, sizeof(aGTDataTmp), pIoCtx, &pMetaXfer, NULL, NULL);
     4567        rc = vmdkFileReadMetaAsync(pImage, pExtent->pFile,
     4568                                   VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
     4569                                   aGTDataTmp, sizeof(aGTDataTmp), pIoCtx, &pMetaXfer, NULL, NULL);
    45414570        if (RT_FAILURE(rc))
    45424571            return rc;
    45434572        /* We can release the metadata transfer immediately. */
    4544         pImage->pInterfaceIOCallbacks->pfnMetaXferRelease(pImage->pInterfaceIO->pvUser, pMetaXfer);
     4573        vmdkFileMetaXferRelease(pImage, pMetaXfer);
    45454574        pGTCacheEntry->uExtent = pExtent->uExtent;
    45464575        pGTCacheEntry->uGTBlock = uGTBlock;
     
    45634592 * possible. Most code from vmdkGetSector also appears here.
    45644593 */
    4565 static int vmdkAllocGrain(PVMDKGTCACHE pCache, PVMDKEXTENT pExtent,
     4594static int vmdkAllocGrain(PVMDKIMAGE pImage, PVMDKEXTENT pExtent,
    45664595                          uint64_t uSector, const void *pvBuf,
    45674596                          uint64_t cbWrite)
    45684597{
     4598    PVMDKGTCACHE pCache = pImage->pGTCache;
    45694599    uint64_t uGDIndex, uGTSector, uRGTSector, uGTBlock;
    45704600    uint64_t cbExtentSize;
     
    45874617         * entry. So there is absolutely no data in this area. Allocate
    45884618         * a new grain table and put the reference to it in the GDs. */
    4589         rc = vmdkFileGetSize(pExtent->pFile, &cbExtentSize);
     4619        rc = vmdkFileGetSize(pImage, pExtent->pFile, &cbExtentSize);
    45904620        if (RT_FAILURE(rc))
    4591             return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname);
     4621            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname);
    45924622        Assert(!(cbExtentSize % 512));
    45934623        cbExtentSize = RT_ALIGN_64(cbExtentSize, 512);
     
    45964626         * end-of-stream marker. Will be re-added after the grain table.
    45974627         * If the file has a footer it also will be re-added before EOS. */
    4598         if (pExtent->pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
     4628        if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
    45994629        {
    46004630            uint64_t uEOSOff = 0;
     
    46044634                uGTSector--;
    46054635                uEOSOff = 512;
    4606                 rc = vmdkWriteMetaSparseExtent(pExtent, VMDK_SECTOR2BYTE(uGTSector) + pExtent->cGTEntries * sizeof(uint32_t));
     4636                rc = vmdkWriteMetaSparseExtent(pImage, pExtent, VMDK_SECTOR2BYTE(uGTSector) + pExtent->cGTEntries * sizeof(uint32_t));
    46074637                if (RT_FAILURE(rc))
    4608                     return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write footer after grain table in '%s'"), pExtent->pszFullname);
     4638                    return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write footer after grain table in '%s'"), pExtent->pszFullname);
    46094639            }
    46104640            pExtent->uLastGrainSector = 0;
    46114641            uint8_t aEOS[512];
    46124642            memset(aEOS, '\0', sizeof(aEOS));
    4613             rc = vmdkFileWriteAt(pExtent->pFile,
    4614                                  VMDK_SECTOR2BYTE(uGTSector) + pExtent->cGTEntries * sizeof(uint32_t) + uEOSOff,
    4615                                  aEOS, sizeof(aEOS), NULL);
     4643            rc = vmdkFileWriteSync(pImage, pExtent->pFile,
     4644                                   VMDK_SECTOR2BYTE(uGTSector) + pExtent->cGTEntries * sizeof(uint32_t) + uEOSOff,
     4645                                   aEOS, sizeof(aEOS), NULL);
    46164646            if (RT_FAILURE(rc))
    4617                 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write end-of stream marker after grain table in '%s'"), pExtent->pszFullname);
     4647                return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write end-of stream marker after grain table in '%s'"), pExtent->pszFullname);
    46184648        }
    46194649        /* Normally the grain table is preallocated for hosted sparse extents
     
    46314661             i++)
    46324662        {
    4633             rc = vmdkFileWriteAt(pExtent->pFile,
    4634                                  VMDK_SECTOR2BYTE(uGTSector) + i * sizeof(aGTDataTmp),
    4635                                  aGTDataTmp, sizeof(aGTDataTmp), NULL);
     4663            rc = vmdkFileWriteSync(pImage, pExtent->pFile,
     4664                                   VMDK_SECTOR2BYTE(uGTSector) + i * sizeof(aGTDataTmp),
     4665                                   aGTDataTmp, sizeof(aGTDataTmp), NULL);
    46364666            if (RT_FAILURE(rc))
    4637                 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write grain table allocation in '%s'"), pExtent->pszFullname);
     4667                return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write grain table allocation in '%s'"), pExtent->pszFullname);
    46384668        }
    46394669        if (pExtent->pRGD)
    46404670        {
    46414671            AssertReturn(!uRGTSector, VERR_VD_VMDK_INVALID_HEADER);
    4642             rc = vmdkFileGetSize(pExtent->pFile, &cbExtentSize);
     4672            rc = vmdkFileGetSize(pImage, pExtent->pFile, &cbExtentSize);
    46434673            if (RT_FAILURE(rc))
    4644                 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname);
     4674                return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname);
    46454675            Assert(!(cbExtentSize % 512));
    46464676            uRGTSector = VMDK_BYTE2SECTOR(cbExtentSize);
     
    46484678             * end-of-stream marker. Will be re-added after the grain table.
    46494679             * If the file has a footer it also will be re-added before EOS. */
    4650             if (pExtent->pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
     4680            if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
    46514681            {
    46524682                uint64_t uEOSOff = 0;
     
    46564686                    uRGTSector--;
    46574687                    uEOSOff = 512;
    4658                     rc = vmdkWriteMetaSparseExtent(pExtent, VMDK_SECTOR2BYTE(uRGTSector) + pExtent->cGTEntries * sizeof(uint32_t));
     4688                    rc = vmdkWriteMetaSparseExtent(pImage, pExtent, VMDK_SECTOR2BYTE(uRGTSector) + pExtent->cGTEntries * sizeof(uint32_t));
    46594689                    if (RT_FAILURE(rc))
    4660                         return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write footer after redundant grain table in '%s'"), pExtent->pszFullname);
     4690                        return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write footer after redundant grain table in '%s'"), pExtent->pszFullname);
    46614691                }
    46624692                pExtent->uLastGrainSector = 0;
    46634693                uint8_t aEOS[512];
    46644694                memset(aEOS, '\0', sizeof(aEOS));
    4665                 rc = vmdkFileWriteAt(pExtent->pFile,
    4666                                      VMDK_SECTOR2BYTE(uRGTSector) + pExtent->cGTEntries * sizeof(uint32_t) + uEOSOff,
    4667                                      aEOS, sizeof(aEOS), NULL);
     4695                rc = vmdkFileWriteSync(pImage, pExtent->pFile,
     4696                                       VMDK_SECTOR2BYTE(uRGTSector) + pExtent->cGTEntries * sizeof(uint32_t) + uEOSOff,
     4697                                       aEOS, sizeof(aEOS), NULL);
    46684698                if (RT_FAILURE(rc))
    4669                     return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write end-of stream marker after redundant grain table in '%s'"), pExtent->pszFullname);
     4699                    return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write end-of stream marker after redundant grain table in '%s'"), pExtent->pszFullname);
    46704700            }
    46714701            /* Normally the redundant grain table is preallocated for hosted
     
    46824712                 i++)
    46834713            {
    4684                 rc = vmdkFileWriteAt(pExtent->pFile,
    4685                                      VMDK_SECTOR2BYTE(uRGTSector) + i * sizeof(aGTDataTmp),
    4686                                      aGTDataTmp, sizeof(aGTDataTmp), NULL);
     4714                rc = vmdkFileWriteSync(pImage, pExtent->pFile,
     4715                                       VMDK_SECTOR2BYTE(uRGTSector) + i * sizeof(aGTDataTmp),
     4716                                       aGTDataTmp, sizeof(aGTDataTmp), NULL);
    46874717                if (RT_FAILURE(rc))
    4688                     return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain table allocation in '%s'"), pExtent->pszFullname);
     4718                    return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain table allocation in '%s'"), pExtent->pszFullname);
    46894719            }
    46904720        }
     
    46954725         * some unused sectors in the extent. */
    46964726        uint32_t uGTSectorLE = RT_H2LE_U64(uGTSector);
    4697         rc = vmdkFileWriteAt(pExtent->pFile,
    4698                              VMDK_SECTOR2BYTE(pExtent->uSectorGD) + uGDIndex * sizeof(uGTSectorLE),
    4699                              &uGTSectorLE, sizeof(uGTSectorLE), NULL);
     4727        rc = vmdkFileWriteSync(pImage, pExtent->pFile,
     4728                               VMDK_SECTOR2BYTE(pExtent->uSectorGD) + uGDIndex * sizeof(uGTSectorLE),
     4729                               &uGTSectorLE, sizeof(uGTSectorLE), NULL);
    47004730        if (RT_FAILURE(rc))
    4701             return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write grain directory entry in '%s'"), pExtent->pszFullname);
     4731            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write grain directory entry in '%s'"), pExtent->pszFullname);
    47024732        if (pExtent->pRGD)
    47034733        {
    47044734            uint32_t uRGTSectorLE = RT_H2LE_U64(uRGTSector);
    4705             rc = vmdkFileWriteAt(pExtent->pFile,
    4706                                  VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + uGDIndex * sizeof(uRGTSectorLE),
    4707                                  &uRGTSectorLE, sizeof(uRGTSectorLE), NULL);
     4735            rc = vmdkFileWriteSync(pImage, pExtent->pFile,
     4736                                   VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + uGDIndex * sizeof(uRGTSectorLE),
     4737                                   &uRGTSectorLE, sizeof(uRGTSectorLE), NULL);
    47084738            if (RT_FAILURE(rc))
    4709                 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain directory entry in '%s'"), pExtent->pszFullname);
     4739                return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain directory entry in '%s'"), pExtent->pszFullname);
    47104740        }
    47114741
     
    47164746    }
    47174747
    4718     rc = vmdkFileGetSize(pExtent->pFile, &cbExtentSize);
     4748    rc = vmdkFileGetSize(pImage, pExtent->pFile, &cbExtentSize);
    47194749    if (RT_FAILURE(rc))
    4720         return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname);
     4750        return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname);
    47214751    Assert(!(cbExtentSize % 512));
    47224752
    47234753    /* Write the data. Always a full grain, or we're in big trouble. */
    4724     if (pExtent->pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
     4754    if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
    47254755    {
    47264756        /* For streamOptimized extents this is a little more difficult, as the
     
    47384768        Assert(cbWrite == VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain));
    47394769        uint32_t cbGrain = 0;
    4740         rc = vmdkFileDeflateAt(pExtent->pFile, cbExtentSize,
    4741                                pvBuf, cbWrite, VMDK_MARKER_IGNORE, uSector, &cbGrain);
     4770        rc = vmdkFileDeflateSync(pImage, pExtent->pFile, cbExtentSize,
     4771                                 pvBuf, cbWrite, VMDK_MARKER_IGNORE, uSector, &cbGrain);
    47424772        if (RT_FAILURE(rc))
    47434773        {
     
    47454775            pExtent->uLastGrainSector = 0;
    47464776            AssertRC(rc);
    4747             return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write allocated compressed data block in '%s'"), pExtent->pszFullname);
     4777            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write allocated compressed data block in '%s'"), pExtent->pszFullname);
    47484778        }
    47494779        cbGrain = RT_ALIGN(cbGrain, 512);
     
    47584788        {
    47594789            uEOSOff = 512;
    4760             rc = vmdkWriteMetaSparseExtent(pExtent, cbExtentSize + RT_ALIGN(cbGrain, 512));
     4790            rc = vmdkWriteMetaSparseExtent(pImage, pExtent, cbExtentSize + RT_ALIGN(cbGrain, 512));
    47614791            if (RT_FAILURE(rc))
    4762                 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write footer after allocated data block in '%s'"), pExtent->pszFullname);
     4792                return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write footer after allocated data block in '%s'"), pExtent->pszFullname);
    47634793        }
    47644794        uint8_t aEOS[512];
    47654795        memset(aEOS, '\0', sizeof(aEOS));
    4766         rc = vmdkFileWriteAt(pExtent->pFile, cbExtentSize + RT_ALIGN(cbGrain, 512) + uEOSOff,
    4767                              aEOS, sizeof(aEOS), NULL);
     4796        rc = vmdkFileWriteSync(pImage, pExtent->pFile,
     4797                               cbExtentSize + RT_ALIGN(cbGrain, 512) + uEOSOff,
     4798                               aEOS, sizeof(aEOS), NULL);
    47684799        if (RT_FAILURE(rc))
    4769             return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write end-of stream marker after allocated data block in '%s'"), pExtent->pszFullname);
     4800            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write end-of stream marker after allocated data block in '%s'"), pExtent->pszFullname);
    47704801    }
    47714802    else
    47724803    {
    4773         rc = vmdkFileWriteAt(pExtent->pFile, cbExtentSize, pvBuf, cbWrite, NULL);
     4804        rc = vmdkFileWriteSync(pImage, pExtent->pFile, cbExtentSize, pvBuf, cbWrite, NULL);
    47744805        if (RT_FAILURE(rc))
    4775             return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write allocated data block in '%s'"), pExtent->pszFullname);
     4806            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write allocated data block in '%s'"), pExtent->pszFullname);
    47764807    }
    47774808
     
    47844815    {
    47854816        /* Cache miss, fetch data from disk. */
    4786         rc = vmdkFileReadAt(pExtent->pFile,
    4787                             VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
    4788                             aGTDataTmp, sizeof(aGTDataTmp), NULL);
     4817        rc = vmdkFileReadSync(pImage, pExtent->pFile,
     4818                              VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
     4819                              aGTDataTmp, sizeof(aGTDataTmp), NULL);
    47894820        if (RT_FAILURE(rc))
    4790             return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot read allocated grain table entry in '%s'"), pExtent->pszFullname);
     4821            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot read allocated grain table entry in '%s'"), pExtent->pszFullname);
    47914822        pGTCacheEntry->uExtent = pExtent->uExtent;
    47924823        pGTCacheEntry->uGTBlock = uGTBlock;
     
    48054836    pGTCacheEntry->aGTData[uGTBlockIndex] = VMDK_BYTE2SECTOR(cbExtentSize);
    48064837    /* Update grain table on disk. */
    4807     rc = vmdkFileWriteAt(pExtent->pFile,
    4808                          VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
    4809                          aGTDataTmp, sizeof(aGTDataTmp), NULL);
     4838    rc = vmdkFileWriteSync(pImage, pExtent->pFile,
     4839                           VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
     4840                           aGTDataTmp, sizeof(aGTDataTmp), NULL);
    48104841    if (RT_FAILURE(rc))
    4811         return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write updated grain table in '%s'"), pExtent->pszFullname);
     4842        return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write updated grain table in '%s'"), pExtent->pszFullname);
    48124843    if (pExtent->pRGD)
    48134844    {
    48144845        /* Update backup grain table on disk. */
    4815         rc = vmdkFileWriteAt(pExtent->pFile,
    4816                              VMDK_SECTOR2BYTE(uRGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
    4817                              aGTDataTmp, sizeof(aGTDataTmp), NULL);
     4846        rc = vmdkFileWriteSync(pImage, pExtent->pFile,
     4847                               VMDK_SECTOR2BYTE(uRGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
     4848                               aGTDataTmp, sizeof(aGTDataTmp), NULL);
    48184849        if (RT_FAILURE(rc))
    4819             return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write updated backup grain table in '%s'"), pExtent->pszFullname);
     4850            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write updated backup grain table in '%s'"), pExtent->pszFullname);
    48204851    }
    48214852#ifdef VBOX_WITH_VMDK_ESX
     
    48334864 */
    48344865static int vmdkAllocGrainAsyncGTUpdate(PVMDKIMAGE pImage, PVMDKEXTENT pExtent,
    4835                                        PVMDKGTCACHE pCache, PVDIOCTX pIoCtx,
     4866                                       PVDIOCTX pIoCtx,
    48364867                                       PVMDKGRAINALLOCASYNC pGrainAlloc)
    48374868{
    48384869    int rc = VINF_SUCCESS;
     4870    PVMDKGTCACHE pCache = pImage->pGTCache;
    48394871    uint32_t aGTDataTmp[VMDK_GT_CACHELINE_SIZE];
    48404872    uint32_t uGTHash, uGTBlockIndex;
     
    48604892        LogFlow(("Cache miss, fetch data from disk\n"));
    48614893        PVDMETAXFER pMetaXfer = NULL;
    4862         rc = pImage->pInterfaceIOCallbacks->pfnReadMetaAsync(pExtent->pImage->pInterfaceIO->pvUser,
    4863                                                              pExtent->pFile->pStorage,
    4864                                                              VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
    4865                                                              aGTDataTmp, sizeof(aGTDataTmp), pIoCtx,
    4866                                                              &pMetaXfer,
    4867                                                              vmdkAllocGrainAsyncComplete, pGrainAlloc);
     4894        rc = vmdkFileReadMetaAsync(pImage, pExtent->pFile,
     4895                                   VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
     4896                                   aGTDataTmp, sizeof(aGTDataTmp), pIoCtx,
     4897                                   &pMetaXfer, vmdkAllocGrainAsyncComplete, pGrainAlloc);
    48684898        if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
    48694899        {
     
    48754905        }
    48764906        else if (RT_FAILURE(rc))
    4877             return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot read allocated grain table entry in '%s'"), pExtent->pszFullname);
    4878         pImage->pInterfaceIOCallbacks->pfnMetaXferRelease(pExtent->pImage->pInterfaceIO->pvUser, pMetaXfer);
     4907            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot read allocated grain table entry in '%s'"), pExtent->pszFullname);
     4908        vmdkFileMetaXferRelease(pImage, pMetaXfer);
    48794909        pGTCacheEntry->uExtent = pExtent->uExtent;
    48804910        pGTCacheEntry->uGTBlock = uGTBlock;
     
    48944924    pGTCacheEntry->aGTData[uGTBlockIndex] = VMDK_BYTE2SECTOR(pGrainAlloc->cbExtentSize);
    48954925    /* Update grain table on disk. */
    4896     rc = pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pExtent->pImage->pInterfaceIO->pvUser,
    4897                                                           pExtent->pFile->pStorage,
    4898                                                           VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
    4899                                                           aGTDataTmp, sizeof(aGTDataTmp), pIoCtx,
    4900                                                           vmdkAllocGrainAsyncComplete, pGrainAlloc);
     4926    rc = vmdkFileWriteMetaAsync(pImage, pExtent->pFile,
     4927                                VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
     4928                                aGTDataTmp, sizeof(aGTDataTmp), pIoCtx,
     4929                                vmdkAllocGrainAsyncComplete, pGrainAlloc);
    49014930    if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
    49024931        pGrainAlloc->cIoXfersPending++;
    49034932    else if (RT_FAILURE(rc))
    4904         return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write updated grain table in '%s'"), pExtent->pszFullname);
     4933        return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write updated grain table in '%s'"), pExtent->pszFullname);
    49054934    if (pExtent->pRGD)
    49064935    {
    49074936        /* Update backup grain table on disk. */
    4908         rc = pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pExtent->pImage->pInterfaceIO->pvUser,
    4909                                                               pExtent->pFile->pStorage,
    4910                                                               VMDK_SECTOR2BYTE(uRGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
    4911                                                               aGTDataTmp, sizeof(aGTDataTmp), pIoCtx,
    4912                                                               vmdkAllocGrainAsyncComplete, pGrainAlloc);
     4937        rc = vmdkFileWriteMetaAsync(pImage, pExtent->pFile,
     4938                                    VMDK_SECTOR2BYTE(uRGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
     4939                                    aGTDataTmp, sizeof(aGTDataTmp), pIoCtx,
     4940                                    vmdkAllocGrainAsyncComplete, pGrainAlloc);
    49134941        if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
    49144942            pGrainAlloc->cIoXfersPending++;
    49154943        else if (RT_FAILURE(rc))
    4916             return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write updated backup grain table in '%s'"), pExtent->pszFullname);
     4944            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write updated backup grain table in '%s'"), pExtent->pszFullname);
    49174945    }
    49184946#ifdef VBOX_WITH_VMDK_ESX
     
    49324960 * Internal - complete the grain allocation by updating disk grain table if required.
    49334961 */
    4934 static int vmdkAllocGrainAsyncComplete(void *pvBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq)
     4962static int vmdkAllocGrainAsyncComplete(void *pBackendData, PVDIOCTX pIoCtx, void *pvUser, int rcReq)
    49354963{
    49364964    int rc = VINF_SUCCESS;
    4937     PVMDKIMAGE pImage = (PVMDKIMAGE)pvBackendData;
     4965    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    49384966    PVMDKGRAINALLOCASYNC pGrainAlloc = (PVMDKGRAINALLOCASYNC)pvUser;
    49394967    PVMDKEXTENT pExtent = pGrainAlloc->pExtent;
    49404968
    4941     LogFlowFunc(("pvBackendData=%#p pIoCtx=%#p pvUser=%#p rcReq=%Rrc\n",
    4942                  pvBackendData, pIoCtx, pvUser, rcReq));
     4969    LogFlowFunc(("pBackendData=%#p pIoCtx=%#p pvUser=%#p rcReq=%Rrc\n",
     4970                 pBackendData, pIoCtx, pvUser, rcReq));
    49434971
    49444972    pGrainAlloc->cIoXfersPending--;
    49454973    if (!pGrainAlloc->cIoXfersPending && pGrainAlloc->fGTUpdateNeeded)
    4946         rc = vmdkAllocGrainAsyncGTUpdate(pImage, pGrainAlloc->pExtent, pImage->pGTCache,
     4974        rc = vmdkAllocGrainAsyncGTUpdate(pImage, pGrainAlloc->pExtent,
    49474975                                         pIoCtx, pGrainAlloc);
    49484976
     
    49604988 * Internal. Allocates a new grain table (if necessary) - async version.
    49614989 */
    4962 static int vmdkAllocGrainAsync(PVMDKGTCACHE pCache, PVMDKEXTENT pExtent,
     4990static int vmdkAllocGrainAsync(PVMDKIMAGE pImage, PVMDKEXTENT pExtent,
    49634991                               PVDIOCTX pIoCtx, uint64_t uSector,
    49644992                               uint64_t cbWrite)
    49654993{
     4994    PVMDKGTCACHE pCache = pImage->pGTCache;
    49664995    uint64_t uGDIndex, uGTSector, uRGTSector;
    49674996    uint64_t cbExtentSize;
    49684997    PVMDKGRAINALLOCASYNC pGrainAlloc = NULL;
    4969     PVMDKIMAGE pImage = pExtent->pImage;
    49704998    int rc;
    49714999
     
    49735001                 pCache, pExtent, pIoCtx, uSector, cbWrite));
    49745002
    4975     AssertReturn(!(pExtent->pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED), VERR_NOT_SUPPORTED);
     5003    AssertReturn(!(pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED), VERR_NOT_SUPPORTED);
    49765004
    49775005    pGrainAlloc = (PVMDKGRAINALLOCASYNC)RTMemAllocZ(sizeof(VMDKGRAINALLOCASYNC));
     
    49975025         * entry. So there is absolutely no data in this area. Allocate
    49985026         * a new grain table and put the reference to it in the GDs. */
    4999         rc = vmdkFileGetSize(pExtent->pFile, &cbExtentSize);
     5027        rc = vmdkFileGetSize(pImage, pExtent->pFile, &cbExtentSize);
    50005028        if (RT_FAILURE(rc))
    5001             return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname);
     5029            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname);
    50025030        Assert(!(cbExtentSize % 512));
    50035031
     
    50245052
    50255053        memset(paGTDataTmp, '\0', cbGTDataTmp);
    5026         rc = pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pExtent->pImage->pInterfaceIO->pvUser,
    5027                                                               pExtent->pFile->pStorage,
    5028                                                               VMDK_SECTOR2BYTE(uGTSector),
    5029                                                               paGTDataTmp, cbGTDataTmp, pIoCtx,
    5030                                                               vmdkAllocGrainAsyncComplete, pGrainAlloc);
     5054        rc = vmdkFileWriteMetaAsync(pImage, pExtent->pFile,
     5055                                    VMDK_SECTOR2BYTE(uGTSector),
     5056                                    paGTDataTmp, cbGTDataTmp, pIoCtx,
     5057                                    vmdkAllocGrainAsyncComplete, pGrainAlloc);
    50315058        if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
    50325059            pGrainAlloc->cIoXfersPending++;
     
    50345061        {
    50355062            RTMemTmpFree(paGTDataTmp);
    5036             return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write grain table allocation in '%s'"), pExtent->pszFullname);
     5063            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write grain table allocation in '%s'"), pExtent->pszFullname);
    50375064        }
    50385065
     
    50405067        {
    50415068            AssertReturn(!uRGTSector, VERR_VD_VMDK_INVALID_HEADER);
    5042             rc = vmdkFileGetSize(pExtent->pFile, &cbExtentSize);
     5069            rc = vmdkFileGetSize(pImage, pExtent->pFile, &cbExtentSize);
    50435070            if (RT_FAILURE(rc))
    5044                 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname);
     5071                return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname);
    50455072            Assert(!(cbExtentSize % 512));
    50465073            uRGTSector = VMDK_BYTE2SECTOR(cbExtentSize);
     
    50565083            /* Write backup grain table by writing the required number of grain
    50575084             * table cache chunks. */
    5058             rc = pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pExtent->pImage->pInterfaceIO->pvUser,
    5059                                                                   pExtent->pFile->pStorage,
    5060                                                                   VMDK_SECTOR2BYTE(uRGTSector),
    5061                                                                   paGTDataTmp, cbGTDataTmp, pIoCtx,
    5062                                                                   vmdkAllocGrainAsyncComplete, pGrainAlloc);
     5085            rc = vmdkFileWriteMetaAsync(pImage, pExtent->pFile,
     5086                                        VMDK_SECTOR2BYTE(uRGTSector),
     5087                                        paGTDataTmp, cbGTDataTmp, pIoCtx,
     5088                                        vmdkAllocGrainAsyncComplete, pGrainAlloc);
    50635089            if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
    50645090                pGrainAlloc->cIoXfersPending++;
     
    50665092            {
    50675093                RTMemTmpFree(paGTDataTmp);
    5068                 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain table allocation in '%s'"), pExtent->pszFullname);
     5094                return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain table allocation in '%s'"), pExtent->pszFullname);
    50695095            }
    50705096        }
     
    50775103         * some unused sectors in the extent. */
    50785104        uint32_t uGTSectorLE = RT_H2LE_U64(uGTSector);
    5079         rc = pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pExtent->pImage->pInterfaceIO->pvUser,
    5080                                                               pExtent->pFile->pStorage,
    5081                                                               VMDK_SECTOR2BYTE(pExtent->uSectorGD) + uGDIndex * sizeof(uGTSectorLE),
    5082                                                               &uGTSectorLE, sizeof(uGTSectorLE), pIoCtx,
    5083                                                               vmdkAllocGrainAsyncComplete, pGrainAlloc);
     5105        rc = vmdkFileWriteMetaAsync(pImage, pExtent->pFile,
     5106                                    VMDK_SECTOR2BYTE(pExtent->uSectorGD) + uGDIndex * sizeof(uGTSectorLE),
     5107                                    &uGTSectorLE, sizeof(uGTSectorLE), pIoCtx,
     5108                                    vmdkAllocGrainAsyncComplete, pGrainAlloc);
    50845109        if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
    50855110            pGrainAlloc->cIoXfersPending++;
    50865111        else if (RT_FAILURE(rc))
    5087             return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write grain directory entry in '%s'"), pExtent->pszFullname);
     5112            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write grain directory entry in '%s'"), pExtent->pszFullname);
    50885113        if (pExtent->pRGD)
    50895114        {
    50905115            uint32_t uRGTSectorLE = RT_H2LE_U64(uRGTSector);
    5091             rc = pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pExtent->pImage->pInterfaceIO->pvUser,
    5092                                                                   pExtent->pFile->pStorage,
    5093                                                                   VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + uGDIndex * sizeof(uGTSectorLE),
    5094                                                                   &uRGTSectorLE, sizeof(uRGTSectorLE), pIoCtx,
    5095                                                                   vmdkAllocGrainAsyncComplete, pGrainAlloc);
     5116            rc = vmdkFileWriteMetaAsync(pImage, pExtent->pFile,
     5117                                        VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + uGDIndex * sizeof(uGTSectorLE),
     5118                                        &uRGTSectorLE, sizeof(uRGTSectorLE), pIoCtx,
     5119                                        vmdkAllocGrainAsyncComplete, pGrainAlloc);
    50965120            if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
    50975121                pGrainAlloc->cIoXfersPending++;
    50985122            else if (RT_FAILURE(rc))
    5099                 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain directory entry in '%s'"), pExtent->pszFullname);
     5123                return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain directory entry in '%s'"), pExtent->pszFullname);
    51005124        }
    51015125
     
    51105134    pGrainAlloc->uRGTSector = uRGTSector;
    51115135
    5112     rc = vmdkFileGetSize(pExtent->pFile, &cbExtentSize);
     5136    rc = vmdkFileGetSize(pImage, pExtent->pFile, &cbExtentSize);
    51135137    if (RT_FAILURE(rc))
    5114         return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname);
     5138        return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname);
    51155139    Assert(!(cbExtentSize % 512));
    51165140
     
    51215145
    51225146    /* Write the data. Always a full grain, or we're in big trouble. */
    5123     rc = pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser,
    5124                                                           pExtent->pFile->pStorage,
    5125                                                           cbExtentSize,
    5126                                                           pIoCtx, cbWrite,
    5127                                                           vmdkAllocGrainAsyncComplete, pGrainAlloc);
     5147    rc = vmdkFileWriteUserAsync(pImage, pExtent->pFile,
     5148                                cbExtentSize, pIoCtx, cbWrite,
     5149                                vmdkAllocGrainAsyncComplete, pGrainAlloc);
    51285150    if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
    51295151        pGrainAlloc->cIoXfersPending++;
    51305152    else if (RT_FAILURE(rc))
    5131         return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write allocated data block in '%s'"), pExtent->pszFullname);
    5132 
    5133     rc = vmdkAllocGrainAsyncGTUpdate(pImage, pExtent, pCache, pIoCtx, pGrainAlloc);
     5153        return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write allocated data block in '%s'"), pExtent->pszFullname);
     5154
     5155    rc = vmdkAllocGrainAsyncGTUpdate(pImage, pExtent, pIoCtx, pGrainAlloc);
    51345156
    51355157    if (!pGrainAlloc->cIoXfersPending)
     
    51445166}
    51455167
     5168/**
     5169 * Replaces a fragment of a string with the specified string.
     5170 *
     5171 * @returns Pointer to the allocated UTF-8 string.
     5172 * @param   pszWhere        UTF-8 string to search in.
     5173 * @param   pszWhat         UTF-8 string to search for.
     5174 * @param   pszByWhat       UTF-8 string to replace the found string with.
     5175 */
     5176static char *vmdkStrReplace(const char *pszWhere, const char *pszWhat,
     5177                            const char *pszByWhat)
     5178{
     5179    AssertPtr(pszWhere);
     5180    AssertPtr(pszWhat);
     5181    AssertPtr(pszByWhat);
     5182    const char *pszFoundStr = strstr(pszWhere, pszWhat);
     5183    if (!pszFoundStr)
     5184        return NULL;
     5185    size_t cFinal = strlen(pszWhere) + 1 + strlen(pszByWhat) - strlen(pszWhat);
     5186    char *pszNewStr = (char *)RTMemAlloc(cFinal);
     5187    if (pszNewStr)
     5188    {
     5189        char *pszTmp = pszNewStr;
     5190        memcpy(pszTmp, pszWhere, pszFoundStr - pszWhere);
     5191        pszTmp += pszFoundStr - pszWhere;
     5192        memcpy(pszTmp, pszByWhat, strlen(pszByWhat));
     5193        pszTmp += strlen(pszByWhat);
     5194        strcpy(pszTmp, pszFoundStr + strlen(pszWhat));
     5195    }
     5196    return pszNewStr;
     5197}
     5198
    51465199
    51475200/** @copydoc VBOXHDDBACKEND::pfnCheckIfValid */
    5148 static int vmdkCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk)
     5201static int vmdkCheckIfValid(const char *pszFilename, PVDINTERFACE pVDIfsDisk,
     5202                            PVDINTERFACE pVDIfsImage)
    51495203{
    51505204    LogFlowFunc(("pszFilename=\"%s\"\n", pszFilename));
     
    51595213        goto out;
    51605214    }
    5161 
    5162     pImage = (PVMDKIMAGE)RTMemAllocZ(sizeof(VMDKIMAGE));
    5163     if (!pImage)
    5164     {
    5165         rc = VERR_NO_MEMORY;
    5166         goto out;
    5167     }
    5168     pImage->pszFilename = pszFilename;
    5169     pImage->pFile = NULL;
    5170     pImage->pExtents = NULL;
    5171     pImage->pFiles = NULL;
    5172     pImage->pGTCache = NULL;
    5173     pImage->pDescData = NULL;
    5174     pImage->pVDIfsDisk = pVDIfsDisk;
    5175     pImage->pVDIfsImage = pVDIfsDisk;
    5176     /** @todo speed up this test open (VD_OPEN_FLAGS_INFO) by skipping as
    5177      * much as possible in vmdkOpenImage. */
    5178     rc = vmdkOpenImage(pImage, VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_READONLY);
    5179     vmdkFreeImage(pImage, false);
    5180     RTMemFree(pImage);
    5181 
    5182 out:
    5183     LogFlowFunc(("returns %Rrc\n", rc));
    5184     return rc;
    5185 }
    5186 
    5187 /** @copydoc VBOXHDDBACKEND::pfnOpen */
    5188 static int vmdkOpen(const char *pszFilename, unsigned uOpenFlags,
    5189                     PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
    5190                     void **ppBackendData)
    5191 {
    5192     LogFlowFunc(("pszFilename=\"%s\" uOpenFlags=%#x pVDIfsDisk=%#p pVDIfsImage=%#p ppBackendData=%#p\n", pszFilename, uOpenFlags, pVDIfsDisk, pVDIfsImage, ppBackendData));
    5193     int rc;
    5194     PVMDKIMAGE pImage;
    5195 
    5196     /* Check open flags. All valid flags are supported. */
    5197     if (uOpenFlags & ~VD_OPEN_FLAGS_MASK)
    5198     {
    5199         rc = VERR_INVALID_PARAMETER;
    5200         goto out;
    5201     }
    5202 
    5203     /* Check remaining arguments. */
    5204     if (   !VALID_PTR(pszFilename)
    5205         || !*pszFilename
    5206         || strchr(pszFilename, '"'))
    5207     {
    5208         rc = VERR_INVALID_PARAMETER;
    5209         goto out;
    5210     }
    5211 
    52125215
    52135216    pImage = (PVMDKIMAGE)RTMemAllocZ(sizeof(VMDKIMAGE));
     
    52255228    pImage->pVDIfsDisk = pVDIfsDisk;
    52265229    pImage->pVDIfsImage = pVDIfsImage;
     5230    /** @todo speed up this test open (VD_OPEN_FLAGS_INFO) by skipping as
     5231     * much as possible in vmdkOpenImage. */
     5232    rc = vmdkOpenImage(pImage, VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_READONLY);
     5233    vmdkFreeImage(pImage, false);
     5234    RTMemFree(pImage);
     5235
     5236out:
     5237    LogFlowFunc(("returns %Rrc\n", rc));
     5238    return rc;
     5239}
     5240
     5241/** @copydoc VBOXHDDBACKEND::pfnOpen */
     5242static int vmdkOpen(const char *pszFilename, unsigned uOpenFlags,
     5243                    PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
     5244                    void **ppBackendData)
     5245{
     5246    LogFlowFunc(("pszFilename=\"%s\" uOpenFlags=%#x pVDIfsDisk=%#p pVDIfsImage=%#p ppBackendData=%#p\n", pszFilename, uOpenFlags, pVDIfsDisk, pVDIfsImage, ppBackendData));
     5247    int rc;
     5248    PVMDKIMAGE pImage;
     5249
     5250    /* Check open flags. All valid flags are supported. */
     5251    if (uOpenFlags & ~VD_OPEN_FLAGS_MASK)
     5252    {
     5253        rc = VERR_INVALID_PARAMETER;
     5254        goto out;
     5255    }
     5256
     5257    /* Check remaining arguments. */
     5258    if (   !VALID_PTR(pszFilename)
     5259        || !*pszFilename
     5260        || strchr(pszFilename, '"'))
     5261    {
     5262        rc = VERR_INVALID_PARAMETER;
     5263        goto out;
     5264    }
     5265
     5266
     5267    pImage = (PVMDKIMAGE)RTMemAllocZ(sizeof(VMDKIMAGE));
     5268    if (!pImage)
     5269    {
     5270        rc = VERR_NO_MEMORY;
     5271        goto out;
     5272    }
     5273    pImage->pszFilename = pszFilename;
     5274    pImage->pFile = NULL;
     5275    pImage->pExtents = NULL;
     5276    pImage->pFiles = NULL;
     5277    pImage->pGTCache = NULL;
     5278    pImage->pDescData = NULL;
     5279    pImage->pVDIfsDisk = pVDIfsDisk;
     5280    pImage->pVDIfsImage = pVDIfsImage;
    52275281
    52285282    rc = vmdkOpenImage(pImage, uOpenFlags);
     
    52385292static int vmdkCreate(const char *pszFilename, uint64_t cbSize,
    52395293                      unsigned uImageFlags, const char *pszComment,
    5240                       PCPDMMEDIAGEOMETRY pPCHSGeometry,
    5241                       PCPDMMEDIAGEOMETRY pLCHSGeometry, PCRTUUID pUuid,
    5242                       unsigned uOpenFlags, unsigned uPercentStart,
    5243                       unsigned uPercentSpan, PVDINTERFACE pVDIfsDisk,
    5244                       PVDINTERFACE pVDIfsImage, PVDINTERFACE pVDIfsOperation,
    5245                       void **ppBackendData)
     5294                      PCVDGEOMETRY pPCHSGeometry, PCVDGEOMETRY pLCHSGeometry,
     5295                      PCRTUUID pUuid, unsigned uOpenFlags,
     5296                      unsigned uPercentStart, unsigned uPercentSpan,
     5297                      PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage,
     5298                      PVDINTERFACE pVDIfsOperation, void **ppBackendData)
    52465299{
    52475300    LogFlowFunc(("pszFilename=\"%s\" cbSize=%llu uImageFlags=%#x pszComment=\"%s\" pPCHSGeometry=%#p pLCHSGeometry=%#p Uuid=%RTuuid uOpenFlags=%#x uPercentStart=%u uPercentSpan=%u pVDIfsDisk=%#p pVDIfsImage=%#p pVDIfsOperation=%#p ppBackendData=%#p", pszFilename, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, ppBackendData));
     
    53485401}
    53495402
    5350 /**
    5351  * Replaces a fragment of a string with the specified string.
    5352  *
    5353  * @returns Pointer to the allocated UTF-8 string.
    5354  * @param   pszWhere        UTF-8 string to search in.
    5355  * @param   pszWhat         UTF-8 string to search for.
    5356  * @param   pszByWhat       UTF-8 string to replace the found string with.
    5357  */
    5358 static char * vmdkStrReplace(const char *pszWhere, const char *pszWhat, const char *pszByWhat)
    5359 {
    5360     AssertPtr(pszWhere);
    5361     AssertPtr(pszWhat);
    5362     AssertPtr(pszByWhat);
    5363     const char *pszFoundStr = strstr(pszWhere, pszWhat);
    5364     if (!pszFoundStr)
    5365         return NULL;
    5366     size_t cFinal = strlen(pszWhere) + 1 + strlen(pszByWhat) - strlen(pszWhat);
    5367     char *pszNewStr = (char *)RTMemAlloc(cFinal);
    5368     if (pszNewStr)
    5369     {
    5370         char *pszTmp = pszNewStr;
    5371         memcpy(pszTmp, pszWhere, pszFoundStr - pszWhere);
    5372         pszTmp += pszFoundStr - pszWhere;
    5373         memcpy(pszTmp, pszByWhat, strlen(pszByWhat));
    5374         pszTmp += strlen(pszByWhat);
    5375         strcpy(pszTmp, pszFoundStr + strlen(pszWhat));
    5376     }
    5377     return pszNewStr;
    5378 }
    5379 
    53805403/** @copydoc VBOXHDDBACKEND::pfnRename */
    53815404static int vmdkRename(void *pBackendData, const char *pszFilename)
     
    54865509    pImage->Descriptor.fDirty = true;
    54875510    /* Flush the descriptor now, in case it is embedded. */
    5488     (void)vmdkFlushImage(pImage);
     5511    vmdkFlushImage(pImage);
    54895512
    54905513    /* Close and rename/move extents. */
     
    55005523        vmdkFileClose(pImage, &pExtent->pFile, false);
    55015524        /* Rename the extent file. */
    5502         rc = RTFileMove(pExtent->pszFullname, apszNewName[i], 0);
     5525        rc = vmdkFileMove(pImage, pExtent->pszFullname, apszNewName[i], 0);
    55035526        if (RT_FAILURE(rc))
    55045527            goto rollback;
     
    55185541    if (!fEmbeddedDesc)
    55195542    {
    5520         rc = RTFileMove(pImage->pszFilename, apszNewName[cExtents], 0);
     5543        rc = vmdkFileMove(pImage, pImage->pszFilename, apszNewName[cExtents], 0);
    55215544        if (RT_FAILURE(rc))
    55225545            goto rollback;
     
    55515574            if (apszOldName[i])
    55525575            {
    5553                 rrc = RTFileMove(apszNewName[i], apszOldName[i], 0);
     5576                rrc = vmdkFileMove(pImage, apszNewName[i], apszOldName[i], 0);
    55545577                AssertRC(rrc);
    55555578            }
     
    55585581        PVMDKFILE pFile;
    55595582        rrc = vmdkFileOpen(pImage, &pFile, pszOldDescName,
    5560                            vmdkFileOpenFlags(VD_OPEN_FLAGS_NORMAL),
    5561                            false);
     5583                           VDOpenFlagsToFileOpenFlags(VD_OPEN_FLAGS_NORMAL,
     5584                                                      false /* fCreate */),
     5585                           false /* fAsyncIO */);
    55625586        AssertRC(rrc);
    55635587        if (fEmbeddedDesc)
     
    56315655    LogFlowFunc(("pBackendData=%#p fDelete=%d\n", pBackendData, fDelete));
    56325656    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    5633     int rc = VINF_SUCCESS;
    5634 
    5635     /* Freeing a never allocated image (e.g. because the open failed) is
    5636      * not signalled as an error. After all nothing bad happens. */
    5637     if (pImage)
    5638     {
    5639         vmdkFreeImage(pImage, fDelete);
    5640         RTMemFree(pImage);
    5641     }
     5657    int rc;
     5658
     5659    rc = vmdkFreeImage(pImage, fDelete);
     5660    RTMemFree(pImage);
    56425661
    56435662    LogFlowFunc(("returns %Rrc\n", rc));
     
    56905709        case VMDKETYPE_ESX_SPARSE:
    56915710#endif /* VBOX_WITH_VMDK_ESX */
    5692             rc = vmdkGetSector(pImage->pGTCache, pExtent, uSectorExtentRel,
     5711            rc = vmdkGetSector(pImage, pExtent, uSectorExtentRel,
    56935712                               &uSectorExtentAbs);
    56945713            if (RT_FAILURE(rc))
     
    57085727                    if (pExtent->uGrainSector != uSectorExtentAbs)
    57095728                    {
    5710                         rc = vmdkFileInflateAt(pExtent->pFile, VMDK_SECTOR2BYTE(uSectorExtentAbs),
    5711                                                pExtent->pvGrain, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain), VMDK_MARKER_IGNORE, &uLBA, NULL);
     5729                        rc = vmdkFileInflateSync(pImage, pExtent->pFile, VMDK_SECTOR2BYTE(uSectorExtentAbs),
     5730                                                 pExtent->pvGrain, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain), VMDK_MARKER_IGNORE, &uLBA, NULL);
    57125731                        if (RT_FAILURE(rc))
    57135732                        {
     
    57235742                else
    57245743                {
    5725                     rc = vmdkFileReadAt(pExtent->pFile,
    5726                                         VMDK_SECTOR2BYTE(uSectorExtentAbs),
    5727                                         pvBuf, cbToRead, NULL);
     5744                    rc = vmdkFileReadSync(pImage, pExtent->pFile,
     5745                                          VMDK_SECTOR2BYTE(uSectorExtentAbs),
     5746                                          pvBuf, cbToRead, NULL);
    57285747                }
    57295748            }
     
    57315750        case VMDKETYPE_VMFS:
    57325751        case VMDKETYPE_FLAT:
    5733             rc = vmdkFileReadAt(pExtent->pFile,
    5734                                 VMDK_SECTOR2BYTE(uSectorExtentRel),
    5735                                 pvBuf, cbToRead, NULL);
     5752            rc = vmdkFileReadSync(pImage, pExtent->pFile,
     5753                                  VMDK_SECTOR2BYTE(uSectorExtentRel),
     5754                                  pvBuf, cbToRead, NULL);
    57365755            break;
    57375756        case VMDKETYPE_ZERO:
     
    58015820        case VMDKETYPE_ESX_SPARSE:
    58025821#endif /* VBOX_WITH_VMDK_ESX */
    5803             rc = vmdkGetSector(pImage->pGTCache, pExtent, uSectorExtentRel,
     5822            rc = vmdkGetSector(pImage, pExtent, uSectorExtentRel,
    58045823                               &uSectorExtentAbs);
    58055824            if (RT_FAILURE(rc))
     
    58225841                    {
    58235842                        /* Allocate GT and find out where to store the grain. */
    5824                         rc = vmdkAllocGrain(pImage->pGTCache, pExtent,
    5825                                             uSectorExtentRel, pvBuf, cbToWrite);
     5843                        rc = vmdkAllocGrain(pImage, pExtent, uSectorExtentRel,
     5844                                            pvBuf, cbToWrite);
    58265845                    }
    58275846                    else
     
    58495868                        ||  pExtent->uGrainSector != pExtent->uLastGrainSector)
    58505869                    {
    5851                         rc = vmdkFileInflateAt(pExtent->pFile, VMDK_SECTOR2BYTE(uSectorExtentAbs),
    5852                                                pExtent->pvGrain, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain), VMDK_MARKER_IGNORE, &uLBA, NULL);
     5870                        rc = vmdkFileInflateSync(pImage, pExtent->pFile, VMDK_SECTOR2BYTE(uSectorExtentAbs),
     5871                                                 pExtent->pvGrain, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain), VMDK_MARKER_IGNORE, &uLBA, NULL);
    58535872                        if (RT_FAILURE(rc))
    58545873                        {
     
    58645883                    memcpy((uint8_t *)pExtent->pvGrain + VMDK_SECTOR2BYTE(uSectorInGrain), pvBuf, cbToWrite);
    58655884                    uint32_t cbGrain = 0;
    5866                     rc = vmdkFileDeflateAt(pExtent->pFile,
    5867                                            VMDK_SECTOR2BYTE(uSectorExtentAbs),
    5868                                            pExtent->pvGrain, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain),
    5869                                            VMDK_MARKER_IGNORE, uLBA, &cbGrain);
     5885                    rc = vmdkFileDeflateSync(pImage, pExtent->pFile,
     5886                                             VMDK_SECTOR2BYTE(uSectorExtentAbs),
     5887                                             pExtent->pvGrain, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain),
     5888                                             VMDK_MARKER_IGNORE, uLBA, &cbGrain);
    58705889                    if (RT_FAILURE(rc))
    58715890                    {
     
    58735892                        pExtent->uLastGrainSector = 0;
    58745893                        AssertRC(rc);
    5875                         return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write compressed data block in '%s'"), pExtent->pszFullname);
     5894                        return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write compressed data block in '%s'"), pExtent->pszFullname);
    58765895                    }
    58775896                    cbGrain = RT_ALIGN(cbGrain, 512);
     
    58845903                    {
    58855904                        uEOSOff = 512;
    5886                         rc = vmdkWriteMetaSparseExtent(pExtent, VMDK_SECTOR2BYTE(uSectorExtentAbs) + RT_ALIGN(cbGrain, 512));
     5905                        rc = vmdkWriteMetaSparseExtent(pImage, pExtent, VMDK_SECTOR2BYTE(uSectorExtentAbs) + RT_ALIGN(cbGrain, 512));
    58875906                        if (RT_FAILURE(rc))
    5888                             return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write footer after data block in '%s'"), pExtent->pszFullname);
     5907                            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write footer after data block in '%s'"), pExtent->pszFullname);
    58895908                    }
    58905909                    uint8_t aEOS[512];
    58915910                    memset(aEOS, '\0', sizeof(aEOS));
    5892                     rc = vmdkFileWriteAt(pExtent->pFile,
    5893                                          VMDK_SECTOR2BYTE(uSectorExtentAbs) + RT_ALIGN(cbGrain, 512) + uEOSOff,
    5894                                          aEOS, sizeof(aEOS), NULL);
     5911                    rc = vmdkFileWriteSync(pImage, pExtent->pFile,
     5912                                           VMDK_SECTOR2BYTE(uSectorExtentAbs) + RT_ALIGN(cbGrain, 512) + uEOSOff,
     5913                                           aEOS, sizeof(aEOS), NULL);
    58955914                    if (RT_FAILURE(rc))
    5896                         return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write end-of stream marker after data block in '%s'"), pExtent->pszFullname);
     5915                        return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write end-of stream marker after data block in '%s'"), pExtent->pszFullname);
    58975916                }
    58985917                else
    58995918                {
    5900                     rc = vmdkFileWriteAt(pExtent->pFile,
    5901                                          VMDK_SECTOR2BYTE(uSectorExtentAbs),
    5902                                          pvBuf, cbToWrite, NULL);
     5919                    rc = vmdkFileWriteSync(pImage, pExtent->pFile,
     5920                                           VMDK_SECTOR2BYTE(uSectorExtentAbs),
     5921                                           pvBuf, cbToWrite, NULL);
    59035922                }
    59045923            }
     
    59085927            /* Clip write range to remain in this extent. */
    59095928            cbToWrite = RT_MIN(cbToWrite, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel));
    5910             rc = vmdkFileWriteAt(pExtent->pFile,
    5911                                  VMDK_SECTOR2BYTE(uSectorExtentRel),
    5912                                  pvBuf, cbToWrite, NULL);
     5929            rc = vmdkFileWriteSync(pImage, pExtent->pFile,
     5930                                   VMDK_SECTOR2BYTE(uSectorExtentRel),
     5931                                   pvBuf, cbToWrite, NULL);
    59135932            break;
    59145933        case VMDKETYPE_ZERO:
     
    59175936            break;
    59185937    }
     5938
    59195939    if (pcbWriteProcess)
    59205940        *pcbWriteProcess = cbToWrite;
     
    59816001        if (pImage->pFile != NULL)
    59826002        {
    5983             int rc = vmdkFileGetSize(pImage->pFile, &cbFile);
     6003            int rc = vmdkFileGetSize(pImage, pImage->pFile, &cbFile);
    59846004            if (RT_SUCCESS(rc))
    59856005                cb += cbFile;
     
    59896009            if (pImage->pExtents[i].pFile != NULL)
    59906010            {
    5991                 int rc = vmdkFileGetSize(pImage->pExtents[i].pFile, &cbFile);
     6011                int rc = vmdkFileGetSize(pImage, pImage->pExtents[i].pFile, &cbFile);
    59926012                if (RT_SUCCESS(rc))
    59936013                    cb += cbFile;
     
    60016021
    60026022/** @copydoc VBOXHDDBACKEND::pfnGetPCHSGeometry */
    6003 static int vmdkGetPCHSGeometry(void *pBackendData,
    6004                                PPDMMEDIAGEOMETRY pPCHSGeometry)
     6023static int vmdkGetPCHSGeometry(void *pBackendData, PVDGEOMETRY pPCHSGeometry)
    60056024{
    60066025    LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p\n", pBackendData, pPCHSGeometry));
     
    60286047
    60296048/** @copydoc VBOXHDDBACKEND::pfnSetPCHSGeometry */
    6030 static int vmdkSetPCHSGeometry(void *pBackendData,
    6031                                PCPDMMEDIAGEOMETRY pPCHSGeometry)
     6049static int vmdkSetPCHSGeometry(void *pBackendData, PCVDGEOMETRY pPCHSGeometry)
    60326050{
    60336051    LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
     
    60606078
    60616079/** @copydoc VBOXHDDBACKEND::pfnGetLCHSGeometry */
    6062 static int vmdkGetLCHSGeometry(void *pBackendData,
    6063                                PPDMMEDIAGEOMETRY pLCHSGeometry)
     6080static int vmdkGetLCHSGeometry(void *pBackendData, PVDGEOMETRY pLCHSGeometry)
    60646081{
    60656082     LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p\n", pBackendData, pLCHSGeometry));
     
    60876104
    60886105/** @copydoc VBOXHDDBACKEND::pfnSetLCHSGeometry */
    6089 static int vmdkSetLCHSGeometry(void *pBackendData,
    6090                                PCPDMMEDIAGEOMETRY pLCHSGeometry)
     6106static int vmdkSetLCHSGeometry(void *pBackendData, PCVDGEOMETRY pLCHSGeometry)
    60916107{
    60926108    LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
     
    64636479    if (pImage)
    64646480    {
    6465         pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n",
     6481        vmdkMessage(pImage, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n",
    64666482                    pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors,
    64676483                    pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors,
    64686484                    VMDK_BYTE2SECTOR(pImage->cbSize));
    6469         pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: uuidCreation={%RTuuid}\n", &pImage->ImageUuid);
    6470         pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: uuidModification={%RTuuid}\n", &pImage->ModificationUuid);
    6471         pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: uuidParent={%RTuuid}\n", &pImage->ParentUuid);
    6472         pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: uuidParentModification={%RTuuid}\n", &pImage->ParentModificationUuid);
    6473     }
    6474 }
    6475 
    6476 
    6477 static int vmdkGetTimeStamp(void *pvBackendData, PRTTIMESPEC pTimeStamp)
    6478 {
    6479     int rc = VERR_NOT_IMPLEMENTED;
    6480     LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
    6481     return rc;
    6482 }
    6483 
    6484 static int vmdkGetParentTimeStamp(void *pvBackendData, PRTTIMESPEC pTimeStamp)
    6485 {
    6486     int rc = VERR_NOT_IMPLEMENTED;
    6487     LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
    6488     return rc;
    6489 }
    6490 
    6491 static int vmdkSetParentTimeStamp(void *pvBackendData, PCRTTIMESPEC pTimeStamp)
    6492 {
    6493     int rc = VERR_NOT_IMPLEMENTED;
    6494     LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
    6495     return rc;
    6496 }
    6497 
    6498 static int vmdkGetParentFilename(void *pvBackendData, char **ppszParentFilename)
    6499 {
    6500     int rc = VERR_NOT_IMPLEMENTED;
    6501     LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
    6502     return rc;
    6503 }
    6504 
    6505 static int vmdkSetParentFilename(void *pvBackendData, const char *pszParentFilename)
    6506 {
    6507     int rc = VERR_NOT_IMPLEMENTED;
    6508     LogFlow(("%s: returned %Rrc\n", __FUNCTION__, rc));
    6509     return rc;
    6510 }
    6511 
    6512 static bool vmdkIsAsyncIOSupported(void *pvBackendData)
    6513 {
    6514     PVMDKIMAGE pImage = (PVMDKIMAGE)pvBackendData;
     6485        vmdkMessage(pImage, "Header: uuidCreation={%RTuuid}\n", &pImage->ImageUuid);
     6486        vmdkMessage(pImage, "Header: uuidModification={%RTuuid}\n", &pImage->ModificationUuid);
     6487        vmdkMessage(pImage, "Header: uuidParent={%RTuuid}\n", &pImage->ParentUuid);
     6488        vmdkMessage(pImage, "Header: uuidParentModification={%RTuuid}\n", &pImage->ParentModificationUuid);
     6489    }
     6490}
     6491
     6492/** @copydoc VBOXHDDBACKEND::pfnIsAsyncIOSupported */
     6493static bool vmdkIsAsyncIOSupported(void *pBackendData)
     6494{
     6495    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    65156496
    65166497    /* We do not support async I/O for stream optimized VMDK images. */
     
    65186499}
    65196500
    6520 static int vmdkAsyncRead(void *pvBackendData, uint64_t uOffset, size_t cbRead,
     6501/** @copydoc VBOXHDDBACKEND::pfnAsyncRead */
     6502static int vmdkAsyncRead(void *pBackendData, uint64_t uOffset, size_t cbRead,
    65216503                         PVDIOCTX pIoCtx, size_t *pcbActuallyRead)
    65226504{
    6523     LogFlowFunc(("pvBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n",
    6524                  pvBackendData, uOffset, pIoCtx, cbRead, pcbActuallyRead));
    6525     PVMDKIMAGE pImage = (PVMDKIMAGE)pvBackendData;
     6505    LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToRead=%zu pcbActuallyRead=%#p\n",
     6506                 pBackendData, uOffset, pIoCtx, cbRead, pcbActuallyRead));
     6507    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    65266508    PVMDKEXTENT pExtent;
    65276509    uint64_t uSectorExtentRel;
     
    65626544        case VMDKETYPE_ESX_SPARSE:
    65636545#endif /* VBOX_WITH_VMDK_ESX */
    6564             rc = vmdkGetSectorAsync(pImage, pIoCtx, pImage->pGTCache, pExtent,
     6546            rc = vmdkGetSectorAsync(pImage, pIoCtx, pExtent,
    65656547                                    uSectorExtentRel, &uSectorExtentAbs);
    65666548            if (RT_FAILURE(rc))
     
    65746556            {
    65756557                AssertMsg(!(pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED), ("Async I/O is not supported for stream optimized VMDK's\n"));
    6576                 rc = pImage->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser,
    6577                                                                      pExtent->pFile->pStorage,
    6578                                                                      VMDK_SECTOR2BYTE(uSectorExtentAbs),
    6579                                                                      pIoCtx, cbRead);
     6558                rc = vmdkFileReadUserAsync(pImage, pExtent->pFile,
     6559                                           VMDK_SECTOR2BYTE(uSectorExtentAbs),
     6560                                           pIoCtx, cbRead);
    65806561            }
    65816562            break;
    65826563        case VMDKETYPE_VMFS:
    65836564        case VMDKETYPE_FLAT:
    6584             rc = pImage->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser,
    6585                                                                  pExtent->pFile->pStorage,
    6586                                                                  VMDK_SECTOR2BYTE(uSectorExtentRel),
    6587                                                                  pIoCtx, cbRead);
     6565            rc = vmdkFileReadUserAsync(pImage, pExtent->pFile,
     6566                                       VMDK_SECTOR2BYTE(uSectorExtentRel),
     6567                                       pIoCtx, cbRead);
    65886568            break;
    65896569        case VMDKETYPE_ZERO:
    65906570            size_t cbSet;
    65916571
    6592             cbSet = pImage->pInterfaceIOCallbacks->pfnIoCtxSet(pImage->pInterfaceIO->pvUser,
    6593                                                                pIoCtx, 0, cbRead);
     6572            cbSet = vmdkFileIoCtxSet(pImage, pIoCtx, 0, cbRead);
    65946573            Assert(cbSet == cbRead);
    65956574
     
    66056584}
    66066585
    6607 static int vmdkAsyncWrite(void *pvBackendData, uint64_t uOffset, size_t cbWrite,
     6586/** @copydoc VBOXHDDBACKEND::pfnAsyncWrite */
     6587static int vmdkAsyncWrite(void *pBackendData, uint64_t uOffset, size_t cbWrite,
    66086588                          PVDIOCTX pIoCtx,
    66096589                          size_t *pcbWriteProcess, size_t *pcbPreRead,
    66106590                          size_t *pcbPostRead, unsigned fWrite)
    66116591{
    6612     LogFlowFunc(("pvBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n",
    6613                  pvBackendData, uOffset, pIoCtx, cbWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));
    6614     PVMDKIMAGE pImage = (PVMDKIMAGE)pvBackendData;
     6592    LogFlowFunc(("pBackendData=%#p uOffset=%llu pIoCtx=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n",
     6593                 pBackendData, uOffset, pIoCtx, cbWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));
     6594    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    66156595    PVMDKEXTENT pExtent;
    66166596    uint64_t uSectorExtentRel;
     
    66606640        case VMDKETYPE_ESX_SPARSE:
    66616641#endif /* VBOX_WITH_VMDK_ESX */
    6662             rc = vmdkGetSectorAsync(pImage, pIoCtx, pImage->pGTCache, pExtent, uSectorExtentRel,
     6642            rc = vmdkGetSectorAsync(pImage, pIoCtx, pExtent, uSectorExtentRel,
    66636643                                    &uSectorExtentAbs);
    66646644            if (RT_FAILURE(rc))
     
    66816661                    {
    66826662                        /* Allocate GT and find out where to store the grain. */
    6683                         rc = vmdkAllocGrainAsync(pImage->pGTCache, pExtent, pIoCtx,
     6663                        rc = vmdkAllocGrainAsync(pImage, pExtent, pIoCtx,
    66846664                                                 uSectorExtentRel, cbWrite);
    66856665                    }
     
    67016681            {
    67026682                Assert(!(pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED));
    6703                 rc = pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser,
    6704                                                                       pExtent->pFile->pStorage,
    6705                                                                       VMDK_SECTOR2BYTE(uSectorExtentAbs),
    6706                                                                       pIoCtx, cbWrite,
    6707                                                                       NULL, NULL);
     6683                rc = vmdkFileWriteUserAsync(pImage, pExtent->pFile,
     6684                                            VMDK_SECTOR2BYTE(uSectorExtentAbs),
     6685                                            pIoCtx, cbWrite, NULL, NULL);
    67086686            }
    67096687            break;
     
    67126690            /* Clip write range to remain in this extent. */
    67136691            cbWrite = RT_MIN(cbWrite, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel));
    6714             rc = pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser,
    6715                                                                   pExtent->pFile->pStorage,
    6716                                                                   VMDK_SECTOR2BYTE(uSectorExtentRel),
    6717                                                                   pIoCtx, cbWrite, NULL, NULL);
     6692            rc = vmdkFileWriteUserAsync(pImage, pExtent->pFile,
     6693                                        VMDK_SECTOR2BYTE(uSectorExtentRel),
     6694                                        pIoCtx, cbWrite, NULL, NULL);
    67186695            break;
    67196696        case VMDKETYPE_ZERO:
     
    67226699            break;
    67236700    }
     6701
    67246702    if (pcbWriteProcess)
    67256703        *pcbWriteProcess = cbWrite;
     
    67306708}
    67316709
    6732 static int vmdkAsyncFlush(void *pvBackendData, PVDIOCTX pIoCtx)
    6733 {
    6734     PVMDKIMAGE pImage = (PVMDKIMAGE)pvBackendData;
     6710/** @copydoc VBOXHDDBACKEND::pfnAsyncFlush */
     6711static int vmdkAsyncFlush(void *pBackendData, PVDIOCTX pIoCtx)
     6712{
     6713    PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData;
    67356714    PVMDKEXTENT pExtent;
    67366715    int rc = VINF_SUCCESS;
     
    67536732                    {
    67546733                        uint64_t cbSize;
    6755                         rc = vmdkFileGetSize(pExtent->pFile, &cbSize);
     6734                        rc = vmdkFileGetSize(pImage, pExtent->pFile, &cbSize);
    67566735                        if (RT_FAILURE(rc))
    67576736                            goto out;
    67586737                        cbSize = RT_ALIGN_64(cbSize, 512);
    6759                         rc = vmdkWriteMetaSparseExtent(pExtent, cbSize - 2*512);
     6738                        rc = vmdkWriteMetaSparseExtent(pImage, pExtent, cbSize - 2*512);
    67606739                        if (RT_FAILURE(rc) && (rc != VERR_VD_ASYNC_IO_IN_PROGRESS))
    67616740                            goto out;
     
    67856764                    && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
    67866765                    && !(pExtent->pszBasename[0] == RTPATH_SLASH))
    6787                     rc = vmdkFileFlushAsync(pExtent->pFile, pIoCtx);
     6766                    rc = vmdkFileFlushAsync(pImage, pExtent->pFile, pIoCtx);
    67886767                break;
    67896768            case VMDKETYPE_ZERO:
     
    68096788    /* uBackendCaps */
    68106789      VD_CAP_UUID | VD_CAP_CREATE_FIXED | VD_CAP_CREATE_DYNAMIC
    6811     | VD_CAP_CREATE_SPLIT_2G | VD_CAP_DIFF | VD_CAP_FILE |VD_CAP_ASYNC,
     6790    | VD_CAP_CREATE_SPLIT_2G | VD_CAP_DIFF | VD_CAP_FILE | VD_CAP_ASYNC
     6791    | VD_CAP_VFS,
    68126792    /* papszFileExtensions */
    68136793    s_apszVmdkFileExtensions,
     
    68756855    vmdkDump,
    68766856    /* pfnGetTimeStamp */
    6877     vmdkGetTimeStamp,
     6857    NULL,
    68786858    /* pfnGetParentTimeStamp */
    6879     vmdkGetParentTimeStamp,
     6859    NULL,
    68806860    /* pfnSetParentTimeStamp */
    6881     vmdkSetParentTimeStamp,
     6861    NULL,
    68826862    /* pfnGetParentFilename */
    6883     vmdkGetParentFilename,
     6863    NULL,
    68846864    /* pfnSetParentFilename */
    6885     vmdkSetParentFilename,
     6865    NULL,
    68866866    /* pfnIsAsyncIOSupported */
    68876867    vmdkIsAsyncIOSupported,
  • trunk/src/VBox/Devices/Storage/testcase/Makefile.kmk

    r32432 r32536  
    9696        $(VBOX_PATH_DEVICES_SRC)/Storage/ParallelsHDDCore.cpp \
    9797        $(VBOX_PATH_DEVICES_SRC)/Storage/DMGHDDCore.cpp
    98  ifdef VBOX_WITH_NEW_IO_CODE
    99  vbox-img_DEFS += VBOX_WITH_NEW_IO_CODE
    100  endif
    10198 vbox-img_DEFS += VBOX_HDD_NO_DYNAMIC_BACKENDS IN_VBOXDDU IN_VBOXDDU_STATIC IN_RT_R3
    10299endif
  • trunk/src/VBox/Devices/Storage/testcase/tstVD.cpp

    r29250 r32536  
    55
    66/*
    7  * Copyright (C) 2006-2007 Oracle Corporation
     7 * Copyright (C) 2006-2010 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    5353}
    5454
    55 static int tstVDMessage(void *pvUser, const char *pszFormat, ...)
    56 {
    57     va_list va;
    58 
     55static int tstVDMessage(void *pvUser, const char *pszFormat, va_list va)
     56{
    5957    RTPrintf("tstVD: ");
    60     va_start(va, pszFormat);
    6158    RTPrintfV(pszFormat, va);
    62     va_end(va);
    6359    return VINF_SUCCESS;
    6460}
     
    6965    int rc;
    7066    PVBOXHDD pVD = NULL;
    71     PDMMEDIAGEOMETRY PCHS = { 0, 0, 0 };
    72     PDMMEDIAGEOMETRY LCHS = { 0, 0, 0 };
     67    VDGEOMETRY      PCHS = { 0, 0, 0 };
     68    VDGEOMETRY      LCHS = { 0, 0, 0 };
    7369    PVDINTERFACE     pVDIfs = NULL;
    7470    VDINTERFACE      VDIError;
     
    127123    int rc;
    128124    PVBOXHDD pVD = NULL;
    129     PDMMEDIAGEOMETRY PCHS = { 0, 0, 0 };
    130     PDMMEDIAGEOMETRY LCHS = { 0, 0, 0 };
     125    VDGEOMETRY      PCHS = { 0, 0, 0 };
     126    VDGEOMETRY      LCHS = { 0, 0, 0 };
    131127    PVDINTERFACE     pVDIfs = NULL;
    132128    VDINTERFACE      VDIError;
     
    509505    PVBOXHDD pVD = NULL;
    510506    char *pszFormat;
    511     PDMMEDIAGEOMETRY PCHS = { 0, 0, 0 };
    512     PDMMEDIAGEOMETRY LCHS = { 0, 0, 0 };
    513     uint64_t u64DiskSize  = 1000 * _1M;
     507    VDGEOMETRY PCHS = { 0, 0, 0 };
     508    VDGEOMETRY LCHS = { 0, 0, 0 };
     509    uint64_t u64DiskSize = 1000 * _1M;
    514510    uint32_t u32SectorSize = 512;
    515511    PVDINTERFACE     pVDIfs = NULL;
     
    551547    {
    552548        RTFileClose(File);
    553         rc = VDGetFormat(NULL, pszBaseFilename, &pszFormat);
     549        rc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */,
     550                         pszBaseFilename, &pszFormat);
    554551        RTPrintf("VDGetFormat() pszFormat=%s rc=%Rrc\n", pszFormat, rc);
    555552        if (RT_SUCCESS(rc) && strcmp(pszFormat, pszBackend))
     
    633630    int rc;
    634631    PVBOXHDD pVD = NULL;
    635     PDMMEDIAGEOMETRY PCHS = { 0, 0, 0 };
    636     PDMMEDIAGEOMETRY LCHS = { 0, 0, 0 };
    637     uint64_t u64DiskSize  = 1000 * _1M;
     632    VDGEOMETRY PCHS = { 0, 0, 0 };
     633    VDGEOMETRY LCHS = { 0, 0, 0 };
     634    uint64_t u64DiskSize = 1000 * _1M;
    638635    uint32_t u32SectorSize = 512;
    639636    PVDINTERFACE     pVDIfs = NULL;
  • trunk/src/VBox/Devices/Storage/testcase/tstVDCopy.cpp

    r31493 r32536  
    9797    AssertRC(rc);
    9898
    99     rc = VDGetFormat(NULL, argv[1], &pszVD1);
     99    rc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */,
     100                     argv[1], &pszVD1);
    100101    CHECK("VDGetFormat() hdd1");
    101102
    102     rc = VDGetFormat(NULL, argv[2], &pszVD2);
     103    rc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */,
     104                     argv[2], &pszVD2);
    103105    CHECK("VDGetFormat() hdd2");
    104106
  • trunk/src/VBox/Devices/Storage/testcase/tstVDShareable.cpp

    r31193 r32536  
    5353}
    5454
    55 static int tstVDMessage(void *pvUser, const char *pszFormat, ...)
     55static int tstVDMessage(void *pvUser, const char *pszFormat, va_list va)
    5656{
    57     va_list va;
    58 
    5957    RTPrintf("tstVD: ");
    60     va_start(va, pszFormat);
    6158    RTPrintfV(pszFormat, va);
    62     va_end(va);
    6359    return VINF_SUCCESS;
    6460}
     
    6965    int rc;
    7066    PVBOXHDD pVD = NULL, pVD2 = NULL;
    71     PDMMEDIAGEOMETRY PCHS = { 0, 0, 0 };
    72     PDMMEDIAGEOMETRY LCHS = { 0, 0, 0 };
     67    VDGEOMETRY      PCHS = { 0, 0, 0 };
     68    VDGEOMETRY      LCHS = { 0, 0, 0 };
    7369    PVDINTERFACE     pVDIfs = NULL;
    7470    VDINTERFACE      VDIError;
  • trunk/src/VBox/Devices/Storage/testcase/tstVDSnap.cpp

    r28800 r32536  
    9292}
    9393
    94 static int tstVDMessage(void *pvUser, const char *pszFormat, ...)
    95 {
    96     va_list va;
    97 
     94static int tstVDMessage(void *pvUser, const char *pszFormat, va_list va)
     95{
    9896    RTPrintf("tstVD: ");
    99     va_start(va, pszFormat);
    10097    RTPrintfV(pszFormat, va);
    101     va_end(va);
    10298    return VINF_SUCCESS;
    10399}
     
    220216    int rc;
    221217    PVBOXHDD pVD = NULL;
    222     PDMMEDIAGEOMETRY PCHS = { 0, 0, 0 };
    223     PDMMEDIAGEOMETRY LCHS = { 0, 0, 0 };
     218    VDGEOMETRY      PCHS = { 0, 0, 0 };
     219    VDGEOMETRY      LCHS = { 0, 0, 0 };
    224220    PVDINTERFACE     pVDIfs = NULL;
    225221    VDINTERFACE      VDIError;
  • trunk/src/VBox/Devices/Storage/testcase/vbox-img.cpp

    r32431 r32536  
    7272}
    7373
    74 static int handleVDMessage(void *pvUser, const char *pszFormat, ...)
     74static int handleVDMessage(void *pvUser, const char *pszFormat, va_list va)
    7575{
    7676    NOREF(pvUser);
    77     va_list args;
    78     va_start(args, pszFormat);
    79     RTPrintfV(pszFormat, args);
    80     va_end(args);
     77    RTPrintfV(pszFormat, va);
    8178    return VINF_SUCCESS;
    8279}
     
    177174        /* Don't pass error interface, as that would triggers error messages
    178175         * because some backends fail to open the image. */
    179         rc = VDGetFormat(NULL, pszFilename, &pszFormat);
     176        rc = VDGetFormat(NULL, NULL, pszFilename, &pszFormat);
    180177        if (RT_FAILURE(rc))
    181178            return errorRuntime("Format autodetect failed: %Rrc\n", rc);
     
    246243    const char *pszDstFilename = NULL;
    247244    char *pszSrcFormat = NULL;
    248     char *pszDstFormat = NULL;
     245    const char *pszDstFormat = NULL;
    249246    const char *pszVariant = NULL;
    250247    PVBOXHDD pSrcDisk = NULL;
     
    338335        if (!pszSrcFormat)
    339336        {
    340             rc = VDGetFormat(NULL, pszSrcFilename, &pszSrcFormat);
     337            rc = VDGetFormat(NULL, NULL, pszSrcFilename, &pszSrcFormat);
    341338            if (RT_FAILURE(rc))
    342339            {
     
    431428    /* just try it */
    432429    char *pszFormat = NULL;
    433     rc = VDGetFormat(NULL, pszFilename, &pszFormat);
     430    rc = VDGetFormat(NULL, NULL, pszFilename, &pszFormat);
    434431    if (RT_FAILURE(rc))
    435432        return errorSyntax("Format autodetect failed: %Rrc\n", rc);
     
    487484    /* just try it */
    488485    char *pszFormat = NULL;
    489     rc = VDGetFormat(NULL, pszFilename, &pszFormat);
     486    rc = VDGetFormat(NULL, NULL, pszFilename, &pszFormat);
    490487    if (RT_FAILURE(rc))
    491488        return errorSyntax("Format autodetect failed: %Rrc\n", rc);
  • trunk/src/VBox/Devices/Storage/testcase/vditool.cpp

    r28855 r32536  
    55
    66/*
    7  * Copyright (C) 2006-2007 Oracle Corporation
     7 * Copyright (C) 2006-2010 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    108108        return PrintDone(rc);
    109109
    110     PDMMEDIAGEOMETRY geo = { 0, 0, 0 }; /* auto-detect */
     110    VDGEOMETRY geo = { 0, 0, 0 }; /* auto-detect */
    111111    rc = VDCreateBase(hdd, "vdi", pszUtf8Filename,
    112112                      (uint64_t)cMBs * _1M,
     
    274274    if (RT_SUCCESS(rc))
    275275    {
    276         PDMMEDIAGEOMETRY LCHSGeometry = {0, 0, 0};
     276        VDGEOMETRY LCHSGeometry = {0, 0, 0};
    277277        rc = VDIDiskSetLCHSGeometry(pVdi, &LCHSGeometry);
    278278    }
  • trunk/src/VBox/Frontends/VBoxManage/VBoxInternalManage.cpp

    r32531 r32536  
    508508}
    509509
    510 static int handleVDMessage(void *pvUser, const char *pszFormat, ...)
     510static int handleVDMessage(void *pvUser, const char *pszFormat, va_list va)
    511511{
    512512    NOREF(pvUser);
    513     va_list args;
    514     va_start(args, pszFormat);
    515     int rc = RTPrintfV(pszFormat, args);
    516     va_end(args);
    517     return rc;
     513    return RTPrintfV(pszFormat, va);
    518514}
    519515
     
    555551    /* just try it */
    556552    char *pszFormat = NULL;
    557     int rc = VDGetFormat(NULL /* pVDIfsDisk */, argv[1], &pszFormat);
     553    int rc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */,
     554                         argv[1], &pszFormat);
    558555    if (RT_FAILURE(rc))
    559556    {
     
    616613    /* just try it */
    617614    char *pszFormat = NULL;
    618     int rc = VDGetFormat(NULL /* pVDIfsDisk */, argv[0], &pszFormat);
     615    int rc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */,
     616                         argv[0], &pszFormat);
    619617    if (RT_FAILURE(rc))
    620618    {
     
    14371435    Assert(RT_MIN(cbSize / 512 / 16 / 63, 16383) -
    14381436           (unsigned int)RT_MIN(cbSize / 512 / 16 / 63, 16383) == 0);
    1439     PDMMEDIAGEOMETRY PCHS, LCHS;
     1437    VDGEOMETRY PCHS, LCHS;
    14401438    PCHS.cCylinders = (unsigned int)RT_MIN(cbSize / 512 / 16 / 63, 16383);
    14411439    PCHS.cHeads = 16;
     
    16411639    {
    16421640        char *pszFormat = NULL;
    1643         vrc = VDGetFormat(NULL /* pVDIfsDisk */, src.c_str(), &pszFormat);
     1641        vrc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */,
     1642                          src.c_str(), &pszFormat);
    16441643        if (RT_FAILURE(vrc))
    16451644        {
     
    17881787        {
    17891788            char *pszFormat = NULL;
    1790             vrc = VDGetFormat(NULL /* pVDIfsDisk */, src.c_str(), &pszFormat);
     1789            vrc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */,
     1790                              src.c_str(), &pszFormat);
    17911791            if (RT_FAILURE(vrc))
    17921792            {
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageDisk.cpp

    r32531 r32536  
    890890    Assert(RT_MIN(cbFile / 512 / 16 / 63, 16383) -
    891891           (unsigned int)RT_MIN(cbFile / 512 / 16 / 63, 16383) == 0);
    892     PDMMEDIAGEOMETRY PCHS, LCHS;
     892    VDGEOMETRY PCHS, LCHS;
    893893    PCHS.cCylinders = (unsigned int)RT_MIN(cbFile / 512 / 16 / 63, 16383);
    894894    PCHS.cHeads = 16;
  • trunk/src/VBox/Main/MediumImpl.cpp

    r32531 r32536  
    35223522            if (RT_SUCCESS(vrc))
    35233523            {
    3524                 vrc = VDGetFormat(NULL, locationFull.c_str(), &backendName);
     3524                vrc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */,
     3525                                  locationFull.c_str(), &backendName);
    35253526            }
    35263527            else if (vrc != VERR_FILE_NOT_FOUND && vrc != VERR_PATH_NOT_FOUND)
     
    35283529                /* assume it's not a file, restore the original location */
    35293530                location = locationFull = aLocation;
    3530                 vrc = VDGetFormat(NULL, locationFull.c_str(), &backendName);
     3531                vrc = VDGetFormat(NULL /* pVDIfsDisk */, NULL /* pVDIfsImage */,
     3532                                  locationFull.c_str(), &backendName);
    35313533            }
    35323534
     
    56095611                throw rc;
    56105612
    5611             PDMMEDIAGEOMETRY geo = { 0, 0, 0 }; /* auto-detect */
     5613            VDGEOMETRY geo = { 0, 0, 0 }; /* auto-detect */
    56125614
    56135615            vrc = VDCreateBase(hdd,
     
    68096811            thisLock.release();
    68106812
    6811             PDMMEDIAGEOMETRY geo = {0, 0, 0}; /* auto */
     6813            VDGEOMETRY geo = {0, 0, 0}; /* auto */
    68126814            vrc = VDResize(hdd, task.mSize, &geo, &geo, task.mVDOperationIfaces);
    68136815            if (RT_FAILURE(vrc))
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r32531 r32536  
    99829982  <enum
    99839983    name="MediumFormatCapabilities"
    9984     uuid="be44ec10-9540-4d3f-aee5-4a4d4c4ad42c"
     9984    uuid="7342ba79-7ce0-4d94-8f86-5ed5a185d9bd"
    99859985  >
    99869986    <desc>
     
    1004910049    </const>
    1005010050
    10051     <const name="CapabilityMask" value="0x1FF"/>
     10051    <const name="VFS" value="0x200">
     10052      <desc>
     10053        The format backend supports virtual filesystem functionality.
     10054      </desc>
     10055    </const>
     10056
     10057    <const name="CapabilityMask" value="0x3FF"/>
    1005210058  </enum>
    1005310059
  • trunk/src/VBox/Runtime/VBox/log-vbox.cpp

    r30732 r32536  
    239239    ASSERT_LOG_GROUP(DRV_HOST_DVD);
    240240    ASSERT_LOG_GROUP(DRV_HOST_FLOPPY);
    241     ASSERT_LOG_GROUP(DRV_ISCSI);
    242     ASSERT_LOG_GROUP(DRV_ISCSI_TRANSPORT_TCP);
    243241    ASSERT_LOG_GROUP(DRV_ISO);
    244242    ASSERT_LOG_GROUP(DRV_KBD_QUEUE);
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