diff mbox

[3/4] block/vpc: give option to force the current_size field in .bdrv_create

Message ID 951bf8f8c49ff3c2a38dcd02fe78ae00a5de8add.1456274059.git.jcody@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jeff Cody Feb. 24, 2016, 12:47 a.m. UTC
When QEMU creates a VHD image, it goes by the original spec,
calculating the current_size based on the nearest CHS geometry (with an
exception for disks > 127GB).

Apparently, Azure will only allow images that are sized to the nearest
MB, and the current_size as calculated from CHS cannot guarantee that.

Allow QEMU to create images similar to how Hyper-V creates images, by
setting current_size to the specified virtual disk size.  This
introduces an option, force_size, to be passed to the vpc format during
image creation, e.g.:

    qemu-img convert -f raw -o force_size -O vpc test.img test.vhd

Bug reference: https://bugs.launchpad.net/qemu/+bug/1490611

Signed-off-by: Jeff Cody <jcody@redhat.com>
---
 block/vpc.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

Comments

Kevin Wolf Feb. 24, 2016, 10:19 a.m. UTC | #1
Am 24.02.2016 um 01:47 hat Jeff Cody geschrieben:
> When QEMU creates a VHD image, it goes by the original spec,
> calculating the current_size based on the nearest CHS geometry (with an
> exception for disks > 127GB).
> 
> Apparently, Azure will only allow images that are sized to the nearest
> MB, and the current_size as calculated from CHS cannot guarantee that.
> 
> Allow QEMU to create images similar to how Hyper-V creates images, by
> setting current_size to the specified virtual disk size.  This
> introduces an option, force_size, to be passed to the vpc format during
> image creation, e.g.:
> 
>     qemu-img convert -f raw -o force_size -O vpc test.img test.vhd
> 
> Bug reference: https://bugs.launchpad.net/qemu/+bug/1490611
> 
> Signed-off-by: Jeff Cody <jcody@redhat.com>

We need to set a different creator string here that makes vpc_open()
recognise the image as current_size based.

Kevin
Jeff Cody Feb. 24, 2016, 12:24 p.m. UTC | #2
On Wed, Feb 24, 2016 at 11:19:37AM +0100, Kevin Wolf wrote:
> Am 24.02.2016 um 01:47 hat Jeff Cody geschrieben:
> > When QEMU creates a VHD image, it goes by the original spec,
> > calculating the current_size based on the nearest CHS geometry (with an
> > exception for disks > 127GB).
> > 
> > Apparently, Azure will only allow images that are sized to the nearest
> > MB, and the current_size as calculated from CHS cannot guarantee that.
> > 
> > Allow QEMU to create images similar to how Hyper-V creates images, by
> > setting current_size to the specified virtual disk size.  This
> > introduces an option, force_size, to be passed to the vpc format during
> > image creation, e.g.:
> > 
> >     qemu-img convert -f raw -o force_size -O vpc test.img test.vhd
> > 
> > Bug reference: https://bugs.launchpad.net/qemu/+bug/1490611
> > 
> > Signed-off-by: Jeff Cody <jcody@redhat.com>
> 
> We need to set a different creator string here that makes vpc_open()
> recognise the image as current_size based.
> 
> Kevin

How about "qem2"?  I initially thought about just changing the case on
"qemu", but I was afraid some other software may treat the app creator
string as case-insensitive.

I'll also update patch 1, to recognize that string as well.
Peter Lieven Feb. 24, 2016, 12:44 p.m. UTC | #3
if the size is forced I would set the chs values to max. this way no new creator String is needed and it is even backwards compatible. this is what disk2vhd does.

Peter 


