Changeset 38621 in vbox for trunk/src/VBox/Storage/VDI.cpp
- Timestamp:
- Sep 4, 2011 4:56:56 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Storage/VDI.cpp
r38469 r38621 102 102 } 103 103 104 if (pImage->paBlocksRev) 105 { 106 RTMemFree(pImage->paBlocksRev); 107 pImage->paBlocksRev = NULL; 108 } 109 104 110 if (fDelete && pImage->pszFilename) 105 111 vdIfIoIntFileDelete(pImage->pIfIo, pImage->pszFilename); … … 703 709 getImageBlocks(&pImage->Header) * sizeof(VDIIMAGEBLOCKPOINTER), 704 710 NULL); 711 712 if (uOpenFlags & VD_OPEN_FLAGS_DISCARD) 713 { 714 /* 715 * Create the back resolving table for discards. 716 * any error or inconsistency results in a fail because this might 717 * get us into trouble later on. 718 */ 719 pImage->paBlocksRev = (unsigned *)RTMemAllocZ(sizeof(unsigned) * getImageBlocks(&pImage->Header)); 720 if (pImage->paBlocksRev) 721 { 722 unsigned cBlocksAllocated = getImageBlocksAllocated(&pImage->Header); 723 unsigned cBlocks = getImageBlocks(&pImage->Header); 724 725 for (unsigned i = 0; i < cBlocksAllocated; i++) 726 pImage->paBlocksRev[i] = VDI_IMAGE_BLOCK_FREE; 727 728 for (unsigned i = 0; i < cBlocks; i++) 729 { 730 VDIIMAGEBLOCKPOINTER ptrBlock = pImage->paBlocks[i]; 731 if (IS_VDI_IMAGE_BLOCK_ALLOCATED(ptrBlock)) 732 { 733 if (ptrBlock < cBlocksAllocated) 734 { 735 if (pImage->paBlocksRev[ptrBlock] == VDI_IMAGE_BLOCK_FREE) 736 pImage->paBlocksRev[ptrBlock] = i; 737 else 738 { 739 rc = VERR_VD_VDI_INVALID_HEADER; 740 break; 741 } 742 } 743 else 744 { 745 rc = VERR_VD_VDI_INVALID_HEADER; 746 break; 747 } 748 } 749 } 750 } 751 else 752 rc = VERR_NO_MEMORY; 753 } 705 754 706 755 out: … … 1205 1254 goto out; 1206 1255 pImage->paBlocks[uBlock] = cBlocksAllocated; 1256 1257 if (pImage->paBlocksRev) 1258 pImage->paBlocksRev[cBlocksAllocated] = uBlock; 1259 1207 1260 setImageBlocksAllocated(&pImage->Header, cBlocksAllocated + 1); 1208 1261 … … 1488 1541 1489 1542 /* Image must be opened and the new flags must be valid. */ 1490 if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE | VD_OPEN_FLAGS_SEQUENTIAL )))1543 if (!pImage || (uOpenFlags & ~(VD_OPEN_FLAGS_READONLY | VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_ASYNC_IO | VD_OPEN_FLAGS_SHAREABLE | VD_OPEN_FLAGS_SEQUENTIAL | VD_OPEN_FLAGS_DISCARD))) 1491 1544 { 1492 1545 rc = VERR_INVALID_PARAMETER; … … 2004 2057 goto out; 2005 2058 pImage->paBlocks[uBlock] = cBlocksAllocated; 2059 2060 if (pImage->paBlocksRev) 2061 pImage->paBlocksRev[cBlocksAllocated] = uBlock; 2062 2006 2063 setImageBlocksAllocated(&pImage->Header, cBlocksAllocated + 1); 2007 2064 … … 2481 2538 2482 2539 2540 /** @copydoc VBOXHDDBACKEND::pfnDiscard */ 2541 static DECLCALLBACK(int) vdiDiscard(void *pBackendData, 2542 uint64_t uOffset, size_t cbDiscard, 2543 size_t *pcbPreAllocated, 2544 size_t *pcbPostAllocated, 2545 size_t *pcbActuallyDiscarded, 2546 void **ppbmAllocationBitmap, 2547 unsigned fDiscard) 2548 { 2549 PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData; 2550 unsigned uBlock; 2551 unsigned offDiscard; 2552 int rc = VINF_SUCCESS; 2553 void *pvBlock = NULL; 2554 2555 LogFlowFunc(("pBackendData=%#p uOffset=%llu cbDiscard=%zu pcbPreAllocated=%#p pcbPostAllocated=%#p pcbActuallyDiscarded=%#p ppbmAllocationBitmap=%#p fDiscard=%#x\n", 2556 pBackendData, uOffset, cbDiscard, pcbPreAllocated, pcbPostAllocated, pcbActuallyDiscarded, ppbmAllocationBitmap, fDiscard)); 2557 2558 AssertPtr(pImage); 2559 Assert(!(uOffset % 512)); 2560 Assert(!(cbDiscard % 512)); 2561 2562 do 2563 { 2564 AssertMsgBreakStmt(!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY), 2565 ("Image is opened readonly\n"), 2566 rc = VERR_VD_IMAGE_READ_ONLY); 2567 2568 AssertMsgBreakStmt(cbDiscard, 2569 ("cbDiscard=%u\n", cbDiscard), 2570 rc = VERR_INVALID_PARAMETER); 2571 2572 /* Calculate starting block number and offset inside it. */ 2573 uBlock = (unsigned)(uOffset >> pImage->uShiftOffset2Index); 2574 offDiscard = (unsigned)uOffset & pImage->uBlockMask; 2575 2576 /* Clip range to at most the rest of the block. */ 2577 cbDiscard = RT_MIN(cbDiscard, getImageBlockSize(&pImage->Header) - offDiscard); 2578 Assert(!(cbDiscard % 512)); 2579 2580 if (pcbPreAllocated) 2581 *pcbPreAllocated = 0; 2582 2583 if (pcbPostAllocated) 2584 *pcbPostAllocated = 0; 2585 2586 if (IS_VDI_IMAGE_BLOCK_ALLOCATED(pImage->paBlocks[uBlock])) 2587 { 2588 uint8_t *pbBlockData; 2589 size_t cbPreAllocated, cbPostAllocated; 2590 2591 cbPreAllocated = offDiscard % getImageBlockSize(&pImage->Header); 2592 cbPostAllocated = getImageBlockSize(&pImage->Header) - cbDiscard - cbPreAllocated; 2593 2594 /* Read the block data. */ 2595 pvBlock = RTMemAlloc(pImage->cbTotalBlockData); 2596 if (!pvBlock) 2597 { 2598 rc = VERR_NO_MEMORY; 2599 break; 2600 } 2601 pbBlockData = (uint8_t *)pvBlock + pImage->offStartBlockData; 2602 2603 uint64_t u64Offset = (uint64_t)pImage->paBlocks[uBlock] * pImage->cbTotalBlockData + pImage->offStartData; 2604 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, u64Offset, 2605 pvBlock, pImage->cbTotalBlockData, NULL); 2606 if (RT_FAILURE(rc)) 2607 break; 2608 2609 /* Clear data. */ 2610 memset(pbBlockData + offDiscard , 0, cbDiscard); 2611 2612 Assert(!(cbDiscard % 4)); 2613 Assert(cbDiscard * 8 <= UINT32_MAX); 2614 if (ASMBitFirstSet((volatile void *)pbBlockData, getImageBlockSize(&pImage->Header) * 8) == -1) 2615 { 2616 uint64_t cbImage; 2617 unsigned idxLastBlock = getImageBlocksAllocated(&pImage->Header) - 1; 2618 unsigned uBlockLast = pImage->paBlocksRev[idxLastBlock]; 2619 2620 pImage->paBlocksRev[idxLastBlock] = VDI_IMAGE_BLOCK_FREE; 2621 2622 /* 2623 * The block is empty, remove it. 2624 * Read the last block of the image first. 2625 */ 2626 if (idxLastBlock != pImage->paBlocks[uBlock]) 2627 { 2628 u64Offset = (uint64_t)idxLastBlock * pImage->cbTotalBlockData + pImage->offStartData; 2629 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, u64Offset, 2630 pvBlock, pImage->cbTotalBlockData, NULL); 2631 if (RT_FAILURE(rc)) 2632 break; 2633 2634 /* Write to the now unallocated block. */ 2635 u64Offset = (uint64_t)pImage->paBlocks[uBlock] * pImage->cbTotalBlockData + pImage->offStartData; 2636 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, u64Offset, 2637 pvBlock, pImage->cbTotalBlockData, NULL); 2638 if (RT_FAILURE(rc)) 2639 break; 2640 2641 /* Update block and reverse block tables. */ 2642 pImage->paBlocks[uBlockLast] = pImage->paBlocks[uBlock]; 2643 rc = vdiUpdateBlockInfo(pImage, uBlockLast); 2644 if (RT_FAILURE(rc)) 2645 break; 2646 } 2647 2648 pImage->paBlocks[uBlock] = VDI_IMAGE_BLOCK_ZERO; 2649 2650 /* Update the block pointers. */ 2651 setImageBlocksAllocated(&pImage->Header, idxLastBlock); 2652 rc = vdiUpdateBlockInfo(pImage, uBlock); 2653 if (RT_FAILURE(rc)) 2654 break; 2655 2656 /* Set new file size. */ 2657 rc = vdIfIoIntFileGetSize(pImage->pIfIo, pImage->pStorage, &cbImage); 2658 if (RT_FAILURE(rc)) 2659 break; 2660 2661 rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage, cbImage - pImage->cbTotalBlockData); 2662 } 2663 else /* if (fDiscard & VD_DISCARD_MARK_UNUSED) */ 2664 { 2665 /* Write changed data to the image. */ 2666 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, u64Offset + offDiscard, 2667 pbBlockData + offDiscard, cbDiscard, NULL); 2668 } 2669 #if 0 2670 else 2671 { 2672 /* Block has data, create allocation bitmap. */ 2673 *pcbPreAllocated = cbPreAllocated; 2674 *pcbPostAllocated = cbPostAllocated; 2675 *ppbmAllocationBitmap = vdAllocationBitmapCreate(pvBlock, getImageBlockSize(&pImage->Header)); 2676 if (RT_UNLIKELY(!*ppbmAllocationBitmap)) 2677 rc = VERR_NO_MEMORY; 2678 else 2679 rc = VERR_VD_DISCARD_ALIGNMENT_NOT_MET; 2680 } 2681 #endif 2682 } 2683 /* else: nothing to do. */ 2684 } while (0); 2685 2686 if (pcbActuallyDiscarded) 2687 *pcbActuallyDiscarded = cbDiscard; 2688 2689 if (pvBlock) 2690 RTMemFree(pvBlock); 2691 2692 LogFlowFunc(("returns %Rrc\n", rc)); 2693 return rc; 2694 } 2695 2483 2696 VBOXHDDBACKEND g_VDIBackend = 2484 2697 { … … 2489 2702 /* uBackendCaps */ 2490 2703 VD_CAP_UUID | VD_CAP_CREATE_FIXED | VD_CAP_CREATE_DYNAMIC 2491 | VD_CAP_DIFF | VD_CAP_FILE | VD_CAP_ASYNC | VD_CAP_VFS ,2704 | VD_CAP_DIFF | VD_CAP_FILE | VD_CAP_ASYNC | VD_CAP_VFS | VD_CAP_DISCARD, 2492 2705 /* paFileExtensions */ 2493 2706 s_aVdiFileExtensions, … … 2577 2790 vdiCompact, 2578 2791 /* pfnResize */ 2579 vdiResize 2792 vdiResize, 2793 /* pfnDiscard */ 2794 vdiDiscard 2580 2795 };
Note:
See TracChangeset
for help on using the changeset viewer.