mirror of
https://git.proxmox.com/git/qemu
synced 2025-07-27 09:39:52 +00:00
VMDK: bugfix, open Haiku vmdk image
Haiku provides a specially formed vmdk image, which let qemu abort. It a combination of sparse header and flat data (i.e. with not l1/l2 table at all). The fix is turn to descriptor when sparse header is zero in field 'capacity'. Signed-off-by: Fam Zheng <famcool@gmail.com> Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
6c031aac4d
commit
f16f509d17
15
block/vmdk.c
15
block/vmdk.c
@ -408,6 +408,9 @@ static int vmdk_open_vmdk3(BlockDriverState *bs,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int vmdk_open_desc_file(BlockDriverState *bs, int flags,
|
||||||
|
int64_t desc_offset);
|
||||||
|
|
||||||
static int vmdk_open_vmdk4(BlockDriverState *bs,
|
static int vmdk_open_vmdk4(BlockDriverState *bs,
|
||||||
BlockDriverState *file,
|
BlockDriverState *file,
|
||||||
int flags)
|
int flags)
|
||||||
@ -422,6 +425,9 @@ static int vmdk_open_vmdk4(BlockDriverState *bs,
|
|||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
if (header.capacity == 0 && header.desc_offset) {
|
||||||
|
return vmdk_open_desc_file(bs, flags, header.desc_offset << 9);
|
||||||
|
}
|
||||||
l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gte)
|
l1_entry_sectors = le32_to_cpu(header.num_gtes_per_gte)
|
||||||
* le64_to_cpu(header.granularity);
|
* le64_to_cpu(header.granularity);
|
||||||
if (l1_entry_sectors <= 0) {
|
if (l1_entry_sectors <= 0) {
|
||||||
@ -559,7 +565,7 @@ static int vmdk_parse_extents(const char *desc, BlockDriverState *bs,
|
|||||||
|
|
||||||
extent = vmdk_add_extent(bs, extent_file, true, sectors,
|
extent = vmdk_add_extent(bs, extent_file, true, sectors,
|
||||||
0, 0, 0, 0, sectors);
|
0, 0, 0, 0, sectors);
|
||||||
extent->flat_start_offset = flat_offset;
|
extent->flat_start_offset = flat_offset << 9;
|
||||||
} else if (!strcmp(type, "SPARSE")) {
|
} else if (!strcmp(type, "SPARSE")) {
|
||||||
/* SPARSE extent */
|
/* SPARSE extent */
|
||||||
ret = vmdk_open_sparse(bs, extent_file, bs->open_flags);
|
ret = vmdk_open_sparse(bs, extent_file, bs->open_flags);
|
||||||
@ -582,14 +588,15 @@ next_line:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vmdk_open_desc_file(BlockDriverState *bs, int flags)
|
static int vmdk_open_desc_file(BlockDriverState *bs, int flags,
|
||||||
|
int64_t desc_offset)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
char buf[2048];
|
char buf[2048];
|
||||||
char ct[128];
|
char ct[128];
|
||||||
BDRVVmdkState *s = bs->opaque;
|
BDRVVmdkState *s = bs->opaque;
|
||||||
|
|
||||||
ret = bdrv_pread(bs->file, 0, buf, sizeof(buf));
|
ret = bdrv_pread(bs->file, desc_offset, buf, sizeof(buf));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -635,7 +642,7 @@ static int vmdk_open(BlockDriverState *bs, int flags)
|
|||||||
s->parent_cid = vmdk_read_cid(bs, 1);
|
s->parent_cid = vmdk_read_cid(bs, 1);
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return vmdk_open_desc_file(bs, flags);
|
return vmdk_open_desc_file(bs, flags, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user