> Am 24.02.2016 um 13:24 schrieb Jeff Cody <jcody@redhat.com>:
> 
>> On Wed, Feb 24, 2016 at 11:19:37AM +0100, Kevin Wolf wrote:
>> Am 24.02.2016 um 01:47 hat Jeff Cody geschrieben:
>>> When QEMU creates a VHD image, it goes by the original spec,
>>> calculating the current_size based on the nearest CHS geometry (with an
>>> exception for disks > 127GB).
>>> 
>>> Apparently, Azure will only allow images that are sized to the nearest
>>> MB, and the current_size as calculated from CHS cannot guarantee that.
>>> 
>>> Allow QEMU to create images similar to how Hyper-V creates images, by
>>> setting current_size to the specified virtual disk size.  This
>>> introduces an option, force_size, to be passed to the vpc format during
>>> image creation, e.g.:
>>> 
>>>    qemu-img convert -f raw -o force_size -O vpc test.img test.vhd
>>> 
>>> Bug reference: https://bugs.launchpad.net/qemu/+bug/1490611
>>> 
>>> Signed-off-by: Jeff Cody <jcody@redhat.com>
>> 
>> We need to set a different creator string here that makes vpc_open()
>> recognise the image as current_size based.
>> 
>> Kevin
> 
> How about "qem2"?  I initially thought about just changing the case on
> "qemu", but I was afraid some other software may treat the app creator
> string as case-insensitive.
> 
> I'll also update patch 1, to recognize that string as well.
Kevin Wolf Feb. 24, 2016, 1:07 p.m. UTC | #4
Am 24.02.2016 um 13:44 hat Peter Lieven geschrieben:
> if the size is forced I would set the chs values to max. this way no
> new creator String is needed and it is even backwards compatible. this
> is what disk2vhd does.

Does disk2vhd do it this way even if the size is smaller than the
maximum that can be represented with CHS?

> > Am 24.02.2016 um 13:24 schrieb Jeff Cody <jcody@redhat.com>:
> > 
> >> On Wed, Feb 24, 2016 at 11:19:37AM +0100, Kevin Wolf wrote:
> >> Am 24.02.2016 um 01:47 hat Jeff Cody geschrieben:
> >>> When QEMU creates a VHD image, it goes by the original spec,
> >>> calculating the current_size based on the nearest CHS geometry (with an
> >>> exception for disks > 127GB).
> >>> 
> >>> Apparently, Azure will only allow images that are sized to the nearest
> >>> MB, and the current_size as calculated from CHS cannot guarantee that.
> >>> 
> >>> Allow QEMU to create images similar to how Hyper-V creates images, by
> >>> setting current_size to the specified virtual disk size.  This
> >>> introduces an option, force_size, to be passed to the vpc format during
> >>> image creation, e.g.:
> >>> 
> >>>    qemu-img convert -f raw -o force_size -O vpc test.img test.vhd
> >>> 
> >>> Bug reference: https://bugs.launchpad.net/qemu/+bug/1490611
> >>> 
> >>> Signed-off-by: Jeff Cody <jcody@redhat.com>
> >> 
> >> We need to set a different creator string here that makes vpc_open()
> >> recognise the image as current_size based.
> >> 
> >> Kevin
> > 
> > How about "qem2"?  I initially thought about just changing the case on
> > "qemu", but I was afraid some other software may treat the app creator
> > string as case-insensitive.
> > 
> > I'll also update patch 1, to recognize that string as well.

I had the same thoughts about our options, and I wasn't fully convinced
of either, so I didn't propose any. I was leaning towards the case
change, though, as I don't think it should make a difference and it
reads nicer. But "qem2" is okay with me, too.

Kevin
Jeff Cody Feb. 24, 2016, 1:40 p.m. UTC | #5
On Wed, Feb 24, 2016 at 02:07:18PM +0100, Kevin Wolf wrote:
> Am 24.02.2016 um 13:44 hat Peter Lieven geschrieben:
> > if the size is forced I would set the chs values to max. this way no
> > new creator String is needed and it is even backwards compatible. this
> > is what disk2vhd does.
> 
> Does disk2vhd do it this way even if the size is smaller than the
> maximum that can be represented with CHS?
>

I don't know about disk2vhd, but I just created a 5G dynamic VHD
image on Hyper-V, and it produced:

cyl: 10402, heads: 16, secs: 63
virtual size: 5.0G (5368709120 bytes)

(the virtual size as calculated by CHS in that case would have been
5368430592 bytes)

I then tested the reverse - I modified qemu to create a VHD image with
5G as the current_size, but maxed out CHS parameters.  I imported it
into Hyper-V, and it worked fine - just recognized as a 5G disk with
5368709120 bytes.

But with all that, it seems like it may be better to mimic the Hyper-V
behavior, and use a new creator app string, with the normal CHS
values.


