VirtualBox

Changeset 38670 in vbox


Ignore:
Timestamp:
Sep 7, 2011 9:40:44 AM (14 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
73883
Message:

DrvDiskIntegrity: Discard records if consistency check is enabled

File:
1 edited

Legend:

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

    r38644 r38670  
    260260}
    261261
     262static void drvdiskintIoLogEntryRelease(PIOLOGENT pIoLogEnt)
     263{
     264    pIoLogEnt->cRefs--;
     265    if (!pIoLogEnt->cRefs)
     266        RTMemFree(pIoLogEnt);
     267}
     268
    262269/**
    263270 * Record a successful write to the virtual disk.
     
    469476
    470477/**
     478 * Discards the given ranges from the disk.
     479 *
     480 * @returns VBox status code.
     481 * @param   pThis    Disk integrity driver instance data.
     482 * @param   paRanges Array of ranges to discard.
     483 * @param   cRanges  Number of ranges in the array.
     484 */
     485static int drvdiskintDiscardRecords(PDRVDISKINTEGRITY pThis, PPDMRANGE paRanges, unsigned cRanges)
     486{
     487    int rc = VINF_SUCCESS;
     488
     489    LogFlowFunc(("pThis=%#p paRanges=%#p cRanges=%u\n", pThis, paRanges, cRanges));
     490
     491    for (unsigned i = 0; i < cRanges; i++)
     492    {
     493        uint64_t offStart = paRanges[i].offStart;
     494        size_t cbLeft = paRanges[i].cbRange;
     495
     496        LogFlowFunc(("Discarding off=%llu cbRange=%zu\n", offStart, cbLeft));
     497
     498        while (cbLeft)
     499        {
     500            size_t cbRange;
     501            PDRVDISKSEGMENT pSeg = (PDRVDISKSEGMENT)RTAvlrFileOffsetRangeGet(pThis->pTreeSegments, offStart);
     502
     503            if (!pSeg)
     504            {
     505                /* Get next segment */
     506                pSeg = (PDRVDISKSEGMENT)RTAvlrFileOffsetGetBestFit(pThis->pTreeSegments, offStart, true);
     507                if (   !pSeg
     508                    || (RTFOFF)offStart + (RTFOFF)cbLeft <= pSeg->Core.Key)
     509                    cbRange = cbLeft;
     510                else
     511                    cbRange = pSeg->Core.Key - offStart;
     512
     513                Assert(!(cbRange % 512));
     514            }
     515            else
     516            {
     517                size_t cbPreLeft, cbPostLeft;
     518
     519                cbRange    = RT_MIN(cbRange, pSeg->Core.KeyLast - offStart + 1);
     520                cbPreLeft  = offStart - pSeg->Core.Key;
     521                cbPostLeft = pSeg->cbSeg - cbRange - cbPreLeft;
     522
     523                Assert(!(cbRange % 512));
     524                Assert(!(cbPreLeft % 512));
     525                Assert(!(cbPostLeft % 512));
     526
     527                LogFlowFunc(("cbRange=%zu cbPreLeft=%zu cbPostLeft=%zu\n",
     528                             cbRange, cbPreLeft, cbPostLeft));
     529
     530                RTAvlrFileOffsetRemove(pThis->pTreeSegments, pSeg->Core.Key);
     531
     532                if (!cbPreLeft && !cbPostLeft)
     533                {
     534                    /* Just free the whole segment. */
     535                    LogFlowFunc(("Freeing whole segment pSeg=%#p\n", pSeg));
     536                    RTMemFree(pSeg->pbSeg);
     537                    for (unsigned idx = 0; idx < pSeg->cIoLogEntries; idx++)
     538                        drvdiskintIoLogEntryRelease(pSeg->apIoLog[idx]);
     539                    RTMemFree(pSeg);
     540                }
     541                else if (cbPreLeft && !cbPostLeft)
     542                {
     543                    /* Realloc to new size and insert. */
     544                    LogFlowFunc(("Realloc segment pSeg=%#p\n", pSeg));
     545                    pSeg->pbSeg = (uint8_t *)RTMemRealloc(pSeg->pbSeg, cbPreLeft);
     546                    for (unsigned idx = cbPreLeft / 512; idx < pSeg->cIoLogEntries; idx++)
     547                        drvdiskintIoLogEntryRelease(pSeg->apIoLog[idx]);
     548                    pSeg = (PDRVDISKSEGMENT)RTMemRealloc(pSeg, RT_OFFSETOF(DRVDISKSEGMENT, apIoLog[cbPreLeft / 512]));
     549                    pSeg->Core.KeyLast = pSeg->Core.Key + cbPreLeft - 1;
     550                    pSeg->cbSeg = cbPreLeft;
     551                    pSeg->cIoLogEntries = cbPreLeft / 512;
     552                    bool fInserted = RTAvlrFileOffsetInsert(pThis->pTreeSegments, &pSeg->Core);
     553                    Assert(fInserted);
     554                }
     555                else if (!cbPreLeft && cbPostLeft)
     556                {
     557                    /* Move data to the front and realloc. */
     558                    LogFlowFunc(("Move data and realloc segment pSeg=%#p\n", pSeg));
     559                    memmove(pSeg->pbSeg, pSeg->pbSeg + cbRange, cbPostLeft);
     560                    for (unsigned idx = 0; idx < cbRange / 512; idx++)
     561                        drvdiskintIoLogEntryRelease(pSeg->apIoLog[idx]);
     562                    for (unsigned idx = 0; idx < cbPostLeft /512; idx++)
     563                        pSeg->apIoLog[idx] = pSeg->apIoLog[(cbRange / 512) + idx];
     564                    pSeg = (PDRVDISKSEGMENT)RTMemRealloc(pSeg, RT_OFFSETOF(DRVDISKSEGMENT, apIoLog[cbPostLeft / 512]));
     565                    pSeg->pbSeg = (uint8_t *)RTMemRealloc(pSeg->pbSeg, cbPostLeft);
     566                    pSeg->Core.Key += cbRange;
     567                    pSeg->cbSeg = cbPostLeft;
     568                    pSeg->cIoLogEntries = cbPostLeft / 512;
     569                    bool fInserted = RTAvlrFileOffsetInsert(pThis->pTreeSegments, &pSeg->Core);
     570                    Assert(fInserted);
     571                }
     572                else
     573                {
     574                    /* Split the segment into 2 new segments. */
     575                    LogFlowFunc(("Split segment pSeg=%#p\n", pSeg));
     576                    PDRVDISKSEGMENT pSegPost = (PDRVDISKSEGMENT)RTMemAllocZ(RT_OFFSETOF(DRVDISKSEGMENT, apIoLog[cbPostLeft / 512]));
     577                    if (pSegPost)
     578                    {
     579                        pSegPost->Core.Key      = pSeg->Core.Key + cbPreLeft + cbRange;
     580                        pSegPost->Core.KeyLast  = pSeg->Core.KeyLast;
     581                        pSegPost->cbSeg         = cbPostLeft;
     582                        pSegPost->pbSeg         = (uint8_t *)RTMemAllocZ(cbPostLeft);
     583                        pSegPost->cIoLogEntries = cbPostLeft / 512;
     584                        if (!pSegPost->pbSeg)
     585                            RTMemFree(pSegPost);
     586                        else
     587                        {
     588                            memcpy(pSegPost->pbSeg, pSeg->pbSeg + cbPreLeft + cbRange, cbPostLeft);
     589                            for (unsigned idx = 0; idx < cbPostLeft / 512; idx++)
     590                                pSegPost->apIoLog[idx] = pSeg->apIoLog[((cbPreLeft + cbRange) / 512) + idx];
     591
     592                            bool fInserted = RTAvlrFileOffsetInsert(pThis->pTreeSegments, &pSegPost->Core);
     593                            Assert(fInserted);
     594                        }
     595                    }
     596
     597                    /* Shrink the current segment. */
     598                    pSeg->pbSeg = (uint8_t *)RTMemRealloc(pSeg->pbSeg, cbPreLeft);
     599                    for (unsigned idx = cbPreLeft / 512; idx < (cbPreLeft + cbRange) / 512; idx++)
     600                        drvdiskintIoLogEntryRelease(pSeg->apIoLog[idx]);
     601                    pSeg = (PDRVDISKSEGMENT)RTMemRealloc(pSeg, RT_OFFSETOF(DRVDISKSEGMENT, apIoLog[cbPreLeft / 512]));
     602                    pSeg->Core.KeyLast = pSeg->Core.Key + cbPreLeft - 1;
     603                    pSeg->cbSeg = cbPreLeft;
     604                    pSeg->cIoLogEntries = cbPreLeft / 512;
     605                    bool fInserted = RTAvlrFileOffsetInsert(pThis->pTreeSegments, &pSeg->Core);
     606                    Assert(fInserted);
     607                } /* if (cbPreLeft && cbPostLeft) */
     608            }
     609
     610            offStart += cbRange;
     611            cbLeft   -= cbRange;
     612        }
     613    }
     614
     615    LogFlowFunc(("returns rc=%Rrc\n", rc));
     616    return rc;
     617}
     618
     619/**
    471620 * Adds a request to the active list.
    472621 *
     
    8901039        AssertRC(rc2);
    8911040    }
     1041
     1042    if (pThis->fCheckConsistency)
     1043        rc = drvdiskintDiscardRecords(pThis, paRanges, cRanges);
    8921044
    8931045    return rc;
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette