VirtualBox

Changeset 38676 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Sep 7, 2011 1:27:22 PM (13 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
73893
Message:

VDI/Discard: Don't read and check a block if the whole block is discarded anyway, saves I/O and CPU cycles

File:
1 edited

Legend:

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

    r38657 r38676  
    887887    }
    888888
     889    return rc;
     890}
     891
     892/**
     893 * Internal: Discard a whole block from the image filling the created hole with
     894 * data from another block.
     895 *
     896 * @returns VBox status code.
     897 * @param   pImage    VDI image instance data.
     898 * @param   uBlock    The block to discard.
     899 * @param   pvBlock   Memory to use for the I/O.
     900 */
     901static int vdiDiscardBlock(PVDIIMAGEDESC pImage, unsigned uBlock, void *pvBlock)
     902{
     903    int rc = VINF_SUCCESS;
     904    uint64_t cbImage;
     905    unsigned idxLastBlock = getImageBlocksAllocated(&pImage->Header) - 1;
     906    unsigned uBlockLast = pImage->paBlocksRev[idxLastBlock];
     907    VDIIMAGEBLOCKPOINTER ptrBlockDiscard = pImage->paBlocks[uBlock];
     908
     909    LogFlowFunc(("pImage=%#p uBlock=%u pvBlock=%#p\n",
     910                 pImage, uBlock, pvBlock));
     911
     912    pImage->paBlocksRev[idxLastBlock] = VDI_IMAGE_BLOCK_FREE;
     913
     914    do
     915    {
     916        /*
     917         * The block is empty, remove it.
     918         * Read the last block of the image first.
     919         */
     920        if (idxLastBlock != ptrBlockDiscard)
     921        {
     922            uint64_t u64Offset;
     923
     924            LogFlowFunc(("Moving block [%u]=%u into [%u]=%u\n",
     925                         uBlockLast, idxLastBlock, uBlock, pImage->paBlocks[uBlock]));
     926
     927            u64Offset = (uint64_t)idxLastBlock * pImage->cbTotalBlockData + pImage->offStartData;
     928            rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, u64Offset,
     929                                       pvBlock, pImage->cbTotalBlockData, NULL);
     930            if (RT_FAILURE(rc))
     931                break;
     932
     933            /* Write to the now unallocated block. */
     934            u64Offset = (uint64_t)ptrBlockDiscard * pImage->cbTotalBlockData + pImage->offStartData;
     935            rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, u64Offset,
     936                                        pvBlock, pImage->cbTotalBlockData, NULL);
     937            if (RT_FAILURE(rc))
     938                break;
     939
     940            /* Update block and reverse block tables. */
     941            pImage->paBlocks[uBlockLast] = ptrBlockDiscard;
     942            pImage->paBlocksRev[ptrBlockDiscard] = uBlockLast;
     943            rc = vdiUpdateBlockInfo(pImage, uBlockLast);
     944            if (RT_FAILURE(rc))
     945                break;
     946        }
     947        else
     948            LogFlowFunc(("Discard last block [%u]=%u\n", uBlock, pImage->paBlocks[uBlock]));
     949
     950        pImage->paBlocks[uBlock] = VDI_IMAGE_BLOCK_ZERO;
     951
     952        /* Update the block pointers. */
     953        setImageBlocksAllocated(&pImage->Header, idxLastBlock);
     954        rc = vdiUpdateBlockInfo(pImage, uBlock);
     955        if (RT_FAILURE(rc))
     956            break;
     957
     958        /* Set new file size. */
     959        rc = vdIfIoIntFileGetSize(pImage->pIfIo, pImage->pStorage, &cbImage);
     960        if (RT_FAILURE(rc))
     961            break;
     962
     963        LogFlowFunc(("Set new size %llu\n", cbImage - pImage->cbTotalBlockData));
     964        rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage, cbImage - pImage->cbTotalBlockData);
     965    } while (0);
     966
     967    LogFlowFunc(("returns rc=%Rrc\n", rc));
    889968    return rc;
    890969}
     
    26462725                break;
    26472726            }
    2648             pbBlockData = (uint8_t *)pvBlock + pImage->offStartBlockData;
    2649 
    2650             uint64_t u64Offset = (uint64_t)pImage->paBlocks[uBlock] * pImage->cbTotalBlockData + pImage->offStartData;
    2651             rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, u64Offset,
    2652                                        pvBlock, pImage->cbTotalBlockData, NULL);
    2653             if (RT_FAILURE(rc))
    2654                 break;
    2655 
    2656             /* Clear data. */
    2657             memset(pbBlockData + offDiscard , 0, cbDiscard);
    2658 
    2659             Assert(!(cbDiscard % 4));
    2660             Assert(cbDiscard * 8 <= UINT32_MAX);
    2661             if (ASMBitFirstSet((volatile void *)pbBlockData, getImageBlockSize(&pImage->Header) * 8) == -1)
    2662             {
    2663                 uint64_t cbImage;
    2664                 unsigned idxLastBlock = getImageBlocksAllocated(&pImage->Header) - 1;
    2665                 unsigned uBlockLast = pImage->paBlocksRev[idxLastBlock];
    2666                 VDIIMAGEBLOCKPOINTER ptrBlockDiscard = pImage->paBlocks[uBlock];
    2667 
    2668                 pImage->paBlocksRev[idxLastBlock] = VDI_IMAGE_BLOCK_FREE;
    2669 
     2727
     2728            if (!cbPreAllocated && !cbPostAllocated)
     2729            {
    26702730                /*
    2671                  * The block is empty, remove it.
    2672                  * Read the last block of the image first.
     2731                 * Discarding a whole block, don't check for allocated sectors.
     2732                 * It is possible to just remove the whole block which avoids
     2733                 * one read and checking the whole block for data.
    26732734                 */
    2674                 if (idxLastBlock != ptrBlockDiscard)
     2735                rc = vdiDiscardBlock(pImage, uBlock, pvBlock);
     2736            }
     2737            else
     2738            {
     2739                /* Read data. */
     2740                pbBlockData = (uint8_t *)pvBlock + pImage->offStartBlockData;
     2741
     2742                uint64_t u64Offset = (uint64_t)pImage->paBlocks[uBlock] * pImage->cbTotalBlockData + pImage->offStartData;
     2743                rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, u64Offset,
     2744                                           pvBlock, pImage->cbTotalBlockData, NULL);
     2745                if (RT_FAILURE(rc))
     2746                    break;
     2747
     2748                /* Clear data. */
     2749                memset(pbBlockData + offDiscard , 0, cbDiscard);
     2750
     2751                Assert(!(cbDiscard % 4));
     2752                Assert(cbDiscard * 8 <= UINT32_MAX);
     2753                if (ASMBitFirstSet((volatile void *)pbBlockData, getImageBlockSize(&pImage->Header) * 8) == -1)
     2754                    rc = vdiDiscardBlock(pImage, uBlock, pvBlock);
     2755                else if (fDiscard & VD_DISCARD_MARK_UNUSED)
    26752756                {
    2676                     LogFlowFunc(("Moving block [%u]=%u into [%u]=%u\n",
    2677                                  uBlockLast, idxLastBlock, uBlock, pImage->paBlocks[uBlock]));
    2678 
    2679                     u64Offset = (uint64_t)idxLastBlock * pImage->cbTotalBlockData + pImage->offStartData;
    2680                     rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, u64Offset,
    2681                                                pvBlock, pImage->cbTotalBlockData, NULL);
    2682                     if (RT_FAILURE(rc))
    2683                         break;
    2684 
    2685                     /* Write to the now unallocated block. */
    2686                     u64Offset = (uint64_t)ptrBlockDiscard * pImage->cbTotalBlockData + pImage->offStartData;
    2687                     rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, u64Offset,
    2688                                                 pvBlock, pImage->cbTotalBlockData, NULL);
    2689                     if (RT_FAILURE(rc))
    2690                         break;
    2691 
    2692                     /* Update block and reverse block tables. */
    2693                     pImage->paBlocks[uBlockLast] = ptrBlockDiscard;
    2694                     pImage->paBlocksRev[ptrBlockDiscard] = uBlockLast;
    2695                     rc = vdiUpdateBlockInfo(pImage, uBlockLast);
    2696                     if (RT_FAILURE(rc))
    2697                         break;
     2757                    /* Write changed data to the image. */
     2758                    rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, u64Offset + offDiscard,
     2759                                                pbBlockData + offDiscard, cbDiscard, NULL);
    26982760                }
    26992761                else
    2700                     LogFlowFunc(("Discard last block [%u]=%u\n", uBlock, pImage->paBlocks[uBlock]));
    2701 
    2702                 pImage->paBlocks[uBlock] = VDI_IMAGE_BLOCK_ZERO;
    2703 
    2704                 /* Update the block pointers. */
    2705                 setImageBlocksAllocated(&pImage->Header, idxLastBlock);
    2706                 rc = vdiUpdateBlockInfo(pImage, uBlock);
    2707                 if (RT_FAILURE(rc))
    2708                     break;
    2709 
    2710                 /* Set new file size. */
    2711                 rc = vdIfIoIntFileGetSize(pImage->pIfIo, pImage->pStorage, &cbImage);
    2712                 if (RT_FAILURE(rc))
    2713                     break;
    2714 
    2715                 LogFlowFunc(("Set new size %llu\n", cbImage - pImage->cbTotalBlockData));
    2716                 rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage, cbImage - pImage->cbTotalBlockData);
    2717             }
    2718             else if (fDiscard & VD_DISCARD_MARK_UNUSED)
    2719             {
    2720                 /* Write changed data to the image. */
    2721                 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, u64Offset + offDiscard,
    2722                                             pbBlockData + offDiscard, cbDiscard, NULL);
    2723             }
    2724             else
    2725             {
    2726                 /* Block has data, create allocation bitmap. */
    2727                 *pcbPreAllocated = cbPreAllocated;
    2728                 *pcbPostAllocated = cbPostAllocated;
    2729                 *ppbmAllocationBitmap = vdiAllocationBitmapCreate(pbBlockData, getImageBlockSize(&pImage->Header));
    2730                 if (RT_UNLIKELY(!*ppbmAllocationBitmap))
    2731                     rc = VERR_NO_MEMORY;
    2732                 else
    2733                     rc = VERR_VD_DISCARD_ALIGNMENT_NOT_MET;
    2734             }
    2735         }
     2762                {
     2763                    /* Block has data, create allocation bitmap. */
     2764                    *pcbPreAllocated = cbPreAllocated;
     2765                    *pcbPostAllocated = cbPostAllocated;
     2766                    *ppbmAllocationBitmap = vdiAllocationBitmapCreate(pbBlockData, getImageBlockSize(&pImage->Header));
     2767                    if (RT_UNLIKELY(!*ppbmAllocationBitmap))
     2768                        rc = VERR_NO_MEMORY;
     2769                    else
     2770                        rc = VERR_VD_DISCARD_ALIGNMENT_NOT_MET;
     2771                }
     2772            } /* if: no complete block discarded */
     2773        } /* if: Block is allocated. */
    27362774        /* else: nothing to do. */
    27372775    } while (0);
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