> > > Am 24.02.2016 um 13:24 schrieb Jeff Cody <jcody@redhat.com>:
> > > 
> > >> On Wed, Feb 24, 2016 at 11:19:37AM +0100, Kevin Wolf wrote:
> > >> Am 24.02.2016 um 01:47 hat Jeff Cody geschrieben:
> > >>> When QEMU creates a VHD image, it goes by the original spec,
> > >>> calculating the current_size based on the nearest CHS geometry (with an
> > >>> exception for disks > 127GB).
> > >>> 
> > >>> Apparently, Azure will only allow images that are sized to the nearest
> > >>> MB, and the current_size as calculated from CHS cannot guarantee that.
> > >>> 
> > >>> Allow QEMU to create images similar to how Hyper-V creates images, by
> > >>> setting current_size to the specified virtual disk size.  This
> > >>> introduces an option, force_size, to be passed to the vpc format during
> > >>> image creation, e.g.:
> > >>> 
> > >>>    qemu-img convert -f raw -o force_size -O vpc test.img test.vhd
> > >>> 
> > >>> Bug reference: https://bugs.launchpad.net/qemu/+bug/1490611
> > >>> 
> > >>> Signed-off-by: Jeff Cody <jcody@redhat.com>
> > >> 
> > >> We need to set a different creator string here that makes vpc_open()
> > >> recognise the image as current_size based.
> > >> 
> > >> Kevin
> > > 
> > > How about "qem2"?  I initially thought about just changing the case on
> > > "qemu", but I was afraid some other software may treat the app creator
> > > string as case-insensitive.
> > > 
> > > I'll also update patch 1, to recognize that string as well.
> 
> I had the same thoughts about our options, and I wasn't fully convinced
> of either, so I didn't propose any. I was leaning towards the case
> change, though, as I don't think it should make a difference and it
> reads nicer. But "qem2" is okay with me, too.
> 
> Kevin
Peter Lieven Feb. 24, 2016, 7:28 p.m. UTC | #6
Am 24.02.2016 um 14:40 schrieb Jeff Cody:
> On Wed, Feb 24, 2016 at 02:07:18PM +0100, Kevin Wolf wrote:
>> Am 24.02.2016 um 13:44 hat Peter Lieven geschrieben:
>>> if the size is forced I would set the chs values to max. this way no
>>> new creator String is needed and it is even backwards compatible. this
>>> is what disk2vhd does.
>> Does disk2vhd do it this way even if the size is smaller than the
>> maximum that can be represented with CHS?
>>
> I don't know about disk2vhd, but I just created a 5G dynamic VHD
> image on Hyper-V, and it produced:
>
> cyl: 10402, heads: 16, secs: 63
> virtual size: 5.0G (5368709120 bytes)
>
> (the virtual size as calculated by CHS in that case would have been
> 5368430592 bytes)
>
> I then tested the reverse - I modified qemu to create a VHD image with
> 5G as the current_size, but maxed out CHS parameters.  I imported it
> into Hyper-V, and it worked fine - just recognized as a 5G disk with
> 5368709120 bytes.

So the idea to set CHS to MAX is not that bad.

>
> But with all that, it seems like it may be better to mimic the Hyper-V
> behavior, and use a new creator app string, with the normal CHS
> values.

But this means that it is not backwards compatible. Maxing out CHS
when forcing the size would mean all old qemu version would look
at current size and not CHS.

Might it be that Hyper-V and others use CHS when an ATA disk is emulated
and the cur_size otherwise? I think this is what virtualbox does.

Peter
Peter Lieven Feb. 24, 2016, 7:29 p.m. UTC | #7
Am 24.02.2016 um 14:07 schrieb Kevin Wolf:
> Am 24.02.2016 um 13:44 hat Peter Lieven geschrieben:
>> if the size is forced I would set the chs values to max. this way no
>> new creator String is needed and it is even backwards compatible. this
>> is what disk2vhd does.
> Does disk2vhd do it this way even if the size is smaller than the
> maximum that can be represented with CHS?

Afaik it always sets it to MAX. This is why we first introduced a check
for the d2v creator in Qemu because all VHD Images created by
disk2vhd where 127GB regardless of their size.

Peter
Jeff Cody Feb. 24, 2016, 9:17 p.m. UTC | #8
On Wed, Feb 24, 2016 at 08:28:20PM +0100, Peter Lieven wrote:
> Am 24.02.2016 um 14:40 schrieb Jeff Cody:
> > On Wed, Feb 24, 2016 at 02:07:18PM +0100, Kevin Wolf wrote:
> >> Am 24.02.2016 um 13:44 hat Peter Lieven geschrieben:
> >>> if the size is forced I would set the chs values to max. this way no
> >>> new creator String is needed and it is even backwards compatible. this
> >>> is what disk2vhd does.
> >> Does disk2vhd do it this way even if the size is smaller than the
> >> maximum that can be represented with CHS?
> >>
> > I don't know about disk2vhd, but I just created a 5G dynamic VHD
> > image on Hyper-V, and it produced:
> >
> > cyl: 10402, heads: 16, secs: 63
> > virtual size: 5.0G (5368709120 bytes)
> >
> > (the virtual size as calculated by CHS in that case would have been
> > 5368430592 bytes)
> >
> > I then tested the reverse - I modified qemu to create a VHD image with
> > 5G as the current_size, but maxed out CHS parameters.  I imported it
> > into Hyper-V, and it worked fine - just recognized as a 5G disk with
> > 5368709120 bytes.
> 
> So the idea to set CHS to MAX is not that bad.
> 

