From nobody Tue Feb 10 15:01:08 2026 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 (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1511209888369766.9716677417616; Mon, 20 Nov 2017 12:31:28 -0800 (PST) Received: from localhost ([::1]:59607 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eGsij-0000tk-Jl for importer@patchew.org; Mon, 20 Nov 2017 15:31:09 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35577) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eGsPy-0000a3-QS for qemu-devel@nongnu.org; Mon, 20 Nov 2017 15:11:51 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eGsPw-0007kS-Lh for qemu-devel@nongnu.org; Mon, 20 Nov 2017 15:11:46 -0500 Received: from mx1.redhat.com ([209.132.183.28]:44348) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eGsPr-0007iA-TE; Mon, 20 Nov 2017 15:11:40 -0500 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 28A5E80082; Mon, 20 Nov 2017 20:11:39 +0000 (UTC) Received: from localhost (ovpn-204-75.brq.redhat.com [10.40.204.75]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 1ABA560BEC; Mon, 20 Nov 2017 20:11:37 +0000 (UTC) From: Max Reitz To: qemu-block@nongnu.org Date: Mon, 20 Nov 2017 21:09:59 +0100 Message-Id: <20171120201004.14999-21-mreitz@redhat.com> In-Reply-To: <20171120201004.14999-1-mreitz@redhat.com> References: <20171120201004.14999-1-mreitz@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.28]); Mon, 20 Nov 2017 20:11:39 +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 v7 for-2.12 20/25] block: Generically refresh runtime options 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 , John Snow , qemu-devel@nongnu.org, Max Reitz 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" Instead of having every block driver which implements bdrv_refresh_filename() copy all of the significant runtime options over to bs->full_open_options, implement this process generically in bdrv_refresh_filename(). This patch only adds this new generic implementation, it does not remove the old functionality. This is done in a follow-up patch. With this patch, some superfluous information (that should never have been there) may be removed from some JSON filenames, as can be seen in the change to iotest 110's reference output. In case of 191, backing nodes that have not been overridden are now removed from the filename. Signed-off-by: Max Reitz Reviewed-by: Alberto Garcia --- block.c | 116 +++++++++++++++++++++++++++++++++++++++++= +++- tests/qemu-iotests/110.out | 2 +- tests/qemu-iotests/191.out | 24 +++++----- 3 files changed, 128 insertions(+), 14 deletions(-) diff --git a/block.c b/block.c index 2e59e77f9d..64ef30bbac 100644 --- a/block.c +++ b/block.c @@ -4944,6 +4944,92 @@ out: return to_replace_bs; } =20 +/** + * Iterates through the list of runtime option keys that are said to be + * "significant" for a BDS. An option is called "significant" if it change= s a + * BDS's data. For example, the null block driver's "size" and "read-zeroe= s" + * options are significant, but its "latency-ns" option is not. + * + * If a key returned by this function ends with a dot, all options startin= g with + * that prefix are significant. + */ +static const char *const *significant_options(BlockDriverState *bs, + const char *const *curopt) +{ + static const char *const global_options[] =3D { + "driver", "filename", "base-directory", NULL + }; + + if (!curopt) { + return &global_options[0]; + } + + curopt++; + if (curopt =3D=3D &global_options[ARRAY_SIZE(global_options) - 1] && b= s->drv) { + curopt =3D bs->drv->sgfnt_runtime_opts; + } + + return (curopt && *curopt) ? curopt : NULL; +} + +/** + * Copies all significant runtime options from bs->options to the given QD= ict. + * The set of significant option keys is determined by invoking + * significant_options(). + * + * Returns true iff any significant option was present in bs->options (and= thus + * copied to the target QDict) with the exception of "filename" and "drive= r". + * The caller is expected to use this value to decide whether the existenc= e of + * significant options prevents the generation of a plain filename. + */ +static bool append_significant_runtime_options(QDict *d, BlockDriverState = *bs) +{ + bool found_any =3D false; + const char *const *option_name =3D NULL; + + if (!bs->drv) { + return false; + } + + while ((option_name =3D significant_options(bs, option_name))) { + bool option_given =3D false; + + assert(strlen(*option_name) > 0); + if ((*option_name)[strlen(*option_name) - 1] !=3D '.') { + QObject *entry =3D qdict_get(bs->options, *option_name); + if (!entry) { + continue; + } + + qobject_incref(entry); + qdict_put_obj(d, *option_name, entry); + option_given =3D true; + } else { + const QDictEntry *entry; + for (entry =3D qdict_first(bs->options); entry; + entry =3D qdict_next(bs->options, entry)) + { + if (strstart(qdict_entry_key(entry), *option_name, NULL)) { + qobject_incref(qdict_entry_value(entry)); + qdict_put_obj(d, qdict_entry_key(entry), + qdict_entry_value(entry)); + option_given =3D true; + } + } + } + + /* While "driver" and "filename" need to be included in a JSON fil= ename, + * their existence does not prohibit generation of a plain filenam= e. */ + if (!found_any && option_given && + strcmp(*option_name, "driver") && strcmp(*option_name, "filena= me")) + { + found_any =3D true; + } + } + + return found_any; +} + static bool append_open_options(QDict *d, BlockDriverState *bs) { const QDictEntry *entry; @@ -5098,9 +5184,37 @@ void bdrv_refresh_filename(BlockDriverState *bs) bs->full_open_options =3D opts; } =20 + /* Gather the options QDict */ + opts =3D qdict_new(); + append_significant_runtime_options(opts, bs); + + if (drv->bdrv_gather_child_options) { + /* Some block drivers may not want to present all of their childre= n's + * options, or name them differently from BdrvChild.name */ + drv->bdrv_gather_child_options(bs, opts); + } else { + QLIST_FOREACH(child, &bs->children, next) { + if (child->role =3D=3D &child_backing && !bs->backing_overridd= en) { + /* We can skip the backing BDS if it has not been overridd= en */ + continue; + } + + QINCREF(child->bs->full_open_options); + qdict_put(opts, child->name, child->bs->full_open_options); + } + + if (bs->backing_overridden && !bs->backing) { + /* Force no backing file */ + qdict_put(opts, "backing", qstring_new()); + } + } + + QDECREF(bs->full_open_options); + bs->full_open_options =3D opts; + if (bs->exact_filename[0]) { pstrcpy(bs->filename, sizeof(bs->filename), bs->exact_filename); - } else if (bs->full_open_options) { + } else { QString *json =3D qobject_to_json(QOBJECT(bs->full_open_options)); snprintf(bs->filename, sizeof(bs->filename), "json:%s", qstring_get_str(json)); diff --git a/tests/qemu-iotests/110.out b/tests/qemu-iotests/110.out index 1d0b2475cc..46e6a60510 100644 --- a/tests/qemu-iotests/110.out +++ b/tests/qemu-iotests/110.out @@ -22,7 +22,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D67108= 864 backing_file=3Dt.IMGFMT.b =20 =3D=3D=3D Nodes without a common directory =3D=3D=3D =20 -image: json:{"driver": "IMGFMT", "file": {"children": [{"driver": "file", = "filename": "TEST_DIR/t.IMGFMT"}, {"driver": "file", "filename": "TEST_DIR/= t.IMGFMT.copy"}], "driver": "quorum", "blkverify": false, "rewrite-corrupte= d": false, "vote-threshold": 1}} +image: json:{"driver": "IMGFMT", "file": {"children": [{"driver": "file", = "filename": "TEST_DIR/t.IMGFMT"}, {"driver": "file", "filename": "TEST_DIR/= t.IMGFMT.copy"}], "driver": "quorum", "vote-threshold": 1}} file format: IMGFMT virtual size: 64M (67108864 bytes) backing file: t.IMGFMT.base (cannot determine actual path) diff --git a/tests/qemu-iotests/191.out b/tests/qemu-iotests/191.out index c1ce99985e..7e42b45ddb 100644 --- a/tests/qemu-iotests/191.out +++ b/tests/qemu-iotests/191.out @@ -61,7 +61,7 @@ wrote 65536/65536 bytes at offset 1048576 }, "backing-filename-format": "qcow2", "virtual-size": 67108864, - "filename": "json:{"backing": {"backing": {"driver": "qcow= 2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driv= er": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.mid"= }}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.q= cow2.ovl2"}}", + "filename": "json:{"backing": {"driver": "qcow2", "file": = {"driver": "file", "filename": "TEST_DIR/t.qcow2.mid"}}, "driver": "qcow2",= "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.ovl2"}}", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, @@ -95,7 +95,7 @@ wrote 65536/65536 bytes at offset 1048576 "direct": false, "writeback": true }, - "file": "json:{"backing": {"backing": {"driver": "qcow2", "fil= e": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qc= ow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.mid"}}, "dri= ver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.ovl= 2"}}", + "file": "json:{"backing": {"driver": "qcow2", "file": {"driver= ": "file", "filename": "TEST_DIR/t.qcow2.mid"}}, "driver": "qcow2", "file":= {"driver": "file", "filename": "TEST_DIR/t.qcow2.ovl2"}}", "encryption_key_missing": false }, { @@ -150,7 +150,7 @@ wrote 65536/65536 bytes at offset 1048576 }, "backing-filename-format": "qcow2", "virtual-size": 67108864, - "filename": "json:{"backing": {"backing": {"driver": "qcow= 2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driv= er": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.mid"= }}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.q= cow2"}}", + "filename": "json:{"backing": {"driver": "qcow2", "file": = {"driver": "file", "filename": "TEST_DIR/t.qcow2.mid"}}, "driver": "qcow2",= "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}}", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, @@ -184,7 +184,7 @@ wrote 65536/65536 bytes at offset 1048576 "direct": false, "writeback": true }, - "file": "json:{"backing": {"backing": {"driver": "qcow2", "fil= e": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qc= ow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.mid"}}, "dri= ver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2"}}", + "file": "json:{"backing": {"driver": "qcow2", "file": {"driver= ": "file", "filename": "TEST_DIR/t.qcow2.mid"}}, "driver": "qcow2", "file":= {"driver": "file", "filename": "TEST_DIR/t.qcow2"}}", "encryption_key_missing": false }, { @@ -464,7 +464,7 @@ wrote 65536/65536 bytes at offset 1048576 }, "backing-filename-format": "qcow2", "virtual-size": 67108864, - "filename": "json:{"backing": {"backing": {"driver": "qcow= 2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driv= er": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.mid"= }}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.q= cow2.ovl2"}}", + "filename": "json:{"backing": {"driver": "qcow2", "file": = {"driver": "file", "filename": "TEST_DIR/t.qcow2.mid"}}, "driver": "qcow2",= "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.ovl2"}}", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, @@ -498,7 +498,7 @@ wrote 65536/65536 bytes at offset 1048576 "direct": false, "writeback": true }, - "file": "json:{"backing": {"backing": {"driver": "qcow2", "fil= e": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driver": "qc= ow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.mid"}}, "dri= ver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.ovl= 2"}}", + "file": "json:{"backing": {"driver": "qcow2", "file": {"driver= ": "file", "filename": "TEST_DIR/t.qcow2.mid"}}, "driver": "qcow2", "file":= {"driver": "file", "filename": "TEST_DIR/t.qcow2.ovl2"}}", "encryption_key_missing": false }, { @@ -554,7 +554,7 @@ wrote 65536/65536 bytes at offset 1048576 }, "backing-filename-format": "qcow2", "virtual-size": 67108864, - "filename": "json:{"backing": {"backing": {"driver": "= qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "= driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.= mid"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR= /t.qcow2.ovl2"}}", + "filename": "json:{"backing": {"driver": "qcow2", "fil= e": {"driver": "file", "filename": "TEST_DIR/t.qcow2.mid"}}, "driver": "qco= w2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.ovl2"}}", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, @@ -573,7 +573,7 @@ wrote 65536/65536 bytes at offset 1048576 }, "backing-filename-format": "qcow2", "virtual-size": 67108864, - "filename": "json:{"backing": {"backing": {"backing": {"dr= iver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.ba= se"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/= t.qcow2.mid"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "= TEST_DIR/t.qcow2.ovl2"}}, "driver": "qcow2", "file": {"driver": "file", "fi= lename": "TEST_DIR/t.qcow2.ovl3"}}", + "filename": "json:{"backing": {"backing": {"driver": "qcow= 2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.mid"}}, "drive= r": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.ovl2"= }}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.q= cow2.ovl3"}}", "cluster-size": 65536, "format": "qcow2", "actual-size": SIZE, @@ -586,8 +586,8 @@ wrote 65536/65536 bytes at offset 1048576 "corrupt": false } }, - "full-backing-filename": "json:{"backing": {"backing": {"d= river": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.b= ase"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR= /t.qcow2.mid"}}, "driver": "qcow2", "file": {"driver": "file", "filename": = "TEST_DIR/t.qcow2.ovl2"}}", - "backing-filename": "json:{"backing": {"backing": {"driver= ": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}= }, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qc= ow2.mid"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST= _DIR/t.qcow2.ovl2"}}", + "full-backing-filename": "json:{"backing": {"driver": "qco= w2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.mid"}}, "driv= er": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.ovl2= "}}", + "backing-filename": "json:{"backing": {"driver": "qcow2", = "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.mid"}}, "driver": = "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.ovl2"}}", "dirty-flag": false }, "iops_wr": 0, @@ -598,7 +598,7 @@ wrote 65536/65536 bytes at offset 1048576 "iops": 0, "bps_wr": 0, "write_threshold": 0, - "backing_file": "json:{"backing": {"backing": {"driver": "qcow= 2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "driv= er": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.mid"= }}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.q= cow2.ovl2"}}", + "backing_file": "json:{"backing": {"driver": "qcow2", "file": = {"driver": "file", "filename": "TEST_DIR/t.qcow2.mid"}}, "driver": "qcow2",= "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.ovl2"}}", "encrypted": false, "bps": 0, "bps_rd": 0, @@ -607,7 +607,7 @@ wrote 65536/65536 bytes at offset 1048576 "direct": false, "writeback": true }, - "file": "json:{"backing": {"backing": {"backing": {"driver": "= qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.base"}}, "= driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.= mid"}}, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR= /t.qcow2.ovl2"}}, "driver": "qcow2", "file": {"driver": "file", "filename":= "TEST_DIR/t.qcow2.ovl3"}}", + "file": "json:{"backing": {"backing": {"driver": "qcow2", "fil= e": {"driver": "file", "filename": "TEST_DIR/t.qcow2.mid"}}, "driver": "qco= w2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.ovl2"}}, "dri= ver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/t.qcow2.ovl= 3"}}", "encryption_key_missing": false }, { --=20 2.13.6