VirtualBox

Changeset 66110 in vbox for trunk


Ignore:
Timestamp:
Mar 15, 2017 12:18:31 PM (8 years ago)
Author:
vboxsync
Message:

Storage/VD: Implement infrastructure for region lists to be able to support CD/DVD image formats which can contain multiple tracks in the future

Location:
trunk
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vd-image-backend.h

    r64272 r66110  
    324324
    325325    /**
     326     * Returns a region list for the disk image if supported, optional.
     327     *
     328     * @returns VBox status code.
     329     * @retval  VERR_NOT_SUPPORTED if region lists are not supported for this kind of image.
     330     * @param   pBackendData    Opaque state data for this image.
     331     * @param   ppRegionList    Where to store the pointer to the region list on success.
     332     */
     333    DECLR3CALLBACKMEMBER(int, pfnQueryRegions, (void *pBackendData, PCVDREGIONLIST *ppRegionList));
     334
     335    /**
     336     * Releases the region list acquired with VDIMAGEBACKEND::pfnQueryRegions() before.
     337     *
     338     * @returns nothing.
     339     * @param   pBackendData    Opaque state data for this image.
     340     * @param   pRegionList     The region list to release.
     341     */
     342    DECLR3CALLBACKMEMBER(void, pfnRegionListRelease, (void *pBackendData, PCVDREGIONLIST pRegionList));
     343
     344    /**
    326345     * Get the image flags of a disk image.
    327346     *
     
    589608
    590609/** The current version of the VDIMAGEBACKEND structure. */
    591 #define VD_IMGBACKEND_VERSION                   VD_VERSION_MAKE(0xff01, 1, 0)
     610#define VD_IMGBACKEND_VERSION                   VD_VERSION_MAKE(0xff01, 2, 0)
    592611
    593612/** @copydoc VDIMAGEBACKEND::pfnComposeLocation */
  • trunk/include/VBox/vd.h

    r64272 r66110  
    494494/** Pointer to constant disk geometry. */
    495495typedef const VDGEOMETRY *PCVDGEOMETRY;
     496
     497/**
     498 * Disk region data form known to us from various standards.
     499 */
     500typedef enum VDREGIONDATAFORM
     501{
     502    /** Invalid data form. */
     503    VDREGIONDATAFORM_INVALID = 0,
     504    /** Raw data, no standardized format. */
     505    VDREGIONDATAFORM_RAW,
     506    /** CD-DA (audio CD), 2352 bytes of data. */
     507    VDREGIONDATAFORM_CDDA,
     508    /** CDDA data is pause. */
     509    VDREGIONDATAFORM_CDDA_PAUSE,
     510    /** Mode 1 with 2048 bytes sector size. */
     511    VDREGIONDATAFORM_MODE1_2048,
     512    /** Mode 1 with 2352 bytes sector size. */
     513    VDREGIONDATAFORM_MODE1_2352,
     514    /** Mode 1 with 0 bytes sector size (generated by the drive). */
     515    VDREGIONDATAFORM_MODE1_0,
     516    /** XA Mode with 2336 bytes sector size. */
     517    VDREGIONDATAFORM_XA_2336,
     518    /** XA Mode with 2352 bytes sector size. */
     519    VDREGIONDATAFORM_XA_2352,
     520    /** XA Mode with 0 bytes sector size (generated by the drive). */
     521    VDREGIONDATAFORM_XA_0,
     522    /** Mode 2 with 2336 bytes sector size. */
     523    VDREGIONDATAFORM_MODE2_2336,
     524    /** Mode 2 with 2352 bytes sector size. */
     525    VDREGIONDATAFORM_MODE2_2352,
     526    /** Mode 2 with 0 bytes sector size (generated by the drive). */
     527    VDREGIONDATAFORM_MODE2_0
     528} VDREGIONDATAFORM;
     529
     530/**
     531 * Disk region metadata forms known to us.
     532 */
     533typedef enum VDREGIONMETADATAFORM
     534{
     535    /** Invalid metadata form. */
     536    VDREGIONMETADATAFORM_INVALID = 0,
     537    /** No metadata assined to the region. */
     538    VDREGIONMETADATAFORM_NONE,
     539    /** Raw metadata, no standardized format. */
     540    VDREGIONMETADATAFORM_RAW
     541} VDREGIONMETADATAFORM;
     542
     543/**
     544 * Disk region descriptor.
     545 */
     546typedef struct VDREGIONDESC
     547{
     548    /** Start of the region in bytes or LBA number (depending on the flag in the
     549     * list header). */
     550    uint64_t                 offRegion;
     551    /** Overall size of the region in bytes or number of blocks (depending on the
     552     * flag in the list header). */
     553    uint64_t                 cRegionBlocksOrBytes;
     554    /** Size of one block in bytes, containing user and metadata. */
     555    uint64_t                 cbBlock;
     556    /** User data form of the block. */
     557    VDREGIONDATAFORM         enmDataForm;
     558    /** Metadata form of the block. */
     559    VDREGIONMETADATAFORM     enmMetadataForm;
     560    /** Size of the data block in bytes. */
     561    uint64_t                 cbData;
     562    /** Size of the metadata in a block in bytes. */
     563    uint64_t                 cbMetadata;
     564} VDREGIONDESC;
     565/** Pointer to a region descriptor. */
     566typedef VDREGIONDESC *PVDREGIONDESC;
     567/** Pointer to a constant region descriptor. */
     568typedef const VDREGIONDESC PCVDREGIONDESC;
     569
     570/**
     571 * Disk region list.
     572 */
     573typedef struct VDREGIONLIST
     574{
     575    /** Flags valid for the region list. */
     576    uint32_t                 fFlags;
     577    /** Number of regions in the descriptor array. */
     578    uint32_t                 cRegions;
     579    /** Region descriptors - variable in size. */
     580    VDREGIONDESC             aRegions[RT_FLEXIBLE_ARRAY];
     581} VDREGIONLIST;
     582/** Pointer to a region list. */
     583typedef VDREGIONLIST *PVDREGIONLIST;
     584/** Pointer to a constant region list. */
     585typedef const VDREGIONLIST *PCVDREGIONLIST;
     586/** Pointer to a region list pointer. */
     587typedef PVDREGIONLIST *PPVDREGIONLIST;
     588
     589/** @name Valid region list flags.
     590 * @{
     591 */
     592/** When set the region start offset and size are given in numbers of blocks
     593 * instead of byte offsets and sizes. */
     594#define VD_REGION_LIST_F_LOC_SIZE_BLOCKS     RT_BIT_32(0)
     595/** Mask of all valid flags. */
     596#define VD_REGION_LIST_F_VALID               (VD_REGION_LIST_F_LOC_SIZE_BLOCKS)
     597/** @} */
    496598
    497599/**
     
    11291231
    11301232/**
     1233 * Queries the available regions of an image in the given VD container.
     1234 *
     1235 * @return  VBox status code.
     1236 * @retval  VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
     1237 * @retval  VERR_NOT_SUPPORTED if the image backend doesn't support region lists.
     1238 * @param   pDisk           Pointer to HDD container.
     1239 * @param   nImage          Image number, counts from 0. 0 is always base image of container.
     1240 * @param   fFlags          Combination of VD_REGION_LIST_F_* flags.
     1241 * @param   ppRegionList    Where to store the pointer to the region list on success, must be freed
     1242 *                          with VDRegionListFree().
     1243 */
     1244VBOXDDU_DECL(int) VDQueryRegions(PVBOXHDD pDisk, unsigned nImage, uint32_t fFlags,
     1245                                 PPVDREGIONLIST ppRegionList);
     1246
     1247/**
     1248 * Frees a region list previously queried with VDQueryRegions().
     1249 *
     1250 * @return  nothing.
     1251 * @param   pRegionList     The region list to free.
     1252 */
     1253VBOXDDU_DECL(void) VDRegionListFree(PVDREGIONLIST pRegionList);
     1254
     1255/**
    11311256 * Get version of image in HDD container.
    11321257 *
  • trunk/src/VBox/Storage/DMG.cpp

    r64272 r66110  
    24522452    /* pfnSetLCHSGeometry */
    24532453    dmgSetLCHSGeometry,
     2454    /* pfnQueryRegions */
     2455    NULL,
     2456    /* pfnRegionListRelease */
     2457    NULL,
    24542458    /* pfnGetImageFlags */
    24552459    dmgGetImageFlags,
  • trunk/src/VBox/Storage/ISCSI.cpp

    r64272 r66110  
    55425542    /* pfnSetLCHSGeometry */
    55435543    iscsiSetLCHSGeometry,
     5544    /* pfnQueryRegions */
     5545    NULL,
     5546    /* pfnRegionListRelease */
     5547    NULL,
    55445548    /* pfnGetImageFlags */
    55455549    iscsiGetImageFlags,
  • trunk/src/VBox/Storage/Parallels.cpp

    r64277 r66110  
    11131113    /* pfnSetLCHSGeometry */
    11141114    parallelsSetLCHSGeometry,
     1115    /* pfnQueryRegions */
     1116    NULL,
     1117    /* pfnRegionListRelease */
     1118    NULL,
    11151119    /* pfnGetImageFlags */
    11161120    parallelsGetImageFlags,
  • trunk/src/VBox/Storage/QCOW.cpp

    r65644 r66110  
    23832383    /* pfnSetLCHSGeometry */
    23842384    qcowSetLCHSGeometry,
     2385    /* pfnQueryRegions */
     2386    NULL,
     2387    /* pfnRegionListRelease */
     2388    NULL,
    23852389    /* pfnGetImageFlags */
    23862390    qcowGetImageFlags,
  • trunk/src/VBox/Storage/QED.cpp

    r65644 r66110  
    24362436    /* pfnSetLCHSGeometry */
    24372437    qedSetLCHSGeometry,
     2438    /* pfnQueryRegions */
     2439    NULL,
     2440    /* pfnRegionListRelease */
     2441    NULL,
    24382442    /* pfnGetImageFlags */
    24392443    qedGetImageFlags,
  • trunk/src/VBox/Storage/RAW.cpp

    r64272 r66110  
    267267                else
    268268                    rc = vdIfError(pImage->pIfError, VERR_DISK_FULL, RT_SRC_POS, N_("Raw: disk would overflow creating image '%s'"), pImage->pszFilename);
     269            }
     270            else
     271            {
     272                rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage, cbSize);
     273                if (RT_SUCCESS(rc))
     274                    pImage->cbSize = cbSize;
    269275            }
    270276        }
     
    10011007    /* pfnSetLCHSGeometry */
    10021008    rawSetLCHSGeometry,
     1009    /* pfnQueryRegions */
     1010    NULL,
     1011    /* pfnRegionListRelease */
     1012    NULL,
    10031013    /* pfnGetImageFlags */
    10041014    rawGetImageFlags,
  • trunk/src/VBox/Storage/VD.cpp

    r64766 r66110  
    57845784
    57855785    RTSemEventSignal(hEvent);
     5786}
     5787
     5788/**
     5789 * Creates a new region list from the given one converting to match the flags if necessary.
     5790 *
     5791 * @returns VBox status code.
     5792 * @param   pRegionList     The region list to convert from.
     5793 * @param   fFlags          The flags for the new region list.
     5794 * @param   ppRegionList    Where to store the new region list on success.
     5795 */
     5796static int vdRegionListConv(PCVDREGIONLIST pRegionList, uint32_t fFlags, PPVDREGIONLIST ppRegionList)
     5797{
     5798    int rc = VINF_SUCCESS;
     5799    PVDREGIONLIST pRegionListNew = (PVDREGIONLIST)RTMemDup(pRegionList, RT_UOFFSETOF(VDREGIONLIST, aRegions[pRegionList->cRegions]));
     5800    if (RT_LIKELY(pRegionListNew))
     5801    {
     5802        /* Do we have to convert anything? */
     5803        if (pRegionList->fFlags != fFlags)
     5804        {
     5805            uint64_t offRegionNext = 0;
     5806
     5807            pRegionListNew->fFlags = fFlags;
     5808            for (unsigned i = 0; i < pRegionListNew->cRegions; i++)
     5809            {
     5810                PVDREGIONDESC pRegion = &pRegionListNew->aRegions[i];
     5811
     5812                if (   (fFlags & VD_REGION_LIST_F_LOC_SIZE_BLOCKS)
     5813                    && !(pRegionList->fFlags & VD_REGION_LIST_F_LOC_SIZE_BLOCKS))
     5814                {
     5815                    Assert(!(pRegion->cRegionBlocksOrBytes % pRegion->cbBlock));
     5816
     5817                    /* Convert from bytes to logical blocks. */
     5818                    pRegion->offRegion            = offRegionNext;
     5819                    pRegion->cRegionBlocksOrBytes = pRegion->cRegionBlocksOrBytes / pRegion->cbBlock;
     5820                    offRegionNext += pRegion->cRegionBlocksOrBytes;
     5821                }
     5822                else
     5823                {
     5824                    /* Convert from logical blocks to bytes. */
     5825                    pRegion->offRegion            = offRegionNext;
     5826                    pRegion->cRegionBlocksOrBytes = pRegion->cRegionBlocksOrBytes * pRegion->cbBlock;
     5827                    offRegionNext += pRegion->cRegionBlocksOrBytes;
     5828                }
     5829            }
     5830        }
     5831
     5832        *ppRegionList = pRegionListNew;
     5833    }
     5834    else
     5835        rc = VERR_NO_MEMORY;
     5836
     5837    return rc;
    57865838}
    57875839
     
    1004210094
    1004310095/**
     10096 * Queries the available regions of an image in the given VD container.
     10097 *
     10098 * @return  VBox status code.
     10099 * @retval  VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
     10100 * @retval  VERR_NOT_SUPPORTED if the image backend doesn't support region lists.
     10101 * @param   pDisk           Pointer to HDD container.
     10102 * @param   nImage          Image number, counts from 0. 0 is always base image of container.
     10103 * @param   fFlags          Combination of VD_REGION_LIST_F_* flags.
     10104 * @param   ppRegionList    Where to store the pointer to the region list on success, must be freed
     10105 *                          with VDRegionListFree().
     10106 */
     10107VBOXDDU_DECL(int) VDQueryRegions(PVBOXHDD pDisk, unsigned nImage, uint32_t fFlags,
     10108                                 PPVDREGIONLIST ppRegionList)
     10109{
     10110    int rc = VINF_SUCCESS;
     10111    int rc2;
     10112    bool fLockRead = false;
     10113
     10114    LogFlowFunc(("pDisk=%#p nImage=%u fFlags=%#x ppRegionList=%#p\n",
     10115                 pDisk, nImage, fFlags, ppRegionList));
     10116    do
     10117    {
     10118        /* sanity check */
     10119        AssertPtrBreakStmt(pDisk, rc = VERR_INVALID_PARAMETER);
     10120        AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
     10121
     10122        /* Check arguments. */
     10123        AssertMsgBreakStmt(VALID_PTR(ppRegionList),
     10124                           ("ppRegionList=%#p\n", ppRegionList),
     10125                           rc = VERR_INVALID_PARAMETER);
     10126
     10127        rc2 = vdThreadStartRead(pDisk);
     10128        AssertRC(rc2);
     10129        fLockRead = true;
     10130
     10131        PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage);
     10132        AssertPtrBreakStmt(pImage, rc = VERR_VD_IMAGE_NOT_FOUND);
     10133
     10134        if (pImage->Backend->pfnQueryRegions)
     10135        {
     10136            PCVDREGIONLIST pRegionList = NULL;
     10137            rc = pImage->Backend->pfnQueryRegions(pImage->pBackendData, &pRegionList);
     10138            if (RT_SUCCESS(rc))
     10139            {
     10140                rc = vdRegionListConv(pRegionList, fFlags, ppRegionList);
     10141
     10142                AssertPtr(pImage->Backend->pfnRegionListRelease);
     10143                pImage->Backend->pfnRegionListRelease(pImage->pBackendData, pRegionList);
     10144            }
     10145        }
     10146        else
     10147            rc = VERR_NOT_SUPPORTED;
     10148
     10149        if (rc == VERR_NOT_SUPPORTED)
     10150        {
     10151            /*
     10152             * Create a list with a single region containing the data gathered from the
     10153             * image and sector size.
     10154             */
     10155            PVDREGIONLIST pRegionList = (PVDREGIONLIST)RTMemAllocZ(RT_UOFFSETOF(VDREGIONLIST, aRegions[1]));
     10156            if (RT_LIKELY(pRegionList))
     10157            {
     10158                uint32_t cbSector = pImage->Backend->pfnGetSectorSize(pImage->pBackendData);
     10159                uint64_t cbImage = pImage->Backend->pfnGetSize(pImage->pBackendData);
     10160
     10161                pRegionList->cRegions = 1;
     10162                pRegionList->fFlags   = fFlags;
     10163
     10164                /*
     10165                 * Single region starting at the first byte/block covering the whole image,
     10166                 * block size equals sector size and contains no metadata.
     10167                 */
     10168                PVDREGIONDESC pRegion = &pRegionList->aRegions[0];
     10169                pRegion->offRegion       = 0; /* Disk start. */
     10170                pRegion->cbBlock         = cbSector;
     10171                pRegion->enmDataForm     = VDREGIONDATAFORM_RAW;
     10172                pRegion->enmMetadataForm = VDREGIONMETADATAFORM_NONE;
     10173                pRegion->cbData          = cbSector;
     10174                pRegion->cbMetadata      = 0;
     10175                if (fFlags & VD_REGION_LIST_F_LOC_SIZE_BLOCKS)
     10176                    pRegion->cRegionBlocksOrBytes = cbImage / cbSector;
     10177                else
     10178                    pRegion->cRegionBlocksOrBytes = cbImage;
     10179
     10180                *ppRegionList  = pRegionList;
     10181            }
     10182            else
     10183                rc = VERR_NO_MEMORY;
     10184        }
     10185    } while (0);
     10186
     10187    if (RT_UNLIKELY(fLockRead))
     10188    {
     10189        rc2 = vdThreadFinishRead(pDisk);
     10190        AssertRC(rc2);
     10191    }
     10192
     10193    LogFlowFunc((": %Rrc\n", rc));
     10194    return rc;
     10195}
     10196
     10197/**
     10198 * Frees a region list previously queried with VDQueryRegions().
     10199 *
     10200 * @return  nothing.
     10201 * @param   pRegionList     The region list to free.
     10202 */
     10203VBOXDDU_DECL(void) VDRegionListFree(PVDREGIONLIST pRegionList)
     10204{
     10205    RTMemFree(pRegionList);
     10206}
     10207
     10208/**
    1004410209 * Get version of image in HDD container.
    1004510210 *
  • trunk/src/VBox/Storage/VDI.cpp

    r65644 r66110  
    31383138    /* pfnSetLCHSGeometry */
    31393139    vdiSetLCHSGeometry,
     3140    /* pfnQueryRegions */
     3141    NULL,
     3142    /* pfnRegionListRelease */
     3143    NULL,
    31403144    /* pfnGetImageFlags */
    31413145    vdiGetImageFlags,
  • trunk/src/VBox/Storage/VHD.cpp

    r64272 r66110  
    30583058    /* pfnSetLCHSGeometry */
    30593059    vhdSetLCHSGeometry,
     3060    /* pfnQueryRegions */
     3061    NULL,
     3062    /* pfnRegionListRelease */
     3063    NULL,
    30603064    /* pfnGetImageFlags */
    30613065    vhdGetImageFlags,
  • trunk/src/VBox/Storage/VHDX.cpp

    r64272 r66110  
    25342534    /* pfnSetLCHSGeometry */
    25352535    vhdxSetLCHSGeometry,
     2536    /* pfnQueryRegions */
     2537    NULL,
     2538    /* pfnRegionListRelease */
     2539    NULL,
    25362540    /* pfnGetImageFlags */
    25372541    vhdxGetImageFlags,
  • trunk/src/VBox/Storage/VMDK.cpp

    r64272 r66110  
    64156415    /* pfnSetLCHSGeometry */
    64166416    vmdkSetLCHSGeometry,
     6417    /* pfnQueryRegions */
     6418    NULL,
     6419    /* pfnRegionListRelease */
     6420    NULL,
    64176421    /* pfnGetImageFlags */
    64186422    vmdkGetImageFlags,
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