VirtualBox

Changeset 27806 in vbox


Ignore:
Timestamp:
Mar 29, 2010 8:18:50 PM (15 years ago)
Author:
vboxsync
Message:

Storage/VBoxHDD+DrvBlock+DrvVD: implement core code for live snapshot merging.

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/pdmifs.h

    r27754 r27806  
    5858 * 'down' or 'up'.  This refers to a model with the device on the top and the
    5959 * drivers stacked below it.  Sometimes there is mention of 'main' or 'external'
    60  * which normally means the same, i.e. the Main or VBoxBFE API.  Pickture the
    61  * orientation of 'main' as horisontal.
     60 * which normally means the same, i.e. the Main or VBoxBFE API.  Picture the
     61 * orientation of 'main' as horizontal.
    6262 *
    6363 * @{
     
    806806/** Pointer to a block notify interface (dummy). */
    807807typedef PDMIBLOCKPORT *PPDMIBLOCKPORT;
     808
     809
     810/**
     811 * Callback which provides progress information.
     812 *
     813 * @return  VBox status code.
     814 * @param   pvUser          Opaque user data.
     815 * @param   uPercent        Completion percentage.
     816 */
     817typedef DECLCALLBACK(int) FNSIMPLEPROGRESS(void *pvUser, unsigned uPercentage);
     818/** Pointer to FNSIMPLEPROGRESS() */
     819typedef FNSIMPLEPROGRESS *PFNSIMPLEPROGRESS;
    808820
    809821
     
    903915
    904916    /**
     917     * Merge medium contents during a live snapshot deletion.
     918     *
     919     * @returns VBox status code.
     920     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     921     * @param   pfnProgress     Function pointer for progress notification.
     922     * @param   pvUser          Opaque user data for progress notification.
     923     * @thread  Any thread.
     924     */
     925    DECLR3CALLBACKMEMBER(int, pfnMerge,(PPDMIBLOCK pInterface, PFNSIMPLEPROGRESS pfnProgress, void *pvUser));
     926
     927    /**
    905928     * Check if the media is readonly or not.
    906929     *
     
    11071130     */
    11081131    DECLR3CALLBACKMEMBER(int, pfnFlush,(PPDMIMEDIA pInterface));
     1132
     1133    /**
     1134     * Merge medium contents during a live snapshot deletion. All details
     1135     * must have been configured through CFGM or this will fail.
     1136     * This method is optional (i.e. the function pointer may be NULL).
     1137     *
     1138     * @returns VBox status code.
     1139     * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     1140     * @param   pfnProgress     Function pointer for progress notification.
     1141     * @param   pvUser          Opaque user data for progress notification.
     1142     * @thread  Any thread.
     1143     */
     1144    DECLR3CALLBACKMEMBER(int, pfnMerge,(PPDMIMEDIA pInterface, PFNSIMPLEPROGRESS pfnProgress, void *pvUser));
    11091145
    11101146    /**
  • trunk/src/VBox/Devices/Storage/DrvBlock.cpp

    r26173 r27806  
    205205
    206206
     207/** @copydoc PDMIBLOCK::pfnMerge */
     208static DECLCALLBACK(int) drvblockMerge(PPDMIBLOCK pInterface,
     209                                       PFNSIMPLEPROGRESS pfnProgress,
     210                                       void *pvUser)
     211{
     212    PDRVBLOCK pThis = PDMIBLOCK_2_DRVBLOCK(pInterface);
     213
     214    /*
     215     * Check the state.
     216     */
     217    if (!pThis->pDrvMedia)
     218    {
     219        AssertMsgFailed(("Invalid state! Not mounted!\n"));
     220        return VERR_PDM_MEDIA_NOT_MOUNTED;
     221    }
     222
     223    if (!pThis->pDrvMedia->pfnMerge)
     224        return VERR_NOT_SUPPORTED;
     225
     226    int rc = pThis->pDrvMedia->pfnMerge(pThis->pDrvMedia, pfnProgress, pvUser);
     227    return rc;
     228}
     229
     230
    207231/** @copydoc PDMIBLOCK::pfnIsReadOnly */
    208232static DECLCALLBACK(bool) drvblockIsReadOnly(PPDMIBLOCK pInterface)
     
    725749    pThis->IBlock.pfnWrite                  = drvblockWrite;
    726750    pThis->IBlock.pfnFlush                  = drvblockFlush;
     751    pThis->IBlock.pfnMerge                  = drvblockMerge;
    727752    pThis->IBlock.pfnIsReadOnly             = drvblockIsReadOnly;
    728753    pThis->IBlock.pfnGetSize                = drvblockGetSize;
  • trunk/src/VBox/Devices/Storage/DrvVD.cpp

    r27739 r27806  
    2828#include <VBox/pdmdrv.h>
    2929#include <VBox/pdmasynccompletion.h>
     30#include <iprt/asm.h>
    3031#include <iprt/alloc.h>
    3132#include <iprt/assert.h>
     
    145146    /** Callback table for async I/O interface. */
    146147    VDINTERFACEASYNCIO VDIAsyncIOCallbacks;
     148    /** Common structure for the supported thread synchronization interface. */
     149    VDINTERFACE        VDIThreadSync;
     150    /** Callback table for thread synchronization interface. */
     151    VDINTERFACETHREADSYNC VDIThreadSyncCallbacks;
    147152    /** Callback table for the configuration information interface. */
    148153    VDINTERFACECONFIG  VDIConfigCallbacks;
     
    155160    /** Pointer to the list of data we need to keep per image. */
    156161    PVBOXIMAGE               pImages;
     162    /** Flag whether a merge operation has been set up. */
     163    bool                fMergePending;
     164    /** Synchronization to prevent destruction before merge finishes. */
     165    RTSEMFASTMUTEX      MergeCompleteMutex;
     166    /** Synchronization between merge and other image accesses. */
     167    RTSEMRW             MergeLock;
     168    /** Source image index for merging. */
     169    unsigned            uMergeSource;
     170    /** Target image index for merging. */
     171    unsigned            uMergeTarget;
    157172} VBOXDISK, *PVBOXDISK;
    158173
     
    193208        RTMemFree(p);
    194209    }
     210}
     211
     212
     213/**
     214 * Make the image temporarily read-only.
     215 *
     216 * @returns VBox status code.
     217 * @param   pThis               The driver instance data.
     218 */
     219static int drvvdSetReadonly(PVBOXDISK pThis)
     220{
     221    int rc = VINF_SUCCESS;
     222    if (!VDIsReadOnly(pThis->pDisk))
     223    {
     224        unsigned uOpenFlags;
     225        rc = VDGetOpenFlags(pThis->pDisk, VD_LAST_IMAGE, &uOpenFlags);
     226        AssertRC(rc);
     227        uOpenFlags |= VD_OPEN_FLAGS_READONLY;
     228        rc = VDSetOpenFlags(pThis->pDisk, VD_LAST_IMAGE, uOpenFlags);
     229        AssertRC(rc);
     230        pThis->fTempReadOnly = true;
     231    }
     232    return rc;
    195233}
    196234
     
    293331                                          void **ppStorage)
    294332{
    295     PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
     333    PVBOXDISK pThis = (PVBOXDISK)pvUser;
    296334    PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)RTMemAllocZ(sizeof(DRVVDSTORAGEBACKEND));
    297335    int rc = VINF_SUCCESS;
     
    311349        if (RT_SUCCESS(rc))
    312350        {
    313             rc = PDMDrvHlpPDMAsyncCompletionTemplateCreate(pDrvVD->pDrvIns, &pStorageBackend->pTemplate,
     351            rc = PDMDrvHlpPDMAsyncCompletionTemplateCreate(pThis->pDrvIns, &pStorageBackend->pTemplate,
    314352                                                           drvvdAsyncTaskCompleted, pStorageBackend, "AsyncTaskCompleted");
    315353            if (RT_SUCCESS(rc))
     
    340378static DECLCALLBACK(int) drvvdAsyncIOClose(void *pvUser, void *pStorage)
    341379{
    342     PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
     380    PVBOXDISK pThis = (PVBOXDISK)pvUser;
    343381    PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
    344382
     
    354392                                              size_t cbRead, void *pvBuf, size_t *pcbRead)
    355393{
    356     PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
     394    PVBOXDISK pThis = (PVBOXDISK)pvUser;
    357395    PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
    358396    PDMDATASEG DataSeg;
     
    386424                                               size_t cbWrite, const void *pvBuf, size_t *pcbWritten)
    387425{
    388     PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
     426    PVBOXDISK pThis = (PVBOXDISK)pvUser;
    389427    PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
    390428    PDMDATASEG DataSeg;
     
    417455static DECLCALLBACK(int) drvvdAsyncIOFlushSync(void *pvUser, void *pStorage)
    418456{
    419     PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
     457    PVBOXDISK pThis = (PVBOXDISK)pvUser;
    420458    PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
    421459    PPDMASYNCCOMPLETIONTASK pTask;
     
    445483                                               void **ppTask)
    446484{
    447     PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
     485    PVBOXDISK pThis = (PVBOXDISK)pvUser;
    448486    PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
    449487
     
    457495                                                void **ppTask)
    458496{
    459     PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
     497    PVBOXDISK pThis = (PVBOXDISK)pvUser;
    460498    PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
    461499
     
    467505                                                void *pvCompletion, void **ppTask)
    468506{
    469     PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
     507    PVBOXDISK pThis = (PVBOXDISK)pvUser;
    470508    PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
    471509
     
    495533
    496534#endif /* VBOX_WITH_PDM_ASYNC_COMPLETION */
     535
     536
     537/*******************************************************************************
     538*   VD Thread Synchronization interface implementation                         *
     539*******************************************************************************/
     540
     541static DECLCALLBACK(int) drvvdThreadStartRead(void *pvUser)
     542{
     543    PVBOXDISK pThis = (PVBOXDISK)pvUser;
     544
     545    return RTSemRWRequestRead(pThis->MergeLock, RT_INDEFINITE_WAIT);
     546}
     547
     548static DECLCALLBACK(int) drvvdThreadFinishRead(void *pvUser)
     549{
     550    PVBOXDISK pThis = (PVBOXDISK)pvUser;
     551
     552    return RTSemRWReleaseRead(pThis->MergeLock);
     553}
     554
     555static DECLCALLBACK(int) drvvdThreadStartWrite(void *pvUser)
     556{
     557    PVBOXDISK pThis = (PVBOXDISK)pvUser;
     558
     559    return RTSemRWRequestWrite(pThis->MergeLock, RT_INDEFINITE_WAIT);
     560}
     561
     562static DECLCALLBACK(int) drvvdThreadFinishWrite(void *pvUser)
     563{
     564    PVBOXDISK pThis = (PVBOXDISK)pvUser;
     565
     566    return RTSemRWReleaseWrite(pThis->MergeLock);
     567}
    497568
    498569
     
    775846    PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
    776847    int rc = VDFlush(pThis->pDisk);
     848    LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
     849    return rc;
     850}
     851
     852/** @copydoc PDMIMEDIA::pfnMerge */
     853static DECLCALLBACK(int) drvvdMerge(PPDMIMEDIA pInterface,
     854                                    PFNSIMPLEPROGRESS pfnProgress,
     855                                    void *pvUser)
     856{
     857    LogFlow(("%s:\n", __FUNCTION__));
     858    PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
     859    int rc = VINF_SUCCESS;
     860
     861    /* Note: There is an unavoidable race between destruction and another
     862     * thread invoking this function. This is handled safely and gracefully by
     863     * atomically invalidating the lock handle in drvvdDestruct. */
     864    int rc2 = RTSemFastMutexRequest(pThis->MergeCompleteMutex);
     865    AssertRC(rc2);
     866    if (RT_SUCCESS(rc2) && pThis->fMergePending)
     867    {
     868        /* Take shortcut: PFNSIMPLEPROGRESS is exactly the same type as
     869         * PFNVDPROGRESS, so there's no need for a conversion function. */
     870        /** @todo maybe introduce a conversion which limits update frequency. */
     871        PVDINTERFACE pVDIfsOperation = NULL;
     872        VDINTERFACE VDIProgress;
     873        VDINTERFACEPROGRESS VDIProgressCallbacks;
     874        VDIProgressCallbacks.cbSize       = sizeof(VDINTERFACEPROGRESS);
     875        VDIProgressCallbacks.enmInterface = VDINTERFACETYPE_PROGRESS;
     876        VDIProgressCallbacks.pfnProgress  = pfnProgress;
     877        rc2 = VDInterfaceAdd(&VDIProgress, "DrvVD_VDIProgress", VDINTERFACETYPE_PROGRESS,
     878                             &VDIProgressCallbacks, pvUser, &pVDIfsOperation);
     879        AssertRC(rc2);
     880        pThis->fMergePending = false;
     881        rc = VDMerge(pThis->pDisk, pThis->uMergeSource,
     882                     pThis->uMergeTarget, pVDIfsOperation);
     883    }
     884    rc2 = RTSemFastMutexRelease(pThis->MergeCompleteMutex);
     885    AssertRC(rc2);
    777886    LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
    778887    return rc;
     
    10171126    LogFlow(("%s:\n", __FUNCTION__));
    10181127    PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
    1019     if (!VDIsReadOnly(pThis->pDisk))
    1020     {
    1021         unsigned uOpenFlags;
    1022         int rc = VDGetOpenFlags(pThis->pDisk, VD_LAST_IMAGE, &uOpenFlags);
    1023         AssertRC(rc);
    1024         uOpenFlags |= VD_OPEN_FLAGS_READONLY;
    1025         rc = VDSetOpenFlags(pThis->pDisk, VD_LAST_IMAGE, uOpenFlags);
    1026         AssertRC(rc);
    1027         pThis->fTempReadOnly = true;
    1028     }
     1128    drvvdSetReadonly(pThis);
    10291129}
    10301130
     
    10551155    PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
    10561156
     1157    RTSEMFASTMUTEX mutex = (RTSEMFASTMUTEX)ASMAtomicXchgPtr((void **)&pThis->MergeCompleteMutex,
     1158                                                            (void *)NIL_RTSEMFASTMUTEX);
     1159    if (mutex != NIL_RTSEMFASTMUTEX)
     1160    {
     1161        /* Request the semaphore to wait until a potentially running merge
     1162         * operation has been finished. */
     1163        int rc = RTSemFastMutexRequest(mutex);
     1164        AssertRC(rc);
     1165        pThis->fMergePending = false;
     1166        rc = RTSemFastMutexRelease(mutex);
     1167        AssertRC(rc);
     1168        rc = RTSemFastMutexDestroy(mutex);
     1169        AssertRC(rc);
     1170    }
     1171    if (pThis->MergeLock != NIL_RTSEMRW)
     1172    {
     1173        int rc = RTSemRWDestroy(pThis->MergeLock);
     1174        AssertRC(rc);
     1175        pThis->MergeLock = NIL_RTSEMRW;
     1176    }
     1177
    10571178    if (VALID_PTR(pThis->pDisk))
    10581179    {
     
    10891210    pThis->pDisk                        = NULL;
    10901211    pThis->fAsyncIOSupported            = false;
     1212    pThis->fMergePending                = false;
     1213    pThis->MergeCompleteMutex           = NIL_RTSEMFASTMUTEX;
     1214    pThis->uMergeSource                 = VD_LAST_IMAGE;
     1215    pThis->uMergeTarget                 = VD_LAST_IMAGE;
    10911216
    10921217    /* IMedia */
     
    10941219    pThis->IMedia.pfnWrite              = drvvdWrite;
    10951220    pThis->IMedia.pfnFlush              = drvvdFlush;
     1221    pThis->IMedia.pfnMerge              = drvvdMerge;
    10961222    pThis->IMedia.pfnGetSize            = drvvdGetSize;
    10971223    pThis->IMedia.pfnIsReadOnly         = drvvdIsReadOnly;
     
    11521278                                          "Format\0Path\0"
    11531279                                          "ReadOnly\0TempReadOnly\0HonorZeroWrites\0"
    1154                                           "HostIPStack\0UseNewIo\0");
     1280                                          "HostIPStack\0UseNewIo\0SetupMerge\0");
    11551281        }
    11561282        else
     
    11581284            /* All other image configurations only contain image name and
    11591285             * the format information. */
    1160             fValid = CFGMR3AreValuesValid(pCurNode, "Format\0Path\0");
     1286            fValid = CFGMR3AreValuesValid(pCurNode, "Format\0Path\0"
     1287                                                    "MergeSource\0MergeTarget\0");
    11611288        }
    11621289        if (!fValid)
     
    12021329            if (fReadOnly && pThis->fTempReadOnly)
    12031330            {
    1204                 rc = PDMDRV_SET_ERROR(pDrvIns, rc,
     1331                rc = PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_DRIVER_INVALID_PROPERTIES,
    12051332                                      N_("DrvVD: Configuration error: Both \"ReadOnly\" and \"TempReadOnly\" are set"));
    12061333                break;
     
    12131340                break;
    12141341            }
     1342            rc = CFGMR3QueryBoolDef(pCurNode, "SetupMerge", &pThis->fMergePending, false);
     1343            if (RT_FAILURE(rc))
     1344            {
     1345                rc = PDMDRV_SET_ERROR(pDrvIns, rc,
     1346                                      N_("DrvVD: Configuration error: Querying \"SetupMerge\" as boolean failed"));
     1347                break;
     1348            }
     1349            if (fReadOnly && pThis->fMergePending)
     1350            {
     1351                rc = PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_DRIVER_INVALID_PROPERTIES,
     1352                                      N_("DrvVD: Configuration error: Both \"ReadOnly\" and \"MergePending\" are set"));
     1353                break;
     1354            }
    12151355        }
    12161356
     
    12231363
    12241364    /*
    1225      * Open the images.
     1365     * Create the image container and the necessary interfaces.
    12261366     */
    12271367    if (RT_SUCCESS(rc))
     
    12931433        }
    12941434
    1295         /** @todo implement and set up the thread synchronization interface
    1296          * if enabled by some CFGM key. If this is enabled then there also
    1297          * needs to be a way for the console object to query the pDisk pointer
    1298          * (so that it can perform the merge in parallel), or alternatively
    1299          * some code needs to be added here which does the merge. The latter
    1300          * might be preferred, as a running merge must block the destruction
    1301          * of the disk, or things will go really wrong. */
     1435        if (RT_SUCCESS(rc) && pThis->fMergePending)
     1436        {
     1437            rc = RTSemFastMutexCreate(&pThis->MergeCompleteMutex);
     1438            if (RT_SUCCESS(rc))
     1439                rc = RTSemRWCreate(&pThis->MergeLock);
     1440            if (RT_SUCCESS(rc))
     1441            {
     1442                pThis->VDIThreadSyncCallbacks.cbSize        = sizeof(VDINTERFACETHREADSYNC);
     1443                pThis->VDIThreadSyncCallbacks.enmInterface  = VDINTERFACETYPE_THREADSYNC;
     1444                pThis->VDIThreadSyncCallbacks.pfnStartRead  = drvvdThreadStartRead;
     1445                pThis->VDIThreadSyncCallbacks.pfnFinishRead = drvvdThreadFinishRead;
     1446                pThis->VDIThreadSyncCallbacks.pfnStartWrite = drvvdThreadStartWrite;
     1447                pThis->VDIThreadSyncCallbacks.pfnFinishWrite = drvvdThreadFinishWrite;
     1448
     1449                rc = VDInterfaceAdd(&pThis->VDIThreadSync, "DrvVD_ThreadSync", VDINTERFACETYPE_THREADSYNC,
     1450                                    &pThis->VDIThreadSyncCallbacks, pThis, &pThis->pVDIfsDisk);
     1451            }
     1452            else
     1453            {
     1454                rc = PDMDRV_SET_ERROR(pDrvIns, rc,
     1455                                      N_("DrvVD: Failed to create semaphores for \"MergePending\""));
     1456            }
     1457        }
    13021458
    13031459        if (RT_SUCCESS(rc))
     
    13111467        pThis->fAsyncIOSupported = true;
    13121468
     1469    unsigned iImageIdx = 0;
    13131470    while (pCurNode && RT_SUCCESS(rc))
    13141471    {
     
    13381495                                  N_("DrvVD: Configuration error: Querying \"Format\" as string failed"));
    13391496            break;
     1497        }
     1498
     1499        bool fMergeSource;
     1500        rc = CFGMR3QueryBoolDef(pCurNode, "MergeSource", &fMergeSource, false);
     1501        if (RT_FAILURE(rc))
     1502        {
     1503            rc = PDMDRV_SET_ERROR(pDrvIns, rc,
     1504                                  N_("DrvVD: Configuration error: Querying \"MergeSource\" as boolean failed"));
     1505            break;
     1506        }
     1507        if (fMergeSource)
     1508        {
     1509            if (pThis->uMergeSource == VD_LAST_IMAGE)
     1510                pThis->uMergeSource = iImageIdx;
     1511            else
     1512            {
     1513                rc = PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_DRIVER_INVALID_PROPERTIES,
     1514                                      N_("DrvVD: Configuration error: Multiple \"MergeSource\" occurrences"));
     1515                break;
     1516            }
     1517        }
     1518
     1519        bool fMergeTarget;
     1520        rc = CFGMR3QueryBoolDef(pCurNode, "MergeTarget", &fMergeTarget, false);
     1521        if (RT_FAILURE(rc))
     1522        {
     1523            rc = PDMDRV_SET_ERROR(pDrvIns, rc,
     1524                                  N_("DrvVD: Configuration error: Querying \"MergeTarget\" as boolean failed"));
     1525            break;
     1526        }
     1527        if (fMergeTarget)
     1528        {
     1529            if (pThis->uMergeTarget == VD_LAST_IMAGE)
     1530                pThis->uMergeTarget = iImageIdx;
     1531            else
     1532            {
     1533                rc = PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_DRIVER_INVALID_PROPERTIES,
     1534                                      N_("DrvVD: Configuration error: Multiple \"MergeTarget\" occurrences"));
     1535                break;
     1536            }
    13401537        }
    13411538
     
    13991596        /* next */
    14001597        iLevel--;
     1598        iImageIdx--;
    14011599        pCurNode = CFGMR3GetParent(pCurNode);
     1600    }
     1601
     1602    if (   RT_SUCCESS(rc)
     1603        && pThis->fMergePending
     1604        && (   pThis->uMergeSource == VD_LAST_IMAGE
     1605            || pThis->uMergeTarget == VD_LAST_IMAGE))
     1606    {
     1607        rc = PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_DRIVER_INVALID_PROPERTIES,
     1608                              N_("DrvVD: Configuration error: Inconsistent image merge data"));
    14021609    }
    14031610
  • trunk/src/VBox/Devices/Storage/VBoxHDD.cpp

    r27736 r27806  
    20072007        AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
    20082008
    2009         rc2 = vdThreadStartRead(pDisk);
     2009        /* For simplicity reasons lock for writing as the image reopen below
     2010         * might need it. After all the reopen is usually needed. */
     2011        rc2 = vdThreadStartWrite(pDisk);
    20102012        AssertRC(rc2);
    20112013        fLockRead = true;
     
    20322034        /* Get size of destination image. */
    20332035        uint64_t cbSize = pImageTo->Backend->pfnGetSize(pImageTo->pvBackendData);
    2034         rc2 = vdThreadFinishRead(pDisk);
     2036        rc2 = vdThreadFinishWrite(pDisk);
    20352037        AssertRC(rc2);
    20362038        fLockRead = false;
     
    21062108                if (pCbProgress && pCbProgress->pfnProgress)
    21072109                {
     2110                    /** @todo r=klaus: this can update the progress to the same
     2111                     * percentage over and over again if the image format makes
     2112                     * relatively small increments. */
    21082113                    rc = pCbProgress->pfnProgress(pIfProgress->pvUser,
    21092114                                                  uOffset * 99 / cbSize);
     
    21882193                if (pCbProgress && pCbProgress->pfnProgress)
    21892194                {
     2195                    /** @todo r=klaus: this can update the progress to the same
     2196                     * percentage over and over again if the image format makes
     2197                     * relatively small increments. */
    21902198                    rc = pCbProgress->pfnProgress(pIfProgress->pvUser,
    21912199                                                  uOffset * 99 / cbSize);
     
    25892597            if (pCbProgress && pCbProgress->pfnProgress)
    25902598            {
     2599                /** @todo r=klaus: this can update the progress to the same
     2600                 * percentage over and over again if the image format makes
     2601                 * relatively small increments. */
    25912602                rc = pCbProgress->pfnProgress(pIfProgress->pvUser,
    25922603                                              uOffset * 99 / cbSize);
     
    25962607            if (pDstCbProgress && pDstCbProgress->pfnProgress)
    25972608            {
     2609                /** @todo r=klaus: this can update the progress to the same
     2610                 * percentage over and over again if the image format makes
     2611                 * relatively small increments. */
    25982612                rc = pDstCbProgress->pfnProgress(pDstIfProgress->pvUser,
    25992613                                                 uOffset * 99 / cbSize);
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