VirtualBox

Changeset 33259 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Oct 20, 2010 12:49:55 PM (14 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
66817
Message:

Storage/VBoxHDD+Main/Snapshot: Implement backward merging of snapshots, needed for live deletion of last remaining snapshot. Required a few minor changes to existing code in paths which so far were untested, to get the details right.

File:
1 edited

Legend:

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

    r33094 r33259  
    166166     * The same as pBase if only one image is used. */
    167167    PVDIMAGE            pLast;
     168
     169    /** If a merge to one of the parents is running this may be non-NULL
     170     * to indicate to what image the writes should be additionally relayed. */
     171    PVDIMAGE            pImageRelay;
    168172
    169173    /** Flags representing the modification state. */
     
    15651569 * write optimizations.
    15661570 */
    1567 static int vdWriteHelper(PVBOXHDD pDisk, PVDIMAGE pImage, PVDIMAGE pImageParentOverride,
    1568                          uint64_t uOffset, const void *pvBuf, size_t cbWrite,
     1571static int vdWriteHelper(PVBOXHDD pDisk, PVDIMAGE pImage,
     1572                         PVDIMAGE pImageParentOverride, uint64_t uOffset,
     1573                         const void *pvBuf, size_t cbWrite,
    15691574                         bool fUpdateCache)
    15701575{
     
    52905295        {
    52915296            /*
    5292              * We may need to update the parent uuid of the child coming after the
    5293              * last image to be merged. We have to reopen it read/write.
     5297             * We may need to update the parent uuid of the child coming after
     5298             * the last image to be merged. We have to reopen it read/write.
    52945299             *
    5295              * This is done before we do the actual merge to prevent an incosistent
    5296              * chain if the mode change fails for some reason.
     5300             * This is done before we do the actual merge to prevent an
     5301             * inconsistent chain if the mode change fails for some reason.
    52975302             */
    52985303            if (pImageFrom->pNext)
     
    53165321                        break;
    53175322                }
     5323
     5324                rc2 = vdThreadFinishWrite(pDisk);
     5325                AssertRC(rc2);
     5326                fLockWrite = false;
     5327            }
     5328
     5329            /* If the merge is from the last image we have to relay all writes
     5330             * to the merge destination as well, so that concurrent writes
     5331             * (in case of a live merge) are handled correctly. */
     5332            if (!pImageFrom->pNext)
     5333            {
     5334                /* Take the write lock. */
     5335                rc2 = vdThreadStartWrite(pDisk);
     5336                AssertRC(rc2);
     5337                fLockWrite = true;
     5338
     5339                pDisk->pImageRelay = pImageTo;
    53185340
    53195341                rc2 = vdThreadFinishWrite(pDisk);
     
    53805402                }
    53815403            } while (uOffset < cbSize);
     5404
     5405            /* In case we set up a "write proxy" image above we must clear
     5406             * this again now to prevent stray writes. Failure or not. */
     5407            if (!pImageFrom->pNext)
     5408            {
     5409                /* Take the write lock. */
     5410                rc2 = vdThreadStartWrite(pDisk);
     5411                AssertRC(rc2);
     5412                fLockWrite = true;
     5413
     5414                pDisk->pImageRelay = NULL;
     5415
     5416                rc2 = vdThreadFinishWrite(pDisk);
     5417                AssertRC(rc2);
     5418                fLockWrite = false;
     5419            }
    53825420        }
    53835421
     
    64756513        rc = vdWriteHelper(pDisk, pImage, NULL, uOffset, pvBuf, cbWrite,
    64766514                           true /* fUpdateCache */);
     6515        if (RT_FAILURE(rc))
     6516            break;
     6517
     6518        /* If there is a merge (in the direction towards a parent) running
     6519         * concurrently then we have to also "relay" the write to this parent,
     6520         * as the merge position might be already past the position where
     6521         * this write is going. The "context" of the write can come from the
     6522         * natural chain, since merging either already did or will take care
     6523         * of the "other" content which is might be needed to fill the block
     6524         * to a full allocation size. The cache doesn't need to be touched
     6525         * as this write is covered by the previous one. */
     6526        if (RT_UNLIKELY(pDisk->pImageRelay))
     6527            rc = vdWriteHelper(pDisk, pDisk->pImageRelay, NULL, uOffset,
     6528                               pvBuf, cbWrite, false /* fUpdateCache */);
    64776529    } while (0);
    64786530
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