Changeset 31804 in vbox
- Timestamp:
- Aug 19, 2010 9:10:57 PM (14 years ago)
- Location:
- trunk/src/VBox/Devices/Storage
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/VDICore.h
r28800 r31804 356 356 } 357 357 358 DECLINLINE(u nsigned) getImageDataOffset(PVDIHEADER ph)358 DECLINLINE(uint32_t) getImageDataOffset(PVDIHEADER ph) 359 359 { 360 360 switch (GET_MAJOR_HEADER_VERSION(ph)) … … 366 366 AssertFailed(); 367 367 return 0; 368 } 369 370 DECLINLINE(void) setImageDataOffset(PVDIHEADER ph, uint32_t offData) 371 { 372 switch (GET_MAJOR_HEADER_VERSION(ph)) 373 { 374 case 0: return; 375 case 1: ph->u.v1.offData = offData; 376 } 377 AssertFailed(); 368 378 } 369 379 … … 398 408 } 399 409 410 DECLINLINE(void) setImageDiskSize(PVDIHEADER ph, uint64_t cbDisk) 411 { 412 switch (GET_MAJOR_HEADER_VERSION(ph)) 413 { 414 case 0: ph->u.v0.cbDisk = cbDisk; return; 415 case 1: ph->u.v1.cbDisk = cbDisk; return; 416 } 417 AssertFailed(); 418 } 419 400 420 DECLINLINE(unsigned) getImageBlockSize(PVDIHEADER ph) 401 421 { … … 430 450 return 0; 431 451 } 452 453 DECLINLINE(void) setImageBlocks(PVDIHEADER ph, unsigned cBlocks) 454 { 455 switch (GET_MAJOR_HEADER_VERSION(ph)) 456 { 457 case 0: ph->u.v0.cBlocks = cBlocks; return; 458 case 1: ph->u.v1.cBlocks = cBlocks; return; 459 } 460 AssertFailed(); 461 } 462 432 463 433 464 DECLINLINE(unsigned) getImageBlocksAllocated(PVDIHEADER ph) -
trunk/src/VBox/Devices/Storage/VDIHDDCore.cpp
r31776 r31804 2513 2513 uPercentStart + uPercentSpan); 2514 2514 } 2515 2516 LogFlowFunc(("returns %Rrc\n", rc)); 2517 return rc; 2518 } 2519 2520 2521 /** @copydoc VBOXHDDBACKEND::pfnResize */ 2522 static int vdiResize(void *pBackendData, uint64_t cbSize, 2523 PCPDMMEDIAGEOMETRY pPCHSGeometry, PCPDMMEDIAGEOMETRY pLCHSGeometry, 2524 unsigned uPercentStart, unsigned uPercentSpan, 2525 PVDINTERFACE pVDIfsDisk, PVDINTERFACE pVDIfsImage, 2526 PVDINTERFACE pVDIfsOperation) 2527 { 2528 PVDIIMAGEDESC pImage = (PVDIIMAGEDESC)pBackendData; 2529 int rc = VINF_SUCCESS; 2530 2531 PFNVDPROGRESS pfnProgress = NULL; 2532 void *pvUser = NULL; 2533 PVDINTERFACE pIfProgress = VDInterfaceGet(pVDIfsOperation, 2534 VDINTERFACETYPE_PROGRESS); 2535 PVDINTERFACEPROGRESS pCbProgress = NULL; 2536 if (pIfProgress) 2537 { 2538 pCbProgress = VDGetInterfaceProgress(pIfProgress); 2539 if (pCbProgress) 2540 pfnProgress = pCbProgress->pfnProgress; 2541 pvUser = pIfProgress->pvUser; 2542 } 2543 2544 /* Making the image smaller is not supported at the moment. */ 2545 if (cbSize < getImageDiskSize(&pImage->Header) || GET_MAJOR_HEADER_VERSION(&pImage->Header) == 0) 2546 rc = VERR_NOT_SUPPORTED; 2547 else if (cbSize > getImageDiskSize(&pImage->Header)) 2548 { 2549 unsigned cBlocksAllocated = getImageBlocksAllocated(&pImage->Header); 2550 uint64_t cbNew = cbSize - getImageDiskSize(&pImage->Header); 2551 uint32_t cBlocksNew = cbNew / getImageBlockSize(&pImage->Header); 2552 if (cbNew % getImageBlockSize(&pImage->Header)) 2553 cBlocksNew++; 2554 uint32_t cbAdditionalBlockspace = cBlocksNew * sizeof(VDIIMAGEBLOCKPOINTER); 2555 uint64_t cbBlockspace = getImageBlocks(&pImage->Header) * sizeof(VDIIMAGEBLOCKPOINTER) + cbAdditionalBlockspace; 2556 2557 uint64_t offImageDataNew = RT_ALIGN_32(pImage->offStartBlocks + cbBlockspace, VDI_GEOMETRY_SECTOR_SIZE); 2558 2559 if ( pImage->offStartData != offImageDataNew 2560 && getImageBlocksAllocated(&pImage->Header) > 0) 2561 { 2562 /* Calculate how many sectors nee to be relocated. */ 2563 uint64_t cbOverlapping = offImageDataNew - pImage->offStartData; 2564 unsigned cBlocksReloc = cbOverlapping / getImageBlockSize(&pImage->Header); 2565 if (cbOverlapping % getImageBlockSize(&pImage->Header)) 2566 cBlocksReloc++; 2567 2568 /* Do the relocation. */ 2569 LogFlow(("Relocating %u blocks\n", cBlocksReloc)); 2570 2571 /* 2572 * Get the blocks we need to relocate first, they are appended to the end 2573 * of the image. 2574 */ 2575 void *pvBuf = NULL, *pvZero = NULL; 2576 do 2577 { 2578 uint64_t offBlockCur = pImage->offStartData; 2579 VDIIMAGEBLOCKPOINTER uBlock = 0; 2580 2581 /* Allocate data buffer. */ 2582 pvBuf = RTMemAllocZ(pImage->cbTotalBlockData); 2583 if (!pvBuf) 2584 { 2585 rc = VERR_NO_MEMORY; 2586 break; 2587 } 2588 2589 /* Allocate buffer for overwrting with zeroes. */ 2590 pvZero = RTMemAllocZ(pImage->cbTotalBlockData); 2591 if (!pvZero) 2592 { 2593 rc = VERR_NO_MEMORY; 2594 break; 2595 } 2596 2597 for (unsigned i = 0; i < cBlocksReloc; i++) 2598 { 2599 /* Search the index in the block table. */ 2600 for (unsigned idxBlock = 0; idxBlock < cBlocksAllocated; idxBlock++) 2601 { 2602 if (pImage->paBlocks[idxBlock] == uBlock) 2603 { 2604 /* Read data and append to the end of the image. */ 2605 rc = vdiFileReadSync(pImage, offBlockCur, pvBuf, pImage->cbTotalBlockData, NULL); 2606 if (RT_FAILURE(rc)) 2607 break; 2608 2609 uint64_t offBlockAppend; 2610 rc = vdiFileGetSize(pImage, &offBlockAppend); 2611 if (RT_FAILURE(rc)) 2612 break; 2613 2614 rc = vdiFileWriteSync(pImage, offBlockAppend, pvBuf, pImage->cbTotalBlockData, NULL); 2615 if (RT_FAILURE(rc)) 2616 break; 2617 2618 /* Zero out the old block area. */ 2619 rc = vdiFileWriteSync(pImage, offBlockCur, pvZero, pImage->cbTotalBlockData, NULL); 2620 if (RT_FAILURE(rc)) 2621 break; 2622 2623 /* Update block counter. */ 2624 pImage->paBlocks[idxBlock] = cBlocksAllocated; 2625 2626 /* 2627 * Decrease the block number of all other entries in the array. 2628 * They were moved one block to the front. 2629 * Doing it as a separate step iterating over the array again 2630 * because an error while relocating the one block might end up 2631 * in a corrupted image otherwise. 2632 */ 2633 for (unsigned idxBlock2 = 0; idxBlock2 < cBlocksAllocated; idxBlock2++) 2634 { 2635 if ( idxBlock2 != idxBlock 2636 && IS_VDI_IMAGE_BLOCK_ALLOCATED(pImage->paBlocks[idxBlock2])) 2637 pImage->paBlocks[idxBlock2]--; 2638 } 2639 } 2640 } 2641 2642 if (RT_FAILURE(rc)) 2643 break; 2644 2645 uBlock++; 2646 offBlockCur += pImage->cbTotalBlockData; 2647 } 2648 } while (0); 2649 2650 if (pvBuf) 2651 RTMemFree(pvBuf); 2652 if (pvZero) 2653 RTMemFree(pvZero); 2654 } 2655 2656 /* 2657 * Relocation done, expand the block array and update the header with 2658 * the new data. 2659 */ 2660 if (RT_SUCCESS(rc)) 2661 { 2662 PVDIIMAGEBLOCKPOINTER paBlocksNew = (PVDIIMAGEBLOCKPOINTER)RTMemRealloc(pImage->paBlocks, getImageBlocks(&pImage->Header) + cBlocksNew); 2663 if (paBlocksNew) 2664 { 2665 /* Mark the new blocks as unallocated. */ 2666 for (unsigned idxBlock = getImageBlocks(&pImage->Header); idxBlock < getImageBlocks(&pImage->Header) + cBlocksNew; idxBlock++) 2667 pImage->paBlocks[idxBlock] = VDI_IMAGE_BLOCK_FREE; 2668 } 2669 else 2670 rc = VERR_NO_MEMORY; 2671 2672 /* Write the block array before updating the rest. */ 2673 rc = vdiFileWriteSync(pImage, pImage->offStartBlocks, pImage->paBlocks, 2674 sizeof(VDIIMAGEBLOCKPOINTER) * (getImageBlocks(&pImage->Header) + cBlocksNew), 2675 NULL); 2676 } 2677 2678 if (RT_SUCCESS(rc)) 2679 { 2680 /* Update size and new block count. */ 2681 setImageDiskSize(&pImage->Header, cbSize); 2682 setImageBlocks(&pImage->Header, getImageBlocks(&pImage->Header) + cBlocksNew); 2683 /* Update geometry. */ 2684 pImage->PCHSGeometry = *pPCHSGeometry; 2685 2686 PVDIDISKGEOMETRY pGeometry = getImageLCHSGeometry(&pImage->Header); 2687 if (pGeometry) 2688 { 2689 pGeometry->cCylinders = pLCHSGeometry->cCylinders; 2690 pGeometry->cHeads = pLCHSGeometry->cHeads; 2691 pGeometry->cSectors = pLCHSGeometry->cSectors; 2692 pGeometry->cbSector = VDI_GEOMETRY_SECTOR_SIZE; 2693 } 2694 } 2695 2696 /* 2697 * We need to update the new offsets for the image data in the out of memory 2698 * case too because we relocated the blocks already. 2699 */ 2700 pImage->offStartData = offImageDataNew; 2701 setImageDataOffset(&pImage->Header, offImageDataNew); 2702 2703 /* Update header information in base image file. */ 2704 vdiFlushImage(pImage); 2705 } 2706 /* Same size doesn't change the image at all. */ 2515 2707 2516 2708 LogFlowFunc(("returns %Rrc\n", rc)); … … 2617 2809 vdiCompact, 2618 2810 /* pfnResize */ 2619 NULL2811 vdiResize 2620 2812 }; 2621 2813
Note:
See TracChangeset
for help on using the changeset viewer.