block: vhdx - force FileOffsetMB field to '0' for certain block states

The v1.0.0 spec calls out PAYLOAD_BLOCK_ZERO FileOffsetMB field as being
'reserved'.  In practice, this means that Hyper-V will fail to read a
disk image with PAYLOAD_BLOCK_ZERO block states with a FileOffsetMB
value other than 0.

The other states that indicate a block that is not there
(PAYLOAD_BLOCK_UNDEFINED, PAYLOAD_BLOCK_NOT_PRESENT,
 PAYLOAD_BLOCK_UNMAPPED) have multiple options for what FileOffsetMB may
be set to, and '0' is explicitly called out as an option.

For all the above states, we will also just set the FileOffsetMB value
to 0.

Signed-off-by: Jeff Cody <jcody@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
Message-id: a9fe92f53f07e6ab1693811e4312c0d1e958500b.1421787566.git.jcody@redhat.com
Signed-off-by: Max Reitz <mreitz@redhat.com>
This commit is contained in:
Jeff Cody 2015-01-20 16:01:43 -05:00 committed by Max Reitz
parent 9a29e18f7d
commit cdf9634bdf

View file

@ -1174,7 +1174,18 @@ static void vhdx_update_bat_table_entry(BlockDriverState *bs, BDRVVHDXState *s,
{
/* The BAT entry is a uint64, with 44 bits for the file offset in units of
* 1MB, and 3 bits for the block state. */
s->bat[sinfo->bat_idx] = sinfo->file_offset;
if ((state == PAYLOAD_BLOCK_ZERO) ||
(state == PAYLOAD_BLOCK_UNDEFINED) ||
(state == PAYLOAD_BLOCK_NOT_PRESENT) ||
(state == PAYLOAD_BLOCK_UNMAPPED)) {
s->bat[sinfo->bat_idx] = 0; /* For PAYLOAD_BLOCK_ZERO, the
FileOffsetMB field is denoted as
'reserved' in the v1.0 spec. If it is
non-zero, MS Hyper-V will fail to read
the disk image */
} else {
s->bat[sinfo->bat_idx] = sinfo->file_offset;
}
s->bat[sinfo->bat_idx] |= state & VHDX_BAT_STATE_BIT_MASK;