From nobody Fri Nov 7 12:01:46 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1547739762298262.7320590644024; Thu, 17 Jan 2019 07:42:42 -0800 (PST) Received: from localhost ([127.0.0.1]:46805 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gk9oX-0008Kb-20 for importer@patchew.org; Thu, 17 Jan 2019 10:42:41 -0500 Received: from eggs.gnu.org ([209.51.188.92]:39001) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gk9gn-0001s2-9Z for qemu-devel@nongnu.org; Thu, 17 Jan 2019 10:34:45 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gk9gl-0007lR-DM for qemu-devel@nongnu.org; Thu, 17 Jan 2019 10:34:41 -0500 Received: from fanzine.igalia.com ([91.117.99.155]:59807) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1gk9gj-0007IX-9q; Thu, 17 Jan 2019 10:34:39 -0500 Received: from [194.100.51.2] (helo=perseus.local) by fanzine.igalia.com with esmtpsa (Cipher TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim) id 1gk9gY-0003bb-F0; Thu, 17 Jan 2019 16:34:26 +0100 Received: from berto by perseus.local with local (Exim 4.89) (envelope-from ) id 1gk9gI-0007RJ-Ux; Thu, 17 Jan 2019 17:34:10 +0200 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=References:In-Reply-To:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=PFg+/K5uhhyjcMVsd3rBh/pBQOvUPjYRbl4PPbZCBIo=; b=Qdkv+J2HSiHMXb2XRLO1W19T//oKZ9yMWOZCYuuxYXH+1fFky1aLZxIRimtm4OdNtahLY0HdRMiwfsrdbHgknrS+Hi41cyBbs1AfL9bZjy8AXvNoENO7DUWC+5lJejs1D4kwLQbS/JsByJYQp3kaIsknEnSki8Brw7CFdB/Axljs59+bYsbvHbg1urBzbn5HHSuakOXndn6S+tRSpSWdf4umd6T9IgPn8aiEH7wlHLFj6sjd58FbRfMJrI01eh6iujyf1o4OO4JHd00bh/g+sO/Ygvyk6blTTbhgjpQWYzCR0z/looEw2zbb4+v9HtTktE2MqyTOi8zvc+Gpx+YQYA==; From: Alberto Garcia To: qemu-devel@nongnu.org Date: Thu, 17 Jan 2019 17:33:57 +0200 Message-Id: X-Mailer: git-send-email 2.11.0 In-Reply-To: References: In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x (no timestamps) [generic] [fuzzy] X-Received-From: 91.117.99.155 Subject: [Qemu-devel] [PATCH 06/13] block: Handle child references in bdrv_reopen_queue() 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-block@nongnu.org, Max Reitz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Children in QMP are specified with BlockdevRef / BlockdevRefOrNull, which can contain a set of child options, a child reference, or NULL. In optional attributes like "backing" it can also be missing. Only the first case (set of child options) is being handled properly by bdrv_reopen_queue(). This patch deals with all the others. Here's how these cases should be handled when bdrv_reopen_queue() is deciding what to do with each child of a BlockDriverState: 1) Set of child options: the options are removed from the parent's options QDict and are passed to the child with a recursive bdrv_reopen_queue() call. This case was already working fine. 2) Child reference: there's two possibilites here. 2a) Reference to the current child: the child is put in the reopen queue, keeping its current set of options (since this was a child reference there was no way to specify a different set of options). 2b) Reference to a different BDS: the current child is not put in the reopen queue at all. Passing a reference to a different BDS can be used to replace a child, although at the moment no driver implements this, so it results in an error. In any case, the current child is not going to be reopened (and might in fact disappear if it's replaced) 3) NULL: This is similar to (2b). Although no driver allows this yet it can be used to detach the current child so it should not be put in the reopen queue. 4) Missing option: at the moment "backing" is the only case where this can happen. With "blockdev-add", leaving "backing" out means that the default backing file is opened. We don't want to open a new image during reopen, so we require that "backing" is always present. We'll relax this requirement a bit in the next patch. Signed-off-by: Alberto Garcia --- block.c | 51 ++++++++++++++++++++++++++++++++++++++++++++---= ---- include/block/block.h | 1 + 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/block.c b/block.c index 056a620eb2..fd51f1cd35 100644 --- a/block.c +++ b/block.c @@ -3032,9 +3032,21 @@ static BlockReopenQueue *bdrv_reopen_queue_child(Blo= ckReopenQueue *bs_queue, bs_entry->state.perm =3D UINT64_MAX; bs_entry->state.shared_perm =3D 0; =20 + /* + * If keep_old_opts is false then it means that unspecified + * options must be reset to its original value. We don't allow + * resetting 'backing' but we need to know if the option is + * missing in order to decide if we have to return an error. + */ + if (!keep_old_opts) { + bs_entry->state.backing_missing =3D + !qdict_haskey(options, "backing") && + !qdict_haskey(options, "backing.driver"); + } + QLIST_FOREACH(child, &bs->children, next) { - QDict *new_child_options; - char *child_key_dot; + QDict *new_child_options =3D NULL; + bool child_keep_old =3D keep_old_opts; =20 /* reopen can only change the options of block devices that were * implicitly created and inherited options. For other (referenced) @@ -3043,13 +3055,31 @@ static BlockReopenQueue *bdrv_reopen_queue_child(Bl= ockReopenQueue *bs_queue, continue; } =20 - child_key_dot =3D g_strdup_printf("%s.", child->name); - qdict_extract_subqdict(explicit_options, NULL, child_key_dot); - qdict_extract_subqdict(options, &new_child_options, child_key_dot); - g_free(child_key_dot); + /* Check if the options contain a child reference */ + if (qdict_haskey(options, child->name)) { + const char *childref =3D qdict_get_try_str(options, child->nam= e); + /* + * The current child must not be reopened if the child + * reference does not point to it. + */ + if (g_strcmp0(childref, child->bs->node_name)) { + continue; + } + /* + * If the child reference points to the current child then + * reopen it with its existing set of options. + */ + child_keep_old =3D true; + } else { + /* Extract child options ("child-name.*") */ + char *child_key_dot =3D g_strdup_printf("%s.", child->name); + qdict_extract_subqdict(explicit_options, NULL, child_key_dot); + qdict_extract_subqdict(options, &new_child_options, child_key_= dot); + g_free(child_key_dot); + } =20 bdrv_reopen_queue_child(bs_queue, child->bs, new_child_options, - child->role, options, flags, keep_old_opts= ); + child->role, options, flags, child_keep_ol= d); } =20 return bs_queue; @@ -3306,6 +3336,13 @@ int bdrv_reopen_prepare(BDRVReopenState *reopen_stat= e, BlockReopenQueue *queue, =20 drv_prepared =3D true; =20 + if (reopen_state->backing_missing) { + error_setg(errp, "backing is missing for '%s'", + reopen_state->bs->node_name); + ret =3D -EINVAL; + goto error; + } + /* Options that are not handled are only okay if they are unchanged * compared to the old state. It is expected that some options are only * used for the initial open, but not reopen (e.g. filename) */ diff --git a/include/block/block.h b/include/block/block.h index a061ef3944..e21616a038 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -187,6 +187,7 @@ typedef struct BDRVReopenState { BlockDriverState *bs; int flags; BlockdevDetectZeroesOptions detect_zeroes; + bool backing_missing; uint64_t perm, shared_perm; QDict *options; QDict *explicit_options; --=20 2.11.0