VirtualBox

Changeset 27211 in vbox


Ignore:
Timestamp:
Mar 9, 2010 12:41:26 PM (15 years ago)
Author:
vboxsync
Message:

VD: Fix data corruption during snapshot merging if the merge direction is parent -> child. Fix updating of the parent uuid for child -> parent merges if there are still childs after the images to be merged

File:
1 edited

Legend:

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

    r27134 r27211  
    300300 * will give us.
    301301 */
    302 static int vdReadHelper(PVBOXHDD pDisk, PVDIMAGE pImage, uint64_t uOffset,
    303                         void *pvBuf, size_t cbRead)
     302static int vdReadHelper(PVBOXHDD pDisk, PVDIMAGE pImage, PVDIMAGE pImageParentOverride,
     303                        uint64_t uOffset, void *pvBuf, size_t cbRead)
    304304{
    305305    int rc;
     
    313313         * stale data when different block sizes are used for the images. */
    314314        cbThisRead = cbRead;
    315         rc = VERR_VD_BLOCK_FREE;
    316         for (PVDIMAGE pCurrImage = pImage;
    317              pCurrImage != NULL && rc == VERR_VD_BLOCK_FREE;
    318              pCurrImage = pCurrImage->pPrev)
    319         {
    320             rc = pCurrImage->Backend->pfnRead(pCurrImage->pvBackendData,
    321                                               uOffset, pvBuf, cbThisRead,
    322                                               &cbThisRead);
     315
     316        /*
     317         * Try to read from the given image.
     318         * If the block is not allocated read from override chain if present.
     319         */
     320        rc = pImage->Backend->pfnRead(pImage->pvBackendData,
     321                                      uOffset, pvBuf, cbThisRead,
     322                                      &cbThisRead);
     323
     324        if (rc == VERR_VD_BLOCK_FREE)
     325        {
     326            for (PVDIMAGE pCurrImage = pImageParentOverride ? pImageParentOverride : pImage->pPrev;
     327                 pCurrImage != NULL && rc == VERR_VD_BLOCK_FREE;
     328                 pCurrImage = pCurrImage->pPrev)
     329            {
     330                rc = pCurrImage->Backend->pfnRead(pCurrImage->pvBackendData,
     331                                                  uOffset, pvBuf, cbThisRead,
     332                                                  &cbThisRead);
     333            }
    323334        }
    324335
     
    345356{
    346357    PVDPARENTSTATEDESC pParentState = (PVDPARENTSTATEDESC)pvUser;
    347     return vdReadHelper(pParentState->pDisk, pParentState->pImage, uOffset,
     358    return vdReadHelper(pParentState->pDisk, pParentState->pImage, NULL, uOffset,
    348359                        pvBuf, cbRead);
    349360}
     
    395406 */
    396407static int vdWriteHelperStandard(PVBOXHDD pDisk, PVDIMAGE pImage,
     408                                 PVDIMAGE pImageParentOverride,
    397409                                 uint64_t uOffset, size_t cbWrite,
    398410                                 size_t cbThisWrite, size_t cbPreRead,
     
    405417    if (cbPreRead)
    406418    {
    407         rc = vdReadHelper(pDisk, pImage, uOffset - cbPreRead, pvTmp,
    408                           cbPreRead);
     419        rc = vdReadHelper(pDisk, pImage, pImageParentOverride,
     420                          uOffset - cbPreRead, pvTmp, cbPreRead);
    409421        if (RT_FAILURE(rc))
    410422            return rc;
     
    440452                   (char *)pvBuf + cbThisWrite, cbWriteCopy);
    441453        if (cbReadImage)
    442             rc = vdReadHelper(pDisk, pImage,
     454            rc = vdReadHelper(pDisk, pImage, pImageParentOverride,
    443455                              uOffset + cbThisWrite + cbWriteCopy,
    444456                              (char *)pvTmp + cbPreRead + cbThisWrite + cbWriteCopy,
     
    472484 */
    473485static int vdWriteHelperOptimized(PVBOXHDD pDisk, PVDIMAGE pImage,
     486                                  PVDIMAGE pImageParentOverride,
    474487                                  uint64_t uOffset, size_t cbWrite,
    475488                                  size_t cbThisWrite, size_t cbPreRead,
     
    501514    /* Read the entire data of the block so that we can compare whether it will
    502515     * be modified by the write or not. */
    503     rc = vdReadHelper(pDisk, pImage, uOffset - cbPreRead, pvTmp,
     516    rc = vdReadHelper(pDisk, pImage, pImageParentOverride, uOffset - cbPreRead, pvTmp,
    504517                      cbPreRead + cbThisWrite + cbPostRead - cbFill);
    505518    if (RT_FAILURE(rc))
     
    548561 * write optimizations.
    549562 */
    550 static int vdWriteHelper(PVBOXHDD pDisk, PVDIMAGE pImage, uint64_t uOffset,
    551                          const void *pvBuf, size_t cbWrite)
     563static int vdWriteHelper(PVBOXHDD pDisk, PVDIMAGE pImage, PVDIMAGE pImageParentOverride,
     564                         uint64_t uOffset, const void *pvBuf, size_t cbWrite)
    552565{
    553566    int rc;
     
    580593                /* Optimized write, suppress writing to a so far unallocated
    581594                 * block if the data is in fact not changed. */
    582                 rc = vdWriteHelperOptimized(pDisk, pImage, uOffset, cbWrite,
     595                rc = vdWriteHelperOptimized(pDisk, pImage, pImageParentOverride,
     596                                            uOffset, cbWrite,
    583597                                            cbThisWrite, cbPreRead, cbPostRead,
    584598                                            pvBuf, pvTmp);
     
    590604                 * backend has some further optimization enabled) cause the
    591605                 * block to be allocated. */
    592                 rc = vdWriteHelperStandard(pDisk, pImage, uOffset, cbWrite,
     606                rc = vdWriteHelperStandard(pDisk, pImage, pImageParentOverride,
     607                                           uOffset, cbWrite,
    593608                                           cbThisWrite, cbPreRead, cbPostRead,
    594609                                           pvBuf, pvTmp);
     
    18391854    return rc;
    18401855}
     1856
    18411857
    18421858/**
     
    19441960                        if (RT_FAILURE(rc))
    19451961                            break;
    1946                         rc = vdWriteHelper(pDisk, pImageTo, uOffset, pvBuf,
     1962                        rc = vdWriteHelper(pDisk, pImageTo, pImageFrom->pPrev,
     1963                                           uOffset, pvBuf,
    19471964                                           cbThisRead);
    19481965                        if (RT_FAILURE(rc))
     
    19701987        else
    19711988        {
     1989            /*
     1990             * We may need to update the parent uuid of the child coming after the
     1991             * last image to be merged. We have to reopen it read/write.
     1992             *
     1993             * This is done before we do the actual merge to prevent an incosistent
     1994             * chain if the mode change fails for some reason.
     1995             */
     1996            if (pImageFrom->pNext)
     1997            {
     1998                PVDIMAGE pImageChild = pImageFrom->pNext;
     1999
     2000                /* We need to open the image in read/write mode. */
     2001                uOpenFlags = pImageChild->Backend->pfnGetOpenFlags(pImageChild->pvBackendData);
     2002
     2003                if (uOpenFlags  & VD_OPEN_FLAGS_READONLY)
     2004                {
     2005                    uOpenFlags  &= ~VD_OPEN_FLAGS_READONLY;
     2006                    rc = pImageChild->Backend->pfnSetOpenFlags(pImageChild->pvBackendData,
     2007                                                               uOpenFlags);
     2008                    if (RT_FAILURE(rc))
     2009                        break;
     2010                }
     2011            }
     2012
    19722013            /* Merge child state into parent. This means writing all blocks
    19732014             * which are allocated in the image up to the source image to the
     
    19962037                    if (RT_FAILURE(rc))
    19972038                        break;
    1998                     rc = vdWriteHelper(pDisk, pImageTo, uOffset, pvBuf,
     2039                    rc = vdWriteHelper(pDisk, pImageTo, NULL, uOffset, pvBuf,
    19992040                                       cbThisRead);
    20002041                    if (RT_FAILURE(rc))
     
    20362077        else
    20372078        {
     2079            /* Update the parent uuid of the child of the last merged image. */
    20382080            if (pImageFrom->pNext)
    20392081            {
     
    20412083                                                   &Uuid);
    20422084                AssertRC(rc);
     2085
    20432086                rc = pImageFrom->Backend->pfnSetParentUuid(pImageFrom->pNext->pvBackendData,
    20442087                                                           &Uuid);
    20452088                AssertRC(rc);
     2089
     2090                /* Reopen readonly if neccessary */
     2091                if (pImageFrom->pNext != pDisk->pLast)
     2092                {
     2093                    PVDIMAGE pImageChild = pImageFrom->pNext;
     2094
     2095                    uOpenFlags = pImageChild->Backend->pfnGetOpenFlags(pImageChild->pvBackendData);
     2096                    uOpenFlags |= VD_OPEN_FLAGS_READONLY;
     2097                    rc = pImageChild->Backend->pfnSetOpenFlags(pImageChild->pvBackendData,
     2098                                                               uOpenFlags);
     2099                    /** @todo: What to do if this fails?. Breaking would
     2100                     * prevent the merged images from being removed
     2101                     * from the chain possibly causing inconsistent behavior.
     2102                     */
     2103                    if (RT_FAILURE(rc))
     2104                        break;
     2105                }
    20462106            }
    20472107        }
     
    23082368            size_t cbThisRead = RT_MIN(VD_MERGE_BUFFER_SIZE, cbRemaining);
    23092369
    2310             rc = vdReadHelper(pDiskFrom, pImageFrom, uOffset, pvBuf,
     2370            rc = vdReadHelper(pDiskFrom, pImageFrom, NULL, uOffset, pvBuf,
    23112371                              cbThisRead);
    23122372            if (RT_FAILURE(rc))
    23132373                break;
    23142374
    2315             rc = vdWriteHelper(pDiskTo, pImageTo, uOffset, pvBuf,
     2375            rc = vdWriteHelper(pDiskTo, pImageTo, NULL, uOffset, pvBuf,
    23162376                               cbThisRead);
    23172377            if (RT_FAILURE(rc))
     
    26502710        AssertPtrBreakStmt(pImage, rc = VERR_VD_NOT_OPENED);
    26512711
    2652         rc = vdReadHelper(pDisk, pImage, uOffset, pvBuf, cbRead);
     2712        rc = vdReadHelper(pDisk, pImage, NULL, uOffset, pvBuf, cbRead);
    26532713    } while (0);
    26542714
     
    26972757
    26982758        vdSetModifiedFlag(pDisk);
    2699         rc = vdWriteHelper(pDisk, pImage, uOffset, pvBuf, cbWrite);
     2759        rc = vdWriteHelper(pDisk, pImage, NULL, uOffset, pvBuf, cbWrite);
    27002760    } while (0);
    27012761
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