VirtualBox

Changeset 38518 in vbox


Ignore:
Timestamp:
Aug 25, 2011 7:46:41 AM (14 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
73646
Message:

VHD: Clip read size before checking if the block is allocated. Fixes incorrect reads which cross block bounaries

File:
1 edited

Legend:

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

    r38469 r38518  
    14521452
    14531453        /*
     1454         * Clip read range to remain in this data block.
     1455         */
     1456        cbBuf = RT_MIN(cbBuf, (pImage->cbDataBlock - (cBATEntryIndex * VHD_SECTOR_SIZE)));
     1457
     1458        /*
    14541459         * If the block is not allocated the content of the entry is ~0
    14551460         */
    14561461        if (pImage->pBlockAllocationTable[cBlockAllocationTableEntry] == ~0U)
    1457         {
    1458             /* Return block size as read. */
    1459             *pcbActuallyRead = RT_MIN(cbBuf, pImage->cSectorsPerDataBlock * VHD_SECTOR_SIZE);
    14601462            rc = VERR_VD_BLOCK_FREE;
    1461             goto out;
    1462         }
    1463 
    1464         uVhdOffset = ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry] + pImage->cDataBlockBitmapSectors + cBATEntryIndex) * VHD_SECTOR_SIZE;
    1465         LogFlowFunc(("uVhdOffset=%llu cbBuf=%u\n", uVhdOffset, cbBuf));
    1466 
    1467         /*
    1468          * Clip read range to remain in this data block.
    1469          */
    1470         cbBuf = RT_MIN(cbBuf, (pImage->cbDataBlock - (cBATEntryIndex * VHD_SECTOR_SIZE)));
    1471 
    1472         /* Read in the block's bitmap. */
    1473         rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage,
    1474                                    ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE,
    1475                                    pImage->pu8Bitmap, pImage->cbDataBlockBitmap,
    1476                                    NULL);
    1477         if (RT_SUCCESS(rc))
    1478         {
    1479             uint32_t cSectors = 0;
    1480 
    1481             if (vhdBlockBitmapSectorContainsData(pImage, cBATEntryIndex))
     1463        {
     1464            uVhdOffset = ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry] + pImage->cDataBlockBitmapSectors + cBATEntryIndex) * VHD_SECTOR_SIZE;
     1465            LogFlowFunc(("uVhdOffset=%llu cbBuf=%u\n", uVhdOffset, cbBuf));
     1466
     1467            /* Read in the block's bitmap. */
     1468            rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage,
     1469                                       ((uint64_t)pImage->pBlockAllocationTable[cBlockAllocationTableEntry]) * VHD_SECTOR_SIZE,
     1470                                       pImage->pu8Bitmap, pImage->cbDataBlockBitmap,
     1471                                       NULL);
     1472            if (RT_SUCCESS(rc))
    14821473            {
    1483                 cBATEntryIndex++;
    1484                 cSectors = 1;
    1485 
    1486                 /*
    1487                  * The first sector being read is marked dirty, read as much as we
    1488                  * can from child. Note that only sectors that are marked dirty
    1489                  * must be read from child.
    1490                  */
    1491                 while (   (cSectors < (cbBuf / VHD_SECTOR_SIZE))
    1492                        && vhdBlockBitmapSectorContainsData(pImage, cBATEntryIndex))
     1474                uint32_t cSectors = 0;
     1475
     1476                if (vhdBlockBitmapSectorContainsData(pImage, cBATEntryIndex))
    14931477                {
    14941478                    cBATEntryIndex++;
    1495                     cSectors++;
     1479                    cSectors = 1;
     1480
     1481                    /*
     1482                     * The first sector being read is marked dirty, read as much as we
     1483                     * can from child. Note that only sectors that are marked dirty
     1484                     * must be read from child.
     1485                     */
     1486                    while (   (cSectors < (cbBuf / VHD_SECTOR_SIZE))
     1487                           && vhdBlockBitmapSectorContainsData(pImage, cBATEntryIndex))
     1488                    {
     1489                        cBATEntryIndex++;
     1490                        cSectors++;
     1491                    }
     1492
     1493                    cbBuf = cSectors * VHD_SECTOR_SIZE;
     1494
     1495                    LogFlowFunc(("uVhdOffset=%llu cbBuf=%u\n", uVhdOffset, cbBuf));
     1496                    rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage,
     1497                                               uVhdOffset, pvBuf, cbBuf, NULL);
    14961498                }
    1497 
    1498                 cbBuf = cSectors * VHD_SECTOR_SIZE;
    1499 
    1500                 LogFlowFunc(("uVhdOffset=%llu cbBuf=%u\n", uVhdOffset, cbBuf));
    1501                 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage,
    1502                                            uVhdOffset, pvBuf, cbBuf, NULL);
     1499                else
     1500                {
     1501                    /*
     1502                     * The first sector being read is marked clean, so we should read from
     1503                     * our parent instead, but only as much as there are the following
     1504                     * clean sectors, because the block may still contain dirty sectors
     1505                     * further on. We just need to compute the number of clean sectors
     1506                     * and pass it to our caller along with the notification that they
     1507                     * should be read from the parent.
     1508                     */
     1509                    cBATEntryIndex++;
     1510                    cSectors = 1;
     1511
     1512                    while (   (cSectors < (cbBuf / VHD_SECTOR_SIZE))
     1513                           && !vhdBlockBitmapSectorContainsData(pImage, cBATEntryIndex))
     1514                    {
     1515                        cBATEntryIndex++;
     1516                        cSectors++;
     1517                    }
     1518
     1519                    cbBuf = cSectors * VHD_SECTOR_SIZE;
     1520                    LogFunc(("Sectors free: uVhdOffset=%llu cbBuf=%u\n", uVhdOffset, cbBuf));
     1521                    rc = VERR_VD_BLOCK_FREE;
     1522                }
    15031523            }
    15041524            else
    1505             {
    1506                 /*
    1507                  * The first sector being read is marked clean, so we should read from
    1508                  * our parent instead, but only as much as there are the following
    1509                  * clean sectors, because the block may still contain dirty sectors
    1510                  * further on. We just need to compute the number of clean sectors
    1511                  * and pass it to our caller along with the notification that they
    1512                  * should be read from the parent.
    1513                  */
    1514                 cBATEntryIndex++;
    1515                 cSectors = 1;
    1516 
    1517                 while (   (cSectors < (cbBuf / VHD_SECTOR_SIZE))
    1518                        && !vhdBlockBitmapSectorContainsData(pImage, cBATEntryIndex))
    1519                 {
    1520                     cBATEntryIndex++;
    1521                     cSectors++;
    1522                 }
    1523 
    1524                 cbBuf = cSectors * VHD_SECTOR_SIZE;
    1525                 LogFunc(("Sectors free: uVhdOffset=%llu cbBuf=%u\n", uVhdOffset, cbBuf));
    1526                 rc = VERR_VD_BLOCK_FREE;
    1527             }
    1528         }
    1529         else
    1530             AssertMsgFailed(("Reading block bitmap failed rc=%Rrc\n", rc));
     1525                AssertMsgFailed(("Reading block bitmap failed rc=%Rrc\n", rc));
     1526        }
    15311527    }
    15321528    else
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