New patch | |||
---|---|---|---|
1 | Changes since v3: | ||
2 | - Split the change into two patches [Philippe Mathieu-Daude]. | ||
1 | 3 | ||
4 | It was found that 'qemu-nbd' is not able to work with some disk images | ||
5 | exported from Azure as it uses a currently unknown 'wa\0\0' 'creator app' | ||
6 | signature. QEMU currently supports two methods for determining the image | ||
7 | size: CHS and 'current_size' and the list of known 'creator app's is used | ||
8 | to decide between the two. Invert the logic in QEMU and make 'current_size' | ||
9 | the default as it seems that VPC and old QEMU are the only two legacy apps | ||
10 | where preferring CHS makes sense. | ||
11 | |||
12 | Vitaly Kuznetsov (2): | ||
13 | vpc: Split off vpc_ignore_current_size() helper | ||
14 | vpc: Read images exported from Azure correctly | ||
15 | |||
16 | block/vpc.c | 65 ++++++++++++++++++++++++++++------------------------- | ||
17 | 1 file changed, 35 insertions(+), 30 deletions(-) | ||
18 | |||
19 | -- | ||
20 | 2.47.0 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | In preparation to making changes to the logic deciding whether CHS or | ||
2 | 'current_size' need to be used in determining the image size, split off | ||
3 | vpc_ignore_current_size() helper. | ||
1 | 4 | ||
5 | No functional change intended. | ||
6 | |||
7 | Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> | ||
8 | --- | ||
9 | block/vpc.c | 67 +++++++++++++++++++++++++++++------------------------ | ||
10 | 1 file changed, 37 insertions(+), 30 deletions(-) | ||
11 | |||
12 | diff --git a/block/vpc.c b/block/vpc.c | ||
13 | index XXXXXXX..XXXXXXX 100644 | ||
14 | --- a/block/vpc.c | ||
15 | +++ b/block/vpc.c | ||
16 | @@ -XXX,XX +XXX,XX @@ static void vpc_parse_options(BlockDriverState *bs, QemuOpts *opts, | ||
17 | } | ||
18 | } | ||
19 | |||
20 | +/* | ||
21 | + * Microsoft Virtual PC and Microsoft Hyper-V produce and read | ||
22 | + * VHD image sizes differently. VPC will rely on CHS geometry, | ||
23 | + * while Hyper-V and disk2vhd use the size specified in the footer. | ||
24 | + * | ||
25 | + * We use a couple of approaches to try and determine the correct method: | ||
26 | + * look at the Creator App field, and look for images that have CHS | ||
27 | + * geometry that is the maximum value. | ||
28 | + * | ||
29 | + * If the CHS geometry is the maximum CHS geometry, then we assume that | ||
30 | + * the size is the footer->current_size to avoid truncation. Otherwise, | ||
31 | + * we follow the table based on footer->creator_app: | ||
32 | + * | ||
33 | + * Known creator apps: | ||
34 | + * 'vpc ' : CHS Virtual PC (uses disk geometry) | ||
35 | + * 'qemu' : CHS QEMU (uses disk geometry) | ||
36 | + * 'qem2' : current_size QEMU (uses current_size) | ||
37 | + * 'win ' : current_size Hyper-V | ||
38 | + * 'd2v ' : current_size Disk2vhd | ||
39 | + * 'tap\0' : current_size XenServer | ||
40 | + * 'CTXS' : current_size XenConverter | ||
41 | + * | ||
42 | + * The user can override the table values via drive options, however | ||
43 | + * even with an override we will still use current_size for images | ||
44 | + * that have CHS geometry of the maximum size. | ||
45 | + */ | ||
46 | +static bool vpc_ignore_current_size(VHDFooter *footer) | ||
47 | +{ | ||
48 | + return !!strncmp(footer->creator_app, "win ", 4) && | ||
49 | + !!strncmp(footer->creator_app, "qem2", 4) && | ||
50 | + !!strncmp(footer->creator_app, "d2v ", 4) && | ||
51 | + !!strncmp(footer->creator_app, "CTXS", 4) && | ||
52 | + !!memcmp(footer->creator_app, "tap", 4)); | ||
53 | +} | ||
54 | + | ||
55 | static int vpc_open(BlockDriverState *bs, QDict *options, int flags, | ||
56 | Error **errp) | ||
57 | { | ||
58 | @@ -XXX,XX +XXX,XX @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags, | ||
59 | bs->total_sectors = (int64_t) | ||
60 | be16_to_cpu(footer->cyls) * footer->heads * footer->secs_per_cyl; | ||
61 | |||
62 | - /* Microsoft Virtual PC and Microsoft Hyper-V produce and read | ||
63 | - * VHD image sizes differently. VPC will rely on CHS geometry, | ||
64 | - * while Hyper-V and disk2vhd use the size specified in the footer. | ||
65 | - * | ||
66 | - * We use a couple of approaches to try and determine the correct method: | ||
67 | - * look at the Creator App field, and look for images that have CHS | ||
68 | - * geometry that is the maximum value. | ||
69 | - * | ||
70 | - * If the CHS geometry is the maximum CHS geometry, then we assume that | ||
71 | - * the size is the footer->current_size to avoid truncation. Otherwise, | ||
72 | - * we follow the table based on footer->creator_app: | ||
73 | - * | ||
74 | - * Known creator apps: | ||
75 | - * 'vpc ' : CHS Virtual PC (uses disk geometry) | ||
76 | - * 'qemu' : CHS QEMU (uses disk geometry) | ||
77 | - * 'qem2' : current_size QEMU (uses current_size) | ||
78 | - * 'win ' : current_size Hyper-V | ||
79 | - * 'd2v ' : current_size Disk2vhd | ||
80 | - * 'tap\0' : current_size XenServer | ||
81 | - * 'CTXS' : current_size XenConverter | ||
82 | - * | ||
83 | - * The user can override the table values via drive options, however | ||
84 | - * even with an override we will still use current_size for images | ||
85 | - * that have CHS geometry of the maximum size. | ||
86 | - */ | ||
87 | - use_chs = (!!strncmp(footer->creator_app, "win ", 4) && | ||
88 | - !!strncmp(footer->creator_app, "qem2", 4) && | ||
89 | - !!strncmp(footer->creator_app, "d2v ", 4) && | ||
90 | - !!strncmp(footer->creator_app, "CTXS", 4) && | ||
91 | - !!memcmp(footer->creator_app, "tap", 4)) || s->force_use_chs; | ||
92 | + /* Use CHS or current_size to determine the image size. */ | ||
93 | + use_chs = vpc_ignore_current_size(footer) || s->force_use_chs; | ||
94 | |||
95 | if (!use_chs || bs->total_sectors == VHD_MAX_GEOMETRY || s->force_use_sz) { | ||
96 | bs->total_sectors = be64_to_cpu(footer->current_size) / | ||
97 | -- | ||
98 | 2.47.0 | diff view generated by jsdifflib |
... | ... | ||
---|---|---|---|
13 | we can see that Azure uses a different 'Creator application' -- | 13 | we can see that Azure uses a different 'Creator application' -- |
14 | 'wa\0\0' (offset 0x1c, likely reads as 'Windows Azure') and QEMU uses this | 14 | 'wa\0\0' (offset 0x1c, likely reads as 'Windows Azure') and QEMU uses this |
15 | field to determine how it can get image size. Apparently, Azure uses 'new' | 15 | field to determine how it can get image size. Apparently, Azure uses 'new' |
16 | method, just like Hyper-V. | 16 | method, just like Hyper-V. |
17 | 17 | ||
18 | Overall, it seems that only VPC and old QEMUs need to be ignored as all new | ||
19 | creator apps seem to have reliable current_size. Invert the logic and make | ||
20 | 'current_size' method the default to avoid adding every new creator app to | ||
21 | the list. | ||
22 | |||
18 | Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> | 23 | Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> |
19 | --- | 24 | --- |
20 | Alternatively, we can probably make 'current_size' the default and only use | 25 | block/vpc.c | 8 +++----- |
21 | CHS for 'vpc '/'qemu'. | 26 | 1 file changed, 3 insertions(+), 5 deletions(-) |
22 | --- | ||
23 | block/vpc.c | 2 ++ | ||
24 | 1 file changed, 2 insertions(+) | ||
25 | 27 | ||
26 | diff --git a/block/vpc.c b/block/vpc.c | 28 | diff --git a/block/vpc.c b/block/vpc.c |
27 | index XXXXXXX..XXXXXXX 100644 | 29 | index XXXXXXX..XXXXXXX 100644 |
28 | --- a/block/vpc.c | 30 | --- a/block/vpc.c |
29 | +++ b/block/vpc.c | 31 | +++ b/block/vpc.c |
30 | @@ -XXX,XX +XXX,XX @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags, | 32 | @@ -XXX,XX +XXX,XX @@ static void vpc_parse_options(BlockDriverState *bs, QemuOpts *opts, |
31 | * 'qemu' : CHS QEMU (uses disk geometry) | 33 | * 'd2v ' : current_size Disk2vhd |
32 | * 'qem2' : current_size QEMU (uses current_size) | 34 | * 'tap\0' : current_size XenServer |
33 | * 'win ' : current_size Hyper-V | 35 | * 'CTXS' : current_size XenConverter |
34 | + * 'wa\0\0': current_size Azure | 36 | + * 'wa\0\0': current_size Azure |
35 | * 'd2v ' : current_size Disk2vhd | 37 | * |
36 | * 'tap\0' : current_size XenServer | 38 | * The user can override the table values via drive options, however |
37 | * 'CTXS' : current_size XenConverter | 39 | * even with an override we will still use current_size for images |
38 | @@ -XXX,XX +XXX,XX @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags, | 40 | @@ -XXX,XX +XXX,XX @@ static void vpc_parse_options(BlockDriverState *bs, QemuOpts *opts, |
39 | * that have CHS geometry of the maximum size. | 41 | */ |
40 | */ | 42 | static bool vpc_ignore_current_size(VHDFooter *footer) |
41 | use_chs = (!!strncmp(footer->creator_app, "win ", 4) && | 43 | { |
42 | + !!memcmp(footer->creator_app, "wa\0", 4) && | 44 | - return !!strncmp(footer->creator_app, "win ", 4) && |
43 | !!strncmp(footer->creator_app, "qem2", 4) && | 45 | - !!strncmp(footer->creator_app, "qem2", 4) && |
44 | !!strncmp(footer->creator_app, "d2v ", 4) && | 46 | - !!strncmp(footer->creator_app, "d2v ", 4) && |
45 | !!strncmp(footer->creator_app, "CTXS", 4) && | 47 | - !!strncmp(footer->creator_app, "CTXS", 4) && |
48 | - !!memcmp(footer->creator_app, "tap", 4)); | ||
49 | + return !strncmp(footer->creator_app, "vpc ", 4) || | ||
50 | + !strncmp(footer->creator_app, "qemu", 4); | ||
51 | } | ||
52 | |||
53 | static int vpc_open(BlockDriverState *bs, QDict *options, int flags, | ||
46 | -- | 54 | -- |
47 | 2.47.0 | 55 | 2.47.0 | diff view generated by jsdifflib |