VirtualBox

Changeset 38413 in vbox


Ignore:
Timestamp:
Aug 11, 2011 11:18:44 AM (14 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
73451
Message:

VD/Parallels: Cleanup, fixes and implement support for parallels image creation to make I/O testing possible

Location:
trunk/src/VBox/Storage
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Storage/Parallels.cpp

    r37739 r38413  
    412412}
    413413
     414/**
     415 * Internal: Create a parallels image.
     416 */
     417static int parallelsCreateImage(PPARALLELSIMAGE pImage, uint64_t cbSize,
     418                                unsigned uImageFlags, const char *pszComment,
     419                                PCVDGEOMETRY pPCHSGeometry,
     420                                PCVDGEOMETRY pLCHSGeometry, unsigned uOpenFlags,
     421                                PFNVDPROGRESS pfnProgress, void *pvUser,
     422                                unsigned uPercentStart, unsigned uPercentSpan)
     423{
     424    int rc = VINF_SUCCESS;
     425    int32_t fOpen;
     426
     427    if (uImageFlags & VD_IMAGE_FLAGS_FIXED)
     428    {
     429        rc = parallelsError(pImage, VERR_VD_INVALID_TYPE, RT_SRC_POS, N_("Parallels: cannot create fixed image '%s'. Create a raw image"), pImage->pszFilename);
     430        goto out;
     431    }
     432
     433    pImage->uOpenFlags   = uOpenFlags & ~VD_OPEN_FLAGS_READONLY;
     434    pImage->uImageFlags  = uImageFlags;
     435    pImage->PCHSGeometry = *pPCHSGeometry;
     436    pImage->LCHSGeometry = *pLCHSGeometry;
     437
     438    if (!pImage->PCHSGeometry.cCylinders)
     439    {
     440        /* Set defaults. */
     441        pImage->PCHSGeometry.cSectors   = 63;
     442        pImage->PCHSGeometry.cHeads     = 16;
     443        pImage->PCHSGeometry.cCylinders = pImage->cbSize / (512 * pImage->PCHSGeometry.cSectors * pImage->PCHSGeometry.cHeads);
     444    }
     445
     446    pImage->pInterfaceError = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ERROR);
     447    if (pImage->pInterfaceError)
     448        pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError);
     449
     450    /* Get I/O interface. */
     451    pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsImage, VDINTERFACETYPE_IOINT);
     452    AssertPtrReturn(pImage->pInterfaceIO, VERR_INVALID_PARAMETER);
     453    pImage->pInterfaceIOCallbacks = VDGetInterfaceIOInt(pImage->pInterfaceIO);
     454    AssertPtrReturn(pImage->pInterfaceIOCallbacks, VERR_INVALID_PARAMETER);
     455
     456    /* Create image file. */
     457    fOpen = VDOpenFlagsToFileOpenFlags(pImage->uOpenFlags, true /* fCreate */);
     458    rc = parallelsFileOpen(pImage, pImage->pszFilename, fOpen);
     459    if (RT_FAILURE(rc))
     460    {
     461        rc = parallelsError(pImage, rc, RT_SRC_POS, N_("Parallels: cannot create image '%s'"), pImage->pszFilename);
     462        goto out;
     463    }
     464
     465    if (RT_SUCCESS(rc) && pfnProgress)
     466        pfnProgress(pvUser, uPercentStart + uPercentSpan * 98 / 100);
     467
     468    /* Setup image state. */
     469    pImage->cbSize                   = cbSize;
     470    pImage->cAllocationBitmapEntries = cbSize / 512 / pImage->PCHSGeometry.cSectors;
     471    if (pImage->cAllocationBitmapEntries * pImage->PCHSGeometry.cSectors * 512 < cbSize)
     472        pImage->cAllocationBitmapEntries++;
     473    pImage->fAllocationBitmapChanged = true;
     474    pImage->cbFileCurrent            = sizeof(ParallelsHeader) + pImage->cAllocationBitmapEntries * sizeof(uint32_t);
     475    /* Round to next sector boundary. */
     476    pImage->cbFileCurrent           += 512 - pImage->cbFileCurrent % 512;
     477    Assert(!(pImage->cbFileCurrent % 512));
     478    pImage->pAllocationBitmap        = (uint32_t *)RTMemAllocZ(pImage->cAllocationBitmapEntries * sizeof(uint32_t));
     479    if (!pImage->pAllocationBitmap)
     480        rc = VERR_NO_MEMORY;
     481
     482    if (RT_SUCCESS(rc))
     483    {
     484        ParallelsHeader Header;
     485
     486        memcpy(Header.HeaderIdentifier, PARALLELS_HEADER_MAGIC, sizeof(Header.HeaderIdentifier));
     487        Header.uVersion                   = RT_H2LE_U32(PARALLELS_DISK_VERSION);
     488        Header.cHeads                     = RT_H2LE_U32(pImage->PCHSGeometry.cHeads);
     489        Header.cCylinders                 = RT_H2LE_U32(pImage->PCHSGeometry.cCylinders);
     490        Header.cSectorsPerTrack           = RT_H2LE_U32(pImage->PCHSGeometry.cSectors);
     491        Header.cEntriesInAllocationBitmap = RT_H2LE_U32(pImage->cAllocationBitmapEntries);
     492        Header.cSectors                   = RT_H2LE_U32(pImage->cbSize / 512);
     493        memset(Header.Padding, 0, sizeof(Header.Padding));
     494
     495        /* Write header and allocation bitmap. */
     496        rc = parallelsFileSetSize(pImage, pImage->cbFileCurrent);
     497        if (RT_SUCCESS(rc))
     498            rc = parallelsFileWriteSync(pImage, 0, &Header, sizeof(Header), NULL);
     499        if (RT_SUCCESS(rc))
     500            rc = parallelsFlushImage(pImage); /* Writes the allocation bitmap. */
     501    }
     502
     503out:
     504    if (RT_SUCCESS(rc) && pfnProgress)
     505        pfnProgress(pvUser, uPercentStart + uPercentSpan);
     506
     507    if (RT_FAILURE(rc))
     508        parallelsFreeImage(pImage, rc != VERR_ALREADY_EXISTS);
     509    return rc;
     510}
    414511
    415512/** @copydoc VBOXHDDBACKEND::pfnCheckIfValid */
     
    502599    }
    503600
    504     /** @todo r=klaus why this duplicate check, async is not claimed... */
    505     if (uOpenFlags & VD_OPEN_FLAGS_ASYNC_IO)
    506     {
    507         rc = VERR_NOT_SUPPORTED;
    508         goto out;
    509     }
    510 
    511601    pImage = (PPARALLELSIMAGE)RTMemAllocZ(sizeof(PARALLELSIMAGE));
    512602    if (!pImage)
     
    543633                           PVDINTERFACE pVDIfsOperation, void **ppBackendData)
    544634{
    545     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));
    546     int rc = VERR_NOT_IMPLEMENTED;
    547 
     635    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",
     636                 pszFilename, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, ppBackendData));
     637    int rc = VINF_SUCCESS;
     638    PPARALLELSIMAGE pImage;
     639
     640    PFNVDPROGRESS pfnProgress = NULL;
     641    void *pvUser = NULL;
     642    PVDINTERFACE pIfProgress = VDInterfaceGet(pVDIfsOperation,
     643                                              VDINTERFACETYPE_PROGRESS);
     644    PVDINTERFACEPROGRESS pCbProgress = NULL;
     645    if (pIfProgress)
     646    {
     647        pCbProgress = VDGetInterfaceProgress(pIfProgress);
     648        if (pCbProgress)
     649            pfnProgress = pCbProgress->pfnProgress;
     650        pvUser = pIfProgress->pvUser;
     651    }
     652
     653    /* Check open flags. All valid flags are supported. */
     654    if (uOpenFlags & ~VD_OPEN_FLAGS_MASK)
     655    {
     656        rc = VERR_INVALID_PARAMETER;
     657        goto out;
     658    }
     659
     660    /* Check remaining arguments. */
     661    if (   !VALID_PTR(pszFilename)
     662        || !*pszFilename
     663        || !VALID_PTR(pPCHSGeometry)
     664        || !VALID_PTR(pLCHSGeometry))
     665    {
     666        rc = VERR_INVALID_PARAMETER;
     667        goto out;
     668    }
     669
     670    pImage = (PPARALLELSIMAGE)RTMemAllocZ(sizeof(PARALLELSIMAGE));
     671    if (!pImage)
     672    {
     673        rc = VERR_NO_MEMORY;
     674        goto out;
     675    }
     676    pImage->pszFilename = pszFilename;
     677    pImage->pStorage = NULL;
     678    pImage->pVDIfsDisk = pVDIfsDisk;
     679    pImage->pVDIfsImage = pVDIfsImage;
     680
     681    rc = parallelsCreateImage(pImage, cbSize, uImageFlags, pszComment,
     682                              pPCHSGeometry, pLCHSGeometry, uOpenFlags,
     683                              pfnProgress, pvUser, uPercentStart, uPercentSpan);
     684    if (RT_SUCCESS(rc))
     685    {
     686        /* So far the image is opened in read/write mode. Make sure the
     687         * image is opened in read-only mode if the caller requested that. */
     688        if (uOpenFlags & VD_OPEN_FLAGS_READONLY)
     689        {
     690            parallelsFreeImage(pImage, false);
     691            rc = parallelsOpenImage(pImage, uOpenFlags);
     692            if (RT_FAILURE(rc))
     693            {
     694                RTMemFree(pImage);
     695                goto out;
     696            }
     697        }
     698        *ppBackendData = pImage;
     699    }
     700    else
     701        RTMemFree(pImage);
     702
     703out:
    548704    LogFlowFunc(("returns %Rrc\n", rc));
    549705    return rc;
     
    612768/** @copydoc VBOXHDDBACKEND::pfnRead */
    613769static int parallelsRead(void *pBackendData, uint64_t uOffset, void *pvBuf,
    614                          size_t cbBuf, size_t *pcbActuallyRead)
    615 {
    616     LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbBuf=%zu pcbActuallyRead=%#p\n", pBackendData, uOffset, pvBuf, cbBuf, pcbActuallyRead));
     770                         size_t cbToRead, size_t *pcbActuallyRead)
     771{
     772    LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n",
     773                 pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead));
    617774    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    618775    int rc = VINF_SUCCESS;
    619     uint64_t uSector;
    620     uint64_t uOffsetInFile;
    621     uint32_t iIndexInAllocationTable;
    622776
    623777    AssertPtr(pImage);
    624778    Assert(uOffset % 512 == 0);
    625     Assert(cbBuf % 512 == 0);
     779    Assert(cbToRead % 512 == 0);
    626780
    627781    if (pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED)
    628     {
    629         rc = parallelsFileReadSync(pImage, uOffset, pvBuf, cbBuf, NULL);
    630     }
    631     else
    632     {
     782        rc = parallelsFileReadSync(pImage, uOffset, pvBuf, cbToRead, NULL);
     783    else
     784    {
     785        uint64_t uSector;
     786        uint32_t iIndexInAllocationTable;
     787
     788        /* Calculate offset in the real file. */
     789        uSector = uOffset / 512;
     790
     791        /* One chunk in the file is always one track big. */
     792        iIndexInAllocationTable = (uint32_t)(uSector / pImage->PCHSGeometry.cSectors);
     793        uSector = uSector % pImage->PCHSGeometry.cSectors;
     794
     795        Assert(iIndexInAllocationTable < pImage->cAllocationBitmapEntries);
     796
     797        cbToRead = RT_MIN(cbToRead, (pImage->PCHSGeometry.cSectors - uSector)*512);
     798
     799        LogFlowFunc(("AllocationBitmap[%u]=%u uSector=%u cbToRead=%zu cAllocationBitmapEntries=%u\n",
     800                     iIndexInAllocationTable, pImage->pAllocationBitmap[iIndexInAllocationTable],
     801                     uSector, cbToRead, pImage->cAllocationBitmapEntries));
     802
     803        if (pImage->pAllocationBitmap[iIndexInAllocationTable] == 0)
     804            rc = VERR_VD_BLOCK_FREE;
     805        else
     806        {
     807            uint64_t uOffsetInFile = ((uint64_t)pImage->pAllocationBitmap[iIndexInAllocationTable] + uSector) * 512;
     808
     809            LogFlowFunc(("uOffsetInFile=%llu\n", uOffsetInFile));
     810            rc = parallelsFileReadSync(pImage, uOffsetInFile, pvBuf, cbToRead, NULL);
     811        }
     812    }
     813
     814    if (   (   RT_SUCCESS(rc)
     815            || rc == VERR_VD_BLOCK_FREE)
     816        && pcbActuallyRead)
     817        *pcbActuallyRead = cbToRead;
     818
     819    LogFlowFunc(("returns %Rrc\n", rc));
     820    return rc;
     821}
     822
     823/** @copydoc VBOXHDDBACKEND::pfnWrite */
     824static int parallelsWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf,
     825                          size_t cbToWrite, size_t *pcbWriteProcess,
     826                          size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite)
     827{
     828    LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p\n",
     829                 pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess));
     830    PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
     831    int rc = VINF_SUCCESS;
     832
     833    AssertPtr(pImage);
     834    Assert(uOffset % 512 == 0);
     835    Assert(cbToWrite % 512 == 0);
     836
     837    if (pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED)
     838        rc = parallelsFileWriteSync(pImage, uOffset, pvBuf, cbToWrite, NULL);
     839    else
     840    {
     841        uint64_t uSector;
     842        uint64_t uOffsetInFile;
     843        uint32_t iIndexInAllocationTable;
     844
    633845        /* Calculate offset in the real file. */
    634846        uSector = uOffset / 512;
     
    637849        uSector = uSector % pImage->PCHSGeometry.cSectors;
    638850
    639         cbBuf = RT_MIN(cbBuf, (pImage->PCHSGeometry.cSectors - uSector)*512);
     851        Assert(iIndexInAllocationTable < pImage->cAllocationBitmapEntries);
     852
     853        cbToWrite = RT_MIN(cbToWrite, (pImage->PCHSGeometry.cSectors - uSector)*512);
     854
     855        LogFlowFunc(("AllocationBitmap[%u]=%u uSector=%u cbToWrite=%zu cAllocationBitmapEntries=%u\n",
     856                     iIndexInAllocationTable, pImage->pAllocationBitmap[iIndexInAllocationTable],
     857                     uSector, cbToWrite, pImage->cAllocationBitmapEntries));
    640858
    641859        if (pImage->pAllocationBitmap[iIndexInAllocationTable] == 0)
    642860        {
    643             rc = VERR_VD_BLOCK_FREE;
     861            if (   cbToWrite == pImage->PCHSGeometry.cSectors * 512
     862                && !(fWrite & VD_WRITE_NO_ALLOC))
     863            {
     864                /* Stay on the safe side. Do not run the risk of confusing the higher
     865                 * level, as that can be pretty lethal to image consistency. */
     866                *pcbPreRead = 0;
     867                *pcbPostRead = 0;
     868
     869                /* Allocate new chunk in the file. */
     870                AssertMsg(pImage->cbFileCurrent % 512 == 0, ("File size is not a multiple of 512\n"));
     871                pImage->pAllocationBitmap[iIndexInAllocationTable] = (uint32_t)(pImage->cbFileCurrent / 512);
     872                pImage->cbFileCurrent += pImage->PCHSGeometry.cSectors * 512;
     873                pImage->fAllocationBitmapChanged = true;
     874
     875                uOffsetInFile = (uint64_t)pImage->pAllocationBitmap[iIndexInAllocationTable] * 512;
     876
     877                LogFlowFunc(("uOffsetInFile=%llu\n", uOffsetInFile));
     878
     879                /*
     880                 * Write the new block at the current end of the file.
     881                 */
     882                rc = parallelsFileWriteSync(pImage, uOffsetInFile, pvBuf, cbToWrite,
     883                                            NULL);
     884            }
     885            else
     886            {
     887                /* Trying to do a partial write to an unallocated cluster. Don't do
     888                 * anything except letting the upper layer know what to do. */
     889                *pcbPreRead  = uSector * 512;
     890                *pcbPostRead = (pImage->PCHSGeometry.cSectors * 512) - cbToWrite - *pcbPreRead;
     891                rc = VERR_VD_BLOCK_FREE;
     892            }
    644893        }
    645894        else
    646895        {
    647             uOffsetInFile = (pImage->pAllocationBitmap[iIndexInAllocationTable] + uSector) * 512;
    648             rc = parallelsFileReadSync(pImage, uOffsetInFile, pvBuf, cbBuf, NULL);
    649         }
    650     }
    651 
    652     if (   RT_SUCCESS(rc)
    653         || rc == VERR_VD_BLOCK_FREE)
    654     {
    655         if (pcbActuallyRead)
    656             *pcbActuallyRead = cbBuf;
    657 
    658         Log2(("parallelsRead: off=%#llx pvBuf=%p cbBuf=%d\n"
    659                 "%.*Rhxd\n",
    660                 uOffset, pvBuf, cbBuf, cbBuf, pvBuf));
    661     }
    662 
    663     LogFlowFunc(("returns %Rrc\n", rc));
    664     return rc;
    665 }
    666 
    667 /** @copydoc VBOXHDDBACKEND::pfnWrite */
    668 static int parallelsWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf,
    669                           size_t cbBuf, size_t *pcbWriteProcess,
    670                           size_t *pcbPreRead, size_t *pcbPostRead, unsigned fWrite)
    671 {
    672     LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbBuf=%zu pcbWriteProcess=%#p\n", pBackendData, uOffset, pvBuf, cbBuf, pcbWriteProcess));
    673     PPARALLELSIMAGE pImage = (PPARALLELSIMAGE)pBackendData;
    674     int rc = VINF_SUCCESS;
    675     uint64_t uSector;
    676     uint64_t uOffsetInFile;
    677     uint32_t iIndexInAllocationTable;
    678 
    679     AssertPtr(pImage);
    680     Assert(uOffset % 512 == 0);
    681     Assert(cbBuf % 512 == 0);
    682 
    683     if (pImage->uImageFlags & VD_IMAGE_FLAGS_FIXED)
    684     {
    685         rc = parallelsFileWriteSync(pImage, uOffset, pvBuf, cbBuf, NULL);
    686     }
    687     else
    688     {
    689         /** Calculate offset in the real file. */
    690         uSector = uOffset / 512;
    691         /** One chunk in the file is always one track big. */
    692         iIndexInAllocationTable = (uint32_t)(uSector / pImage->PCHSGeometry.cSectors);
    693         uSector = uSector % pImage->PCHSGeometry.cSectors;
    694 
    695         cbBuf = RT_MIN(cbBuf, (pImage->PCHSGeometry.cSectors - uSector)*512);
    696 
    697         if (pImage->pAllocationBitmap[iIndexInAllocationTable] == 0)
    698         {
    699             /* Allocate new chunk in the file. */
    700             AssertMsg(pImage->cbFileCurrent % 512 == 0, ("File size is not a multiple of 512\n"));
    701             pImage->pAllocationBitmap[iIndexInAllocationTable] = (uint32_t)(pImage->cbFileCurrent / 512);
    702             pImage->cbFileCurrent += pImage->PCHSGeometry.cSectors * 512;
    703             pImage->fAllocationBitmapChanged = true;
    704 
    705             uint8_t *pNewBlock = (uint8_t *)RTMemAllocZ(pImage->PCHSGeometry.cSectors * 512);
    706 
    707             if (!pNewBlock)
    708             {
    709                 rc = VERR_NO_MEMORY;
    710                 goto out;
    711             }
    712 
    713             uOffsetInFile = (uint64_t)pImage->pAllocationBitmap[iIndexInAllocationTable] * 512;
    714             memcpy(pNewBlock + (uOffset - ((uint64_t)iIndexInAllocationTable * pImage->PCHSGeometry.cSectors * 512)),
    715                    pvBuf, cbBuf);
    716 
    717             /*
    718              * Write the new block at the current end of the file.
    719              */
    720             rc = parallelsFileWriteSync(pImage, uOffsetInFile, pNewBlock,
    721                                         pImage->PCHSGeometry.cSectors * 512,
    722                                         NULL);
    723 
    724             RTMemFree(pNewBlock);
    725         }
    726         else
    727         {
    728             uOffsetInFile = (pImage->pAllocationBitmap[iIndexInAllocationTable] + uSector) * 512;
    729             rc = parallelsFileWriteSync(pImage, uOffsetInFile, pvBuf, cbBuf, NULL);
     896            uOffsetInFile = ((uint64_t)pImage->pAllocationBitmap[iIndexInAllocationTable] + uSector) * 512;
     897
     898            LogFlowFunc(("uOffsetInFile=%llu\n", uOffsetInFile));
     899            rc = parallelsFileWriteSync(pImage, uOffsetInFile, pvBuf, cbToWrite, NULL);
    730900        }
    731901    }
    732902
    733903    if (pcbWriteProcess)
    734         *pcbWriteProcess = cbBuf;
    735 
    736     /* Stay on the safe side. Do not run the risk of confusing the higher
    737      * level, as that can be pretty lethal to image consistency. */
    738     *pcbPreRead = 0;
    739     *pcbPostRead = 0;
     904        *pcbWriteProcess = cbToWrite;
    740905
    741906out:
     
    9611126
    9621127    /* Image must be opened and the new flags must be valid. */
    963     /** @todo r=klaus add VD_OPEN_FLAGS_ASYNC_IO when async io has been tested */
    964     if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_SHAREABLE | VD_OPEN_FLAGS_SEQUENTIAL)))
     1128    if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_SHAREABLE | VD_OPEN_FLAGS_SEQUENTIAL | VD_OPEN_FLAGS_ASYNC_IO)))
    9651129    {
    9661130        rc = VERR_INVALID_PARAMETER;
     
    13101474                                                 NULL, NULL);
    13111475            }
     1476
     1477            *pcbPreRead  = 0;
     1478            *pcbPostRead = 0;
    13121479        }
    13131480        else
     
    13481515    sizeof(VBOXHDDBACKEND),
    13491516    /* uBackendCaps */
    1350     VD_CAP_FILE | VD_CAP_ASYNC | VD_CAP_VFS,
     1517    VD_CAP_FILE | VD_CAP_ASYNC | VD_CAP_VFS | VD_CAP_CREATE_DYNAMIC | VD_CAP_DIFF,
    13511518    /* paFileExtensions */
    13521519    s_aParallelsFileExtensions,
  • trunk/src/VBox/Storage/testcase/tstVDIo.vd

    r38204 r38413  
    6464destroydisk name=test
    6565
     66# Parallels disk
     67print msg=Testing_Parallels
     68createdisk name=test verify=yes
     69create disk=test mode=base name=tstShared.hdd type=dynamic backend=Parallels size=200M
     70io disk=test async=yes max-reqs=32 mode=seq blocksize=64k off=0-200M size=200M writes=100
     71io disk=test async=yes max-reqs=32 mode=seq blocksize=64k off=0-200M size=200M writes=0
     72create disk=test mode=diff name=tstShared2.hdd type=dynamic backend=Parallels size=200M
     73io disk=test async=yes max-reqs=32 mode=rnd blocksize=64k off=0-200M size=200M writes=50
     74create disk=test mode=diff name=tstShared3.hdd type=dynamic backend=Parallels size=200M
     75io disk=test async=yes max-reqs=32 mode=rnd blocksize=64k off=0-200M size=200M writes=50
     76close disk=test mode=single delete=yes
     77close disk=test mode=single delete=yes
     78close disk=test mode=single delete=yes
     79destroydisk name=test
     80
    6681iorngdestroy
    6782
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