From patchwork Wed Nov 30 01:18:46 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Max Reitz X-Patchwork-Id: 9453441 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id B3D0E6071C for ; Wed, 30 Nov 2016 01:38:33 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A61122818E for ; Wed, 30 Nov 2016 01:38:33 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9A17228334; Wed, 30 Nov 2016 01:38:33 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id F22D42818E for ; Wed, 30 Nov 2016 01:38:32 +0000 (UTC) Received: from localhost ([::1]:40239 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cBtqx-0006YX-Rn for patchwork-qemu-devel@patchwork.kernel.org; Tue, 29 Nov 2016 20:38:31 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54771) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cBtYq-0008EF-VY for qemu-devel@nongnu.org; Tue, 29 Nov 2016 20:19:50 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cBtYp-0006Vo-ME for qemu-devel@nongnu.org; Tue, 29 Nov 2016 20:19:49 -0500 Received: from mx1.redhat.com ([209.132.183.28]:52370) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cBtYk-0006RW-GV; Tue, 29 Nov 2016 20:19:42 -0500 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id AC412201EA; Wed, 30 Nov 2016 01:19:41 +0000 (UTC) Received: from localhost (ovpn-116-36.phx2.redhat.com [10.3.116.36]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id uAU1Jd5J010180 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Tue, 29 Nov 2016 20:19:40 -0500 From: Max Reitz To: qemu-block@nongnu.org Date: Wed, 30 Nov 2016 02:18:46 +0100 Message-Id: <20161130011851.24696-21-mreitz@redhat.com> In-Reply-To: <20161130011851.24696-1-mreitz@redhat.com> References: <20161130011851.24696-1-mreitz@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Wed, 30 Nov 2016 01:19:41 +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 v3 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 , qemu-devel@nongnu.org, Max Reitz Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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. Signed-off-by: Max Reitz --- block.c | 116 ++++++++++++++++++++++++++++++++++++++++++++- tests/qemu-iotests/110.out | 4 +- 2 files changed, 117 insertions(+), 3 deletions(-) diff --git a/block.c b/block.c index d789caa..9242054 100644 --- a/block.c +++ b/block.c @@ -3935,6 +3935,92 @@ out: return to_replace_bs; } +/** + * Iterates through the list of runtime option keys that are said to be + * "significant" for a BDS. An option is called "significant" if it changes a + * BDS's data. For example, the null block driver's "size" and "read-zeroes" + * options are significant, but its "latency-ns" option is not. + * + * If a key returned by this function ends with a dot, all options starting with + * that prefix are significant. + */ +static const char *const *significant_options(BlockDriverState *bs, + const char *const *curopt) +{ + static const char *const global_options[] = { + "driver", "filename", "base-directory", NULL + }; + + if (!curopt) { + return &global_options[0]; + } + + curopt++; + if (curopt == &global_options[ARRAY_SIZE(global_options) - 1] && bs->drv) { + curopt = bs->drv->sgfnt_runtime_opts; + } + + return (curopt && *curopt) ? curopt : NULL; +} + +/** + * Copies all significant runtime options from bs->options to the given QDict. + * 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 "driver". + * The caller is expected to use this value to decide whether the existence of + * significant options prevents the generation of a plain filename. + */ +static bool append_significant_runtime_options(QDict *d, BlockDriverState *bs) +{ + bool found_any = false; + const char *const *option_name = NULL; + + if (!bs->drv) { + return false; + } + + while ((option_name = significant_options(bs, option_name))) { + bool option_given = false; + + assert(strlen(*option_name) > 0); + if ((*option_name)[strlen(*option_name) - 1] != '.') { + QObject *entry = qdict_get(bs->options, *option_name); + if (!entry) { + continue; + } + + qobject_incref(entry); + qdict_put_obj(d, *option_name, entry); + option_given = true; + } else { + const QDictEntry *entry; + for (entry = qdict_first(bs->options); entry; + entry = 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 = true; + } + } + } + + /* While "driver" and "filename" need to be included in a JSON filename, + * their existence does not prohibit generation of a plain filename. */ + if (!found_any && option_given && + strcmp(*option_name, "driver") && strcmp(*option_name, "filename")) + { + found_any = true; + } + } + + return found_any; +} + static bool append_open_options(QDict *d, BlockDriverState *bs) { const QDictEntry *entry; @@ -4093,9 +4179,37 @@ void bdrv_refresh_filename(BlockDriverState *bs) bs->full_open_options = opts; } + /* Gather the options QDict */ + opts = 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 children'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 == &child_backing && !bs->backing_overridden) { + /* We can skip the backing BDS if it has not been overridden */ + 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 = opts; + if (bs->exact_filename[0]) { pstrcpy(bs->filename, sizeof(bs->filename), bs->exact_filename); - } else if (bs->full_open_options) { + } else { QString *json = 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 e1845d8..7eb199d 100644 --- a/tests/qemu-iotests/110.out +++ b/tests/qemu-iotests/110.out @@ -22,12 +22,12 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 backing_file=t.IMGFMT.b === Nodes without a common directory === -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-corrupted": 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) -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-corrupted": 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", "base-directory": "TEST_DIR/", "vote-threshold": 1}} file format: IMGFMT virtual size: 64M (67108864 bytes) backing file: t.IMGFMT.base (actual path: TEST_DIR/t.IMGFMT.base)