From nobody Mon Apr 29 12:08:20 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 149925955941528.5888353375816; Wed, 5 Jul 2017 05:59:19 -0700 (PDT) Received: from localhost ([::1]:46091 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dSjtj-0006Iv-ST for importer@patchew.org; Wed, 05 Jul 2017 08:59:15 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59115) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dSjsL-000573-9s for qemu-devel@nongnu.org; Wed, 05 Jul 2017 08:57:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dSjsJ-0003Aj-2r for qemu-devel@nongnu.org; Wed, 05 Jul 2017 08:57:49 -0400 Received: from mx1.redhat.com ([209.132.183.28]:56844) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dSjsI-0003AV-Q6 for qemu-devel@nongnu.org; Wed, 05 Jul 2017 08:57:47 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id AFA6C334586; Wed, 5 Jul 2017 12:57:45 +0000 (UTC) Received: from localhost (ovpn-117-111.ams2.redhat.com [10.36.117.111]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3B3326C20B; Wed, 5 Jul 2017 12:57:45 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com AFA6C334586 Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=stefanha@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com AFA6C334586 From: Stefan Hajnoczi To: qemu-devel@nongnu.org Date: Wed, 5 Jul 2017 13:57:30 +0100 Message-Id: <20170705125738.8777-2-stefanha@redhat.com> In-Reply-To: <20170705125738.8777-1-stefanha@redhat.com> References: <20170705125738.8777-1-stefanha@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Wed, 05 Jul 2017 12:57:45 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v9 1/9] block: add bdrv_measure() API X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Alberto Garcia , Max Reitz , Nir Soffer , Maor Lipchuk , Stefan Hajnoczi , John Snow Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" bdrv_measure() provides a conservative maximum for the size of a new image. This information is handy if storage needs to be allocated (e.g. a SAN or an LVM volume) ahead of time. Signed-off-by: Stefan Hajnoczi Reviewed-by: Alberto Garcia --- v9: * Clarify that backing file clusters also available in the new image file *may* be ommitted from the calculation [Max] v6: * Change bdrv_measure() return type to BlockMeasureInfo * [Eric] * Clarify that holes in sparse POSIX files are still counted [Eric] --- qapi/block-core.json | 25 +++++++++++++++++++++++++ include/block/block.h | 2 ++ include/block/block_int.h | 2 ++ block.c | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 64 insertions(+) diff --git a/qapi/block-core.json b/qapi/block-core.json index f85c223..7973f24 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -464,6 +464,31 @@ '*dirty-bitmaps': ['BlockDirtyInfo'] } } =20 ## +# @BlockMeasureInfo: +# +# Image file size calculation information. This structure describes the s= ize +# requirements for creating a new image file. +# +# The size requirements depend on the new image file format. File size al= ways +# equals virtual disk size for the 'raw' format, even for sparse POSIX fil= es. +# Compact formats such as 'qcow2' represent unallocated and zero regions +# efficiently so file size may be smaller than virtual disk size. +# +# The values are upper bounds that are guaranteed to fit the new image fil= e. +# Subsequent modification, such as internal snapshot or bitmap creation, m= ay +# require additional space and is not covered here. +# +# @required: Size required for a new image file, in bytes. +# +# @fully-allocated: Image file size, in bytes, once data has been written +# to all sectors. +# +# Since: 2.10 +## +{ 'struct': 'BlockMeasureInfo', + 'data': {'required': 'int', 'fully-allocated': 'int'} } + +## # @query-block: # # Get a list of BlockInfo for all virtual block devices. diff --git a/include/block/block.h b/include/block/block.h index 4c149ad..a1e1a19 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -306,6 +306,8 @@ int bdrv_truncate(BdrvChild *child, int64_t offset, Err= or **errp); int64_t bdrv_nb_sectors(BlockDriverState *bs); int64_t bdrv_getlength(BlockDriverState *bs); int64_t bdrv_get_allocated_file_size(BlockDriverState *bs); +BlockMeasureInfo *bdrv_measure(BlockDriver *drv, QemuOpts *opts, + BlockDriverState *in_bs, Error **errp); void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr); void bdrv_refresh_limits(BlockDriverState *bs, Error **errp); int bdrv_commit(BlockDriverState *bs); diff --git a/include/block/block_int.h b/include/block/block_int.h index 15fa602..94b3721 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -209,6 +209,8 @@ struct BlockDriver { int64_t (*bdrv_getlength)(BlockDriverState *bs); bool has_variable_length; int64_t (*bdrv_get_allocated_file_size)(BlockDriverState *bs); + BlockMeasureInfo *(*bdrv_measure)(QemuOpts *opts, BlockDriverState *in= _bs, + Error **errp); =20 int coroutine_fn (*bdrv_co_pwritev_compressed)(BlockDriverState *bs, uint64_t offset, uint64_t bytes, QEMUIOVector *qiov); diff --git a/block.c b/block.c index 6943962..aef51f0 100644 --- a/block.c +++ b/block.c @@ -3450,6 +3450,41 @@ int64_t bdrv_get_allocated_file_size(BlockDriverStat= e *bs) return -ENOTSUP; } =20 +/* + * bdrv_measure: + * @drv: Format driver + * @opts: Creation options for new image + * @in_bs: Existing image containing data for new image (may be NULL) + * @errp: Error object + * Returns: A #BlockMeasureInfo (free using qapi_free_BlockMeasureInfo()) + * or NULL on error + * + * Calculate file size required to create a new image. + * + * If @in_bs is given then space for allocated clusters and zero clusters + * from that image are included in the calculation. If @opts contains a + * backing file that is shared by @in_bs then backing clusters may be omit= ted + * from the calculation. + * + * If @in_bs is NULL then the calculation includes no allocated clusters + * unless a preallocation option is given in @opts. + * + * Note that @in_bs may use a different BlockDriver from @drv. + * + * If an error occurs the @errp pointer is set. + */ +BlockMeasureInfo *bdrv_measure(BlockDriver *drv, QemuOpts *opts, + BlockDriverState *in_bs, Error **errp) +{ + if (!drv->bdrv_measure) { + error_setg(errp, "Block driver '%s' does not support size measurem= ent", + drv->format_name); + return NULL; + } + + return drv->bdrv_measure(opts, in_bs, errp); +} + /** * Return number of sectors on success, -errno on error. */ --=20 2.9.4 From nobody Mon Apr 29 12:08:20 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 149925971089654.53494042114107; Wed, 5 Jul 2017 06:01:50 -0700 (PDT) Received: from localhost ([::1]:46107 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dSjwC-0000Hd-11 for importer@patchew.org; Wed, 05 Jul 2017 09:01:48 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59141) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dSjsY-0005Fe-0S for qemu-devel@nongnu.org; Wed, 05 Jul 2017 08:58:02 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dSjsU-0003Cj-5a for qemu-devel@nongnu.org; Wed, 05 Jul 2017 08:58:02 -0400 Received: from mx1.redhat.com ([209.132.183.28]:63622) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dSjsT-0003Cd-VN for qemu-devel@nongnu.org; Wed, 05 Jul 2017 08:57:58 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D378DC058EA7; Wed, 5 Jul 2017 12:57:56 +0000 (UTC) Received: from localhost (ovpn-117-111.ams2.redhat.com [10.36.117.111]) by smtp.corp.redhat.com (Postfix) with ESMTP id 15E7A7E2D6; Wed, 5 Jul 2017 12:57:46 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com D378DC058EA7 Authentication-Results: ext-mx08.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx08.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=stefanha@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com D378DC058EA7 From: Stefan Hajnoczi To: qemu-devel@nongnu.org Date: Wed, 5 Jul 2017 13:57:31 +0100 Message-Id: <20170705125738.8777-3-stefanha@redhat.com> In-Reply-To: <20170705125738.8777-1-stefanha@redhat.com> References: <20170705125738.8777-1-stefanha@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Wed, 05 Jul 2017 12:57:57 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v9 2/9] raw-format: add bdrv_measure() support X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Alberto Garcia , Max Reitz , Nir Soffer , Maor Lipchuk , Stefan Hajnoczi , John Snow Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Maximum size calculation is trivial for the raw format: it's just the requested image size (because there is no metadata). Signed-off-by: Stefan Hajnoczi Reviewed-by: Alberto Garcia --- block/raw-format.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/block/raw-format.c b/block/raw-format.c index 0d185fe..71412a7 100644 --- a/block/raw-format.c +++ b/block/raw-format.c @@ -312,6 +312,31 @@ static int64_t raw_getlength(BlockDriverState *bs) return s->size; } =20 +static BlockMeasureInfo *raw_measure(QemuOpts *opts, BlockDriverState *in_= bs, + Error **errp) +{ + BlockMeasureInfo *info; + int64_t required; + + if (in_bs) { + required =3D bdrv_getlength(in_bs); + if (required < 0) { + error_setg_errno(errp, -required, "Unable to get image size"); + return NULL; + } + } else { + required =3D ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, = 0), + BDRV_SECTOR_SIZE); + } + + info =3D g_new(BlockMeasureInfo, 1); + info->required =3D required; + + /* Unallocated sectors count towards the file size in raw images */ + info->fully_allocated =3D info->required; + return info; +} + static int raw_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) { return bdrv_get_info(bs->file->bs, bdi); @@ -479,6 +504,7 @@ BlockDriver bdrv_raw =3D { .bdrv_truncate =3D &raw_truncate, .bdrv_getlength =3D &raw_getlength, .has_variable_length =3D true, + .bdrv_measure =3D &raw_measure, .bdrv_get_info =3D &raw_get_info, .bdrv_refresh_limits =3D &raw_refresh_limits, .bdrv_probe_blocksizes =3D &raw_probe_blocksizes, --=20 2.9.4 From nobody Mon Apr 29 12:08:20 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1499259712847618.242497411694; Wed, 5 Jul 2017 06:01:52 -0700 (PDT) Received: from localhost ([::1]:46108 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dSjwD-0000Hw-3z for importer@patchew.org; Wed, 05 Jul 2017 09:01:49 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59152) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dSjsb-0005ID-GT for qemu-devel@nongnu.org; Wed, 05 Jul 2017 08:58:11 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dSjsa-0003F7-9u for qemu-devel@nongnu.org; Wed, 05 Jul 2017 08:58:05 -0400 Received: from mx1.redhat.com ([209.132.183.28]:53910) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dSjsa-0003Ep-0L for qemu-devel@nongnu.org; Wed, 05 Jul 2017 08:58:04 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E43FFC058EB2; Wed, 5 Jul 2017 12:58:02 +0000 (UTC) Received: from localhost (ovpn-117-111.ams2.redhat.com [10.36.117.111]) by smtp.corp.redhat.com (Postfix) with ESMTP id 566666FB9D; Wed, 5 Jul 2017 12:57:58 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com E43FFC058EB2 Authentication-Results: ext-mx08.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx08.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=stefanha@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com E43FFC058EB2 From: Stefan Hajnoczi To: qemu-devel@nongnu.org Date: Wed, 5 Jul 2017 13:57:32 +0100 Message-Id: <20170705125738.8777-4-stefanha@redhat.com> In-Reply-To: <20170705125738.8777-1-stefanha@redhat.com> References: <20170705125738.8777-1-stefanha@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Wed, 05 Jul 2017 12:58:03 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v9 3/9] qcow2: extract preallocation calculation function X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Alberto Garcia , Max Reitz , Nir Soffer , Maor Lipchuk , Stefan Hajnoczi , John Snow Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Calculating the preallocated image size will be needed to implement .bdrv_measure(). Extract the code out into a separate function. Signed-off-by: Stefan Hajnoczi Reviewed-by: Alberto Garcia --- block/qcow2.c | 136 +++++++++++++++++++++++++++++++++---------------------= ---- 1 file changed, 77 insertions(+), 59 deletions(-) diff --git a/block/qcow2.c b/block/qcow2.c index 2f94f03..058cc56 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -2140,6 +2140,80 @@ static int preallocate(BlockDriverState *bs) return 0; } =20 +/** + * qcow2_calc_prealloc_size: + * @total_size: virtual disk size in bytes + * @cluster_size: cluster size in bytes + * @refcount_order: refcount bits power-of-2 exponent + * + * Returns: Total number of bytes required for the fully allocated image + * (including metadata). + */ +static int64_t qcow2_calc_prealloc_size(int64_t total_size, + size_t cluster_size, + int refcount_order) +{ + /* Note: The following calculation does not need to be exact; if it is= a + * bit off, either some bytes will be "leaked" (which is fine) or we + * will need to increase the file size by some bytes (which is fine, + * too, as long as the bulk is allocated here). Therefore, using + * floating point arithmetic is fine. */ + int64_t meta_size =3D 0; + uint64_t nreftablee, nrefblocke, nl1e, nl2e, refblock_count; + int64_t aligned_total_size =3D align_offset(total_size, cluster_size); + int cluster_bits =3D ctz32(cluster_size); + int refblock_bits, refblock_size; + /* refcount entry size in bytes */ + double rces =3D (1 << refcount_order) / 8.; + + /* see qcow2_open() */ + refblock_bits =3D cluster_bits - (refcount_order - 3); + refblock_size =3D 1 << refblock_bits; + + /* header: 1 cluster */ + meta_size +=3D cluster_size; + + /* total size of L2 tables */ + nl2e =3D aligned_total_size / cluster_size; + nl2e =3D align_offset(nl2e, cluster_size / sizeof(uint64_t)); + meta_size +=3D nl2e * sizeof(uint64_t); + + /* total size of L1 tables */ + nl1e =3D nl2e * sizeof(uint64_t) / cluster_size; + nl1e =3D align_offset(nl1e, cluster_size / sizeof(uint64_t)); + meta_size +=3D nl1e * sizeof(uint64_t); + + /* total size of refcount blocks + * + * note: every host cluster is reference-counted, including metadata + * (even refcount blocks are recursively included). + * Let: + * a =3D total_size (this is the guest disk size) + * m =3D meta size not including refcount blocks and refcount tables + * c =3D cluster size + * y1 =3D number of refcount blocks entries + * y2 =3D meta size including everything + * rces =3D refcount entry size in bytes + * then, + * y1 =3D (y2 + a)/c + * y2 =3D y1 * rces + y1 * rces * sizeof(u64) / c + m + * we can get y1: + * y1 =3D (a + m) / (c - rces - rces * sizeof(u64) / c) + */ + nrefblocke =3D (aligned_total_size + meta_size + cluster_size) + / (cluster_size - rces - rces * sizeof(uint64_t) + / cluster_size); + refblock_count =3D DIV_ROUND_UP(nrefblocke, refblock_size); + meta_size +=3D refblock_count * cluster_size; + + /* total size of refcount tables */ + nreftablee =3D align_offset(refblock_count, + cluster_size / sizeof(uint64_t)); + meta_size +=3D nreftablee * sizeof(uint64_t); + + return meta_size + aligned_total_size; +} + static int qcow2_create2(const char *filename, int64_t total_size, const char *backing_file, const char *backing_for= mat, int flags, size_t cluster_size, PreallocMode prea= lloc, @@ -2178,65 +2252,9 @@ static int qcow2_create2(const char *filename, int64= _t total_size, int ret; =20 if (prealloc =3D=3D PREALLOC_MODE_FULL || prealloc =3D=3D PREALLOC_MOD= E_FALLOC) { - /* Note: The following calculation does not need to be exact; if i= t is a - * bit off, either some bytes will be "leaked" (which is fine) or = we - * will need to increase the file size by some bytes (which is fin= e, - * too, as long as the bulk is allocated here). Therefore, using - * floating point arithmetic is fine. */ - int64_t meta_size =3D 0; - uint64_t nreftablee, nrefblocke, nl1e, nl2e, refblock_count; - int64_t aligned_total_size =3D align_offset(total_size, cluster_si= ze); - int refblock_bits, refblock_size; - /* refcount entry size in bytes */ - double rces =3D (1 << refcount_order) / 8.; - - /* see qcow2_open() */ - refblock_bits =3D cluster_bits - (refcount_order - 3); - refblock_size =3D 1 << refblock_bits; - - /* header: 1 cluster */ - meta_size +=3D cluster_size; - - /* total size of L2 tables */ - nl2e =3D aligned_total_size / cluster_size; - nl2e =3D align_offset(nl2e, cluster_size / sizeof(uint64_t)); - meta_size +=3D nl2e * sizeof(uint64_t); - - /* total size of L1 tables */ - nl1e =3D nl2e * sizeof(uint64_t) / cluster_size; - nl1e =3D align_offset(nl1e, cluster_size / sizeof(uint64_t)); - meta_size +=3D nl1e * sizeof(uint64_t); - - /* total size of refcount blocks - * - * note: every host cluster is reference-counted, including metada= ta - * (even refcount blocks are recursively included). - * Let: - * a =3D total_size (this is the guest disk size) - * m =3D meta size not including refcount blocks and refcount ta= bles - * c =3D cluster size - * y1 =3D number of refcount blocks entries - * y2 =3D meta size including everything - * rces =3D refcount entry size in bytes - * then, - * y1 =3D (y2 + a)/c - * y2 =3D y1 * rces + y1 * rces * sizeof(u64) / c + m - * we can get y1: - * y1 =3D (a + m) / (c - rces - rces * sizeof(u64) / c) - */ - nrefblocke =3D (aligned_total_size + meta_size + cluster_size) - / (cluster_size - rces - rces * sizeof(uint64_t) - / cluster_size); - refblock_count =3D DIV_ROUND_UP(nrefblocke, refblock_size); - meta_size +=3D refblock_count * cluster_size; - - /* total size of refcount tables */ - nreftablee =3D align_offset(refblock_count, - cluster_size / sizeof(uint64_t)); - meta_size +=3D nreftablee * sizeof(uint64_t); - - qemu_opt_set_number(opts, BLOCK_OPT_SIZE, - aligned_total_size + meta_size, &error_abort); + int64_t prealloc_size =3D + qcow2_calc_prealloc_size(total_size, cluster_size, refcount_or= der); + qemu_opt_set_number(opts, BLOCK_OPT_SIZE, prealloc_size, &error_ab= ort); qemu_opt_set(opts, BLOCK_OPT_PREALLOC, PreallocMode_lookup[preallo= c], &error_abort); } --=20 2.9.4 From nobody Mon Apr 29 12:08:20 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1499259598310501.11942942693827; Wed, 5 Jul 2017 05:59:58 -0700 (PDT) Received: from localhost ([::1]:46093 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dSjuO-00077F-2h for importer@patchew.org; Wed, 05 Jul 2017 08:59:56 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59186) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dSjsk-0005OO-QK for qemu-devel@nongnu.org; Wed, 05 Jul 2017 08:58:16 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dSjsg-0003H3-Ka for qemu-devel@nongnu.org; Wed, 05 Jul 2017 08:58:14 -0400 Received: from mx1.redhat.com ([209.132.183.28]:28800) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dSjsg-0003Gg-BK for qemu-devel@nongnu.org; Wed, 05 Jul 2017 08:58:10 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 3FDA6C04B924; Wed, 5 Jul 2017 12:58:09 +0000 (UTC) Received: from localhost (ovpn-117-111.ams2.redhat.com [10.36.117.111]) by smtp.corp.redhat.com (Postfix) with ESMTP id 78E861712E; Wed, 5 Jul 2017 12:58:04 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 3FDA6C04B924 Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=stefanha@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 3FDA6C04B924 From: Stefan Hajnoczi To: qemu-devel@nongnu.org Date: Wed, 5 Jul 2017 13:57:33 +0100 Message-Id: <20170705125738.8777-5-stefanha@redhat.com> In-Reply-To: <20170705125738.8777-1-stefanha@redhat.com> References: <20170705125738.8777-1-stefanha@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Wed, 05 Jul 2017 12:58:09 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v9 4/9] qcow2: make refcount size calculation conservative X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Alberto Garcia , Max Reitz , Nir Soffer , Maor Lipchuk , Stefan Hajnoczi , John Snow Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The refcount metadata size calculation is inaccurate and can produce numbers that are too small. This is bad because we should calculate a conservative number - one that is guaranteed to be large enough. This patch switches the approach to a fixed point calculation because the existing equation is hard to solve when inaccuracies are taken care of. Signed-off-by: Stefan Hajnoczi Reviewed-by: Alberto Garcia --- block/qcow2.c | 83 ++++++++++++++++++++++++++++++-------------------------= ---- 1 file changed, 42 insertions(+), 41 deletions(-) diff --git a/block/qcow2.c b/block/qcow2.c index 058cc56..538f867 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -2140,6 +2140,43 @@ static int preallocate(BlockDriverState *bs) return 0; } =20 +/* qcow2_refcount_metadata_size: + * @clusters: number of clusters to refcount (including data and L1/L2 tab= les) + * @cluster_size: size of a cluster, in bytes + * @refcount_order: refcount bits power-of-2 exponent + * + * Returns: Number of bytes required for refcount blocks and table metadat= a. + */ +static int64_t qcow2_refcount_metadata_size(int64_t clusters, + size_t cluster_size, + int refcount_order) +{ + /* + * Every host cluster is reference-counted, including metadata (even + * refcount metadata is recursively included). + * + * An accurate formula for the size of refcount metadata size is diffi= cult + * to derive. An easier method of calculation is finding the fixed po= int + * where no further refcount blocks or table clusters are required to + * reference count every cluster. + */ + int64_t blocks_per_table_cluster =3D cluster_size / sizeof(uint64_t); + int64_t refcounts_per_block =3D cluster_size * 8 / (1 << refcount_orde= r); + int64_t table =3D 0; /* number of refcount table clusters */ + int64_t blocks =3D 0; /* number of refcount block clusters */ + int64_t last; + int64_t n =3D 0; + + do { + last =3D n; + blocks =3D DIV_ROUND_UP(clusters + table + blocks, refcounts_per_b= lock); + table =3D DIV_ROUND_UP(blocks, blocks_per_table_cluster); + n =3D clusters + blocks + table; + } while (n !=3D last); + + return (blocks + table) * cluster_size; +} + /** * qcow2_calc_prealloc_size: * @total_size: virtual disk size in bytes @@ -2153,22 +2190,9 @@ static int64_t qcow2_calc_prealloc_size(int64_t tota= l_size, size_t cluster_size, int refcount_order) { - /* Note: The following calculation does not need to be exact; if it is= a - * bit off, either some bytes will be "leaked" (which is fine) or we - * will need to increase the file size by some bytes (which is fine, - * too, as long as the bulk is allocated here). Therefore, using - * floating point arithmetic is fine. */ int64_t meta_size =3D 0; - uint64_t nreftablee, nrefblocke, nl1e, nl2e, refblock_count; + uint64_t nl1e, nl2e; int64_t aligned_total_size =3D align_offset(total_size, cluster_size); - int cluster_bits =3D ctz32(cluster_size); - int refblock_bits, refblock_size; - /* refcount entry size in bytes */ - double rces =3D (1 << refcount_order) / 8.; - - /* see qcow2_open() */ - refblock_bits =3D cluster_bits - (refcount_order - 3); - refblock_size =3D 1 << refblock_bits; =20 /* header: 1 cluster */ meta_size +=3D cluster_size; @@ -2183,33 +2207,10 @@ static int64_t qcow2_calc_prealloc_size(int64_t tot= al_size, nl1e =3D align_offset(nl1e, cluster_size / sizeof(uint64_t)); meta_size +=3D nl1e * sizeof(uint64_t); =20 - /* total size of refcount blocks - * - * note: every host cluster is reference-counted, including metadata - * (even refcount blocks are recursively included). - * Let: - * a =3D total_size (this is the guest disk size) - * m =3D meta size not including refcount blocks and refcount tables - * c =3D cluster size - * y1 =3D number of refcount blocks entries - * y2 =3D meta size including everything - * rces =3D refcount entry size in bytes - * then, - * y1 =3D (y2 + a)/c - * y2 =3D y1 * rces + y1 * rces * sizeof(u64) / c + m - * we can get y1: - * y1 =3D (a + m) / (c - rces - rces * sizeof(u64) / c) - */ - nrefblocke =3D (aligned_total_size + meta_size + cluster_size) - / (cluster_size - rces - rces * sizeof(uint64_t) - / cluster_size); - refblock_count =3D DIV_ROUND_UP(nrefblocke, refblock_size); - meta_size +=3D refblock_count * cluster_size; - - /* total size of refcount tables */ - nreftablee =3D align_offset(refblock_count, - cluster_size / sizeof(uint64_t)); - meta_size +=3D nreftablee * sizeof(uint64_t); + /* total size of refcount table and blocks */ + meta_size +=3D qcow2_refcount_metadata_size( + (meta_size + aligned_total_size) / cluster_size, + cluster_size, refcount_order); =20 return meta_size + aligned_total_size; } --=20 2.9.4 From nobody Mon Apr 29 12:08:20 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 14992598572426.917124935557126; Wed, 5 Jul 2017 06:04:17 -0700 (PDT) Received: from localhost ([::1]:46120 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dSjyU-0002Dm-Ty for importer@patchew.org; Wed, 05 Jul 2017 09:04:10 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59188) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dSjsk-0005OS-TP for qemu-devel@nongnu.org; Wed, 05 Jul 2017 08:58:16 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dSjsj-0003Hn-Gz for qemu-devel@nongnu.org; Wed, 05 Jul 2017 08:58:15 -0400 Received: from mx1.redhat.com ([209.132.183.28]:36544) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dSjsj-0003HS-6Z for qemu-devel@nongnu.org; Wed, 05 Jul 2017 08:58:13 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 230437F3F1; Wed, 5 Jul 2017 12:58:12 +0000 (UTC) Received: from localhost (ovpn-117-111.ams2.redhat.com [10.36.117.111]) by smtp.corp.redhat.com (Postfix) with ESMTP id A27395C88A; Wed, 5 Jul 2017 12:58:11 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 230437F3F1 Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=stefanha@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 230437F3F1 From: Stefan Hajnoczi To: qemu-devel@nongnu.org Date: Wed, 5 Jul 2017 13:57:34 +0100 Message-Id: <20170705125738.8777-6-stefanha@redhat.com> In-Reply-To: <20170705125738.8777-1-stefanha@redhat.com> References: <20170705125738.8777-1-stefanha@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Wed, 05 Jul 2017 12:58:12 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v9 5/9] qcow2: extract image creation option parsing X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Alberto Garcia , Max Reitz , Nir Soffer , Maor Lipchuk , Stefan Hajnoczi , John Snow Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The image creation options parsed by qcow2_create() are also needed to implement .bdrv_measure(). Extract the parsing code, including input validation. Signed-off-by: Stefan Hajnoczi Reviewed-by: Alberto Garcia --- block/qcow2.c | 109 +++++++++++++++++++++++++++++++++++++++---------------= ---- 1 file changed, 73 insertions(+), 36 deletions(-) diff --git a/block/qcow2.c b/block/qcow2.c index 538f867..361a24a 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -2215,24 +2215,73 @@ static int64_t qcow2_calc_prealloc_size(int64_t tot= al_size, return meta_size + aligned_total_size; } =20 -static int qcow2_create2(const char *filename, int64_t total_size, - const char *backing_file, const char *backing_for= mat, - int flags, size_t cluster_size, PreallocMode prea= lloc, - QemuOpts *opts, int version, int refcount_order, - Error **errp) +static size_t qcow2_opt_get_cluster_size_del(QemuOpts *opts, Error **errp) { + size_t cluster_size; int cluster_bits; - QDict *options; =20 - /* Calculate cluster_bits */ + cluster_size =3D qemu_opt_get_size_del(opts, BLOCK_OPT_CLUSTER_SIZE, + DEFAULT_CLUSTER_SIZE); cluster_bits =3D ctz32(cluster_size); if (cluster_bits < MIN_CLUSTER_BITS || cluster_bits > MAX_CLUSTER_BITS= || (1 << cluster_bits) !=3D cluster_size) { error_setg(errp, "Cluster size must be a power of two between %d a= nd " "%dk", 1 << MIN_CLUSTER_BITS, 1 << (MAX_CLUSTER_BITS - = 10)); - return -EINVAL; + return 0; } + return cluster_size; +} + +static int qcow2_opt_get_version_del(QemuOpts *opts, Error **errp) +{ + char *buf; + int ret; + + buf =3D qemu_opt_get_del(opts, BLOCK_OPT_COMPAT_LEVEL); + if (!buf) { + ret =3D 3; /* default */ + } else if (!strcmp(buf, "0.10")) { + ret =3D 2; + } else if (!strcmp(buf, "1.1")) { + ret =3D 3; + } else { + error_setg(errp, "Invalid compatibility level: '%s'", buf); + ret =3D -EINVAL; + } + g_free(buf); + return ret; +} + +static uint64_t qcow2_opt_get_refcount_bits_del(QemuOpts *opts, int versio= n, + Error **errp) +{ + uint64_t refcount_bits; + + refcount_bits =3D qemu_opt_get_number_del(opts, BLOCK_OPT_REFCOUNT_BIT= S, 16); + if (refcount_bits > 64 || !is_power_of_2(refcount_bits)) { + error_setg(errp, "Refcount width must be a power of two and may no= t " + "exceed 64 bits"); + return 0; + } + + if (version < 3 && refcount_bits !=3D 16) { + error_setg(errp, "Different refcount widths than 16 bits require " + "compatibility level 1.1 or above (use compat=3D1.1 or " + "greater)"); + return 0; + } + + return refcount_bits; +} + +static int qcow2_create2(const char *filename, int64_t total_size, + const char *backing_file, const char *backing_for= mat, + int flags, size_t cluster_size, PreallocMode prea= lloc, + QemuOpts *opts, int version, int refcount_order, + Error **errp) +{ + QDict *options; =20 /* * Open the image file and write a minimal qcow2 header. @@ -2282,7 +2331,7 @@ static int qcow2_create2(const char *filename, int64_= t total_size, *header =3D (QCowHeader) { .magic =3D cpu_to_be32(QCOW_MAGIC), .version =3D cpu_to_be32(version), - .cluster_bits =3D cpu_to_be32(cluster_bits), + .cluster_bits =3D cpu_to_be32(ctz32(cluster_size)), .size =3D cpu_to_be64(0), .l1_table_offset =3D cpu_to_be64(0), .l1_size =3D cpu_to_be32(0), @@ -2418,8 +2467,8 @@ static int qcow2_create(const char *filename, QemuOpt= s *opts, Error **errp) int flags =3D 0; size_t cluster_size =3D DEFAULT_CLUSTER_SIZE; PreallocMode prealloc; - int version =3D 3; - uint64_t refcount_bits =3D 16; + int version; + uint64_t refcount_bits; int refcount_order; Error *local_err =3D NULL; int ret; @@ -2432,8 +2481,12 @@ static int qcow2_create(const char *filename, QemuOp= ts *opts, Error **errp) if (qemu_opt_get_bool_del(opts, BLOCK_OPT_ENCRYPT, false)) { flags |=3D BLOCK_FLAG_ENCRYPT; } - cluster_size =3D qemu_opt_get_size_del(opts, BLOCK_OPT_CLUSTER_SIZE, - DEFAULT_CLUSTER_SIZE); + cluster_size =3D qcow2_opt_get_cluster_size_del(opts, &local_err); + if (local_err) { + error_propagate(errp, local_err); + ret =3D -EINVAL; + goto finish; + } buf =3D qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC); prealloc =3D qapi_enum_parse(PreallocMode_lookup, buf, PREALLOC_MODE__MAX, PREALLOC_MODE_OFF, @@ -2443,16 +2496,10 @@ static int qcow2_create(const char *filename, QemuO= pts *opts, Error **errp) ret =3D -EINVAL; goto finish; } - g_free(buf); - buf =3D qemu_opt_get_del(opts, BLOCK_OPT_COMPAT_LEVEL); - if (!buf) { - /* keep the default */ - } else if (!strcmp(buf, "0.10")) { - version =3D 2; - } else if (!strcmp(buf, "1.1")) { - version =3D 3; - } else { - error_setg(errp, "Invalid compatibility level: '%s'", buf); + + version =3D qcow2_opt_get_version_del(opts, &local_err); + if (local_err) { + error_propagate(errp, local_err); ret =3D -EINVAL; goto finish; } @@ -2475,19 +2522,9 @@ static int qcow2_create(const char *filename, QemuOp= ts *opts, Error **errp) goto finish; } =20 - refcount_bits =3D qemu_opt_get_number_del(opts, BLOCK_OPT_REFCOUNT_BIT= S, - refcount_bits); - if (refcount_bits > 64 || !is_power_of_2(refcount_bits)) { - error_setg(errp, "Refcount width must be a power of two and may no= t " - "exceed 64 bits"); - ret =3D -EINVAL; - goto finish; - } - - if (version < 3 && refcount_bits !=3D 16) { - error_setg(errp, "Different refcount widths than 16 bits require " - "compatibility level 1.1 or above (use compat=3D1.1 or " - "greater)"); + refcount_bits =3D qcow2_opt_get_refcount_bits_del(opts, version, &loca= l_err); + if (local_err) { + error_propagate(errp, local_err); ret =3D -EINVAL; goto finish; } --=20 2.9.4 From nobody Mon Apr 29 12:08:20 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1499259608946323.1906645323721; Wed, 5 Jul 2017 06:00:08 -0700 (PDT) Received: from localhost ([::1]:46094 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dSjuY-0007FR-Ik for importer@patchew.org; Wed, 05 Jul 2017 09:00:06 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59232) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dSjsp-0005SY-SL for qemu-devel@nongnu.org; Wed, 05 Jul 2017 08:58:23 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dSjso-0003LC-Rx for qemu-devel@nongnu.org; Wed, 05 Jul 2017 08:58:19 -0400 Received: from mx1.redhat.com ([209.132.183.28]:59888) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dSjso-0003Ke-IN for qemu-devel@nongnu.org; Wed, 05 Jul 2017 08:58:18 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 7076B80F95; Wed, 5 Jul 2017 12:58:17 +0000 (UTC) Received: from localhost (ovpn-117-111.ams2.redhat.com [10.36.117.111]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7BF0E6F43F; Wed, 5 Jul 2017 12:58:13 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 7076B80F95 Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=stefanha@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 7076B80F95 From: Stefan Hajnoczi To: qemu-devel@nongnu.org Date: Wed, 5 Jul 2017 13:57:35 +0100 Message-Id: <20170705125738.8777-7-stefanha@redhat.com> In-Reply-To: <20170705125738.8777-1-stefanha@redhat.com> References: <20170705125738.8777-1-stefanha@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Wed, 05 Jul 2017 12:58:17 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v9 6/9] qcow2: add bdrv_measure() support X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Alberto Garcia , Max Reitz , Nir Soffer , Maor Lipchuk , Stefan Hajnoczi , John Snow Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Use qcow2_calc_prealloc_size() to get the required file size. Signed-off-by: Stefan Hajnoczi Reviewed-by: Alberto Garcia --- v8: * Use QCOW_MAX_L1_SIZE to check maximum virtual disk size [Berto] Look at virtual disk size because metadata does not need to fit into the L1 table. v7: * Check that qcow2 supports the image file size [Berto] --- block/qcow2.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 137 insertions(+) diff --git a/block/qcow2.c b/block/qcow2.c index 361a24a..033dbac 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -3002,6 +3002,142 @@ static coroutine_fn int qcow2_co_flush_to_os(BlockD= riverState *bs) return 0; } =20 +static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *i= n_bs, + Error **errp) +{ + Error *local_err =3D NULL; + BlockMeasureInfo *info; + uint64_t required =3D 0; /* bytes that contribute to required size */ + uint64_t virtual_size; /* disk size as seen by guest */ + uint64_t refcount_bits; + uint64_t l2_tables; + size_t cluster_size; + int version; + char *optstr; + PreallocMode prealloc; + bool has_backing_file; + + /* Parse image creation options */ + cluster_size =3D qcow2_opt_get_cluster_size_del(opts, &local_err); + if (local_err) { + goto err; + } + + version =3D qcow2_opt_get_version_del(opts, &local_err); + if (local_err) { + goto err; + } + + refcount_bits =3D qcow2_opt_get_refcount_bits_del(opts, version, &loca= l_err); + if (local_err) { + goto err; + } + + optstr =3D qemu_opt_get_del(opts, BLOCK_OPT_PREALLOC); + prealloc =3D qapi_enum_parse(PreallocMode_lookup, optstr, + PREALLOC_MODE__MAX, PREALLOC_MODE_OFF, + &local_err); + g_free(optstr); + if (local_err) { + goto err; + } + + optstr =3D qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE); + has_backing_file =3D !!optstr; + g_free(optstr); + + virtual_size =3D align_offset(qemu_opt_get_size_del(opts, BLOCK_OPT_SI= ZE, 0), + cluster_size); + + /* Check that virtual disk size is valid */ + l2_tables =3D DIV_ROUND_UP(virtual_size / cluster_size, + cluster_size / sizeof(uint64_t)); + if (l2_tables * sizeof(uint64_t) > QCOW_MAX_L1_SIZE) { + error_setg(&local_err, "The image size is too large " + "(try using a larger cluster size)"); + goto err; + } + + /* Account for input image */ + if (in_bs) { + int64_t ssize =3D bdrv_getlength(in_bs); + if (ssize < 0) { + error_setg_errno(&local_err, -ssize, + "Unable to get image virtual_size"); + goto err; + } + + virtual_size =3D align_offset(ssize, cluster_size); + + if (has_backing_file) { + /* We don't how much of the backing chain is shared by the inp= ut + * image and the new image file. In the worst case the new im= age's + * backing file has nothing in common with the input image. Be + * conservative and assume all clusters need to be written. + */ + required =3D virtual_size; + } else { + int cluster_sectors =3D cluster_size / BDRV_SECTOR_SIZE; + int64_t sector_num; + int pnum =3D 0; + + for (sector_num =3D 0; + sector_num < ssize / BDRV_SECTOR_SIZE; + sector_num +=3D pnum) { + int nb_sectors =3D MAX(ssize / BDRV_SECTOR_SIZE - sector_n= um, + INT_MAX); + BlockDriverState *file; + int64_t ret; + + ret =3D bdrv_get_block_status_above(in_bs, NULL, + sector_num, nb_sectors, + &pnum, &file); + if (ret < 0) { + error_setg_errno(&local_err, -ret, + "Unable to get block status"); + goto err; + } + + if (ret & BDRV_BLOCK_ZERO) { + /* Skip zero regions (safe with no backing file) */ + } else if ((ret & (BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED)= ) =3D=3D + (BDRV_BLOCK_DATA | BDRV_BLOCK_ALLOCATED)) { + /* Extend pnum to end of cluster for next iteration */ + pnum =3D ROUND_UP(sector_num + pnum, cluster_sectors) - + sector_num; + + /* Count clusters we've seen */ + required +=3D (sector_num % cluster_sectors + pnum) * + BDRV_SECTOR_SIZE; + } + } + } + } + + /* Take into account preallocation. Nothing special is needed for + * PREALLOC_MODE_METADATA since metadata is always counted. + */ + if (prealloc =3D=3D PREALLOC_MODE_FULL || prealloc =3D=3D PREALLOC_MOD= E_FALLOC) { + required =3D virtual_size; + } + + info =3D g_new(BlockMeasureInfo, 1); + info->fully_allocated =3D + qcow2_calc_prealloc_size(virtual_size, cluster_size, + ctz32(refcount_bits)); + + /* Remove data clusters that are not required. This overestimates the + * required size because metadata needed for the fully allocated file = is + * still counted. + */ + info->required =3D info->fully_allocated - virtual_size + required; + return info; + +err: + error_propagate(errp, local_err); + return NULL; +} + static int qcow2_get_info(BlockDriverState *bs, BlockDriverInfo *bdi) { BDRVQcow2State *s =3D bs->opaque; @@ -3549,6 +3685,7 @@ BlockDriver bdrv_qcow2 =3D { .bdrv_snapshot_delete =3D qcow2_snapshot_delete, .bdrv_snapshot_list =3D qcow2_snapshot_list, .bdrv_snapshot_load_tmp =3D qcow2_snapshot_load_tmp, + .bdrv_measure =3D qcow2_measure, .bdrv_get_info =3D qcow2_get_info, .bdrv_get_specific_info =3D qcow2_get_specific_info, =20 --=20 2.9.4 From nobody Mon Apr 29 12:08:20 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 149926002751116.024019567997016; Wed, 5 Jul 2017 06:07:07 -0700 (PDT) Received: from localhost ([::1]:46153 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dSk1E-0004wS-Ra for importer@patchew.org; Wed, 05 Jul 2017 09:07:00 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59288) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dSjsx-0005Z8-Gj for qemu-devel@nongnu.org; Wed, 05 Jul 2017 08:58:29 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dSjsv-0003Ph-Sc for qemu-devel@nongnu.org; Wed, 05 Jul 2017 08:58:27 -0400 Received: from mx1.redhat.com ([209.132.183.28]:57894) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dSjsv-0003PO-Ia for qemu-devel@nongnu.org; Wed, 05 Jul 2017 08:58:25 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 6B6223DEE4; Wed, 5 Jul 2017 12:58:24 +0000 (UTC) Received: from localhost (ovpn-117-111.ams2.redhat.com [10.36.117.111]) by smtp.corp.redhat.com (Postfix) with ESMTP id CB2ED7E8F9; Wed, 5 Jul 2017 12:58:18 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 6B6223DEE4 Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx05.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=stefanha@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 6B6223DEE4 From: Stefan Hajnoczi To: qemu-devel@nongnu.org Date: Wed, 5 Jul 2017 13:57:36 +0100 Message-Id: <20170705125738.8777-8-stefanha@redhat.com> In-Reply-To: <20170705125738.8777-1-stefanha@redhat.com> References: <20170705125738.8777-1-stefanha@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Wed, 05 Jul 2017 12:58:24 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v9 7/9] qemu-img: add measure subcommand X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Alberto Garcia , Max Reitz , Nir Soffer , Maor Lipchuk , Stefan Hajnoczi , John Snow Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The measure subcommand calculates the size required by a new image file. This can be used by users or management tools that need to allocate space on an LVM volume, SAN LUN, etc before creating or converting an image file. Suggested-by: Maor Lipchuk Signed-off-by: Stefan Hajnoczi Reviewed-by: Alberto Garcia --- v9: * Fix swapped fmt <-> output_fmt parameters in documentation [Max] v7: * Really use UINT64_MAX everywhere instead of ~0ULL [Berto] v5: * Use UINT64_MAX instead of ~0ULL [Berto] * Document qemu-img measure ofmt, fmt, output_fmt, and snapshot_param [Berto] --- qemu-img.c | 234 +++++++++++++++++++++++++++++++++++++++++++++++++++= ++++ qemu-img-cmds.hx | 6 ++ qemu-img.texi | 30 +++++++ 3 files changed, 270 insertions(+) diff --git a/qemu-img.c b/qemu-img.c index 91ad6be..b989091 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -61,6 +61,7 @@ enum { OPTION_FLUSH_INTERVAL =3D 261, OPTION_NO_DRAIN =3D 262, OPTION_TARGET_IMAGE_OPTS =3D 263, + OPTION_SIZE =3D 264, }; =20 typedef enum OutputFormat { @@ -4451,6 +4452,239 @@ out: return 0; } =20 +static void dump_json_block_measure_info(BlockMeasureInfo *info) +{ + QString *str; + QObject *obj; + Visitor *v =3D qobject_output_visitor_new(&obj); + + visit_type_BlockMeasureInfo(v, NULL, &info, &error_abort); + visit_complete(v, &obj); + str =3D qobject_to_json_pretty(obj); + assert(str !=3D NULL); + printf("%s\n", qstring_get_str(str)); + qobject_decref(obj); + visit_free(v); + QDECREF(str); +} + +static int img_measure(int argc, char **argv) +{ + static const struct option long_options[] =3D { + {"help", no_argument, 0, 'h'}, + {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS}, + {"object", required_argument, 0, OPTION_OBJECT}, + {"output", required_argument, 0, OPTION_OUTPUT}, + {"size", required_argument, 0, OPTION_SIZE}, + {"force-share", no_argument, 0, 'U'}, + {0, 0, 0, 0} + }; + OutputFormat output_format =3D OFORMAT_HUMAN; + BlockBackend *in_blk =3D NULL; + BlockDriver *drv; + const char *filename =3D NULL; + const char *fmt =3D NULL; + const char *out_fmt =3D "raw"; + char *options =3D NULL; + char *snapshot_name =3D NULL; + bool force_share =3D false; + QemuOpts *opts =3D NULL; + QemuOpts *object_opts =3D NULL; + QemuOpts *sn_opts =3D NULL; + QemuOptsList *create_opts =3D NULL; + bool image_opts =3D false; + uint64_t img_size =3D UINT64_MAX; + BlockMeasureInfo *info =3D NULL; + Error *local_err =3D NULL; + int ret =3D 1; + int c; + + while ((c =3D getopt_long(argc, argv, "hf:O:o:l:U", + long_options, NULL)) !=3D -1) { + switch (c) { + case '?': + case 'h': + help(); + break; + case 'f': + fmt =3D optarg; + break; + case 'O': + out_fmt =3D optarg; + break; + case 'o': + if (!is_valid_option_list(optarg)) { + error_report("Invalid option list: %s", optarg); + goto out; + } + if (!options) { + options =3D g_strdup(optarg); + } else { + char *old_options =3D options; + options =3D g_strdup_printf("%s,%s", options, optarg); + g_free(old_options); + } + break; + case 'l': + if (strstart(optarg, SNAPSHOT_OPT_BASE, NULL)) { + sn_opts =3D qemu_opts_parse_noisily(&internal_snapshot_opt= s, + optarg, false); + if (!sn_opts) { + error_report("Failed in parsing snapshot param '%s'", + optarg); + goto out; + } + } else { + snapshot_name =3D optarg; + } + break; + case 'U': + force_share =3D true; + break; + case OPTION_OBJECT: + object_opts =3D qemu_opts_parse_noisily(&qemu_object_opts, + optarg, true); + if (!object_opts) { + goto out; + } + break; + case OPTION_IMAGE_OPTS: + image_opts =3D true; + break; + case OPTION_OUTPUT: + if (!strcmp(optarg, "json")) { + output_format =3D OFORMAT_JSON; + } else if (!strcmp(optarg, "human")) { + output_format =3D OFORMAT_HUMAN; + } else { + error_report("--output must be used with human or json " + "as argument."); + goto out; + } + break; + case OPTION_SIZE: + { + int64_t sval; + + sval =3D cvtnum(optarg); + if (sval < 0) { + if (sval =3D=3D -ERANGE) { + error_report("Image size must be less than 8 EiB!"); + } else { + error_report("Invalid image size specified! You may us= e " + "k, M, G, T, P or E suffixes for "); + error_report("kilobytes, megabytes, gigabytes, terabyt= es, " + "petabytes and exabytes."); + } + goto out; + } + img_size =3D (uint64_t)sval; + } + break; + } + } + + if (qemu_opts_foreach(&qemu_object_opts, + user_creatable_add_opts_foreach, + NULL, NULL)) { + goto out; + } + + if (argc - optind > 1) { + error_report("At most one filename argument is allowed."); + goto out; + } else if (argc - optind =3D=3D 1) { + filename =3D argv[optind]; + } + + if (!filename && + (object_opts || image_opts || fmt || snapshot_name || sn_opts)) { + error_report("--object, --image-opts, -f, and -l " + "require a filename argument."); + goto out; + } + if (filename && img_size !=3D UINT64_MAX) { + error_report("--size N cannot be used together with a filename."); + goto out; + } + if (!filename && img_size =3D=3D UINT64_MAX) { + error_report("Either --size N or one filename must be specified."); + goto out; + } + + if (filename) { + in_blk =3D img_open(image_opts, filename, fmt, 0, + false, false, force_share); + if (!in_blk) { + goto out; + } + + if (sn_opts) { + bdrv_snapshot_load_tmp(blk_bs(in_blk), + qemu_opt_get(sn_opts, SNAPSHOT_OPT_ID), + qemu_opt_get(sn_opts, SNAPSHOT_OPT_NAME), + &local_err); + } else if (snapshot_name !=3D NULL) { + bdrv_snapshot_load_tmp_by_id_or_name(blk_bs(in_blk), + snapshot_name, &local_err); + } + if (local_err) { + error_reportf_err(local_err, "Failed to load snapshot: "); + goto out; + } + } + + drv =3D bdrv_find_format(out_fmt); + if (!drv) { + error_report("Unknown file format '%s'", out_fmt); + goto out; + } + if (!drv->create_opts) { + error_report("Format driver '%s' does not support image creation", + drv->format_name); + goto out; + } + + create_opts =3D qemu_opts_append(create_opts, drv->create_opts); + create_opts =3D qemu_opts_append(create_opts, bdrv_file.create_opts); + opts =3D qemu_opts_create(create_opts, NULL, 0, &error_abort); + if (options) { + qemu_opts_do_parse(opts, options, NULL, &local_err); + if (local_err) { + error_report_err(local_err); + error_report("Invalid options for file format '%s'", out_fmt); + goto out; + } + } + if (img_size !=3D UINT64_MAX) { + qemu_opt_set_number(opts, BLOCK_OPT_SIZE, img_size, &error_abort); + } + + info =3D bdrv_measure(drv, opts, in_blk ? blk_bs(in_blk) : NULL, &loca= l_err); + if (local_err) { + error_report_err(local_err); + goto out; + } + + if (output_format =3D=3D OFORMAT_HUMAN) { + printf("required size: %" PRIu64 "\n", info->required); + printf("fully allocated size: %" PRIu64 "\n", info->fully_allocate= d); + } else { + dump_json_block_measure_info(info); + } + + ret =3D 0; + +out: + qapi_free_BlockMeasureInfo(info); + qemu_opts_del(object_opts); + qemu_opts_del(opts); + qemu_opts_del(sn_opts); + qemu_opts_free(create_opts); + g_free(options); + blk_unref(in_blk); + return ret; +} =20 static const img_cmd_t img_cmds[] =3D { #define DEF(option, callback, arg_string) \ diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx index a39fcdb..ac5946b 100644 --- a/qemu-img-cmds.hx +++ b/qemu-img-cmds.hx @@ -63,6 +63,12 @@ STEXI @item map [--object @var{objectdef}] [--image-opts] [-f @var{fmt}] [--outp= ut=3D@var{ofmt}] [-U] @var{filename} ETEXI =20 +DEF("measure", img_measure, +"measure [--output=3Dofmt] [-O output_fmt] [-o options] [--size N | [--obj= ect objectdef] [--image-opts] [-f fmt] [-l snapshot_param] filename]") +STEXI +@item measure [--output=3D@var{ofmt}] [-O @var{output_fmt}] [-o @var{optio= ns}] [--size @var{N} | [--object @var{objectdef}] [--image-opts] [-f @var{f= mt}] [-l @var{snapshot_param}] @var{filename}] +ETEXI + DEF("snapshot", img_snapshot, "snapshot [--object objectdef] [--image-opts] [-U] [-q] [-l | -a snaps= hot | -c snapshot | -d snapshot] filename") STEXI diff --git a/qemu-img.texi b/qemu-img.texi index 5b925ec..269780a 100644 --- a/qemu-img.texi +++ b/qemu-img.texi @@ -438,6 +438,36 @@ preallocated. For more information, consult @file{include/block/block.h} in QEMU's source code. =20 +@item measure [--output=3D@var{ofmt}] [-O @var{output_fmt}] [-o @var{optio= ns}] [--size @var{N} | [--object @var{objectdef}] [--image-opts] [-f @var{f= mt}] [-l @var{snapshot_param}] @var{filename}] + +Calculate the file size required for a new image. This information can be= used +to size logical volumes or SAN LUNs appropriately for the image that will = be +placed in them. The values reported are guaranteed to be large enough to = fit +the image. The command can output in the format @var{ofmt} which is either +@code{human} or @code{json}. + +If the size @var{N} is given then act as if creating a new empty image file +using @command{qemu-img create}. If @var{filename} is given then act as if +converting an existing image file using @command{qemu-img convert}. The f= ormat +of the new file is given by @var{output_fmt} while the format of an existi= ng +file is given by @var{fmt}. + +A snapshot in an existing image can be specified using @var{snapshot_param= }. + +The following fields are reported: +@example +required size: 524288 +fully allocated size: 1074069504 +@end example + +The @code{required size} is the file size of the new image. It may be sma= ller +than the virtual disk size if the image format supports compact representa= tion. + +The @code{fully allocated size} is the file size of the new image once dat= a has +been written to all sectors. This is the maximum size that the image file= can +occupy with the exception of internal snapshots, dirty bitmaps, vmstate da= ta, +and other advanced image format features. + @item snapshot [-l | -a @var{snapshot} | -c @var{snapshot} | -d @var{snaps= hot} ] @var{filename} =20 List, apply, create or delete snapshots in image @var{filename}. --=20 2.9.4 From nobody Mon Apr 29 12:08:20 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1499259757910451.1513704616043; Wed, 5 Jul 2017 06:02:37 -0700 (PDT) Received: from localhost ([::1]:46109 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dSjwu-0000ra-NG for importer@patchew.org; Wed, 05 Jul 2017 09:02:32 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59333) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dSjt7-00061C-P8 for qemu-devel@nongnu.org; Wed, 05 Jul 2017 08:58:38 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dSjt3-0003VE-TY for qemu-devel@nongnu.org; Wed, 05 Jul 2017 08:58:37 -0400 Received: from mx1.redhat.com ([209.132.183.28]:34120) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dSjt3-0003Uy-NU for qemu-devel@nongnu.org; Wed, 05 Jul 2017 08:58:33 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 964034E909; Wed, 5 Jul 2017 12:58:32 +0000 (UTC) Received: from localhost (ovpn-117-111.ams2.redhat.com [10.36.117.111]) by smtp.corp.redhat.com (Postfix) with ESMTP id C29106FB9D; Wed, 5 Jul 2017 12:58:25 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 964034E909 Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=stefanha@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 964034E909 From: Stefan Hajnoczi To: qemu-devel@nongnu.org Date: Wed, 5 Jul 2017 13:57:37 +0100 Message-Id: <20170705125738.8777-9-stefanha@redhat.com> In-Reply-To: <20170705125738.8777-1-stefanha@redhat.com> References: <20170705125738.8777-1-stefanha@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Wed, 05 Jul 2017 12:58:32 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v9 8/9] qemu-iotests: support per-format golden output files X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Alberto Garcia , Max Reitz , Nir Soffer , Maor Lipchuk , Stefan Hajnoczi , John Snow Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Some tests produce format-dependent output. Either the difference is filtered out and ignored, or the test case is format-specific so we don't need to worry about per-format output differences. There is a third case: the test script is the same for all image formats and the format-dependent output is relevant. An ugly workaround is to copy-paste the test into multiple per-format test cases. This duplicates code and is not maintainable. This patch allows test cases to add per-format golden output files so a single test case can work correctly when format-dependent output must be checked: 123.out.qcow2 123.out.raw 123.out.vmdk ... This naming scheme is not composable with 123.out.nocache or 123.pc.out, two other scenarios where output files are split. I don't think it matters since few test cases need these features. Signed-off-by: Stefan Hajnoczi Reviewed-by: Alberto Garcia --- tests/qemu-iotests/check | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check index 4b1c674..29553cf 100755 --- a/tests/qemu-iotests/check +++ b/tests/qemu-iotests/check @@ -338,6 +338,11 @@ do reference=3D"$reference_machine" fi =20 + reference_format=3D"$source_iotests/$seq.out.$IMGFMT" + if [ -f "$reference_format" ]; then + reference=3D"$reference_format" + fi + if [ "$CACHEMODE" =3D "none" ]; then [ -f "$source_iotests/$seq.out.nocache" ] && reference=3D"= $source_iotests/$seq.out.nocache" fi --=20 2.9.4 From nobody Mon Apr 29 12:08:20 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1499259772815493.94997775405284; Wed, 5 Jul 2017 06:02:52 -0700 (PDT) Received: from localhost ([::1]:46110 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dSjxA-00014K-IC for importer@patchew.org; Wed, 05 Jul 2017 09:02:48 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59357) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dSjt9-00066A-I7 for qemu-devel@nongnu.org; Wed, 05 Jul 2017 08:58:42 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dSjt6-0003Wc-Ud for qemu-devel@nongnu.org; Wed, 05 Jul 2017 08:58:39 -0400 Received: from mx1.redhat.com ([209.132.183.28]:37010) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1dSjt6-0003WC-LT for qemu-devel@nongnu.org; Wed, 05 Jul 2017 08:58:36 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 82DE88E771; Wed, 5 Jul 2017 12:58:35 +0000 (UTC) Received: from localhost (ovpn-117-111.ams2.redhat.com [10.36.117.111]) by smtp.corp.redhat.com (Postfix) with ESMTP id 312297E8F5; Wed, 5 Jul 2017 12:58:33 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 82DE88E771 Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx02.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=stefanha@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 82DE88E771 From: Stefan Hajnoczi To: qemu-devel@nongnu.org Date: Wed, 5 Jul 2017 13:57:38 +0100 Message-Id: <20170705125738.8777-10-stefanha@redhat.com> In-Reply-To: <20170705125738.8777-1-stefanha@redhat.com> References: <20170705125738.8777-1-stefanha@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Wed, 05 Jul 2017 12:58:35 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v9 9/9] iotests: add test 178 for qemu-img measure X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Alberto Garcia , Max Reitz , Nir Soffer , Maor Lipchuk , Stefan Hajnoczi , John Snow Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Signed-off-by: Stefan Hajnoczi Reviewed-by: Alberto Garcia --- v8: * Check 2P file size [Berto] v7: * Check max file size with 7 exabytes [Berto] --- tests/qemu-iotests/178 | 170 +++++++++++++++++++++++ tests/qemu-iotests/178.out.qcow2 | 286 +++++++++++++++++++++++++++++++++++= ++++ tests/qemu-iotests/178.out.raw | 158 +++++++++++++++++++++ tests/qemu-iotests/group | 1 + 4 files changed, 615 insertions(+) create mode 100755 tests/qemu-iotests/178 create mode 100644 tests/qemu-iotests/178.out.qcow2 create mode 100644 tests/qemu-iotests/178.out.raw diff --git a/tests/qemu-iotests/178 b/tests/qemu-iotests/178 new file mode 100755 index 0000000..6af52c6 --- /dev/null +++ b/tests/qemu-iotests/178 @@ -0,0 +1,170 @@ +#!/bin/bash +# +# qemu-img measure sub-command tests +# +# Copyright (C) 2017 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +# creator +owner=3Dstefanha@redhat.com + +seq=3D`basename $0` +echo "QA output created by $seq" + +here=3D`pwd` +status=3D1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img + rm -f "$TEST_IMG.converted" +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter +. ./common.pattern + +_supported_fmt raw qcow2 +_supported_proto file +_supported_os Linux + +echo "=3D=3D Input validation =3D=3D" +echo + +_make_test_img 1G + +$QEMU_IMG measure # missing arguments +$QEMU_IMG measure --size 2G "$TEST_IMG" # only one allowed +$QEMU_IMG measure "$TEST_IMG" a # only one filename allowed +$QEMU_IMG measure --object secret,id=3Dsec0,data=3DMTIzNDU2,format=3Dbase6= 4 # missing filename +$QEMU_IMG measure --image-opts # missing filename +$QEMU_IMG measure -f qcow2 # missing filename +$QEMU_IMG measure -l snap1 # missing filename +$QEMU_IMG measure -o , # invalid option list +$QEMU_IMG measure -l snapshot.foo # invalid snapshot option +$QEMU_IMG measure --output foo # invalid output format +$QEMU_IMG measure --size -1 # invalid image size +$QEMU_IMG measure -O foo "$TEST_IMG" # unknown image file format + +make_test_img_with_fmt() { + # Shadow global variables within this function + local IMGFMT=3D"$1" IMGOPTS=3D"" + _make_test_img "$2" +} + +qemu_io_with_fmt() { + # Shadow global variables within this function + local QEMU_IO_OPTIONS=3D$(echo "$QEMU_IO_OPTIONS" | sed "s/-f $IMGFMT/= -f $1/") + shift + $QEMU_IO "$@" +} + +# The proof is in the pudding: converted image size cannot be larger than = the +# required size. +# +# Note: if a change to the image format code causes the file size to chang= e, +# then this test fails! This is good because it's a reminder to check tha= t the +# required size is still at least as big as the actual converted file size. +convert_and_show_size() { + local fmt=3D"$1" + shift + $QEMU_IMG convert -f "$fmt" -O "$IMGFMT" "$TEST_IMG" "$@" "$TEST_IMG.c= onverted" + stat -c "converted image file size in bytes: %s" "$TEST_IMG.converted" +} + +for ofmt in human json; do + echo + echo "=3D=3D Size calculation for a new file ($ofmt) =3D=3D" + echo + + # Try a few interesting sizes + $QEMU_IMG measure --output=3D$ofmt -O "$IMGFMT" --size 0 + $QEMU_IMG measure --output=3D$ofmt -O "$IMGFMT" --size 2G + $QEMU_IMG measure --output=3D$ofmt -O "$IMGFMT" --size 64G + $QEMU_IMG measure --output=3D$ofmt -O "$IMGFMT" --size 256G + $QEMU_IMG measure --output=3D$ofmt -O "$IMGFMT" --size 1T + $QEMU_IMG measure --output=3D$ofmt -O "$IMGFMT" --size 2P + $QEMU_IMG measure --output=3D$ofmt -O "$IMGFMT" --size 7E + + # Always test the raw input files but also IMGFMT + for fmt in $(echo -e "raw\n$IMGFMT\n" | sort -u); do + echo + echo "=3D=3D Empty $fmt input image ($ofmt) =3D=3D" + echo + make_test_img_with_fmt "$fmt" 0 + $QEMU_IMG measure --output=3D$ofmt -f "$fmt" -O "$IMGFMT" "$TEST_I= MG" + echo + convert_and_show_size "$fmt" + + echo + echo "=3D=3D $fmt input image with data ($ofmt) =3D=3D" + echo + make_test_img_with_fmt "$fmt" 1G + $QEMU_IMG measure --output=3D$ofmt -f "$fmt" -O "$IMGFMT" "$TEST_I= MG" + qemu_io_with_fmt "$fmt" -c "write 512 512" "$TEST_IMG" | _filter_q= emu_io + qemu_io_with_fmt "$fmt" -c "write 64K 64K" "$TEST_IMG" | _filter_q= emu_io + if [ "$fmt" =3D "qcow2" ]; then + $QEMU_IMG snapshot -c snapshot1 "$TEST_IMG" + fi + qemu_io_with_fmt "$fmt" -c "write 128M 63K" "$TEST_IMG" | _filter_= qemu_io + $QEMU_IMG measure --output=3D$ofmt -f "$fmt" -O "$IMGFMT" "$TEST_I= MG" + echo + convert_and_show_size "$fmt" + + if [ "$fmt" =3D "qcow2" ]; then + echo + echo "=3D=3D $fmt input image with internal snapshot ($ofmt) = =3D=3D" + echo + $QEMU_IMG measure --output=3D$ofmt -f "$fmt" -l snapshot1 \ + -O "$IMGFMT" "$TEST_IMG" + echo + convert_and_show_size "$fmt" -l snapshot1 + fi + + if [ "$IMGFMT" =3D "qcow2" ]; then + echo + echo "=3D=3D $fmt input image and a backing file ($ofmt) =3D= =3D" + echo + # The backing file doesn't need to exist :) + $QEMU_IMG measure --output=3D$ofmt -o backing_file=3Dx \ + -f "$fmt" -O "$IMGFMT" "$TEST_IMG" + fi + + echo + echo "=3D=3D $fmt input image and preallocation ($ofmt) =3D=3D" + echo + $QEMU_IMG measure --output=3D$ofmt -o preallocation=3Dfull \ + -f "$fmt" -O "$IMGFMT" "$TEST_IMG" + echo + convert_and_show_size "$fmt" -o preallocation=3Dfull + + echo + echo "=3D=3D Fully-allocated $fmt input image ($ofmt) =3D=3D" + echo + make_test_img_with_fmt "$fmt" 8M + qemu_io_with_fmt "$fmt" -c "write 0 8M" "$TEST_IMG" | _filter_qemu= _io + $QEMU_IMG measure --output=3D$ofmt -f "$fmt" -O "$IMGFMT" "$TEST_I= MG" + echo + convert_and_show_size "$fmt" + done +done + +# success, all done +echo "*** done" +rm -f $seq.full +status=3D0 diff --git a/tests/qemu-iotests/178.out.qcow2 b/tests/qemu-iotests/178.out.= qcow2 new file mode 100644 index 0000000..d42d4a4 --- /dev/null +++ b/tests/qemu-iotests/178.out.qcow2 @@ -0,0 +1,286 @@ +QA output created by 178 +=3D=3D Input validation =3D=3D + +Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D1073741824 +qemu-img: Either --size N or one filename must be specified. +qemu-img: --size N cannot be used together with a filename. +qemu-img: At most one filename argument is allowed. +qemu-img: --object, --image-opts, -f, and -l require a filename argument. +qemu-img: --object, --image-opts, -f, and -l require a filename argument. +qemu-img: --object, --image-opts, -f, and -l require a filename argument. +qemu-img: --object, --image-opts, -f, and -l require a filename argument. +qemu-img: Invalid option list: , +qemu-img: Invalid parameter 'snapshot.foo' +qemu-img: Failed in parsing snapshot param 'snapshot.foo' +qemu-img: --output must be used with human or json as argument. +qemu-img: Image size must be less than 8 EiB! +qemu-img: Unknown file format 'foo' + +=3D=3D Size calculation for a new file (human) =3D=3D + +required size: 196608 +fully allocated size: 196608 +required size: 589824 +fully allocated size: 2148073472 +required size: 10747904 +fully allocated size: 68730224640 +required size: 42205184 +fully allocated size: 274920112128 +required size: 168034304 +fully allocated size: 1099679662080 +required size: 343650009088 +fully allocated size: 2252143463694336 +qemu-img: The image size is too large (try using a larger cluster size) + +=3D=3D Empty qcow2 input image (human) =3D=3D + +Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D0 +required size: 196608 +fully allocated size: 196608 + +converted image file size in bytes: 196608 + +=3D=3D qcow2 input image with data (human) =3D=3D + +Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D1073741824 +required size: 393216 +fully allocated size: 1074135040 +wrote 512/512 bytes at offset 512 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 65536/65536 bytes at offset 65536 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 64512/64512 bytes at offset 134217728 +63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +required size: 589824 +fully allocated size: 1074135040 + +converted image file size in bytes: 524288 + +=3D=3D qcow2 input image with internal snapshot (human) =3D=3D + +required size: 524288 +fully allocated size: 1074135040 + +converted image file size in bytes: 458752 + +=3D=3D qcow2 input image and a backing file (human) =3D=3D + +required size: 1074135040 +fully allocated size: 1074135040 + +=3D=3D qcow2 input image and preallocation (human) =3D=3D + +required size: 1074135040 +fully allocated size: 1074135040 + +converted image file size in bytes: 1074135040 + +=3D=3D Fully-allocated qcow2 input image (human) =3D=3D + +Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D8388608 +wrote 8388608/8388608 bytes at offset 0 +8 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +required size: 8716288 +fully allocated size: 8716288 + +converted image file size in bytes: 8716288 + +=3D=3D Empty raw input image (human) =3D=3D + +Formatting 'TEST_DIR/t.qcow2', fmt=3DIMGFMT size=3D0 +required size: 196608 +fully allocated size: 196608 + +converted image file size in bytes: 196608 + +=3D=3D raw input image with data (human) =3D=3D + +Formatting 'TEST_DIR/t.qcow2', fmt=3DIMGFMT size=3D1073741824 +required size: 393216 +fully allocated size: 1074135040 +wrote 512/512 bytes at offset 512 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 65536/65536 bytes at offset 65536 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 64512/64512 bytes at offset 134217728 +63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +required size: 589824 +fully allocated size: 1074135040 + +converted image file size in bytes: 524288 + +=3D=3D raw input image and a backing file (human) =3D=3D + +required size: 1074135040 +fully allocated size: 1074135040 + +=3D=3D raw input image and preallocation (human) =3D=3D + +required size: 1074135040 +fully allocated size: 1074135040 + +converted image file size in bytes: 1074135040 + +=3D=3D Fully-allocated raw input image (human) =3D=3D + +Formatting 'TEST_DIR/t.qcow2', fmt=3DIMGFMT size=3D8388608 +wrote 8388608/8388608 bytes at offset 0 +8 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +required size: 8716288 +fully allocated size: 8716288 + +converted image file size in bytes: 8716288 + +=3D=3D Size calculation for a new file (json) =3D=3D + +{ + "required": 196608, + "fully-allocated": 196608 +} +{ + "required": 589824, + "fully-allocated": 2148073472 +} +{ + "required": 10747904, + "fully-allocated": 68730224640 +} +{ + "required": 42205184, + "fully-allocated": 274920112128 +} +{ + "required": 168034304, + "fully-allocated": 1099679662080 +} +{ + "required": 343650009088, + "fully-allocated": 2252143463694336 +} +qemu-img: The image size is too large (try using a larger cluster size) + +=3D=3D Empty qcow2 input image (json) =3D=3D + +Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D0 +{ + "required": 196608, + "fully-allocated": 196608 +} + +converted image file size in bytes: 196608 + +=3D=3D qcow2 input image with data (json) =3D=3D + +Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D1073741824 +{ + "required": 393216, + "fully-allocated": 1074135040 +} +wrote 512/512 bytes at offset 512 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 65536/65536 bytes at offset 65536 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 64512/64512 bytes at offset 134217728 +63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{ + "required": 589824, + "fully-allocated": 1074135040 +} + +converted image file size in bytes: 524288 + +=3D=3D qcow2 input image with internal snapshot (json) =3D=3D + +{ + "required": 524288, + "fully-allocated": 1074135040 +} + +converted image file size in bytes: 458752 + +=3D=3D qcow2 input image and a backing file (json) =3D=3D + +{ + "required": 1074135040, + "fully-allocated": 1074135040 +} + +=3D=3D qcow2 input image and preallocation (json) =3D=3D + +{ + "required": 1074135040, + "fully-allocated": 1074135040 +} + +converted image file size in bytes: 1074135040 + +=3D=3D Fully-allocated qcow2 input image (json) =3D=3D + +Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D8388608 +wrote 8388608/8388608 bytes at offset 0 +8 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{ + "required": 8716288, + "fully-allocated": 8716288 +} + +converted image file size in bytes: 8716288 + +=3D=3D Empty raw input image (json) =3D=3D + +Formatting 'TEST_DIR/t.qcow2', fmt=3DIMGFMT size=3D0 +{ + "required": 196608, + "fully-allocated": 196608 +} + +converted image file size in bytes: 196608 + +=3D=3D raw input image with data (json) =3D=3D + +Formatting 'TEST_DIR/t.qcow2', fmt=3DIMGFMT size=3D1073741824 +{ + "required": 393216, + "fully-allocated": 1074135040 +} +wrote 512/512 bytes at offset 512 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 65536/65536 bytes at offset 65536 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 64512/64512 bytes at offset 134217728 +63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{ + "required": 589824, + "fully-allocated": 1074135040 +} + +converted image file size in bytes: 524288 + +=3D=3D raw input image and a backing file (json) =3D=3D + +{ + "required": 1074135040, + "fully-allocated": 1074135040 +} + +=3D=3D raw input image and preallocation (json) =3D=3D + +{ + "required": 1074135040, + "fully-allocated": 1074135040 +} + +converted image file size in bytes: 1074135040 + +=3D=3D Fully-allocated raw input image (json) =3D=3D + +Formatting 'TEST_DIR/t.qcow2', fmt=3DIMGFMT size=3D8388608 +wrote 8388608/8388608 bytes at offset 0 +8 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{ + "required": 8716288, + "fully-allocated": 8716288 +} + +converted image file size in bytes: 8716288 +*** done diff --git a/tests/qemu-iotests/178.out.raw b/tests/qemu-iotests/178.out.raw new file mode 100644 index 0000000..6478365 --- /dev/null +++ b/tests/qemu-iotests/178.out.raw @@ -0,0 +1,158 @@ +QA output created by 178 +=3D=3D Input validation =3D=3D + +Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D1073741824 +qemu-img: Either --size N or one filename must be specified. +qemu-img: --size N cannot be used together with a filename. +qemu-img: At most one filename argument is allowed. +qemu-img: --object, --image-opts, -f, and -l require a filename argument. +qemu-img: --object, --image-opts, -f, and -l require a filename argument. +qemu-img: --object, --image-opts, -f, and -l require a filename argument. +qemu-img: --object, --image-opts, -f, and -l require a filename argument. +qemu-img: Invalid option list: , +qemu-img: Invalid parameter 'snapshot.foo' +qemu-img: Failed in parsing snapshot param 'snapshot.foo' +qemu-img: --output must be used with human or json as argument. +qemu-img: Image size must be less than 8 EiB! +qemu-img: Unknown file format 'foo' + +=3D=3D Size calculation for a new file (human) =3D=3D + +required size: 0 +fully allocated size: 0 +required size: 2147483648 +fully allocated size: 2147483648 +required size: 68719476736 +fully allocated size: 68719476736 +required size: 274877906944 +fully allocated size: 274877906944 +required size: 1099511627776 +fully allocated size: 1099511627776 +required size: 2251799813685248 +fully allocated size: 2251799813685248 +required size: 8070450532247928832 +fully allocated size: 8070450532247928832 + +=3D=3D Empty raw input image (human) =3D=3D + +Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D0 +required size: 0 +fully allocated size: 0 + +converted image file size in bytes: 0 + +=3D=3D raw input image with data (human) =3D=3D + +Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D1073741824 +required size: 1073741824 +fully allocated size: 1073741824 +wrote 512/512 bytes at offset 512 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 65536/65536 bytes at offset 65536 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 64512/64512 bytes at offset 134217728 +63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +required size: 1073741824 +fully allocated size: 1073741824 + +converted image file size in bytes: 1073741824 + +=3D=3D raw input image and preallocation (human) =3D=3D + +required size: 1073741824 +fully allocated size: 1073741824 + +converted image file size in bytes: 1073741824 + +=3D=3D Fully-allocated raw input image (human) =3D=3D + +Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D8388608 +wrote 8388608/8388608 bytes at offset 0 +8 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +required size: 8388608 +fully allocated size: 8388608 + +converted image file size in bytes: 8388608 + +=3D=3D Size calculation for a new file (json) =3D=3D + +{ + "required": 0, + "fully-allocated": 0 +} +{ + "required": 2147483648, + "fully-allocated": 2147483648 +} +{ + "required": 68719476736, + "fully-allocated": 68719476736 +} +{ + "required": 274877906944, + "fully-allocated": 274877906944 +} +{ + "required": 1099511627776, + "fully-allocated": 1099511627776 +} +{ + "required": 2251799813685248, + "fully-allocated": 2251799813685248 +} +{ + "required": 8070450532247928832, + "fully-allocated": 8070450532247928832 +} + +=3D=3D Empty raw input image (json) =3D=3D + +Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D0 +{ + "required": 0, + "fully-allocated": 0 +} + +converted image file size in bytes: 0 + +=3D=3D raw input image with data (json) =3D=3D + +Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D1073741824 +{ + "required": 1073741824, + "fully-allocated": 1073741824 +} +wrote 512/512 bytes at offset 512 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 65536/65536 bytes at offset 65536 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 64512/64512 bytes at offset 134217728 +63 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{ + "required": 1073741824, + "fully-allocated": 1073741824 +} + +converted image file size in bytes: 1073741824 + +=3D=3D raw input image and preallocation (json) =3D=3D + +{ + "required": 1073741824, + "fully-allocated": 1073741824 +} + +converted image file size in bytes: 1073741824 + +=3D=3D Fully-allocated raw input image (json) =3D=3D + +Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D8388608 +wrote 8388608/8388608 bytes at offset 0 +8 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +{ + "required": 8388608, + "fully-allocated": 8388608 +} + +converted image file size in bytes: 8388608 +*** done diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index 318ae74..c69efb5 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -171,6 +171,7 @@ 175 auto quick 176 rw auto backing 177 rw auto quick +178 auto quick 179 rw auto quick 181 rw auto migration 182 rw auto quick --=20 2.9.4