VirtualBox

Changeset 64504 in vbox for trunk/src/VBox/Storage


Ignore:
Timestamp:
Nov 1, 2016 9:56:56 AM (9 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
111642
Message:

VDI: Only change the offset of the data blocks if the current start would overlap with the new block table

File:
1 edited

Legend:

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

    r64272 r64504  
    24852485        uint64_t offStartDataNew = RT_ALIGN_32(pImage->offStartBlocks + cbBlockspaceNew, VDI_DATA_ALIGN); /** < New start offset for block data after the resize */
    24862486
    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            }
    25032594
    25042595            /*
    2505              * Get the blocks we need to relocate first, they are appended to the end
    2506              * 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.
    25072598             */
    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        }
    26002602
    26012603        /*
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