VirtualBox

Changeset 7690 in vbox for trunk/src


Ignore:
Timestamp:
Apr 1, 2008 5:51:08 PM (17 years ago)
Author:
vboxsync
Message:

Integrate contributed code to implement VDCopy function in VBoxHDD-new.

File:
1 edited

Legend:

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

    r7281 r7690  
    15761576                         PFNVMPROGRESS pfnProgress, void *pvUser)
    15771577{
    1578     return VERR_NOT_IMPLEMENTED;
     1578    int rc, rc2 = VINF_SUCCESS;
     1579    void *pvBuf = NULL;
     1580    PVDIMAGE pImageTo = NULL;
     1581
     1582    LogFlowFunc(("pDiskFrom=%#p nImage=%u pDiskTo=%#p pszBackend=\"%s\" pszFilename=\"%s\" fMoveByRename=%d cbSize=%llu pfnProgress=%#p pvUser=%#p\n",
     1583                 pDiskFrom, nImage, pDiskTo, pszBackend, pszFilename, fMoveByRename, cbSize, pfnProgress, pvUser));
     1584
     1585    do {
     1586        /* Check arguments. */
     1587        AssertMsgBreak(VALID_PTR(pDiskFrom), ("pDiskFrom=%#p\n", pDiskFrom),
     1588                       rc = VERR_INVALID_PARAMETER);
     1589        AssertMsg(pDiskFrom->u32Signature == VBOXHDDDISK_SIGNATURE,
     1590                  ("u32Signature=%08x\n", pDiskFrom->u32Signature));
     1591
     1592        PVDIMAGE pImageFrom = vdGetImageByNumber(pDiskFrom, nImage);
     1593        AssertBreak(VALID_PTR(pImageFrom), rc = VERR_VDI_IMAGE_NOT_FOUND);
     1594        AssertMsgBreak(VALID_PTR(pDiskTo), ("pDiskTo=%#p\n", pDiskTo),
     1595                       rc = VERR_INVALID_PARAMETER);
     1596        AssertMsg(pDiskTo->u32Signature == VBOXHDDDISK_SIGNATURE,
     1597                  ("u32Signature=%08x\n", pDiskTo->u32Signature));
     1598
     1599        /* If the containers are equal and the backend is the same, rename the image. */
     1600        if (   (pDiskFrom == pDiskTo)
     1601            && (!strcmp(pszBackend, pImageFrom->Backend->pszBackendName)))
     1602        {
     1603            /* Rename the image. */
     1604            rc = pImageFrom->Backend->pfnRename(pImageFrom->pvBackendData, pszFilename ? pszFilename : pImageFrom->pszFilename);
     1605            break;
     1606        }
     1607
     1608        /* If the fMoveByRename flag is set and the backend is the same, rename the image. */
     1609        if (   (fMoveByRename == true)
     1610            && (!strcmp(pszBackend, pImageFrom->Backend->pszBackendName)))
     1611        {
     1612            /* Close the source image. */
     1613            rc = pImageFrom->Backend->pfnClose(pImageFrom->pvBackendData, false);
     1614            if (VBOX_FAILURE(rc))
     1615                break;
     1616
     1617            /* Open the source image in the destination container. */
     1618            rc = VDOpen(pDiskTo, pImageFrom->Backend->pszBackendName, pImageFrom->pszFilename, pImageFrom->uOpenFlags);
     1619            if (VBOX_FAILURE(rc))
     1620                goto movefail;
     1621
     1622            pImageTo = pDiskTo->pLast;
     1623
     1624            /* Rename the image. */
     1625            rc = pImageTo->Backend->pfnRename(pImageTo->pvBackendData, pszFilename ? pszFilename : pImageTo->pszFilename);
     1626            if (VBOX_FAILURE(rc))
     1627                goto movefail;
     1628
     1629            /* Cleanup the leftovers. */
     1630            vdRemoveImageFromList(pDiskFrom, pImageFrom);
     1631            pImageFrom->pvBackendData = NULL;
     1632
     1633            if (pImageFrom->hPlugin != NIL_RTLDRMOD)
     1634                RTLdrClose(pImageFrom->hPlugin);
     1635
     1636            if (pImageFrom->pszFilename)
     1637                RTStrFree(pImageFrom->pszFilename);
     1638
     1639            RTMemFree(pImageFrom);
     1640
     1641            break;
     1642movefail:
     1643            /* In case of failure, re-open the source image in the source container. */
     1644            rc2 = VDOpen(pDiskFrom, pImageFrom->Backend->pszBackendName, pImageFrom->pszFilename, pImageFrom->uOpenFlags);
     1645            if (VBOX_FAILURE(rc2))
     1646                /* @todo Uncertain what to do on error. If this happens pImageFrom and pImageTo are both closed. */
     1647                rc = rc2;
     1648            break;
     1649        }
     1650
     1651        /* If fMoveByRename is set pszFilename is allowed to be NULL, so do the parameter check here. */
     1652        AssertMsgBreak(VALID_PTR(pszFilename) && *pszFilename,
     1653                       ("pszFilename=%#p \"%s\"\n", pszFilename, pszFilename),
     1654                       rc = VERR_INVALID_PARAMETER);
     1655
     1656        /* Collect properties of source image. */
     1657        VDIMAGETYPE enmTypeFrom;
     1658        rc = VDGetImageType(pDiskFrom, nImage, &enmTypeFrom);
     1659        if (VBOX_FAILURE(rc))
     1660            break;
     1661
     1662        uint64_t cbSizeFrom = VDGetSize(pDiskFrom, nImage);
     1663        if (cbSizeFrom == 0)
     1664        {
     1665            rc = VERR_VDI_VALUE_NOT_FOUND;
     1666            break;
     1667        }
     1668       
     1669        if (cbSize == 0)
     1670            cbSize = cbSizeFrom;
     1671
     1672        unsigned uImageFlagsFrom;
     1673        rc = VDGetImageFlags(pDiskFrom, nImage, &uImageFlagsFrom);
     1674        if (VBOX_FAILURE(rc))
     1675            break;
     1676     
     1677        /* @todo Get this from the source image. */
     1678        PDMMEDIAGEOMETRY PCHSGeometryFrom = {0, 0, 0};
     1679        PDMMEDIAGEOMETRY LCHSGeometryFrom = {0, 0, 0};
     1680       
     1681        unsigned uOpenFlagsFrom;
     1682        rc = VDGetOpenFlags(pDiskFrom, nImage, &uOpenFlagsFrom);
     1683        if (VBOX_FAILURE(rc))
     1684            break;
     1685
     1686        /* Create destination image with the properties of the source image. */
     1687        /* @todo Copy the comment. */
     1688        if (enmTypeFrom == VD_IMAGE_TYPE_DIFF)
     1689        {
     1690            rc = VDCreateDiff(pDiskTo, pszBackend, pszFilename, uImageFlagsFrom,
     1691                              "", uOpenFlagsFrom, NULL, NULL);
     1692        } else {
     1693            rc = VDCreateBase(pDiskTo, pszBackend, pszFilename, enmTypeFrom,
     1694                              cbSize, uImageFlagsFrom, "",
     1695                              &PCHSGeometryFrom, &LCHSGeometryFrom,
     1696                              uOpenFlagsFrom, NULL, NULL);
     1697        }
     1698        if (VBOX_FAILURE(rc))
     1699            break;
     1700
     1701        pImageTo = pDiskTo->pLast;
     1702        AssertBreak(VALID_PTR(pImageTo), rc = VERR_VDI_IMAGE_NOT_FOUND);
     1703
     1704        /* Allocate tmp buffer. */
     1705        pvBuf = RTMemTmpAlloc(VD_MERGE_BUFFER_SIZE);
     1706        if (!pvBuf)
     1707        {
     1708            rc = VERR_NO_MEMORY;
     1709            break;
     1710        }
     1711
     1712        /* Copy the data. */
     1713        uint64_t uOffset = 0;
     1714        uint64_t cbRemaining = cbSize;
     1715       
     1716        do
     1717        {
     1718            size_t cbThisRead = RT_MIN(VD_MERGE_BUFFER_SIZE, cbRemaining);
     1719
     1720            rc = vdReadHelper(pDiskFrom, pImageFrom, uOffset, pvBuf,
     1721                              cbThisRead);
     1722            if (VBOX_FAILURE(rc))
     1723                break;
     1724
     1725            rc = vdWriteHelper(pDiskTo, pImageTo, uOffset, pvBuf,
     1726                               cbThisRead);
     1727            if (VBOX_FAILURE(rc))
     1728                break;
     1729
     1730            uOffset += cbThisRead;
     1731            cbRemaining -= cbThisRead;
     1732            if (pfnProgress)
     1733            {
     1734                rc = pfnProgress(NULL /* WARNING! pVM=NULL  */,
     1735                                 ((cbSize - cbRemaining) * 100) / cbSize,
     1736                                 pvUser);
     1737                if (VBOX_FAILURE(rc))
     1738                    break;
     1739            }
     1740        } while (uOffset < cbSize);
     1741
     1742        /* If fMoveByRename is set but the backend is different, close and delete pImageFrom. */
     1743        if (   (fMoveByRename == true)
     1744            && (strcmp(pszBackend, pImageFrom->Backend->pszBackendName)))
     1745        {
     1746            vdRemoveImageFromList(pDiskFrom, pImageFrom);
     1747
     1748            /* Close and delete image. */
     1749            rc2 = pImageFrom->Backend->pfnClose(pImageFrom->pvBackendData, true);
     1750            AssertRC(rc2);
     1751            pImageFrom->pvBackendData = NULL;
     1752
     1753            /* Free remaining resources. */
     1754            if (pImageFrom->hPlugin != NIL_RTLDRMOD)
     1755                RTLdrClose(pImageFrom->hPlugin);
     1756
     1757            if (pImageFrom->pszFilename)
     1758                RTStrFree(pImageFrom->pszFilename);
     1759
     1760            RTMemFree(pImageFrom);
     1761        }
     1762    } while (0);
     1763
     1764    if (VBOX_FAILURE(rc) && pImageTo)
     1765    {
     1766        /* Error detected, but new image created. Remove image from list. */
     1767        vdRemoveImageFromList(pDiskTo, pImageTo);
     1768
     1769        /* Close and delete image. */
     1770        rc2 = pImageTo->Backend->pfnClose(pImageTo->pvBackendData, true);
     1771        AssertRC(rc2);
     1772        pImageTo->pvBackendData = NULL;
     1773
     1774        /* Free remaining resources. */
     1775        if (pImageTo->hPlugin != NIL_RTLDRMOD)
     1776            RTLdrClose(pImageTo->hPlugin);
     1777
     1778        if (pImageTo->pszFilename)
     1779            RTStrFree(pImageTo->pszFilename);
     1780       
     1781        RTMemFree(pImageTo);
     1782    }
     1783
     1784    if (pvBuf)
     1785        RTMemTmpFree(pvBuf);
     1786
     1787    if (VBOX_SUCCESS(rc) && pfnProgress)
     1788        pfnProgress(NULL /* WARNING! pVM=NULL  */, 100, pvUser);
     1789
     1790    LogFlowFunc(("returns %Vrc\n", rc));
     1791    return rc;
    15791792}
    15801793
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