VirtualBox

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


Ignore:
Timestamp:
Oct 19, 2010 3:12:48 PM (14 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
66783
Message:

Storage/RAW: implement sequential read/write case

File:
1 edited

Legend:

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

    r33182 r33234  
    3838{
    3939    /** Image name. */
    40     const char       *pszFilename;
     40    const char          *pszFilename;
    4141    /** Storage handle. */
    42     PVDIOSTORAGE      pStorage;
     42    PVDIOSTORAGE        pStorage;
    4343    /** I/O interface. */
    44     PVDINTERFACE      pInterfaceIO;
     44    PVDINTERFACE        pInterfaceIO;
    4545    /** Async I/O interface callbacks. */
    46     PVDINTERFACEIOINT pInterfaceIOCallbacks;
     46    PVDINTERFACEIOINT   pInterfaceIOCallbacks;
    4747
    4848    /** Pointer to the per-disk VD interface list. */
    49     PVDINTERFACE      pVDIfsDisk;
     49    PVDINTERFACE        pVDIfsDisk;
    5050    /** Pointer to the per-image VD interface list. */
    51     PVDINTERFACE      pVDIfsImage;
     51    PVDINTERFACE        pVDIfsImage;
    5252
    5353    /** Error callback. */
    54     PVDINTERFACE      pInterfaceError;
     54    PVDINTERFACE        pInterfaceError;
    5555    /** Opaque data for error callback. */
    56     PVDINTERFACEERROR pInterfaceErrorCallbacks;
     56    PVDINTERFACEERROR   pInterfaceErrorCallbacks;
    5757
    5858    /** Open flags passed by VBoxHD layer. */
    59     unsigned          uOpenFlags;
     59    unsigned            uOpenFlags;
    6060    /** Image flags defined during creation or determined during open. */
    61     unsigned          uImageFlags;
     61    unsigned            uImageFlags;
    6262    /** Total size of the image. */
    63     uint64_t          cbSize;
     63    uint64_t            cbSize;
     64    /** Position in the image (only truly used for sequential access). */
     65    uint64_t            offAccess;
     66    /** Flag if this is a newly created image. */
     67    bool                fCreate;
    6468    /** Physical geometry of this image. */
    65     VDGEOMETRY        PCHSGeometry;
     69    VDGEOMETRY          PCHSGeometry;
    6670    /** Logical geometry of this image. */
    67     VDGEOMETRY        LCHSGeometry;
     71    VDGEOMETRY          LCHSGeometry;
    6872
    6973} RAWIMAGE, *PRAWIMAGE;
     74
     75
     76/** Size of write operations when filling an image with zeroes. */
     77#define RAW_FILL_SIZE (128 * _1K)
    7078
    7179/*******************************************************************************
     
    249257            /* No point updating the file that is deleted anyway. */
    250258            if (!fDelete)
     259            {
     260                /* For newly created images in sequential mode fill it to
     261                 * the nominal size. */
     262                if (   pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL
     263                    && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
     264                    && pImage->fCreate)
     265                {
     266                    /* Fill rest of image with zeroes, a must for sequential
     267                     * images to reach the nominal size. */
     268                    uint64_t uOff;
     269                    void *pvBuf = RTMemTmpAllocZ(RAW_FILL_SIZE);
     270                    if (!pvBuf)
     271                        goto out;
     272
     273                    uOff = pImage->offAccess;
     274                    /* Write data to all image blocks. */
     275                    while (uOff < pImage->cbSize)
     276                    {
     277                        unsigned cbChunk = (unsigned)RT_MIN(pImage->cbSize,
     278                                                            RAW_FILL_SIZE);
     279
     280                        rc = rawFileWriteSync(pImage, uOff, pvBuf, cbChunk,
     281                                              NULL);
     282                        if (RT_FAILURE(rc))
     283                            goto out;
     284
     285                        uOff += cbChunk;
     286                    }
     287out:
     288                    if (pvBuf)
     289                        RTMemTmpFree(pvBuf);
     290                }
    251291                rawFlushImage(pImage);
     292            }
    252293
    253294            rawFileClose(pImage);
     
    271312
    272313    pImage->uOpenFlags = uOpenFlags;
     314    pImage->fCreate = false;
    273315
    274316    pImage->pInterfaceError = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ERROR);
     
    324366    RTFOFF cbFree = 0;
    325367    uint64_t uOff;
    326     size_t cbBuf = 128 * _1K;
    327368    void *pvBuf = NULL;
     369    int32_t fOpen;
    328370
    329371    if (uImageFlags & VD_IMAGE_FLAGS_DIFF)
     
    339381
    340382    pImage->uImageFlags = uImageFlags;
     383    pImage->fCreate = true;
    341384    pImage->PCHSGeometry = *pPCHSGeometry;
    342385    pImage->LCHSGeometry = *pLCHSGeometry;
     
    353396
    354397    /* Create image file. */
    355     rc = rawFileOpen(pImage, pImage->pszFilename,
    356                      VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags,
    357                                                 true /* fCreate */));
     398    fOpen = VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags, true /* fCreate */);
     399    if (uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL)
     400        fOpen &= ~RTFILE_O_READ;
     401    rc = rawFileOpen(pImage, pImage->pszFilename, fOpen);
    358402    if (RT_FAILURE(rc))
    359403    {
     
    362406    }
    363407
    364     /* Check the free space on the disk and leave early if there is not
    365      * sufficient space available. */
    366     rc = rawFileGetFreeSpace(pImage, pImage->pszFilename, &cbFree);
    367     if (RT_SUCCESS(rc) /* ignore errors */ && ((uint64_t)cbFree < cbSize))
    368     {
    369         rc = rawError(pImage, VERR_DISK_FULL, RT_SRC_POS, N_("Raw: disk would overflow creating image '%s'"), pImage->pszFilename);
    370         goto out;
    371     }
    372 
    373     /* Allocate & commit whole file if fixed image, it must be more
    374      * effective than expanding file by write operations. */
    375     rc = rawFileSetSize(pImage, cbSize);
    376     if (RT_FAILURE(rc))
    377     {
    378         rc = rawError(pImage, rc, RT_SRC_POS, N_("Raw: setting image size failed for '%s'"), pImage->pszFilename);
    379         goto out;
    380     }
    381 
    382     /* Fill image with zeroes. We do this for every fixed-size image since on
    383      * some systems (for example Windows Vista), it takes ages to write a block
    384      * near the end of a sparse file and the guest could complain about an ATA
    385      * timeout. */
    386     pvBuf = RTMemTmpAllocZ(cbBuf);
    387     if (!pvBuf)
    388     {
    389         rc = VERR_NO_MEMORY;
    390         goto out;
    391     }
    392 
    393     uOff = 0;
    394     /* Write data to all image blocks. */
    395     while (uOff < cbSize)
    396     {
    397         unsigned cbChunk = (unsigned)RT_MIN(cbSize, cbBuf);
    398 
    399         rc = rawFileWriteSync(pImage, uOff, pvBuf, cbChunk, NULL);
     408    if (!(uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL))
     409    {
     410        /* Check the free space on the disk and leave early if there is not
     411         * sufficient space available. */
     412        rc = rawFileGetFreeSpace(pImage, pImage->pszFilename, &cbFree);
     413        if (RT_SUCCESS(rc) /* ignore errors */ && ((uint64_t)cbFree < cbSize))
     414        {
     415            rc = rawError(pImage, VERR_DISK_FULL, RT_SRC_POS, N_("Raw: disk would overflow creating image '%s'"), pImage->pszFilename);
     416            goto out;
     417        }
     418
     419        /* Allocate & commit whole file if fixed image, it must be more
     420         * effective than expanding file by write operations. */
     421        rc = rawFileSetSize(pImage, cbSize);
    400422        if (RT_FAILURE(rc))
    401423        {
    402             rc = rawError(pImage, rc, RT_SRC_POS, N_("Raw: writing block failed for '%s'"), pImage->pszFilename);
     424            rc = rawError(pImage, rc, RT_SRC_POS, N_("Raw: setting image size failed for '%s'"), pImage->pszFilename);
    403425            goto out;
    404426        }
    405427
    406         uOff += cbChunk;
    407 
    408         if (pfnProgress)
     428        /* Fill image with zeroes. We do this for every fixed-size image since
     429         * on some systems (for example Windows Vista), it takes ages to write
     430         * a block near the end of a sparse file and the guest could complain
     431         * about an ATA timeout. */
     432        pvBuf = RTMemTmpAllocZ(RAW_FILL_SIZE);
     433        if (!pvBuf)
    409434        {
    410             rc = pfnProgress(pvUser,
    411                              uPercentStart + uOff * uPercentSpan * 98 / (cbSize * 100));
     435            rc = VERR_NO_MEMORY;
     436            goto out;
     437        }
     438
     439        uOff = 0;
     440        /* Write data to all image blocks. */
     441        while (uOff < cbSize)
     442        {
     443            unsigned cbChunk = (unsigned)RT_MIN(cbSize, RAW_FILL_SIZE);
     444
     445            rc = rawFileWriteSync(pImage, uOff, pvBuf, cbChunk, NULL);
    412446            if (RT_FAILURE(rc))
     447            {
     448                rc = rawError(pImage, rc, RT_SRC_POS, N_("Raw: writing block failed for '%s'"), pImage->pszFilename);
    413449                goto out;
     450            }
     451
     452            uOff += cbChunk;
     453
     454            if (pfnProgress)
     455            {
     456                rc = pfnProgress(pvUser,
     457                                 uPercentStart + uOff * uPercentSpan * 98 / (cbSize * 100));
     458                if (RT_FAILURE(rc))
     459                    goto out;
     460            }
    414461        }
    415462    }
    416     RTMemTmpFree(pvBuf);
    417463
    418464    if (RT_SUCCESS(rc) && pfnProgress)
     
    424470
    425471out:
     472    if (pvBuf)
     473        RTMemTmpFree(pvBuf);
     474
    426475    if (RT_SUCCESS(rc) && pfnProgress)
    427476        pfnProgress(pvUser, uPercentStart + uPercentSpan);
     
    662711    }
    663712
     713    /* For sequential access do not allow to go back. */
     714    if (   pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL
     715        && uOffset < pImage->offAccess)
     716    {
     717        rc = VERR_INVALID_PARAMETER;
     718        goto out;
     719    }
     720
    664721    rc = rawFileReadSync(pImage, uOffset, pvBuf, cbToRead, NULL);
    665     *pcbActuallyRead = cbToRead;
     722    pImage->offAccess = uOffset + cbToRead;
     723    if (pcbActuallyRead)
     724        *pcbActuallyRead = cbToRead;
    666725
    667726out:
     
    696755    }
    697756
     757    /* For sequential access do not allow to go back. */
     758    if (   pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL
     759        && uOffset < pImage->offAccess)
     760    {
     761        rc = VERR_INVALID_PARAMETER;
     762        goto out;
     763    }
     764
    698765    rc = rawFileWriteSync(pImage, uOffset, pvBuf, cbToWrite, NULL);
     766    pImage->offAccess = uOffset + cbToWrite;
    699767    if (pcbWriteProcess)
    700768        *pcbWriteProcess = cbToWrite;
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