... | ... | ||
---|---|---|---|
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 | Changes since v1/v2: invert the logic and make 'vpc' and 'qemu' use CHS |
21 | CHS for 'vpc '/'qemu'. | 26 | while defaulting to current_size. |
22 | --- | 27 | --- |
23 | block/vpc.c | 2 ++ | 28 | block/vpc.c | 65 ++++++++++++++++++++++++++++------------------------- |
24 | 1 file changed, 2 insertions(+) | 29 | 1 file changed, 35 insertions(+), 30 deletions(-) |
25 | 30 | ||
26 | diff --git a/block/vpc.c b/block/vpc.c | 31 | diff --git a/block/vpc.c b/block/vpc.c |
27 | index XXXXXXX..XXXXXXX 100644 | 32 | index XXXXXXX..XXXXXXX 100644 |
28 | --- a/block/vpc.c | 33 | --- a/block/vpc.c |
29 | +++ b/block/vpc.c | 34 | +++ b/block/vpc.c |
35 | @@ -XXX,XX +XXX,XX @@ static void vpc_parse_options(BlockDriverState *bs, QemuOpts *opts, | ||
36 | } | ||
37 | } | ||
38 | |||
39 | +/* | ||
40 | + * Microsoft Virtual PC and Microsoft Hyper-V produce and read | ||
41 | + * VHD image sizes differently. VPC will rely on CHS geometry, | ||
42 | + * while Hyper-V and disk2vhd use the size specified in the footer. | ||
43 | + * | ||
44 | + * We use a couple of approaches to try and determine the correct method: | ||
45 | + * look at the Creator App field, and look for images that have CHS | ||
46 | + * geometry that is the maximum value. | ||
47 | + * | ||
48 | + * If the CHS geometry is the maximum CHS geometry, then we assume that | ||
49 | + * the size is the footer->current_size to avoid truncation. Otherwise, | ||
50 | + * we follow the table based on footer->creator_app: | ||
51 | + * | ||
52 | + * Currently known creator apps: | ||
53 | + * 'vpc ' : CHS Virtual PC (uses disk geometry) | ||
54 | + * 'qemu' : CHS QEMU (uses disk geometry) | ||
55 | + * 'qem2' : current_size QEMU (uses current_size) | ||
56 | + * 'win ' : current_size Hyper-V | ||
57 | + * 'd2v ' : current_size Disk2vhd | ||
58 | + * 'tap\0' : current_size XenServer | ||
59 | + * 'CTXS' : current_size XenConverter | ||
60 | + * 'wa\0\0': current_size Azure | ||
61 | + * | ||
62 | + * The user can override the table values via drive options, however | ||
63 | + * even with an override we will still use current_size for images | ||
64 | + * that have CHS geometry of the maximum size. | ||
65 | + */ | ||
66 | +static bool vpc_ignore_current_size(VHDFooter *footer) | ||
67 | +{ | ||
68 | + return !strncmp(footer->creator_app, "vpc ", 4) || | ||
69 | + !strncmp(footer->creator_app, "qemu", 4); | ||
70 | +} | ||
71 | + | ||
72 | static int vpc_open(BlockDriverState *bs, QDict *options, int flags, | ||
73 | Error **errp) | ||
74 | { | ||
30 | @@ -XXX,XX +XXX,XX @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags, | 75 | @@ -XXX,XX +XXX,XX @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags, |
31 | * 'qemu' : CHS QEMU (uses disk geometry) | 76 | bs->total_sectors = (int64_t) |
32 | * 'qem2' : current_size QEMU (uses current_size) | 77 | be16_to_cpu(footer->cyls) * footer->heads * footer->secs_per_cyl; |
33 | * 'win ' : current_size Hyper-V | 78 | |
34 | + * 'wa\0\0': current_size Azure | 79 | - /* Microsoft Virtual PC and Microsoft Hyper-V produce and read |
35 | * 'd2v ' : current_size Disk2vhd | 80 | - * VHD image sizes differently. VPC will rely on CHS geometry, |
36 | * 'tap\0' : current_size XenServer | 81 | - * while Hyper-V and disk2vhd use the size specified in the footer. |
37 | * 'CTXS' : current_size XenConverter | 82 | - * |
38 | @@ -XXX,XX +XXX,XX @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags, | 83 | - * We use a couple of approaches to try and determine the correct method: |
39 | * that have CHS geometry of the maximum size. | 84 | - * look at the Creator App field, and look for images that have CHS |
40 | */ | 85 | - * geometry that is the maximum value. |
41 | use_chs = (!!strncmp(footer->creator_app, "win ", 4) && | 86 | - * |
42 | + !!memcmp(footer->creator_app, "wa\0", 4) && | 87 | - * If the CHS geometry is the maximum CHS geometry, then we assume that |
43 | !!strncmp(footer->creator_app, "qem2", 4) && | 88 | - * the size is the footer->current_size to avoid truncation. Otherwise, |
44 | !!strncmp(footer->creator_app, "d2v ", 4) && | 89 | - * we follow the table based on footer->creator_app: |
45 | !!strncmp(footer->creator_app, "CTXS", 4) && | 90 | - * |
91 | - * Known creator apps: | ||
92 | - * 'vpc ' : CHS Virtual PC (uses disk geometry) | ||
93 | - * 'qemu' : CHS QEMU (uses disk geometry) | ||
94 | - * 'qem2' : current_size QEMU (uses current_size) | ||
95 | - * 'win ' : current_size Hyper-V | ||
96 | - * 'd2v ' : current_size Disk2vhd | ||
97 | - * 'tap\0' : current_size XenServer | ||
98 | - * 'CTXS' : current_size XenConverter | ||
99 | - * | ||
100 | - * The user can override the table values via drive options, however | ||
101 | - * even with an override we will still use current_size for images | ||
102 | - * that have CHS geometry of the maximum size. | ||
103 | - */ | ||
104 | - use_chs = (!!strncmp(footer->creator_app, "win ", 4) && | ||
105 | - !!strncmp(footer->creator_app, "qem2", 4) && | ||
106 | - !!strncmp(footer->creator_app, "d2v ", 4) && | ||
107 | - !!strncmp(footer->creator_app, "CTXS", 4) && | ||
108 | - !!memcmp(footer->creator_app, "tap", 4)) || s->force_use_chs; | ||
109 | + /* Use CHS or current_size to determine the image size */ | ||
110 | + use_chs = vpc_ignore_current_size(footer) || s->force_use_chs; | ||
111 | |||
112 | if (!use_chs || bs->total_sectors == VHD_MAX_GEOMETRY || s->force_use_sz) { | ||
113 | bs->total_sectors = be64_to_cpu(footer->current_size) / | ||
46 | -- | 114 | -- |
47 | 2.47.0 | 115 | 2.47.0 | diff view generated by jsdifflib |