Changeset 64504 in vbox for trunk/src/VBox/Storage
- Timestamp:
- Nov 1, 2016 9:56:56 AM (9 years ago)
- svn:sync-xref-src-repo-rev:
- 111642
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Storage/VDI.cpp
r64272 r64504 2485 2485 uint64_t offStartDataNew = RT_ALIGN_32(pImage->offStartBlocks + cbBlockspaceNew, VDI_DATA_ALIGN); /** < New start offset for block data after the resize */ 2486 2486 2487 if ( pImage->offStartData < offStartDataNew 2488 && cBlocksAllocated > 0) 2489 { 2490 /* Calculate how many sectors need to be relocated. */ 2491 uint64_t cbOverlapping = offStartDataNew - pImage->offStartData; 2492 unsigned cBlocksReloc = cbOverlapping / getImageBlockSize(&pImage->Header); 2493 if (cbOverlapping % getImageBlockSize(&pImage->Header)) 2494 cBlocksReloc++; 2495 2496 /* Since only full blocks can be relocated the new data start is 2497 * determined by moving it block by block. */ 2498 cBlocksReloc = RT_MIN(cBlocksReloc, cBlocksAllocated); 2499 offStartDataNew = pImage->offStartData; 2500 2501 /* Do the relocation. */ 2502 LogFlow(("Relocating %u blocks\n", cBlocksReloc)); 2487 if (pImage->offStartData < offStartDataNew) 2488 { 2489 if (cBlocksAllocated > 0) 2490 { 2491 /* Calculate how many sectors need to be relocated. */ 2492 uint64_t cbOverlapping = offStartDataNew - pImage->offStartData; 2493 unsigned cBlocksReloc = cbOverlapping / getImageBlockSize(&pImage->Header); 2494 if (cbOverlapping % getImageBlockSize(&pImage->Header)) 2495 cBlocksReloc++; 2496 2497 /* Since only full blocks can be relocated the new data start is 2498 * determined by moving it block by block. */ 2499 cBlocksReloc = RT_MIN(cBlocksReloc, cBlocksAllocated); 2500 offStartDataNew = pImage->offStartData; 2501 2502 /* Do the relocation. */ 2503 LogFlow(("Relocating %u blocks\n", cBlocksReloc)); 2504 2505 /* 2506 * Get the blocks we need to relocate first, they are appended to the end 2507 * of the image. 2508 */ 2509 void *pvBuf = NULL, *pvZero = NULL; 2510 do 2511 { 2512 /* Allocate data buffer. */ 2513 pvBuf = RTMemAllocZ(pImage->cbTotalBlockData); 2514 if (!pvBuf) 2515 { 2516 rc = VERR_NO_MEMORY; 2517 break; 2518 } 2519 2520 /* Allocate buffer for overwriting with zeroes. */ 2521 pvZero = RTMemAllocZ(pImage->cbTotalBlockData); 2522 if (!pvZero) 2523 { 2524 rc = VERR_NO_MEMORY; 2525 break; 2526 } 2527 2528 for (unsigned i = 0; i < cBlocksReloc; i++) 2529 { 2530 /* Search the index in the block table. */ 2531 for (unsigned idxBlock = 0; idxBlock < cBlocksOld; idxBlock++) 2532 { 2533 if (!pImage->paBlocks[idxBlock]) 2534 { 2535 /* Read data and append to the end of the image. */ 2536 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, 2537 offStartDataNew, pvBuf, 2538 pImage->cbTotalBlockData); 2539 if (RT_FAILURE(rc)) 2540 break; 2541 2542 uint64_t offBlockAppend; 2543 rc = vdIfIoIntFileGetSize(pImage->pIfIo, pImage->pStorage, &offBlockAppend); 2544 if (RT_FAILURE(rc)) 2545 break; 2546 2547 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, 2548 offBlockAppend, pvBuf, 2549 pImage->cbTotalBlockData); 2550 if (RT_FAILURE(rc)) 2551 break; 2552 2553 /* Zero out the old block area. */ 2554 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, 2555 offStartDataNew, pvZero, 2556 pImage->cbTotalBlockData); 2557 if (RT_FAILURE(rc)) 2558 break; 2559 2560 /* Update block counter. */ 2561 pImage->paBlocks[idxBlock] = cBlocksAllocated - 1; 2562 2563 /* 2564 * Decrease the block number of all other entries in the array. 2565 * They were moved one block to the front. 2566 * Doing it as a separate step iterating over the array again 2567 * because an error while relocating the block might end up 2568 * in a corrupted image otherwise. 2569 */ 2570 for (unsigned idxBlock2 = 0; idxBlock2 < cBlocksOld; idxBlock2++) 2571 { 2572 if ( idxBlock2 != idxBlock 2573 && IS_VDI_IMAGE_BLOCK_ALLOCATED(pImage->paBlocks[idxBlock2])) 2574 pImage->paBlocks[idxBlock2]--; 2575 } 2576 2577 /* Continue with the next block. */ 2578 break; 2579 } 2580 } 2581 2582 if (RT_FAILURE(rc)) 2583 break; 2584 2585 offStartDataNew += pImage->cbTotalBlockData; 2586 } 2587 } while (0); 2588 2589 if (pvBuf) 2590 RTMemFree(pvBuf); 2591 if (pvZero) 2592 RTMemFree(pvZero); 2593 } 2503 2594 2504 2595 /* 2505 * Get the blocks we need to relocate first, they are appended to the end2506 * of the image.2596 * We need to update the new offsets for the image data in the out of memory 2597 * case too because we relocated the blocks already. 2507 2598 */ 2508 void *pvBuf = NULL, *pvZero = NULL; 2509 do 2510 { 2511 /* Allocate data buffer. */ 2512 pvBuf = RTMemAllocZ(pImage->cbTotalBlockData); 2513 if (!pvBuf) 2514 { 2515 rc = VERR_NO_MEMORY; 2516 break; 2517 } 2518 2519 /* Allocate buffer for overwriting with zeroes. */ 2520 pvZero = RTMemAllocZ(pImage->cbTotalBlockData); 2521 if (!pvZero) 2522 { 2523 rc = VERR_NO_MEMORY; 2524 break; 2525 } 2526 2527 for (unsigned i = 0; i < cBlocksReloc; i++) 2528 { 2529 /* Search the index in the block table. */ 2530 for (unsigned idxBlock = 0; idxBlock < cBlocksOld; idxBlock++) 2531 { 2532 if (!pImage->paBlocks[idxBlock]) 2533 { 2534 /* Read data and append to the end of the image. */ 2535 rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, 2536 offStartDataNew, pvBuf, 2537 pImage->cbTotalBlockData); 2538 if (RT_FAILURE(rc)) 2539 break; 2540 2541 uint64_t offBlockAppend; 2542 rc = vdIfIoIntFileGetSize(pImage->pIfIo, pImage->pStorage, &offBlockAppend); 2543 if (RT_FAILURE(rc)) 2544 break; 2545 2546 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, 2547 offBlockAppend, pvBuf, 2548 pImage->cbTotalBlockData); 2549 if (RT_FAILURE(rc)) 2550 break; 2551 2552 /* Zero out the old block area. */ 2553 rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, 2554 offStartDataNew, pvZero, 2555 pImage->cbTotalBlockData); 2556 if (RT_FAILURE(rc)) 2557 break; 2558 2559 /* Update block counter. */ 2560 pImage->paBlocks[idxBlock] = cBlocksAllocated - 1; 2561 2562 /* 2563 * Decrease the block number of all other entries in the array. 2564 * They were moved one block to the front. 2565 * Doing it as a separate step iterating over the array again 2566 * because an error while relocating the block might end up 2567 * in a corrupted image otherwise. 2568 */ 2569 for (unsigned idxBlock2 = 0; idxBlock2 < cBlocksOld; idxBlock2++) 2570 { 2571 if ( idxBlock2 != idxBlock 2572 && IS_VDI_IMAGE_BLOCK_ALLOCATED(pImage->paBlocks[idxBlock2])) 2573 pImage->paBlocks[idxBlock2]--; 2574 } 2575 2576 /* Continue with the next block. */ 2577 break; 2578 } 2579 } 2580 2581 if (RT_FAILURE(rc)) 2582 break; 2583 2584 offStartDataNew += pImage->cbTotalBlockData; 2585 } 2586 } while (0); 2587 2588 if (pvBuf) 2589 RTMemFree(pvBuf); 2590 if (pvZero) 2591 RTMemFree(pvZero); 2592 } 2593 2594 /* 2595 * We need to update the new offsets for the image data in the out of memory 2596 * case too because we relocated the blocks already. 2597 */ 2598 pImage->offStartData = offStartDataNew; 2599 setImageDataOffset(&pImage->Header, offStartDataNew); 2599 pImage->offStartData = offStartDataNew; 2600 setImageDataOffset(&pImage->Header, offStartDataNew); 2601 } 2600 2602 2601 2603 /*
Note:
See TracChangeset
for help on using the changeset viewer.