From patchwork Wed Feb 24 16:21:45 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Cody X-Patchwork-Id: 587531 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 1FC8514030C for ; Thu, 25 Feb 2016 03:24:23 +1100 (AEDT) Received: from localhost ([::1]:36766 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aYcEf-0004GO-5G for incoming@patchwork.ozlabs.org; Wed, 24 Feb 2016 11:24:21 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37823) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aYcCQ-0008Vr-Nf for qemu-devel@nongnu.org; Wed, 24 Feb 2016 11:22:08 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aYcCL-0002uB-Mu for qemu-devel@nongnu.org; Wed, 24 Feb 2016 11:22:02 -0500 Received: from mx1.redhat.com ([209.132.183.28]:39568) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aYcCI-0002s4-Ny; Wed, 24 Feb 2016 11:21:54 -0500 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) by mx1.redhat.com (Postfix) with ESMTPS id 64F726314A; Wed, 24 Feb 2016 16:21:54 +0000 (UTC) Received: from localhost (ovpn-112-42.phx2.redhat.com [10.3.112.42]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u1OGLqZi004559 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA256 bits=256 verify=NO); Wed, 24 Feb 2016 11:21:53 -0500 From: Jeff Cody To: qemu-block@nongnu.org Date: Wed, 24 Feb 2016 11:21:45 -0500 Message-Id: In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Wed, 24 Feb 2016 16:21:54 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Cc: kwolf@redhat.com, pl@kamp.de, qemu-devel@nongnu.org Subject: [Qemu-devel] [PATCH v2 3/4] block/vpc: give option to force the current_size field in .bdrv_create X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 When using the "force_size" option, the creator app field used by QEMU will be "qem2" instead of "qemu", to indicate the difference. In light of this, we also add parsing of the "qem2" field during vpc_open. Bug reference: https://bugs.launchpad.net/qemu/+bug/1490611 Signed-off-by: Jeff Cody --- block/vpc.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/block/vpc.c b/block/vpc.c index 54a38a7..8f84b17 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" @@ -288,6 +290,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags, * Known creator apps: * 'vpc ' : CHS Virtual PC (uses disk geometry) * 'qemu' : CHS QEMU (uses disk geometry) + * 'qem2' : current_size QEMU (uses current_size) * 'win ' : current_size Hyper-V * 'd2v ' : current_size Disk2vhd * @@ -296,6 +299,7 @@ static int vpc_open(BlockDriverState *bs, QDict *options, int flags, * that have CHS geometry of the maximum size. */ use_chs = (!!strncmp(footer->creator_app, "win ", 4) && + !!strncmp(footer->creator_app, "qem2", 4) && !!strncmp(footer->creator_app, "d2v ", 4)) || s->force_use_chs; if (!use_chs || bs->total_sectors == VHD_MAX_GEOMETRY || s->force_use_sz) { @@ -850,6 +854,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 +875,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 +903,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) { @@ -912,8 +920,11 @@ static int vpc_create(const char *filename, QemuOpts *opts, Error **errp) memset(buf, 0, 1024); memcpy(footer->creator, "conectix", 8); - /* TODO Check if "qemu" creator_app is ok for VPC */ - memcpy(footer->creator_app, "qemu", 4); + if (force_size) { + memcpy(footer->creator_app, "qem2", 4); + } else { + memcpy(footer->creator_app, "qemu", 4); + } memcpy(footer->creator_os, "Wi2k", 4); footer->features = cpu_to_be32(0x02); @@ -994,6 +1005,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 */ } } };