Changeset 38676 in vbox for trunk/src/VBox
- Timestamp:
- Sep 7, 2011 1:27:22 PM (13 years ago)
- svn:sync-xref-src-repo-rev:
- 73893
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Storage/VDI.cpp
r38657 r38676 887 887 } 888 888 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 */ 901 static 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)); 889 968 return rc; 890 969 } … … 2646 2725 break; 2647 2726 } 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 { 2670 2730 /* 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. 2673 2734 */ 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) 2675 2756 { 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); 2698 2760 } 2699 2761 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. */ 2736 2774 /* else: nothing to do. */ 2737 2775 } while (0);
Note:
See TracChangeset
for help on using the changeset viewer.