From nobody Mon May 6 12:43:05 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; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1544183787975130.51520953244074; Fri, 7 Dec 2018 03:56:27 -0800 (PST) Received: from localhost ([::1]:45566 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gVEjx-0008E8-D6 for importer@patchew.org; Fri, 07 Dec 2018 06:56:17 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51772) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gVEhh-0006yH-Fx for qemu-devel@nongnu.org; Fri, 07 Dec 2018 06:53:58 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gVEhg-0004aN-9O for qemu-devel@nongnu.org; Fri, 07 Dec 2018 06:53:57 -0500 Received: from mx1.redhat.com ([209.132.183.28]:46078) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gVEhd-0004YJ-B0; Fri, 07 Dec 2018 06:53:53 -0500 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 ABAE2308FF0C; Fri, 7 Dec 2018 11:53:52 +0000 (UTC) Received: from linux.fritz.box.com (ovpn-117-248.ams2.redhat.com [10.36.117.248]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3F8886BC2F; Fri, 7 Dec 2018 11:53:51 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 7 Dec 2018 12:53:39 +0100 Message-Id: <20181207115343.6747-2-kwolf@redhat.com> In-Reply-To: <20181207115343.6747-1-kwolf@redhat.com> References: <20181207115343.6747-1-kwolf@redhat.com> MIME-Version: 1.0 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.49]); Fri, 07 Dec 2018 11:53:52 +0000 (UTC) Content-Transfer-Encoding: quoted-printable 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 v4 1/5] vmdk: Refactor vmdk_create_extent 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: kwolf@redhat.com, qemu-devel@nongnu.org, armbru@redhat.com, mreitz@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" From: Fam Zheng The extracted vmdk_init_extent takes a BlockBackend object and initializes the format metadata. It is the common part between "qemu-img create" and "blockdev-create". Add a "BlockBackend *pbb" parameter to vmdk_create_extent, to return the opened BB to the caller in the next patch. Signed-off-by: Fam Zheng Reviewed-by: Markus Armbruster Signed-off-by: Kevin Wolf --- block/vmdk.c | 69 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 26 deletions(-) diff --git a/block/vmdk.c b/block/vmdk.c index 2c9e86d98f..32fc2c84b3 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -1741,35 +1741,17 @@ static int coroutine_fn vmdk_co_pwrite_zeroes(Block= DriverState *bs, return ret; } =20 -static int vmdk_create_extent(const char *filename, int64_t filesize, - bool flat, bool compress, bool zeroed_grain, - QemuOpts *opts, Error **errp) +static int vmdk_init_extent(BlockBackend *blk, + int64_t filesize, bool flat, + bool compress, bool zeroed_grain, + Error **errp) { int ret, i; - BlockBackend *blk =3D NULL; VMDK4Header header; - Error *local_err =3D NULL; uint32_t tmp, magic, grains, gd_sectors, gt_size, gt_count; uint32_t *gd_buf =3D NULL; int gd_buf_size; =20 - ret =3D bdrv_create_file(filename, opts, &local_err); - if (ret < 0) { - error_propagate(errp, local_err); - goto exit; - } - - blk =3D blk_new_open(filename, NULL, NULL, - BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, - &local_err); - if (blk =3D=3D NULL) { - error_propagate(errp, local_err); - ret =3D -EIO; - goto exit; - } - - blk_set_allow_write_beyond_eof(blk, true); - if (flat) { ret =3D blk_truncate(blk, filesize, PREALLOC_MODE_OFF, errp); goto exit; @@ -1863,15 +1845,50 @@ static int vmdk_create_extent(const char *filename,= int64_t filesize, gd_buf, gd_buf_size, 0); if (ret < 0) { error_setg(errp, QERR_IO_ERROR); - goto exit; } =20 ret =3D 0; +exit: + g_free(gd_buf); + return ret; +} + +static int vmdk_create_extent(const char *filename, int64_t filesize, + bool flat, bool compress, bool zeroed_grain, + BlockBackend **pbb, + QemuOpts *opts, Error **errp) +{ + int ret; + BlockBackend *blk =3D NULL; + Error *local_err =3D NULL; + + ret =3D bdrv_create_file(filename, opts, &local_err); + if (ret < 0) { + error_propagate(errp, local_err); + goto exit; + } + + blk =3D blk_new_open(filename, NULL, NULL, + BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, + &local_err); + if (blk =3D=3D NULL) { + error_propagate(errp, local_err); + ret =3D -EIO; + goto exit; + } + + blk_set_allow_write_beyond_eof(blk, true); + + ret =3D vmdk_init_extent(blk, filesize, flat, compress, zeroed_grain, = errp); exit: if (blk) { - blk_unref(blk); + if (pbb) { + *pbb =3D blk; + } else { + blk_unref(blk); + blk =3D NULL; + } } - g_free(gd_buf); return ret; } =20 @@ -2094,7 +2111,7 @@ static int coroutine_fn vmdk_co_create_opts(const cha= r *filename, QemuOpts *opts snprintf(ext_filename, PATH_MAX, "%s%s", path, desc_filename); =20 if (vmdk_create_extent(ext_filename, size, - flat, compress, zeroed_grain, opts, errp)) { + flat, compress, zeroed_grain, NULL, opts, e= rrp)) { ret =3D -EINVAL; goto exit; } --=20 2.19.2 From nobody Mon May 6 12:43:05 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; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1544183794338958.8155701994446; Fri, 7 Dec 2018 03:56:34 -0800 (PST) Received: from localhost ([::1]:45568 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gVEkD-0008R0-26 for importer@patchew.org; Fri, 07 Dec 2018 06:56:33 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51855) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gVEhs-00074r-DE for qemu-devel@nongnu.org; Fri, 07 Dec 2018 06:54:11 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gVEhn-0005NW-F6 for qemu-devel@nongnu.org; Fri, 07 Dec 2018 06:54:06 -0500 Received: from mx1.redhat.com ([209.132.183.28]:49496) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gVEhg-0004aE-Od; Fri, 07 Dec 2018 06:53:56 -0500 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 12F34307DAB6; Fri, 7 Dec 2018 11:53:56 +0000 (UTC) Received: from linux.fritz.box.com (ovpn-117-248.ams2.redhat.com [10.36.117.248]) by smtp.corp.redhat.com (Postfix) with ESMTP id 03FAE6BC2F; Fri, 7 Dec 2018 11:53:52 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 7 Dec 2018 12:53:40 +0100 Message-Id: <20181207115343.6747-3-kwolf@redhat.com> In-Reply-To: <20181207115343.6747-1-kwolf@redhat.com> References: <20181207115343.6747-1-kwolf@redhat.com> MIME-Version: 1.0 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.42]); Fri, 07 Dec 2018 11:53:56 +0000 (UTC) Content-Transfer-Encoding: quoted-printable 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 v4 2/5] vmdk: Implement .bdrv_co_create callback 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: kwolf@redhat.com, qemu-devel@nongnu.org, armbru@redhat.com, mreitz@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" From: Fam Zheng This makes VMDK support blockdev-create. The implementation reuses the image creation code in vmdk_co_create_opts which now acceptes a callback pointer to "retrieve" BlockBackend pointers from the caller. This way we separate the logic between file/extent acquisition and initialization. The QAPI command parameters are mostly the same as the old create_opts except the dropped legacy @compat6 switch, which is redundant with @hwversion. Signed-off-by: Fam Zheng Signed-off-by: Kevin Wolf Reviewed-by: Markus Armbruster --- qapi/block-core.json | 70 +++++++ qapi/qapi-schema.json | 16 +- block/vmdk.c | 448 ++++++++++++++++++++++++++++++------------ 3 files changed, 400 insertions(+), 134 deletions(-) diff --git a/qapi/block-core.json b/qapi/block-core.json index d4fe710836..0793550cf2 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -4021,6 +4021,75 @@ 'size': 'size', '*cluster-size' : 'size' } } =20 +## +# @BlockdevVmdkSubformat: +# +# Subformat options for VMDK images +# +# @monolithicSparse: Single file image with sparse cluster allocation +# +# @monolithicFlat: Single flat data image and a descriptor file +# +# @twoGbMaxExtentSparse: Data is split into 2GB (per virtual LBA) sparse e= xtent +# files, in addition to a descriptor file +# +# @twoGbMaxExtentFlat: Data is split into 2GB (per virtual LBA) flat ext= ent +# files, in addition to a descriptor file +# +# @streamOptimized: Single file image sparse cluster allocation, opti= mized +# for streaming over network. +# +# Since: 4.0 +## +{ 'enum': 'BlockdevVmdkSubformat', + 'data': [ 'monolithicSparse', 'monolithicFlat', 'twoGbMaxExtentSparse', + 'twoGbMaxExtentFlat', 'streamOptimized'] } + +## +# @BlockdevVmdkAdapterType: +# +# Adapter type info for VMDK images +# +# Since: 4.0 +## +{ 'enum': 'BlockdevVmdkAdapterType', + 'data': [ 'ide', 'buslogic', 'lsilogic', 'legacyESX'] } + +## +# @BlockdevCreateOptionsVmdk: +# +# Driver specific image creation options for VMDK. +# +# @file Where to store the new image file. This refers to the image +# file for monolithcSparse and streamOptimized format, or the +# descriptor file for other formats. +# @size Size of the virtual disk in bytes +# @extents Where to store the data extents. Required for monolithcFla= t, +# twoGbMaxExtentSparse and twoGbMaxExtentFlat formats. For +# monolithicFlat, only one entry is required; for +# twoGbMaxExtent* formats, the number of entries required is +# calculated as extent_number =3D virtual_size / 2GB. +# @subformat The subformat of the VMDK image. Default: "monolithicSpars= e". +# @backing-file The path of backing file. Default: no backing file is used. +# @adapter-type The adapter type used to fill in the descriptor. Default: = ide. +# @hwversion Hardware version. The meaningful options are "4" or "6". +# Default: "4". +# @zeroed-grain Whether to enable zeroed-grain feature for sparse subforma= ts. +# Default: false. +# +# Since: 4.0 +## +{ 'struct': 'BlockdevCreateOptionsVmdk', + 'data': { 'file': 'BlockdevRef', + 'size': 'size', + '*extents': ['BlockdevRef'], + '*subformat': 'BlockdevVmdkSubformat', + '*backing-file': 'str', + '*adapter-type': 'BlockdevVmdkAdapterType', + '*hwversion': 'str', + '*zeroed-grain': 'bool' } } + + ## # @SheepdogRedundancyType: # @@ -4215,6 +4284,7 @@ 'ssh': 'BlockdevCreateOptionsSsh', 'vdi': 'BlockdevCreateOptionsVdi', 'vhdx': 'BlockdevCreateOptionsVhdx', + 'vmdk': 'BlockdevCreateOptionsVmdk', 'vpc': 'BlockdevCreateOptionsVpc' } } =20 diff --git a/qapi/qapi-schema.json b/qapi/qapi-schema.json index 65b6dc2f6f..339f9b315b 100644 --- a/qapi/qapi-schema.json +++ b/qapi/qapi-schema.json @@ -63,13 +63,15 @@ 'query-tpm-types', 'ringbuf-read' ], 'name-case-whitelist': [ - 'ACPISlotType', # DIMM, visible through query-acpi-ospm-st= atus - 'CpuInfoMIPS', # PC, visible through query-cpu - 'CpuInfoTricore', # PC, visible through query-cpu - 'QapiErrorClass', # all members, visible through errors - 'UuidInfo', # UUID, visible through query-uuid - 'X86CPURegister32', # all members, visible indirectly through = qom-get - 'q_obj_CpuInfo-base' # CPU, visible through query-cpu + 'ACPISlotType', # DIMM, visible through query-acpi-osp= m-status + 'CpuInfoMIPS', # PC, visible through query-cpu + 'CpuInfoTricore', # PC, visible through query-cpu + 'BlockdevVmdkSubformat', # all members, to match VMDK spec spel= lings + 'BlockdevVmdkAdapterType', # legacyESX, to match VMDK spec spelli= ngs + 'QapiErrorClass', # all members, visible through errors + 'UuidInfo', # UUID, visible through query-uuid + 'X86CPURegister32', # all members, visible indirectly thro= ugh qom-get + 'q_obj_CpuInfo-base' # CPU, visible through query-cpu ] } } =20 # Documentation generated with qapi-gen.py is in source order, with diff --git a/block/vmdk.c b/block/vmdk.c index 32fc2c84b3..5a162ee85c 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -1932,33 +1932,56 @@ static int filename_decompose(const char *filename,= char *path, char *prefix, return VMDK_OK; } =20 -static int coroutine_fn vmdk_co_create_opts(const char *filename, QemuOpts= *opts, - Error **errp) +/* + * idx =3D=3D 0: get or create the descriptor file (also the image file if= in a + * non-split format. + * idx >=3D 1: get the n-th extent if in a split subformat + */ +typedef BlockBackend *(*vmdk_create_extent_fn)(int64_t size, + int idx, + bool flat, + bool split, + bool compress, + bool zeroed_grain, + void *opaque, + Error **errp); + +static void vmdk_desc_add_extent(GString *desc, + const char *extent_line_fmt, + int64_t size, const char *filename) +{ + char *basename =3D g_path_get_basename(filename); + + g_string_append_printf(desc, extent_line_fmt, + DIV_ROUND_UP(size, BDRV_SECTOR_SIZE), basename); + g_free(basename); +} + +static int coroutine_fn vmdk_co_do_create(int64_t size, + BlockdevVmdkSubformat subformat, + BlockdevVmdkAdapterType adapter_= type, + const char *backing_file, + const char *hw_version, + bool compat6, + bool zeroed_grain, + vmdk_create_extent_fn extent_fn, + void *opaque, + Error **errp) { - int idx =3D 0; - BlockBackend *new_blk =3D NULL; + int extent_idx; + BlockBackend *blk =3D NULL; Error *local_err =3D NULL; char *desc =3D NULL; - int64_t total_size =3D 0, filesize; - char *adapter_type =3D NULL; - char *backing_file =3D NULL; - char *hw_version =3D NULL; - char *fmt =3D NULL; int ret =3D 0; bool flat, split, compress; GString *ext_desc_lines; - char *path =3D g_malloc0(PATH_MAX); - char *prefix =3D g_malloc0(PATH_MAX); - char *postfix =3D g_malloc0(PATH_MAX); - char *desc_line =3D g_malloc0(BUF_SIZE); - char *ext_filename =3D g_malloc0(PATH_MAX); - char *desc_filename =3D g_malloc0(PATH_MAX); const int64_t split_size =3D 0x80000000; /* VMDK has constant split s= ize */ - const char *desc_extent_line; + int64_t extent_size; + int64_t created_size =3D 0; + const char *extent_line_fmt; char *parent_desc_line =3D g_malloc0(BUF_SIZE); uint32_t parent_cid =3D 0xffffffff; uint32_t number_heads =3D 16; - bool zeroed_grain =3D false; uint32_t desc_offset =3D 0, desc_len; const char desc_template[] =3D "# Disk DescriptorFile\n" @@ -1982,71 +2005,35 @@ static int coroutine_fn vmdk_co_create_opts(const c= har *filename, QemuOpts *opts =20 ext_desc_lines =3D g_string_new(NULL); =20 - if (filename_decompose(filename, path, prefix, postfix, PATH_MAX, errp= )) { - ret =3D -EINVAL; - goto exit; - } /* Read out options */ - total_size =3D ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0), - BDRV_SECTOR_SIZE); - adapter_type =3D qemu_opt_get_del(opts, BLOCK_OPT_ADAPTER_TYPE); - backing_file =3D qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE); - hw_version =3D qemu_opt_get_del(opts, BLOCK_OPT_HWVERSION); - if (qemu_opt_get_bool_del(opts, BLOCK_OPT_COMPAT6, false)) { - if (strcmp(hw_version, "undefined")) { + if (compat6) { + if (hw_version) { error_setg(errp, "compat6 cannot be enabled with hwversion set"); ret =3D -EINVAL; goto exit; } - g_free(hw_version); - hw_version =3D g_strdup("6"); - } - if (strcmp(hw_version, "undefined") =3D=3D 0) { - g_free(hw_version); - hw_version =3D g_strdup("4"); + hw_version =3D "6"; } - fmt =3D qemu_opt_get_del(opts, BLOCK_OPT_SUBFMT); - if (qemu_opt_get_bool_del(opts, BLOCK_OPT_ZEROED_GRAIN, false)) { - zeroed_grain =3D true; + if (!hw_version) { + hw_version =3D "4"; } =20 - if (!adapter_type) { - adapter_type =3D g_strdup("ide"); - } else if (strcmp(adapter_type, "ide") && - strcmp(adapter_type, "buslogic") && - strcmp(adapter_type, "lsilogic") && - strcmp(adapter_type, "legacyESX")) { - error_setg(errp, "Unknown adapter type: '%s'", adapter_type); - ret =3D -EINVAL; - goto exit; - } - if (strcmp(adapter_type, "ide") !=3D 0) { + if (adapter_type !=3D BLOCKDEV_VMDK_ADAPTER_TYPE_IDE) { /* that's the number of heads with which vmware operates when creating, exporting, etc. vmdk files with a non-ide adapter typ= e */ number_heads =3D 255; } - if (!fmt) { - /* Default format to monolithicSparse */ - fmt =3D g_strdup("monolithicSparse"); - } else if (strcmp(fmt, "monolithicFlat") && - strcmp(fmt, "monolithicSparse") && - strcmp(fmt, "twoGbMaxExtentSparse") && - strcmp(fmt, "twoGbMaxExtentFlat") && - strcmp(fmt, "streamOptimized")) { - error_setg(errp, "Unknown subformat: '%s'", fmt); - ret =3D -EINVAL; - goto exit; - } - split =3D !(strcmp(fmt, "twoGbMaxExtentFlat") && - strcmp(fmt, "twoGbMaxExtentSparse")); - flat =3D !(strcmp(fmt, "monolithicFlat") && - strcmp(fmt, "twoGbMaxExtentFlat")); - compress =3D !strcmp(fmt, "streamOptimized"); + split =3D (subformat =3D=3D BLOCKDEV_VMDK_SUBFORMAT_TWOGBMAXEXTENTFLAT= ) || + (subformat =3D=3D BLOCKDEV_VMDK_SUBFORMAT_TWOGBMAXEXTENTSPARSE= ); + flat =3D (subformat =3D=3D BLOCKDEV_VMDK_SUBFORMAT_MONOLITHICFLAT) || + (subformat =3D=3D BLOCKDEV_VMDK_SUBFORMAT_TWOGBMAXEXTENTFLAT); + compress =3D subformat =3D=3D BLOCKDEV_VMDK_SUBFORMAT_STREAMOPTIMIZED; + if (flat) { - desc_extent_line =3D "RW %" PRId64 " FLAT \"%s\" 0\n"; + extent_line_fmt =3D "RW %" PRId64 " FLAT \"%s\" 0\n"; } else { - desc_extent_line =3D "RW %" PRId64 " SPARSE \"%s\"\n"; + extent_line_fmt =3D "RW %" PRId64 " SPARSE \"%s\"\n"; } if (flat && backing_file) { error_setg(errp, "Flat image can't have backing file"); @@ -2058,10 +2045,34 @@ static int coroutine_fn vmdk_co_create_opts(const c= har *filename, QemuOpts *opts ret =3D -ENOTSUP; goto exit; } + + /* Create extents */ + if (split) { + extent_size =3D split_size; + } else { + extent_size =3D size; + } + if (!split && !flat) { + created_size =3D extent_size; + } else { + created_size =3D 0; + } + /* Get the descriptor file BDS */ + blk =3D extent_fn(created_size, 0, flat, split, compress, zeroed_grain, + opaque, errp); + if (!blk) { + ret =3D -EIO; + goto exit; + } + if (!split && !flat) { + vmdk_desc_add_extent(ext_desc_lines, extent_line_fmt, created_size, + blk_bs(blk)->filename); + } + if (backing_file) { - BlockBackend *blk; + BlockBackend *backing; char *full_backing =3D g_new0(char, PATH_MAX); - bdrv_get_full_backing_filename_from_filename(filename, backing_fil= e, + bdrv_get_full_backing_filename_from_filename(blk_bs(blk)->filename= , backing_file, full_backing, PATH_MA= X, &local_err); if (local_err) { @@ -2071,106 +2082,211 @@ static int coroutine_fn vmdk_co_create_opts(const= char *filename, QemuOpts *opts goto exit; } =20 - blk =3D blk_new_open(full_backing, NULL, NULL, - BDRV_O_NO_BACKING, errp); + backing =3D blk_new_open(full_backing, NULL, NULL, + BDRV_O_NO_BACKING, errp); g_free(full_backing); - if (blk =3D=3D NULL) { + if (backing =3D=3D NULL) { ret =3D -EIO; goto exit; } - if (strcmp(blk_bs(blk)->drv->format_name, "vmdk")) { - blk_unref(blk); + if (strcmp(blk_bs(backing)->drv->format_name, "vmdk")) { + error_setg(errp, "Invalid backing file format: %s. Must be vmd= k", + blk_bs(backing)->drv->format_name); + blk_unref(backing); ret =3D -EINVAL; goto exit; } - ret =3D vmdk_read_cid(blk_bs(blk), 0, &parent_cid); - blk_unref(blk); + ret =3D vmdk_read_cid(blk_bs(backing), 0, &parent_cid); + blk_unref(backing); if (ret) { + error_setg(errp, "Failed to read parent CID"); goto exit; } snprintf(parent_desc_line, BUF_SIZE, "parentFileNameHint=3D\"%s\"", backing_file); } - - /* Create extents */ - filesize =3D total_size; - while (filesize > 0) { - int64_t size =3D filesize; - - if (split && size > split_size) { - size =3D split_size; - } - if (split) { - snprintf(desc_filename, PATH_MAX, "%s-%c%03d%s", - prefix, flat ? 'f' : 's', ++idx, postfix); - } else if (flat) { - snprintf(desc_filename, PATH_MAX, "%s-flat%s", prefix, postfix= ); - } else { - snprintf(desc_filename, PATH_MAX, "%s%s", prefix, postfix); - } - snprintf(ext_filename, PATH_MAX, "%s%s", path, desc_filename); - - if (vmdk_create_extent(ext_filename, size, - flat, compress, zeroed_grain, NULL, opts, e= rrp)) { + extent_idx =3D 1; + while (created_size < size) { + BlockBackend *extent_blk; + int64_t cur_size =3D MIN(size - created_size, extent_size); + extent_blk =3D extent_fn(cur_size, extent_idx, flat, split, compre= ss, + zeroed_grain, opaque, errp); + if (!extent_blk) { ret =3D -EINVAL; goto exit; } - filesize -=3D size; - - /* Format description line */ - snprintf(desc_line, BUF_SIZE, - desc_extent_line, size / BDRV_SECTOR_SIZE, desc_filena= me); - g_string_append(ext_desc_lines, desc_line); + vmdk_desc_add_extent(ext_desc_lines, extent_line_fmt, cur_size, + blk_bs(extent_blk)->filename); + created_size +=3D cur_size; + extent_idx++; + blk_unref(extent_blk); } /* generate descriptor file */ desc =3D g_strdup_printf(desc_template, g_random_int(), parent_cid, - fmt, + BlockdevVmdkSubformat_str(subformat), parent_desc_line, ext_desc_lines->str, hw_version, - total_size / + size / (int64_t)(63 * number_heads * BDRV_SECTOR_S= IZE), number_heads, - adapter_type); + BlockdevVmdkAdapterType_str(adapter_type)); desc_len =3D strlen(desc); /* the descriptor offset =3D 0x200 */ if (!split && !flat) { desc_offset =3D 0x200; - } else { - ret =3D bdrv_create_file(filename, opts, &local_err); + } + + ret =3D blk_pwrite(blk, desc_offset, desc, desc_len, 0); + if (ret < 0) { + error_setg_errno(errp, -ret, "Could not write description"); + goto exit; + } + /* bdrv_pwrite write padding zeros to align to sector, we don't need t= hat + * for description file */ + if (desc_offset =3D=3D 0) { + ret =3D blk_truncate(blk, desc_len, PREALLOC_MODE_OFF, errp); if (ret < 0) { - error_propagate(errp, local_err); goto exit; } } + ret =3D 0; +exit: + if (blk) { + blk_unref(blk); + } + g_free(desc); + g_free(parent_desc_line); + g_string_free(ext_desc_lines, true); + return ret; +} =20 - new_blk =3D blk_new_open(filename, NULL, NULL, - BDRV_O_RDWR | BDRV_O_RESIZE | BDRV_O_PROTOCOL, - &local_err); - if (new_blk =3D=3D NULL) { - error_propagate(errp, local_err); - ret =3D -EIO; +typedef struct { + char *path; + char *prefix; + char *postfix; + QemuOpts *opts; +} VMDKCreateOptsData; + +static BlockBackend *vmdk_co_create_opts_cb(int64_t size, int idx, + bool flat, bool split, bool co= mpress, + bool zeroed_grain, void *opaqu= e, + Error **errp) +{ + BlockBackend *blk =3D NULL; + BlockDriverState *bs =3D NULL; + VMDKCreateOptsData *data =3D opaque; + char *ext_filename =3D NULL; + char *rel_filename =3D NULL; + + if (idx =3D=3D 0) { + rel_filename =3D g_strdup_printf("%s%s", data->prefix, data->postf= ix); + } else if (split) { + rel_filename =3D g_strdup_printf("%s-%c%03d%s", + data->prefix, + flat ? 'f' : 's', idx, data->postfi= x); + } else { + assert(idx =3D=3D 1); + rel_filename =3D g_strdup_printf("%s-flat%s", data->prefix, data->= postfix); + } + + ext_filename =3D g_strdup_printf("%s%s", data->path, rel_filename); + g_free(rel_filename); + + if (vmdk_create_extent(ext_filename, size, + flat, compress, zeroed_grain, &blk, data->opts, + errp)) { goto exit; } + bdrv_unref(bs); +exit: + g_free(ext_filename); + return blk; +} =20 - blk_set_allow_write_beyond_eof(new_blk, true); +static int coroutine_fn vmdk_co_create_opts(const char *filename, QemuOpts= *opts, + Error **errp) +{ + Error *local_err =3D NULL; + char *desc =3D NULL; + int64_t total_size =3D 0; + char *adapter_type =3D NULL; + BlockdevVmdkAdapterType adapter_type_enum; + char *backing_file =3D NULL; + char *hw_version =3D NULL; + char *fmt =3D NULL; + BlockdevVmdkSubformat subformat; + int ret =3D 0; + char *path =3D g_malloc0(PATH_MAX); + char *prefix =3D g_malloc0(PATH_MAX); + char *postfix =3D g_malloc0(PATH_MAX); + char *desc_line =3D g_malloc0(BUF_SIZE); + char *ext_filename =3D g_malloc0(PATH_MAX); + char *desc_filename =3D g_malloc0(PATH_MAX); + char *parent_desc_line =3D g_malloc0(BUF_SIZE); + bool zeroed_grain; + bool compat6; + VMDKCreateOptsData data; =20 - ret =3D blk_pwrite(new_blk, desc_offset, desc, desc_len, 0); - if (ret < 0) { - error_setg_errno(errp, -ret, "Could not write description"); + if (filename_decompose(filename, path, prefix, postfix, PATH_MAX, errp= )) { + ret =3D -EINVAL; goto exit; } - /* bdrv_pwrite write padding zeros to align to sector, we don't need t= hat - * for description file */ - if (desc_offset =3D=3D 0) { - ret =3D blk_truncate(new_blk, desc_len, PREALLOC_MODE_OFF, errp); + /* Read out options */ + total_size =3D ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0), + BDRV_SECTOR_SIZE); + adapter_type =3D qemu_opt_get_del(opts, BLOCK_OPT_ADAPTER_TYPE); + backing_file =3D qemu_opt_get_del(opts, BLOCK_OPT_BACKING_FILE); + hw_version =3D qemu_opt_get_del(opts, BLOCK_OPT_HWVERSION); + compat6 =3D qemu_opt_get_bool_del(opts, BLOCK_OPT_COMPAT6, false); + if (strcmp(hw_version, "undefined") =3D=3D 0) { + g_free(hw_version); + hw_version =3D g_strdup("4"); } -exit: - if (new_blk) { - blk_unref(new_blk); + fmt =3D qemu_opt_get_del(opts, BLOCK_OPT_SUBFMT); + zeroed_grain =3D qemu_opt_get_bool_del(opts, BLOCK_OPT_ZEROED_GRAIN, f= alse); + + if (adapter_type) { + adapter_type_enum =3D qapi_enum_parse(&BlockdevVmdkAdapterType_loo= kup, + adapter_type, + BLOCKDEV_VMDK_ADAPTER_TYPE_IDE, + &local_err); + if (local_err) { + error_propagate(errp, local_err); + ret =3D -EINVAL; + goto exit; + } + } else { + adapter_type_enum =3D BLOCKDEV_VMDK_ADAPTER_TYPE_IDE; } + + if (!fmt) { + /* Default format to monolithicSparse */ + subformat =3D BLOCKDEV_VMDK_SUBFORMAT_MONOLITHICSPARSE; + } else { + subformat =3D qapi_enum_parse(&BlockdevVmdkSubformat_lookup, + fmt, + BLOCKDEV_VMDK_SUBFORMAT_MONOLITHICSPAR= SE, + &local_err); + if (local_err) { + error_propagate(errp, local_err); + ret =3D -EINVAL; + goto exit; + } + } + data =3D (VMDKCreateOptsData){ + .prefix =3D prefix, + .postfix =3D postfix, + .path =3D path, + .opts =3D opts, + }; + ret =3D vmdk_co_do_create(total_size, subformat, adapter_type_enum, + backing_file, hw_version, compat6, zeroed_grai= n, + vmdk_co_create_opts_cb, &data, errp); + +exit: g_free(adapter_type); g_free(backing_file); g_free(hw_version); @@ -2183,7 +2299,84 @@ exit: g_free(ext_filename); g_free(desc_filename); g_free(parent_desc_line); - g_string_free(ext_desc_lines, true); + return ret; +} + +static BlockBackend *vmdk_co_create_cb(int64_t size, int idx, + bool flat, bool split, bool compres= s, + bool zeroed_grain, void *opaque, + Error **errp) +{ + int ret; + BlockDriverState *bs; + BlockBackend *blk; + BlockdevCreateOptionsVmdk *opts =3D opaque; + + if (idx =3D=3D 0) { + bs =3D bdrv_open_blockdev_ref(opts->file, errp); + } else { + int i; + BlockdevRefList *list =3D opts->extents; + for (i =3D 1; i < idx; i++) { + if (!list || !list->next) { + error_setg(errp, "Extent [%d] not specified", i); + return NULL; + } + list =3D list->next; + } + if (!list) { + error_setg(errp, "Extent [%d] not specified", idx - 1); + return NULL; + } + bs =3D bdrv_open_blockdev_ref(list->value, errp); + } + if (!bs) { + return NULL; + } + blk =3D blk_new(BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE | BLK_PERM_R= ESIZE, + BLK_PERM_ALL); + if (blk_insert_bs(blk, bs, errp)) { + bdrv_unref(bs); + return NULL; + } + blk_set_allow_write_beyond_eof(blk, true); + bdrv_unref(bs); + + ret =3D vmdk_init_extent(blk, size, flat, compress, zeroed_grain, errp= ); + if (ret) { + blk_unref(blk); + blk =3D NULL; + } + return blk; +} + +static int coroutine_fn vmdk_co_create(BlockdevCreateOptions *create_optio= ns, + Error **errp) +{ + int ret; + BlockdevCreateOptionsVmdk *opts; + + opts =3D &create_options->u.vmdk; + + /* Validate options */ + if (!QEMU_IS_ALIGNED(opts->size, BDRV_SECTOR_SIZE)) { + error_setg(errp, "Image size must be a multiple of 512 bytes"); + ret =3D -EINVAL; + goto out; + } + + ret =3D vmdk_co_do_create(opts->size, + opts->subformat, + opts->adapter_type, + opts->backing_file, + opts->hwversion, + false, + opts->zeroed_grain, + vmdk_co_create_cb, + opts, errp); + return ret; + +out: return ret; } =20 @@ -2451,6 +2644,7 @@ static BlockDriver bdrv_vmdk =3D { .bdrv_co_pwrite_zeroes =3D vmdk_co_pwrite_zeroes, .bdrv_close =3D vmdk_close, .bdrv_co_create_opts =3D vmdk_co_create_opts, + .bdrv_co_create =3D vmdk_co_create, .bdrv_co_flush_to_disk =3D vmdk_co_flush, .bdrv_co_block_status =3D vmdk_co_block_status, .bdrv_get_allocated_file_size =3D vmdk_get_allocated_file_size, --=20 2.19.2 From nobody Mon May 6 12:43:05 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; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1544183951934419.87542163742273; Fri, 7 Dec 2018 03:59:11 -0800 (PST) Received: from localhost ([::1]:45583 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gVEmk-0003v1-SE for importer@patchew.org; Fri, 07 Dec 2018 06:59:10 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51865) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gVEht-00075N-3y for qemu-devel@nongnu.org; Fri, 07 Dec 2018 06:54:14 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gVEhs-0005oh-BY for qemu-devel@nongnu.org; Fri, 07 Dec 2018 06:54:09 -0500 Received: from mx1.redhat.com ([209.132.183.28]:45090) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gVEhk-0004rL-DS; Fri, 07 Dec 2018 06:54:00 -0500 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 A4F77315486E; Fri, 7 Dec 2018 11:53:59 +0000 (UTC) Received: from linux.fritz.box.com (ovpn-117-248.ams2.redhat.com [10.36.117.248]) by smtp.corp.redhat.com (Postfix) with ESMTP id 611616BC2F; Fri, 7 Dec 2018 11:53:56 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 7 Dec 2018 12:53:41 +0100 Message-Id: <20181207115343.6747-4-kwolf@redhat.com> In-Reply-To: <20181207115343.6747-1-kwolf@redhat.com> References: <20181207115343.6747-1-kwolf@redhat.com> MIME-Version: 1.0 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.41]); Fri, 07 Dec 2018 11:53:59 +0000 (UTC) Content-Transfer-Encoding: quoted-printable 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 v4 3/5] iotests: Filter cid numbers in VMDK extent info 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: kwolf@redhat.com, qemu-devel@nongnu.org, armbru@redhat.com, mreitz@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" From: Fam Zheng Signed-off-by: Fam Zheng Signed-off-by: Kevin Wolf --- tests/qemu-iotests/common.filter | 1 + tests/qemu-iotests/iotests.py | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.f= ilter index 2031e353a5..1aa7d57140 100644 --- a/tests/qemu-iotests/common.filter +++ b/tests/qemu-iotests/common.filter @@ -165,6 +165,7 @@ _filter_img_info() -e "/table_size: [0-9]\\+/d" \ -e "/compat: '[^']*'/d" \ -e "/compat6: \\(on\\|off\\)/d" \ + -e "s/cid: [0-9]\+/cid: XXXXXXXXXX/" \ -e "/static: \\(on\\|off\\)/d" \ -e "/zeroed_grain: \\(on\\|off\\)/d" \ -e "/subformat: '[^']*'/d" \ diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py index d537538ba0..4142937239 100644 --- a/tests/qemu-iotests/iotests.py +++ b/tests/qemu-iotests/iotests.py @@ -248,6 +248,7 @@ def filter_img_info(output, filename): .replace(imgfmt, 'IMGFMT') line =3D re.sub('iters: [0-9]+', 'iters: XXX', line) line =3D re.sub('uuid: [-a-f0-9]+', 'uuid: XXXXXXXX-XXXX-XXXX-XXXX= -XXXXXXXXXXXX', line) + line =3D re.sub('cid: [0-9]+', 'cid: XXXXXXXXXX', line) lines.append(line) return '\n'.join(lines) =20 --=20 2.19.2 From nobody Mon May 6 12:43:05 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; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 154418393795512.354861034324585; Fri, 7 Dec 2018 03:58:57 -0800 (PST) Received: from localhost ([::1]:45582 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gVEmW-0002nA-JX for importer@patchew.org; Fri, 07 Dec 2018 06:58:56 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51912) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gVEhy-0007A6-L2 for qemu-devel@nongnu.org; Fri, 07 Dec 2018 06:54:16 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gVEhw-00066a-AO for qemu-devel@nongnu.org; Fri, 07 Dec 2018 06:54:14 -0500 Received: from mx1.redhat.com ([209.132.183.28]:46124) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gVEhm-00057T-9T; Fri, 07 Dec 2018 06:54:02 -0500 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 963483086258; Fri, 7 Dec 2018 11:54:01 +0000 (UTC) Received: from linux.fritz.box.com (ovpn-117-248.ams2.redhat.com [10.36.117.248]) by smtp.corp.redhat.com (Postfix) with ESMTP id F127A69214; Fri, 7 Dec 2018 11:53:59 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 7 Dec 2018 12:53:42 +0100 Message-Id: <20181207115343.6747-5-kwolf@redhat.com> In-Reply-To: <20181207115343.6747-1-kwolf@redhat.com> References: <20181207115343.6747-1-kwolf@redhat.com> MIME-Version: 1.0 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.49]); Fri, 07 Dec 2018 11:54:01 +0000 (UTC) Content-Transfer-Encoding: quoted-printable 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 v4 4/5] iotests: Add VMDK tests for blockdev-create 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: kwolf@redhat.com, qemu-devel@nongnu.org, armbru@redhat.com, mreitz@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Signed-off-by: Fam Zheng Signed-off-by: Kevin Wolf --- tests/qemu-iotests/237 | 233 +++++++++++++++++++++++++ tests/qemu-iotests/237.out | 347 +++++++++++++++++++++++++++++++++++++ tests/qemu-iotests/group | 1 + 3 files changed, 581 insertions(+) create mode 100755 tests/qemu-iotests/237 create mode 100644 tests/qemu-iotests/237.out diff --git a/tests/qemu-iotests/237 b/tests/qemu-iotests/237 new file mode 100755 index 0000000000..e04a1ac6be --- /dev/null +++ b/tests/qemu-iotests/237 @@ -0,0 +1,233 @@ +#!/usr/bin/env python +# +# Test vmdk and file image creation +# +# Copyright (C) 2018 Red Hat, Inc. +# +# Creator/Owner: Kevin Wolf +# +# 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 . +# + +import iotests +from iotests import imgfmt + +iotests.verify_image_format(supported_fmts=3D['vmdk']) + +def blockdev_create(vm, options): + result =3D vm.qmp_log('blockdev-create', job_id=3D'job0', options=3Dop= tions) + + if 'return' in result: + assert result['return'] =3D=3D {} + vm.run_job('job0') + iotests.log("") + +with iotests.FilePath('t.vmdk') as disk_path, \ + iotests.FilePath('t.vmdk.1') as extent1_path, \ + iotests.FilePath('t.vmdk.2') as extent2_path, \ + iotests.FilePath('t.vmdk.3') as extent3_path, \ + iotests.VM() as vm: + + # + # Successful image creation (defaults) + # + iotests.log("=3D=3D=3D Successful image creation (defaults) =3D=3D=3D") + iotests.log("") + + size =3D 5 * 1024 * 1024 * 1024 + + vm.launch() + blockdev_create(vm, { 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) + + vm.qmp_log('blockdev-add', driver=3D'file', filename=3Ddisk_path, + node_name=3D'imgfile') + + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'imgfile', + 'size': size }) + vm.shutdown() + + iotests.img_info_log(disk_path) + + # + # Successful image creation (inline blockdev-add, explicit defaults) + # + iotests.log("=3D=3D=3D Successful image creation (inline blockdev-add,= explicit defaults) =3D=3D=3D") + iotests.log("") + + # Choose a different size to show that we got a new image + size =3D 64 * 1024 * 1024 + + vm.launch() + blockdev_create(vm, { 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) + + blockdev_create(vm, { 'driver': imgfmt, + 'file': { + 'driver': 'file', + 'filename': disk_path, + }, + 'size': size, + 'extents': [], + 'subformat': 'monolithicSparse', + 'adapter-type': 'ide', + 'hwversion': '4', + 'zeroed-grain': False }) + vm.shutdown() + + iotests.img_info_log(disk_path) + + # + # Successful image creation (non-default options) + # + iotests.log("=3D=3D=3D Successful image creation (with non-default opt= ions) =3D=3D=3D") + iotests.log("") + + # Choose a different size to show that we got a new image + size =3D 32 * 1024 * 1024 + + vm.launch() + blockdev_create(vm, { 'driver': 'file', + 'filename': disk_path, + 'size': 0 }) + + blockdev_create(vm, { 'driver': imgfmt, + 'file': { + 'driver': 'file', + 'filename': disk_path, + }, + 'size': size, + 'extents': [], + 'subformat': 'monolithicSparse', + 'adapter-type': 'buslogic', + 'zeroed-grain': True }) + vm.shutdown() + + iotests.img_info_log(disk_path) + + # + # Invalid BlockdevRef + # + iotests.log("=3D=3D=3D Invalid BlockdevRef =3D=3D=3D") + iotests.log("") + + vm.launch() + blockdev_create(vm, { 'driver': imgfmt, + 'file': "this doesn't exist", + 'size': size }) + vm.shutdown() + + # + # Adapter types + # + + iotests.log("=3D=3D=3D Adapter types =3D=3D=3D") + iotests.log("") + + vm.add_blockdev('driver=3Dfile,filename=3D%s,node-name=3Dnode0' % (dis= k_path)) + + # Valid + iotests.log("=3D=3D Valid adapter types =3D=3D") + iotests.log("") + + vm.launch() + for adapter_type in [ 'ide', 'buslogic', 'lsilogic', 'legacyESX' ]: + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': size, + 'adapter-type': adapter_type }) + vm.shutdown() + + # Invalid + iotests.log("=3D=3D Invalid adapter types =3D=3D") + iotests.log("") + + vm.launch() + for adapter_type in [ 'foo', 'IDE', 'legacyesx', 1 ]: + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': size, + 'adapter-type': adapter_type }) + vm.shutdown() + + # + # Other subformats + # + iotests.log("=3D=3D=3D Other subformats =3D=3D=3D") + iotests.log("") + + for path in [ extent1_path, extent2_path, extent3_path ]: + msg =3D iotests.qemu_img_pipe('create', '-f', imgfmt, path, '0') + iotests.log(msg, [iotests.filter_testfiles]) + + vm.add_blockdev('driver=3Dfile,filename=3D%s,node-name=3Dext1' % (exte= nt1_path)) + vm.add_blockdev('driver=3Dfile,filename=3D%s,node-name=3Dext2' % (exte= nt2_path)) + vm.add_blockdev('driver=3Dfile,filename=3D%s,node-name=3Dext3' % (exte= nt3_path)) + + # Missing extent + iotests.log("=3D=3D Missing extent =3D=3D") + iotests.log("") + + vm.launch() + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': size, + 'subformat': 'monolithicFlat' }) + vm.shutdown() + + # Correct extent + iotests.log("=3D=3D Correct extent =3D=3D") + iotests.log("") + + vm.launch() + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': size, + 'subformat': 'monolithicFlat', + 'extents': ['ext1'] }) + vm.shutdown() + + # Extra extent + iotests.log("=3D=3D Extra extent =3D=3D") + iotests.log("") + + vm.launch() + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': 512, + 'subformat': 'monolithicFlat', + 'extents': ['ext1', 'ext2', 'ext3'] }) + vm.shutdown() + + # Split formats + iotests.log("=3D=3D Split formats =3D=3D") + iotests.log("") + + for size in [ 512, 1073741824, 2147483648, 5368709120 ]: + for subfmt in [ 'twoGbMaxExtentFlat', 'twoGbMaxExtentSparse' ]: + iotests.log("=3D %s %d =3D" % (subfmt, size)) + iotests.log("") + + vm.launch() + blockdev_create(vm, { 'driver': imgfmt, + 'file': 'node0', + 'size': size, + 'subformat': subfmt, + 'extents': ['ext1', 'ext2', 'ext3'] }) + vm.shutdown() + + iotests.img_info_log(disk_path) diff --git a/tests/qemu-iotests/237.out b/tests/qemu-iotests/237.out new file mode 100644 index 0000000000..1aa9aad349 --- /dev/null +++ b/tests/qemu-iotests/237.out @@ -0,0 +1,347 @@ +=3D=3D=3D Successful image creation (defaults) =3D=3D=3D + +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} + +{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "T= EST_DIR/PID-t.vmdk", "node_name": "imgfile"}} +{"return": {}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"driver": "vmdk", "file": "imgfile", "size": 5368709120}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} + +image: TEST_IMG +file format: IMGFMT +virtual size: 5.0G (5368709120 bytes) +cluster_size: 65536 +Format specific information: + cid: XXXXXXXXXX + parent cid: XXXXXXXXXX + create type: monolithicSparse + extents: + [0]: + virtual size: 5368709120 + filename: TEST_IMG + cluster size: 65536 + format:=20 + +=3D=3D=3D Successful image creation (inline blockdev-add, explicit default= s) =3D=3D=3D + +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} + +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"adapter-type": "ide", "driver": "vmdk", "extents": [], "file": {"driver":= "file", "filename": "TEST_DIR/PID-t.vmdk"}, "hwversion": "4", "size": 6710= 8864, "subformat": "monolithicSparse", "zeroed-grain": false}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} + +image: TEST_IMG +file format: IMGFMT +virtual size: 64M (67108864 bytes) +cluster_size: 65536 +Format specific information: + cid: XXXXXXXXXX + parent cid: XXXXXXXXXX + create type: monolithicSparse + extents: + [0]: + virtual size: 67108864 + filename: TEST_IMG + cluster size: 65536 + format:=20 + +=3D=3D=3D Successful image creation (with non-default options) =3D=3D=3D + +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"driver": "file", "filename": "TEST_DIR/PID-t.vmdk", "size": 0}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} + +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"adapter-type": "buslogic", "driver": "vmdk", "extents": [], "file": {"dri= ver": "file", "filename": "TEST_DIR/PID-t.vmdk"}, "size": 33554432, "subfor= mat": "monolithicSparse", "zeroed-grain": true}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} + +image: TEST_IMG +file format: IMGFMT +virtual size: 32M (33554432 bytes) +cluster_size: 65536 +Format specific information: + cid: XXXXXXXXXX + parent cid: XXXXXXXXXX + create type: monolithicSparse + extents: + [0]: + virtual size: 33554432 + filename: TEST_IMG + cluster size: 65536 + format:=20 + +=3D=3D=3D Invalid BlockdevRef =3D=3D=3D + +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"driver": "vmdk", "file": "this doesn't exist", "size": 33554432}}} +{"return": {}} +Job failed: Cannot find device=3Dthis doesn't exist nor node_name=3Dthis d= oesn't exist +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} + +=3D=3D=3D Adapter types =3D=3D=3D + +=3D=3D Valid adapter types =3D=3D + +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"adapter-type": "ide", "driver": "vmdk", "file": "node0", "size": 33554432= }}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} + +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"adapter-type": "buslogic", "driver": "vmdk", "file": "node0", "size": 335= 54432}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} + +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"adapter-type": "lsilogic", "driver": "vmdk", "file": "node0", "size": 335= 54432}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} + +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"adapter-type": "legacyESX", "driver": "vmdk", "file": "node0", "size": 33= 554432}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} + +=3D=3D Invalid adapter types =3D=3D + +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"adapter-type": "foo", "driver": "vmdk", "file": "node0", "size": 33554432= }}} +{"error": {"class": "GenericError", "desc": "Invalid parameter 'foo'"}} + +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"adapter-type": "IDE", "driver": "vmdk", "file": "node0", "size": 33554432= }}} +{"error": {"class": "GenericError", "desc": "Invalid parameter 'IDE'"}} + +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"adapter-type": "legacyesx", "driver": "vmdk", "file": "node0", "size": 33= 554432}}} +{"error": {"class": "GenericError", "desc": "Invalid parameter 'legacyesx'= "}} + +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"adapter-type": 1, "driver": "vmdk", "file": "node0", "size": 33554432}}} +{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'o= ptions.adapter-type', expected: string"}} + +=3D=3D=3D Other subformats =3D=3D=3D + +Formatting 'TEST_DIR/PID-t.vmdk.1', fmt=3Dvmdk size=3D0 compat6=3Doff hwve= rsion=3Dundefined + +Formatting 'TEST_DIR/PID-t.vmdk.2', fmt=3Dvmdk size=3D0 compat6=3Doff hwve= rsion=3Dundefined + +Formatting 'TEST_DIR/PID-t.vmdk.3', fmt=3Dvmdk size=3D0 compat6=3Doff hwve= rsion=3Dundefined + +=3D=3D Missing extent =3D=3D + +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"driver": "vmdk", "file": "node0", "size": 33554432, "subformat": "monolit= hicFlat"}}} +{"return": {}} +Job failed: Extent [0] not specified +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} + +=3D=3D Correct extent =3D=3D + +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 33554432, = "subformat": "monolithicFlat"}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} + +=3D=3D Extra extent =3D=3D + +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "s= ize": 512, "subformat": "monolithicFlat"}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} + +=3D=3D Split formats =3D=3D + +=3D twoGbMaxExtentFlat 512 =3D + +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "s= ize": 512, "subformat": "twoGbMaxExtentFlat"}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} + +image: TEST_IMG +file format: IMGFMT +virtual size: 512 (512 bytes) +Format specific information: + cid: XXXXXXXXXX + parent cid: XXXXXXXXXX + create type: twoGbMaxExtentFlat + extents: + [0]: + virtual size: 512 + filename: TEST_IMG.1 + format: FLAT + +=3D twoGbMaxExtentSparse 512 =3D + +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "s= ize": 512, "subformat": "twoGbMaxExtentSparse"}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} + +image: TEST_IMG +file format: IMGFMT +virtual size: 512 (512 bytes) +cluster_size: 65536 +Format specific information: + cid: XXXXXXXXXX + parent cid: XXXXXXXXXX + create type: twoGbMaxExtentSparse + extents: + [0]: + virtual size: 512 + filename: TEST_IMG.1 + cluster size: 65536 + format: SPARSE + +=3D twoGbMaxExtentFlat 1073741824 =3D + +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "s= ize": 1073741824, "subformat": "twoGbMaxExtentFlat"}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} + +image: TEST_IMG +file format: IMGFMT +virtual size: 1.0G (1073741824 bytes) +Format specific information: + cid: XXXXXXXXXX + parent cid: XXXXXXXXXX + create type: twoGbMaxExtentFlat + extents: + [0]: + virtual size: 1073741824 + filename: TEST_IMG.1 + format: FLAT + +=3D twoGbMaxExtentSparse 1073741824 =3D + +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "s= ize": 1073741824, "subformat": "twoGbMaxExtentSparse"}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} + +image: TEST_IMG +file format: IMGFMT +virtual size: 1.0G (1073741824 bytes) +cluster_size: 65536 +Format specific information: + cid: XXXXXXXXXX + parent cid: XXXXXXXXXX + create type: twoGbMaxExtentSparse + extents: + [0]: + virtual size: 1073741824 + filename: TEST_IMG.1 + cluster size: 65536 + format: SPARSE + +=3D twoGbMaxExtentFlat 2147483648 =3D + +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "s= ize": 2147483648, "subformat": "twoGbMaxExtentFlat"}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} + +image: TEST_IMG +file format: IMGFMT +virtual size: 2.0G (2147483648 bytes) +Format specific information: + cid: XXXXXXXXXX + parent cid: XXXXXXXXXX + create type: twoGbMaxExtentFlat + extents: + [0]: + virtual size: 2147483648 + filename: TEST_IMG.1 + format: FLAT + +=3D twoGbMaxExtentSparse 2147483648 =3D + +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "s= ize": 2147483648, "subformat": "twoGbMaxExtentSparse"}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} + +image: TEST_IMG +file format: IMGFMT +virtual size: 2.0G (2147483648 bytes) +cluster_size: 65536 +Format specific information: + cid: XXXXXXXXXX + parent cid: XXXXXXXXXX + create type: twoGbMaxExtentSparse + extents: + [0]: + virtual size: 2147483648 + filename: TEST_IMG.1 + cluster size: 65536 + format: SPARSE + +=3D twoGbMaxExtentFlat 5368709120 =3D + +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "s= ize": 5368709120, "subformat": "twoGbMaxExtentFlat"}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} + +image: TEST_IMG +file format: IMGFMT +virtual size: 5.0G (5368709120 bytes) +Format specific information: + cid: XXXXXXXXXX + parent cid: XXXXXXXXXX + create type: twoGbMaxExtentFlat + extents: + [0]: + virtual size: 2147483648 + filename: TEST_IMG.1 + format: FLAT + [1]: + virtual size: 2147483648 + filename: TEST_IMG.2 + format: FLAT + [2]: + virtual size: 1073741824 + filename: TEST_IMG.3 + format: FLAT + +=3D twoGbMaxExtentSparse 5368709120 =3D + +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "s= ize": 5368709120, "subformat": "twoGbMaxExtentSparse"}}} +{"return": {}} +{"execute": "job-dismiss", "arguments": {"id": "job0"}} +{"return": {}} + +image: TEST_IMG +file format: IMGFMT +virtual size: 5.0G (5368709120 bytes) +cluster_size: 65536 +Format specific information: + cid: XXXXXXXXXX + parent cid: XXXXXXXXXX + create type: twoGbMaxExtentSparse + extents: + [0]: + virtual size: 2147483648 + filename: TEST_IMG.1 + cluster size: 65536 + format: SPARSE + [1]: + virtual size: 2147483648 + filename: TEST_IMG.2 + cluster size: 65536 + format: SPARSE + [2]: + virtual size: 1073741824 + filename: TEST_IMG.3 + cluster size: 65536 + format: SPARSE + diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index 61a6d98ebd..c4de595f29 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -233,3 +233,4 @@ 233 auto quick 234 auto quick migration 235 auto quick +237 rw auto quick --=20 2.19.2 From nobody Mon May 6 12:43:05 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; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1544183806262226.99335676694102; Fri, 7 Dec 2018 03:56:46 -0800 (PST) Received: from localhost ([::1]:45570 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gVEkP-00009H-2L for importer@patchew.org; Fri, 07 Dec 2018 06:56:45 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:51920) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gVEhz-0007Ak-Bk for qemu-devel@nongnu.org; Fri, 07 Dec 2018 06:54:16 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gVEhx-0006HI-Qg for qemu-devel@nongnu.org; Fri, 07 Dec 2018 06:54:15 -0500 Received: from mx1.redhat.com ([209.132.183.28]:45820) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1gVEhs-0005jQ-Iz; Fri, 07 Dec 2018 06:54:08 -0500 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 72FC03081D88; Fri, 7 Dec 2018 11:54:06 +0000 (UTC) Received: from linux.fritz.box.com (ovpn-117-248.ams2.redhat.com [10.36.117.248]) by smtp.corp.redhat.com (Postfix) with ESMTP id E183E6BC2F; Fri, 7 Dec 2018 11:54:01 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 7 Dec 2018 12:53:43 +0100 Message-Id: <20181207115343.6747-6-kwolf@redhat.com> In-Reply-To: <20181207115343.6747-1-kwolf@redhat.com> References: <20181207115343.6747-1-kwolf@redhat.com> MIME-Version: 1.0 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.43]); Fri, 07 Dec 2018 11:54:06 +0000 (UTC) Content-Transfer-Encoding: quoted-printable 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 v4 5/5] vmdk: Reject excess extents in blockdev-create 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: kwolf@redhat.com, qemu-devel@nongnu.org, armbru@redhat.com, mreitz@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Clarify that the number of extents provided in BlockdevCreateOptionsVmdk must match the number of extents that will actually be used. Providing more extents will result in an error now. This requires adapting the test case to provide the right number of extents. Signed-off-by: Kevin Wolf Reviewed-by: Markus Armbruster --- qapi/block-core.json | 3 ++- block/vmdk.c | 29 ++++++++++++++++++++++++----- tests/qemu-iotests/237 | 6 +++++- tests/qemu-iotests/237.out | 13 +++++++------ 4 files changed, 38 insertions(+), 13 deletions(-) diff --git a/qapi/block-core.json b/qapi/block-core.json index 0793550cf2..afdd2f89a2 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -4068,7 +4068,8 @@ # twoGbMaxExtentSparse and twoGbMaxExtentFlat formats. For # monolithicFlat, only one entry is required; for # twoGbMaxExtent* formats, the number of entries required is -# calculated as extent_number =3D virtual_size / 2GB. +# calculated as extent_number =3D virtual_size / 2GB. Provid= ing +# more extents than will be used is an error. # @subformat The subformat of the VMDK image. Default: "monolithicSpars= e". # @backing-file The path of backing file. Default: no backing file is used. # @adapter-type The adapter type used to fill in the descriptor. Default: = ide. diff --git a/block/vmdk.c b/block/vmdk.c index 5a162ee85c..682ad93aa1 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -1970,6 +1970,7 @@ static int coroutine_fn vmdk_co_do_create(int64_t siz= e, { int extent_idx; BlockBackend *blk =3D NULL; + BlockBackend *extent_blk; Error *local_err =3D NULL; char *desc =3D NULL; int ret =3D 0; @@ -2107,7 +2108,6 @@ static int coroutine_fn vmdk_co_do_create(int64_t siz= e, } extent_idx =3D 1; while (created_size < size) { - BlockBackend *extent_blk; int64_t cur_size =3D MIN(size - created_size, extent_size); extent_blk =3D extent_fn(cur_size, extent_idx, flat, split, compre= ss, zeroed_grain, opaque, errp); @@ -2121,6 +2121,17 @@ static int coroutine_fn vmdk_co_do_create(int64_t si= ze, extent_idx++; blk_unref(extent_blk); } + + /* Check whether we got excess extents */ + extent_blk =3D extent_fn(-1, extent_idx, flat, split, compress, zeroed= _grain, + opaque, NULL); + if (extent_blk) { + blk_unref(extent_blk); + error_setg(errp, "List of extents contains unused extents"); + ret =3D -EINVAL; + goto exit; + } + /* generate descriptor file */ desc =3D g_strdup_printf(desc_template, g_random_int(), @@ -2181,6 +2192,12 @@ static BlockBackend *vmdk_co_create_opts_cb(int64_t = size, int idx, char *ext_filename =3D NULL; char *rel_filename =3D NULL; =20 + /* We're done, don't create excess extents. */ + if (size =3D=3D -1) { + assert(errp =3D=3D NULL); + return NULL; + } + if (idx =3D=3D 0) { rel_filename =3D g_strdup_printf("%s%s", data->prefix, data->postf= ix); } else if (split) { @@ -2342,10 +2359,12 @@ static BlockBackend *vmdk_co_create_cb(int64_t size= , int idx, blk_set_allow_write_beyond_eof(blk, true); bdrv_unref(bs); =20 - ret =3D vmdk_init_extent(blk, size, flat, compress, zeroed_grain, errp= ); - if (ret) { - blk_unref(blk); - blk =3D NULL; + if (size !=3D -1) { + ret =3D vmdk_init_extent(blk, size, flat, compress, zeroed_grain, = errp); + if (ret) { + blk_unref(blk); + blk =3D NULL; + } } return blk; } diff --git a/tests/qemu-iotests/237 b/tests/qemu-iotests/237 index e04a1ac6be..251771d7fb 100755 --- a/tests/qemu-iotests/237 +++ b/tests/qemu-iotests/237 @@ -20,6 +20,7 @@ # along with this program. If not, see . # =20 +import math import iotests from iotests import imgfmt =20 @@ -222,12 +223,15 @@ with iotests.FilePath('t.vmdk') as disk_path, \ iotests.log("=3D %s %d =3D" % (subfmt, size)) iotests.log("") =20 + num_extents =3D math.ceil(size / 2.0**31) + extents =3D [ "ext%d" % (i) for i in range(1, num_extents + 1)= ] + vm.launch() blockdev_create(vm, { 'driver': imgfmt, 'file': 'node0', 'size': size, 'subformat': subfmt, - 'extents': ['ext1', 'ext2', 'ext3'] }) + 'extents': extents }) vm.shutdown() =20 iotests.img_info_log(disk_path) diff --git a/tests/qemu-iotests/237.out b/tests/qemu-iotests/237.out index 1aa9aad349..241c864369 100644 --- a/tests/qemu-iotests/237.out +++ b/tests/qemu-iotests/237.out @@ -154,6 +154,7 @@ Job failed: Extent [0] not specified =20 {"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "s= ize": 512, "subformat": "monolithicFlat"}}} {"return": {}} +Job failed: List of extents contains unused extents {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} =20 @@ -161,7 +162,7 @@ Job failed: Extent [0] not specified =20 =3D twoGbMaxExtentFlat 512 =3D =20 -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "s= ize": 512, "subformat": "twoGbMaxExtentFlat"}}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 512, "subf= ormat": "twoGbMaxExtentFlat"}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -181,7 +182,7 @@ Format specific information: =20 =3D twoGbMaxExtentSparse 512 =3D =20 -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "s= ize": 512, "subformat": "twoGbMaxExtentSparse"}}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 512, "subf= ormat": "twoGbMaxExtentSparse"}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -203,7 +204,7 @@ Format specific information: =20 =3D twoGbMaxExtentFlat 1073741824 =3D =20 -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "s= ize": 1073741824, "subformat": "twoGbMaxExtentFlat"}}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 1073741824= , "subformat": "twoGbMaxExtentFlat"}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -223,7 +224,7 @@ Format specific information: =20 =3D twoGbMaxExtentSparse 1073741824 =3D =20 -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "s= ize": 1073741824, "subformat": "twoGbMaxExtentSparse"}}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 1073741824= , "subformat": "twoGbMaxExtentSparse"}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -245,7 +246,7 @@ Format specific information: =20 =3D twoGbMaxExtentFlat 2147483648 =3D =20 -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "s= ize": 2147483648, "subformat": "twoGbMaxExtentFlat"}}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 2147483648= , "subformat": "twoGbMaxExtentFlat"}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -265,7 +266,7 @@ Format specific information: =20 =3D twoGbMaxExtentSparse 2147483648 =3D =20 -{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"driver": "vmdk", "extents": ["ext1", "ext2", "ext3"], "file": "node0", "s= ize": 2147483648, "subformat": "twoGbMaxExtentSparse"}}} +{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": = {"driver": "vmdk", "extents": ["ext1"], "file": "node0", "size": 2147483648= , "subformat": "twoGbMaxExtentSparse"}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} --=20 2.19.2