From nobody Tue May 7 21:08:57 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 1529072626499783.7204837384468; Fri, 15 Jun 2018 07:23:46 -0700 (PDT) Received: from localhost ([::1]:47120 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpdh-0007YG-MT for importer@patchew.org; Fri, 15 Jun 2018 10:23:45 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58838) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpbL-0005q9-S4 for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:21 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTpbK-0003TK-Qv for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:19 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:54380 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fTpbE-0003MF-Rz; Fri, 15 Jun 2018 10:21:12 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 7C54240122A1; Fri, 15 Jun 2018 14:21:12 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-70.ams2.redhat.com [10.36.117.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id CBBDE63A4F; Fri, 15 Jun 2018 14:21:11 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 15 Jun 2018 16:20:43 +0200 Message-Id: <20180615142108.27814-2-kwolf@redhat.com> In-Reply-To: <20180615142108.27814-1-kwolf@redhat.com> References: <20180615142108.27814-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Fri, 15 Jun 2018 14:21:12 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Fri, 15 Jun 2018 14:21:12 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL 01/26] qemu-img: Fix assert when mapping unaligned raw file 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 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" From: Eric Blake Commit a290f085 exposed a latent bug in qemu-img map introduced during the conversion of block status to be byte-based. Earlier in commit 5e344dd8, the internal interface get_block_status() switched to take byte-based parameters, but still called a sector-based block layer function; as such, rounding was added in the lone caller to obey the contract. However, commit 237d78f8 changed get_block_status() to truly be byte-based, at which point rounding to sector boundaries can result in calling bdrv_block_status() with 'bytes =3D=3D 0' (a coding error) when the boundary between data and a hole falls mid-sector (true for the past-EOF implicit hole present in POSIX files). Fix things by removing the rounding that is now no longer necessary. See also https://bugzilla.redhat.com/1589738 Fixes: 237d78f8 Reported-by: Dan Kenigsberg Reported-by: Nir Soffer Reported-by: Maor Lipchuk CC: qemu-stable@nongnu.org Signed-off-by: Eric Blake Signed-off-by: Kevin Wolf --- qemu-img.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qemu-img.c b/qemu-img.c index 1dcdd47254..e1a506f7f6 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -2906,7 +2906,7 @@ static int img_map(int argc, char **argv) int64_t n; =20 /* Probe up to 1 GiB at a time. */ - n =3D QEMU_ALIGN_DOWN(MIN(1 << 30, length - offset), BDRV_SECTOR_S= IZE); + n =3D MIN(1 << 30, length - offset); ret =3D get_block_status(bs, offset, n, &next); =20 if (ret < 0) { --=20 2.13.6 From nobody Tue May 7 21:08:57 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 1529073006614903.1419525626184; Fri, 15 Jun 2018 07:30:06 -0700 (PDT) Received: from localhost ([::1]:47171 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpjn-00058f-3M for importer@patchew.org; Fri, 15 Jun 2018 10:30:03 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58846) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpbM-0005qZ-8b for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:26 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTpbK-0003TU-Rf for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:20 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:55622 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fTpbF-0003Ms-PK; Fri, 15 Jun 2018 10:21:13 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 66EC587A81; Fri, 15 Jun 2018 14:21:13 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-70.ams2.redhat.com [10.36.117.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id B761E63A72; Fri, 15 Jun 2018 14:21:12 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 15 Jun 2018 16:20:44 +0200 Message-Id: <20180615142108.27814-3-kwolf@redhat.com> In-Reply-To: <20180615142108.27814-1-kwolf@redhat.com> References: <20180615142108.27814-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Fri, 15 Jun 2018 14:21:13 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Fri, 15 Jun 2018 14:21:13 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL 02/26] iotests: Add test 221 to catch qemu-img map regression 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 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" From: Eric Blake Although qemu-img creates aligned files (by rounding up), it must also gracefully handle files that are not sector-aligned. Test that the bug fixed in the previous patch does not recur. It's a bit annoying that we can see the (implicit) hole past the end of the file on to the next sector boundary, so if we ever reach the point where we report a byte-accurate size rather than our current behavior of always rounding up, this test will probably need a slight modification. Signed-off-by: Eric Blake Signed-off-by: Kevin Wolf --- tests/qemu-iotests/221 | 60 ++++++++++++++++++++++++++++++++++++++++++= ++++ tests/qemu-iotests/221.out | 16 +++++++++++++ tests/qemu-iotests/group | 1 + 3 files changed, 77 insertions(+) create mode 100755 tests/qemu-iotests/221 create mode 100644 tests/qemu-iotests/221.out diff --git a/tests/qemu-iotests/221 b/tests/qemu-iotests/221 new file mode 100755 index 0000000000..41c4e4bdf8 --- /dev/null +++ b/tests/qemu-iotests/221 @@ -0,0 +1,60 @@ +#!/bin/bash +# +# Test qemu-img vs. unaligned images +# +# Copyright (C) 2018 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +seq=3D"$(basename $0)" +echo "QA output created by $seq" + +here=3D"$PWD" +status=3D1 # failure is the default! + +_cleanup() +{ + _cleanup_test_img +} +trap "_cleanup; exit \$status" 0 1 2 3 15 + +# get standard environment, filters and checks +. ./common.rc +. ./common.filter + +_supported_fmt raw +_supported_proto file +_supported_os Linux + +echo +echo "=3D=3D=3D Check mapping of unaligned raw image =3D=3D=3D" +echo + +_make_test_img 43009 # qemu-img create rounds size up +$QEMU_IMG map --output=3Djson "$TEST_IMG" | _filter_qemu_img_map + +truncate --size=3D43009 "$TEST_IMG" # so we resize it and check again +$QEMU_IMG map --output=3Djson "$TEST_IMG" | _filter_qemu_img_map + +$QEMU_IO -c 'w 43008 1' "$TEST_IMG" | _filter_qemu_io # writing also round= s up +$QEMU_IMG map --output=3Djson "$TEST_IMG" | _filter_qemu_img_map + +truncate --size=3D43009 "$TEST_IMG" # so we resize it and check again +$QEMU_IMG map --output=3Djson "$TEST_IMG" | _filter_qemu_img_map + +# success, all done +echo '*** done' +rm -f $seq.full +status=3D0 diff --git a/tests/qemu-iotests/221.out b/tests/qemu-iotests/221.out new file mode 100644 index 0000000000..a9c0190aad --- /dev/null +++ b/tests/qemu-iotests/221.out @@ -0,0 +1,16 @@ +QA output created by 221 + +=3D=3D=3D Check mapping of unaligned raw image =3D=3D=3D + +Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D43009 +[{ "start": 0, "length": 43520, "depth": 0, "zero": true, "data": false, "= offset": OFFSET}] +[{ "start": 0, "length": 43520, "depth": 0, "zero": true, "data": false, "= offset": OFFSET}] +wrote 1/1 bytes at offset 43008 +1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +[{ "start": 0, "length": 40960, "depth": 0, "zero": true, "data": false, "= offset": OFFSET}, +{ "start": 40960, "length": 2049, "depth": 0, "zero": false, "data": true,= "offset": OFFSET}, +{ "start": 43009, "length": 511, "depth": 0, "zero": true, "data": false, = "offset": OFFSET}] +[{ "start": 0, "length": 40960, "depth": 0, "zero": true, "data": false, "= offset": OFFSET}, +{ "start": 40960, "length": 2049, "depth": 0, "zero": false, "data": true,= "offset": OFFSET}, +{ "start": 43009, "length": 511, "depth": 0, "zero": true, "data": false, = "offset": OFFSET}] +*** done diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group index 0914c922d7..937a3d0a4d 100644 --- a/tests/qemu-iotests/group +++ b/tests/qemu-iotests/group @@ -218,3 +218,4 @@ 217 rw auto quick 218 rw auto quick 219 rw auto +221 rw auto quick --=20 2.13.6 From nobody Tue May 7 21:08:57 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 1529073128362827.4567868664824; Fri, 15 Jun 2018 07:32:08 -0700 (PDT) Received: from localhost ([::1]:47190 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTplj-000725-OD for importer@patchew.org; Fri, 15 Jun 2018 10:32:03 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58901) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpbO-0005tX-Mm for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:23 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTpbK-0003Tc-Ru for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:22 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:54382 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fTpbG-0003Ne-MD; Fri, 15 Jun 2018 10:21:14 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 50D1040122A1; Fri, 15 Jun 2018 14:21:14 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-70.ams2.redhat.com [10.36.117.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id A1FEC63A4F; Fri, 15 Jun 2018 14:21:13 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 15 Jun 2018 16:20:45 +0200 Message-Id: <20180615142108.27814-4-kwolf@redhat.com> In-Reply-To: <20180615142108.27814-1-kwolf@redhat.com> References: <20180615142108.27814-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Fri, 15 Jun 2018 14:21:14 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Fri, 15 Jun 2018 14:21:14 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL 03/26] jobs: fix stale wording 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 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" From: John Snow During the design for manual completion, we decided not to use the "manual" property as a shorthand for both auto-dismiss and auto-finalize. Fix the wording. Signed-off-by: John Snow Reviewed-by: Jeff Cody Reviewed-by: Markus Armbruster Signed-off-by: Kevin Wolf --- qapi/job.json | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/qapi/job.json b/qapi/job.json index 17d10037c4..226443594b 100644 --- a/qapi/job.json +++ b/qapi/job.json @@ -50,16 +50,17 @@ # the last job in a transaction. # # @pending: The job has finished its work, but has finalization steps that= it -# needs to make prior to completing. These changes may require -# manual intervention by the management process if manual was set -# to true. These changes may still fail. +# needs to make prior to completing. These changes will require +# manual intervention via @job-finalize if auto-finalize was set= to +# false. These pending changes may still fail. # # @aborting: The job is in the process of being aborted, and will finish w= ith # an error. The job will afterwards report that it is @conclude= d. # This status may not be visible to the management process. # -# @concluded: The job has finished all work. If manual was set to true, th= e job -# will remain in the query list until it is dismissed. +# @concluded: The job has finished all work. If auto-dismiss was set to fa= lse, +# the job will remain in the query list until it is dismissed = via +# @job-dismiss. # # @null: The job is in the process of being dismantled. This state should = not # ever be visible externally. --=20 2.13.6 From nobody Tue May 7 21:08:57 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 15290726129651016.035098231808; Fri, 15 Jun 2018 07:23:32 -0700 (PDT) Received: from localhost ([::1]:47117 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpdU-0007NJ-2q for importer@patchew.org; Fri, 15 Jun 2018 10:23:32 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58824) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpbL-0005pw-JW for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:20 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTpbK-0003Tb-Rs for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:19 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:50208 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fTpbH-0003OF-Jr; Fri, 15 Jun 2018 10:21:15 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 3BF5B81A3245; Fri, 15 Jun 2018 14:21:15 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-70.ams2.redhat.com [10.36.117.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8C3A263A4F; Fri, 15 Jun 2018 14:21:14 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 15 Jun 2018 16:20:46 +0200 Message-Id: <20180615142108.27814-5-kwolf@redhat.com> In-Reply-To: <20180615142108.27814-1-kwolf@redhat.com> References: <20180615142108.27814-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Fri, 15 Jun 2018 14:21:15 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Fri, 15 Jun 2018 14:21:15 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL 04/26] jobs: fix verb references in docs 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 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" From: John Snow These point to the job versions now, not the blockjob versions which don't really exist anymore. Except set-speed, which does. It sticks out like a sore thumb. This patch doesn't fix that, but it doesn't make it any worse, either. Signed-off-by: John Snow Reviewed-by: Jeff Cody Reviewed-by: Markus Armbruster Signed-off-by: Kevin Wolf --- qapi/job.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/qapi/job.json b/qapi/job.json index 226443594b..9d074eb8d2 100644 --- a/qapi/job.json +++ b/qapi/job.json @@ -76,19 +76,19 @@ # # Represents command verbs that can be applied to a job. # -# @cancel: see @block-job-cancel +# @cancel: see @job-cancel # -# @pause: see @block-job-pause +# @pause: see @job-pause # -# @resume: see @block-job-resume +# @resume: see @job-resume # # @set-speed: see @block-job-set-speed # -# @complete: see @block-job-complete +# @complete: see @job-complete # -# @dismiss: see @block-job-dismiss +# @dismiss: see @job-dismiss # -# @finalize: see @block-job-finalize +# @finalize: see @job-finalize # # Since: 2.12 ## --=20 2.13.6 From nobody Tue May 7 21:08:57 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 1529073320808345.7534526303971; Fri, 15 Jun 2018 07:35:20 -0700 (PDT) Received: from localhost ([::1]:47205 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpoo-0001TT-NT for importer@patchew.org; Fri, 15 Jun 2018 10:35:14 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58950) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpbQ-0005w0-Sl for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:25 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTpbP-0003Zy-SQ for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:24 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:50210 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fTpbI-0003Pd-I4; Fri, 15 Jun 2018 10:21:16 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 27A2C81A3245; Fri, 15 Jun 2018 14:21:16 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-70.ams2.redhat.com [10.36.117.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id 776AD63A4F; Fri, 15 Jun 2018 14:21:15 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 15 Jun 2018 16:20:47 +0200 Message-Id: <20180615142108.27814-6-kwolf@redhat.com> In-Reply-To: <20180615142108.27814-1-kwolf@redhat.com> References: <20180615142108.27814-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Fri, 15 Jun 2018 14:21:16 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Fri, 15 Jun 2018 14:21:16 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL 05/26] rbd: Drop deprecated -drive parameter "filename" 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 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" From: Markus Armbruster Parameter "filename" is deprecated since commit 91589d9e5ca, v2.10.0. Time to get rid of it. Signed-off-by: Markus Armbruster Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/rbd.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/block/rbd.c b/block/rbd.c index a16431e267..40c6e4185f 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -632,25 +632,9 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *= options, int flags, QObject *crumpled =3D NULL; const QDictEntry *e; Error *local_err =3D NULL; - const char *filename; char *keypairs, *secretid; int r; =20 - /* If we are given a filename, parse the filename, with precedence giv= en to - * filename encoded options */ - filename =3D qdict_get_try_str(options, "filename"); - if (filename) { - warn_report("'filename' option specified. " - "This is an unsupported option, and may be deprecated " - "in the future"); - qemu_rbd_parse_filename(filename, options, &local_err); - qdict_del(options, "filename"); - if (local_err) { - error_propagate(errp, local_err); - return -EINVAL; - } - } - keypairs =3D g_strdup(qdict_get_try_str(options, "=3Dkeyvalue-pairs")); if (keypairs) { qdict_del(options, "=3Dkeyvalue-pairs"); --=20 2.13.6 From nobody Tue May 7 21:08:57 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 15290727871451002.8775410483214; Fri, 15 Jun 2018 07:26:27 -0700 (PDT) Received: from localhost ([::1]:47145 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpgI-0001tm-D8 for importer@patchew.org; Fri, 15 Jun 2018 10:26:26 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58952) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpbQ-0005w2-Th for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:26 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTpbP-0003Zr-Pw for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:24 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:45846 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fTpbJ-0003Qp-Ec; Fri, 15 Jun 2018 10:21:17 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 136BC88840; Fri, 15 Jun 2018 14:21:17 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-70.ams2.redhat.com [10.36.117.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6313B63A72; Fri, 15 Jun 2018 14:21:16 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 15 Jun 2018 16:20:48 +0200 Message-Id: <20180615142108.27814-7-kwolf@redhat.com> In-Reply-To: <20180615142108.27814-1-kwolf@redhat.com> References: <20180615142108.27814-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Fri, 15 Jun 2018 14:21:17 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Fri, 15 Jun 2018 14:21:17 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL 06/26] iscsi: Drop deprecated -drive parameter "filename" 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 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" From: Markus Armbruster Parameter "filename" is deprecated since commit 5c3ad1a6a8f, v2.10.0. Time to get rid of it. Signed-off-by: Markus Armbruster Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/iscsi.c | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/block/iscsi.c b/block/iscsi.c index c2fbd8a8aa..7e3ea72bd2 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -1713,10 +1713,6 @@ static QemuOptsList runtime_opts =3D { .name =3D "timeout", .type =3D QEMU_OPT_NUMBER, }, - { - .name =3D "filename", - .type =3D QEMU_OPT_STRING, - }, { /* end of list */ } }, }; @@ -1756,27 +1752,12 @@ static int iscsi_open(BlockDriverState *bs, QDict *= options, int flags, char *initiator_name =3D NULL; QemuOpts *opts; Error *local_err =3D NULL; - const char *transport_name, *portal, *target, *filename; + const char *transport_name, *portal, *target; #if LIBISCSI_API_VERSION >=3D (20160603) enum iscsi_transport_type transport; #endif int i, ret =3D 0, timeout =3D 0, lun; =20 - /* If we are given a filename, parse the filename, with precedence giv= en to - * filename encoded options */ - filename =3D qdict_get_try_str(options, "filename"); - if (filename) { - warn_report("'filename' option specified. " - "This is an unsupported option, and may be deprecated " - "in the future"); - iscsi_parse_filename(filename, options, &local_err); - if (local_err) { - ret =3D -EINVAL; - error_propagate(errp, local_err); - goto exit; - } - } - opts =3D qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); qemu_opts_absorb_qdict(opts, options, &local_err); if (local_err) { @@ -2006,7 +1987,7 @@ out: } memset(iscsilun, 0, sizeof(IscsiLun)); } -exit: + return ret; } =20 --=20 2.13.6 From nobody Tue May 7 21:08:57 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 1529073211208348.2234193760596; Fri, 15 Jun 2018 07:33:31 -0700 (PDT) Received: from localhost ([::1]:47192 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpn8-0008Ha-Cw for importer@patchew.org; Fri, 15 Jun 2018 10:33:30 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58992) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpbS-0005xq-9n for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:28 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTpbP-0003a3-SK for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:26 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:54384 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fTpbK-0003SK-Bn; Fri, 15 Jun 2018 10:21:18 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id F25D240122A1; Fri, 15 Jun 2018 14:21:17 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-70.ams2.redhat.com [10.36.117.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4EC6C63A51; Fri, 15 Jun 2018 14:21:17 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 15 Jun 2018 16:20:49 +0200 Message-Id: <20180615142108.27814-8-kwolf@redhat.com> In-Reply-To: <20180615142108.27814-1-kwolf@redhat.com> References: <20180615142108.27814-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Fri, 15 Jun 2018 14:21:18 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Fri, 15 Jun 2018 14:21:18 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL 07/26] block: Add block-specific QDict header 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 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" From: Max Reitz There are numerous QDict functions that have been introduced for and are used only by the block layer. Move their declarations into an own header file to reflect that. While qdict_extract_subqdict() is in fact used outside of the block layer (in util/qemu-config.c), it is still a function related very closely to how the block layer works with nested QDicts, namely by sometimes flattening them. Therefore, its declaration is put into this header as well and util/qemu-config.c includes it with a comment stating exactly which function it needs. Suggested-by: Markus Armbruster Signed-off-by: Max Reitz Message-Id: <20180509165530.29561-7-mreitz@redhat.com> [Copyright note tweaked, superfluous includes dropped] Signed-off-by: Markus Armbruster Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- include/block/qdict.h | 32 ++++++++++++++++++++++++++++++++ include/qapi/qmp/qdict.h | 17 ----------------- block.c | 1 + block/gluster.c | 1 + block/iscsi.c | 1 + block/nbd.c | 1 + block/nfs.c | 1 + block/parallels.c | 1 + block/qcow.c | 1 + block/qcow2.c | 1 + block/qed.c | 1 + block/quorum.c | 1 + block/rbd.c | 1 + block/sheepdog.c | 1 + block/snapshot.c | 1 + block/ssh.c | 1 + block/vhdx.c | 1 + block/vpc.c | 1 + block/vvfat.c | 1 + block/vxhs.c | 1 + blockdev.c | 1 + qobject/qdict.c | 1 + tests/check-qdict.c | 1 + tests/check-qobject.c | 1 + tests/test-replication.c | 1 + util/qemu-config.c | 1 + 26 files changed, 56 insertions(+), 17 deletions(-) create mode 100644 include/block/qdict.h diff --git a/include/block/qdict.h b/include/block/qdict.h new file mode 100644 index 0000000000..71c037afba --- /dev/null +++ b/include/block/qdict.h @@ -0,0 +1,32 @@ +/* + * Special QDict functions used by the block layer + * + * Copyright (c) 2013-2018 Red Hat, Inc. + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or l= ater. + * See the COPYING.LIB file in the top-level directory. + */ + +#ifndef BLOCK_QDICT_H +#define BLOCK_QDICT_H + +#include "qapi/qmp/qdict.h" + +void qdict_copy_default(QDict *dst, QDict *src, const char *key); +void qdict_set_default_str(QDict *dst, const char *key, const char *val); + +void qdict_join(QDict *dest, QDict *src, bool overwrite); + +void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start); +void qdict_array_split(QDict *src, QList **dst); +int qdict_array_entries(QDict *src, const char *subqdict); +QObject *qdict_crumple(const QDict *src, Error **errp); +void qdict_flatten(QDict *qdict); + +typedef struct QDictRenames { + const char *from; + const char *to; +} QDictRenames; +bool qdict_rename_keys(QDict *qdict, const QDictRenames *renames, Error **= errp); + +#endif diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h index 921a28d2d3..7f3ec10a10 100644 --- a/include/qapi/qmp/qdict.h +++ b/include/qapi/qmp/qdict.h @@ -67,23 +67,6 @@ int64_t qdict_get_try_int(const QDict *qdict, const char= *key, bool qdict_get_try_bool(const QDict *qdict, const char *key, bool def_valu= e); const char *qdict_get_try_str(const QDict *qdict, const char *key); =20 -void qdict_copy_default(QDict *dst, QDict *src, const char *key); -void qdict_set_default_str(QDict *dst, const char *key, const char *val); - QDict *qdict_clone_shallow(const QDict *src); -void qdict_flatten(QDict *qdict); - -void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start); -void qdict_array_split(QDict *src, QList **dst); -int qdict_array_entries(QDict *src, const char *subqdict); -QObject *qdict_crumple(const QDict *src, Error **errp); - -void qdict_join(QDict *dest, QDict *src, bool overwrite); - -typedef struct QDictRenames { - const char *from; - const char *to; -} QDictRenames; -bool qdict_rename_keys(QDict *qdict, const QDictRenames *renames, Error **= errp); =20 #endif /* QDICT_H */ diff --git a/block.c b/block.c index 50887087f3..afe30caac3 100644 --- a/block.c +++ b/block.c @@ -27,6 +27,7 @@ #include "block/block_int.h" #include "block/blockjob.h" #include "block/nbd.h" +#include "block/qdict.h" #include "qemu/error-report.h" #include "module_block.h" #include "qemu/module.h" diff --git a/block/gluster.c b/block/gluster.c index 9900b6420c..b5fe7f3e87 100644 --- a/block/gluster.c +++ b/block/gluster.c @@ -11,6 +11,7 @@ #include "qemu/osdep.h" #include #include "block/block_int.h" +#include "block/qdict.h" #include "qapi/error.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qerror.h" diff --git a/block/iscsi.c b/block/iscsi.c index 7e3ea72bd2..9f00fb47a5 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -33,6 +33,7 @@ #include "qemu/bitops.h" #include "qemu/bitmap.h" #include "block/block_int.h" +#include "block/qdict.h" #include "scsi/constants.h" #include "qemu/iov.h" #include "qemu/option.h" diff --git a/block/nbd.c b/block/nbd.c index ff8333e3c1..d6c4c4ddbc 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -28,6 +28,7 @@ =20 #include "qemu/osdep.h" #include "nbd-client.h" +#include "block/qdict.h" #include "qapi/error.h" #include "qemu/uri.h" #include "block/block_int.h" diff --git a/block/nfs.c b/block/nfs.c index 3349b67a76..3170b059b3 100644 --- a/block/nfs.c +++ b/block/nfs.c @@ -29,6 +29,7 @@ #include "qemu/error-report.h" #include "qapi/error.h" #include "block/block_int.h" +#include "block/qdict.h" #include "trace.h" #include "qemu/iov.h" #include "qemu/option.h" diff --git a/block/parallels.c b/block/parallels.c index 6e9c37f44e..c1d9643498 100644 --- a/block/parallels.c +++ b/block/parallels.c @@ -31,6 +31,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "block/block_int.h" +#include "block/qdict.h" #include "sysemu/block-backend.h" #include "qemu/module.h" #include "qemu/option.h" diff --git a/block/qcow.c b/block/qcow.c index 1f866af0d3..8c08908fd8 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -26,6 +26,7 @@ #include "qapi/error.h" #include "qemu/error-report.h" #include "block/block_int.h" +#include "block/qdict.h" #include "sysemu/block-backend.h" #include "qemu/module.h" #include "qemu/option.h" diff --git a/block/qcow2.c b/block/qcow2.c index 6fa5e1d71a..d2d955f984 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -24,6 +24,7 @@ =20 #include "qemu/osdep.h" #include "block/block_int.h" +#include "block/qdict.h" #include "sysemu/block-backend.h" #include "qemu/module.h" #include diff --git a/block/qed.c b/block/qed.c index 65cfe92393..324a953cbc 100644 --- a/block/qed.c +++ b/block/qed.c @@ -13,6 +13,7 @@ */ =20 #include "qemu/osdep.h" +#include "block/qdict.h" #include "qapi/error.h" #include "qemu/timer.h" #include "qemu/bswap.h" diff --git a/block/quorum.c b/block/quorum.c index b6476c405a..9152da8c58 100644 --- a/block/quorum.c +++ b/block/quorum.c @@ -17,6 +17,7 @@ #include "qemu/cutils.h" #include "qemu/option.h" #include "block/block_int.h" +#include "block/qdict.h" #include "qapi/error.h" #include "qapi/qapi-events-block.h" #include "qapi/qmp/qdict.h" diff --git a/block/rbd.c b/block/rbd.c index 40c6e4185f..9659c7361f 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -18,6 +18,7 @@ #include "qemu/error-report.h" #include "qemu/option.h" #include "block/block_int.h" +#include "block/qdict.h" #include "crypto/secret.h" #include "qemu/cutils.h" #include "qapi/qmp/qstring.h" diff --git a/block/sheepdog.c b/block/sheepdog.c index 7b98725af7..2e1f0e6eca 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -24,6 +24,7 @@ #include "qemu/option.h" #include "qemu/sockets.h" #include "block/block_int.h" +#include "block/qdict.h" #include "sysemu/block-backend.h" #include "qemu/bitops.h" #include "qemu/cutils.h" diff --git a/block/snapshot.c b/block/snapshot.c index 2953d96c06..f9903bc94e 100644 --- a/block/snapshot.c +++ b/block/snapshot.c @@ -25,6 +25,7 @@ #include "qemu/osdep.h" #include "block/snapshot.h" #include "block/block_int.h" +#include "block/qdict.h" #include "qapi/error.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qerror.h" diff --git a/block/ssh.c b/block/ssh.c index 4c4fa3ccfc..eec37dd27c 100644 --- a/block/ssh.c +++ b/block/ssh.c @@ -28,6 +28,7 @@ #include =20 #include "block/block_int.h" +#include "block/qdict.h" #include "qapi/error.h" #include "qemu/error-report.h" #include "qemu/option.h" diff --git a/block/vhdx.c b/block/vhdx.c index 0831c5c5f4..2e32e24514 100644 --- a/block/vhdx.c +++ b/block/vhdx.c @@ -18,6 +18,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "block/block_int.h" +#include "block/qdict.h" #include "sysemu/block-backend.h" #include "qemu/module.h" #include "qemu/option.h" diff --git a/block/vpc.c b/block/vpc.c index 0ebfcd3cc8..41c8c980f1 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -26,6 +26,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "block/block_int.h" +#include "block/qdict.h" #include "sysemu/block-backend.h" #include "qemu/module.h" #include "qemu/option.h" diff --git a/block/vvfat.c b/block/vvfat.c index 662dca0114..4595f335b8 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -27,6 +27,7 @@ #include #include "qapi/error.h" #include "block/block_int.h" +#include "block/qdict.h" #include "qemu/module.h" #include "qemu/option.h" #include "qemu/bswap.h" diff --git a/block/vxhs.c b/block/vxhs.c index 339e23218d..0cb0a007e9 100644 --- a/block/vxhs.c +++ b/block/vxhs.c @@ -12,6 +12,7 @@ #include #include #include "block/block_int.h" +#include "block/qdict.h" #include "qapi/qmp/qerror.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qstring.h" diff --git a/blockdev.c b/blockdev.c index 4862323012..c24e261e37 100644 --- a/blockdev.c +++ b/blockdev.c @@ -35,6 +35,7 @@ #include "sysemu/blockdev.h" #include "hw/block/block.h" #include "block/blockjob.h" +#include "block/qdict.h" #include "block/throttle-groups.h" #include "monitor/monitor.h" #include "qemu/error-report.h" diff --git a/qobject/qdict.c b/qobject/qdict.c index 22800eeceb..0554c64553 100644 --- a/qobject/qdict.c +++ b/qobject/qdict.c @@ -11,6 +11,7 @@ */ =20 #include "qemu/osdep.h" +#include "block/qdict.h" #include "qapi/qmp/qnum.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qbool.h" diff --git a/tests/check-qdict.c b/tests/check-qdict.c index eba5d3528e..93e2112b6d 100644 --- a/tests/check-qdict.c +++ b/tests/check-qdict.c @@ -11,6 +11,7 @@ */ =20 #include "qemu/osdep.h" +#include "block/qdict.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qlist.h" #include "qapi/qmp/qnum.h" diff --git a/tests/check-qobject.c b/tests/check-qobject.c index 5cb08fcb63..16ccbde82c 100644 --- a/tests/check-qobject.c +++ b/tests/check-qobject.c @@ -8,6 +8,7 @@ */ =20 #include "qemu/osdep.h" +#include "block/qdict.h" #include "qapi/qmp/qbool.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qlist.h" diff --git a/tests/test-replication.c b/tests/test-replication.c index 68c0d04f2a..c8165ae954 100644 --- a/tests/test-replication.c +++ b/tests/test-replication.c @@ -15,6 +15,7 @@ #include "qemu/option.h" #include "replication.h" #include "block/block_int.h" +#include "block/qdict.h" #include "sysemu/block-backend.h" =20 #define IMG_SIZE (64 * 1024 * 1024) diff --git a/util/qemu-config.c b/util/qemu-config.c index 14d84022dc..9d2e278e29 100644 --- a/util/qemu-config.c +++ b/util/qemu-config.c @@ -1,4 +1,5 @@ #include "qemu/osdep.h" +#include "block/qdict.h" /* for qdict_extract_subqdict() */ #include "qapi/error.h" #include "qapi/qapi-commands-misc.h" #include "qapi/qmp/qdict.h" --=20 2.13.6 From nobody Tue May 7 21:08:57 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 1529074401361853.7053478431336; Fri, 15 Jun 2018 07:53:21 -0700 (PDT) Received: from localhost ([::1]:47313 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTq6K-0007vw-9x for importer@patchew.org; Fri, 15 Jun 2018 10:53:20 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59388) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpbl-0006LG-Do for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTpbd-0003pN-CM for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:45 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:50212 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fTpbL-0003U6-HE; Fri, 15 Jun 2018 10:21:19 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2A2D881A3245; Fri, 15 Jun 2018 14:21:19 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-70.ams2.redhat.com [10.36.117.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3A77B63A51; Fri, 15 Jun 2018 14:21:18 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 15 Jun 2018 16:20:50 +0200 Message-Id: <20180615142108.27814-9-kwolf@redhat.com> In-Reply-To: <20180615142108.27814-1-kwolf@redhat.com> References: <20180615142108.27814-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Fri, 15 Jun 2018 14:21:19 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Fri, 15 Jun 2018 14:21:19 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL 08/26] qobject: Move block-specific qdict code to block-qdict.c 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 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" From: Markus Armbruster Pure code motion, except for two brace placements and a comment tweaked to appease checkpatch. Signed-off-by: Markus Armbruster Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- qobject/block-qdict.c | 640 ++++++++++++++++++++++++++++++++++++++++++= ++ qobject/qdict.c | 629 ------------------------------------------= -- tests/check-block-qdict.c | 655 ++++++++++++++++++++++++++++++++++++++++++= ++++ tests/check-qdict.c | 642 ------------------------------------------= --- MAINTAINERS | 2 + qobject/Makefile.objs | 1 + tests/Makefile.include | 4 + 7 files changed, 1302 insertions(+), 1271 deletions(-) create mode 100644 qobject/block-qdict.c create mode 100644 tests/check-block-qdict.c diff --git a/qobject/block-qdict.c b/qobject/block-qdict.c new file mode 100644 index 0000000000..fb92010dc5 --- /dev/null +++ b/qobject/block-qdict.c @@ -0,0 +1,640 @@ +/* + * Special QDict functions used by the block layer + * + * Copyright (c) 2013-2018 Red Hat, Inc. + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or l= ater. + * See the COPYING.LIB file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "block/qdict.h" +#include "qapi/qmp/qlist.h" +#include "qemu/cutils.h" +#include "qapi/error.h" + +/** + * qdict_copy_default(): If no entry mapped by 'key' exists in 'dst' yet, = the + * value of 'key' in 'src' is copied there (and the refcount increased + * accordingly). + */ +void qdict_copy_default(QDict *dst, QDict *src, const char *key) +{ + QObject *val; + + if (qdict_haskey(dst, key)) { + return; + } + + val =3D qdict_get(src, key); + if (val) { + qdict_put_obj(dst, key, qobject_ref(val)); + } +} + +/** + * qdict_set_default_str(): If no entry mapped by 'key' exists in 'dst' ye= t, a + * new QString initialised by 'val' is put there. + */ +void qdict_set_default_str(QDict *dst, const char *key, const char *val) +{ + if (qdict_haskey(dst, key)) { + return; + } + + qdict_put_str(dst, key, val); +} + +static void qdict_flatten_qdict(QDict *qdict, QDict *target, + const char *prefix); + +static void qdict_flatten_qlist(QList *qlist, QDict *target, const char *p= refix) +{ + QObject *value; + const QListEntry *entry; + char *new_key; + int i; + + /* This function is never called with prefix =3D=3D NULL, i.e., it is = always + * called from within qdict_flatten_q(list|dict)(). Therefore, it does= not + * need to remove list entries during the iteration (the whole list wi= ll be + * deleted eventually anyway from qdict_flatten_qdict()). */ + assert(prefix); + + entry =3D qlist_first(qlist); + + for (i =3D 0; entry; entry =3D qlist_next(entry), i++) { + value =3D qlist_entry_obj(entry); + new_key =3D g_strdup_printf("%s.%i", prefix, i); + + if (qobject_type(value) =3D=3D QTYPE_QDICT) { + qdict_flatten_qdict(qobject_to(QDict, value), target, new_key); + } else if (qobject_type(value) =3D=3D QTYPE_QLIST) { + qdict_flatten_qlist(qobject_to(QList, value), target, new_key); + } else { + /* All other types are moved to the target unchanged. */ + qdict_put_obj(target, new_key, qobject_ref(value)); + } + + g_free(new_key); + } +} + +static void qdict_flatten_qdict(QDict *qdict, QDict *target, const char *p= refix) +{ + QObject *value; + const QDictEntry *entry, *next; + char *new_key; + bool delete; + + entry =3D qdict_first(qdict); + + while (entry !=3D NULL) { + + next =3D qdict_next(qdict, entry); + value =3D qdict_entry_value(entry); + new_key =3D NULL; + delete =3D false; + + if (prefix) { + new_key =3D g_strdup_printf("%s.%s", prefix, entry->key); + } + + if (qobject_type(value) =3D=3D QTYPE_QDICT) { + /* Entries of QDicts are processed recursively, the QDict obje= ct + * itself disappears. */ + qdict_flatten_qdict(qobject_to(QDict, value), target, + new_key ? new_key : entry->key); + delete =3D true; + } else if (qobject_type(value) =3D=3D QTYPE_QLIST) { + qdict_flatten_qlist(qobject_to(QList, value), target, + new_key ? new_key : entry->key); + delete =3D true; + } else if (prefix) { + /* All other objects are moved to the target unchanged. */ + qdict_put_obj(target, new_key, qobject_ref(value)); + delete =3D true; + } + + g_free(new_key); + + if (delete) { + qdict_del(qdict, entry->key); + + /* Restart loop after modifying the iterated QDict */ + entry =3D qdict_first(qdict); + continue; + } + + entry =3D next; + } +} + +/** + * qdict_flatten(): For each nested QDict with key x, all fields with key y + * are moved to this QDict and their key is renamed to "x.y". For each nes= ted + * QList with key x, the field at index y is moved to this QDict with the = key + * "x.y" (i.e., the reverse of what qdict_array_split() does). + * This operation is applied recursively for nested QDicts and QLists. + */ +void qdict_flatten(QDict *qdict) +{ + qdict_flatten_qdict(qdict, qdict, NULL); +} + +/* extract all the src QDict entries starting by start into dst */ +void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start) + +{ + const QDictEntry *entry, *next; + const char *p; + + *dst =3D qdict_new(); + entry =3D qdict_first(src); + + while (entry !=3D NULL) { + next =3D qdict_next(src, entry); + if (strstart(entry->key, start, &p)) { + qdict_put_obj(*dst, p, qobject_ref(entry->value)); + qdict_del(src, entry->key); + } + entry =3D next; + } +} + +static int qdict_count_prefixed_entries(const QDict *src, const char *star= t) +{ + const QDictEntry *entry; + int count =3D 0; + + for (entry =3D qdict_first(src); entry; entry =3D qdict_next(src, entr= y)) { + if (strstart(entry->key, start, NULL)) { + if (count =3D=3D INT_MAX) { + return -ERANGE; + } + count++; + } + } + + return count; +} + +/** + * qdict_array_split(): This function moves array-like elements of a QDict= into + * a new QList. Every entry in the original QDict with a key "%u" or one + * prefixed "%u.", where %u designates an unsigned integer starting at 0 a= nd + * incrementally counting up, will be moved to a new QDict at index %u in = the + * output QList with the key prefix removed, if that prefix is "%u.". If t= he + * whole key is just "%u", the whole QObject will be moved unchanged witho= ut + * creating a new QDict. The function terminates when there is no entry in= the + * QDict with a prefix directly (incrementally) following the last one; it= also + * returns if there are both entries with "%u" and "%u." for the same inde= x %u. + * Example: {"0.a": 42, "0.b": 23, "1.x": 0, "4.y": 1, "o.o": 7, "2": 66} + * (or {"1.x": 0, "4.y": 1, "0.a": 42, "o.o": 7, "0.b": 23, "2": 66}) + * =3D> [{"a": 42, "b": 23}, {"x": 0}, 66] + * and {"4.y": 1, "o.o": 7} (remainder of the old QDict) + */ +void qdict_array_split(QDict *src, QList **dst) +{ + unsigned i; + + *dst =3D qlist_new(); + + for (i =3D 0; i < UINT_MAX; i++) { + QObject *subqobj; + bool is_subqdict; + QDict *subqdict; + char indexstr[32], prefix[32]; + size_t snprintf_ret; + + snprintf_ret =3D snprintf(indexstr, 32, "%u", i); + assert(snprintf_ret < 32); + + subqobj =3D qdict_get(src, indexstr); + + snprintf_ret =3D snprintf(prefix, 32, "%u.", i); + assert(snprintf_ret < 32); + + /* Overflow is the same as positive non-zero results */ + is_subqdict =3D qdict_count_prefixed_entries(src, prefix); + + /* + * There may be either a single subordinate object (named + * "%u") or multiple objects (each with a key prefixed "%u."), + * but not both. + */ + if (!subqobj =3D=3D !is_subqdict) { + break; + } + + if (is_subqdict) { + qdict_extract_subqdict(src, &subqdict, prefix); + assert(qdict_size(subqdict) > 0); + } else { + qobject_ref(subqobj); + qdict_del(src, indexstr); + } + + qlist_append_obj(*dst, subqobj ?: QOBJECT(subqdict)); + } +} + +/** + * qdict_split_flat_key: + * @key: the key string to split + * @prefix: non-NULL pointer to hold extracted prefix + * @suffix: non-NULL pointer to remaining suffix + * + * Given a flattened key such as 'foo.0.bar', split it into two parts + * at the first '.' separator. Allows double dot ('..') to escape the + * normal separator. + * + * e.g. + * 'foo.0.bar' -> prefix=3D'foo' and suffix=3D'0.bar' + * 'foo..0.bar' -> prefix=3D'foo.0' and suffix=3D'bar' + * + * The '..' sequence will be unescaped in the returned 'prefix' + * string. The 'suffix' string will be left in escaped format, so it + * can be fed back into the qdict_split_flat_key() key as the input + * later. + * + * The caller is responsible for freeing the string returned in @prefix + * using g_free(). + */ +static void qdict_split_flat_key(const char *key, char **prefix, + const char **suffix) +{ + const char *separator; + size_t i, j; + + /* Find first '.' separator, but if there is a pair '..' + * that acts as an escape, so skip over '..' */ + separator =3D NULL; + do { + if (separator) { + separator +=3D 2; + } else { + separator =3D key; + } + separator =3D strchr(separator, '.'); + } while (separator && separator[1] =3D=3D '.'); + + if (separator) { + *prefix =3D g_strndup(key, separator - key); + *suffix =3D separator + 1; + } else { + *prefix =3D g_strdup(key); + *suffix =3D NULL; + } + + /* Unescape the '..' sequence into '.' */ + for (i =3D 0, j =3D 0; (*prefix)[i] !=3D '\0'; i++, j++) { + if ((*prefix)[i] =3D=3D '.') { + assert((*prefix)[i + 1] =3D=3D '.'); + i++; + } + (*prefix)[j] =3D (*prefix)[i]; + } + (*prefix)[j] =3D '\0'; +} + +/** + * qdict_is_list: + * @maybe_list: dict to check if keys represent list elements. + * + * Determine whether all keys in @maybe_list are valid list elements. + * If @maybe_list is non-zero in length and all the keys look like + * valid list indexes, this will return 1. If @maybe_list is zero + * length or all keys are non-numeric then it will return 0 to indicate + * it is a normal qdict. If there is a mix of numeric and non-numeric + * keys, or the list indexes are non-contiguous, an error is reported. + * + * Returns: 1 if a valid list, 0 if a dict, -1 on error + */ +static int qdict_is_list(QDict *maybe_list, Error **errp) +{ + const QDictEntry *ent; + ssize_t len =3D 0; + ssize_t max =3D -1; + int is_list =3D -1; + int64_t val; + + for (ent =3D qdict_first(maybe_list); ent !=3D NULL; + ent =3D qdict_next(maybe_list, ent)) { + + if (qemu_strtoi64(ent->key, NULL, 10, &val) =3D=3D 0) { + if (is_list =3D=3D -1) { + is_list =3D 1; + } else if (!is_list) { + error_setg(errp, + "Cannot mix list and non-list keys"); + return -1; + } + len++; + if (val > max) { + max =3D val; + } + } else { + if (is_list =3D=3D -1) { + is_list =3D 0; + } else if (is_list) { + error_setg(errp, + "Cannot mix list and non-list keys"); + return -1; + } + } + } + + if (is_list =3D=3D -1) { + assert(!qdict_size(maybe_list)); + is_list =3D 0; + } + + /* NB this isn't a perfect check - e.g. it won't catch + * a list containing '1', '+1', '01', '3', but that + * does not matter - we've still proved that the + * input is a list. It is up the caller to do a + * stricter check if desired */ + if (len !=3D (max + 1)) { + error_setg(errp, "List indices are not contiguous, " + "saw %zd elements but %zd largest index", + len, max); + return -1; + } + + return is_list; +} + +/** + * qdict_crumple: + * @src: the original flat dictionary (only scalar values) to crumple + * + * Takes a flat dictionary whose keys use '.' separator to indicate + * nesting, and values are scalars, and crumples it into a nested + * structure. + * + * To include a literal '.' in a key name, it must be escaped as '..' + * + * For example, an input of: + * + * { 'foo.0.bar': 'one', 'foo.0.wizz': '1', + * 'foo.1.bar': 'two', 'foo.1.wizz': '2' } + * + * will result in an output of: + * + * { + * 'foo': [ + * { 'bar': 'one', 'wizz': '1' }, + * { 'bar': 'two', 'wizz': '2' } + * ], + * } + * + * The following scenarios in the input dict will result in an + * error being returned: + * + * - Any values in @src are non-scalar types + * - If keys in @src imply that a particular level is both a + * list and a dict. e.g., "foo.0.bar" and "foo.eek.bar". + * - If keys in @src imply that a particular level is a list, + * but the indices are non-contiguous. e.g. "foo.0.bar" and + * "foo.2.bar" without any "foo.1.bar" present. + * - If keys in @src represent list indexes, but are not in + * the "%zu" format. e.g. "foo.+0.bar" + * + * Returns: either a QDict or QList for the nested data structure, or NULL + * on error + */ +QObject *qdict_crumple(const QDict *src, Error **errp) +{ + const QDictEntry *ent; + QDict *two_level, *multi_level =3D NULL; + QObject *dst =3D NULL, *child; + size_t i; + char *prefix =3D NULL; + const char *suffix =3D NULL; + int is_list; + + two_level =3D qdict_new(); + + /* Step 1: split our totally flat dict into a two level dict */ + for (ent =3D qdict_first(src); ent !=3D NULL; ent =3D qdict_next(src, = ent)) { + if (qobject_type(ent->value) =3D=3D QTYPE_QDICT || + qobject_type(ent->value) =3D=3D QTYPE_QLIST) { + error_setg(errp, "Value %s is not a scalar", + ent->key); + goto error; + } + + qdict_split_flat_key(ent->key, &prefix, &suffix); + + child =3D qdict_get(two_level, prefix); + if (suffix) { + QDict *child_dict =3D qobject_to(QDict, child); + if (!child_dict) { + if (child) { + error_setg(errp, "Key %s prefix is already set as a sc= alar", + prefix); + goto error; + } + + child_dict =3D qdict_new(); + qdict_put_obj(two_level, prefix, QOBJECT(child_dict)); + } + + qdict_put_obj(child_dict, suffix, qobject_ref(ent->value)); + } else { + if (child) { + error_setg(errp, "Key %s prefix is already set as a dict", + prefix); + goto error; + } + qdict_put_obj(two_level, prefix, qobject_ref(ent->value)); + } + + g_free(prefix); + prefix =3D NULL; + } + + /* Step 2: optionally process the two level dict recursively + * into a multi-level dict */ + multi_level =3D qdict_new(); + for (ent =3D qdict_first(two_level); ent !=3D NULL; + ent =3D qdict_next(two_level, ent)) { + QDict *dict =3D qobject_to(QDict, ent->value); + if (dict) { + child =3D qdict_crumple(dict, errp); + if (!child) { + goto error; + } + + qdict_put_obj(multi_level, ent->key, child); + } else { + qdict_put_obj(multi_level, ent->key, qobject_ref(ent->value)); + } + } + qobject_unref(two_level); + two_level =3D NULL; + + /* Step 3: detect if we need to turn our dict into list */ + is_list =3D qdict_is_list(multi_level, errp); + if (is_list < 0) { + goto error; + } + + if (is_list) { + dst =3D QOBJECT(qlist_new()); + + for (i =3D 0; i < qdict_size(multi_level); i++) { + char *key =3D g_strdup_printf("%zu", i); + + child =3D qdict_get(multi_level, key); + g_free(key); + + if (!child) { + error_setg(errp, "Missing list index %zu", i); + goto error; + } + + qlist_append_obj(qobject_to(QList, dst), qobject_ref(child)); + } + qobject_unref(multi_level); + multi_level =3D NULL; + } else { + dst =3D QOBJECT(multi_level); + } + + return dst; + + error: + g_free(prefix); + qobject_unref(multi_level); + qobject_unref(two_level); + qobject_unref(dst); + return NULL; +} + +/** + * qdict_array_entries(): Returns the number of direct array entries if the + * sub-QDict of src specified by the prefix in subqdict (or src itself for + * prefix =3D=3D "") is valid as an array, i.e. the length of the created = list if + * the sub-QDict would become empty after calling qdict_array_split() on i= t. If + * the array is not valid, -EINVAL is returned. + */ +int qdict_array_entries(QDict *src, const char *subqdict) +{ + const QDictEntry *entry; + unsigned i; + unsigned entries =3D 0; + size_t subqdict_len =3D strlen(subqdict); + + assert(!subqdict_len || subqdict[subqdict_len - 1] =3D=3D '.'); + + /* qdict_array_split() loops until UINT_MAX, but as we want to return + * negative errors, we only have a signed return value here. Any addit= ional + * entries will lead to -EINVAL. */ + for (i =3D 0; i < INT_MAX; i++) { + QObject *subqobj; + int subqdict_entries; + char *prefix =3D g_strdup_printf("%s%u.", subqdict, i); + + subqdict_entries =3D qdict_count_prefixed_entries(src, prefix); + + /* Remove ending "." */ + prefix[strlen(prefix) - 1] =3D 0; + subqobj =3D qdict_get(src, prefix); + + g_free(prefix); + + if (subqdict_entries < 0) { + return subqdict_entries; + } + + /* There may be either a single subordinate object (named "%u") or + * multiple objects (each with a key prefixed "%u."), but not both= . */ + if (subqobj && subqdict_entries) { + return -EINVAL; + } else if (!subqobj && !subqdict_entries) { + break; + } + + entries +=3D subqdict_entries ? subqdict_entries : 1; + } + + /* Consider everything handled that isn't part of the given sub-QDict = */ + for (entry =3D qdict_first(src); entry; entry =3D qdict_next(src, entr= y)) { + if (!strstart(qdict_entry_key(entry), subqdict, NULL)) { + entries++; + } + } + + /* Anything left in the sub-QDict that wasn't handled? */ + if (qdict_size(src) !=3D entries) { + return -EINVAL; + } + + return i; +} + +/** + * qdict_join(): Absorb the src QDict into the dest QDict, that is, move a= ll + * elements from src to dest. + * + * If an element from src has a key already present in dest, it will not be + * moved unless overwrite is true. + * + * If overwrite is true, the conflicting values in dest will be discarded = and + * replaced by the corresponding values from src. + * + * Therefore, with overwrite being true, the src QDict will always be empt= y when + * this function returns. If overwrite is false, the src QDict will be emp= ty + * iff there were no conflicts. + */ +void qdict_join(QDict *dest, QDict *src, bool overwrite) +{ + const QDictEntry *entry, *next; + + entry =3D qdict_first(src); + while (entry) { + next =3D qdict_next(src, entry); + + if (overwrite || !qdict_haskey(dest, entry->key)) { + qdict_put_obj(dest, entry->key, qobject_ref(entry->value)); + qdict_del(src, entry->key); + } + + entry =3D next; + } +} + +/** + * qdict_rename_keys(): Rename keys in qdict according to the replacements + * specified in the array renames. The array must be terminated by an entry + * with from =3D NULL. + * + * The renames are performed individually in the order of the array, so en= tries + * may be renamed multiple times and may or may not conflict depending on = the + * order of the renames array. + * + * Returns true for success, false in error cases. + */ +bool qdict_rename_keys(QDict *qdict, const QDictRenames *renames, Error **= errp) +{ + QObject *qobj; + + while (renames->from) { + if (qdict_haskey(qdict, renames->from)) { + if (qdict_haskey(qdict, renames->to)) { + error_setg(errp, "'%s' and its alias '%s' can't be used at= the " + "same time", renames->to, renames->from); + return false; + } + + qobj =3D qdict_get(qdict, renames->from); + qdict_put_obj(qdict, renames->to, qobject_ref(qobj)); + qdict_del(qdict, renames->from); + } + + renames++; + } + return true; +} diff --git a/qobject/qdict.c b/qobject/qdict.c index 0554c64553..3d8c2f7bbc 100644 --- a/qobject/qdict.c +++ b/qobject/qdict.c @@ -11,17 +11,11 @@ */ =20 #include "qemu/osdep.h" -#include "block/qdict.h" #include "qapi/qmp/qnum.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qbool.h" -#include "qapi/qmp/qlist.h" #include "qapi/qmp/qnull.h" #include "qapi/qmp/qstring.h" -#include "qapi/error.h" -#include "qemu/queue.h" -#include "qemu-common.h" -#include "qemu/cutils.h" =20 /** * qdict_new(): Create a new QDict @@ -464,626 +458,3 @@ void qdict_destroy_obj(QObject *obj) =20 g_free(qdict); } - -/** - * qdict_copy_default(): If no entry mapped by 'key' exists in 'dst' yet, = the - * value of 'key' in 'src' is copied there (and the refcount increased - * accordingly). - */ -void qdict_copy_default(QDict *dst, QDict *src, const char *key) -{ - QObject *val; - - if (qdict_haskey(dst, key)) { - return; - } - - val =3D qdict_get(src, key); - if (val) { - qdict_put_obj(dst, key, qobject_ref(val)); - } -} - -/** - * qdict_set_default_str(): If no entry mapped by 'key' exists in 'dst' ye= t, a - * new QString initialised by 'val' is put there. - */ -void qdict_set_default_str(QDict *dst, const char *key, const char *val) -{ - if (qdict_haskey(dst, key)) { - return; - } - - qdict_put_str(dst, key, val); -} - -static void qdict_flatten_qdict(QDict *qdict, QDict *target, - const char *prefix); - -static void qdict_flatten_qlist(QList *qlist, QDict *target, const char *p= refix) -{ - QObject *value; - const QListEntry *entry; - char *new_key; - int i; - - /* This function is never called with prefix =3D=3D NULL, i.e., it is = always - * called from within qdict_flatten_q(list|dict)(). Therefore, it does= not - * need to remove list entries during the iteration (the whole list wi= ll be - * deleted eventually anyway from qdict_flatten_qdict()). */ - assert(prefix); - - entry =3D qlist_first(qlist); - - for (i =3D 0; entry; entry =3D qlist_next(entry), i++) { - value =3D qlist_entry_obj(entry); - new_key =3D g_strdup_printf("%s.%i", prefix, i); - - if (qobject_type(value) =3D=3D QTYPE_QDICT) { - qdict_flatten_qdict(qobject_to(QDict, value), target, new_key); - } else if (qobject_type(value) =3D=3D QTYPE_QLIST) { - qdict_flatten_qlist(qobject_to(QList, value), target, new_key); - } else { - /* All other types are moved to the target unchanged. */ - qdict_put_obj(target, new_key, qobject_ref(value)); - } - - g_free(new_key); - } -} - -static void qdict_flatten_qdict(QDict *qdict, QDict *target, const char *p= refix) -{ - QObject *value; - const QDictEntry *entry, *next; - char *new_key; - bool delete; - - entry =3D qdict_first(qdict); - - while (entry !=3D NULL) { - - next =3D qdict_next(qdict, entry); - value =3D qdict_entry_value(entry); - new_key =3D NULL; - delete =3D false; - - if (prefix) { - new_key =3D g_strdup_printf("%s.%s", prefix, entry->key); - } - - if (qobject_type(value) =3D=3D QTYPE_QDICT) { - /* Entries of QDicts are processed recursively, the QDict obje= ct - * itself disappears. */ - qdict_flatten_qdict(qobject_to(QDict, value), target, - new_key ? new_key : entry->key); - delete =3D true; - } else if (qobject_type(value) =3D=3D QTYPE_QLIST) { - qdict_flatten_qlist(qobject_to(QList, value), target, - new_key ? new_key : entry->key); - delete =3D true; - } else if (prefix) { - /* All other objects are moved to the target unchanged. */ - qdict_put_obj(target, new_key, qobject_ref(value)); - delete =3D true; - } - - g_free(new_key); - - if (delete) { - qdict_del(qdict, entry->key); - - /* Restart loop after modifying the iterated QDict */ - entry =3D qdict_first(qdict); - continue; - } - - entry =3D next; - } -} - -/** - * qdict_flatten(): For each nested QDict with key x, all fields with key y - * are moved to this QDict and their key is renamed to "x.y". For each nes= ted - * QList with key x, the field at index y is moved to this QDict with the = key - * "x.y" (i.e., the reverse of what qdict_array_split() does). - * This operation is applied recursively for nested QDicts and QLists. - */ -void qdict_flatten(QDict *qdict) -{ - qdict_flatten_qdict(qdict, qdict, NULL); -} - -/* extract all the src QDict entries starting by start into dst */ -void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start) - -{ - const QDictEntry *entry, *next; - const char *p; - - *dst =3D qdict_new(); - entry =3D qdict_first(src); - - while (entry !=3D NULL) { - next =3D qdict_next(src, entry); - if (strstart(entry->key, start, &p)) { - qdict_put_obj(*dst, p, qobject_ref(entry->value)); - qdict_del(src, entry->key); - } - entry =3D next; - } -} - -static int qdict_count_prefixed_entries(const QDict *src, const char *star= t) -{ - const QDictEntry *entry; - int count =3D 0; - - for (entry =3D qdict_first(src); entry; entry =3D qdict_next(src, entr= y)) { - if (strstart(entry->key, start, NULL)) { - if (count =3D=3D INT_MAX) { - return -ERANGE; - } - count++; - } - } - - return count; -} - -/** - * qdict_array_split(): This function moves array-like elements of a QDict= into - * a new QList. Every entry in the original QDict with a key "%u" or one - * prefixed "%u.", where %u designates an unsigned integer starting at 0 a= nd - * incrementally counting up, will be moved to a new QDict at index %u in = the - * output QList with the key prefix removed, if that prefix is "%u.". If t= he - * whole key is just "%u", the whole QObject will be moved unchanged witho= ut - * creating a new QDict. The function terminates when there is no entry in= the - * QDict with a prefix directly (incrementally) following the last one; it= also - * returns if there are both entries with "%u" and "%u." for the same inde= x %u. - * Example: {"0.a": 42, "0.b": 23, "1.x": 0, "4.y": 1, "o.o": 7, "2": 66} - * (or {"1.x": 0, "4.y": 1, "0.a": 42, "o.o": 7, "0.b": 23, "2": 66}) - * =3D> [{"a": 42, "b": 23}, {"x": 0}, 66] - * and {"4.y": 1, "o.o": 7} (remainder of the old QDict) - */ -void qdict_array_split(QDict *src, QList **dst) -{ - unsigned i; - - *dst =3D qlist_new(); - - for (i =3D 0; i < UINT_MAX; i++) { - QObject *subqobj; - bool is_subqdict; - QDict *subqdict; - char indexstr[32], prefix[32]; - size_t snprintf_ret; - - snprintf_ret =3D snprintf(indexstr, 32, "%u", i); - assert(snprintf_ret < 32); - - subqobj =3D qdict_get(src, indexstr); - - snprintf_ret =3D snprintf(prefix, 32, "%u.", i); - assert(snprintf_ret < 32); - - /* Overflow is the same as positive non-zero results */ - is_subqdict =3D qdict_count_prefixed_entries(src, prefix); - - // There may be either a single subordinate object (named "%u") or - // multiple objects (each with a key prefixed "%u."), but not both. - if (!subqobj =3D=3D !is_subqdict) { - break; - } - - if (is_subqdict) { - qdict_extract_subqdict(src, &subqdict, prefix); - assert(qdict_size(subqdict) > 0); - } else { - qobject_ref(subqobj); - qdict_del(src, indexstr); - } - - qlist_append_obj(*dst, subqobj ?: QOBJECT(subqdict)); - } -} - -/** - * qdict_split_flat_key: - * @key: the key string to split - * @prefix: non-NULL pointer to hold extracted prefix - * @suffix: non-NULL pointer to remaining suffix - * - * Given a flattened key such as 'foo.0.bar', split it into two parts - * at the first '.' separator. Allows double dot ('..') to escape the - * normal separator. - * - * e.g. - * 'foo.0.bar' -> prefix=3D'foo' and suffix=3D'0.bar' - * 'foo..0.bar' -> prefix=3D'foo.0' and suffix=3D'bar' - * - * The '..' sequence will be unescaped in the returned 'prefix' - * string. The 'suffix' string will be left in escaped format, so it - * can be fed back into the qdict_split_flat_key() key as the input - * later. - * - * The caller is responsible for freeing the string returned in @prefix - * using g_free(). - */ -static void qdict_split_flat_key(const char *key, char **prefix, - const char **suffix) -{ - const char *separator; - size_t i, j; - - /* Find first '.' separator, but if there is a pair '..' - * that acts as an escape, so skip over '..' */ - separator =3D NULL; - do { - if (separator) { - separator +=3D 2; - } else { - separator =3D key; - } - separator =3D strchr(separator, '.'); - } while (separator && separator[1] =3D=3D '.'); - - if (separator) { - *prefix =3D g_strndup(key, separator - key); - *suffix =3D separator + 1; - } else { - *prefix =3D g_strdup(key); - *suffix =3D NULL; - } - - /* Unescape the '..' sequence into '.' */ - for (i =3D 0, j =3D 0; (*prefix)[i] !=3D '\0'; i++, j++) { - if ((*prefix)[i] =3D=3D '.') { - assert((*prefix)[i + 1] =3D=3D '.'); - i++; - } - (*prefix)[j] =3D (*prefix)[i]; - } - (*prefix)[j] =3D '\0'; -} - -/** - * qdict_is_list: - * @maybe_list: dict to check if keys represent list elements. - * - * Determine whether all keys in @maybe_list are valid list elements. - * If @maybe_list is non-zero in length and all the keys look like - * valid list indexes, this will return 1. If @maybe_list is zero - * length or all keys are non-numeric then it will return 0 to indicate - * it is a normal qdict. If there is a mix of numeric and non-numeric - * keys, or the list indexes are non-contiguous, an error is reported. - * - * Returns: 1 if a valid list, 0 if a dict, -1 on error - */ -static int qdict_is_list(QDict *maybe_list, Error **errp) -{ - const QDictEntry *ent; - ssize_t len =3D 0; - ssize_t max =3D -1; - int is_list =3D -1; - int64_t val; - - for (ent =3D qdict_first(maybe_list); ent !=3D NULL; - ent =3D qdict_next(maybe_list, ent)) { - - if (qemu_strtoi64(ent->key, NULL, 10, &val) =3D=3D 0) { - if (is_list =3D=3D -1) { - is_list =3D 1; - } else if (!is_list) { - error_setg(errp, - "Cannot mix list and non-list keys"); - return -1; - } - len++; - if (val > max) { - max =3D val; - } - } else { - if (is_list =3D=3D -1) { - is_list =3D 0; - } else if (is_list) { - error_setg(errp, - "Cannot mix list and non-list keys"); - return -1; - } - } - } - - if (is_list =3D=3D -1) { - assert(!qdict_size(maybe_list)); - is_list =3D 0; - } - - /* NB this isn't a perfect check - e.g. it won't catch - * a list containing '1', '+1', '01', '3', but that - * does not matter - we've still proved that the - * input is a list. It is up the caller to do a - * stricter check if desired */ - if (len !=3D (max + 1)) { - error_setg(errp, "List indices are not contiguous, " - "saw %zd elements but %zd largest index", - len, max); - return -1; - } - - return is_list; -} - -/** - * qdict_crumple: - * @src: the original flat dictionary (only scalar values) to crumple - * - * Takes a flat dictionary whose keys use '.' separator to indicate - * nesting, and values are scalars, and crumples it into a nested - * structure. - * - * To include a literal '.' in a key name, it must be escaped as '..' - * - * For example, an input of: - * - * { 'foo.0.bar': 'one', 'foo.0.wizz': '1', - * 'foo.1.bar': 'two', 'foo.1.wizz': '2' } - * - * will result in an output of: - * - * { - * 'foo': [ - * { 'bar': 'one', 'wizz': '1' }, - * { 'bar': 'two', 'wizz': '2' } - * ], - * } - * - * The following scenarios in the input dict will result in an - * error being returned: - * - * - Any values in @src are non-scalar types - * - If keys in @src imply that a particular level is both a - * list and a dict. e.g., "foo.0.bar" and "foo.eek.bar". - * - If keys in @src imply that a particular level is a list, - * but the indices are non-contiguous. e.g. "foo.0.bar" and - * "foo.2.bar" without any "foo.1.bar" present. - * - If keys in @src represent list indexes, but are not in - * the "%zu" format. e.g. "foo.+0.bar" - * - * Returns: either a QDict or QList for the nested data structure, or NULL - * on error - */ -QObject *qdict_crumple(const QDict *src, Error **errp) -{ - const QDictEntry *ent; - QDict *two_level, *multi_level =3D NULL; - QObject *dst =3D NULL, *child; - size_t i; - char *prefix =3D NULL; - const char *suffix =3D NULL; - int is_list; - - two_level =3D qdict_new(); - - /* Step 1: split our totally flat dict into a two level dict */ - for (ent =3D qdict_first(src); ent !=3D NULL; ent =3D qdict_next(src, = ent)) { - if (qobject_type(ent->value) =3D=3D QTYPE_QDICT || - qobject_type(ent->value) =3D=3D QTYPE_QLIST) { - error_setg(errp, "Value %s is not a scalar", - ent->key); - goto error; - } - - qdict_split_flat_key(ent->key, &prefix, &suffix); - - child =3D qdict_get(two_level, prefix); - if (suffix) { - QDict *child_dict =3D qobject_to(QDict, child); - if (!child_dict) { - if (child) { - error_setg(errp, "Key %s prefix is already set as a sc= alar", - prefix); - goto error; - } - - child_dict =3D qdict_new(); - qdict_put_obj(two_level, prefix, QOBJECT(child_dict)); - } - - qdict_put_obj(child_dict, suffix, qobject_ref(ent->value)); - } else { - if (child) { - error_setg(errp, "Key %s prefix is already set as a dict", - prefix); - goto error; - } - qdict_put_obj(two_level, prefix, qobject_ref(ent->value)); - } - - g_free(prefix); - prefix =3D NULL; - } - - /* Step 2: optionally process the two level dict recursively - * into a multi-level dict */ - multi_level =3D qdict_new(); - for (ent =3D qdict_first(two_level); ent !=3D NULL; - ent =3D qdict_next(two_level, ent)) { - QDict *dict =3D qobject_to(QDict, ent->value); - if (dict) { - child =3D qdict_crumple(dict, errp); - if (!child) { - goto error; - } - - qdict_put_obj(multi_level, ent->key, child); - } else { - qdict_put_obj(multi_level, ent->key, qobject_ref(ent->value)); - } - } - qobject_unref(two_level); - two_level =3D NULL; - - /* Step 3: detect if we need to turn our dict into list */ - is_list =3D qdict_is_list(multi_level, errp); - if (is_list < 0) { - goto error; - } - - if (is_list) { - dst =3D QOBJECT(qlist_new()); - - for (i =3D 0; i < qdict_size(multi_level); i++) { - char *key =3D g_strdup_printf("%zu", i); - - child =3D qdict_get(multi_level, key); - g_free(key); - - if (!child) { - error_setg(errp, "Missing list index %zu", i); - goto error; - } - - qlist_append_obj(qobject_to(QList, dst), qobject_ref(child)); - } - qobject_unref(multi_level); - multi_level =3D NULL; - } else { - dst =3D QOBJECT(multi_level); - } - - return dst; - - error: - g_free(prefix); - qobject_unref(multi_level); - qobject_unref(two_level); - qobject_unref(dst); - return NULL; -} - -/** - * qdict_array_entries(): Returns the number of direct array entries if the - * sub-QDict of src specified by the prefix in subqdict (or src itself for - * prefix =3D=3D "") is valid as an array, i.e. the length of the created = list if - * the sub-QDict would become empty after calling qdict_array_split() on i= t. If - * the array is not valid, -EINVAL is returned. - */ -int qdict_array_entries(QDict *src, const char *subqdict) -{ - const QDictEntry *entry; - unsigned i; - unsigned entries =3D 0; - size_t subqdict_len =3D strlen(subqdict); - - assert(!subqdict_len || subqdict[subqdict_len - 1] =3D=3D '.'); - - /* qdict_array_split() loops until UINT_MAX, but as we want to return - * negative errors, we only have a signed return value here. Any addit= ional - * entries will lead to -EINVAL. */ - for (i =3D 0; i < INT_MAX; i++) { - QObject *subqobj; - int subqdict_entries; - char *prefix =3D g_strdup_printf("%s%u.", subqdict, i); - - subqdict_entries =3D qdict_count_prefixed_entries(src, prefix); - - /* Remove ending "." */ - prefix[strlen(prefix) - 1] =3D 0; - subqobj =3D qdict_get(src, prefix); - - g_free(prefix); - - if (subqdict_entries < 0) { - return subqdict_entries; - } - - /* There may be either a single subordinate object (named "%u") or - * multiple objects (each with a key prefixed "%u."), but not both= . */ - if (subqobj && subqdict_entries) { - return -EINVAL; - } else if (!subqobj && !subqdict_entries) { - break; - } - - entries +=3D subqdict_entries ? subqdict_entries : 1; - } - - /* Consider everything handled that isn't part of the given sub-QDict = */ - for (entry =3D qdict_first(src); entry; entry =3D qdict_next(src, entr= y)) { - if (!strstart(qdict_entry_key(entry), subqdict, NULL)) { - entries++; - } - } - - /* Anything left in the sub-QDict that wasn't handled? */ - if (qdict_size(src) !=3D entries) { - return -EINVAL; - } - - return i; -} - -/** - * qdict_join(): Absorb the src QDict into the dest QDict, that is, move a= ll - * elements from src to dest. - * - * If an element from src has a key already present in dest, it will not be - * moved unless overwrite is true. - * - * If overwrite is true, the conflicting values in dest will be discarded = and - * replaced by the corresponding values from src. - * - * Therefore, with overwrite being true, the src QDict will always be empt= y when - * this function returns. If overwrite is false, the src QDict will be emp= ty - * iff there were no conflicts. - */ -void qdict_join(QDict *dest, QDict *src, bool overwrite) -{ - const QDictEntry *entry, *next; - - entry =3D qdict_first(src); - while (entry) { - next =3D qdict_next(src, entry); - - if (overwrite || !qdict_haskey(dest, entry->key)) { - qdict_put_obj(dest, entry->key, qobject_ref(entry->value)); - qdict_del(src, entry->key); - } - - entry =3D next; - } -} - -/** - * qdict_rename_keys(): Rename keys in qdict according to the replacements - * specified in the array renames. The array must be terminated by an entry - * with from =3D NULL. - * - * The renames are performed individually in the order of the array, so en= tries - * may be renamed multiple times and may or may not conflict depending on = the - * order of the renames array. - * - * Returns true for success, false in error cases. - */ -bool qdict_rename_keys(QDict *qdict, const QDictRenames *renames, Error **= errp) -{ - QObject *qobj; - - while (renames->from) { - if (qdict_haskey(qdict, renames->from)) { - if (qdict_haskey(qdict, renames->to)) { - error_setg(errp, "'%s' and its alias '%s' can't be used at= the " - "same time", renames->to, renames->from); - return false; - } - - qobj =3D qdict_get(qdict, renames->from); - qdict_put_obj(qdict, renames->to, qobject_ref(qobj)); - qdict_del(qdict, renames->from); - } - - renames++; - } - return true; -} diff --git a/tests/check-block-qdict.c b/tests/check-block-qdict.c new file mode 100644 index 0000000000..5b9f4d506e --- /dev/null +++ b/tests/check-block-qdict.c @@ -0,0 +1,655 @@ +/* + * Unit-tests for Block layer QDict extras + * + * Copyright (c) 2013-2018 Red Hat, Inc. + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or l= ater. + * See the COPYING.LIB file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "block/qdict.h" +#include "qapi/qmp/qlist.h" +#include "qapi/qmp/qnum.h" +#include "qapi/error.h" + +static void qdict_defaults_test(void) +{ + QDict *dict, *copy; + + dict =3D qdict_new(); + copy =3D qdict_new(); + + qdict_set_default_str(dict, "foo", "abc"); + qdict_set_default_str(dict, "foo", "def"); + g_assert_cmpstr(qdict_get_str(dict, "foo"), =3D=3D, "abc"); + qdict_set_default_str(dict, "bar", "ghi"); + + qdict_copy_default(copy, dict, "foo"); + g_assert_cmpstr(qdict_get_str(copy, "foo"), =3D=3D, "abc"); + qdict_set_default_str(copy, "bar", "xyz"); + qdict_copy_default(copy, dict, "bar"); + g_assert_cmpstr(qdict_get_str(copy, "bar"), =3D=3D, "xyz"); + + qobject_unref(copy); + qobject_unref(dict); +} + +static void qdict_flatten_test(void) +{ + QList *list1 =3D qlist_new(); + QList *list2 =3D qlist_new(); + QDict *dict1 =3D qdict_new(); + QDict *dict2 =3D qdict_new(); + QDict *dict3 =3D qdict_new(); + + /* + * Test the flattening of + * + * { + * "e": [ + * 42, + * [ + * 23, + * 66, + * { + * "a": 0, + * "b": 1 + * } + * ] + * ], + * "f": { + * "c": 2, + * "d": 3, + * }, + * "g": 4 + * } + * + * to + * + * { + * "e.0": 42, + * "e.1.0": 23, + * "e.1.1": 66, + * "e.1.2.a": 0, + * "e.1.2.b": 1, + * "f.c": 2, + * "f.d": 3, + * "g": 4 + * } + */ + + qdict_put_int(dict1, "a", 0); + qdict_put_int(dict1, "b", 1); + + qlist_append_int(list1, 23); + qlist_append_int(list1, 66); + qlist_append(list1, dict1); + qlist_append_int(list2, 42); + qlist_append(list2, list1); + + qdict_put_int(dict2, "c", 2); + qdict_put_int(dict2, "d", 3); + qdict_put(dict3, "e", list2); + qdict_put(dict3, "f", dict2); + qdict_put_int(dict3, "g", 4); + + qdict_flatten(dict3); + + g_assert(qdict_get_int(dict3, "e.0") =3D=3D 42); + g_assert(qdict_get_int(dict3, "e.1.0") =3D=3D 23); + g_assert(qdict_get_int(dict3, "e.1.1") =3D=3D 66); + g_assert(qdict_get_int(dict3, "e.1.2.a") =3D=3D 0); + g_assert(qdict_get_int(dict3, "e.1.2.b") =3D=3D 1); + g_assert(qdict_get_int(dict3, "f.c") =3D=3D 2); + g_assert(qdict_get_int(dict3, "f.d") =3D=3D 3); + g_assert(qdict_get_int(dict3, "g") =3D=3D 4); + + g_assert(qdict_size(dict3) =3D=3D 8); + + qobject_unref(dict3); +} + +static void qdict_array_split_test(void) +{ + QDict *test_dict =3D qdict_new(); + QDict *dict1, *dict2; + QNum *int1; + QList *test_list; + + /* + * Test the split of + * + * { + * "1.x": 0, + * "4.y": 1, + * "0.a": 42, + * "o.o": 7, + * "0.b": 23, + * "2": 66 + * } + * + * to + * + * [ + * { + * "a": 42, + * "b": 23 + * }, + * { + * "x": 0 + * }, + * 66 + * ] + * + * and + * + * { + * "4.y": 1, + * "o.o": 7 + * } + * + * (remaining in the old QDict) + * + * This example is given in the comment of qdict_array_split(). + */ + + qdict_put_int(test_dict, "1.x", 0); + qdict_put_int(test_dict, "4.y", 1); + qdict_put_int(test_dict, "0.a", 42); + qdict_put_int(test_dict, "o.o", 7); + qdict_put_int(test_dict, "0.b", 23); + qdict_put_int(test_dict, "2", 66); + + qdict_array_split(test_dict, &test_list); + + dict1 =3D qobject_to(QDict, qlist_pop(test_list)); + dict2 =3D qobject_to(QDict, qlist_pop(test_list)); + int1 =3D qobject_to(QNum, qlist_pop(test_list)); + + g_assert(dict1); + g_assert(dict2); + g_assert(int1); + g_assert(qlist_empty(test_list)); + + qobject_unref(test_list); + + g_assert(qdict_get_int(dict1, "a") =3D=3D 42); + g_assert(qdict_get_int(dict1, "b") =3D=3D 23); + + g_assert(qdict_size(dict1) =3D=3D 2); + + qobject_unref(dict1); + + g_assert(qdict_get_int(dict2, "x") =3D=3D 0); + + g_assert(qdict_size(dict2) =3D=3D 1); + + qobject_unref(dict2); + + g_assert_cmpint(qnum_get_int(int1), =3D=3D, 66); + + qobject_unref(int1); + + g_assert(qdict_get_int(test_dict, "4.y") =3D=3D 1); + g_assert(qdict_get_int(test_dict, "o.o") =3D=3D 7); + + g_assert(qdict_size(test_dict) =3D=3D 2); + + qobject_unref(test_dict); + + /* + * Test the split of + * + * { + * "0": 42, + * "1": 23, + * "1.x": 84 + * } + * + * to + * + * [ + * 42 + * ] + * + * and + * + * { + * "1": 23, + * "1.x": 84 + * } + * + * That is, test whether splitting stops if there is both an entry wit= h key + * of "%u" and other entries with keys prefixed "%u." for the same ind= ex. + */ + + test_dict =3D qdict_new(); + + qdict_put_int(test_dict, "0", 42); + qdict_put_int(test_dict, "1", 23); + qdict_put_int(test_dict, "1.x", 84); + + qdict_array_split(test_dict, &test_list); + + int1 =3D qobject_to(QNum, qlist_pop(test_list)); + + g_assert(int1); + g_assert(qlist_empty(test_list)); + + qobject_unref(test_list); + + g_assert_cmpint(qnum_get_int(int1), =3D=3D, 42); + + qobject_unref(int1); + + g_assert(qdict_get_int(test_dict, "1") =3D=3D 23); + g_assert(qdict_get_int(test_dict, "1.x") =3D=3D 84); + + g_assert(qdict_size(test_dict) =3D=3D 2); + + qobject_unref(test_dict); +} + +static void qdict_array_entries_test(void) +{ + QDict *dict =3D qdict_new(); + + g_assert_cmpint(qdict_array_entries(dict, "foo."), =3D=3D, 0); + + qdict_put_int(dict, "bar", 0); + qdict_put_int(dict, "baz.0", 0); + g_assert_cmpint(qdict_array_entries(dict, "foo."), =3D=3D, 0); + + qdict_put_int(dict, "foo.1", 0); + g_assert_cmpint(qdict_array_entries(dict, "foo."), =3D=3D, -EINVAL); + qdict_put_int(dict, "foo.0", 0); + g_assert_cmpint(qdict_array_entries(dict, "foo."), =3D=3D, 2); + qdict_put_int(dict, "foo.bar", 0); + g_assert_cmpint(qdict_array_entries(dict, "foo."), =3D=3D, -EINVAL); + qdict_del(dict, "foo.bar"); + + qdict_put_int(dict, "foo.2.a", 0); + qdict_put_int(dict, "foo.2.b", 0); + qdict_put_int(dict, "foo.2.c", 0); + g_assert_cmpint(qdict_array_entries(dict, "foo."), =3D=3D, 3); + g_assert_cmpint(qdict_array_entries(dict, ""), =3D=3D, -EINVAL); + + qobject_unref(dict); + + dict =3D qdict_new(); + qdict_put_int(dict, "1", 0); + g_assert_cmpint(qdict_array_entries(dict, ""), =3D=3D, -EINVAL); + qdict_put_int(dict, "0", 0); + g_assert_cmpint(qdict_array_entries(dict, ""), =3D=3D, 2); + qdict_put_int(dict, "bar", 0); + g_assert_cmpint(qdict_array_entries(dict, ""), =3D=3D, -EINVAL); + qdict_del(dict, "bar"); + + qdict_put_int(dict, "2.a", 0); + qdict_put_int(dict, "2.b", 0); + qdict_put_int(dict, "2.c", 0); + g_assert_cmpint(qdict_array_entries(dict, ""), =3D=3D, 3); + + qobject_unref(dict); +} + +static void qdict_join_test(void) +{ + QDict *dict1, *dict2; + bool overwrite =3D false; + int i; + + dict1 =3D qdict_new(); + dict2 =3D qdict_new(); + + /* Test everything once without overwrite and once with */ + do { + /* Test empty dicts */ + qdict_join(dict1, dict2, overwrite); + + g_assert(qdict_size(dict1) =3D=3D 0); + g_assert(qdict_size(dict2) =3D=3D 0); + + /* First iteration: Test movement */ + /* Second iteration: Test empty source and non-empty destination */ + qdict_put_int(dict2, "foo", 42); + + for (i =3D 0; i < 2; i++) { + qdict_join(dict1, dict2, overwrite); + + g_assert(qdict_size(dict1) =3D=3D 1); + g_assert(qdict_size(dict2) =3D=3D 0); + + g_assert(qdict_get_int(dict1, "foo") =3D=3D 42); + } + + /* Test non-empty source and destination without conflict */ + qdict_put_int(dict2, "bar", 23); + + qdict_join(dict1, dict2, overwrite); + + g_assert(qdict_size(dict1) =3D=3D 2); + g_assert(qdict_size(dict2) =3D=3D 0); + + g_assert(qdict_get_int(dict1, "foo") =3D=3D 42); + g_assert(qdict_get_int(dict1, "bar") =3D=3D 23); + + /* Test conflict */ + qdict_put_int(dict2, "foo", 84); + + qdict_join(dict1, dict2, overwrite); + + g_assert(qdict_size(dict1) =3D=3D 2); + g_assert(qdict_size(dict2) =3D=3D !overwrite); + + g_assert(qdict_get_int(dict1, "foo") =3D=3D (overwrite ? 84 : 42)); + g_assert(qdict_get_int(dict1, "bar") =3D=3D 23); + + if (!overwrite) { + g_assert(qdict_get_int(dict2, "foo") =3D=3D 84); + } + + /* Check the references */ + g_assert(qdict_get(dict1, "foo")->base.refcnt =3D=3D 1); + g_assert(qdict_get(dict1, "bar")->base.refcnt =3D=3D 1); + + if (!overwrite) { + g_assert(qdict_get(dict2, "foo")->base.refcnt =3D=3D 1); + } + + /* Clean up */ + qdict_del(dict1, "foo"); + qdict_del(dict1, "bar"); + + if (!overwrite) { + qdict_del(dict2, "foo"); + } + } while (overwrite ^=3D true); + + qobject_unref(dict1); + qobject_unref(dict2); +} + +static void qdict_crumple_test_recursive(void) +{ + QDict *src, *dst, *rule, *vnc, *acl, *listen; + QList *rules; + + src =3D qdict_new(); + qdict_put_str(src, "vnc.listen.addr", "127.0.0.1"); + qdict_put_str(src, "vnc.listen.port", "5901"); + qdict_put_str(src, "vnc.acl.rules.0.match", "fred"); + qdict_put_str(src, "vnc.acl.rules.0.policy", "allow"); + qdict_put_str(src, "vnc.acl.rules.1.match", "bob"); + qdict_put_str(src, "vnc.acl.rules.1.policy", "deny"); + qdict_put_str(src, "vnc.acl.default", "deny"); + qdict_put_str(src, "vnc.acl..name", "acl0"); + qdict_put_str(src, "vnc.acl.rule..name", "acl0"); + + dst =3D qobject_to(QDict, qdict_crumple(src, &error_abort)); + g_assert(dst); + g_assert_cmpint(qdict_size(dst), =3D=3D, 1); + + vnc =3D qdict_get_qdict(dst, "vnc"); + g_assert(vnc); + g_assert_cmpint(qdict_size(vnc), =3D=3D, 3); + + listen =3D qdict_get_qdict(vnc, "listen"); + g_assert(listen); + g_assert_cmpint(qdict_size(listen), =3D=3D, 2); + g_assert_cmpstr("127.0.0.1", =3D=3D, qdict_get_str(listen, "addr")); + g_assert_cmpstr("5901", =3D=3D, qdict_get_str(listen, "port")); + + acl =3D qdict_get_qdict(vnc, "acl"); + g_assert(acl); + g_assert_cmpint(qdict_size(acl), =3D=3D, 3); + + rules =3D qdict_get_qlist(acl, "rules"); + g_assert(rules); + g_assert_cmpint(qlist_size(rules), =3D=3D, 2); + + rule =3D qobject_to(QDict, qlist_pop(rules)); + g_assert(rule); + g_assert_cmpint(qdict_size(rule), =3D=3D, 2); + g_assert_cmpstr("fred", =3D=3D, qdict_get_str(rule, "match")); + g_assert_cmpstr("allow", =3D=3D, qdict_get_str(rule, "policy")); + qobject_unref(rule); + + rule =3D qobject_to(QDict, qlist_pop(rules)); + g_assert(rule); + g_assert_cmpint(qdict_size(rule), =3D=3D, 2); + g_assert_cmpstr("bob", =3D=3D, qdict_get_str(rule, "match")); + g_assert_cmpstr("deny", =3D=3D, qdict_get_str(rule, "policy")); + qobject_unref(rule); + + /* With recursive crumpling, we should see all names unescaped */ + g_assert_cmpstr("acl0", =3D=3D, qdict_get_str(vnc, "acl.name")); + g_assert_cmpstr("acl0", =3D=3D, qdict_get_str(acl, "rule.name")); + + qobject_unref(src); + qobject_unref(dst); +} + +static void qdict_crumple_test_empty(void) +{ + QDict *src, *dst; + + src =3D qdict_new(); + + dst =3D qobject_to(QDict, qdict_crumple(src, &error_abort)); + + g_assert_cmpint(qdict_size(dst), =3D=3D, 0); + + qobject_unref(src); + qobject_unref(dst); +} + +static int qdict_count_entries(QDict *dict) +{ + const QDictEntry *e; + int count =3D 0; + + for (e =3D qdict_first(dict); e; e =3D qdict_next(dict, e)) { + count++; + } + + return count; +} + +static void qdict_rename_keys_test(void) +{ + QDict *dict =3D qdict_new(); + QDict *copy; + QDictRenames *renames; + Error *local_err =3D NULL; + + qdict_put_str(dict, "abc", "foo"); + qdict_put_str(dict, "abcdef", "bar"); + qdict_put_int(dict, "number", 42); + qdict_put_bool(dict, "flag", true); + qdict_put_null(dict, "nothing"); + + /* Empty rename list */ + renames =3D (QDictRenames[]) { + { NULL, "this can be anything" } + }; + copy =3D qdict_clone_shallow(dict); + qdict_rename_keys(copy, renames, &error_abort); + + g_assert_cmpstr(qdict_get_str(copy, "abc"), =3D=3D, "foo"); + g_assert_cmpstr(qdict_get_str(copy, "abcdef"), =3D=3D, "bar"); + g_assert_cmpint(qdict_get_int(copy, "number"), =3D=3D, 42); + g_assert_cmpint(qdict_get_bool(copy, "flag"), =3D=3D, true); + g_assert(qobject_type(qdict_get(copy, "nothing")) =3D=3D QTYPE_QNULL); + g_assert_cmpint(qdict_count_entries(copy), =3D=3D, 5); + + qobject_unref(copy); + + /* Simple rename of all entries */ + renames =3D (QDictRenames[]) { + { "abc", "str1" }, + { "abcdef", "str2" }, + { "number", "int" }, + { "flag", "bool" }, + { "nothing", "null" }, + { NULL , NULL } + }; + copy =3D qdict_clone_shallow(dict); + qdict_rename_keys(copy, renames, &error_abort); + + g_assert(!qdict_haskey(copy, "abc")); + g_assert(!qdict_haskey(copy, "abcdef")); + g_assert(!qdict_haskey(copy, "number")); + g_assert(!qdict_haskey(copy, "flag")); + g_assert(!qdict_haskey(copy, "nothing")); + + g_assert_cmpstr(qdict_get_str(copy, "str1"), =3D=3D, "foo"); + g_assert_cmpstr(qdict_get_str(copy, "str2"), =3D=3D, "bar"); + g_assert_cmpint(qdict_get_int(copy, "int"), =3D=3D, 42); + g_assert_cmpint(qdict_get_bool(copy, "bool"), =3D=3D, true); + g_assert(qobject_type(qdict_get(copy, "null")) =3D=3D QTYPE_QNULL); + g_assert_cmpint(qdict_count_entries(copy), =3D=3D, 5); + + qobject_unref(copy); + + /* Renames are processed top to bottom */ + renames =3D (QDictRenames[]) { + { "abc", "tmp" }, + { "abcdef", "abc" }, + { "number", "abcdef" }, + { "flag", "number" }, + { "nothing", "flag" }, + { "tmp", "nothing" }, + { NULL , NULL } + }; + copy =3D qdict_clone_shallow(dict); + qdict_rename_keys(copy, renames, &error_abort); + + g_assert_cmpstr(qdict_get_str(copy, "nothing"), =3D=3D, "foo"); + g_assert_cmpstr(qdict_get_str(copy, "abc"), =3D=3D, "bar"); + g_assert_cmpint(qdict_get_int(copy, "abcdef"), =3D=3D, 42); + g_assert_cmpint(qdict_get_bool(copy, "number"), =3D=3D, true); + g_assert(qobject_type(qdict_get(copy, "flag")) =3D=3D QTYPE_QNULL); + g_assert(!qdict_haskey(copy, "tmp")); + g_assert_cmpint(qdict_count_entries(copy), =3D=3D, 5); + + qobject_unref(copy); + + /* Conflicting rename */ + renames =3D (QDictRenames[]) { + { "abcdef", "abc" }, + { NULL , NULL } + }; + copy =3D qdict_clone_shallow(dict); + qdict_rename_keys(copy, renames, &local_err); + + g_assert(local_err !=3D NULL); + error_free(local_err); + local_err =3D NULL; + + g_assert_cmpstr(qdict_get_str(copy, "abc"), =3D=3D, "foo"); + g_assert_cmpstr(qdict_get_str(copy, "abcdef"), =3D=3D, "bar"); + g_assert_cmpint(qdict_get_int(copy, "number"), =3D=3D, 42); + g_assert_cmpint(qdict_get_bool(copy, "flag"), =3D=3D, true); + g_assert(qobject_type(qdict_get(copy, "nothing")) =3D=3D QTYPE_QNULL); + g_assert_cmpint(qdict_count_entries(copy), =3D=3D, 5); + + qobject_unref(copy); + + /* Renames in an empty dict */ + renames =3D (QDictRenames[]) { + { "abcdef", "abc" }, + { NULL , NULL } + }; + + qobject_unref(dict); + dict =3D qdict_new(); + + qdict_rename_keys(dict, renames, &error_abort); + g_assert(qdict_first(dict) =3D=3D NULL); + + qobject_unref(dict); +} + +static void qdict_crumple_test_bad_inputs(void) +{ + QDict *src; + Error *error =3D NULL; + + src =3D qdict_new(); + /* rule.0 can't be both a string and a dict */ + qdict_put_str(src, "rule.0", "fred"); + qdict_put_str(src, "rule.0.policy", "allow"); + + g_assert(qdict_crumple(src, &error) =3D=3D NULL); + g_assert(error !=3D NULL); + error_free(error); + error =3D NULL; + qobject_unref(src); + + src =3D qdict_new(); + /* rule can't be both a list and a dict */ + qdict_put_str(src, "rule.0", "fred"); + qdict_put_str(src, "rule.a", "allow"); + + g_assert(qdict_crumple(src, &error) =3D=3D NULL); + g_assert(error !=3D NULL); + error_free(error); + error =3D NULL; + qobject_unref(src); + + src =3D qdict_new(); + /* The input should be flat, ie no dicts or lists */ + qdict_put(src, "rule.a", qdict_new()); + qdict_put_str(src, "rule.b", "allow"); + + g_assert(qdict_crumple(src, &error) =3D=3D NULL); + g_assert(error !=3D NULL); + error_free(error); + error =3D NULL; + qobject_unref(src); + + src =3D qdict_new(); + /* List indexes must not have gaps */ + qdict_put_str(src, "rule.0", "deny"); + qdict_put_str(src, "rule.3", "allow"); + + g_assert(qdict_crumple(src, &error) =3D=3D NULL); + g_assert(error !=3D NULL); + error_free(error); + error =3D NULL; + qobject_unref(src); + + src =3D qdict_new(); + /* List indexes must be in %zu format */ + qdict_put_str(src, "rule.0", "deny"); + qdict_put_str(src, "rule.+1", "allow"); + + g_assert(qdict_crumple(src, &error) =3D=3D NULL); + g_assert(error !=3D NULL); + error_free(error); + error =3D NULL; + qobject_unref(src); +} + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + + g_test_add_func("/public/defaults", qdict_defaults_test); + g_test_add_func("/public/flatten", qdict_flatten_test); + g_test_add_func("/public/array_split", qdict_array_split_test); + g_test_add_func("/public/array_entries", qdict_array_entries_test); + g_test_add_func("/public/join", qdict_join_test); + g_test_add_func("/public/crumple/recursive", + qdict_crumple_test_recursive); + g_test_add_func("/public/crumple/empty", + qdict_crumple_test_empty); + g_test_add_func("/public/crumple/bad_inputs", + qdict_crumple_test_bad_inputs); + + g_test_add_func("/public/rename_keys", qdict_rename_keys_test); + + return g_test_run(); +} diff --git a/tests/check-qdict.c b/tests/check-qdict.c index 93e2112b6d..86e9fe7dc4 100644 --- a/tests/check-qdict.c +++ b/tests/check-qdict.c @@ -11,13 +11,7 @@ */ =20 #include "qemu/osdep.h" -#include "block/qdict.h" #include "qapi/qmp/qdict.h" -#include "qapi/qmp/qlist.h" -#include "qapi/qmp/qnum.h" -#include "qapi/qmp/qstring.h" -#include "qapi/error.h" -#include "qemu-common.h" =20 /* * Public Interface test-cases @@ -157,28 +151,6 @@ static void qdict_get_try_str_test(void) qobject_unref(tests_dict); } =20 -static void qdict_defaults_test(void) -{ - QDict *dict, *copy; - - dict =3D qdict_new(); - copy =3D qdict_new(); - - qdict_set_default_str(dict, "foo", "abc"); - qdict_set_default_str(dict, "foo", "def"); - g_assert_cmpstr(qdict_get_str(dict, "foo"), =3D=3D, "abc"); - qdict_set_default_str(dict, "bar", "ghi"); - - qdict_copy_default(copy, dict, "foo"); - g_assert_cmpstr(qdict_get_str(copy, "foo"), =3D=3D, "abc"); - qdict_set_default_str(copy, "bar", "xyz"); - qdict_copy_default(copy, dict, "bar"); - g_assert_cmpstr(qdict_get_str(copy, "bar"), =3D=3D, "xyz"); - - qobject_unref(copy); - qobject_unref(dict); -} - static void qdict_haskey_not_test(void) { QDict *tests_dict =3D qdict_new(); @@ -254,606 +226,6 @@ static void qdict_iterapi_test(void) qobject_unref(tests_dict); } =20 -static void qdict_flatten_test(void) -{ - QList *list1 =3D qlist_new(); - QList *list2 =3D qlist_new(); - QDict *dict1 =3D qdict_new(); - QDict *dict2 =3D qdict_new(); - QDict *dict3 =3D qdict_new(); - - /* - * Test the flattening of - * - * { - * "e": [ - * 42, - * [ - * 23, - * 66, - * { - * "a": 0, - * "b": 1 - * } - * ] - * ], - * "f": { - * "c": 2, - * "d": 3, - * }, - * "g": 4 - * } - * - * to - * - * { - * "e.0": 42, - * "e.1.0": 23, - * "e.1.1": 66, - * "e.1.2.a": 0, - * "e.1.2.b": 1, - * "f.c": 2, - * "f.d": 3, - * "g": 4 - * } - */ - - qdict_put_int(dict1, "a", 0); - qdict_put_int(dict1, "b", 1); - - qlist_append_int(list1, 23); - qlist_append_int(list1, 66); - qlist_append(list1, dict1); - qlist_append_int(list2, 42); - qlist_append(list2, list1); - - qdict_put_int(dict2, "c", 2); - qdict_put_int(dict2, "d", 3); - qdict_put(dict3, "e", list2); - qdict_put(dict3, "f", dict2); - qdict_put_int(dict3, "g", 4); - - qdict_flatten(dict3); - - g_assert(qdict_get_int(dict3, "e.0") =3D=3D 42); - g_assert(qdict_get_int(dict3, "e.1.0") =3D=3D 23); - g_assert(qdict_get_int(dict3, "e.1.1") =3D=3D 66); - g_assert(qdict_get_int(dict3, "e.1.2.a") =3D=3D 0); - g_assert(qdict_get_int(dict3, "e.1.2.b") =3D=3D 1); - g_assert(qdict_get_int(dict3, "f.c") =3D=3D 2); - g_assert(qdict_get_int(dict3, "f.d") =3D=3D 3); - g_assert(qdict_get_int(dict3, "g") =3D=3D 4); - - g_assert(qdict_size(dict3) =3D=3D 8); - - qobject_unref(dict3); -} - -static void qdict_array_split_test(void) -{ - QDict *test_dict =3D qdict_new(); - QDict *dict1, *dict2; - QNum *int1; - QList *test_list; - - /* - * Test the split of - * - * { - * "1.x": 0, - * "4.y": 1, - * "0.a": 42, - * "o.o": 7, - * "0.b": 23, - * "2": 66 - * } - * - * to - * - * [ - * { - * "a": 42, - * "b": 23 - * }, - * { - * "x": 0 - * }, - * 66 - * ] - * - * and - * - * { - * "4.y": 1, - * "o.o": 7 - * } - * - * (remaining in the old QDict) - * - * This example is given in the comment of qdict_array_split(). - */ - - qdict_put_int(test_dict, "1.x", 0); - qdict_put_int(test_dict, "4.y", 1); - qdict_put_int(test_dict, "0.a", 42); - qdict_put_int(test_dict, "o.o", 7); - qdict_put_int(test_dict, "0.b", 23); - qdict_put_int(test_dict, "2", 66); - - qdict_array_split(test_dict, &test_list); - - dict1 =3D qobject_to(QDict, qlist_pop(test_list)); - dict2 =3D qobject_to(QDict, qlist_pop(test_list)); - int1 =3D qobject_to(QNum, qlist_pop(test_list)); - - g_assert(dict1); - g_assert(dict2); - g_assert(int1); - g_assert(qlist_empty(test_list)); - - qobject_unref(test_list); - - g_assert(qdict_get_int(dict1, "a") =3D=3D 42); - g_assert(qdict_get_int(dict1, "b") =3D=3D 23); - - g_assert(qdict_size(dict1) =3D=3D 2); - - qobject_unref(dict1); - - g_assert(qdict_get_int(dict2, "x") =3D=3D 0); - - g_assert(qdict_size(dict2) =3D=3D 1); - - qobject_unref(dict2); - - g_assert_cmpint(qnum_get_int(int1), =3D=3D, 66); - - qobject_unref(int1); - - g_assert(qdict_get_int(test_dict, "4.y") =3D=3D 1); - g_assert(qdict_get_int(test_dict, "o.o") =3D=3D 7); - - g_assert(qdict_size(test_dict) =3D=3D 2); - - qobject_unref(test_dict); - - /* - * Test the split of - * - * { - * "0": 42, - * "1": 23, - * "1.x": 84 - * } - * - * to - * - * [ - * 42 - * ] - * - * and - * - * { - * "1": 23, - * "1.x": 84 - * } - * - * That is, test whether splitting stops if there is both an entry wit= h key - * of "%u" and other entries with keys prefixed "%u." for the same ind= ex. - */ - - test_dict =3D qdict_new(); - - qdict_put_int(test_dict, "0", 42); - qdict_put_int(test_dict, "1", 23); - qdict_put_int(test_dict, "1.x", 84); - - qdict_array_split(test_dict, &test_list); - - int1 =3D qobject_to(QNum, qlist_pop(test_list)); - - g_assert(int1); - g_assert(qlist_empty(test_list)); - - qobject_unref(test_list); - - g_assert_cmpint(qnum_get_int(int1), =3D=3D, 42); - - qobject_unref(int1); - - g_assert(qdict_get_int(test_dict, "1") =3D=3D 23); - g_assert(qdict_get_int(test_dict, "1.x") =3D=3D 84); - - g_assert(qdict_size(test_dict) =3D=3D 2); - - qobject_unref(test_dict); -} - -static void qdict_array_entries_test(void) -{ - QDict *dict =3D qdict_new(); - - g_assert_cmpint(qdict_array_entries(dict, "foo."), =3D=3D, 0); - - qdict_put_int(dict, "bar", 0); - qdict_put_int(dict, "baz.0", 0); - g_assert_cmpint(qdict_array_entries(dict, "foo."), =3D=3D, 0); - - qdict_put_int(dict, "foo.1", 0); - g_assert_cmpint(qdict_array_entries(dict, "foo."), =3D=3D, -EINVAL); - qdict_put_int(dict, "foo.0", 0); - g_assert_cmpint(qdict_array_entries(dict, "foo."), =3D=3D, 2); - qdict_put_int(dict, "foo.bar", 0); - g_assert_cmpint(qdict_array_entries(dict, "foo."), =3D=3D, -EINVAL); - qdict_del(dict, "foo.bar"); - - qdict_put_int(dict, "foo.2.a", 0); - qdict_put_int(dict, "foo.2.b", 0); - qdict_put_int(dict, "foo.2.c", 0); - g_assert_cmpint(qdict_array_entries(dict, "foo."), =3D=3D, 3); - g_assert_cmpint(qdict_array_entries(dict, ""), =3D=3D, -EINVAL); - - qobject_unref(dict); - - dict =3D qdict_new(); - qdict_put_int(dict, "1", 0); - g_assert_cmpint(qdict_array_entries(dict, ""), =3D=3D, -EINVAL); - qdict_put_int(dict, "0", 0); - g_assert_cmpint(qdict_array_entries(dict, ""), =3D=3D, 2); - qdict_put_int(dict, "bar", 0); - g_assert_cmpint(qdict_array_entries(dict, ""), =3D=3D, -EINVAL); - qdict_del(dict, "bar"); - - qdict_put_int(dict, "2.a", 0); - qdict_put_int(dict, "2.b", 0); - qdict_put_int(dict, "2.c", 0); - g_assert_cmpint(qdict_array_entries(dict, ""), =3D=3D, 3); - - qobject_unref(dict); -} - -static void qdict_join_test(void) -{ - QDict *dict1, *dict2; - bool overwrite =3D false; - int i; - - dict1 =3D qdict_new(); - dict2 =3D qdict_new(); - - /* Test everything once without overwrite and once with */ - do - { - /* Test empty dicts */ - qdict_join(dict1, dict2, overwrite); - - g_assert(qdict_size(dict1) =3D=3D 0); - g_assert(qdict_size(dict2) =3D=3D 0); - - /* First iteration: Test movement */ - /* Second iteration: Test empty source and non-empty destination */ - qdict_put_int(dict2, "foo", 42); - - for (i =3D 0; i < 2; i++) { - qdict_join(dict1, dict2, overwrite); - - g_assert(qdict_size(dict1) =3D=3D 1); - g_assert(qdict_size(dict2) =3D=3D 0); - - g_assert(qdict_get_int(dict1, "foo") =3D=3D 42); - } - - /* Test non-empty source and destination without conflict */ - qdict_put_int(dict2, "bar", 23); - - qdict_join(dict1, dict2, overwrite); - - g_assert(qdict_size(dict1) =3D=3D 2); - g_assert(qdict_size(dict2) =3D=3D 0); - - g_assert(qdict_get_int(dict1, "foo") =3D=3D 42); - g_assert(qdict_get_int(dict1, "bar") =3D=3D 23); - - /* Test conflict */ - qdict_put_int(dict2, "foo", 84); - - qdict_join(dict1, dict2, overwrite); - - g_assert(qdict_size(dict1) =3D=3D 2); - g_assert(qdict_size(dict2) =3D=3D !overwrite); - - g_assert(qdict_get_int(dict1, "foo") =3D=3D (overwrite ? 84 : 42)); - g_assert(qdict_get_int(dict1, "bar") =3D=3D 23); - - if (!overwrite) { - g_assert(qdict_get_int(dict2, "foo") =3D=3D 84); - } - - /* Check the references */ - g_assert(qdict_get(dict1, "foo")->base.refcnt =3D=3D 1); - g_assert(qdict_get(dict1, "bar")->base.refcnt =3D=3D 1); - - if (!overwrite) { - g_assert(qdict_get(dict2, "foo")->base.refcnt =3D=3D 1); - } - - /* Clean up */ - qdict_del(dict1, "foo"); - qdict_del(dict1, "bar"); - - if (!overwrite) { - qdict_del(dict2, "foo"); - } - } - while (overwrite ^=3D true); - - qobject_unref(dict1); - qobject_unref(dict2); -} - -static void qdict_crumple_test_recursive(void) -{ - QDict *src, *dst, *rule, *vnc, *acl, *listen; - QList *rules; - - src =3D qdict_new(); - qdict_put_str(src, "vnc.listen.addr", "127.0.0.1"); - qdict_put_str(src, "vnc.listen.port", "5901"); - qdict_put_str(src, "vnc.acl.rules.0.match", "fred"); - qdict_put_str(src, "vnc.acl.rules.0.policy", "allow"); - qdict_put_str(src, "vnc.acl.rules.1.match", "bob"); - qdict_put_str(src, "vnc.acl.rules.1.policy", "deny"); - qdict_put_str(src, "vnc.acl.default", "deny"); - qdict_put_str(src, "vnc.acl..name", "acl0"); - qdict_put_str(src, "vnc.acl.rule..name", "acl0"); - - dst =3D qobject_to(QDict, qdict_crumple(src, &error_abort)); - g_assert(dst); - g_assert_cmpint(qdict_size(dst), =3D=3D, 1); - - vnc =3D qdict_get_qdict(dst, "vnc"); - g_assert(vnc); - g_assert_cmpint(qdict_size(vnc), =3D=3D, 3); - - listen =3D qdict_get_qdict(vnc, "listen"); - g_assert(listen); - g_assert_cmpint(qdict_size(listen), =3D=3D, 2); - g_assert_cmpstr("127.0.0.1", =3D=3D, qdict_get_str(listen, "addr")); - g_assert_cmpstr("5901", =3D=3D, qdict_get_str(listen, "port")); - - acl =3D qdict_get_qdict(vnc, "acl"); - g_assert(acl); - g_assert_cmpint(qdict_size(acl), =3D=3D, 3); - - rules =3D qdict_get_qlist(acl, "rules"); - g_assert(rules); - g_assert_cmpint(qlist_size(rules), =3D=3D, 2); - - rule =3D qobject_to(QDict, qlist_pop(rules)); - g_assert(rule); - g_assert_cmpint(qdict_size(rule), =3D=3D, 2); - g_assert_cmpstr("fred", =3D=3D, qdict_get_str(rule, "match")); - g_assert_cmpstr("allow", =3D=3D, qdict_get_str(rule, "policy")); - qobject_unref(rule); - - rule =3D qobject_to(QDict, qlist_pop(rules)); - g_assert(rule); - g_assert_cmpint(qdict_size(rule), =3D=3D, 2); - g_assert_cmpstr("bob", =3D=3D, qdict_get_str(rule, "match")); - g_assert_cmpstr("deny", =3D=3D, qdict_get_str(rule, "policy")); - qobject_unref(rule); - - /* With recursive crumpling, we should see all names unescaped */ - g_assert_cmpstr("acl0", =3D=3D, qdict_get_str(vnc, "acl.name")); - g_assert_cmpstr("acl0", =3D=3D, qdict_get_str(acl, "rule.name")); - - qobject_unref(src); - qobject_unref(dst); -} - -static void qdict_crumple_test_empty(void) -{ - QDict *src, *dst; - - src =3D qdict_new(); - - dst =3D qobject_to(QDict, qdict_crumple(src, &error_abort)); - - g_assert_cmpint(qdict_size(dst), =3D=3D, 0); - - qobject_unref(src); - qobject_unref(dst); -} - -static int qdict_count_entries(QDict *dict) -{ - const QDictEntry *e; - int count =3D 0; - - for (e =3D qdict_first(dict); e; e =3D qdict_next(dict, e)) { - count++; - } - - return count; -} - -static void qdict_rename_keys_test(void) -{ - QDict *dict =3D qdict_new(); - QDict *copy; - QDictRenames *renames; - Error *local_err =3D NULL; - - qdict_put_str(dict, "abc", "foo"); - qdict_put_str(dict, "abcdef", "bar"); - qdict_put_int(dict, "number", 42); - qdict_put_bool(dict, "flag", true); - qdict_put_null(dict, "nothing"); - - /* Empty rename list */ - renames =3D (QDictRenames[]) { - { NULL, "this can be anything" } - }; - copy =3D qdict_clone_shallow(dict); - qdict_rename_keys(copy, renames, &error_abort); - - g_assert_cmpstr(qdict_get_str(copy, "abc"), =3D=3D, "foo"); - g_assert_cmpstr(qdict_get_str(copy, "abcdef"), =3D=3D, "bar"); - g_assert_cmpint(qdict_get_int(copy, "number"), =3D=3D, 42); - g_assert_cmpint(qdict_get_bool(copy, "flag"), =3D=3D, true); - g_assert(qobject_type(qdict_get(copy, "nothing")) =3D=3D QTYPE_QNULL); - g_assert_cmpint(qdict_count_entries(copy), =3D=3D, 5); - - qobject_unref(copy); - - /* Simple rename of all entries */ - renames =3D (QDictRenames[]) { - { "abc", "str1" }, - { "abcdef", "str2" }, - { "number", "int" }, - { "flag", "bool" }, - { "nothing", "null" }, - { NULL , NULL } - }; - copy =3D qdict_clone_shallow(dict); - qdict_rename_keys(copy, renames, &error_abort); - - g_assert(!qdict_haskey(copy, "abc")); - g_assert(!qdict_haskey(copy, "abcdef")); - g_assert(!qdict_haskey(copy, "number")); - g_assert(!qdict_haskey(copy, "flag")); - g_assert(!qdict_haskey(copy, "nothing")); - - g_assert_cmpstr(qdict_get_str(copy, "str1"), =3D=3D, "foo"); - g_assert_cmpstr(qdict_get_str(copy, "str2"), =3D=3D, "bar"); - g_assert_cmpint(qdict_get_int(copy, "int"), =3D=3D, 42); - g_assert_cmpint(qdict_get_bool(copy, "bool"), =3D=3D, true); - g_assert(qobject_type(qdict_get(copy, "null")) =3D=3D QTYPE_QNULL); - g_assert_cmpint(qdict_count_entries(copy), =3D=3D, 5); - - qobject_unref(copy); - - /* Renames are processed top to bottom */ - renames =3D (QDictRenames[]) { - { "abc", "tmp" }, - { "abcdef", "abc" }, - { "number", "abcdef" }, - { "flag", "number" }, - { "nothing", "flag" }, - { "tmp", "nothing" }, - { NULL , NULL } - }; - copy =3D qdict_clone_shallow(dict); - qdict_rename_keys(copy, renames, &error_abort); - - g_assert_cmpstr(qdict_get_str(copy, "nothing"), =3D=3D, "foo"); - g_assert_cmpstr(qdict_get_str(copy, "abc"), =3D=3D, "bar"); - g_assert_cmpint(qdict_get_int(copy, "abcdef"), =3D=3D, 42); - g_assert_cmpint(qdict_get_bool(copy, "number"), =3D=3D, true); - g_assert(qobject_type(qdict_get(copy, "flag")) =3D=3D QTYPE_QNULL); - g_assert(!qdict_haskey(copy, "tmp")); - g_assert_cmpint(qdict_count_entries(copy), =3D=3D, 5); - - qobject_unref(copy); - - /* Conflicting rename */ - renames =3D (QDictRenames[]) { - { "abcdef", "abc" }, - { NULL , NULL } - }; - copy =3D qdict_clone_shallow(dict); - qdict_rename_keys(copy, renames, &local_err); - - g_assert(local_err !=3D NULL); - error_free(local_err); - local_err =3D NULL; - - g_assert_cmpstr(qdict_get_str(copy, "abc"), =3D=3D, "foo"); - g_assert_cmpstr(qdict_get_str(copy, "abcdef"), =3D=3D, "bar"); - g_assert_cmpint(qdict_get_int(copy, "number"), =3D=3D, 42); - g_assert_cmpint(qdict_get_bool(copy, "flag"), =3D=3D, true); - g_assert(qobject_type(qdict_get(copy, "nothing")) =3D=3D QTYPE_QNULL); - g_assert_cmpint(qdict_count_entries(copy), =3D=3D, 5); - - qobject_unref(copy); - - /* Renames in an empty dict */ - renames =3D (QDictRenames[]) { - { "abcdef", "abc" }, - { NULL , NULL } - }; - - qobject_unref(dict); - dict =3D qdict_new(); - - qdict_rename_keys(dict, renames, &error_abort); - g_assert(qdict_first(dict) =3D=3D NULL); - - qobject_unref(dict); -} - -static void qdict_crumple_test_bad_inputs(void) -{ - QDict *src; - Error *error =3D NULL; - - src =3D qdict_new(); - /* rule.0 can't be both a string and a dict */ - qdict_put_str(src, "rule.0", "fred"); - qdict_put_str(src, "rule.0.policy", "allow"); - - g_assert(qdict_crumple(src, &error) =3D=3D NULL); - g_assert(error !=3D NULL); - error_free(error); - error =3D NULL; - qobject_unref(src); - - src =3D qdict_new(); - /* rule can't be both a list and a dict */ - qdict_put_str(src, "rule.0", "fred"); - qdict_put_str(src, "rule.a", "allow"); - - g_assert(qdict_crumple(src, &error) =3D=3D NULL); - g_assert(error !=3D NULL); - error_free(error); - error =3D NULL; - qobject_unref(src); - - src =3D qdict_new(); - /* The input should be flat, ie no dicts or lists */ - qdict_put(src, "rule.a", qdict_new()); - qdict_put_str(src, "rule.b", "allow"); - - g_assert(qdict_crumple(src, &error) =3D=3D NULL); - g_assert(error !=3D NULL); - error_free(error); - error =3D NULL; - qobject_unref(src); - - src =3D qdict_new(); - /* List indexes must not have gaps */ - qdict_put_str(src, "rule.0", "deny"); - qdict_put_str(src, "rule.3", "allow"); - - g_assert(qdict_crumple(src, &error) =3D=3D NULL); - g_assert(error !=3D NULL); - error_free(error); - error =3D NULL; - qobject_unref(src); - - src =3D qdict_new(); - /* List indexes must be in %zu format */ - qdict_put_str(src, "rule.0", "deny"); - qdict_put_str(src, "rule.+1", "allow"); - - g_assert(qdict_crumple(src, &error) =3D=3D NULL); - g_assert(error !=3D NULL); - error_free(error); - error =3D NULL; - qobject_unref(src); -} - /* * Errors test-cases */ @@ -987,29 +359,15 @@ int main(int argc, char **argv) g_test_add_func("/public/get_try_int", qdict_get_try_int_test); g_test_add_func("/public/get_str", qdict_get_str_test); g_test_add_func("/public/get_try_str", qdict_get_try_str_test); - g_test_add_func("/public/defaults", qdict_defaults_test); g_test_add_func("/public/haskey_not", qdict_haskey_not_test); g_test_add_func("/public/haskey", qdict_haskey_test); g_test_add_func("/public/del", qdict_del_test); g_test_add_func("/public/to_qdict", qobject_to_qdict_test); g_test_add_func("/public/iterapi", qdict_iterapi_test); - g_test_add_func("/public/flatten", qdict_flatten_test); - g_test_add_func("/public/array_split", qdict_array_split_test); - g_test_add_func("/public/array_entries", qdict_array_entries_test); - g_test_add_func("/public/join", qdict_join_test); =20 g_test_add_func("/errors/put_exists", qdict_put_exists_test); g_test_add_func("/errors/get_not_exists", qdict_get_not_exists_test); =20 - g_test_add_func("/public/crumple/recursive", - qdict_crumple_test_recursive); - g_test_add_func("/public/crumple/empty", - qdict_crumple_test_empty); - g_test_add_func("/public/crumple/bad_inputs", - qdict_crumple_test_bad_inputs); - - g_test_add_func("/public/rename_keys", qdict_rename_keys_test); - /* The Big one */ if (g_test_slow()) { g_test_add_func("/stress/test", qdict_stress_test); diff --git a/MAINTAINERS b/MAINTAINERS index 8a94517e9e..0fb5f38f9f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1369,6 +1369,8 @@ F: qemu-img* F: qemu-io* F: tests/qemu-iotests/ F: util/qemu-progress.c +F: qobject/block-qdict.c +F: test/check-block-qdict.c T: git git://repo.or.cz/qemu/kevin.git block =20 Block I/O path diff --git a/qobject/Makefile.objs b/qobject/Makefile.objs index 002d25873a..7b12c9cacf 100644 --- a/qobject/Makefile.objs +++ b/qobject/Makefile.objs @@ -1,2 +1,3 @@ util-obj-y =3D qnull.o qnum.o qstring.o qdict.o qlist.o qbool.o qlit.o util-obj-y +=3D qjson.o qobject.o json-lexer.o json-streamer.o json-parser= .o +util-obj-y +=3D block-qdict.o diff --git a/tests/Makefile.include b/tests/Makefile.include index 607afe5bed..ca91da26cb 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -39,6 +39,8 @@ SYSEMU_TARGET_LIST :=3D $(subst -softmmu.mak,,$(notdir \ =20 check-unit-y =3D tests/check-qdict$(EXESUF) gcov-files-check-qdict-y =3D qobject/qdict.c +check-unit-y =3D tests/check-block-qdict$(EXESUF) +gcov-files-check-block-qdict-y =3D qobject/block-qdict.c check-unit-y +=3D tests/test-char$(EXESUF) gcov-files-check-qdict-y =3D chardev/char.c check-unit-y +=3D tests/check-qnum$(EXESUF) @@ -584,6 +586,7 @@ GENERATED_FILES +=3D tests/test-qapi-types.h tests/test= -qapi-visit.h \ test-obj-y =3D tests/check-qnum.o tests/check-qstring.o tests/check-qdict.= o \ tests/check-qlist.o tests/check-qnull.o tests/check-qobject.o \ tests/check-qjson.o tests/check-qlit.o \ + tests/check-block-qtest.o \ tests/test-coroutine.o tests/test-string-output-visitor.o \ tests/test-string-input-visitor.o tests/test-qobject-output-visitor.o \ tests/test-clone-visitor.o \ @@ -614,6 +617,7 @@ test-block-obj-y =3D $(block-obj-y) $(test-io-obj-y) te= sts/iothread.o tests/check-qnum$(EXESUF): tests/check-qnum.o $(test-util-obj-y) tests/check-qstring$(EXESUF): tests/check-qstring.o $(test-util-obj-y) tests/check-qdict$(EXESUF): tests/check-qdict.o $(test-util-obj-y) +tests/check-block-qdict$(EXESUF): tests/check-block-qdict.o $(test-util-ob= j-y) tests/check-qlist$(EXESUF): tests/check-qlist.o $(test-util-obj-y) tests/check-qnull$(EXESUF): tests/check-qnull.o $(test-util-obj-y) tests/check-qobject$(EXESUF): tests/check-qobject.o $(test-util-obj-y) --=20 2.13.6 From nobody Tue May 7 21:08:57 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 1529073214947544.538457806164; Fri, 15 Jun 2018 07:33:34 -0700 (PDT) Received: from localhost ([::1]:47193 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpnC-0008Kz-3y for importer@patchew.org; Fri, 15 Jun 2018 10:33:34 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59227) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpbb-00069P-8a for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:37 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTpbU-0003fH-9i for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:35 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:50214 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fTpbM-0003VY-Eg; Fri, 15 Jun 2018 10:21:20 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 1788881A3245; Fri, 15 Jun 2018 14:21:20 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-70.ams2.redhat.com [10.36.117.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id 660A163A51; Fri, 15 Jun 2018 14:21:19 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 15 Jun 2018 16:20:51 +0200 Message-Id: <20180615142108.27814-10-kwolf@redhat.com> In-Reply-To: <20180615142108.27814-1-kwolf@redhat.com> References: <20180615142108.27814-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Fri, 15 Jun 2018 14:21:20 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Fri, 15 Jun 2018 14:21:20 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL 09/26] block: Fix -blockdev for certain non-string scalars 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 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" From: Markus Armbruster Configuration flows through the block subsystem in a rather peculiar way. Configuration made with -drive enters it as QemuOpts. Configuration made with -blockdev / blockdev-add enters it as QAPI type BlockdevOptions. The block subsystem uses QDict, QemuOpts and QAPI types internally. The precise flow is next to impossible to explain (I tried for this commit message, but gave up after wasting several hours). What I can explain is a flaw in the BlockDriver interface that leads to this bug: $ qemu-system-x86_64 -blockdev node-name=3Dn1,driver=3Dnfs,server.type= =3Dinet,server.host=3Dlocalhost,path=3D/foo/bar,user=3D1234 qemu-system-x86_64: -blockdev node-name=3Dn1,driver=3Dnfs,server.type= =3Dinet,server.host=3Dlocalhost,path=3D/foo/bar,user=3D1234: Internal error= : parameter user invalid QMP blockdev-add is broken the same way. Here's what happens. The block layer passes configuration represented as flat QDict (with dotted keys) to BlockDriver methods .bdrv_file_open(). The QDict's members are typed according to the QAPI schema. nfs_file_open() converts it to QAPI type BlockdevOptionsNfs, with qdict_crumple() and a qobject input visitor. This visitor comes in two flavors. The plain flavor requires scalars to be typed according to the QAPI schema. That's the case here. The keyval flavor requires string scalars. That's not the case here. nfs_file_open() uses the latter, and promptly falls apart for members @user, @group, @tcp-syn-count, @readahead-size, @page-cache-size, @debug. Switching to the plain flavor would fix -blockdev, but break -drive, because there the scalars arrive in nfs_file_open() as strings. The proper fix would be to replace the QDict by QAPI type BlockdevOptions in the BlockDriver interface. Sadly, that's beyond my reach right now. Next best would be to fix the block layer to always pass correctly typed QDicts to the BlockDriver methods. Also beyond my reach. What I can do is throw another hack onto the pile: have nfs_file_open() convert all members to string, so use of the keyval flavor actually works, by replacing qdict_crumple() by new function qdict_crumple_for_keyval_qiv(). The pattern "pass result of qdict_crumple() to qobject_input_visitor_new_keyval()" occurs several times more: * qemu_rbd_open() Same issue as nfs_file_open(), but since BlockdevOptionsRbd has only string members, its only a latent bug. Fix it anyway. * parallels_co_create_opts(), qcow_co_create_opts(), qcow2_co_create_opts(), bdrv_qed_co_create_opts(), sd_co_create_opts(), vhdx_co_create_opts(), vpc_co_create_opts() These work, because they create the QDict with qemu_opts_to_qdict_filtered(), which creates only string scalars. The function sports a TODO comment asking for better typing; that's going to be fun. Use qdict_crumple_for_keyval_qiv() to be safe. Signed-off-by: Markus Armbruster Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- include/block/qdict.h | 1 + block/nfs.c | 2 +- block/parallels.c | 2 +- block/qcow.c | 2 +- block/qcow2.c | 2 +- block/qed.c | 2 +- block/rbd.c | 2 +- block/sheepdog.c | 2 +- block/vhdx.c | 2 +- block/vpc.c | 2 +- qobject/block-qdict.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++= ++++ 11 files changed, 67 insertions(+), 9 deletions(-) diff --git a/include/block/qdict.h b/include/block/qdict.h index 71c037afba..47d9638c37 100644 --- a/include/block/qdict.h +++ b/include/block/qdict.h @@ -21,6 +21,7 @@ void qdict_extract_subqdict(QDict *src, QDict **dst, cons= t char *start); void qdict_array_split(QDict *src, QList **dst); int qdict_array_entries(QDict *src, const char *subqdict); QObject *qdict_crumple(const QDict *src, Error **errp); +QObject *qdict_crumple_for_keyval_qiv(QDict *qdict, Error **errp); void qdict_flatten(QDict *qdict); =20 typedef struct QDictRenames { diff --git a/block/nfs.c b/block/nfs.c index 3170b059b3..6935b611cc 100644 --- a/block/nfs.c +++ b/block/nfs.c @@ -561,7 +561,7 @@ static BlockdevOptionsNfs *nfs_options_qdict_to_qapi(QD= ict *options, const QDictEntry *e; Error *local_err =3D NULL; =20 - crumpled =3D qdict_crumple(options, errp); + crumpled =3D qdict_crumple_for_keyval_qiv(options, errp); if (crumpled =3D=3D NULL) { return NULL; } diff --git a/block/parallels.c b/block/parallels.c index c1d9643498..695899fc4b 100644 --- a/block/parallels.c +++ b/block/parallels.c @@ -653,7 +653,7 @@ static int coroutine_fn parallels_co_create_opts(const = char *filename, qdict_put_str(qdict, "driver", "parallels"); qdict_put_str(qdict, "file", bs->node_name); =20 - qobj =3D qdict_crumple(qdict, errp); + qobj =3D qdict_crumple_for_keyval_qiv(qdict, errp); qobject_unref(qdict); qdict =3D qobject_to(QDict, qobj); if (qdict =3D=3D NULL) { diff --git a/block/qcow.c b/block/qcow.c index 8c08908fd8..860b058240 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -997,7 +997,7 @@ static int coroutine_fn qcow_co_create_opts(const char = *filename, qdict_put_str(qdict, "driver", "qcow"); qdict_put_str(qdict, "file", bs->node_name); =20 - qobj =3D qdict_crumple(qdict, errp); + qobj =3D qdict_crumple_for_keyval_qiv(qdict, errp); qobject_unref(qdict); qdict =3D qobject_to(QDict, qobj); if (qdict =3D=3D NULL) { diff --git a/block/qcow2.c b/block/qcow2.c index d2d955f984..0a27afa2ef 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -3152,7 +3152,7 @@ static int coroutine_fn qcow2_co_create_opts(const ch= ar *filename, QemuOpts *opt qdict_put_str(qdict, "file", bs->node_name); =20 /* Now get the QAPI type BlockdevCreateOptions */ - qobj =3D qdict_crumple(qdict, errp); + qobj =3D qdict_crumple_for_keyval_qiv(qdict, errp); qobject_unref(qdict); qdict =3D qobject_to(QDict, qobj); if (qdict =3D=3D NULL) { diff --git a/block/qed.c b/block/qed.c index 324a953cbc..88fa36d409 100644 --- a/block/qed.c +++ b/block/qed.c @@ -763,7 +763,7 @@ static int coroutine_fn bdrv_qed_co_create_opts(const c= har *filename, qdict_put_str(qdict, "driver", "qed"); qdict_put_str(qdict, "file", bs->node_name); =20 - qobj =3D qdict_crumple(qdict, errp); + qobj =3D qdict_crumple_for_keyval_qiv(qdict, errp); qobject_unref(qdict); qdict =3D qobject_to(QDict, qobj); if (qdict =3D=3D NULL) { diff --git a/block/rbd.c b/block/rbd.c index 9659c7361f..09720e97c0 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -647,7 +647,7 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *o= ptions, int flags, } =20 /* Convert the remaining options into a QAPI object */ - crumpled =3D qdict_crumple(options, errp); + crumpled =3D qdict_crumple_for_keyval_qiv(options, errp); if (crumpled =3D=3D NULL) { r =3D -EINVAL; goto out; diff --git a/block/sheepdog.c b/block/sheepdog.c index 2e1f0e6eca..a93f93d360 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -2217,7 +2217,7 @@ static int coroutine_fn sd_co_create_opts(const char = *filename, QemuOpts *opts, } =20 /* Get the QAPI object */ - crumpled =3D qdict_crumple(qdict, errp); + crumpled =3D qdict_crumple_for_keyval_qiv(qdict, errp); if (crumpled =3D=3D NULL) { ret =3D -EINVAL; goto fail; diff --git a/block/vhdx.c b/block/vhdx.c index 2e32e24514..78b29d9fc7 100644 --- a/block/vhdx.c +++ b/block/vhdx.c @@ -2005,7 +2005,7 @@ static int coroutine_fn vhdx_co_create_opts(const cha= r *filename, qdict_put_str(qdict, "driver", "vhdx"); qdict_put_str(qdict, "file", bs->node_name); =20 - qobj =3D qdict_crumple(qdict, errp); + qobj =3D qdict_crumple_for_keyval_qiv(qdict, errp); qobject_unref(qdict); qdict =3D qobject_to(QDict, qobj); if (qdict =3D=3D NULL) { diff --git a/block/vpc.c b/block/vpc.c index 41c8c980f1..16178e5a90 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -1119,7 +1119,7 @@ static int coroutine_fn vpc_co_create_opts(const char= *filename, qdict_put_str(qdict, "driver", "vpc"); qdict_put_str(qdict, "file", bs->node_name); =20 - qobj =3D qdict_crumple(qdict, errp); + qobj =3D qdict_crumple_for_keyval_qiv(qdict, errp); qobject_unref(qdict); qdict =3D qobject_to(QDict, qobj); if (qdict =3D=3D NULL) { diff --git a/qobject/block-qdict.c b/qobject/block-qdict.c index fb92010dc5..aba372c2eb 100644 --- a/qobject/block-qdict.c +++ b/qobject/block-qdict.c @@ -9,7 +9,10 @@ =20 #include "qemu/osdep.h" #include "block/qdict.h" +#include "qapi/qmp/qbool.h" #include "qapi/qmp/qlist.h" +#include "qapi/qmp/qnum.h" +#include "qapi/qmp/qstring.h" #include "qemu/cutils.h" #include "qapi/error.h" =20 @@ -514,6 +517,60 @@ QObject *qdict_crumple(const QDict *src, Error **errp) } =20 /** + * qdict_crumple_for_keyval_qiv: + * @src: the flat dictionary (only scalar values) to crumple + * @errp: location to store error + * + * Like qdict_crumple(), but additionally transforms scalar values so + * the result can be passed to qobject_input_visitor_new_keyval(). + * + * The block subsystem uses this function to prepare its flat QDict + * with possibly confused scalar types for a visit. It should not be + * used for anything else, and it should go away once the block + * subsystem has been cleaned up. + */ +QObject *qdict_crumple_for_keyval_qiv(QDict *src, Error **errp) +{ + QDict *tmp =3D NULL; + char *buf; + const char *s; + const QDictEntry *ent; + QObject *dst; + + for (ent =3D qdict_first(src); ent; ent =3D qdict_next(src, ent)) { + buf =3D NULL; + switch (qobject_type(ent->value)) { + case QTYPE_QNULL: + case QTYPE_QSTRING: + continue; + case QTYPE_QNUM: + s =3D buf =3D qnum_to_string(qobject_to(QNum, ent->value)); + break; + case QTYPE_QDICT: + case QTYPE_QLIST: + /* @src isn't flat; qdict_crumple() will fail */ + continue; + case QTYPE_QBOOL: + s =3D qbool_get_bool(qobject_to(QBool, ent->value)) + ? "on" : "off"; + break; + default: + abort(); + } + + if (!tmp) { + tmp =3D qdict_clone_shallow(src); + } + qdict_put(tmp, ent->key, qstring_from_str(s)); + g_free(buf); + } + + dst =3D qdict_crumple(tmp ?: src, errp); + qobject_unref(tmp); + return dst; +} + +/** * qdict_array_entries(): Returns the number of direct array entries if the * sub-QDict of src specified by the prefix in subqdict (or src itself for * prefix =3D=3D "") is valid as an array, i.e. the length of the created = list if --=20 2.13.6 From nobody Tue May 7 21:08:57 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 1529073404626498.3043733395168; Fri, 15 Jun 2018 07:36:44 -0700 (PDT) Received: from localhost ([::1]:47211 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpqD-0002uS-Bn for importer@patchew.org; Fri, 15 Jun 2018 10:36:41 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59079) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpbV-000628-J6 for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:31 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTpbU-0003fZ-Bp for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:29 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:50218 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fTpbN-0003Wo-Bu; Fri, 15 Jun 2018 10:21:21 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 02E8B81A3245; Fri, 15 Jun 2018 14:21:21 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-70.ams2.redhat.com [10.36.117.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5222D63A72; Fri, 15 Jun 2018 14:21:20 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 15 Jun 2018 16:20:52 +0200 Message-Id: <20180615142108.27814-11-kwolf@redhat.com> In-Reply-To: <20180615142108.27814-1-kwolf@redhat.com> References: <20180615142108.27814-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Fri, 15 Jun 2018 14:21:21 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Fri, 15 Jun 2018 14:21:21 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL 10/26] block: Fix -drive for certain non-string scalars 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 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" From: Markus Armbruster The previous commit fixed -blockdev breakage due to misuse of the qobject input visitor's keyval flavor in bdrv_file_open(). The commit message explain why using the plain flavor would be just as wrong; it would break -drive. Turns out we break it in three places: nbd_open(), sd_open() and ssh_file_open(). They are even marked FIXME. Example breakage: $ qemu-system-x86 -drive node-name=3Dn1,driver=3Dnbd,server.type=3Dinet= ,server.host=3Dlocalhost,server.port=3D1234,server.numeric=3Doff qemu-system-x86: -drive node-name=3Dn1,driver=3Dnbd,server.type=3Dinet,= server.host=3Dlocalhost,server.port=3D1234,server.numeric=3Doff: Invalid pa= rameter type for 'numeric', expected: boolean Fix it the same way: replace qdict_crumple() by qdict_crumple_for_keyval_qiv(), and switch from plain to the keyval flavor. Signed-off-by: Markus Armbruster Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/nbd.c | 12 ++---------- block/sheepdog.c | 12 ++---------- block/ssh.c | 12 ++---------- 3 files changed, 6 insertions(+), 30 deletions(-) diff --git a/block/nbd.c b/block/nbd.c index d6c4c4ddbc..614dd9fec0 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -273,20 +273,12 @@ static SocketAddress *nbd_config(BDRVNBDState *s, QDi= ct *options, goto done; } =20 - crumpled_addr =3D qdict_crumple(addr, errp); + crumpled_addr =3D qdict_crumple_for_keyval_qiv(addr, errp); if (!crumpled_addr) { goto done; } =20 - /* - * FIXME .numeric, .to, .ipv4 or .ipv6 don't work with -drive - * server.type=3Dinet. .to doesn't matter, it's ignored anyway. - * That's because when @options come from -blockdev or - * blockdev_add, members are typed according to the QAPI schema, - * but when they come from -drive, they're all QString. The - * visitor expects the former. - */ - iv =3D qobject_input_visitor_new(crumpled_addr); + iv =3D qobject_input_visitor_new_keyval(crumpled_addr); visit_type_SocketAddress(iv, NULL, &saddr, &local_err); if (local_err) { error_propagate(errp, local_err); diff --git a/block/sheepdog.c b/block/sheepdog.c index a93f93d360..29e3e1eaaa 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -546,20 +546,12 @@ static SocketAddress *sd_server_config(QDict *options= , Error **errp) =20 qdict_extract_subqdict(options, &server, "server."); =20 - crumpled_server =3D qdict_crumple(server, errp); + crumpled_server =3D qdict_crumple_for_keyval_qiv(server, errp); if (!crumpled_server) { goto done; } =20 - /* - * FIXME .numeric, .to, .ipv4 or .ipv6 don't work with -drive - * server.type=3Dinet. .to doesn't matter, it's ignored anyway. - * That's because when @options come from -blockdev or - * blockdev_add, members are typed according to the QAPI schema, - * but when they come from -drive, they're all QString. The - * visitor expects the former. - */ - iv =3D qobject_input_visitor_new(crumpled_server); + iv =3D qobject_input_visitor_new_keyval(crumpled_server); visit_type_SocketAddress(iv, NULL, &saddr, &local_err); if (local_err) { error_propagate(errp, local_err); diff --git a/block/ssh.c b/block/ssh.c index eec37dd27c..bd85d989d5 100644 --- a/block/ssh.c +++ b/block/ssh.c @@ -623,20 +623,12 @@ static BlockdevOptionsSsh *ssh_parse_options(QDict *o= ptions, Error **errp) } =20 /* Create the QAPI object */ - crumpled =3D qdict_crumple(options, errp); + crumpled =3D qdict_crumple_for_keyval_qiv(options, errp); if (crumpled =3D=3D NULL) { goto fail; } =20 - /* - * FIXME .numeric, .to, .ipv4 or .ipv6 don't work with -drive. - * .to doesn't matter, it's ignored anyway. - * That's because when @options come from -blockdev or - * blockdev_add, members are typed according to the QAPI schema, - * but when they come from -drive, they're all QString. The - * visitor expects the former. - */ - v =3D qobject_input_visitor_new(crumpled); + v =3D qobject_input_visitor_new_keyval(crumpled); visit_type_BlockdevOptionsSsh(v, NULL, &result, &local_err); visit_free(v); qobject_unref(crumpled); --=20 2.13.6 From nobody Tue May 7 21:08:57 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 1529073802359985.3985939838545; Fri, 15 Jun 2018 07:43:22 -0700 (PDT) Received: from localhost ([::1]:47257 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpwf-0008SH-I5 for importer@patchew.org; Fri, 15 Jun 2018 10:43:21 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59319) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpbf-0006FH-AP for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:40 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTpbY-0003jY-Di for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:39 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:55624 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fTpbO-0003Xu-DI; Fri, 15 Jun 2018 10:21:22 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E280287A81; Fri, 15 Jun 2018 14:21:21 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-70.ams2.redhat.com [10.36.117.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3DB5563A51; Fri, 15 Jun 2018 14:21:21 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 15 Jun 2018 16:20:53 +0200 Message-Id: <20180615142108.27814-12-kwolf@redhat.com> In-Reply-To: <20180615142108.27814-1-kwolf@redhat.com> References: <20180615142108.27814-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Fri, 15 Jun 2018 14:21:21 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Fri, 15 Jun 2018 14:21:21 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL 11/26] block: Clean up a misuse of qobject_to() in .bdrv_co_create_opts() 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 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" From: Markus Armbruster The following pattern occurs in the .bdrv_co_create_opts() methods of parallels, qcow, qcow2, qed, vhdx and vpc: qobj =3D qdict_crumple_for_keyval_qiv(qdict, errp); qobject_unref(qdict); qdict =3D qobject_to(QDict, qobj); if (qdict =3D=3D NULL) { ret =3D -EINVAL; goto done; } v =3D qobject_input_visitor_new_keyval(QOBJECT(qdict)); [...] ret =3D 0; done: qobject_unref(qdict); [...] return ret; If qobject_to() fails, we return failure without setting errp. That's wrong. As far as I can tell, it cannot fail here. Clean it up anyway, by removing the useless conversion. Signed-off-by: Markus Armbruster Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/parallels.c | 9 ++++----- block/qcow.c | 9 ++++----- block/qcow2.c | 9 ++++----- block/qed.c | 9 ++++----- block/vhdx.c | 9 ++++----- block/vpc.c | 9 ++++----- 6 files changed, 24 insertions(+), 30 deletions(-) diff --git a/block/parallels.c b/block/parallels.c index 695899fc4b..ceb7a15d62 100644 --- a/block/parallels.c +++ b/block/parallels.c @@ -616,7 +616,7 @@ static int coroutine_fn parallels_co_create_opts(const = char *filename, BlockdevCreateOptions *create_options =3D NULL; Error *local_err =3D NULL; BlockDriverState *bs =3D NULL; - QDict *qdict =3D NULL; + QDict *qdict; QObject *qobj; Visitor *v; int ret; @@ -654,14 +654,13 @@ static int coroutine_fn parallels_co_create_opts(cons= t char *filename, qdict_put_str(qdict, "file", bs->node_name); =20 qobj =3D qdict_crumple_for_keyval_qiv(qdict, errp); - qobject_unref(qdict); - qdict =3D qobject_to(QDict, qobj); - if (qdict =3D=3D NULL) { + if (!qobj) { ret =3D -EINVAL; goto done; } =20 - v =3D qobject_input_visitor_new_keyval(QOBJECT(qdict)); + v =3D qobject_input_visitor_new_keyval(qobj); + qobject_unref(qobj); visit_type_BlockdevCreateOptions(v, NULL, &create_options, &local_err); visit_free(v); =20 diff --git a/block/qcow.c b/block/qcow.c index 860b058240..2f81f081fd 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -946,7 +946,7 @@ static int coroutine_fn qcow_co_create_opts(const char = *filename, { BlockdevCreateOptions *create_options =3D NULL; BlockDriverState *bs =3D NULL; - QDict *qdict =3D NULL; + QDict *qdict; QObject *qobj; Visitor *v; const char *val; @@ -998,14 +998,13 @@ static int coroutine_fn qcow_co_create_opts(const cha= r *filename, qdict_put_str(qdict, "file", bs->node_name); =20 qobj =3D qdict_crumple_for_keyval_qiv(qdict, errp); - qobject_unref(qdict); - qdict =3D qobject_to(QDict, qobj); - if (qdict =3D=3D NULL) { + if (!qobj) { ret =3D -EINVAL; goto fail; } =20 - v =3D qobject_input_visitor_new_keyval(QOBJECT(qdict)); + v =3D qobject_input_visitor_new_keyval(qobj); + qobject_unref(qobj); visit_type_BlockdevCreateOptions(v, NULL, &create_options, &local_err); visit_free(v); =20 diff --git a/block/qcow2.c b/block/qcow2.c index 0a27afa2ef..8c338661db 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -3080,7 +3080,7 @@ static int coroutine_fn qcow2_co_create_opts(const ch= ar *filename, QemuOpts *opt Error **errp) { BlockdevCreateOptions *create_options =3D NULL; - QDict *qdict =3D NULL; + QDict *qdict; QObject *qobj; Visitor *v; BlockDriverState *bs =3D NULL; @@ -3153,14 +3153,13 @@ static int coroutine_fn qcow2_co_create_opts(const = char *filename, QemuOpts *opt =20 /* Now get the QAPI type BlockdevCreateOptions */ qobj =3D qdict_crumple_for_keyval_qiv(qdict, errp); - qobject_unref(qdict); - qdict =3D qobject_to(QDict, qobj); - if (qdict =3D=3D NULL) { + if (!qobj) { ret =3D -EINVAL; goto finish; } =20 - v =3D qobject_input_visitor_new_keyval(QOBJECT(qdict)); + v =3D qobject_input_visitor_new_keyval(qobj); + qobject_unref(qobj); visit_type_BlockdevCreateOptions(v, NULL, &create_options, &local_err); visit_free(v); =20 diff --git a/block/qed.c b/block/qed.c index 88fa36d409..fcec760b26 100644 --- a/block/qed.c +++ b/block/qed.c @@ -722,7 +722,7 @@ static int coroutine_fn bdrv_qed_co_create_opts(const c= har *filename, Error **errp) { BlockdevCreateOptions *create_options =3D NULL; - QDict *qdict =3D NULL; + QDict *qdict; QObject *qobj; Visitor *v; BlockDriverState *bs =3D NULL; @@ -764,14 +764,13 @@ static int coroutine_fn bdrv_qed_co_create_opts(const= char *filename, qdict_put_str(qdict, "file", bs->node_name); =20 qobj =3D qdict_crumple_for_keyval_qiv(qdict, errp); - qobject_unref(qdict); - qdict =3D qobject_to(QDict, qobj); - if (qdict =3D=3D NULL) { + if (!qobj) { ret =3D -EINVAL; goto fail; } =20 - v =3D qobject_input_visitor_new_keyval(QOBJECT(qdict)); + v =3D qobject_input_visitor_new_keyval(qobj); + qobject_unref(qobj); visit_type_BlockdevCreateOptions(v, NULL, &create_options, &local_err); visit_free(v); =20 diff --git a/block/vhdx.c b/block/vhdx.c index 78b29d9fc7..f2aec3d2cd 100644 --- a/block/vhdx.c +++ b/block/vhdx.c @@ -1965,7 +1965,7 @@ static int coroutine_fn vhdx_co_create_opts(const cha= r *filename, Error **errp) { BlockdevCreateOptions *create_options =3D NULL; - QDict *qdict =3D NULL; + QDict *qdict; QObject *qobj; Visitor *v; BlockDriverState *bs =3D NULL; @@ -2006,14 +2006,13 @@ static int coroutine_fn vhdx_co_create_opts(const c= har *filename, qdict_put_str(qdict, "file", bs->node_name); =20 qobj =3D qdict_crumple_for_keyval_qiv(qdict, errp); - qobject_unref(qdict); - qdict =3D qobject_to(QDict, qobj); - if (qdict =3D=3D NULL) { + if (!qobj) { ret =3D -EINVAL; goto fail; } =20 - v =3D qobject_input_visitor_new_keyval(QOBJECT(qdict)); + v =3D qobject_input_visitor_new_keyval(qobj); + qobject_unref(qobj); visit_type_BlockdevCreateOptions(v, NULL, &create_options, &local_err); visit_free(v); =20 diff --git a/block/vpc.c b/block/vpc.c index 16178e5a90..a9bb04149d 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -1081,7 +1081,7 @@ static int coroutine_fn vpc_co_create_opts(const char= *filename, QemuOpts *opts, Error **errp) { BlockdevCreateOptions *create_options =3D NULL; - QDict *qdict =3D NULL; + QDict *qdict; QObject *qobj; Visitor *v; BlockDriverState *bs =3D NULL; @@ -1120,14 +1120,13 @@ static int coroutine_fn vpc_co_create_opts(const ch= ar *filename, qdict_put_str(qdict, "file", bs->node_name); =20 qobj =3D qdict_crumple_for_keyval_qiv(qdict, errp); - qobject_unref(qdict); - qdict =3D qobject_to(QDict, qobj); - if (qdict =3D=3D NULL) { + if (!qobj) { ret =3D -EINVAL; goto fail; } =20 - v =3D qobject_input_visitor_new_keyval(QOBJECT(qdict)); + v =3D qobject_input_visitor_new_keyval(qobj); + qobject_unref(qobj); visit_type_BlockdevCreateOptions(v, NULL, &create_options, &local_err); visit_free(v); =20 --=20 2.13.6 From nobody Tue May 7 21:08:57 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 1529073001029919.3650665266848; Fri, 15 Jun 2018 07:30:01 -0700 (PDT) Received: from localhost ([::1]:47169 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpjg-00051f-Lb for importer@patchew.org; Fri, 15 Jun 2018 10:29:56 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59101) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpbW-00063A-9P for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:32 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTpbU-0003fO-9x for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:30 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:54408 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fTpbP-0003Yy-6C; Fri, 15 Jun 2018 10:21:23 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id CE6E340122CE; Fri, 15 Jun 2018 14:21:22 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-70.ams2.redhat.com [10.36.117.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2943263A51; Fri, 15 Jun 2018 14:21:22 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 15 Jun 2018 16:20:54 +0200 Message-Id: <20180615142108.27814-13-kwolf@redhat.com> In-Reply-To: <20180615142108.27814-1-kwolf@redhat.com> References: <20180615142108.27814-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Fri, 15 Jun 2018 14:21:22 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Fri, 15 Jun 2018 14:21:22 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL 12/26] block: Factor out qobject_input_visitor_new_flat_confused() 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 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" From: Markus Armbruster Signed-off-by: Markus Armbruster Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- include/block/qdict.h | 3 ++- block/nbd.c | 7 ++----- block/nfs.c | 7 ++----- block/parallels.c | 7 ++----- block/qcow.c | 7 ++----- block/qcow2.c | 7 ++----- block/qed.c | 7 ++----- block/rbd.c | 7 ++----- block/sheepdog.c | 14 ++++---------- block/ssh.c | 7 ++----- block/vhdx.c | 7 ++----- block/vpc.c | 7 ++----- qobject/block-qdict.c | 28 +++++++++++++++++++++++++++- 13 files changed, 53 insertions(+), 62 deletions(-) diff --git a/include/block/qdict.h b/include/block/qdict.h index 47d9638c37..d8cb502d7d 100644 --- a/include/block/qdict.h +++ b/include/block/qdict.h @@ -21,7 +21,6 @@ void qdict_extract_subqdict(QDict *src, QDict **dst, cons= t char *start); void qdict_array_split(QDict *src, QList **dst); int qdict_array_entries(QDict *src, const char *subqdict); QObject *qdict_crumple(const QDict *src, Error **errp); -QObject *qdict_crumple_for_keyval_qiv(QDict *qdict, Error **errp); void qdict_flatten(QDict *qdict); =20 typedef struct QDictRenames { @@ -30,4 +29,6 @@ typedef struct QDictRenames { } QDictRenames; bool qdict_rename_keys(QDict *qdict, const QDictRenames *renames, Error **= errp); =20 +Visitor *qobject_input_visitor_new_flat_confused(QDict *qdict, + Error **errp); #endif diff --git a/block/nbd.c b/block/nbd.c index 614dd9fec0..13db4030e6 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -263,7 +263,6 @@ static SocketAddress *nbd_config(BDRVNBDState *s, QDict= *options, { SocketAddress *saddr =3D NULL; QDict *addr =3D NULL; - QObject *crumpled_addr =3D NULL; Visitor *iv =3D NULL; Error *local_err =3D NULL; =20 @@ -273,12 +272,11 @@ static SocketAddress *nbd_config(BDRVNBDState *s, QDi= ct *options, goto done; } =20 - crumpled_addr =3D qdict_crumple_for_keyval_qiv(addr, errp); - if (!crumpled_addr) { + iv =3D qobject_input_visitor_new_flat_confused(addr, errp); + if (!iv) { goto done; } =20 - iv =3D qobject_input_visitor_new_keyval(crumpled_addr); visit_type_SocketAddress(iv, NULL, &saddr, &local_err); if (local_err) { error_propagate(errp, local_err); @@ -287,7 +285,6 @@ static SocketAddress *nbd_config(BDRVNBDState *s, QDict= *options, =20 done: qobject_unref(addr); - qobject_unref(crumpled_addr); visit_free(iv); return saddr; } diff --git a/block/nfs.c b/block/nfs.c index 6935b611cc..743ca0450e 100644 --- a/block/nfs.c +++ b/block/nfs.c @@ -556,20 +556,17 @@ static BlockdevOptionsNfs *nfs_options_qdict_to_qapi(= QDict *options, Error **errp) { BlockdevOptionsNfs *opts =3D NULL; - QObject *crumpled =3D NULL; Visitor *v; const QDictEntry *e; Error *local_err =3D NULL; =20 - crumpled =3D qdict_crumple_for_keyval_qiv(options, errp); - if (crumpled =3D=3D NULL) { + v =3D qobject_input_visitor_new_flat_confused(options, errp); + if (!v) { return NULL; } =20 - v =3D qobject_input_visitor_new_keyval(crumpled); visit_type_BlockdevOptionsNfs(v, NULL, &opts, &local_err); visit_free(v); - qobject_unref(crumpled); =20 if (local_err) { error_propagate(errp, local_err); diff --git a/block/parallels.c b/block/parallels.c index ceb7a15d62..fd215e202a 100644 --- a/block/parallels.c +++ b/block/parallels.c @@ -617,7 +617,6 @@ static int coroutine_fn parallels_co_create_opts(const = char *filename, Error *local_err =3D NULL; BlockDriverState *bs =3D NULL; QDict *qdict; - QObject *qobj; Visitor *v; int ret; =20 @@ -653,14 +652,12 @@ static int coroutine_fn parallels_co_create_opts(cons= t char *filename, qdict_put_str(qdict, "driver", "parallels"); qdict_put_str(qdict, "file", bs->node_name); =20 - qobj =3D qdict_crumple_for_keyval_qiv(qdict, errp); - if (!qobj) { + v =3D qobject_input_visitor_new_flat_confused(qdict, errp); + if (!v) { ret =3D -EINVAL; goto done; } =20 - v =3D qobject_input_visitor_new_keyval(qobj); - qobject_unref(qobj); visit_type_BlockdevCreateOptions(v, NULL, &create_options, &local_err); visit_free(v); =20 diff --git a/block/qcow.c b/block/qcow.c index 2f81f081fd..5532731b9f 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -947,7 +947,6 @@ static int coroutine_fn qcow_co_create_opts(const char = *filename, BlockdevCreateOptions *create_options =3D NULL; BlockDriverState *bs =3D NULL; QDict *qdict; - QObject *qobj; Visitor *v; const char *val; Error *local_err =3D NULL; @@ -997,14 +996,12 @@ static int coroutine_fn qcow_co_create_opts(const cha= r *filename, qdict_put_str(qdict, "driver", "qcow"); qdict_put_str(qdict, "file", bs->node_name); =20 - qobj =3D qdict_crumple_for_keyval_qiv(qdict, errp); - if (!qobj) { + v =3D qobject_input_visitor_new_flat_confused(qdict, errp); + if (!v) { ret =3D -EINVAL; goto fail; } =20 - v =3D qobject_input_visitor_new_keyval(qobj); - qobject_unref(qobj); visit_type_BlockdevCreateOptions(v, NULL, &create_options, &local_err); visit_free(v); =20 diff --git a/block/qcow2.c b/block/qcow2.c index 8c338661db..945132f692 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -3081,7 +3081,6 @@ static int coroutine_fn qcow2_co_create_opts(const ch= ar *filename, QemuOpts *opt { BlockdevCreateOptions *create_options =3D NULL; QDict *qdict; - QObject *qobj; Visitor *v; BlockDriverState *bs =3D NULL; Error *local_err =3D NULL; @@ -3152,14 +3151,12 @@ static int coroutine_fn qcow2_co_create_opts(const = char *filename, QemuOpts *opt qdict_put_str(qdict, "file", bs->node_name); =20 /* Now get the QAPI type BlockdevCreateOptions */ - qobj =3D qdict_crumple_for_keyval_qiv(qdict, errp); - if (!qobj) { + v =3D qobject_input_visitor_new_flat_confused(qdict, errp); + if (!v) { ret =3D -EINVAL; goto finish; } =20 - v =3D qobject_input_visitor_new_keyval(qobj); - qobject_unref(qobj); visit_type_BlockdevCreateOptions(v, NULL, &create_options, &local_err); visit_free(v); =20 diff --git a/block/qed.c b/block/qed.c index fcec760b26..2363814538 100644 --- a/block/qed.c +++ b/block/qed.c @@ -723,7 +723,6 @@ static int coroutine_fn bdrv_qed_co_create_opts(const c= har *filename, { BlockdevCreateOptions *create_options =3D NULL; QDict *qdict; - QObject *qobj; Visitor *v; BlockDriverState *bs =3D NULL; Error *local_err =3D NULL; @@ -763,14 +762,12 @@ static int coroutine_fn bdrv_qed_co_create_opts(const= char *filename, qdict_put_str(qdict, "driver", "qed"); qdict_put_str(qdict, "file", bs->node_name); =20 - qobj =3D qdict_crumple_for_keyval_qiv(qdict, errp); - if (!qobj) { + v =3D qobject_input_visitor_new_flat_confused(qdict, errp); + if (!v) { ret =3D -EINVAL; goto fail; } =20 - v =3D qobject_input_visitor_new_keyval(qobj); - qobject_unref(qobj); visit_type_BlockdevCreateOptions(v, NULL, &create_options, &local_err); visit_free(v); =20 diff --git a/block/rbd.c b/block/rbd.c index 09720e97c0..82346a2a5e 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -630,7 +630,6 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict *o= ptions, int flags, BDRVRBDState *s =3D bs->opaque; BlockdevOptionsRbd *opts =3D NULL; Visitor *v; - QObject *crumpled =3D NULL; const QDictEntry *e; Error *local_err =3D NULL; char *keypairs, *secretid; @@ -647,16 +646,14 @@ static int qemu_rbd_open(BlockDriverState *bs, QDict = *options, int flags, } =20 /* Convert the remaining options into a QAPI object */ - crumpled =3D qdict_crumple_for_keyval_qiv(options, errp); - if (crumpled =3D=3D NULL) { + v =3D qobject_input_visitor_new_flat_confused(options, errp); + if (!v) { r =3D -EINVAL; goto out; } =20 - v =3D qobject_input_visitor_new_keyval(crumpled); visit_type_BlockdevOptionsRbd(v, NULL, &opts, &local_err); visit_free(v); - qobject_unref(crumpled); =20 if (local_err) { error_propagate(errp, local_err); diff --git a/block/sheepdog.c b/block/sheepdog.c index 29e3e1eaaa..665b1763eb 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -539,19 +539,17 @@ static void sd_aio_setup(SheepdogAIOCB *acb, BDRVShee= pdogState *s, static SocketAddress *sd_server_config(QDict *options, Error **errp) { QDict *server =3D NULL; - QObject *crumpled_server =3D NULL; Visitor *iv =3D NULL; SocketAddress *saddr =3D NULL; Error *local_err =3D NULL; =20 qdict_extract_subqdict(options, &server, "server."); =20 - crumpled_server =3D qdict_crumple_for_keyval_qiv(server, errp); - if (!crumpled_server) { + iv =3D qobject_input_visitor_new_flat_confused(server, errp); + if (!iv) { goto done; } =20 - iv =3D qobject_input_visitor_new_keyval(crumpled_server); visit_type_SocketAddress(iv, NULL, &saddr, &local_err); if (local_err) { error_propagate(errp, local_err); @@ -560,7 +558,6 @@ static SocketAddress *sd_server_config(QDict *options, = Error **errp) =20 done: visit_free(iv); - qobject_unref(crumpled_server); qobject_unref(server); return saddr; } @@ -2173,7 +2170,6 @@ static int coroutine_fn sd_co_create_opts(const char = *filename, QemuOpts *opts, { BlockdevCreateOptions *create_options =3D NULL; QDict *qdict, *location_qdict; - QObject *crumpled; Visitor *v; char *redundancy; Error *local_err =3D NULL; @@ -2209,16 +2205,14 @@ static int coroutine_fn sd_co_create_opts(const cha= r *filename, QemuOpts *opts, } =20 /* Get the QAPI object */ - crumpled =3D qdict_crumple_for_keyval_qiv(qdict, errp); - if (crumpled =3D=3D NULL) { + v =3D qobject_input_visitor_new_flat_confused(qdict, errp); + if (!v) { ret =3D -EINVAL; goto fail; } =20 - v =3D qobject_input_visitor_new_keyval(crumpled); visit_type_BlockdevCreateOptions(v, NULL, &create_options, &local_err); visit_free(v); - qobject_unref(crumpled); =20 if (local_err) { error_propagate(errp, local_err); diff --git a/block/ssh.c b/block/ssh.c index bd85d989d5..da7bbf73e2 100644 --- a/block/ssh.c +++ b/block/ssh.c @@ -606,7 +606,6 @@ static BlockdevOptionsSsh *ssh_parse_options(QDict *opt= ions, Error **errp) BlockdevOptionsSsh *result =3D NULL; QemuOpts *opts =3D NULL; Error *local_err =3D NULL; - QObject *crumpled; const QDictEntry *e; Visitor *v; =20 @@ -623,15 +622,13 @@ static BlockdevOptionsSsh *ssh_parse_options(QDict *o= ptions, Error **errp) } =20 /* Create the QAPI object */ - crumpled =3D qdict_crumple_for_keyval_qiv(options, errp); - if (crumpled =3D=3D NULL) { + v =3D qobject_input_visitor_new_flat_confused(options, errp); + if (!v) { goto fail; } =20 - v =3D qobject_input_visitor_new_keyval(crumpled); visit_type_BlockdevOptionsSsh(v, NULL, &result, &local_err); visit_free(v); - qobject_unref(crumpled); =20 if (local_err) { error_propagate(errp, local_err); diff --git a/block/vhdx.c b/block/vhdx.c index f2aec3d2cd..a677703a9e 100644 --- a/block/vhdx.c +++ b/block/vhdx.c @@ -1966,7 +1966,6 @@ static int coroutine_fn vhdx_co_create_opts(const cha= r *filename, { BlockdevCreateOptions *create_options =3D NULL; QDict *qdict; - QObject *qobj; Visitor *v; BlockDriverState *bs =3D NULL; Error *local_err =3D NULL; @@ -2005,14 +2004,12 @@ static int coroutine_fn vhdx_co_create_opts(const c= har *filename, qdict_put_str(qdict, "driver", "vhdx"); qdict_put_str(qdict, "file", bs->node_name); =20 - qobj =3D qdict_crumple_for_keyval_qiv(qdict, errp); - if (!qobj) { + v =3D qobject_input_visitor_new_flat_confused(qdict, errp); + if (!v) { ret =3D -EINVAL; goto fail; } =20 - v =3D qobject_input_visitor_new_keyval(qobj); - qobject_unref(qobj); visit_type_BlockdevCreateOptions(v, NULL, &create_options, &local_err); visit_free(v); =20 diff --git a/block/vpc.c b/block/vpc.c index a9bb04149d..bf294abfa7 100644 --- a/block/vpc.c +++ b/block/vpc.c @@ -1082,7 +1082,6 @@ static int coroutine_fn vpc_co_create_opts(const char= *filename, { BlockdevCreateOptions *create_options =3D NULL; QDict *qdict; - QObject *qobj; Visitor *v; BlockDriverState *bs =3D NULL; Error *local_err =3D NULL; @@ -1119,14 +1118,12 @@ static int coroutine_fn vpc_co_create_opts(const ch= ar *filename, qdict_put_str(qdict, "driver", "vpc"); qdict_put_str(qdict, "file", bs->node_name); =20 - qobj =3D qdict_crumple_for_keyval_qiv(qdict, errp); - if (!qobj) { + v =3D qobject_input_visitor_new_flat_confused(qdict, errp); + if (!v) { ret =3D -EINVAL; goto fail; } =20 - v =3D qobject_input_visitor_new_keyval(qobj); - qobject_unref(qobj); visit_type_BlockdevCreateOptions(v, NULL, &create_options, &local_err); visit_free(v); =20 diff --git a/qobject/block-qdict.c b/qobject/block-qdict.c index aba372c2eb..41f39abc4a 100644 --- a/qobject/block-qdict.c +++ b/qobject/block-qdict.c @@ -13,6 +13,7 @@ #include "qapi/qmp/qlist.h" #include "qapi/qmp/qnum.h" #include "qapi/qmp/qstring.h" +#include "qapi/qobject-input-visitor.h" #include "qemu/cutils.h" #include "qapi/error.h" =20 @@ -529,7 +530,7 @@ QObject *qdict_crumple(const QDict *src, Error **errp) * used for anything else, and it should go away once the block * subsystem has been cleaned up. */ -QObject *qdict_crumple_for_keyval_qiv(QDict *src, Error **errp) +static QObject *qdict_crumple_for_keyval_qiv(QDict *src, Error **errp) { QDict *tmp =3D NULL; char *buf; @@ -695,3 +696,28 @@ bool qdict_rename_keys(QDict *qdict, const QDictRename= s *renames, Error **errp) } return true; } + +/* + * Create a QObject input visitor for flat @qdict with possibly + * confused scalar types. + * + * The block subsystem uses this function to visit its flat QDict with + * possibly confused scalar types. It should not be used for anything + * else, and it should go away once the block subsystem has been + * cleaned up. + */ +Visitor *qobject_input_visitor_new_flat_confused(QDict *qdict, + Error **errp) +{ + QObject *crumpled; + Visitor *v; + + crumpled =3D qdict_crumple_for_keyval_qiv(qdict, errp); + if (!crumpled) { + return NULL; + } + + v =3D qobject_input_visitor_new_keyval(crumpled); + qobject_unref(crumpled); + return v; +} --=20 2.13.6 From nobody Tue May 7 21:08:57 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 1529073009635454.11860617583363; Fri, 15 Jun 2018 07:30:09 -0700 (PDT) Received: from localhost ([::1]:47172 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpjs-0005Ez-SZ for importer@patchew.org; Fri, 15 Jun 2018 10:30:08 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59167) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpbZ-00066x-6P for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:34 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTpbX-0003j2-Sc for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:33 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:45848 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fTpbQ-0003aF-56; Fri, 15 Jun 2018 10:21:24 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id BADD288840; Fri, 15 Jun 2018 14:21:23 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-70.ams2.redhat.com [10.36.117.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id 151ED63A51; Fri, 15 Jun 2018 14:21:22 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 15 Jun 2018 16:20:55 +0200 Message-Id: <20180615142108.27814-14-kwolf@redhat.com> In-Reply-To: <20180615142108.27814-1-kwolf@redhat.com> References: <20180615142108.27814-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Fri, 15 Jun 2018 14:21:23 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Fri, 15 Jun 2018 14:21:23 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL 13/26] block: Make remaining uses of qobject input visitor more robust 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 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" From: Markus Armbruster Remaining uses of qobject_input_visitor_new_keyval() in the block subsystem: * block_crypto_open_opts_init() Currently doesn't visit any non-string scalars, thus safe. It's called from - block_crypto_open_luks() Creates the QDict with qemu_opts_to_qdict_filtered(), which creates only string scalars, but has a TODO asking for other types. - qcow_open() - qcow2_open(), qcow2_co_invalidate_cache(), qcow2_reopen_prepare() * block_crypto_create_opts_init(), called from - block_crypto_co_create_opts_luks() Also creates the QDict with qemu_opts_to_qdict_filtered(). * vdi_co_create_opts() Also creates the QDict with qemu_opts_to_qdict_filtered(). Replace these uses by qobject_input_visitor_new_flat_confused() for robustness. This adds crumpling. Right now, that's a no-op, but if we ever extend these things in non-flat ways, crumpling will be needed. Signed-off-by: Markus Armbruster Signed-off-by: Kevin Wolf --- block/crypto.c | 12 +++++++++--- block/vdi.c | 8 ++++++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/block/crypto.c b/block/crypto.c index bc322b50f5..82091c5f70 100644 --- a/block/crypto.c +++ b/block/crypto.c @@ -21,11 +21,11 @@ #include "qemu/osdep.h" =20 #include "block/block_int.h" +#include "block/qdict.h" #include "sysemu/block-backend.h" #include "crypto/block.h" #include "qapi/opts-visitor.h" #include "qapi/qapi-visit-crypto.h" -#include "qapi/qmp/qdict.h" #include "qapi/qobject-input-visitor.h" #include "qapi/error.h" #include "qemu/option.h" @@ -159,7 +159,10 @@ block_crypto_open_opts_init(QCryptoBlockFormat format, ret =3D g_new0(QCryptoBlockOpenOptions, 1); ret->format =3D format; =20 - v =3D qobject_input_visitor_new_keyval(QOBJECT(opts)); + v =3D qobject_input_visitor_new_flat_confused(opts, &local_err); + if (local_err) { + goto out; + } =20 visit_start_struct(v, NULL, NULL, 0, &local_err); if (local_err) { @@ -210,7 +213,10 @@ block_crypto_create_opts_init(QCryptoBlockFormat forma= t, ret =3D g_new0(QCryptoBlockCreateOptions, 1); ret->format =3D format; =20 - v =3D qobject_input_visitor_new_keyval(QOBJECT(opts)); + v =3D qobject_input_visitor_new_flat_confused(opts, &local_err); + if (local_err) { + goto out; + } =20 visit_start_struct(v, NULL, NULL, 0, &local_err); if (local_err) { diff --git a/block/vdi.c b/block/vdi.c index 668af0a828..1d8ed67dbf 100644 --- a/block/vdi.c +++ b/block/vdi.c @@ -51,10 +51,10 @@ =20 #include "qemu/osdep.h" #include "qapi/error.h" -#include "qapi/qmp/qdict.h" #include "qapi/qobject-input-visitor.h" #include "qapi/qapi-visit-block-core.h" #include "block/block_int.h" +#include "block/qdict.h" #include "sysemu/block-backend.h" #include "qemu/module.h" #include "qemu/option.h" @@ -934,7 +934,11 @@ static int coroutine_fn vdi_co_create_opts(const char = *filename, QemuOpts *opts, } =20 /* Get the QAPI object */ - v =3D qobject_input_visitor_new_keyval(QOBJECT(qdict)); + v =3D qobject_input_visitor_new_flat_confused(qdict, errp); + if (!v) { + ret =3D -EINVAL; + goto done; + } visit_type_BlockdevCreateOptions(v, NULL, &create_options, &local_err); visit_free(v); =20 --=20 2.13.6 From nobody Tue May 7 21:08:57 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 1529073508298908.8950376633986; Fri, 15 Jun 2018 07:38:28 -0700 (PDT) Received: from localhost ([::1]:47226 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTprv-0004LZ-6w for importer@patchew.org; Fri, 15 Jun 2018 10:38:27 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59049) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpbU-00060q-Do for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:29 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTpbT-0003eY-Bf for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:28 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:50222 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fTpbR-0003aw-39; Fri, 15 Jun 2018 10:21:25 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A500981A3245; Fri, 15 Jun 2018 14:21:24 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-70.ams2.redhat.com [10.36.117.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id 00AFA63A72; Fri, 15 Jun 2018 14:21:23 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 15 Jun 2018 16:20:56 +0200 Message-Id: <20180615142108.27814-15-kwolf@redhat.com> In-Reply-To: <20180615142108.27814-1-kwolf@redhat.com> References: <20180615142108.27814-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Fri, 15 Jun 2018 14:21:24 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Fri, 15 Jun 2018 14:21:24 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL 14/26] block-qdict: Simplify qdict_flatten_qdict() 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 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" From: Markus Armbruster There's no need to restart the loop. We don't elsewhere, e.g. in qdict_extract_subqdict(), qdict_join() and qemu_opts_absorb_qdict(). Simplify accordingly. Signed-off-by: Markus Armbruster Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- qobject/block-qdict.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/qobject/block-qdict.c b/qobject/block-qdict.c index 41f39abc4a..f32df343e8 100644 --- a/qobject/block-qdict.c +++ b/qobject/block-qdict.c @@ -89,16 +89,13 @@ static void qdict_flatten_qdict(QDict *qdict, QDict *ta= rget, const char *prefix) QObject *value; const QDictEntry *entry, *next; char *new_key; - bool delete; =20 entry =3D qdict_first(qdict); =20 while (entry !=3D NULL) { - next =3D qdict_next(qdict, entry); value =3D qdict_entry_value(entry); new_key =3D NULL; - delete =3D false; =20 if (prefix) { new_key =3D g_strdup_printf("%s.%s", prefix, entry->key); @@ -109,27 +106,18 @@ static void qdict_flatten_qdict(QDict *qdict, QDict *= target, const char *prefix) * itself disappears. */ qdict_flatten_qdict(qobject_to(QDict, value), target, new_key ? new_key : entry->key); - delete =3D true; + qdict_del(qdict, entry->key); } else if (qobject_type(value) =3D=3D QTYPE_QLIST) { qdict_flatten_qlist(qobject_to(QList, value), target, new_key ? new_key : entry->key); - delete =3D true; + qdict_del(qdict, entry->key); } else if (prefix) { /* All other objects are moved to the target unchanged. */ qdict_put_obj(target, new_key, qobject_ref(value)); - delete =3D true; - } - - g_free(new_key); - - if (delete) { qdict_del(qdict, entry->key); - - /* Restart loop after modifying the iterated QDict */ - entry =3D qdict_first(qdict); - continue; } =20 + g_free(new_key); entry =3D next; } } --=20 2.13.6 From nobody Tue May 7 21:08:57 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 1529072837954311.71198033516976; Fri, 15 Jun 2018 07:27:17 -0700 (PDT) Received: from localhost ([::1]:47146 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTph6-0002ex-W7 for importer@patchew.org; Fri, 15 Jun 2018 10:27:17 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59089) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpbV-00062T-QF for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:31 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTpbU-0003fW-BE for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:29 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:45850 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fTpbR-0003cQ-UV; Fri, 15 Jun 2018 10:21:25 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9010288840; Fri, 15 Jun 2018 14:21:25 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-70.ams2.redhat.com [10.36.117.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id E06C763A51; Fri, 15 Jun 2018 14:21:24 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 15 Jun 2018 16:20:57 +0200 Message-Id: <20180615142108.27814-16-kwolf@redhat.com> In-Reply-To: <20180615142108.27814-1-kwolf@redhat.com> References: <20180615142108.27814-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Fri, 15 Jun 2018 14:21:25 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Fri, 15 Jun 2018 14:21:25 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL 15/26] block-qdict: Tweak qdict_flatten_qdict(), qdict_flatten_qlist() 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 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" From: Markus Armbruster qdict_flatten_qdict() skips copying scalars from @qdict to @target when the two are the same. Fair enough, but it uses a non-obvious test for "same". Replace it by the obvious one. While there, improve comments. Signed-off-by: Markus Armbruster Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- qobject/block-qdict.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/qobject/block-qdict.c b/qobject/block-qdict.c index f32df343e8..a4e1c8d08f 100644 --- a/qobject/block-qdict.c +++ b/qobject/block-qdict.c @@ -71,12 +71,15 @@ static void qdict_flatten_qlist(QList *qlist, QDict *ta= rget, const char *prefix) value =3D qlist_entry_obj(entry); new_key =3D g_strdup_printf("%s.%i", prefix, i); =20 + /* + * Flatten non-empty QDict and QList recursively into @target, + * copy other objects to @target + */ if (qobject_type(value) =3D=3D QTYPE_QDICT) { qdict_flatten_qdict(qobject_to(QDict, value), target, new_key); } else if (qobject_type(value) =3D=3D QTYPE_QLIST) { qdict_flatten_qlist(qobject_to(QList, value), target, new_key); } else { - /* All other types are moved to the target unchanged. */ qdict_put_obj(target, new_key, qobject_ref(value)); } =20 @@ -101,9 +104,11 @@ static void qdict_flatten_qdict(QDict *qdict, QDict *t= arget, const char *prefix) new_key =3D g_strdup_printf("%s.%s", prefix, entry->key); } =20 + /* + * Flatten non-empty QDict and QList recursively into @target, + * copy other objects to @target + */ if (qobject_type(value) =3D=3D QTYPE_QDICT) { - /* Entries of QDicts are processed recursively, the QDict obje= ct - * itself disappears. */ qdict_flatten_qdict(qobject_to(QDict, value), target, new_key ? new_key : entry->key); qdict_del(qdict, entry->key); @@ -111,8 +116,7 @@ static void qdict_flatten_qdict(QDict *qdict, QDict *ta= rget, const char *prefix) qdict_flatten_qlist(qobject_to(QList, value), target, new_key ? new_key : entry->key); qdict_del(qdict, entry->key); - } else if (prefix) { - /* All other objects are moved to the target unchanged. */ + } else if (target !=3D qdict) { qdict_put_obj(target, new_key, qobject_ref(value)); qdict_del(qdict, entry->key); } --=20 2.13.6 From nobody Tue May 7 21:08:57 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 152907360785798.44568343999913; Fri, 15 Jun 2018 07:40:07 -0700 (PDT) Received: from localhost ([::1]:47233 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTptX-0005hT-2a for importer@patchew.org; Fri, 15 Jun 2018 10:40:07 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59160) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpbY-00066I-Lg for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:34 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTpbX-0003iK-CI for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:32 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:50224 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fTpbS-0003dU-TU; Fri, 15 Jun 2018 10:21:27 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 7B31F81A3245; Fri, 15 Jun 2018 14:21:26 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-70.ams2.redhat.com [10.36.117.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id CBF8463A51; Fri, 15 Jun 2018 14:21:25 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 15 Jun 2018 16:20:58 +0200 Message-Id: <20180615142108.27814-17-kwolf@redhat.com> In-Reply-To: <20180615142108.27814-1-kwolf@redhat.com> References: <20180615142108.27814-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Fri, 15 Jun 2018 14:21:26 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Fri, 15 Jun 2018 14:21:26 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL 16/26] block-qdict: Clean up qdict_crumple() a bit 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 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" From: Markus Armbruster When you mix scalar and non-scalar keys, whether you get an "already set as scalar" or an "already set as dict" error depends on qdict iteration order. Neither message makes much sense. Replace by ""Cannot mix scalar and non-scalar keys". This is similar to the message we get for mixing list and non-list keys. I find qdict_crumple()'s first loop hard to understand. Rearrange it and add a comment. Signed-off-by: Markus Armbruster Signed-off-by: Kevin Wolf --- qobject/block-qdict.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/qobject/block-qdict.c b/qobject/block-qdict.c index a4e1c8d08f..36cf58acc8 100644 --- a/qobject/block-qdict.c +++ b/qobject/block-qdict.c @@ -403,7 +403,7 @@ static int qdict_is_list(QDict *maybe_list, Error **err= p) QObject *qdict_crumple(const QDict *src, Error **errp) { const QDictEntry *ent; - QDict *two_level, *multi_level =3D NULL; + QDict *two_level, *multi_level =3D NULL, *child_dict; QObject *dst =3D NULL, *child; size_t i; char *prefix =3D NULL; @@ -422,28 +422,28 @@ QObject *qdict_crumple(const QDict *src, Error **errp) } =20 qdict_split_flat_key(ent->key, &prefix, &suffix); - child =3D qdict_get(two_level, prefix); + child_dict =3D qobject_to(QDict, child); + + if (child) { + /* + * If @child_dict, then all previous keys with this prefix + * had a suffix. If @suffix, this one has one as well, + * and we're good, else there's a clash. + */ + if (!child_dict || !suffix) { + error_setg(errp, "Cannot mix scalar and non-scalar keys"); + goto error; + } + } + if (suffix) { - QDict *child_dict =3D qobject_to(QDict, child); if (!child_dict) { - if (child) { - error_setg(errp, "Key %s prefix is already set as a sc= alar", - prefix); - goto error; - } - child_dict =3D qdict_new(); - qdict_put_obj(two_level, prefix, QOBJECT(child_dict)); + qdict_put(two_level, prefix, child_dict); } - qdict_put_obj(child_dict, suffix, qobject_ref(ent->value)); } else { - if (child) { - error_setg(errp, "Key %s prefix is already set as a dict", - prefix); - goto error; - } qdict_put_obj(two_level, prefix, qobject_ref(ent->value)); } =20 --=20 2.13.6 From nobody Tue May 7 21:08:57 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 1529073203706285.09934047809156; Fri, 15 Jun 2018 07:33:23 -0700 (PDT) Received: from localhost ([::1]:47191 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpn0-00089s-RZ for importer@patchew.org; Fri, 15 Jun 2018 10:33:22 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59163) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpbY-00066Q-Qs for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:34 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTpbX-0003iv-Qb for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:32 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:55628 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fTpbT-0003ej-Pq; Fri, 15 Jun 2018 10:21:27 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 6886387A81; Fri, 15 Jun 2018 14:21:27 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-70.ams2.redhat.com [10.36.117.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id B877563A51; Fri, 15 Jun 2018 14:21:26 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 15 Jun 2018 16:20:59 +0200 Message-Id: <20180615142108.27814-18-kwolf@redhat.com> In-Reply-To: <20180615142108.27814-1-kwolf@redhat.com> References: <20180615142108.27814-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Fri, 15 Jun 2018 14:21:27 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Fri, 15 Jun 2018 14:21:27 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL 17/26] block-qdict: Simplify qdict_is_list() some 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 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" From: Markus Armbruster Signed-off-by: Markus Armbruster Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- qobject/block-qdict.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/qobject/block-qdict.c b/qobject/block-qdict.c index 36cf58acc8..e51a3d2c0f 100644 --- a/qobject/block-qdict.c +++ b/qobject/block-qdict.c @@ -317,27 +317,22 @@ static int qdict_is_list(QDict *maybe_list, Error **e= rrp) =20 for (ent =3D qdict_first(maybe_list); ent !=3D NULL; ent =3D qdict_next(maybe_list, ent)) { + int is_index =3D !qemu_strtoi64(ent->key, NULL, 10, &val); =20 - if (qemu_strtoi64(ent->key, NULL, 10, &val) =3D=3D 0) { - if (is_list =3D=3D -1) { - is_list =3D 1; - } else if (!is_list) { - error_setg(errp, - "Cannot mix list and non-list keys"); - return -1; - } + if (is_list =3D=3D -1) { + is_list =3D is_index; + } + + if (is_index !=3D is_list) { + error_setg(errp, "Cannot mix list and non-list keys"); + return -1; + } + + if (is_index) { len++; if (val > max) { max =3D val; } - } else { - if (is_list =3D=3D -1) { - is_list =3D 0; - } else if (is_list) { - error_setg(errp, - "Cannot mix list and non-list keys"); - return -1; - } } } =20 --=20 2.13.6 From nobody Tue May 7 21:08:57 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 1529073979883136.05339824515102; Fri, 15 Jun 2018 07:46:19 -0700 (PDT) Received: from localhost ([::1]:47281 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpzX-0002fC-5t for importer@patchew.org; Fri, 15 Jun 2018 10:46:19 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59321) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpbf-0006FN-DD for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:40 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTpbZ-0003kh-2e for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:39 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:54414 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fTpbU-0003fm-MO; Fri, 15 Jun 2018 10:21:28 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 53F7A40122A1; Fri, 15 Jun 2018 14:21:28 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-70.ams2.redhat.com [10.36.117.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id A425C63A72; Fri, 15 Jun 2018 14:21:27 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 15 Jun 2018 16:21:00 +0200 Message-Id: <20180615142108.27814-19-kwolf@redhat.com> In-Reply-To: <20180615142108.27814-1-kwolf@redhat.com> References: <20180615142108.27814-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Fri, 15 Jun 2018 14:21:28 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Fri, 15 Jun 2018 14:21:28 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL 18/26] check-block-qdict: Rename qdict_flatten()'s variables for clarity 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 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" From: Markus Armbruster Signed-off-by: Markus Armbruster Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- tests/check-block-qdict.c | 57 ++++++++++++++++++++++++-------------------= ---- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/tests/check-block-qdict.c b/tests/check-block-qdict.c index 5b9f4d506e..29f58a2d3d 100644 --- a/tests/check-block-qdict.c +++ b/tests/check-block-qdict.c @@ -37,11 +37,11 @@ static void qdict_defaults_test(void) =20 static void qdict_flatten_test(void) { - QList *list1 =3D qlist_new(); - QList *list2 =3D qlist_new(); - QDict *dict1 =3D qdict_new(); - QDict *dict2 =3D qdict_new(); - QDict *dict3 =3D qdict_new(); + QList *e_1 =3D qlist_new(); + QList *e =3D qlist_new(); + QDict *e_1_2 =3D qdict_new(); + QDict *f =3D qdict_new(); + QDict *root =3D qdict_new(); =20 /* * Test the flattening of @@ -79,35 +79,36 @@ static void qdict_flatten_test(void) * } */ =20 - qdict_put_int(dict1, "a", 0); - qdict_put_int(dict1, "b", 1); + qdict_put_int(e_1_2, "a", 0); + qdict_put_int(e_1_2, "b", 1); =20 - qlist_append_int(list1, 23); - qlist_append_int(list1, 66); - qlist_append(list1, dict1); - qlist_append_int(list2, 42); - qlist_append(list2, list1); + qlist_append_int(e_1, 23); + qlist_append_int(e_1, 66); + qlist_append(e_1, e_1_2); + qlist_append_int(e, 42); + qlist_append(e, e_1); =20 - qdict_put_int(dict2, "c", 2); - qdict_put_int(dict2, "d", 3); - qdict_put(dict3, "e", list2); - qdict_put(dict3, "f", dict2); - qdict_put_int(dict3, "g", 4); + qdict_put_int(f, "c", 2); + qdict_put_int(f, "d", 3); =20 - qdict_flatten(dict3); + qdict_put(root, "e", e); + qdict_put(root, "f", f); + qdict_put_int(root, "g", 4); =20 - g_assert(qdict_get_int(dict3, "e.0") =3D=3D 42); - g_assert(qdict_get_int(dict3, "e.1.0") =3D=3D 23); - g_assert(qdict_get_int(dict3, "e.1.1") =3D=3D 66); - g_assert(qdict_get_int(dict3, "e.1.2.a") =3D=3D 0); - g_assert(qdict_get_int(dict3, "e.1.2.b") =3D=3D 1); - g_assert(qdict_get_int(dict3, "f.c") =3D=3D 2); - g_assert(qdict_get_int(dict3, "f.d") =3D=3D 3); - g_assert(qdict_get_int(dict3, "g") =3D=3D 4); + qdict_flatten(root); =20 - g_assert(qdict_size(dict3) =3D=3D 8); + g_assert(qdict_get_int(root, "e.0") =3D=3D 42); + g_assert(qdict_get_int(root, "e.1.0") =3D=3D 23); + g_assert(qdict_get_int(root, "e.1.1") =3D=3D 66); + g_assert(qdict_get_int(root, "e.1.2.a") =3D=3D 0); + g_assert(qdict_get_int(root, "e.1.2.b") =3D=3D 1); + g_assert(qdict_get_int(root, "f.c") =3D=3D 2); + g_assert(qdict_get_int(root, "f.d") =3D=3D 3); + g_assert(qdict_get_int(root, "g") =3D=3D 4); =20 - qobject_unref(dict3); + g_assert(qdict_size(root) =3D=3D 8); + + qobject_unref(root); } =20 static void qdict_array_split_test(void) --=20 2.13.6 From nobody Tue May 7 21:08:57 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 1529073405116129.14129547871005; Fri, 15 Jun 2018 07:36:45 -0700 (PDT) Received: from localhost ([::1]:47212 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpqG-0002v5-By for importer@patchew.org; Fri, 15 Jun 2018 10:36:44 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59199) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpba-00068B-5u for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:38 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTpbY-0003kW-WE for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:34 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:54416 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fTpbV-0003gJ-J8; Fri, 15 Jun 2018 10:21:29 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 3EF8B40122A1; Fri, 15 Jun 2018 14:21:29 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-70.ams2.redhat.com [10.36.117.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8FB406352E; Fri, 15 Jun 2018 14:21:28 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 15 Jun 2018 16:21:01 +0200 Message-Id: <20180615142108.27814-20-kwolf@redhat.com> In-Reply-To: <20180615142108.27814-1-kwolf@redhat.com> References: <20180615142108.27814-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Fri, 15 Jun 2018 14:21:29 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Fri, 15 Jun 2018 14:21:29 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL 19/26] check-block-qdict: Cover flattening of empty lists and dictionaries 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 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" From: Markus Armbruster Signed-off-by: Markus Armbruster Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- tests/check-block-qdict.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/check-block-qdict.c b/tests/check-block-qdict.c index 29f58a2d3d..2da16f01a6 100644 --- a/tests/check-block-qdict.c +++ b/tests/check-block-qdict.c @@ -41,6 +41,8 @@ static void qdict_flatten_test(void) QList *e =3D qlist_new(); QDict *e_1_2 =3D qdict_new(); QDict *f =3D qdict_new(); + QList *y =3D qlist_new(); + QDict *z =3D qdict_new(); QDict *root =3D qdict_new(); =20 /* @@ -62,7 +64,9 @@ static void qdict_flatten_test(void) * "c": 2, * "d": 3, * }, - * "g": 4 + * "g": 4, + * "y": [{}], + * "z": {"a": []} * } * * to @@ -77,6 +81,8 @@ static void qdict_flatten_test(void) * "f.d": 3, * "g": 4 * } + * + * Note that "y" and "z" get eaten. */ =20 qdict_put_int(e_1_2, "a", 0); @@ -91,9 +97,15 @@ static void qdict_flatten_test(void) qdict_put_int(f, "c", 2); qdict_put_int(f, "d", 3); =20 + qlist_append(y, qdict_new()); + + qdict_put(z, "a", qlist_new()); + qdict_put(root, "e", e); qdict_put(root, "f", f); qdict_put_int(root, "g", 4); + qdict_put(root, "y", y); + qdict_put(root, "z", z); =20 qdict_flatten(root); =20 --=20 2.13.6 From nobody Tue May 7 21:08:57 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 1529073405776979.650437526299; Fri, 15 Jun 2018 07:36:45 -0700 (PDT) Received: from localhost ([::1]:47213 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpqG-0002vj-Vk for importer@patchew.org; Fri, 15 Jun 2018 10:36:45 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59285) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpbd-0006Cd-GU for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:40 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTpbb-0003n2-B1 for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:37 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:50226 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fTpbW-0003hQ-GG; Fri, 15 Jun 2018 10:21:30 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2B64081A3245; Fri, 15 Jun 2018 14:21:30 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-70.ams2.redhat.com [10.36.117.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7B6DA6352E; Fri, 15 Jun 2018 14:21:29 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 15 Jun 2018 16:21:02 +0200 Message-Id: <20180615142108.27814-21-kwolf@redhat.com> In-Reply-To: <20180615142108.27814-1-kwolf@redhat.com> References: <20180615142108.27814-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Fri, 15 Jun 2018 14:21:30 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Fri, 15 Jun 2018 14:21:30 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL 20/26] block: Fix -blockdev / blockdev-add for empty objects and arrays 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 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" From: Markus Armbruster -blockdev and blockdev-add silently ignore empty objects and arrays in their argument. That's because qmp_blockdev_add() converts the argument to a flat QDict, and qdict_flatten() eats empty QDict and QList members. For instance, we ignore an empty BlockdevOptions member @cache. No real harm, as absent means the same as empty there. Thus, the flaw puts an artificial restriction on the QAPI schema: we can't have potentially empty objects and arrays within BlockdevOptions, except when they're optional and "empty" has the same meaning as "absent". Our QAPI schema satisfies this restriction (I checked), but it's a trap for the unwary, and a temptation to employ awkward workarounds for the wary. Let's get rid of it. Change qdict_flatten() and qdict_crumple() to treat empty dictionaries and lists exactly like scalars. Signed-off-by: Markus Armbruster Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- qobject/block-qdict.c | 54 +++++++++++++++++++++++++++++--------------= ---- tests/check-block-qdict.c | 38 ++++++++++++++++++++++++++------- 2 files changed, 63 insertions(+), 29 deletions(-) diff --git a/qobject/block-qdict.c b/qobject/block-qdict.c index e51a3d2c0f..df833083a7 100644 --- a/qobject/block-qdict.c +++ b/qobject/block-qdict.c @@ -56,6 +56,8 @@ static void qdict_flatten_qlist(QList *qlist, QDict *targ= et, const char *prefix) { QObject *value; const QListEntry *entry; + QDict *dict_val; + QList *list_val; char *new_key; int i; =20 @@ -69,16 +71,18 @@ static void qdict_flatten_qlist(QList *qlist, QDict *ta= rget, const char *prefix) =20 for (i =3D 0; entry; entry =3D qlist_next(entry), i++) { value =3D qlist_entry_obj(entry); + dict_val =3D qobject_to(QDict, value); + list_val =3D qobject_to(QList, value); new_key =3D g_strdup_printf("%s.%i", prefix, i); =20 /* * Flatten non-empty QDict and QList recursively into @target, * copy other objects to @target */ - if (qobject_type(value) =3D=3D QTYPE_QDICT) { - qdict_flatten_qdict(qobject_to(QDict, value), target, new_key); - } else if (qobject_type(value) =3D=3D QTYPE_QLIST) { - qdict_flatten_qlist(qobject_to(QList, value), target, new_key); + if (dict_val && qdict_size(dict_val)) { + qdict_flatten_qdict(dict_val, target, new_key); + } else if (list_val && !qlist_empty(list_val)) { + qdict_flatten_qlist(list_val, target, new_key); } else { qdict_put_obj(target, new_key, qobject_ref(value)); } @@ -91,6 +95,8 @@ static void qdict_flatten_qdict(QDict *qdict, QDict *targ= et, const char *prefix) { QObject *value; const QDictEntry *entry, *next; + QDict *dict_val; + QList *list_val; char *new_key; =20 entry =3D qdict_first(qdict); @@ -98,6 +104,8 @@ static void qdict_flatten_qdict(QDict *qdict, QDict *tar= get, const char *prefix) while (entry !=3D NULL) { next =3D qdict_next(qdict, entry); value =3D qdict_entry_value(entry); + dict_val =3D qobject_to(QDict, value); + list_val =3D qobject_to(QList, value); new_key =3D NULL; =20 if (prefix) { @@ -108,12 +116,12 @@ static void qdict_flatten_qdict(QDict *qdict, QDict *= target, const char *prefix) * Flatten non-empty QDict and QList recursively into @target, * copy other objects to @target */ - if (qobject_type(value) =3D=3D QTYPE_QDICT) { - qdict_flatten_qdict(qobject_to(QDict, value), target, + if (dict_val && qdict_size(dict_val)) { + qdict_flatten_qdict(dict_val, target, new_key ? new_key : entry->key); qdict_del(qdict, entry->key); - } else if (qobject_type(value) =3D=3D QTYPE_QLIST) { - qdict_flatten_qlist(qobject_to(QList, value), target, + } else if (list_val && !qlist_empty(list_val)) { + qdict_flatten_qlist(list_val, target, new_key ? new_key : entry->key); qdict_del(qdict, entry->key); } else if (target !=3D qdict) { @@ -127,10 +135,11 @@ static void qdict_flatten_qdict(QDict *qdict, QDict *= target, const char *prefix) } =20 /** - * qdict_flatten(): For each nested QDict with key x, all fields with key y - * are moved to this QDict and their key is renamed to "x.y". For each nes= ted - * QList with key x, the field at index y is moved to this QDict with the = key - * "x.y" (i.e., the reverse of what qdict_array_split() does). + * qdict_flatten(): For each nested non-empty QDict with key x, all + * fields with key y are moved to this QDict and their key is renamed + * to "x.y". For each nested non-empty QList with key x, the field at + * index y is moved to this QDict with the key "x.y" (i.e., the + * reverse of what qdict_array_split() does). * This operation is applied recursively for nested QDicts and QLists. */ void qdict_flatten(QDict *qdict) @@ -361,8 +370,8 @@ static int qdict_is_list(QDict *maybe_list, Error **err= p) * @src: the original flat dictionary (only scalar values) to crumple * * Takes a flat dictionary whose keys use '.' separator to indicate - * nesting, and values are scalars, and crumples it into a nested - * structure. + * nesting, and values are scalars, empty dictionaries or empty lists, + * and crumples it into a nested structure. * * To include a literal '.' in a key name, it must be escaped as '..' * @@ -399,6 +408,8 @@ QObject *qdict_crumple(const QDict *src, Error **errp) { const QDictEntry *ent; QDict *two_level, *multi_level =3D NULL, *child_dict; + QDict *dict_val; + QList *list_val; QObject *dst =3D NULL, *child; size_t i; char *prefix =3D NULL; @@ -409,10 +420,11 @@ QObject *qdict_crumple(const QDict *src, Error **errp) =20 /* Step 1: split our totally flat dict into a two level dict */ for (ent =3D qdict_first(src); ent !=3D NULL; ent =3D qdict_next(src, = ent)) { - if (qobject_type(ent->value) =3D=3D QTYPE_QDICT || - qobject_type(ent->value) =3D=3D QTYPE_QLIST) { - error_setg(errp, "Value %s is not a scalar", - ent->key); + dict_val =3D qobject_to(QDict, ent->value); + list_val =3D qobject_to(QList, ent->value); + if ((dict_val && qdict_size(dict_val)) + || (list_val && !qlist_empty(list_val))) { + error_setg(errp, "Value %s is not flat", ent->key); goto error; } =20 @@ -451,9 +463,9 @@ QObject *qdict_crumple(const QDict *src, Error **errp) multi_level =3D qdict_new(); for (ent =3D qdict_first(two_level); ent !=3D NULL; ent =3D qdict_next(two_level, ent)) { - QDict *dict =3D qobject_to(QDict, ent->value); - if (dict) { - child =3D qdict_crumple(dict, errp); + dict_val =3D qobject_to(QDict, ent->value); + if (dict_val && qdict_size(dict_val)) { + child =3D qdict_crumple(dict_val, errp); if (!child) { goto error; } diff --git a/tests/check-block-qdict.c b/tests/check-block-qdict.c index 2da16f01a6..1d20fccbd4 100644 --- a/tests/check-block-qdict.c +++ b/tests/check-block-qdict.c @@ -79,10 +79,10 @@ static void qdict_flatten_test(void) * "e.1.2.b": 1, * "f.c": 2, * "f.d": 3, - * "g": 4 + * "g": 4, + * "y.0": {}, + * "z.a": [] * } - * - * Note that "y" and "z" get eaten. */ =20 qdict_put_int(e_1_2, "a", 0); @@ -117,8 +117,10 @@ static void qdict_flatten_test(void) g_assert(qdict_get_int(root, "f.c") =3D=3D 2); g_assert(qdict_get_int(root, "f.d") =3D=3D 3); g_assert(qdict_get_int(root, "g") =3D=3D 4); + g_assert(!qdict_size(qdict_get_qdict(root, "y.0"))); + g_assert(qlist_empty(qdict_get_qlist(root, "z.a"))); =20 - g_assert(qdict_size(root) =3D=3D 8); + g_assert(qdict_size(root) =3D=3D 10); =20 qobject_unref(root); } @@ -387,7 +389,8 @@ static void qdict_join_test(void) static void qdict_crumple_test_recursive(void) { QDict *src, *dst, *rule, *vnc, *acl, *listen; - QList *rules; + QDict *empty, *empty_dict, *empty_list_0; + QList *rules, *empty_list, *empty_dict_a; =20 src =3D qdict_new(); qdict_put_str(src, "vnc.listen.addr", "127.0.0.1"); @@ -399,10 +402,12 @@ static void qdict_crumple_test_recursive(void) qdict_put_str(src, "vnc.acl.default", "deny"); qdict_put_str(src, "vnc.acl..name", "acl0"); qdict_put_str(src, "vnc.acl.rule..name", "acl0"); + qdict_put(src, "empty.dict.a", qlist_new()); + qdict_put(src, "empty.list.0", qdict_new()); =20 dst =3D qobject_to(QDict, qdict_crumple(src, &error_abort)); g_assert(dst); - g_assert_cmpint(qdict_size(dst), =3D=3D, 1); + g_assert_cmpint(qdict_size(dst), =3D=3D, 2); =20 vnc =3D qdict_get_qdict(dst, "vnc"); g_assert(vnc); @@ -440,6 +445,21 @@ static void qdict_crumple_test_recursive(void) g_assert_cmpstr("acl0", =3D=3D, qdict_get_str(vnc, "acl.name")); g_assert_cmpstr("acl0", =3D=3D, qdict_get_str(acl, "rule.name")); =20 + empty =3D qdict_get_qdict(dst, "empty"); + g_assert(empty); + g_assert_cmpint(qdict_size(empty), =3D=3D, 2); + empty_dict =3D qdict_get_qdict(empty, "dict"); + g_assert(empty_dict); + g_assert_cmpint(qdict_size(empty_dict), =3D=3D, 1); + empty_dict_a =3D qdict_get_qlist(empty_dict, "a"); + g_assert(empty_dict_a && qlist_empty(empty_dict_a)); + empty_list =3D qdict_get_qlist(empty, "list"); + g_assert(empty_list); + g_assert_cmpint(qlist_size(empty_list), =3D=3D, 1); + empty_list_0 =3D qobject_to(QDict, qlist_pop(empty_list)); + g_assert(empty_list_0); + g_assert_cmpint(qdict_size(empty_list_0), =3D=3D, 0); + qobject_unref(src); qobject_unref(dst); } @@ -587,7 +607,7 @@ static void qdict_rename_keys_test(void) =20 static void qdict_crumple_test_bad_inputs(void) { - QDict *src; + QDict *src, *nested; Error *error =3D NULL; =20 src =3D qdict_new(); @@ -614,7 +634,9 @@ static void qdict_crumple_test_bad_inputs(void) =20 src =3D qdict_new(); /* The input should be flat, ie no dicts or lists */ - qdict_put(src, "rule.a", qdict_new()); + nested =3D qdict_new(); + qdict_put(nested, "x", qdict_new()); + qdict_put(src, "rule.a", nested); qdict_put_str(src, "rule.b", "allow"); =20 g_assert(qdict_crumple(src, &error) =3D=3D NULL); --=20 2.13.6 From nobody Tue May 7 21:08:57 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 1529073810450329.37093871085926; Fri, 15 Jun 2018 07:43:30 -0700 (PDT) Received: from localhost ([::1]:47258 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpwn-0000AX-Gx for importer@patchew.org; Fri, 15 Jun 2018 10:43:29 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59254) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpbc-0006Bd-Ot for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:38 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTpbb-0003mp-2K for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:36 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:54418 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fTpbX-0003iF-FB; Fri, 15 Jun 2018 10:21:31 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 16AC540122A1; Fri, 15 Jun 2018 14:21:31 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-70.ams2.redhat.com [10.36.117.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id 671AE6352E; Fri, 15 Jun 2018 14:21:30 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 15 Jun 2018 16:21:03 +0200 Message-Id: <20180615142108.27814-22-kwolf@redhat.com> In-Reply-To: <20180615142108.27814-1-kwolf@redhat.com> References: <20180615142108.27814-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Fri, 15 Jun 2018 14:21:31 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Fri, 15 Jun 2018 14:21:31 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL 21/26] rbd: New parameter auth-client-required 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 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" From: Markus Armbruster Parameter auth-client-required lets you configure authentication methods. We tried to provide that in v2.9.0, but backed out due to interface design doubts (commit 464444fcc16). This commit is similar to what we backed out, but simpler: we use a list of enumeration values instead of a list of objects with a member of enumeration type. Let's review our reasons for backing out the first try, as stated in the commit message: * The implementation uses deprecated rados_conf_set() key "auth_supported". No biggie. Fixed: we use "auth-client-required". * The implementation makes -drive silently ignore invalid parameters "auth" and "auth-supported.*.X" where X isn't "auth". Fixable (in fact I'm going to fix similar bugs around parameter server), so again no biggie. That fix is commit 2836284db60. This commit doesn't bring the bugs back. * BlockdevOptionsRbd member @password-secret applies only to authentication method cephx. Should it be a variant member of RbdAuthMethod? We've had time to ponder, and we decided to stick to the way Ceph configuration works: the key configured separately, and silently ignored if the authentication method doesn't use it. * BlockdevOptionsRbd member @user could apply to both methods cephx and none, but I'm not sure it's actually used with none. If it isn't, should it be a variant member of RbdAuthMethod? Likewise. * The client offers a *set* of authentication methods, not a list. Should the methods be optional members of BlockdevOptionsRbd instead of members of list @auth-supported? The latter begs the question what multiple entries for the same method mean. Trivial question now that RbdAuthMethod contains nothing but @type, but less so when RbdAuthMethod acquires other members, such the ones discussed above. Again, we decided to stick to the way Ceph configuration works, except we make auth-client-required a list of enumeration values instead of a string containing keywords separated by delimiters. * How BlockdevOptionsRbd member @auth-supported interacts with settings from a configuration file specified with @conf is undocumented. I suspect it's untested, too. Not actually true, the documentation for @conf says "Values in the configuration file will be overridden by options specified via QAPI", and we've tested this. Signed-off-by: Markus Armbruster Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- qapi/block-core.json | 13 +++++++++++++ block/rbd.c | 42 ++++++++++++++++++++++++++++++++---------- 2 files changed, 45 insertions(+), 10 deletions(-) diff --git a/qapi/block-core.json b/qapi/block-core.json index fff23fc82b..0f68ca56f3 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -3178,6 +3178,14 @@ =20 =20 ## +# @RbdAuthMode: +# +# Since: 3.0 +## +{ 'enum': 'RbdAuthMode', + 'data': [ 'cephx', 'none' ] } + +## # @BlockdevOptionsRbd: # # @pool: Ceph pool name. @@ -3192,6 +3200,10 @@ # # @user: Ceph id name. # +# @auth-client-required: Acceptable authentication modes. +# This maps to Ceph configuration option +# "auth_client_required". (Since 3.0) +# # @server: Monitor host address and port. This maps # to the "mon_host" Ceph option. # @@ -3203,6 +3215,7 @@ '*conf': 'str', '*snapshot': 'str', '*user': 'str', + '*auth-client-required': ['RbdAuthMode'], '*server': ['InetSocketAddressBase'] } } =20 ## diff --git a/block/rbd.c b/block/rbd.c index 82346a2a5e..ea0575d068 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -240,20 +240,42 @@ static void qemu_rbd_refresh_limits(BlockDriverState = *bs, Error **errp) =20 =20 static int qemu_rbd_set_auth(rados_t cluster, const char *secretid, + BlockdevOptionsRbd *opts, Error **errp) { - if (secretid =3D=3D 0) { - return 0; - } + char *acr; + int r; + GString *accu; + RbdAuthModeList *auth; + + if (secretid) { + gchar *secret =3D qcrypto_secret_lookup_as_base64(secretid, + errp); + if (!secret) { + return -1; + } =20 - gchar *secret =3D qcrypto_secret_lookup_as_base64(secretid, - errp); - if (!secret) { - return -1; + rados_conf_set(cluster, "key", secret); + g_free(secret); } =20 - rados_conf_set(cluster, "key", secret); - g_free(secret); + if (opts->has_auth_client_required) { + accu =3D g_string_new(""); + for (auth =3D opts->auth_client_required; auth; auth =3D auth->nex= t) { + if (accu->str[0]) { + g_string_append_c(accu, ';'); + } + g_string_append(accu, RbdAuthMode_str(auth->value)); + } + acr =3D g_string_free(accu, FALSE); + r =3D rados_conf_set(cluster, "auth_client_required", acr); + g_free(acr); + if (r < 0) { + error_setg_errno(errp, -r, + "Could not set 'auth_client_required'"); + return r; + } + } =20 return 0; } @@ -585,7 +607,7 @@ static int qemu_rbd_connect(rados_t *cluster, rados_ioc= tx_t *io_ctx, } } =20 - if (qemu_rbd_set_auth(*cluster, secretid, errp) < 0) { + if (qemu_rbd_set_auth(*cluster, secretid, opts, errp) < 0) { r =3D -EIO; goto failed_shutdown; } --=20 2.13.6 From nobody Tue May 7 21:08:57 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 1529073584330252.6669896726919; Fri, 15 Jun 2018 07:39:44 -0700 (PDT) Received: from localhost ([::1]:47229 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpt9-0005Nt-Hc for importer@patchew.org; Fri, 15 Jun 2018 10:39:43 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59277) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpbd-0006C2-84 for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:40 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTpbb-0003ny-Vy for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:37 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:50228 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fTpbY-0003jF-Cp; Fri, 15 Jun 2018 10:21:32 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 0318981A3245; Fri, 15 Jun 2018 14:21:32 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-70.ams2.redhat.com [10.36.117.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id 534E063A72; Fri, 15 Jun 2018 14:21:31 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 15 Jun 2018 16:21:04 +0200 Message-Id: <20180615142108.27814-23-kwolf@redhat.com> In-Reply-To: <20180615142108.27814-1-kwolf@redhat.com> References: <20180615142108.27814-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Fri, 15 Jun 2018 14:21:32 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Fri, 15 Jun 2018 14:21:32 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL 22/26] rbd: New parameter key-secret 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 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" From: Markus Armbruster Legacy -drive supports "password-secret" parameter that isn't available with -blockdev / blockdev-add. That's because we backed out our first try to provide it there due to interface design doubts, in commit 577d8c9a811, v2.9.0. This is the second try. It brings back the parameter, except it's named "key-secret" now. Let's review our reasons for backing out the first try, as stated in the commit message: * BlockdevOptionsRbd member @password-secret isn't actually a password, it's a key generated by Ceph. Addressed by the rename. * We're not sure where member @password-secret belongs (see the previous commit). See previous commit. * How @password-secret interacts with settings from a configuration file specified with @conf is undocumented. Not actually true, the documentation for @conf says "Values in the configuration file will be overridden by options specified via QAPI", and we've tested this. Signed-off-by: Markus Armbruster Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- qapi/block-core.json | 6 ++++++ block/rbd.c | 41 +++++++++++++++++++++++++---------------- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/qapi/block-core.json b/qapi/block-core.json index 0f68ca56f3..ab629d1647 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -3204,6 +3204,11 @@ # This maps to Ceph configuration option # "auth_client_required". (Since 3.0) # +# @key-secret: ID of a QCryptoSecret object providing a key +# for cephx authentication. +# This maps to Ceph configuration option +# "key". (Since 3.0) +# # @server: Monitor host address and port. This maps # to the "mon_host" Ceph option. # @@ -3216,6 +3221,7 @@ '*snapshot': 'str', '*user': 'str', '*auth-client-required': ['RbdAuthMode'], + '*key-secret': 'str', '*server': ['InetSocketAddressBase'] } } =20 ## diff --git a/block/rbd.c b/block/rbd.c index ea0575d068..f2c6965418 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -239,24 +239,25 @@ static void qemu_rbd_refresh_limits(BlockDriverState = *bs, Error **errp) } =20 =20 -static int qemu_rbd_set_auth(rados_t cluster, const char *secretid, - BlockdevOptionsRbd *opts, +static int qemu_rbd_set_auth(rados_t cluster, BlockdevOptionsRbd *opts, Error **errp) { - char *acr; + char *key, *acr; int r; GString *accu; RbdAuthModeList *auth; =20 - if (secretid) { - gchar *secret =3D qcrypto_secret_lookup_as_base64(secretid, - errp); - if (!secret) { - return -1; + if (opts->key_secret) { + key =3D qcrypto_secret_lookup_as_base64(opts->key_secret, errp); + if (!key) { + return -EIO; + } + r =3D rados_conf_set(cluster, "key", key); + g_free(key); + if (r < 0) { + error_setg_errno(errp, -r, "Could not set 'key'"); + return r; } - - rados_conf_set(cluster, "key", secret); - g_free(secret); } =20 if (opts->has_auth_client_required) { @@ -367,9 +368,7 @@ static QemuOptsList runtime_opts =3D { }, }; =20 -/* FIXME Deprecate and remove keypairs or make it available in QMP. - * password_secret should eventually be configurable in opts->location. Su= pport - * for it in .bdrv_open will make it work here as well. */ +/* FIXME Deprecate and remove keypairs or make it available in QMP. */ static int qemu_rbd_do_create(BlockdevCreateOptions *options, const char *keypairs, const char *password_s= ecret, Error **errp) @@ -575,6 +574,16 @@ static int qemu_rbd_connect(rados_t *cluster, rados_io= ctx_t *io_ctx, Error *local_err =3D NULL; int r; =20 + if (secretid) { + if (opts->key_secret) { + error_setg(errp, + "Legacy 'password-secret' clashes with 'key-secret'= "); + return -EINVAL; + } + opts->key_secret =3D g_strdup(secretid); + opts->has_key_secret =3D true; + } + mon_host =3D qemu_rbd_mon_host(opts, &local_err); if (local_err) { error_propagate(errp, local_err); @@ -607,8 +616,8 @@ static int qemu_rbd_connect(rados_t *cluster, rados_ioc= tx_t *io_ctx, } } =20 - if (qemu_rbd_set_auth(*cluster, secretid, opts, errp) < 0) { - r =3D -EIO; + r =3D qemu_rbd_set_auth(*cluster, opts, errp); + if (r < 0) { goto failed_shutdown; } =20 --=20 2.13.6 From nobody Tue May 7 21:08:57 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 1529073768522197.3906046541756; Fri, 15 Jun 2018 07:42:48 -0700 (PDT) Received: from localhost ([::1]:47255 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpw2-0007tw-Le for importer@patchew.org; Fri, 15 Jun 2018 10:42:42 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59334) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpbg-0006H4-A1 for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:42 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTpbe-0003qN-Br for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:40 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:45852 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fTpbZ-0003ke-Cu; Fri, 15 Jun 2018 10:21:33 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E439788840; Fri, 15 Jun 2018 14:21:32 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-70.ams2.redhat.com [10.36.117.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3EE4F63A51; Fri, 15 Jun 2018 14:21:32 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 15 Jun 2018 16:21:05 +0200 Message-Id: <20180615142108.27814-24-kwolf@redhat.com> In-Reply-To: <20180615142108.27814-1-kwolf@redhat.com> References: <20180615142108.27814-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Fri, 15 Jun 2018 14:21:32 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Fri, 15 Jun 2018 14:21:32 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL 23/26] block: Remove deprecated -drive geometry 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: kwolf@redhat.com, qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The -drive options cyls, heads, secs and trans were deprecated in QEMU 2.10. It's time to remove them. hd-geo-test tested both the old version with geometry options in -drive and the new one with -device. Therefore the code using -drive doesn't have to be replaced there, we just need to remove the -drive test cases. This in turn allows some simplification of the code. Signed-off-by: Kevin Wolf Reviewed-by: Markus Armbruster --- include/sysemu/blockdev.h | 1 - blockdev.c | 75 +------------------------------------------= ---- hw/block/block.c | 14 --------- tests/hd-geo-test.c | 37 +++++------------------ hmp-commands.hx | 1 - qemu-doc.texi | 5 ---- qemu-options.hx | 7 +---- 7 files changed, 9 insertions(+), 131 deletions(-) diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h index ac22f2ae1f..37ea39719e 100644 --- a/include/sysemu/blockdev.h +++ b/include/sysemu/blockdev.h @@ -35,7 +35,6 @@ struct DriveInfo { int auto_del; /* see blockdev_mark_auto_del() */ bool is_default; /* Added by default_drive() ? */ int media_cd; - int cyls, heads, secs, trans; QemuOpts *opts; char *serial; QTAILQ_ENTRY(DriveInfo) next; diff --git a/blockdev.c b/blockdev.c index c24e261e37..bc9f34810f 100644 --- a/blockdev.c +++ b/blockdev.c @@ -731,22 +731,6 @@ QemuOptsList qemu_legacy_drive_opts =3D { .type =3D QEMU_OPT_STRING, .help =3D "interface (ide, scsi, sd, mtd, floppy, pflash, virt= io)", },{ - .name =3D "cyls", - .type =3D QEMU_OPT_NUMBER, - .help =3D "number of cylinders (ide disk geometry)", - },{ - .name =3D "heads", - .type =3D QEMU_OPT_NUMBER, - .help =3D "number of heads (ide disk geometry)", - },{ - .name =3D "secs", - .type =3D QEMU_OPT_NUMBER, - .help =3D "number of sectors (ide disk geometry)", - },{ - .name =3D "trans", - .type =3D QEMU_OPT_STRING, - .help =3D "chs translation (auto, lba, none)", - },{ .name =3D "addr", .type =3D QEMU_OPT_STRING, .help =3D "pci address (virtio only)", @@ -792,7 +776,6 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterface= Type block_default_type) QemuOpts *legacy_opts; DriveMediaType media =3D MEDIA_DISK; BlockInterfaceType type; - int cyls, heads, secs, translation; int max_devs, bus_id, unit_id, index; const char *devaddr; const char *werror, *rerror; @@ -803,7 +786,7 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterface= Type block_default_type) Error *local_err =3D NULL; int i; const char *deprecated[] =3D { - "serial", "trans", "secs", "heads", "cyls", "addr" + "serial", "addr" }; =20 /* Change legacy command line options into QMP ones */ @@ -932,57 +915,6 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfac= eType block_default_type) type =3D block_default_type; } =20 - /* Geometry */ - cyls =3D qemu_opt_get_number(legacy_opts, "cyls", 0); - heads =3D qemu_opt_get_number(legacy_opts, "heads", 0); - secs =3D qemu_opt_get_number(legacy_opts, "secs", 0); - - if (cyls || heads || secs) { - if (cyls < 1) { - error_report("invalid physical cyls number"); - goto fail; - } - if (heads < 1) { - error_report("invalid physical heads number"); - goto fail; - } - if (secs < 1) { - error_report("invalid physical secs number"); - goto fail; - } - } - - translation =3D BIOS_ATA_TRANSLATION_AUTO; - value =3D qemu_opt_get(legacy_opts, "trans"); - if (value !=3D NULL) { - if (!cyls) { - error_report("'%s' trans must be used with cyls, heads and sec= s", - value); - goto fail; - } - if (!strcmp(value, "none")) { - translation =3D BIOS_ATA_TRANSLATION_NONE; - } else if (!strcmp(value, "lba")) { - translation =3D BIOS_ATA_TRANSLATION_LBA; - } else if (!strcmp(value, "large")) { - translation =3D BIOS_ATA_TRANSLATION_LARGE; - } else if (!strcmp(value, "rechs")) { - translation =3D BIOS_ATA_TRANSLATION_RECHS; - } else if (!strcmp(value, "auto")) { - translation =3D BIOS_ATA_TRANSLATION_AUTO; - } else { - error_report("'%s' invalid translation type", value); - goto fail; - } - } - - if (media =3D=3D MEDIA_CDROM) { - if (cyls || secs || heads) { - error_report("CHS can't be set with media=3Dcdrom"); - goto fail; - } - } - /* Device address specified by bus/unit or index. * If none was specified, try to find the first free one. */ bus_id =3D qemu_opt_get_number(legacy_opts, "bus", 0); @@ -1105,11 +1037,6 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterf= aceType block_default_type) dinfo =3D g_malloc0(sizeof(*dinfo)); dinfo->opts =3D all_opts; =20 - dinfo->cyls =3D cyls; - dinfo->heads =3D heads; - dinfo->secs =3D secs; - dinfo->trans =3D translation; - dinfo->type =3D type; dinfo->bus =3D bus_id; dinfo->unit =3D unit_id; diff --git a/hw/block/block.c b/hw/block/block.c index b91e2b6d7e..b6c80ab0b7 100644 --- a/hw/block/block.c +++ b/hw/block/block.c @@ -108,20 +108,6 @@ bool blkconf_geometry(BlockConf *conf, int *ptrans, unsigned cyls_max, unsigned heads_max, unsigned secs= _max, Error **errp) { - DriveInfo *dinfo; - - if (!conf->cyls && !conf->heads && !conf->secs) { - /* try to fall back to value set with legacy -drive cyls=3D... */ - dinfo =3D blk_legacy_dinfo(conf->blk); - if (dinfo) { - conf->cyls =3D dinfo->cyls; - conf->heads =3D dinfo->heads; - conf->secs =3D dinfo->secs; - if (ptrans) { - *ptrans =3D dinfo->trans; - } - } - } if (!conf->cyls && !conf->heads && !conf->secs) { hd_geometry_guess(conf->blk, &conf->cyls, &conf->heads, &conf->secs, diff --git a/tests/hd-geo-test.c b/tests/hd-geo-test.c index 24870b38f4..ce665f1f83 100644 --- a/tests/hd-geo-test.c +++ b/tests/hd-geo-test.c @@ -201,7 +201,7 @@ static void setup_mbr(int img_idx, MBRcontents mbr) =20 static int setup_ide(int argc, char *argv[], int argv_sz, int ide_idx, const char *dev, int img_idx, - MBRcontents mbr, const char *opts) + MBRcontents mbr) { char *s1, *s2, *s3; =20 @@ -216,7 +216,7 @@ static int setup_ide(int argc, char *argv[], int argv_s= z, s3 =3D g_strdup(",media=3Dcdrom"); } argc =3D append_arg(argc, argv, argv_sz, - g_strdup_printf("%s%s%s%s", s1, s2, s3, opts)); + g_strdup_printf("%s%s%s", s1, s2, s3)); g_free(s1); g_free(s2); g_free(s3); @@ -260,7 +260,7 @@ static void test_ide_mbr(bool use_device, MBRcontents m= br) for (i =3D 0; i < backend_last; i++) { cur_ide[i] =3D &hd_chst[i][mbr]; dev =3D use_device ? (is_hd(cur_ide[i]) ? "ide-hd" : "ide-cd") : N= ULL; - argc =3D setup_ide(argc, argv, ARGV_SIZE, i, dev, i, mbr, ""); + argc =3D setup_ide(argc, argv, ARGV_SIZE, i, dev, i, mbr); } args =3D g_strjoinv(" ", argv); qtest_start(args); @@ -327,16 +327,12 @@ static void test_ide_drive_user(const char *dev, bool= trans) const CHST expected_chst =3D { secs / (4 * 32) , 4, 32, trans }; =20 argc =3D setup_common(argv, ARGV_SIZE); - opts =3D g_strdup_printf("%s,%s%scyls=3D%d,heads=3D%d,secs=3D%d", - dev ?: "", - trans && dev ? "bios-chs-" : "", - trans ? "trans=3Dlba," : "", + opts =3D g_strdup_printf("%s,%scyls=3D%d,heads=3D%d,secs=3D%d", + dev, trans ? "bios-chs-trans=3Dlba," : "", expected_chst.cyls, expected_chst.heads, expected_chst.secs); cur_ide[0] =3D &expected_chst; - argc =3D setup_ide(argc, argv, ARGV_SIZE, - 0, dev ? opts : NULL, backend_small, mbr_chs, - dev ? "" : opts); + argc =3D setup_ide(argc, argv, ARGV_SIZE, 0, opts, backend_small, mbr_= chs); g_free(opts); args =3D g_strjoinv(" ", argv); qtest_start(args); @@ -347,22 +343,6 @@ static void test_ide_drive_user(const char *dev, bool = trans) } =20 /* - * Test case: IDE device (if=3Dide) with explicit CHS - */ -static void test_ide_drive_user_chs(void) -{ - test_ide_drive_user(NULL, false); -} - -/* - * Test case: IDE device (if=3Dide) with explicit CHS and translation - */ -static void test_ide_drive_user_chst(void) -{ - test_ide_drive_user(NULL, true); -} - -/* * Test case: IDE device (if=3Dnone) with explicit CHS */ static void test_ide_device_user_chs(void) @@ -392,8 +372,7 @@ static void test_ide_drive_cd_0(void) for (i =3D 0; i <=3D backend_empty; i++) { ide_idx =3D backend_empty - i; cur_ide[ide_idx] =3D &hd_chst[i][mbr_blank]; - argc =3D setup_ide(argc, argv, ARGV_SIZE, - ide_idx, NULL, i, mbr_blank, ""); + argc =3D setup_ide(argc, argv, ARGV_SIZE, ide_idx, NULL, i, mbr_bl= ank); } args =3D g_strjoinv(" ", argv); qtest_start(args); @@ -422,8 +401,6 @@ int main(int argc, char **argv) qtest_add_func("hd-geo/ide/drive/mbr/blank", test_ide_drive_mbr_blank); qtest_add_func("hd-geo/ide/drive/mbr/lba", test_ide_drive_mbr_lba); qtest_add_func("hd-geo/ide/drive/mbr/chs", test_ide_drive_mbr_chs); - qtest_add_func("hd-geo/ide/drive/user/chs", test_ide_drive_user_chs); - qtest_add_func("hd-geo/ide/drive/user/chst", test_ide_drive_user_chst); qtest_add_func("hd-geo/ide/drive/cd_0", test_ide_drive_cd_0); qtest_add_func("hd-geo/ide/device/mbr/blank", test_ide_device_mbr_blan= k); qtest_add_func("hd-geo/ide/device/mbr/lba", test_ide_device_mbr_lba); diff --git a/hmp-commands.hx b/hmp-commands.hx index 0734fea931..0de7c4c29e 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1283,7 +1283,6 @@ ETEXI .params =3D "[-n] [[:]:]\n" "[file=3Dfile][,if=3Dtype][,bus=3Dn]\n" "[,unit=3Dm][,media=3Dd][,index=3Di]\n" - "[,cyls=3Dc,heads=3Dh,secs=3Ds[,trans=3Dt]]\n" "[,snapshot=3Don|off][,cache=3Don|off]\n" "[,readonly=3Don|off][,copy-on-read=3Don|off]", .help =3D "add drive to PCI storage controller", diff --git a/qemu-doc.texi b/qemu-doc.texi index cd05760cac..ab95bffc74 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -2850,11 +2850,6 @@ with ``-device ...,netdev=3Dx''), or ``-nic user,smb= =3D/some/dir'' (for embedded NICs). The new syntax allows different settings to be provided per NIC. =20 -@subsection -drive cyls=3D...,heads=3D...,secs=3D...,trans=3D... (since 2.= 10.0) - -The drive geometry arguments are replaced by the the geometry arguments -that can be specified with the ``-device'' parameter. - @subsection -drive serial=3D... (since 2.10.0) =20 The drive serial argument is replaced by the the serial argument diff --git a/qemu-options.hx b/qemu-options.hx index c0d3951e9f..a14b9655c5 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -804,9 +804,8 @@ ETEXI =20 DEF("drive", HAS_ARG, QEMU_OPTION_drive, "-drive [file=3Dfile][,if=3Dtype][,bus=3Dn][,unit=3Dm][,media=3Dd][,in= dex=3Di]\n" - " [,cyls=3Dc,heads=3Dh,secs=3Ds[,trans=3Dt]][,snapshot=3Don|off]= \n" " [,cache=3Dwritethrough|writeback|none|directsync|unsafe][,form= at=3Df]\n" - " [,serial=3Ds][,addr=3DA][,rerror=3Dignore|stop|report]\n" + " [,snapshot=3Don|off][,serial=3Ds][,addr=3DA][,rerror=3Dignore|= stop|report]\n" " [,werror=3Dignore|stop|report|enospc][,id=3Dname][,aio=3Dthrea= ds|native]\n" " [,readonly=3Don|off][,copy-on-read=3Don|off]\n" " [,discard=3Dignore|unmap][,detect-zeroes=3Don|off|unmap]\n" @@ -847,10 +846,6 @@ This option defines where is connected the drive by us= ing an index in the list of available connectors of a given interface type. @item media=3D@var{media} This option defines the type of the media: disk or cdrom. -@item cyls=3D@var{c},heads=3D@var{h},secs=3D@var{s}[,trans=3D@var{t}] -Force disk physical geometry and the optional BIOS translation (trans=3Dno= ne or -lba). These parameters are deprecated, use the corresponding parameters -of @code{-device} instead. @item snapshot=3D@var{snapshot} @var{snapshot} is "on" or "off" and controls snapshot mode for the given d= rive (see @option{-snapshot}). --=20 2.13.6 From nobody Tue May 7 21:08:57 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 1529074183674673.9959334826157; Fri, 15 Jun 2018 07:49:43 -0700 (PDT) Received: from localhost ([::1]:47294 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTq2o-0005A6-Pp for importer@patchew.org; Fri, 15 Jun 2018 10:49:42 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59358) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpbj-0006Kk-Iw for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:47 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTpbd-0003pb-Gs for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:43 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:54422 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fTpba-0003lU-7s; Fri, 15 Jun 2018 10:21:34 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id CF83340122A1; Fri, 15 Jun 2018 14:21:33 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-70.ams2.redhat.com [10.36.117.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2BEEF63A51; Fri, 15 Jun 2018 14:21:33 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 15 Jun 2018 16:21:06 +0200 Message-Id: <20180615142108.27814-25-kwolf@redhat.com> In-Reply-To: <20180615142108.27814-1-kwolf@redhat.com> References: <20180615142108.27814-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Fri, 15 Jun 2018 14:21:33 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Fri, 15 Jun 2018 14:21:33 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL 24/26] block: Remove deprecated -drive option addr 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 Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The -drive option addr was deprecated in QEMU 2.10. It's time to remove it. Signed-off-by: Kevin Wolf Reviewed-by: Markus Armbruster Reviewed-by: Jeff Cody --- include/sysemu/blockdev.h | 1 - blockdev.c | 17 +---------------- device-hotplug.c | 4 ---- qemu-doc.texi | 5 ----- qemu-options.hx | 5 +---- 5 files changed, 2 insertions(+), 30 deletions(-) diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h index 37ea39719e..c0ae3700ec 100644 --- a/include/sysemu/blockdev.h +++ b/include/sysemu/blockdev.h @@ -28,7 +28,6 @@ typedef enum { } BlockInterfaceType; =20 struct DriveInfo { - const char *devaddr; BlockInterfaceType type; int bus; int unit; diff --git a/blockdev.c b/blockdev.c index bc9f34810f..2984e400c2 100644 --- a/blockdev.c +++ b/blockdev.c @@ -731,10 +731,6 @@ QemuOptsList qemu_legacy_drive_opts =3D { .type =3D QEMU_OPT_STRING, .help =3D "interface (ide, scsi, sd, mtd, floppy, pflash, virt= io)", },{ - .name =3D "addr", - .type =3D QEMU_OPT_STRING, - .help =3D "pci address (virtio only)", - },{ .name =3D "serial", .type =3D QEMU_OPT_STRING, .help =3D "disk serial number", @@ -777,7 +773,6 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterface= Type block_default_type) DriveMediaType media =3D MEDIA_DISK; BlockInterfaceType type; int max_devs, bus_id, unit_id, index; - const char *devaddr; const char *werror, *rerror; bool read_only =3D false; bool copy_on_read; @@ -786,7 +781,7 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterface= Type block_default_type) Error *local_err =3D NULL; int i; const char *deprecated[] =3D { - "serial", "addr" + "serial" }; =20 /* Change legacy command line options into QMP ones */ @@ -976,12 +971,6 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfac= eType block_default_type) } =20 /* Add virtio block device */ - devaddr =3D qemu_opt_get(legacy_opts, "addr"); - if (devaddr && type !=3D IF_VIRTIO) { - error_report("addr is not supported by this bus type"); - goto fail; - } - if (type =3D=3D IF_VIRTIO) { QemuOpts *devopts; devopts =3D qemu_opts_create(qemu_find_opts("device"), NULL, 0, @@ -993,9 +982,6 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterface= Type block_default_type) } qemu_opt_set(devopts, "drive", qdict_get_str(bs_opts, "id"), &error_abort); - if (devaddr) { - qemu_opt_set(devopts, "addr", devaddr, &error_abort); - } } =20 filename =3D qemu_opt_get(legacy_opts, "file"); @@ -1040,7 +1026,6 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfa= ceType block_default_type) dinfo->type =3D type; dinfo->bus =3D bus_id; dinfo->unit =3D unit_id; - dinfo->devaddr =3D devaddr; dinfo->serial =3D g_strdup(serial); =20 blk_set_legacy_dinfo(blk, dinfo); diff --git a/device-hotplug.c b/device-hotplug.c index 23fd6656f1..cd427e2c76 100644 --- a/device-hotplug.c +++ b/device-hotplug.c @@ -69,10 +69,6 @@ void hmp_drive_add(Monitor *mon, const QDict *qdict) if (!dinfo) { goto err; } - if (dinfo->devaddr) { - monitor_printf(mon, "Parameter addr not supported\n"); - goto err; - } =20 switch (dinfo->type) { case IF_NONE: diff --git a/qemu-doc.texi b/qemu-doc.texi index ab95bffc74..338477725f 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -2855,11 +2855,6 @@ provided per NIC. The drive serial argument is replaced by the the serial argument that can be specified with the ``-device'' parameter. =20 -@subsection -drive addr=3D... (since 2.10.0) - -The drive addr argument is replaced by the the addr argument -that can be specified with the ``-device'' parameter. - @subsection -usbdevice (since 2.10.0) =20 The ``-usbdevice DEV'' argument is now a synonym for setting diff --git a/qemu-options.hx b/qemu-options.hx index a14b9655c5..c2531e2f3c 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -805,7 +805,7 @@ ETEXI DEF("drive", HAS_ARG, QEMU_OPTION_drive, "-drive [file=3Dfile][,if=3Dtype][,bus=3Dn][,unit=3Dm][,media=3Dd][,in= dex=3Di]\n" " [,cache=3Dwritethrough|writeback|none|directsync|unsafe][,form= at=3Df]\n" - " [,snapshot=3Don|off][,serial=3Ds][,addr=3DA][,rerror=3Dignore|= stop|report]\n" + " [,snapshot=3Don|off][,serial=3Ds][,rerror=3Dignore|stop|report= ]\n" " [,werror=3Dignore|stop|report|enospc][,id=3Dname][,aio=3Dthrea= ds|native]\n" " [,readonly=3Don|off][,copy-on-read=3Don|off]\n" " [,discard=3Dignore|unmap][,detect-zeroes=3Don|off|unmap]\n" @@ -883,9 +883,6 @@ an untrusted format header. This option specifies the serial number to assign to the device. This parameter is deprecated, use the corresponding parameter of @code{-device} instead. -@item addr=3D@var{addr} -Specify the controller's PCI address (if=3Dvirtio only). This parameter is -deprecated, use the corresponding parameter of @code{-device} instead. @item werror=3D@var{action},rerror=3D@var{action} Specify which @var{action} to take on write and read errors. Valid actions= are: "ignore" (ignore the error and try to continue), "stop" (pause QEMU), --=20 2.13.6 From nobody Tue May 7 21:08:57 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 1529074015010146.6678119461086; Fri, 15 Jun 2018 07:46:55 -0700 (PDT) Received: from localhost ([::1]:47282 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTq06-0003AO-4c for importer@patchew.org; Fri, 15 Jun 2018 10:46:54 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59393) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpbn-0006LV-54 for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:51 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTpbg-0003sm-Ba for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:47 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:54424 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fTpbb-0003mZ-5B; Fri, 15 Jun 2018 10:21:35 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id BC82440122A1; Fri, 15 Jun 2018 14:21:34 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-70.ams2.redhat.com [10.36.117.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id 17AC463A51; Fri, 15 Jun 2018 14:21:33 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 15 Jun 2018 16:21:07 +0200 Message-Id: <20180615142108.27814-26-kwolf@redhat.com> In-Reply-To: <20180615142108.27814-1-kwolf@redhat.com> References: <20180615142108.27814-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Fri, 15 Jun 2018 14:21:34 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Fri, 15 Jun 2018 14:21:34 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL 25/26] block: Remove deprecated -drive option serial 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 Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" The -drive option serial was deprecated in QEMU 2.10. It's time to remove it. Tests need to be updated to set the serial number with -global instead of using the -drive option. Signed-off-by: Kevin Wolf Reviewed-by: Markus Armbruster Reviewed-by: Jeff Cody --- include/hw/block/block.h | 1 - include/sysemu/blockdev.h | 1 - block/block-backend.c | 1 - blockdev.c | 10 ---------- hw/block/block.c | 13 ------------- hw/block/nvme.c | 1 - hw/block/virtio-blk.c | 1 - hw/ide/qdev.c | 1 - hw/scsi/scsi-disk.c | 1 - hw/usb/dev-storage.c | 1 - tests/ahci-test.c | 6 +++--- tests/ide-test.c | 8 ++++---- qemu-doc.texi | 5 ----- qemu-options.hx | 6 +----- 14 files changed, 8 insertions(+), 48 deletions(-) diff --git a/include/hw/block/block.h b/include/hw/block/block.h index d4f4dfffab..e9f9e2223f 100644 --- a/include/hw/block/block.h +++ b/include/hw/block/block.h @@ -72,7 +72,6 @@ static inline unsigned int get_physical_block_exp(BlockCo= nf *conf) =20 /* Configuration helpers */ =20 -void blkconf_serial(BlockConf *conf, char **serial); bool blkconf_geometry(BlockConf *conf, int *trans, unsigned cyls_max, unsigned heads_max, unsigned secs= _max, Error **errp); diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h index c0ae3700ec..24954b94e0 100644 --- a/include/sysemu/blockdev.h +++ b/include/sysemu/blockdev.h @@ -35,7 +35,6 @@ struct DriveInfo { bool is_default; /* Added by default_drive() ? */ int media_cd; QemuOpts *opts; - char *serial; QTAILQ_ENTRY(DriveInfo) next; }; =20 diff --git a/block/block-backend.c b/block/block-backend.c index d55c328736..2d1a3463e8 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -419,7 +419,6 @@ static void drive_info_del(DriveInfo *dinfo) return; } qemu_opts_del(dinfo->opts); - g_free(dinfo->serial); g_free(dinfo); } =20 diff --git a/blockdev.c b/blockdev.c index 2984e400c2..d1ab425085 100644 --- a/blockdev.c +++ b/blockdev.c @@ -731,10 +731,6 @@ QemuOptsList qemu_legacy_drive_opts =3D { .type =3D QEMU_OPT_STRING, .help =3D "interface (ide, scsi, sd, mtd, floppy, pflash, virt= io)", },{ - .name =3D "serial", - .type =3D QEMU_OPT_STRING, - .help =3D "disk serial number", - },{ .name =3D "file", .type =3D QEMU_OPT_STRING, .help =3D "file name", @@ -776,12 +772,10 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfa= ceType block_default_type) const char *werror, *rerror; bool read_only =3D false; bool copy_on_read; - const char *serial; const char *filename; Error *local_err =3D NULL; int i; const char *deprecated[] =3D { - "serial" }; =20 /* Change legacy command line options into QMP ones */ @@ -949,9 +943,6 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterface= Type block_default_type) goto fail; } =20 - /* Serial number */ - serial =3D qemu_opt_get(legacy_opts, "serial"); - /* no id supplied -> create one */ if (qemu_opts_id(all_opts) =3D=3D NULL) { char *new_id; @@ -1026,7 +1017,6 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfa= ceType block_default_type) dinfo->type =3D type; dinfo->bus =3D bus_id; dinfo->unit =3D unit_id; - dinfo->serial =3D g_strdup(serial); =20 blk_set_legacy_dinfo(blk, dinfo); =20 diff --git a/hw/block/block.c b/hw/block/block.c index b6c80ab0b7..cf0eb826f1 100644 --- a/hw/block/block.c +++ b/hw/block/block.c @@ -15,19 +15,6 @@ #include "qapi/qapi-types-block.h" #include "qemu/error-report.h" =20 -void blkconf_serial(BlockConf *conf, char **serial) -{ - DriveInfo *dinfo; - - if (!*serial) { - /* try to fall back to value set with legacy -drive serial=3D... */ - dinfo =3D blk_legacy_dinfo(conf->blk); - if (dinfo) { - *serial =3D g_strdup(dinfo->serial); - } - } -} - void blkconf_blocksizes(BlockConf *conf) { BlockBackend *blk =3D conf->blk; diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 811084b6a7..d5bf95b79b 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -1215,7 +1215,6 @@ static void nvme_realize(PCIDevice *pci_dev, Error **= errp) return; } =20 - blkconf_serial(&n->conf, &n->serial); if (!n->serial) { error_setg(errp, "serial property not set"); return; diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index 50b5c869e3..225fe44b7a 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -935,7 +935,6 @@ static void virtio_blk_device_realize(DeviceState *dev,= Error **errp) return; } =20 - blkconf_serial(&conf->conf, &conf->serial); if (!blkconf_apply_backend_options(&conf->conf, blk_is_read_only(conf->conf.blk), t= rue, errp)) { diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index f395d24592..573b022e1e 100644 --- a/hw/ide/qdev.c +++ b/hw/ide/qdev.c @@ -188,7 +188,6 @@ static void ide_dev_initfn(IDEDevice *dev, IDEDriveKind= kind, Error **errp) return; } =20 - blkconf_serial(&dev->conf, &dev->serial); if (kind !=3D IDE_CD) { if (!blkconf_geometry(&dev->conf, &dev->chs_trans, 65535, 16, 255, errp)) { diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index ded23d36ca..aeaf611854 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -2368,7 +2368,6 @@ static void scsi_realize(SCSIDevice *dev, Error **err= p) return; } =20 - blkconf_serial(&s->qdev.conf, &s->serial); blkconf_blocksizes(&s->qdev.conf); =20 if (s->qdev.conf.logical_block_size > diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index 481694a473..47b992f403 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -606,7 +606,6 @@ static void usb_msd_storage_realize(USBDevice *dev, Err= or **errp) return; } =20 - blkconf_serial(&s->conf, &dev->serial); blkconf_blocksizes(&s->conf); if (!blkconf_apply_backend_options(&s->conf, blk_is_read_only(blk), tr= ue, errp)) { diff --git a/tests/ahci-test.c b/tests/ahci-test.c index 1a7b761304..937ed2f910 100644 --- a/tests/ahci-test.c +++ b/tests/ahci-test.c @@ -180,12 +180,12 @@ static AHCIQState *ahci_boot(const char *cli, ...) s =3D ahci_vboot(cli, ap); va_end(ap); } else { - cli =3D "-drive if=3Dnone,id=3Ddrive0,file=3D%s,cache=3Dwriteback,= serial=3D%s" - ",format=3D%s" + cli =3D "-drive if=3Dnone,id=3Ddrive0,file=3D%s,cache=3Dwriteback,= format=3D%s" " -M q35 " "-device ide-hd,drive=3Ddrive0 " + "-global ide-hd.serial=3D%s " "-global ide-hd.ver=3D%s"; - s =3D ahci_boot(cli, tmp_path, "testdisk", imgfmt, "version"); + s =3D ahci_boot(cli, tmp_path, imgfmt, "testdisk", "version"); } =20 return s; diff --git a/tests/ide-test.c b/tests/ide-test.c index 2384c2c3e2..f39431b1a9 100644 --- a/tests/ide-test.c +++ b/tests/ide-test.c @@ -529,8 +529,8 @@ static void test_bmdma_no_busmaster(void) static void test_bmdma_setup(void) { ide_test_start( - "-drive file=3D%s,if=3Dide,serial=3D%s,cache=3Dwriteback,format=3D= raw " - "-global ide-hd.ver=3D%s", + "-drive file=3D%s,if=3Dide,cache=3Dwriteback,format=3Draw " + "-global ide-hd.serial=3D%s -global ide-hd.ver=3D%s", tmp_path, "testdisk", "version"); qtest_irq_intercept_in(global_qtest, "ioapic"); } @@ -561,8 +561,8 @@ static void test_identify(void) int ret; =20 ide_test_start( - "-drive file=3D%s,if=3Dide,serial=3D%s,cache=3Dwriteback,format=3D= raw " - "-global ide-hd.ver=3D%s", + "-drive file=3D%s,if=3Dide,cache=3Dwriteback,format=3Draw " + "-global ide-hd.serial=3D%s -global ide-hd.ver=3D%s", tmp_path, "testdisk", "version"); =20 dev =3D get_pci_device(&bmdma_bar, &ide_bar); diff --git a/qemu-doc.texi b/qemu-doc.texi index 338477725f..282bc3dc35 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -2850,11 +2850,6 @@ with ``-device ...,netdev=3Dx''), or ``-nic user,smb= =3D/some/dir'' (for embedded NICs). The new syntax allows different settings to be provided per NIC. =20 -@subsection -drive serial=3D... (since 2.10.0) - -The drive serial argument is replaced by the the serial argument -that can be specified with the ``-device'' parameter. - @subsection -usbdevice (since 2.10.0) =20 The ``-usbdevice DEV'' argument is now a synonym for setting diff --git a/qemu-options.hx b/qemu-options.hx index c2531e2f3c..d5b0c26e8e 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -805,7 +805,7 @@ ETEXI DEF("drive", HAS_ARG, QEMU_OPTION_drive, "-drive [file=3Dfile][,if=3Dtype][,bus=3Dn][,unit=3Dm][,media=3Dd][,in= dex=3Di]\n" " [,cache=3Dwritethrough|writeback|none|directsync|unsafe][,form= at=3Df]\n" - " [,snapshot=3Don|off][,serial=3Ds][,rerror=3Dignore|stop|report= ]\n" + " [,snapshot=3Don|off][,rerror=3Dignore|stop|report]\n" " [,werror=3Dignore|stop|report|enospc][,id=3Dname][,aio=3Dthrea= ds|native]\n" " [,readonly=3Don|off][,copy-on-read=3Don|off]\n" " [,discard=3Dignore|unmap][,detect-zeroes=3Don|off|unmap]\n" @@ -879,10 +879,6 @@ The default mode is @option{cache=3Dwriteback}. Specify which disk @var{format} will be used rather than detecting the format. Can be used to specify format=3Draw to avoid interpreting an untrusted format header. -@item serial=3D@var{serial} -This option specifies the serial number to assign to the device. This -parameter is deprecated, use the corresponding parameter of @code{-device} -instead. @item werror=3D@var{action},rerror=3D@var{action} Specify which @var{action} to take on write and read errors. Valid actions= are: "ignore" (ignore the error and try to continue), "stop" (pause QEMU), --=20 2.13.6 From nobody Tue May 7 21:08:57 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 152907397593796.8712576711415; Fri, 15 Jun 2018 07:46:15 -0700 (PDT) Received: from localhost ([::1]:47280 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpzT-0002cG-4s for importer@patchew.org; Fri, 15 Jun 2018 10:46:15 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59375) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fTpbk-0006LE-J5 for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:46 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fTpbj-0003xG-O3 for qemu-devel@nongnu.org; Fri, 15 Jun 2018 10:21:44 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:54428 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fTpbc-0003ng-3l; Fri, 15 Jun 2018 10:21:36 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A735840122A1; Fri, 15 Jun 2018 14:21:35 +0000 (UTC) Received: from localhost.localdomain.com (ovpn-117-70.ams2.redhat.com [10.36.117.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id 02D9A63A72; Fri, 15 Jun 2018 14:21:34 +0000 (UTC) From: Kevin Wolf To: qemu-block@nongnu.org Date: Fri, 15 Jun 2018 16:21:08 +0200 Message-Id: <20180615142108.27814-27-kwolf@redhat.com> In-Reply-To: <20180615142108.27814-1-kwolf@redhat.com> References: <20180615142108.27814-1-kwolf@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Fri, 15 Jun 2018 14:21:35 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Fri, 15 Jun 2018 14:21:35 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'kwolf@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL 26/26] block: Remove dead deprecation warning code 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 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" We removed all options from the 'deprecated' array, so the code is dead and can be removed as well. Signed-off-by: Kevin Wolf Reviewed-by: Markus Armbruster --- blockdev.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/blockdev.c b/blockdev.c index d1ab425085..7f65cd7497 100644 --- a/blockdev.c +++ b/blockdev.c @@ -775,8 +775,6 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterface= Type block_default_type) const char *filename; Error *local_err =3D NULL; int i; - const char *deprecated[] =3D { - }; =20 /* Change legacy command line options into QMP ones */ static const struct { @@ -853,16 +851,6 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfac= eType block_default_type) goto fail; } =20 - /* Other deprecated options */ - if (!qtest_enabled()) { - for (i =3D 0; i < ARRAY_SIZE(deprecated); i++) { - if (qemu_opt_get(legacy_opts, deprecated[i]) !=3D NULL) { - error_report("'%s' is deprecated, please use the correspon= ding " - "option of '-device' instead", deprecated[i]); - } - } - } - /* Media type */ value =3D qemu_opt_get(legacy_opts, "media"); if (value) { --=20 2.13.6