I agree.  I just did a test with disk2vhd, against an empty (but
formatted) 7.5G usb drive.  Here is what it created:

# ./qemu-img info /mnt/nfs-2/tmp/WINtsts2.VHD
cyls: 65535, heads: 16, sectors: 255
image: /mnt/nfs-2/tmp/WINtsts2.VHD
file format: vpc
virtual size: 7.5G (8095006720 bytes)

I really like how one company has 3 different tools that all handle
this differently.

> >
> > But with all that, it seems like it may be better to mimic the Hyper-V
> > behavior, and use a new creator app string, with the normal CHS
> > values.
> 
> But this means that it is not backwards compatible. Maxing out CHS
> when forcing the size would mean all old qemu version would look
> at current size and not CHS.
>

That is a valid concern.  So, how about this:

With 'force_size' during image create, set the CHS parameters to MAX
(as d2v does), but also set the creator app to 'qem2'.  This at least
gives other software a chance to learn that new creator app and handle
it differently, if needed (and it shouldn't hurt anything, and will
still be backwards compatible).


> Might it be that Hyper-V and others use CHS when an ATA disk is emulated
> and the cur_size otherwise? I think this is what virtualbox does.

I tested the Hyper-V created image under a Linux VM in Hyper-V.  The
VM is using IDE controllers, and the image size was the current_size,
not the CHS calculation.

Jeff
diff mbox

Patch

diff --git a/block/vpc.c b/block/vpc.c
index 54a38a7..48ef16e 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -49,6 +49,8 @@  enum vhd_type {
 #define VHD_MAX_SECTORS       (65535LL * 255 * 255)
 #define VHD_MAX_GEOMETRY      (65535LL *  16 * 255)
 
+#define VPC_OPT_FORCE_SIZE "force_size"
+
 // always big-endian
 typedef struct vhd_footer {
     char        creator[8]; // "conectix"
@@ -850,6 +852,7 @@  static int vpc_create(const char *filename, QemuOpts *opts, Error **errp)
     int64_t total_size;
     int disk_type;
     int ret = -EIO;
+    bool force_size;
     Error *local_err = NULL;
     BlockDriverState *bs = NULL;
 
@@ -870,6 +873,8 @@  static int vpc_create(const char *filename, QemuOpts *opts, Error **errp)
         disk_type = VHD_DYNAMIC;
     }
 
+    force_size = qemu_opt_get_bool_del(opts, VPC_OPT_FORCE_SIZE, false);
+
     ret = bdrv_create_file(filename, opts, &local_err);
     if (ret < 0) {
         error_propagate(errp, local_err);
@@ -896,7 +901,8 @@  static int vpc_create(const char *filename, QemuOpts *opts, Error **errp)
         calculate_geometry(total_sectors + i, &cyls, &heads, &secs_per_cyl);
     }
 
-    if ((int64_t)cyls * heads * secs_per_cyl == VHD_MAX_GEOMETRY) {
+    if ((int64_t)cyls * heads * secs_per_cyl == VHD_MAX_GEOMETRY ||
+            force_size) {
         total_sectors = total_size / BDRV_SECTOR_SIZE;
         /* Allow a maximum disk size of approximately 2 TB */
         if (total_sectors > VHD_MAX_SECTORS) {
@@ -994,6 +1000,13 @@  static QemuOptsList vpc_create_opts = {
                 "Type of virtual hard disk format. Supported formats are "
                 "{dynamic (default) | fixed} "
         },
+        {
+            .name = VPC_OPT_FORCE_SIZE,
+            .type = QEMU_OPT_BOOL,
+            .help = "Force disk size calculation to use the actual size "
+                    "specified, rather than using the nearest CHS-based "
+                    "calculation"
+        },
         { /* end of list */ }
     }
 };