VirtualBox

Changeset 33182 in vbox for trunk/src/VBox/Devices/Storage


Ignore:
Timestamp:
Oct 18, 2010 8:30:05 AM (14 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
66718
Message:

Devices/Storage: implement sequential reading of streamOptimized VMDK images

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

Legend:

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

    r32768 r33182  
    20962096    int rc;
    20972097
    2098     /* Image must be opened and the new flags must be valid. Just readonly and
    2099      * info flags are supported. */
    2100     if (!pThis || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO || VD_OPEN_FLAGS_SHAREABLE)))
     2098    /* Image must be opened and the new flags must be valid. */
     2099    if (!pThis || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO || VD_OPEN_FLAGS_SHAREABLE | VD_OPEN_FLAGS_SEQUENTIAL)))
    21012100    {
    21022101        rc = VERR_INVALID_PARAMETER;
  • trunk/src/VBox/Devices/Storage/ISCSIHDDCore.cpp

    r33124 r33182  
    48934893    int rc;
    48944894
    4895     /* Image must be opened and the new flags must be valid. Just readonly and
    4896      * info flags are supported. */
    4897     if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE)))
     4895    /* Image must be opened and the new flags must be valid. */
     4896    if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE | VD_OPEN_FLAGS_SEQUENTIAL)))
    48984897    {
    48994898        rc = VERR_INVALID_PARAMETER;
  • trunk/src/VBox/Devices/Storage/ParallelsHDDCore.cpp

    r32553 r33182  
    957957    int rc;
    958958
    959     /* Image must be opened and the new flags must be valid. Just readonly and
    960      * info flags are supported. */
     959    /* Image must be opened and the new flags must be valid. */
    961960    /** @todo r=klaus add VD_OPEN_FLAGS_ASYNC_IO when async io has been tested */
    962     if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_SHAREABLE)))
     961    if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_SHAREABLE | VD_OPEN_FLAGS_SEQUENTIAL)))
    963962    {
    964963        rc = VERR_INVALID_PARAMETER;
  • trunk/src/VBox/Devices/Storage/RawHDDCore.cpp

    r32598 r33182  
    926926    int rc;
    927927
    928     /* Image must be opened and the new flags must be valid. Just readonly and
    929      * info flags are supported. */
    930     if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE)))
     928    /* Image must be opened and the new flags must be valid. */
     929    if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE | VD_OPEN_FLAGS_SEQUENTIAL)))
    931930    {
    932931        rc = VERR_INVALID_PARAMETER;
  • trunk/src/VBox/Devices/Storage/VDIHDDCore.cpp

    r33081 r33182  
    16361636    const char *pszFilename;
    16371637
    1638     /* Image must be opened and the new flags must be valid. Just readonly and
    1639      * info flags are supported. */
    1640     if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE)))
     1638    /* Image must be opened and the new flags must be valid. */
     1639    if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE | VD_OPEN_FLAGS_SEQUENTIAL)))
    16411640    {
    16421641        rc = VERR_INVALID_PARAMETER;
  • trunk/src/VBox/Devices/Storage/VHDHDDCore.cpp

    r33131 r33182  
    20802080    int rc;
    20812081
    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)))
     2082    /* Image must be opened and the new flags must be valid. */
     2083    if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE | VD_OPEN_FLAGS_SEQUENTIAL)))
    20852084    {
    20862085        rc = VERR_INVALID_PARAMETER;
  • trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp

    r33088 r33182  
    306306    /** Append position for writing new grain. Only for sparse extents. */
    307307    uint64_t    uAppendPosition;
    308     /** Last grain which has been written to. Only for streamOptimized extents. */
    309     uint32_t    uLastGrainWritten;
    310     /** Sector number of last grain which has been written to. Only for
    311      * streamOptimized extents. */
    312     uint32_t    uLastGrainSector;
    313     /** Starting sector of the decompressed grain buffer. */
    314     uint32_t    uGrainSector;
     308    /** Last grain which was accessed. Only for streamOptimized extents. */
     309    uint32_t    uLastGrainAccess;
     310    /** Starting sector corresponding to the grain buffer. */
     311    uint32_t    uGrainSectorAbs;
     312    /** Grain number corresponding to the grain buffer. */
     313    uint32_t    uGrain;
     314    /** Actual size of the compressed data, only valid for reading. */
     315    uint32_t    cbGrainStreamRead;
    315316    /** Size of compressed grain buffer for streamOptimized extents. */
    316317    size_t      cbCompGrain;
     
    523524*******************************************************************************/
    524525
     526static void vmdkFreeStreamBuffers(PVMDKEXTENT pExtent);
    525527static void vmdkFreeExtentData(PVMDKIMAGE pImage, PVMDKEXTENT pExtent,
    526528                               bool fDelete);
     
    869871DECLINLINE(int) vmdkFileInflateSync(PVMDKIMAGE pImage, PVMDKEXTENT pExtent,
    870872                                    uint64_t uOffset, void *pvBuf,
    871                                     size_t cbToRead, uint64_t *puLBA,
    872                                     uint32_t *pcbMarkerData)
     873                                    size_t cbToRead, const void *pcvMarker,
     874                                    uint64_t *puLBA, uint32_t *pcbMarkerData)
    873875{
    874876    if (pExtent->pFile->fAsyncIO)
     
    884886        size_t cbCompSize, cbActuallyRead;
    885887
    886         rc = vmdkFileReadSync(pImage, pExtent->pFile, uOffset, pMarker,
    887                               RT_OFFSETOF(VMDKMARKER, uType), NULL);
    888         if (RT_FAILURE(rc))
    889             return rc;
     888        if (!pcvMarker)
     889        {
     890            rc = vmdkFileReadSync(pImage, pExtent->pFile, uOffset, pMarker,
     891                                  RT_OFFSETOF(VMDKMARKER, uType), NULL);
     892            if (RT_FAILURE(rc))
     893                return rc;
     894        }
     895        else
     896            memcpy(pMarker, pcvMarker, RT_OFFSETOF(VMDKMARKER, uType));
     897
    890898        cbCompSize = RT_LE2H_U32(pMarker->cbSize);
    891899        if (cbCompSize == 0)
     
    11571165
    11581166/**
    1159  * Internal: allocate all buffers associated with grain directories. This
    1160  * includes the compressed/uncompressed buffers for streamOptimized images.
     1167 * Internal: allocate the compressed/uncompressed buffers for streamOptimized
     1168 * images.
    11611169 */
    1162 static int vmdkAllocGrainDirectory(PVMDKIMAGE pImage, PVMDKEXTENT pExtent)
     1170static int vmdkAllocStreamBuffers(PVMDKIMAGE pImage, PVMDKEXTENT pExtent)
    11631171{
    11641172    int rc = VINF_SUCCESS;
    1165     size_t cbGD = pExtent->cGDEntries * sizeof(uint32_t);
    1166     uint32_t *pGD = NULL, *pRGD = NULL;
    1167 
    1168     pGD = (uint32_t *)RTMemAllocZ(cbGD);
    1169     if (!pGD)
    1170     {
    1171         rc = VERR_NO_MEMORY;
    1172         goto out;
    1173     }
    1174     pExtent->pGD = pGD;
    1175 
    1176     if (pExtent->uSectorRGD)
    1177     {
    1178         pRGD = (uint32_t *)RTMemAllocZ(cbGD);
    1179         if (!pRGD)
    1180         {
    1181             rc = VERR_NO_MEMORY;
    1182             goto out;
    1183         }
    1184         pExtent->pRGD = pRGD;
    1185     }
    11861173
    11871174    if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
     
    12101197out:
    12111198    if (RT_FAILURE(rc))
     1199        vmdkFreeStreamBuffers(pExtent);
     1200    return rc;
     1201}
     1202
     1203/**
     1204 * Internal: allocate all buffers associated with grain directories.
     1205 */
     1206static int vmdkAllocGrainDirectory(PVMDKIMAGE pImage, PVMDKEXTENT pExtent)
     1207{
     1208    int rc = VINF_SUCCESS;
     1209    size_t cbGD = pExtent->cGDEntries * sizeof(uint32_t);
     1210    uint32_t *pGD = NULL, *pRGD = NULL;
     1211
     1212    pGD = (uint32_t *)RTMemAllocZ(cbGD);
     1213    if (!pGD)
     1214    {
     1215        rc = VERR_NO_MEMORY;
     1216        goto out;
     1217    }
     1218    pExtent->pGD = pGD;
     1219
     1220    if (pExtent->uSectorRGD)
     1221    {
     1222        pRGD = (uint32_t *)RTMemAllocZ(cbGD);
     1223        if (!pRGD)
     1224        {
     1225            rc = VERR_NO_MEMORY;
     1226            goto out;
     1227        }
     1228        pExtent->pRGD = pRGD;
     1229    }
     1230
     1231out:
     1232    if (RT_FAILURE(rc))
    12121233        vmdkFreeGrainDirectory(pExtent);
    12131234    return rc;
     
    12231244    if (pExtent->enmType != VMDKETYPE_HOSTED_SPARSE)
    12241245        goto out;
     1246
     1247    if (   pExtent->uSectorGD == VMDK_GD_AT_END
     1248        || pExtent->uSectorRGD == VMDK_GD_AT_END)
     1249    {
     1250        rc = VERR_INTERNAL_ERROR;
     1251        goto out;
     1252    }
    12251253
    12261254    rc = vmdkAllocGrainDirectory(pImage, pExtent);
     
    13901418        pExtent->uSectorGD = uStartSector + VMDK_BYTE2SECTOR(cbGDRounded + cbGTRounded);
    13911419    }
     1420
     1421    rc = vmdkAllocStreamBuffers(pImage, pExtent);
     1422    if (RT_FAILURE(rc))
     1423        goto out;
    13921424
    13931425    rc = vmdkAllocGrainDirectory(pImage, pExtent);
     
    26762708 * as found in monolithic files.
    26772709 */
    2678 static int vmdkReadBinaryMetaExtent(PVMDKIMAGE pImage, PVMDKEXTENT pExtent)
     2710static int vmdkReadBinaryMetaExtent(PVMDKIMAGE pImage, PVMDKEXTENT pExtent,
     2711                                    bool fMagicAlreadyRead)
    26792712{
    26802713    SparseExtentHeader Header;
    26812714    uint64_t cSectorsPerGDE;
    2682 
    2683     int rc = vmdkFileReadSync(pImage, pExtent->pFile, 0, &Header, sizeof(Header), NULL);
     2715    uint64_t cbFile = 0;
     2716    int rc;
     2717
     2718    if (fMagicAlreadyRead)
     2719        rc = vmdkFileReadSync(pImage, pExtent->pFile, 0, &Header,
     2720                              sizeof(Header), NULL);
     2721    else
     2722    {
     2723        Header.magicNumber = RT_H2LE_U32(VMDK_SPARSE_MAGICNUMBER);
     2724        rc = vmdkFileReadSync(pImage, pExtent->pFile,
     2725                              RT_OFFSETOF(SparseExtentHeader, version),
     2726                              &Header.version,
     2727                                sizeof(Header)
     2728                              - RT_OFFSETOF(SparseExtentHeader, version),
     2729                              NULL);
     2730    }
    26842731    AssertRC(rc);
    26852732    if (RT_FAILURE(rc))
     
    26922739        goto out;
    26932740
    2694     rc = vmdkFileGetSize(pImage, pExtent->pFile, &pExtent->uAppendPosition);
    2695     AssertRC(rc);
    2696     if (RT_FAILURE(rc))
    2697     {
    2698         rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot get size of '%s'"), pExtent->pszFullname);
    2699         goto out;
    2700     }
    2701     pExtent->uAppendPosition = RT_ALIGN_64(pExtent->uAppendPosition, 512);
    2702 
    27032741    if (    RT_LE2H_U32(Header.flags & RT_BIT(17))
    27042742        &&  RT_LE2H_U64(Header.gdOffset) == VMDK_GD_AT_END)
     2743        pExtent->fFooter = true;
     2744
     2745    if (   !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     2746        || (   pExtent->fFooter
     2747            && !(pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL)))
     2748    {
     2749        rc = vmdkFileGetSize(pImage, pExtent->pFile, &cbFile);
     2750        AssertRC(rc);
     2751        if (RT_FAILURE(rc))
     2752        {
     2753            rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot get size of '%s'"), pExtent->pszFullname);
     2754            goto out;
     2755        }
     2756    }
     2757
     2758    if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
     2759        pExtent->uAppendPosition = RT_ALIGN_64(cbFile, 512);
     2760
     2761    if (   !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     2762        || (   pExtent->fFooter
     2763            && !(pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL)))
    27052764    {
    27062765        /* Read the footer, which comes before the end-of-stream marker. */
    27072766        rc = vmdkFileReadSync(pImage, pExtent->pFile,
    2708                               pExtent->uAppendPosition - 2*512, &Header,
     2767                              cbFile - 2*512, &Header,
    27092768                              sizeof(Header), NULL);
    27102769        AssertRC(rc);
     
    27172776        if (RT_FAILURE(rc))
    27182777            goto out;
    2719         pExtent->fFooter = true;
    27202778        /* Prohibit any writes to this extent. */
    27212779        pExtent->uAppendPosition = 0;
    27222780    }
     2781
    27232782    pExtent->uVersion = RT_LE2H_U32(Header.version);
    27242783    pExtent->enmType = VMDKETYPE_HOSTED_SPARSE; /* Just dummy value, changed later. */
     
    27432802        pExtent->uSectorRGD = 0;
    27442803    }
    2745     if (pExtent->uSectorGD == VMDK_GD_AT_END || pExtent->uSectorRGD == VMDK_GD_AT_END)
     2804    if (   (   pExtent->uSectorGD == VMDK_GD_AT_END
     2805            || pExtent->uSectorRGD == VMDK_GD_AT_END)
     2806        && (   !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     2807            || !(pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL)))
    27462808    {
    27472809        rc = vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: cannot resolve grain directory offset in '%s'"), pExtent->pszFullname);
     
    27862848{
    27872849    int rc = VINF_SUCCESS;
     2850
     2851/* disabled the check as there are too many truncated vmdk images out there */
     2852#ifdef VBOX_WITH_VMDK_STRICT_SIZE_CHECK
    27882853    uint64_t cbExtentSize;
    2789 
    27902854    /* The image must be a multiple of a sector in size and contain the data
    27912855     * area (flat images only). If not, it means the image is at least
     
    27972861        goto out;
    27982862    }
    2799 /* disabled the check as there are too many truncated vmdk images out there */
    2800 #ifdef VBOX_WITH_VMDK_STRICT_SIZE_CHECK
    28012863    if (    cbExtentSize != RT_ALIGN_64(cbExtentSize, 512)
    28022864        &&  (pExtent->enmType != VMDKETYPE_FLAT || pExtent->cNominalSectors + pExtent->uSectorOffset > VMDK_BYTE2SECTOR(cbExtentSize)))
     
    28272889    }
    28282890
     2891    rc = vmdkAllocStreamBuffers(pImage, pExtent);
     2892    if (RT_FAILURE(rc))
     2893        goto out;
     2894
    28292895    /* Prohibit any writes to this streamOptimized extent. */
    28302896    if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
    28312897        pExtent->uAppendPosition = 0;
    28322898
    2833     rc = vmdkReadGrainDirectory(pImage, pExtent);
     2899    if (   !(pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
     2900        || !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     2901        || !(pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL))
     2902        rc = vmdkReadGrainDirectory(pImage, pExtent);
     2903    else
     2904    {
     2905        pExtent->uGrainSectorAbs = pExtent->cOverheadSectors;
     2906        pExtent->cbGrainStreamRead = 0;
     2907    }
    28342908
    28352909out:
     
    30343108
    30353109/**
     3110 * Internal: free the buffers used for streamOptimized images.
     3111 */
     3112static void vmdkFreeStreamBuffers(PVMDKEXTENT pExtent)
     3113{
     3114    if (pExtent->pvCompGrain)
     3115    {
     3116        RTMemFree(pExtent->pvCompGrain);
     3117        pExtent->pvCompGrain = NULL;
     3118    }
     3119    if (pExtent->pvGrain)
     3120    {
     3121        RTMemFree(pExtent->pvGrain);
     3122        pExtent->pvGrain = NULL;
     3123    }
     3124}
     3125
     3126/**
    30363127 * Internal: free the memory used by the extent data structure, optionally
    30373128 * deleting the referenced files.
     
    30643155        pExtent->pszFullname = NULL;
    30653156    }
    3066     if (pExtent->pvCompGrain)
    3067     {
    3068         RTMemFree(pExtent->pvCompGrain);
    3069         pExtent->pvCompGrain = NULL;
    3070     }
    3071     if (pExtent->pvGrain)
    3072     {
    3073         RTMemFree(pExtent->pvGrain);
    3074         pExtent->pvGrain = NULL;
    3075     }
     3157    vmdkFreeStreamBuffers(pExtent);
    30763158}
    30773159
     
    32083290            goto out;
    32093291        }
    3210         rc = vmdkReadBinaryMetaExtent(pImage, pExtent);
     3292        rc = vmdkReadBinaryMetaExtent(pImage, pExtent, false /* fMagicAlreadyRead */);
    32113293        if (RT_FAILURE(rc))
    32123294            goto out;
     
    33993481                        goto out;
    34003482                    }
    3401                     rc = vmdkReadBinaryMetaExtent(pImage, pExtent);
     3483                    rc = vmdkReadBinaryMetaExtent(pImage, pExtent,
     3484                                                  true /* fMagicAlreadyRead */);
    34023485                    if (RT_FAILURE(rc))
    34033486                        goto out;
     
    34893572    }
    34903573
    3491     rc = vmdkAllocateGrainTableCache(pImage);
    3492     if (RT_FAILURE(rc))
    3493         goto out;
     3574    if (   !(pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
     3575        || !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     3576        || !(pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL))
     3577        rc = vmdkAllocateGrainTableCache(pImage);
    34943578
    34953579out:
     
    44324516            /* No need to write any pending data if the file will be deleted
    44334517             * or if the new file wasn't successfully created. */
    4434             if (!fDelete && pImage->pExtents && pImage->pExtents[0].cGTEntries)
     4518            if (   !fDelete && pImage->pExtents
     4519                && pImage->pExtents[0].cGTEntries
     4520                && pImage->pExtents[0].uAppendPosition)
    44354521            {
    44364522                PVMDKEXTENT pExtent = &pImage->pExtents[0];
    4437                 uint32_t uLastGDEntry = pExtent->uLastGrainWritten / pExtent->cGTEntries;
     4523                uint32_t uLastGDEntry = pExtent->uLastGrainAccess / pExtent->cGTEntries;
    44384524                if (uLastGDEntry != pExtent->cGDEntries - 1)
    44394525                {
     
    47454831    int rc;
    47464832
    4747     /* For newly created streamOptimized images this must be a no-op. */
    4748     if (   pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED
    4749         && pExtent->uAppendPosition)
     4833    /* For newly created and readonly/sequentially opened streamOptimized
     4834     * images this must be a no-op, as the grain directory is not there. */
     4835    if (   (   pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED
     4836            && pExtent->uAppendPosition)
     4837        || (   pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED
     4838            && pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY
     4839            && pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL))
    47504840    {
    47514841        *puExtentSector = 0;
     
    49875077        /* Invalidate cache, just in case some code incorrectly allows mixing
    49885078         * of reads and writes. Normally shouldn't be needed. */
    4989         pExtent->uGrainSector = 0;
    4990         pExtent->uLastGrainSector = 0;
     5079        pExtent->uGrainSectorAbs = 0;
    49915080
    49925081        /* Write compressed data block and the markers. */
     
    49995088            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write allocated compressed data block in '%s'"), pExtent->pszFullname);
    50005089        }
    5001         pExtent->uLastGrainWritten = uSector / pExtent->cSectorsPerGrain;
     5090        pExtent->uLastGrainAccess = uSector / pExtent->cSectorsPerGrain;
    50025091        pExtent->uAppendPosition += cbGrain;
    50035092    }
     
    51005189    uCacheEntry = uGrain % VMDK_GT_CACHELINE_SIZE;
    51015190    uGDEntry = uGrain / pExtent->cGTEntries;
    5102     uLastGDEntry = pExtent->uLastGrainWritten / pExtent->cGTEntries;
    5103     if (uGrain < pExtent->uLastGrainWritten)
     5191    uLastGDEntry = pExtent->uLastGrainAccess / pExtent->cGTEntries;
     5192    if (uGrain < pExtent->uLastGrainAccess)
    51045193        return VERR_VD_VMDK_INVALID_WRITE;
    51055194
     
    51545243    if (RT_FAILURE(rc))
    51555244    {
    5156         pExtent->uGrainSector = 0;
    5157         pExtent->uLastGrainSector = 0;
     5245        pExtent->uGrainSectorAbs = 0;
    51585246        AssertRC(rc);
    51595247        return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write compressed data block in '%s'"), pExtent->pszFullname);
    51605248    }
    5161     pExtent->uLastGrainSector = VMDK_BYTE2SECTOR(uFileOffset);
    5162     pExtent->uLastGrainWritten = uGrain;
     5249    pExtent->uLastGrainAccess = uGrain;
    51635250    pExtent->uAppendPosition += cbGrain;
    51645251
     
    54705557
    54715558    return rc;
     5559}
     5560
     5561/**
     5562 * Internal. Reads the contents by sequentially going over the compressed
     5563 * grains (hoping that they are in sequence).
     5564 */
     5565static int vmdkStreamReadSequential(PVMDKIMAGE pImage, PVMDKEXTENT pExtent,
     5566                                    uint64_t uSector, void *pvBuf,
     5567                                    uint64_t cbRead)
     5568{
     5569    int rc;
     5570
     5571    /* Do not allow to go back. */
     5572    uint32_t uGrain = uSector / pExtent->cSectorsPerGrain;
     5573    if (uGrain < pExtent->uLastGrainAccess)
     5574        return VERR_VD_VMDK_INVALID_STATE;
     5575    pExtent->uLastGrainAccess = uGrain;
     5576
     5577    /* After a previous error do not attempt to recover, as it would need
     5578     * seeking (in the general case backwards which is forbidden). */
     5579    if (!pExtent->uGrainSectorAbs)
     5580        return VERR_VD_VMDK_INVALID_STATE;
     5581
     5582    /* Check if we need to read something from the image or if what we have
     5583     * in the buffer is good to fulfill the request. */
     5584    if (!pExtent->cbGrainStreamRead || uGrain > pExtent->uGrain)
     5585    {
     5586        uint32_t uGrainSectorAbs =   pExtent->uGrainSectorAbs
     5587                                   + VMDK_BYTE2SECTOR(pExtent->cbGrainStreamRead);
     5588
     5589        /* Get the marker from the next data block - and skip everything which
     5590         * is not a compressed grain. If it's a compressed grain which is for
     5591         * the requested sector (or after), read it. */
     5592        VMDKMARKER Marker;
     5593        do
     5594        {
     5595            RT_ZERO(Marker);
     5596            rc = vmdkFileReadSync(pImage, pExtent->pFile,
     5597                                  VMDK_SECTOR2BYTE(uGrainSectorAbs),
     5598                                  &Marker, RT_OFFSETOF(VMDKMARKER, uType),
     5599                                  NULL);
     5600            if (RT_FAILURE(rc))
     5601                return rc;
     5602            Marker.uSector = RT_LE2H_U64(Marker.uSector);
     5603            Marker.cbSize = RT_LE2H_U32(Marker.cbSize);
     5604
     5605            if (Marker.cbSize == 0)
     5606            {
     5607                /* A marker for something else than a compressed grain. */
     5608                rc = vmdkFileReadSync(pImage, pExtent->pFile,
     5609                                        VMDK_SECTOR2BYTE(uGrainSectorAbs)
     5610                                      + RT_OFFSETOF(VMDKMARKER, uType),
     5611                                      &Marker.uType, sizeof(Marker.uType),
     5612                                      NULL);
     5613                Marker.uType = RT_LE2H_U32(Marker.uType);
     5614                switch (Marker.uType)
     5615                {
     5616                    case VMDK_MARKER_EOS:
     5617                        uGrainSectorAbs++;
     5618                        break;
     5619                    case VMDK_MARKER_GT:
     5620                        uGrainSectorAbs += 1 + VMDK_BYTE2SECTOR(pExtent->cGTEntries * sizeof(uint32_t));
     5621                        break;
     5622                    case VMDK_MARKER_GD:
     5623                        uGrainSectorAbs += 1 + VMDK_BYTE2SECTOR(RT_ALIGN(pExtent->cGDEntries * sizeof(uint32_t), 512));
     5624                        break;
     5625                    case VMDK_MARKER_FOOTER:
     5626                        uGrainSectorAbs += 2;
     5627                        break;
     5628                    default:
     5629                        AssertMsgFailed(("VMDK: corrupted marker, type=%#x\n", Marker.uType));
     5630                        pExtent->uGrainSectorAbs = 0;
     5631                        return VERR_VD_VMDK_INVALID_STATE;
     5632                }
     5633                pExtent->cbGrainStreamRead = 0;
     5634            }
     5635            else
     5636            {
     5637                /* A compressed grain marker. If it is at/after what we're
     5638                 * interested in read and decompress data. */
     5639                if (uSector > Marker.uSector + pExtent->cSectorsPerGrain)
     5640                {
     5641                    uGrainSectorAbs += VMDK_BYTE2SECTOR(RT_ALIGN(Marker.cbSize + RT_OFFSETOF(VMDKMARKER, uType), 512));
     5642                    continue;
     5643                }
     5644                uint64_t uLBA;
     5645                uint32_t cbGrainStreamRead = 0;
     5646                rc = vmdkFileInflateSync(pImage, pExtent,
     5647                                         VMDK_SECTOR2BYTE(uGrainSectorAbs),
     5648                                         pExtent->pvGrain,
     5649                                         VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain),
     5650                                         &Marker, &uLBA, &cbGrainStreamRead);
     5651                if (RT_FAILURE(rc))
     5652                {
     5653                    pExtent->uGrainSectorAbs = 0;
     5654                    return rc;
     5655                }
     5656                if (   pExtent->uGrain
     5657                    && uLBA / pExtent->cSectorsPerGrain <= pExtent->uGrain)
     5658                {
     5659                    pExtent->uGrainSectorAbs = 0;
     5660                    return VERR_VD_VMDK_INVALID_STATE;
     5661                }
     5662                pExtent->uGrain = uLBA / pExtent->cSectorsPerGrain;
     5663                pExtent->cbGrainStreamRead = cbGrainStreamRead;
     5664                break;
     5665            }
     5666        } while (Marker.uType != VMDK_MARKER_EOS);
     5667
     5668        pExtent->uGrainSectorAbs = uGrainSectorAbs;
     5669
     5670        if (!pExtent->cbGrainStreamRead && Marker.uType == VMDK_MARKER_EOS)
     5671        {
     5672            pExtent->uGrain = UINT32_MAX;
     5673            /* Must set a non-zero value for pExtent->cbGrainStreamRead or
     5674             * the next read would try to get more data, and we're at EOF. */
     5675            pExtent->cbGrainStreamRead = 1;
     5676        }
     5677    }
     5678
     5679    if (pExtent->uGrain > uSector / pExtent->cSectorsPerGrain)
     5680    {
     5681        /* The next data block we have is not for this area, so just return
     5682         * that there is no data. */
     5683        return VERR_VD_BLOCK_FREE;
     5684    }
     5685
     5686    uint32_t uSectorInGrain = uSector % pExtent->cSectorsPerGrain;
     5687    memcpy(pvBuf,
     5688           (uint8_t *)pExtent->pvGrain + VMDK_SECTOR2BYTE(uSectorInGrain),
     5689           cbRead);
     5690    return VINF_SUCCESS;
    54725691}
    54735692
     
    60216240            Assert(!(cbToRead % 512));
    60226241            if (uSectorExtentAbs == 0)
    6023                 rc = VERR_VD_BLOCK_FREE;
     6242            {
     6243                if (   !(pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
     6244                    || !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     6245                    || !(pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL))
     6246                    rc = VERR_VD_BLOCK_FREE;
     6247                else
     6248                    rc = vmdkStreamReadSequential(pImage, pExtent,
     6249                                                  uSectorExtentRel,
     6250                                                  pvBuf, cbToRead);
     6251            }
    60246252            else
    60256253            {
     
    60296257                    uSectorExtentAbs -= uSectorInGrain;
    60306258                    uint64_t uLBA;
    6031                     if (pExtent->uGrainSector != uSectorExtentAbs)
     6259                    if (pExtent->uGrainSectorAbs != uSectorExtentAbs)
    60326260                    {
    60336261                        rc = vmdkFileInflateSync(pImage, pExtent,
     
    60356263                                                 pExtent->pvGrain,
    60366264                                                 VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain),
    6037                                                  &uLBA, NULL);
     6265                                                 NULL, &uLBA, NULL);
    60386266                        if (RT_FAILURE(rc))
    60396267                        {
    6040                             pExtent->uGrainSector = 0;
     6268                            pExtent->uGrainSectorAbs = 0;
    60416269                            AssertRC(rc);
    60426270                            goto out;
    60436271                        }
    6044                         pExtent->uGrainSector = uSectorExtentAbs;
     6272                        pExtent->uGrainSectorAbs = uSectorExtentAbs;
     6273                        pExtent->uGrain = uSectorExtentRel / pExtent->cSectorsPerGrain;
    60456274                        Assert(uLBA == uSectorExtentRel);
    60466275                    }
     
    61376366            cbToWrite = RT_MIN(cbToWrite, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain - uSectorExtentRel % pExtent->cSectorsPerGrain));
    61386367            if (    pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED
    6139                 &&  uSectorExtentRel < (uint64_t)pExtent->uLastGrainWritten * pExtent->cSectorsPerGrain)
     6368                &&  uSectorExtentRel < (uint64_t)pExtent->uLastGrainAccess * pExtent->cSectorsPerGrain)
    61406369            {
    61416370                rc = VERR_VD_VMDK_INVALID_WRITE;
     
    61866415                     * which is somewhere between expensive and impossible. */
    61876416                    rc = VERR_VD_VMDK_INVALID_STATE;
    6188                     pExtent->uGrainSector = 0;
    6189                     pExtent->uLastGrainSector = 0;
     6417                    pExtent->uGrainSectorAbs = 0;
    61906418                    AssertRC(rc);
    61916419                }
     
    64646692    int rc;
    64656693
    6466     /* Image must be opened and the new flags must be valid. Just readonly and
    6467      * info flags are supported. */
    6468     if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE)))
     6694    /* Image must be opened and the new flags must be valid. */
     6695    if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE | VD_OPEN_FLAGS_SEQUENTIAL)))
    64696696    {
    64706697        rc = VERR_INVALID_PARAMETER;
     
    69657192            cbWrite = RT_MIN(cbWrite, VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain - uSectorExtentRel % pExtent->cSectorsPerGrain));
    69667193            if (    pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED
    6967                 &&  uSectorExtentRel < (uint64_t)pExtent->uLastGrainWritten * pExtent->cSectorsPerGrain)
     7194                &&  uSectorExtentRel < (uint64_t)pExtent->uLastGrainAccess * pExtent->cSectorsPerGrain)
    69687195            {
    69697196                rc = VERR_VD_VMDK_INVALID_WRITE;
Note: See TracChangeset for help on using the changeset viewer.

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