Error getting dynamic VHDX content



I used the following parameters to create a dynamic VHDX and got an error while getting its content stream extents: Unable to complete read of 32776 bytes.
using (var fileStream = File.Create(dynamicVhdxPath))
     var capacity = 1645815529472; // about 1.5 TB
     var blockSize = 1024 * 1024;
     using (var vhdx = DiscUtils.Vhdx.Disk.InitializeDynamic(fileStream, Ownership.None, capacity, blockSize))
         var extents = vhdx.Content.Extents.ToArray();
This is supported in the VHD API; I used the New-VHD cmdlet to create a disk using the same parameters and attached it successfully. If this disk is opened using DiscUtils then the same error occurs.

file attachments


dotnet4fun wrote Oct 8, 2014 at 5:59 AM

I've investigated this in more detail. It happens for block size = 1 MB and capacities starting from 126977 MB. At this capacity the BAT stream length is 1 MB. The next capacity that works is 131042 MB when the BAT stream length changes to 2 MB.

The error occurs when getting BAT data for the last chunk, in Chunk ctor:
_batData = Utilities.ReadFully(bat, (_blocksPerChunk + 1) * 8);
This amount of data is not available on the BAT stream. I suggest the following fix:
_batData = new byte[(_blocksPerChunk + 1) * 8];
Utilities.ReadFully(bat, _batData, 0, _batData.Length);
This works for me. This is how I tested this:
  • create a dynamic VHDX using the VHD API. Block size = 1MB and capacity = 131041 MB.
  • attach it and initialized it to GPT (to make sure data is written at the end of the disk)
  • open it using DiscUtils
  • create a new raw disk
  • clone the VHDX to the raw disk. The raw disk has a GUID partition table.

dotnet4fun wrote Oct 8, 2014 at 11:06 AM

This fix did not work when cloning the disk to another VHDX. It failed on Chunk.AllocateSpaceForBlock because the block offset was beyond the BAT stream capacity. I updated the fix so that Chunk has a number of blocks which is <= chunk ratio; the ContentStream uses this block count when getting the raw stream extents. I am not sure if this matches the VHDX specs, but it does the job for now. Please see attached patch.

dotnet4fun wrote Oct 9, 2014 at 9:45 AM

Previous patch has an issue with the block count per chunk and throws exception when getting HasSectorBitmap and SectorBitmapPos. It did not affect my test, but I think it will have an impact sooner or later. Attached new patch which corrects this problem.