From nobody Fri Mar 29 06:12:19 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 1520880719420513.401049593691; Mon, 12 Mar 2018 11:51:59 -0700 (PDT) Received: from localhost ([::1]:33968 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSY4-0008N9-MA for importer@patchew.org; Mon, 12 Mar 2018 14:51:52 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45197) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJT-0000fe-3Q for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:47 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJS-0005wZ-00 for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:47 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:58834 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 1evSJR-0005wB-RU for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:45 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5C7C3401C9AE for ; Mon, 12 Mar 2018 18:36:35 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0F694215CDAE; Mon, 12 Mar 2018 18:36:34 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:35:52 -0500 Message-Id: <20180312183628.394722-2-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Mon, 12 Mar 2018 18:36:35 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Mon, 12 Mar 2018 18:36:35 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@redhat.com' RCPT:'' Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL 01/36] qapi2texi: minor python code simplification 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: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" From: Marc-Andr=C3=A9 Lureau Signed-off-by: Marc-Andr=C3=A9 Lureau Reviewed-by: Markus Armbruster Message-Id: <20180305172951.2150-2-marcandre.lureau@redhat.com> Signed-off-by: Eric Blake --- scripts/qapi/doc.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/scripts/qapi/doc.py b/scripts/qapi/doc.py index 0ea68bf8134..79d11bbe9b5 100644 --- a/scripts/qapi/doc.py +++ b/scripts/qapi/doc.py @@ -134,10 +134,9 @@ def texi_enum_value(value): def texi_member(member, suffix=3D''): """Format a table of members item for an object type member""" typ =3D member.type.doc_type() - return '@item @code{%s%s%s}%s%s\n' % ( - member.name, - ': ' if typ else '', - typ if typ else '', + membertype =3D ': ' + typ if typ else '' + return '@item @code{%s%s}%s%s\n' % ( + member.name, membertype, ' (optional)' if member.optional else '', suffix) --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 1520880829746761.5945743945601; Mon, 12 Mar 2018 11:53:49 -0700 (PDT) Received: from localhost ([::1]:33980 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSZw-0001We-Ur for importer@patchew.org; Mon, 12 Mar 2018 14:53:49 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45110) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJQ-0000cj-8U for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:45 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJN-0005rr-42 for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:44 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:49250 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 1evSJM-0005rM-VP for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:41 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D9A134023BB3 for ; Mon, 12 Mar 2018 18:36:35 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7EEDF215CDAC; Mon, 12 Mar 2018 18:36:35 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:35:53 -0500 Message-Id: <20180312183628.394722-3-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 12 Mar 2018 18:36:35 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 12 Mar 2018 18:36:35 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@redhat.com' RCPT:'' Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL 02/36] qlit: use QType instead of int 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: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Markus Armbruster Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" From: Marc-Andr=C3=A9 Lureau Suggested-by: Markus Armbruster Signed-off-by: Marc-Andr=C3=A9 Lureau Reviewed-by: Eric Blake Reviewed-by: Markus Armbruster Message-Id: <20180305172951.2150-3-marcandre.lureau@redhat.com> Signed-off-by: Eric Blake --- include/qapi/qmp/qlit.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/qapi/qmp/qlit.h b/include/qapi/qmp/qlit.h index 56f9d97bd98..f1ed082df81 100644 --- a/include/qapi/qmp/qlit.h +++ b/include/qapi/qmp/qlit.h @@ -20,7 +20,7 @@ typedef struct QLitDictEntry QLitDictEntry; typedef struct QLitObject QLitObject; struct QLitObject { - int type; + QType type; union { bool qbool; int64_t qnum; --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 1520881328101552.3579374976239; Mon, 12 Mar 2018 12:02:08 -0700 (PDT) Received: from localhost ([::1]:34033 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSht-0000NV-4G for importer@patchew.org; Mon, 12 Mar 2018 15:02:01 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45115) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJQ-0000cm-AD for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:46 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJN-0005rz-4Q for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:44 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:58826 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 1evSJM-0005rI-VL for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:41 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 6C14A4040073 for ; Mon, 12 Mar 2018 18:36:36 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0B032215CDAC; Mon, 12 Mar 2018 18:36:35 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:35:54 -0500 Message-Id: <20180312183628.394722-4-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Mon, 12 Mar 2018 18:36:36 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Mon, 12 Mar 2018 18:36:36 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@redhat.com' RCPT:'' Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL 03/36] qlit: add qobject_from_qlit() 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: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Markus Armbruster Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" From: Marc-Andr=C3=A9 Lureau Instantiate a QObject* from a literal QLitObject. LitObject only supports int64_t for now. uint64_t and double aren't implemented. Signed-off-by: Marc-Andr=C3=A9 Lureau Reviewed-by: Markus Armbruster Message-Id: <20180305172951.2150-4-marcandre.lureau@redhat.com> Signed-off-by: Eric Blake --- include/qapi/qmp/qlit.h | 2 ++ qobject/qlit.c | 37 +++++++++++++++++++++++++++++++++++++ tests/check-qlit.c | 28 ++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) diff --git a/include/qapi/qmp/qlit.h b/include/qapi/qmp/qlit.h index f1ed082df81..c0676d5daf2 100644 --- a/include/qapi/qmp/qlit.h +++ b/include/qapi/qmp/qlit.h @@ -50,4 +50,6 @@ struct QLitDictEntry { bool qlit_equal_qobject(const QLitObject *lhs, const QObject *rhs); +QObject *qobject_from_qlit(const QLitObject *qlit); + #endif /* QLIT_H */ diff --git a/qobject/qlit.c b/qobject/qlit.c index 948e0b860cd..d0e1b72fd01 100644 --- a/qobject/qlit.c +++ b/qobject/qlit.c @@ -21,6 +21,7 @@ #include "qapi/qmp/qnum.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qstring.h" +#include "qapi/qmp/qnull.h" static bool qlit_equal_qdict(const QLitObject *lhs, const QDict *qdict) { @@ -86,3 +87,39 @@ bool qlit_equal_qobject(const QLitObject *lhs, const QOb= ject *rhs) return false; } + +QObject *qobject_from_qlit(const QLitObject *qlit) +{ + switch (qlit->type) { + case QTYPE_QNULL: + return QOBJECT(qnull()); + case QTYPE_QNUM: + return QOBJECT(qnum_from_int(qlit->value.qnum)); + case QTYPE_QSTRING: + return QOBJECT(qstring_from_str(qlit->value.qstr)); + case QTYPE_QDICT: { + QDict *qdict =3D qdict_new(); + QLitDictEntry *e; + + for (e =3D qlit->value.qdict; e->key; e++) { + qdict_put_obj(qdict, e->key, qobject_from_qlit(&e->value)); + } + return QOBJECT(qdict); + } + case QTYPE_QLIST: { + QList *qlist =3D qlist_new(); + QLitObject *e; + + for (e =3D qlit->value.qlist; e->type !=3D QTYPE_NONE; e++) { + qlist_append_obj(qlist, qobject_from_qlit(e)); + } + return QOBJECT(qlist); + } + case QTYPE_QBOOL: + return QOBJECT(qbool_from_bool(qlit->value.qbool)); + default: + assert(0); + } + + return NULL; +} diff --git a/tests/check-qlit.c b/tests/check-qlit.c index 5d0f65b9c77..836f4a3090c 100644 --- a/tests/check-qlit.c +++ b/tests/check-qlit.c @@ -9,9 +9,11 @@ #include "qemu/osdep.h" +#include "qapi/qmp/qbool.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qlist.h" #include "qapi/qmp/qlit.h" +#include "qapi/qmp/qnum.h" #include "qapi/qmp/qstring.h" static QLitObject qlit =3D QLIT_QDICT(((QLitDictEntry[]) { @@ -63,11 +65,37 @@ static void qlit_equal_qobject_test(void) qobject_decref(qobj); } +static void qobject_from_qlit_test(void) +{ + QObject *obj, *qobj =3D qobject_from_qlit(&qlit); + QDict *qdict; + QList *bee; + + qdict =3D qobject_to_qdict(qobj); + g_assert_cmpint(qdict_get_int(qdict, "foo"), =3D=3D, 42); + g_assert_cmpstr(qdict_get_str(qdict, "bar"), =3D=3D, "hello world"); + g_assert(qobject_type(qdict_get(qdict, "baz")) =3D=3D QTYPE_QNULL); + + bee =3D qdict_get_qlist(qdict, "bee"); + obj =3D qlist_pop(bee); + g_assert_cmpint(qnum_get_int(qobject_to_qnum(obj)), =3D=3D, 43); + qobject_decref(obj); + obj =3D qlist_pop(bee); + g_assert_cmpint(qnum_get_int(qobject_to_qnum(obj)), =3D=3D, 44); + qobject_decref(obj); + obj =3D qlist_pop(bee); + g_assert(qbool_get_bool(qobject_to_qbool(obj))); + qobject_decref(obj); + + qobject_decref(qobj); +} + int main(int argc, char **argv) { g_test_init(&argc, &argv, NULL); g_test_add_func("/qlit/equal_qobject", qlit_equal_qobject_test); + g_test_add_func("/qlit/qobject_from_qlit", qobject_from_qlit_test); return g_test_run(); } --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 1520881086835545.391138434595; Mon, 12 Mar 2018 11:58:06 -0700 (PDT) Received: from localhost ([::1]:34007 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSdz-0005Dl-20 for importer@patchew.org; Mon, 12 Mar 2018 14:57:59 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45108) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJQ-0000ci-8O for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:47 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJN-0005s5-4Y for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:44 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:33590 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 1evSJM-0005rL-Uz for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:41 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2DF42814DF58; Mon, 12 Mar 2018 18:36:37 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id 957C5215CDAC; Mon, 12 Mar 2018 18:36:36 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:35:55 -0500 Message-Id: <20180312183628.394722-5-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 12 Mar 2018 18:36:37 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 12 Mar 2018 18:36:37 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@redhat.com' RCPT:'' Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL 04/36] qapi: generate a literal qobject for introspection 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: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Markus Armbruster , "Dr. David Alan Gilbert" , Michael Roth Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" From: Marc-Andr=C3=A9 Lureau Replace the generated json string with a literal qobject. The later is easier to deal with, at run time as well as compile time: adding #if conditionals will be easier than in a json string. The output of query-qmp-schema is not changed. Signed-off-by: Marc-Andr=C3=A9 Lureau Reviewed-by: Markus Armbruster Message-Id: <20180305172951.2150-5-marcandre.lureau@redhat.com> [eblake: fix python 3 failure] Signed-off-by: Eric Blake --- docs/devel/qapi-code-gen.txt | 29 ++++++++++----- scripts/qapi/introspect.py | 76 +++++++++++++++++++++-------------= ---- monitor.c | 2 +- tests/test-qobject-input-visitor.c | 11 ++++-- 4 files changed, 70 insertions(+), 48 deletions(-) diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt index 25b7180a189..99d81230e26 100644 --- a/docs/devel/qapi-code-gen.txt +++ b/docs/devel/qapi-code-gen.txt @@ -1319,18 +1319,27 @@ Example: #ifndef EXAMPLE_QMP_INTROSPECT_H #define EXAMPLE_QMP_INTROSPECT_H - extern const char example_qmp_schema_json[]; + extern const QLitObject qmp_schema_qlit; #endif $ cat qapi-generated/example-qapi-introspect.c [Uninteresting stuff omitted...] - const char example_qmp_schema_json[] =3D "[" - "{\"arg-type\": \"0\", \"meta-type\": \"event\", \"name\": \"MY_EV= ENT\"}, " - "{\"arg-type\": \"1\", \"meta-type\": \"command\", \"name\": \"my-= command\", \"ret-type\": \"2\"}, " - "{\"members\": [], \"meta-type\": \"object\", \"name\": \"0\"}, " - "{\"members\": [{\"name\": \"arg1\", \"type\": \"[2]\"}], \"meta-t= ype\": \"object\", \"name\": \"1\"}, " - "{\"members\": [{\"name\": \"integer\", \"type\": \"int\"}, {\"def= ault\": null, \"name\": \"string\", \"type\": \"str\"}], \"meta-type\": \"o= bject\", \"name\": \"2\"}, " - "{\"element-type\": \"2\", \"meta-type\": \"array\", \"name\": \"[= 2]\"}, " - "{\"json-type\": \"int\", \"meta-type\": \"builtin\", \"name\": \"= int\"}, " - "{\"json-type\": \"string\", \"meta-type\": \"builtin\", \"name\":= \"str\"}]"; + const QLitObject example_qmp_schema_qlit =3D QLIT_QLIST(((QLitObject[]= ) { + QLIT_QDICT(((QLitDictEntry[]) { + { "arg-type", QLIT_QSTR("0") }, + { "meta-type", QLIT_QSTR("event") }, + { "name", QLIT_QSTR("Event") }, + { } + })), + QLIT_QDICT(((QLitDictEntry[]) { + { "members", QLIT_QLIST(((QLitObject[]) { + { } + })) }, + { "meta-type", QLIT_QSTR("object") }, + { "name", QLIT_QSTR("0") }, + { } + })), + ... + { } + })); diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py index f66c397fb0e..1d46a6d6b6f 100644 --- a/scripts/qapi/introspect.py +++ b/scripts/qapi/introspect.py @@ -13,26 +13,36 @@ See the COPYING file in the top-level directory. from qapi.common import * -# Caveman's json.dumps() replacement (we're stuck at Python 2.4) -# TODO try to use json.dumps() once we get unstuck -def to_json(obj, level=3D0): +def to_qlit(obj, level=3D0, suppress_first_indent=3DFalse): + + def indent(level): + return level * 4 * ' ' + + ret =3D '' + if not suppress_first_indent: + ret +=3D indent(level) if obj is None: - ret =3D 'null' + ret +=3D 'QLIT_QNULL' elif isinstance(obj, str): - ret =3D '"' + obj.replace('"', r'\"') + '"' + ret +=3D 'QLIT_QSTR(' + to_c_string(obj) + ')' elif isinstance(obj, list): - elts =3D [to_json(elt, level + 1) + elts =3D [to_qlit(elt, level + 1) for elt in obj] - ret =3D '[' + ', '.join(elts) + ']' + elts.append(indent(level + 1) + "{}") + ret +=3D 'QLIT_QLIST(((QLitObject[]) {\n' + ret +=3D ',\n'.join(elts) + '\n' + ret +=3D indent(level) + '}))' elif isinstance(obj, dict): - elts =3D ['"%s": %s' % (key.replace('"', r'\"'), - to_json(obj[key], level + 1)) - for key in sorted(obj.keys())] - ret =3D '{' + ', '.join(elts) + '}' + elts =3D [] + for key, value in sorted(obj.items()): + elts.append(indent(level + 1) + '{ %s, %s }' % + (to_c_string(key), to_qlit(value, level + 1, True)= )) + elts.append(indent(level + 1) + '{}') + ret +=3D 'QLIT_QDICT(((QLitDictEntry[]) {\n' + ret +=3D ',\n'.join(elts) + '\n' + ret +=3D indent(level) + '}))' else: assert False # not implemented - if level =3D=3D 1: - ret =3D '\n' + ret return ret @@ -48,7 +58,7 @@ class QAPISchemaGenIntrospectVisitor(QAPISchemaMonolithic= CVisitor): ' * QAPI/QMP schema introspection', __doc__) self._unmask =3D unmask self._schema =3D None - self._jsons =3D [] + self._qlits =3D [] self._used_types =3D [] self._name_map =3D {} self._genc.add(mcgen(''' @@ -63,27 +73,27 @@ class QAPISchemaGenIntrospectVisitor(QAPISchemaMonolith= icCVisitor): def visit_end(self): # visit the types that are actually used - jsons =3D self._jsons - self._jsons =3D [] + qlits =3D self._qlits + self._qlits =3D [] for typ in self._used_types: typ.visit(self) # generate C # TODO can generate awfully long lines - jsons.extend(self._jsons) - name =3D c_name(self._prefix, protect=3DFalse) + 'qmp_schema_json' + qlits.extend(self._qlits) + name =3D c_name(self._prefix, protect=3DFalse) + 'qmp_schema_qlit' self._genh.add(mcgen(''' -extern const char %(c_name)s[]; +#include "qapi/qmp/qlit.h" + +extern const QLitObject %(c_name)s; ''', c_name=3Dc_name(name))) - lines =3D to_json(jsons).split('\n') - c_string =3D '\n '.join([to_c_string(line) for line in lines]) self._genc.add(mcgen(''' -const char %(c_name)s[] =3D %(c_string)s; +const QLitObject %(c_name)s =3D %(c_string)s; ''', c_name=3Dc_name(name), - c_string=3Dc_string)) + c_string=3Dto_qlit(qlits))) self._schema =3D None - self._jsons =3D [] + self._qlits =3D [] self._used_types =3D [] self._name_map =3D {} @@ -117,12 +127,12 @@ const char %(c_name)s[] =3D %(c_string)s; return '[' + self._use_type(typ.element_type) + ']' return self._name(typ.name) - def _gen_json(self, name, mtype, obj): + def _gen_qlit(self, name, mtype, obj): if mtype not in ('command', 'event', 'builtin', 'array'): name =3D self._name(name) obj['name'] =3D name obj['meta-type'] =3D mtype - self._jsons.append(obj) + self._qlits.append(obj) def _gen_member(self, member): ret =3D {'name': member.name, 'type': self._use_type(member.type)} @@ -138,24 +148,24 @@ const char %(c_name)s[] =3D %(c_string)s; return {'case': variant.name, 'type': self._use_type(variant.type)} def visit_builtin_type(self, name, info, json_type): - self._gen_json(name, 'builtin', {'json-type': json_type}) + self._gen_qlit(name, 'builtin', {'json-type': json_type}) def visit_enum_type(self, name, info, values, prefix): - self._gen_json(name, 'enum', {'values': values}) + self._gen_qlit(name, 'enum', {'values': values}) def visit_array_type(self, name, info, element_type): element =3D self._use_type(element_type) - self._gen_json('[' + element + ']', 'array', {'element-type': elem= ent}) + self._gen_qlit('[' + element + ']', 'array', {'element-type': elem= ent}) def visit_object_type_flat(self, name, info, members, variants): obj =3D {'members': [self._gen_member(m) for m in members]} if variants: obj.update(self._gen_variants(variants.tag_member.name, variants.variants)) - self._gen_json(name, 'object', obj) + self._gen_qlit(name, 'object', obj) def visit_alternate_type(self, name, info, variants): - self._gen_json(name, 'alternate', + self._gen_qlit(name, 'alternate', {'members': [{'type': self._use_type(m.type)} for m in variants.variants]}) @@ -163,13 +173,13 @@ const char %(c_name)s[] =3D %(c_string)s; gen, success_response, boxed): arg_type =3D arg_type or self._schema.the_empty_object_type ret_type =3D ret_type or self._schema.the_empty_object_type - self._gen_json(name, 'command', + self._gen_qlit(name, 'command', {'arg-type': self._use_type(arg_type), 'ret-type': self._use_type(ret_type)}) def visit_event(self, name, info, arg_type, boxed): arg_type =3D arg_type or self._schema.the_empty_object_type - self._gen_json(name, 'event', {'arg-type': self._use_type(arg_type= )}) + self._gen_qlit(name, 'event', {'arg-type': self._use_type(arg_type= )}) def gen_introspect(schema, output_dir, prefix, opt_unmask): diff --git a/monitor.c b/monitor.c index a4417f26cde..db166fab52f 100644 --- a/monitor.c +++ b/monitor.c @@ -956,7 +956,7 @@ EventInfoList *qmp_query_events(Error **errp) static void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data, Error **errp) { - *ret_data =3D qobject_from_json(qmp_schema_json, &error_abort); + *ret_data =3D qobject_from_qlit(&qmp_schema_qlit); } /* diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-= visitor.c index 79b1a8cb175..55db6bdef13 100644 --- a/tests/test-qobject-input-visitor.c +++ b/tests/test-qobject-input-visitor.c @@ -1250,24 +1250,27 @@ static void test_visitor_in_fail_alternate(TestInpu= tVisitorData *data, } static void do_test_visitor_in_qmp_introspect(TestInputVisitorData *data, - const char *schema_json) + const QLitObject *qlit) { SchemaInfoList *schema =3D NULL; + QObject *obj =3D qobject_from_qlit(qlit); Visitor *v; - v =3D visitor_input_test_init_raw(data, schema_json); + v =3D qobject_input_visitor_new(obj); visit_type_SchemaInfoList(v, NULL, &schema, &error_abort); g_assert(schema); qapi_free_SchemaInfoList(schema); + qobject_decref(obj); + visit_free(v); } static void test_visitor_in_qmp_introspect(TestInputVisitorData *data, const void *unused) { - do_test_visitor_in_qmp_introspect(data, test_qmp_schema_json); - do_test_visitor_in_qmp_introspect(data, qmp_schema_json); + do_test_visitor_in_qmp_introspect(data, &test_qmp_schema_qlit); + do_test_visitor_in_qmp_introspect(data, &qmp_schema_qlit); } int main(int argc, char **argv) --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 1520880996769865.112845992418; Mon, 12 Mar 2018 11:56:36 -0700 (PDT) Received: from localhost ([::1]:33998 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evScc-0003zt-4z for importer@patchew.org; Mon, 12 Mar 2018 14:56:34 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45107) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJQ-0000ch-8O for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:45 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJN-0005rj-3Z for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:44 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:40634 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 1evSJM-0005rJ-V8 for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:41 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9E2CC76FB9 for ; Mon, 12 Mar 2018 18:36:37 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5276E215CDAC; Mon, 12 Mar 2018 18:36:37 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:35:56 -0500 Message-Id: <20180312183628.394722-6-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Mon, 12 Mar 2018 18:36:37 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Mon, 12 Mar 2018 18:36:37 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@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/36] compiler: Add QEMU_BUILD_BUG_MSG() macro 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: Max Reitz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Max Reitz _Static_assert() allows us to specify messages, and that may come in handy. Even without _Static_assert(), encouraging developers to put a helpful message next to the QEMU_BUILD_BUG_* may make debugging easier whenever it breaks. Signed-off-by: Max Reitz Message-Id: <20180224154033.29559-2-mreitz@redhat.com> Reviewed-by: Eric Blake Reviewed-by: Alberto Garcia Signed-off-by: Eric Blake --- include/qemu/compiler.h | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h index 2cbe6a4f16e..9f762695d11 100644 --- a/include/qemu/compiler.h +++ b/include/qemu/compiler.h @@ -82,15 +82,21 @@ int:(x) ? -1 : 1; \ } +/* QEMU_BUILD_BUG_MSG() emits the message given if _Static_assert is + * supported; otherwise, it will be omitted from the compiler error + * message (but as it remains present in the source code, it can still + * be useful when debugging). */ #if defined(CONFIG_STATIC_ASSERT) -#define QEMU_BUILD_BUG_ON(x) _Static_assert(!(x), "not expecting: " #x) +#define QEMU_BUILD_BUG_MSG(x, msg) _Static_assert(!(x), msg) #elif defined(__COUNTER__) -#define QEMU_BUILD_BUG_ON(x) typedef QEMU_BUILD_BUG_ON_STRUCT(x) \ +#define QEMU_BUILD_BUG_MSG(x, msg) typedef QEMU_BUILD_BUG_ON_STRUCT(x) \ glue(qemu_build_bug_on__, __COUNTER__) __attribute__((unused)) #else -#define QEMU_BUILD_BUG_ON(x) +#define QEMU_BUILD_BUG_MSG(x, msg) #endif +#define QEMU_BUILD_BUG_ON(x) QEMU_BUILD_BUG_MSG(x, "not expecting: " #x) + #define QEMU_BUILD_BUG_ON_ZERO(x) (sizeof(QEMU_BUILD_BUG_ON_STRUCT(x)) - \ sizeof(QEMU_BUILD_BUG_ON_STRUCT(x))) --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 1520881152831421.58779681010276; Mon, 12 Mar 2018 11:59:12 -0700 (PDT) Received: from localhost ([::1]:34010 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSf9-0006Jv-V8 for importer@patchew.org; Mon, 12 Mar 2018 14:59:12 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45105) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJQ-0000cc-7M for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:46 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJN-0005rq-3p for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:44 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:49252 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 1evSJM-0005rK-VH for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:41 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 26BD3406E897 for ; Mon, 12 Mar 2018 18:36:38 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id C3D34215CDAC; Mon, 12 Mar 2018 18:36:37 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:35:57 -0500 Message-Id: <20180312183628.394722-7-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 12 Mar 2018 18:36:38 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 12 Mar 2018 18:36:38 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@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/36] qapi: Add qobject_to() 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: Markus Armbruster , Max Reitz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Max Reitz This is a dynamic casting macro that, given a QObject type, returns an object as that type or NULL if the object is of a different type (or NULL itself). The macro uses lower-case letters because: 1. There does not seem to be a hard rule on whether qemu macros have to be upper-cased, 2. The current situation in qapi/qmp is inconsistent (compare e.g. QINCREF() vs. qdict_put()), 3. qobject_to() will evaluate its @obj parameter only once, thus it is generally not important to the caller whether it is a macro or not, 4. I prefer it aesthetically. The macro parameter order is chosen with typename first for consistency with other QAPI macros like QAPI_CLONE(), as well as for legibility (read it as "qobject to" type "applied to" obj). Signed-off-by: Max Reitz Message-Id: <20180224154033.29559-3-mreitz@redhat.com> Reviewed-by: Eric Blake Reviewed-by: Alberto Garcia [eblake: swap parameter order to list type first] Signed-off-by: Eric Blake --- include/qapi/qmp/qobject.h | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/include/qapi/qmp/qobject.h b/include/qapi/qmp/qobject.h index 012439a2e3b..ea9702270e7 100644 --- a/include/qapi/qmp/qobject.h +++ b/include/qapi/qmp/qobject.h @@ -50,6 +50,22 @@ struct QObject { #define QDECREF(obj) \ qobject_decref(obj ? QOBJECT(obj) : NULL) +/* Required for qobject_to() */ +#define QTYPE_CAST_TO_QNull QTYPE_QNULL +#define QTYPE_CAST_TO_QNum QTYPE_QNUM +#define QTYPE_CAST_TO_QString QTYPE_QSTRING +#define QTYPE_CAST_TO_QDict QTYPE_QDICT +#define QTYPE_CAST_TO_QList QTYPE_QLIST +#define QTYPE_CAST_TO_QBool QTYPE_QBOOL + +QEMU_BUILD_BUG_MSG(QTYPE__MAX !=3D 7, + "The QTYPE_CAST_TO_* list needs to be extended"); + +#define qobject_to(type, obj) \ + container_of(qobject_check_type(obj, glue(QTYPE_CAST_TO_, type)) ?: \ + QOBJECT((type *)NULL), \ + type, base) + /* Initialize an object to default values */ static inline void qobject_init(QObject *obj, QType type) { @@ -102,4 +118,18 @@ static inline QType qobject_type(const QObject *obj) return obj->type; } +/** + * qobject_check_type(): Helper function for the qobject_to() macro. + * Return @obj, but only if @obj is not NULL and @type is equal to + * @obj's type. Return NULL otherwise. + */ +static inline QObject *qobject_check_type(const QObject *obj, QType type) +{ + if (obj && qobject_type(obj) =3D=3D type) { + return (QObject *)obj; + } else { + return NULL; + } +} + #endif /* QOBJECT_H */ --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 1520882022556669.4639378470758; Mon, 12 Mar 2018 12:13:42 -0700 (PDT) Received: from localhost ([::1]:34114 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSt6-0001fG-PX for importer@patchew.org; Mon, 12 Mar 2018 15:13:36 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45582) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJj-00011d-Oe for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:37:10 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJd-000656-93 for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:37:03 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:38312 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 1evSJN-0005sE-Ri; Mon, 12 Mar 2018 14:36:42 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 46749D144E; Mon, 12 Mar 2018 18:36:41 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id 837A7215CDAC; Mon, 12 Mar 2018 18:36:38 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:35:58 -0500 Message-Id: <20180312183628.394722-8-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Mon, 12 Mar 2018 18:36:41 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Mon, 12 Mar 2018 18:36:41 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@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/36] qapi: Replace qobject_to_X(o) by qobject_to(X, o) 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: "open list:Sheepdog" , "Michael S. Tsirkin" , Jeff Cody , Markus Armbruster , Michael Roth , Josh Durgin , "open list:Block layer core" , David Hildenbrand , Alexander Graf , Marcel Apfelbaum , Liu Yuan , Eduardo Habkost , "Dr. David Alan Gilbert" , "open list:S390" , Igor Mammedov , Richard Henderson , Kevin Wolf , Hitoshi Mitake , Cornelia Huck , Max Reitz , Paolo Bonzini , =?UTF-8?q?Andreas=20F=C3=A4rber?= 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 This patch was generated using the following Coccinelle script: @@ expression Obj; @@ ( - qobject_to_qnum(Obj) + qobject_to(QNum, Obj) | - qobject_to_qstring(Obj) + qobject_to(QString, Obj) | - qobject_to_qdict(Obj) + qobject_to(QDict, Obj) | - qobject_to_qlist(Obj) + qobject_to(QList, Obj) | - qobject_to_qbool(Obj) + qobject_to(QBool, Obj) ) and a bit of manual fix-up for overly long lines and three places in tests/check-qjson.c that Coccinelle did not find. Signed-off-by: Max Reitz Reviewed-by: Alberto Garcia Message-Id: <20180224154033.29559-4-mreitz@redhat.com> Reviewed-by: Eric Blake [eblake: swap order from qobject_to(o, X), rebase to master] Signed-off-by: Eric Blake --- tests/libqtest.c | 6 ++--- block.c | 4 +-- block/qapi.c | 12 ++++----- block/qcow2.c | 2 +- block/rbd.c | 8 +++--- block/sheepdog.c | 2 +- blockdev.c | 7 ++--- hw/i386/acpi-build.c | 14 +++++----- monitor.c | 8 +++--- qapi/qmp-dispatch.c | 2 +- qapi/qobject-input-visitor.c | 20 +++++++------- qapi/qobject-output-visitor.c | 4 +-- qga/main.c | 2 +- qmp.c | 2 +- qobject/json-parser.c | 2 +- qobject/qbool.c | 4 +-- qobject/qdict.c | 38 +++++++++++++------------- qobject/qjson.c | 10 +++---- qobject/qlist.c | 6 ++--- qobject/qlit.c | 10 +++---- qobject/qnum.c | 6 ++--- qobject/qstring.c | 6 ++--- qom/object.c | 8 +++--- target/i386/cpu.c | 2 +- target/s390x/cpu_models.c | 2 +- tests/check-qdict.c | 20 +++++++------- tests/check-qjson.c | 41 ++++++++++++++-------------- tests/check-qlist.c | 4 +-- tests/check-qlit.c | 10 +++---- tests/check-qnum.c | 4 +-- tests/check-qobject.c | 2 +- tests/check-qstring.c | 2 +- tests/device-introspect-test.c | 14 +++++----- tests/numa-test.c | 8 +++--- tests/qom-test.c | 4 +-- tests/test-char.c | 2 +- tests/test-keyval.c | 8 +++--- tests/test-qga.c | 19 ++++++------- tests/test-qmp-cmds.c | 12 ++++----- tests/test-qmp-event.c | 16 +++++------ tests/test-qobject-input-visitor.c | 10 +++---- tests/test-qobject-output-visitor.c | 54 ++++++++++++++++++---------------= ---- tests/test-x86-cpuid-compat.c | 17 ++++++------ util/keyval.c | 4 +-- util/qemu-config.c | 2 +- util/qemu-option.c | 6 ++--- 46 files changed, 225 insertions(+), 221 deletions(-) diff --git a/tests/libqtest.c b/tests/libqtest.c index 13c910069b5..200b2b9e92a 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -430,7 +430,7 @@ static void qmp_response(JSONMessageParser *parser, GQu= eue *tokens) } g_assert(!qmp->response); - qmp->response =3D qobject_to_qdict(obj); + qmp->response =3D qobject_to(QDict, obj); g_assert(qmp->response); } @@ -1008,11 +1008,11 @@ void qtest_cb_for_every_machine(void (*cb)(const ch= ar *machine)) g_assert(list); for (p =3D qlist_first(list); p; p =3D qlist_next(p)) { - minfo =3D qobject_to_qdict(qlist_entry_obj(p)); + minfo =3D qobject_to(QDict, qlist_entry_obj(p)); g_assert(minfo); qobj =3D qdict_get(minfo, "name"); g_assert(qobj); - qstr =3D qobject_to_qstring(qobj); + qstr =3D qobject_to(QString, qobj); g_assert(qstr); mname =3D qstring_get_str(qstr); cb(mname); diff --git a/block.c b/block.c index 75a9fd49de1..cd74da3a601 100644 --- a/block.c +++ b/block.c @@ -1457,7 +1457,7 @@ static QDict *parse_json_filename(const char *filenam= e, Error **errp) return NULL; } - options =3D qobject_to_qdict(options_obj); + options =3D qobject_to(QDict, options_obj); if (!options) { qobject_decref(options_obj); error_setg(errp, "Invalid JSON object given"); @@ -2433,7 +2433,7 @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef = *ref, Error **errp) } visit_complete(v, &obj); - qdict =3D qobject_to_qdict(obj); + qdict =3D qobject_to(QDict, obj); qdict_flatten(qdict); /* bdrv_open_inherit() defaults to the values in bdrv_flags (for diff --git a/block/qapi.c b/block/qapi.c index 4c9923d262b..f2e0aa2cbe7 100644 --- a/block/qapi.c +++ b/block/qapi.c @@ -647,29 +647,29 @@ static void dump_qobject(fprintf_function func_fprint= f, void *f, { switch (qobject_type(obj)) { case QTYPE_QNUM: { - QNum *value =3D qobject_to_qnum(obj); + QNum *value =3D qobject_to(QNum, obj); char *tmp =3D qnum_to_string(value); func_fprintf(f, "%s", tmp); g_free(tmp); break; } case QTYPE_QSTRING: { - QString *value =3D qobject_to_qstring(obj); + QString *value =3D qobject_to(QString, obj); func_fprintf(f, "%s", qstring_get_str(value)); break; } case QTYPE_QDICT: { - QDict *value =3D qobject_to_qdict(obj); + QDict *value =3D qobject_to(QDict, obj); dump_qdict(func_fprintf, f, comp_indent, value); break; } case QTYPE_QLIST: { - QList *value =3D qobject_to_qlist(obj); + QList *value =3D qobject_to(QList, obj); dump_qlist(func_fprintf, f, comp_indent, value); break; } case QTYPE_QBOOL: { - QBool *value =3D qobject_to_qbool(obj); + QBool *value =3D qobject_to(QBool, obj); func_fprintf(f, "%s", qbool_get_bool(value) ? "true" : "false"= ); break; } @@ -730,7 +730,7 @@ void bdrv_image_info_specific_dump(fprintf_function fun= c_fprintf, void *f, visit_type_ImageInfoSpecific(v, NULL, &info_spec, &error_abort); visit_complete(v, &obj); - data =3D qdict_get(qobject_to_qdict(obj), "data"); + data =3D qdict_get(qobject_to(QDict, obj), "data"); dump_qobject(func_fprintf, f, 1, data); qobject_decref(obj); visit_free(v); diff --git a/block/qcow2.c b/block/qcow2.c index 7472af69312..cf4f3becae6 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -3125,7 +3125,7 @@ static int coroutine_fn qcow2_co_create_opts(const ch= ar *filename, QemuOpts *opt /* Now get the QAPI type BlockdevCreateOptions */ qobj =3D qdict_crumple(qdict, errp); QDECREF(qdict); - qdict =3D qobject_to_qdict(qobj); + qdict =3D qobject_to(QDict, qobj); if (qdict =3D=3D NULL) { ret =3D -EINVAL; goto finish; diff --git a/block/rbd.c b/block/rbd.c index 294ed07ac41..5b64849dc67 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -263,14 +263,14 @@ static int qemu_rbd_set_keypairs(rados_t cluster, con= st char *keypairs_json, if (!keypairs_json) { return ret; } - keypairs =3D qobject_to_qlist(qobject_from_json(keypairs_json, - &error_abort)); + keypairs =3D qobject_to(QList, + qobject_from_json(keypairs_json, &error_abort)); remaining =3D qlist_size(keypairs) / 2; assert(remaining); while (remaining--) { - name =3D qobject_to_qstring(qlist_pop(keypairs)); - value =3D qobject_to_qstring(qlist_pop(keypairs)); + name =3D qobject_to(QString, qlist_pop(keypairs)); + value =3D qobject_to(QString, qlist_pop(keypairs)); assert(name && value); key =3D qstring_get_str(name); diff --git a/block/sheepdog.c b/block/sheepdog.c index 8680b2926f0..abda8857768 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -1887,7 +1887,7 @@ static int sd_create_prealloc(BlockdevOptionsSheepdog= *location, int64_t size, return -EINVAL; } - qdict =3D qobject_to_qdict(obj); + qdict =3D qobject_to(QDict, obj); qdict_flatten(qdict); qdict_put_str(qdict, "driver", "sheepdog"); diff --git a/blockdev.c b/blockdev.c index 1fbfd3a2c40..c9a212b3149 100644 --- a/blockdev.c +++ b/blockdev.c @@ -334,7 +334,8 @@ static bool parse_stats_intervals(BlockAcctStats *stats= , QList *intervals, case QTYPE_QSTRING: { unsigned long long length; - const char *str =3D qstring_get_str(qobject_to_qstring(entry->= value)); + const char *str =3D qstring_get_str(qobject_to(QString, + entry->value)); if (parse_uint_full(str, &length, 10) =3D=3D 0 && length > 0 && length <=3D UINT_MAX) { block_acct_add_interval(stats, (unsigned) length); @@ -346,7 +347,7 @@ static bool parse_stats_intervals(BlockAcctStats *stats= , QList *intervals, } case QTYPE_QNUM: { - int64_t length =3D qnum_get_int(qobject_to_qnum(entry->value)); + int64_t length =3D qnum_get_int(qobject_to(QNum, entry->value)= ); if (length > 0 && length <=3D UINT_MAX) { block_acct_add_interval(stats, (unsigned) length); @@ -3982,7 +3983,7 @@ void qmp_blockdev_add(BlockdevOptions *options, Error= **errp) } visit_complete(v, &obj); - qdict =3D qobject_to_qdict(obj); + qdict =3D qobject_to(QDict, obj); qdict_flatten(qdict); diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index deb440f2863..2d62499bf12 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -154,21 +154,21 @@ static void acpi_get_pm_info(AcpiPmInfo *pm) /* Fill in optional s3/s4 related properties */ o =3D object_property_get_qobject(obj, ACPI_PM_PROP_S3_DISABLED, NULL); if (o) { - pm->s3_disabled =3D qnum_get_uint(qobject_to_qnum(o)); + pm->s3_disabled =3D qnum_get_uint(qobject_to(QNum, o)); } else { pm->s3_disabled =3D false; } qobject_decref(o); o =3D object_property_get_qobject(obj, ACPI_PM_PROP_S4_DISABLED, NULL); if (o) { - pm->s4_disabled =3D qnum_get_uint(qobject_to_qnum(o)); + pm->s4_disabled =3D qnum_get_uint(qobject_to(QNum, o)); } else { pm->s4_disabled =3D false; } qobject_decref(o); o =3D object_property_get_qobject(obj, ACPI_PM_PROP_S4_VAL, NULL); if (o) { - pm->s4_val =3D qnum_get_uint(qobject_to_qnum(o)); + pm->s4_val =3D qnum_get_uint(qobject_to(QNum, o)); } else { pm->s4_val =3D false; } @@ -514,7 +514,7 @@ static void build_append_pci_bus_devices(Aml *parent_sc= ope, PCIBus *bus, bsel =3D object_property_get_qobject(OBJECT(bus), ACPI_PCIHP_PROP_BSEL= , NULL); if (bsel) { - uint64_t bsel_val =3D qnum_get_uint(qobject_to_qnum(bsel)); + uint64_t bsel_val =3D qnum_get_uint(qobject_to(QNum, bsel)); aml_append(parent_scope, aml_name_decl("BSEL", aml_int(bsel_val))); notify_method =3D aml_method("DVNT", 2, AML_NOTSERIALIZED); @@ -624,7 +624,7 @@ static void build_append_pci_bus_devices(Aml *parent_sc= ope, PCIBus *bus, /* If bus supports hotplug select it and notify about local events */ if (bsel) { - uint64_t bsel_val =3D qnum_get_uint(qobject_to_qnum(bsel)); + uint64_t bsel_val =3D qnum_get_uint(qobject_to(QNum, bsel)); aml_append(method, aml_store(aml_int(bsel_val), aml_name("BNUM"))); aml_append(method, @@ -2638,12 +2638,12 @@ static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg) if (!o) { return false; } - mcfg->mcfg_base =3D qnum_get_uint(qobject_to_qnum(o)); + mcfg->mcfg_base =3D qnum_get_uint(qobject_to(QNum, o)); qobject_decref(o); o =3D object_property_get_qobject(pci_host, PCIE_HOST_MCFG_SIZE, NULL); assert(o); - mcfg->mcfg_size =3D qnum_get_uint(qobject_to_qnum(o)); + mcfg->mcfg_size =3D qnum_get_uint(qobject_to(QNum, o)); qobject_decref(o); return true; } diff --git a/monitor.c b/monitor.c index db166fab52f..c18a2f2dc98 100644 --- a/monitor.c +++ b/monitor.c @@ -447,7 +447,7 @@ monitor_qapi_event_queue(QAPIEvent event, QDict *qdict,= Error **errp) /* Unthrottled event */ monitor_qapi_event_emit(event, qdict); } else { - QDict *data =3D qobject_to_qdict(qdict_get(qdict, "data")); + QDict *data =3D qobject_to(QDict, qdict_get(qdict, "data")); MonitorQAPIEventState key =3D { .event =3D event, .data =3D data }; evstate =3D g_hash_table_lookup(monitor_qapi_event_state, &key); @@ -3774,7 +3774,7 @@ static void handle_qmp_command(JSONMessageParser *par= ser, GQueue *tokens) goto err_out; } - qdict =3D qobject_to_qdict(req); + qdict =3D qobject_to(QDict, req); if (qdict) { id =3D qdict_get(qdict, "id"); qobject_incref(id); @@ -3790,7 +3790,7 @@ static void handle_qmp_command(JSONMessageParser *par= ser, GQueue *tokens) rsp =3D qmp_dispatch(cur_mon->qmp.commands, req); if (mon->qmp.commands =3D=3D &qmp_cap_negotiation_commands) { - qdict =3D qdict_get_qdict(qobject_to_qdict(rsp), "error"); + qdict =3D qdict_get_qdict(qobject_to(QDict, rsp), "error"); if (qdict && !g_strcmp0(qdict_get_try_str(qdict, "class"), QapiErrorClass_str(ERROR_CLASS_COMMAND_NOT_FOUND))) { @@ -3811,7 +3811,7 @@ err_out: if (rsp) { if (id) { - qdict_put_obj(qobject_to_qdict(rsp), "id", id); + qdict_put_obj(qobject_to(QDict, rsp), "id", id); id =3D NULL; } diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index e31ac4be1fb..af537f3d7d2 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -26,7 +26,7 @@ static QDict *qmp_dispatch_check_obj(const QObject *reque= st, Error **errp) bool has_exec_key =3D false; QDict *dict =3D NULL; - dict =3D qobject_to_qdict(request); + dict =3D qobject_to(QDict, request); if (!dict) { error_setg(errp, "QMP input must be a JSON object"); return NULL; diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c index 023317b05fc..0b5293385e5 100644 --- a/qapi/qobject-input-visitor.c +++ b/qapi/qobject-input-visitor.c @@ -137,7 +137,7 @@ static QObject *qobject_input_try_get_object(QObjectInp= utVisitor *qiv, if (qobject_type(qobj) =3D=3D QTYPE_QDICT) { assert(name); - ret =3D qdict_get(qobject_to_qdict(qobj), name); + ret =3D qdict_get(qobject_to(QDict, qobj), name); if (tos->h && consume && ret) { bool removed =3D g_hash_table_remove(tos->h, name); assert(removed); @@ -185,7 +185,7 @@ static const char *qobject_input_get_keyval(QObjectInpu= tVisitor *qiv, return NULL; } - qstr =3D qobject_to_qstring(qobj); + qstr =3D qobject_to(QString, qobj); if (!qstr) { switch (qobject_type(qobj)) { case QTYPE_QDICT: @@ -224,11 +224,11 @@ static const QListEntry *qobject_input_push(QObjectIn= putVisitor *qiv, if (qobject_type(obj) =3D=3D QTYPE_QDICT) { h =3D g_hash_table_new(g_str_hash, g_str_equal); - qdict_iter(qobject_to_qdict(obj), qdict_add_key, h); + qdict_iter(qobject_to(QDict, obj), qdict_add_key, h); tos->h =3D h; } else { assert(qobject_type(obj) =3D=3D QTYPE_QLIST); - tos->entry =3D qlist_first(qobject_to_qlist(obj)); + tos->entry =3D qlist_first(qobject_to(QList, obj)); tos->index =3D -1; } @@ -395,7 +395,7 @@ static void qobject_input_type_int64(Visitor *v, const = char *name, int64_t *obj, if (!qobj) { return; } - qnum =3D qobject_to_qnum(qobj); + qnum =3D qobject_to(QNum, qobj); if (!qnum || !qnum_get_try_int(qnum, obj)) { error_setg(errp, QERR_INVALID_PARAMETER_TYPE, full_name(qiv, name), "integer"); @@ -430,7 +430,7 @@ static void qobject_input_type_uint64(Visitor *v, const= char *name, if (!qobj) { return; } - qnum =3D qobject_to_qnum(qobj); + qnum =3D qobject_to(QNum, qobj); if (!qnum) { goto err; } @@ -477,7 +477,7 @@ static void qobject_input_type_bool(Visitor *v, const c= har *name, bool *obj, if (!qobj) { return; } - qbool =3D qobject_to_qbool(qobj); + qbool =3D qobject_to(QBool, qobj); if (!qbool) { error_setg(errp, QERR_INVALID_PARAMETER_TYPE, full_name(qiv, name), "boolean"); @@ -518,7 +518,7 @@ static void qobject_input_type_str(Visitor *v, const ch= ar *name, char **obj, if (!qobj) { return; } - qstr =3D qobject_to_qstring(qobj); + qstr =3D qobject_to(QString, qobj); if (!qstr) { error_setg(errp, QERR_INVALID_PARAMETER_TYPE, full_name(qiv, name), "string"); @@ -547,7 +547,7 @@ static void qobject_input_type_number(Visitor *v, const= char *name, double *obj, if (!qobj) { return; } - qnum =3D qobject_to_qnum(qobj); + qnum =3D qobject_to(QNum, qobj); if (!qnum) { error_setg(errp, QERR_INVALID_PARAMETER_TYPE, full_name(qiv, name), "number"); @@ -734,7 +734,7 @@ Visitor *qobject_input_visitor_new_str(const char *str, } return NULL; } - args =3D qobject_to_qdict(obj); + args =3D qobject_to(QDict, obj); assert(args); v =3D qobject_input_visitor_new(QOBJECT(args)); } else { diff --git a/qapi/qobject-output-visitor.c b/qapi/qobject-output-visitor.c index 7c3b42cfe2b..877e37eeb88 100644 --- a/qapi/qobject-output-visitor.c +++ b/qapi/qobject-output-visitor.c @@ -92,11 +92,11 @@ static void qobject_output_add_obj(QObjectOutputVisitor= *qov, const char *name, switch (qobject_type(cur)) { case QTYPE_QDICT: assert(name); - qdict_put_obj(qobject_to_qdict(cur), name, value); + qdict_put_obj(qobject_to(QDict, cur), name, value); break; case QTYPE_QLIST: assert(!name); - qlist_append_obj(qobject_to_qlist(cur), value); + qlist_append_obj(qobject_to(QList, cur), value); break; default: g_assert_not_reached(); diff --git a/qga/main.c b/qga/main.c index f9c83050c5d..7cc1748c04f 100644 --- a/qga/main.c +++ b/qga/main.c @@ -607,7 +607,7 @@ static void process_event(JSONMessageParser *parser, GQ= ueue *tokens) g_assert(s && parser); g_debug("process_event: called"); - qdict =3D qobject_to_qdict(json_parser_parse_err(tokens, NULL, &err)); + qdict =3D qobject_to(QDict, json_parser_parse_err(tokens, NULL, &err)); if (err || !qdict) { QDECREF(qdict); qdict =3D qdict_new(); diff --git a/qmp.c b/qmp.c index 8c7d1cc4790..7e606d84867 100644 --- a/qmp.c +++ b/qmp.c @@ -705,7 +705,7 @@ void qmp_object_add(const char *type, const char *id, Object *obj; if (props) { - pdict =3D qobject_to_qdict(props); + pdict =3D qobject_to(QDict, props); if (!pdict) { error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "props", "dict"); return; diff --git a/qobject/json-parser.c b/qobject/json-parser.c index b7245624158..055c7f0272a 100644 --- a/qobject/json-parser.c +++ b/qobject/json-parser.c @@ -308,7 +308,7 @@ static int parse_pair(JSONParserContext *ctxt, QDict *d= ict, va_list *ap) goto out; } - qdict_put_obj(dict, qstring_get_str(qobject_to_qstring(key)), value); + qdict_put_obj(dict, qstring_get_str(qobject_to(QString, key)), value); qobject_decref(key); diff --git a/qobject/qbool.c b/qobject/qbool.c index e5a7a538793..5be6277cca8 100644 --- a/qobject/qbool.c +++ b/qobject/qbool.c @@ -55,7 +55,7 @@ QBool *qobject_to_qbool(const QObject *obj) */ bool qbool_is_equal(const QObject *x, const QObject *y) { - return qobject_to_qbool(x)->value =3D=3D qobject_to_qbool(y)->value; + return qobject_to(QBool, x)->value =3D=3D qobject_to(QBool, y)->value; } /** @@ -65,5 +65,5 @@ bool qbool_is_equal(const QObject *x, const QObject *y) void qbool_destroy_obj(QObject *obj) { assert(obj !=3D NULL); - g_free(qobject_to_qbool(obj)); + g_free(qobject_to(QBool, obj)); } diff --git a/qobject/qdict.c b/qobject/qdict.c index 229b8c840b1..1e588123d00 100644 --- a/qobject/qdict.c +++ b/qobject/qdict.c @@ -206,7 +206,7 @@ size_t qdict_size(const QDict *qdict) */ double qdict_get_double(const QDict *qdict, const char *key) { - return qnum_get_double(qobject_to_qnum(qdict_get(qdict, key))); + return qnum_get_double(qobject_to(QNum, qdict_get(qdict, key))); } /** @@ -219,7 +219,7 @@ double qdict_get_double(const QDict *qdict, const char = *key) */ int64_t qdict_get_int(const QDict *qdict, const char *key) { - return qnum_get_int(qobject_to_qnum(qdict_get(qdict, key))); + return qnum_get_int(qobject_to(QNum, qdict_get(qdict, key))); } /** @@ -232,7 +232,7 @@ int64_t qdict_get_int(const QDict *qdict, const char *k= ey) */ bool qdict_get_bool(const QDict *qdict, const char *key) { - return qbool_get_bool(qobject_to_qbool(qdict_get(qdict, key))); + return qbool_get_bool(qobject_to(QBool, qdict_get(qdict, key))); } /** @@ -240,7 +240,7 @@ bool qdict_get_bool(const QDict *qdict, const char *key) */ QList *qdict_get_qlist(const QDict *qdict, const char *key) { - return qobject_to_qlist(qdict_get(qdict, key)); + return qobject_to(QList, qdict_get(qdict, key)); } /** @@ -248,7 +248,7 @@ QList *qdict_get_qlist(const QDict *qdict, const char *= key) */ QDict *qdict_get_qdict(const QDict *qdict, const char *key) { - return qobject_to_qdict(qdict_get(qdict, key)); + return qobject_to(QDict, qdict_get(qdict, key)); } /** @@ -262,7 +262,7 @@ QDict *qdict_get_qdict(const QDict *qdict, const char *= key) */ const char *qdict_get_str(const QDict *qdict, const char *key) { - return qstring_get_str(qobject_to_qstring(qdict_get(qdict, key))); + return qstring_get_str(qobject_to(QString, qdict_get(qdict, key))); } /** @@ -275,7 +275,7 @@ const char *qdict_get_str(const QDict *qdict, const cha= r *key) int64_t qdict_get_try_int(const QDict *qdict, const char *key, int64_t def_value) { - QNum *qnum =3D qobject_to_qnum(qdict_get(qdict, key)); + QNum *qnum =3D qobject_to(QNum, qdict_get(qdict, key)); int64_t val; if (!qnum || !qnum_get_try_int(qnum, &val)) { @@ -294,7 +294,7 @@ int64_t qdict_get_try_int(const QDict *qdict, const cha= r *key, */ bool qdict_get_try_bool(const QDict *qdict, const char *key, bool def_valu= e) { - QBool *qbool =3D qobject_to_qbool(qdict_get(qdict, key)); + QBool *qbool =3D qobject_to(QBool, qdict_get(qdict, key)); return qbool ? qbool_get_bool(qbool) : def_value; } @@ -309,7 +309,7 @@ bool qdict_get_try_bool(const QDict *qdict, const char = *key, bool def_value) */ const char *qdict_get_try_str(const QDict *qdict, const char *key) { - QString *qstr =3D qobject_to_qstring(qdict_get(qdict, key)); + QString *qstr =3D qobject_to(QString, qdict_get(qdict, key)); return qstr ? qstring_get_str(qstr) : NULL; } @@ -432,8 +432,8 @@ void qdict_del(QDict *qdict, const char *key) */ bool qdict_is_equal(const QObject *x, const QObject *y) { - const QDict *dict_x =3D qobject_to_qdict(x); - const QDict *dict_y =3D qobject_to_qdict(y); + const QDict *dict_x =3D qobject_to(QDict, x); + const QDict *dict_y =3D qobject_to(QDict, y); const QDictEntry *e; if (qdict_size(dict_x) !=3D qdict_size(dict_y)) { @@ -461,7 +461,7 @@ void qdict_destroy_obj(QObject *obj) QDict *qdict; assert(obj !=3D NULL); - qdict =3D qobject_to_qdict(obj); + qdict =3D qobject_to(QDict, obj); for (i =3D 0; i < QDICT_BUCKET_MAX; i++) { QDictEntry *entry =3D QLIST_FIRST(&qdict->table[i]); @@ -532,9 +532,9 @@ static void qdict_flatten_qlist(QList *qlist, QDict *ta= rget, const char *prefix) 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); + 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); + qdict_flatten_qlist(qobject_to(QList, value), target, new_key); } else { /* All other types are moved to the target unchanged. */ qobject_incref(value); @@ -568,11 +568,11 @@ static void qdict_flatten_qdict(QDict *qdict, QDict *= target, const char *prefix) 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, + 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, + qdict_flatten_qlist(qobject_to(QList, value), target, new_key ? new_key : entry->key); delete =3D true; } else if (prefix) { @@ -904,7 +904,7 @@ QObject *qdict_crumple(const QDict *src, Error **errp) qdict_put_obj(two_level, prefix, child); } qobject_incref(ent->value); - qdict_put_obj(qobject_to_qdict(child), suffix, ent->value); + qdict_put_obj(qobject_to(QDict, child), suffix, ent->value); } else { if (child) { error_setg(errp, "Key %s prefix is already set as a dict", @@ -926,7 +926,7 @@ QObject *qdict_crumple(const QDict *src, Error **errp) ent =3D qdict_next(two_level, ent)) { if (qobject_type(ent->value) =3D=3D QTYPE_QDICT) { - child =3D qdict_crumple(qobject_to_qdict(ent->value), errp); + child =3D qdict_crumple(qobject_to(QDict, ent->value), errp); if (!child) { goto error; } @@ -961,7 +961,7 @@ QObject *qdict_crumple(const QDict *src, Error **errp) } qobject_incref(child); - qlist_append_obj(qobject_to_qlist(dst), child); + qlist_append_obj(qobject_to(QList, dst), child); } QDECREF(multi_level); multi_level =3D NULL; diff --git a/qobject/qjson.c b/qobject/qjson.c index e1ce75651cc..655d38adf1b 100644 --- a/qobject/qjson.c +++ b/qobject/qjson.c @@ -137,14 +137,14 @@ static void to_json(const QObject *obj, QString *str,= int pretty, int indent) qstring_append(str, "null"); break; case QTYPE_QNUM: { - QNum *val =3D qobject_to_qnum(obj); + QNum *val =3D qobject_to(QNum, obj); char *buffer =3D qnum_to_string(val); qstring_append(str, buffer); g_free(buffer); break; } case QTYPE_QSTRING: { - QString *val =3D qobject_to_qstring(obj); + QString *val =3D qobject_to(QString, obj); const char *ptr; int cp; char buf[16]; @@ -201,7 +201,7 @@ static void to_json(const QObject *obj, QString *str, i= nt pretty, int indent) } case QTYPE_QDICT: { ToJsonIterState s; - QDict *val =3D qobject_to_qdict(obj); + QDict *val =3D qobject_to(QDict, obj); s.count =3D 0; s.str =3D str; @@ -220,7 +220,7 @@ static void to_json(const QObject *obj, QString *str, i= nt pretty, int indent) } case QTYPE_QLIST: { ToJsonIterState s; - QList *val =3D qobject_to_qlist(obj); + QList *val =3D qobject_to(QList, obj); s.count =3D 0; s.str =3D str; @@ -238,7 +238,7 @@ static void to_json(const QObject *obj, QString *str, i= nt pretty, int indent) break; } case QTYPE_QBOOL: { - QBool *val =3D qobject_to_qbool(obj); + QBool *val =3D qobject_to(QBool, obj); if (qbool_get_bool(val)) { qstring_append(str, "true"); diff --git a/qobject/qlist.c b/qobject/qlist.c index 613a95c12b9..77f19ffda78 100644 --- a/qobject/qlist.c +++ b/qobject/qlist.c @@ -173,8 +173,8 @@ QList *qobject_to_qlist(const QObject *obj) */ bool qlist_is_equal(const QObject *x, const QObject *y) { - const QList *list_x =3D qobject_to_qlist(x); - const QList *list_y =3D qobject_to_qlist(y); + const QList *list_x =3D qobject_to(QList, x); + const QList *list_y =3D qobject_to(QList, y); const QListEntry *entry_x, *entry_y; entry_x =3D qlist_first(list_x); @@ -203,7 +203,7 @@ void qlist_destroy_obj(QObject *obj) QListEntry *entry, *next_entry; assert(obj !=3D NULL); - qlist =3D qobject_to_qlist(obj); + qlist =3D qobject_to(QList, obj); QTAILQ_FOREACH_SAFE(entry, &qlist->head, next, next_entry) { QTAILQ_REMOVE(&qlist->head, entry, next); diff --git a/qobject/qlit.c b/qobject/qlit.c index d0e1b72fd01..be8332136c2 100644 --- a/qobject/qlit.c +++ b/qobject/qlit.c @@ -69,16 +69,16 @@ bool qlit_equal_qobject(const QLitObject *lhs, const QO= bject *rhs) switch (lhs->type) { case QTYPE_QBOOL: - return lhs->value.qbool =3D=3D qbool_get_bool(qobject_to_qbool(rhs= )); + return lhs->value.qbool =3D=3D qbool_get_bool(qobject_to(QBool, rh= s)); case QTYPE_QNUM: - return lhs->value.qnum =3D=3D qnum_get_int(qobject_to_qnum(rhs)); + return lhs->value.qnum =3D=3D qnum_get_int(qobject_to(QNum, rhs)); case QTYPE_QSTRING: return (strcmp(lhs->value.qstr, - qstring_get_str(qobject_to_qstring(rhs))) =3D=3D 0); + qstring_get_str(qobject_to(QString, rhs))) =3D=3D 0= ); case QTYPE_QDICT: - return qlit_equal_qdict(lhs, qobject_to_qdict(rhs)); + return qlit_equal_qdict(lhs, qobject_to(QDict, rhs)); case QTYPE_QLIST: - return qlit_equal_qlist(lhs, qobject_to_qlist(rhs)); + return qlit_equal_qlist(lhs, qobject_to(QList, rhs)); case QTYPE_QNULL: return true; default: diff --git a/qobject/qnum.c b/qobject/qnum.c index 60c395c1bce..ea091cfaa4b 100644 --- a/qobject/qnum.c +++ b/qobject/qnum.c @@ -221,8 +221,8 @@ QNum *qobject_to_qnum(const QObject *obj) */ bool qnum_is_equal(const QObject *x, const QObject *y) { - QNum *num_x =3D qobject_to_qnum(x); - QNum *num_y =3D qobject_to_qnum(y); + QNum *num_x =3D qobject_to(QNum, x); + QNum *num_y =3D qobject_to(QNum, y); switch (num_x->kind) { case QNUM_I64: @@ -271,5 +271,5 @@ bool qnum_is_equal(const QObject *x, const QObject *y) void qnum_destroy_obj(QObject *obj) { assert(obj !=3D NULL); - g_free(qobject_to_qnum(obj)); + g_free(qobject_to(QNum, obj)); } diff --git a/qobject/qstring.c b/qobject/qstring.c index 05b4bbc2d62..2b2153206df 100644 --- a/qobject/qstring.c +++ b/qobject/qstring.c @@ -132,8 +132,8 @@ const char *qstring_get_str(const QString *qstring) */ bool qstring_is_equal(const QObject *x, const QObject *y) { - return !strcmp(qobject_to_qstring(x)->string, - qobject_to_qstring(y)->string); + return !strcmp(qobject_to(QString, x)->string, + qobject_to(QString, y)->string); } /** @@ -145,7 +145,7 @@ void qstring_destroy_obj(QObject *obj) QString *qs; assert(obj !=3D NULL); - qs =3D qobject_to_qstring(obj); + qs =3D qobject_to(QString, obj); g_free(qs->string); g_free(qs); } diff --git a/qom/object.c b/qom/object.c index 755ad038197..7b3a6158fde 100644 --- a/qom/object.c +++ b/qom/object.c @@ -1129,7 +1129,7 @@ char *object_property_get_str(Object *obj, const char= *name, if (!ret) { return NULL; } - qstring =3D qobject_to_qstring(ret); + qstring =3D qobject_to(QString, ret); if (!qstring) { error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "string"); retval =3D NULL; @@ -1190,7 +1190,7 @@ bool object_property_get_bool(Object *obj, const char= *name, if (!ret) { return false; } - qbool =3D qobject_to_qbool(ret); + qbool =3D qobject_to(QBool, ret); if (!qbool) { error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "boolean"); retval =3D false; @@ -1222,7 +1222,7 @@ int64_t object_property_get_int(Object *obj, const ch= ar *name, return -1; } - qnum =3D qobject_to_qnum(ret); + qnum =3D qobject_to(QNum, ret); if (!qnum || !qnum_get_try_int(qnum, &retval)) { error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "int"); retval =3D -1; @@ -1251,7 +1251,7 @@ uint64_t object_property_get_uint(Object *obj, const = char *name, if (!ret) { return 0; } - qnum =3D qobject_to_qnum(ret); + qnum =3D qobject_to(QNum, ret); if (!qnum || !qnum_get_try_uint(qnum, &retval)) { error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "uint"); retval =3D 0; diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 2c04645ceac..a1234cc780d 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -3101,7 +3101,7 @@ arch_query_cpu_model_expansion(CpuModelExpansionType = type, xc =3D x86_cpu_from_model(model->name, model->has_props ? - qobject_to_qdict(model->props) : + qobject_to(QDict, model->props) : NULL, &err); if (err) { goto out; diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c index 1d5f0da4fe0..2741b6803f7 100644 --- a/target/s390x/cpu_models.c +++ b/target/s390x/cpu_models.c @@ -453,7 +453,7 @@ static void cpu_model_from_info(S390CPUModel *model, co= nst CpuModelInfo *info, Object *obj; if (info->props) { - qdict =3D qobject_to_qdict(info->props); + qdict =3D qobject_to(QDict, info->props); if (!qdict) { error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "props", "dict"); return; diff --git a/tests/check-qdict.c b/tests/check-qdict.c index a3faea8bfc2..2e73c2f86ea 100644 --- a/tests/check-qdict.c +++ b/tests/check-qdict.c @@ -51,7 +51,7 @@ static void qdict_put_obj_test(void) g_assert(qdict_size(qdict) =3D=3D 1); ent =3D QLIST_FIRST(&qdict->table[12345 % QDICT_BUCKET_MAX]); - qn =3D qobject_to_qnum(ent->value); + qn =3D qobject_to(QNum, ent->value); g_assert_cmpint(qnum_get_int(qn), =3D=3D, num); QDECREF(qdict); @@ -81,7 +81,7 @@ static void qdict_get_test(void) obj =3D qdict_get(tests_dict, key); g_assert(obj !=3D NULL); - qn =3D qobject_to_qnum(obj); + qn =3D qobject_to(QNum, obj); g_assert_cmpint(qnum_get_int(qn), =3D=3D, value); QDECREF(tests_dict); @@ -216,7 +216,7 @@ static void qdict_del_test(void) static void qobject_to_qdict_test(void) { QDict *tests_dict =3D qdict_new(); - g_assert(qobject_to_qdict(QOBJECT(tests_dict)) =3D=3D tests_dict); + g_assert(qobject_to(QDict, QOBJECT(tests_dict)) =3D=3D tests_dict); QDECREF(tests_dict); } @@ -381,9 +381,9 @@ static void qdict_array_split_test(void) 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)); + 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); @@ -450,7 +450,7 @@ static void qdict_array_split_test(void) qdict_array_split(test_dict, &test_list); - int1 =3D qobject_to_qnum(qlist_pop(test_list)); + int1 =3D qobject_to(QNum, qlist_pop(test_list)); g_assert(int1); g_assert(qlist_empty(test_list)); @@ -607,7 +607,7 @@ static void qdict_crumple_test_recursive(void) 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)); + dst =3D qobject_to(QDict, qdict_crumple(src, &error_abort)); g_assert(dst); g_assert_cmpint(qdict_size(dst), =3D=3D, 1); @@ -629,14 +629,14 @@ static void qdict_crumple_test_recursive(void) g_assert(rules); g_assert_cmpint(qlist_size(rules), =3D=3D, 2); - rule =3D qobject_to_qdict(qlist_pop(rules)); + 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")); QDECREF(rule); - rule =3D qobject_to_qdict(qlist_pop(rules)); + 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")); diff --git a/tests/check-qjson.c b/tests/check-qjson.c index a18ea47cb74..997f4d3d2c9 100644 --- a/tests/check-qjson.c +++ b/tests/check-qjson.c @@ -60,7 +60,7 @@ static void escaped_string(void) QString *str; obj =3D qobject_from_json(test_cases[i].encoded, &error_abort); - str =3D qobject_to_qstring(obj); + str =3D qobject_to(QString, obj); g_assert(str); g_assert_cmpstr(qstring_get_str(str), =3D=3D, test_cases[i].decode= d); @@ -92,7 +92,7 @@ static void simple_string(void) QString *str; obj =3D qobject_from_json(test_cases[i].encoded, &error_abort); - str =3D qobject_to_qstring(obj); + str =3D qobject_to(QString, obj); g_assert(str); g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) =3D= =3D 0); @@ -123,7 +123,7 @@ static void single_quote_string(void) QString *str; obj =3D qobject_from_json(test_cases[i].encoded, &error_abort); - str =3D qobject_to_qstring(obj); + str =3D qobject_to(QString, obj); g_assert(str); g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) =3D= =3D 0); @@ -817,7 +817,7 @@ static void utf8_string(void) obj =3D qobject_from_json(json_in, utf8_out ? &error_abort : NULL); if (utf8_out) { - str =3D qobject_to_qstring(obj); + str =3D qobject_to(QString, obj); g_assert(str); g_assert_cmpstr(qstring_get_str(str), =3D=3D, utf8_out); } else { @@ -843,7 +843,7 @@ static void utf8_string(void) */ if (0 && json_out !=3D json_in) { obj =3D qobject_from_json(json_out, &error_abort); - str =3D qobject_to_qstring(obj); + str =3D qobject_to(QString, obj); g_assert(str); g_assert_cmpstr(qstring_get_str(str), =3D=3D, utf8_out); } @@ -864,8 +864,8 @@ static void vararg_string(void) for (i =3D 0; test_cases[i].decoded; i++) { QString *str; - str =3D qobject_to_qstring(qobject_from_jsonf("%s", - test_cases[i].decoded)= ); + str =3D qobject_to(QString, + qobject_from_jsonf("%s", test_cases[i].decoded)); g_assert(str); g_assert(strcmp(qstring_get_str(str), test_cases[i].decoded) =3D= =3D 0); @@ -893,8 +893,9 @@ static void simple_number(void) QNum *qnum; int64_t val; - qnum =3D qobject_to_qnum(qobject_from_json(test_cases[i].encoded, - &error_abort)); + qnum =3D qobject_to(QNum, + qobject_from_json(test_cases[i].encoded, + &error_abort)); g_assert(qnum); g_assert(qnum_get_try_int(qnum, &val)); g_assert_cmpint(val, =3D=3D, test_cases[i].decoded); @@ -920,7 +921,7 @@ static void large_number(void) uint64_t val; int64_t ival; - qnum =3D qobject_to_qnum(qobject_from_json(maxu64, &error_abort)); + qnum =3D qobject_to(QNum, qobject_from_json(maxu64, &error_abort)); g_assert(qnum); g_assert_cmpuint(qnum_get_uint(qnum), =3D=3D, 18446744073709551615U); g_assert(!qnum_get_try_int(qnum, &ival)); @@ -930,7 +931,7 @@ static void large_number(void) QDECREF(str); QDECREF(qnum); - qnum =3D qobject_to_qnum(qobject_from_json(gtu64, &error_abort)); + qnum =3D qobject_to(QNum, qobject_from_json(gtu64, &error_abort)); g_assert(qnum); g_assert_cmpfloat(qnum_get_double(qnum), =3D=3D, 18446744073709552e3); g_assert(!qnum_get_try_uint(qnum, &val)); @@ -941,7 +942,7 @@ static void large_number(void) QDECREF(str); QDECREF(qnum); - qnum =3D qobject_to_qnum(qobject_from_json(lti64, &error_abort)); + qnum =3D qobject_to(QNum, qobject_from_json(lti64, &error_abort)); g_assert(qnum); g_assert_cmpfloat(qnum_get_double(qnum), =3D=3D, -92233720368547758e2); g_assert(!qnum_get_try_uint(qnum, &val)); @@ -973,7 +974,7 @@ static void float_number(void) QNum *qnum; obj =3D qobject_from_json(test_cases[i].encoded, &error_abort); - qnum =3D qobject_to_qnum(obj); + qnum =3D qobject_to(QNum, obj); g_assert(qnum); g_assert(qnum_get_double(qnum) =3D=3D test_cases[i].decoded); @@ -997,17 +998,17 @@ static void vararg_number(void) double valuef =3D 2.323423423; int64_t val; - qnum =3D qobject_to_qnum(qobject_from_jsonf("%d", value)); + qnum =3D qobject_to(QNum, qobject_from_jsonf("%d", value)); g_assert(qnum_get_try_int(qnum, &val)); g_assert_cmpint(val, =3D=3D, value); QDECREF(qnum); - qnum =3D qobject_to_qnum(qobject_from_jsonf("%lld", value_ll)); + qnum =3D qobject_to(QNum, qobject_from_jsonf("%lld", value_ll)); g_assert(qnum_get_try_int(qnum, &val)); g_assert_cmpint(val, =3D=3D, value_ll); QDECREF(qnum); - qnum =3D qobject_to_qnum(qobject_from_jsonf("%f", valuef)); + qnum =3D qobject_to(QNum, qobject_from_jsonf("%f", valuef)); g_assert(qnum_get_double(qnum) =3D=3D valuef); QDECREF(qnum); } @@ -1020,7 +1021,7 @@ static void keyword_literal(void) QString *str; obj =3D qobject_from_json("true", &error_abort); - qbool =3D qobject_to_qbool(obj); + qbool =3D qobject_to(QBool, obj); g_assert(qbool); g_assert(qbool_get_bool(qbool) =3D=3D true); @@ -1031,7 +1032,7 @@ static void keyword_literal(void) QDECREF(qbool); obj =3D qobject_from_json("false", &error_abort); - qbool =3D qobject_to_qbool(obj); + qbool =3D qobject_to(QBool, obj); g_assert(qbool); g_assert(qbool_get_bool(qbool) =3D=3D false); @@ -1041,13 +1042,13 @@ static void keyword_literal(void) QDECREF(qbool); - qbool =3D qobject_to_qbool(qobject_from_jsonf("%i", false)); + qbool =3D qobject_to(QBool, qobject_from_jsonf("%i", false)); g_assert(qbool); g_assert(qbool_get_bool(qbool) =3D=3D false); QDECREF(qbool); /* Test that non-zero values other than 1 get collapsed to true */ - qbool =3D qobject_to_qbool(qobject_from_jsonf("%i", 2)); + qbool =3D qobject_to(QBool, qobject_from_jsonf("%i", 2)); g_assert(qbool); g_assert(qbool_get_bool(qbool) =3D=3D true); QDECREF(qbool); diff --git a/tests/check-qlist.c b/tests/check-qlist.c index 259980d5239..a1c69ed6481 100644 --- a/tests/check-qlist.c +++ b/tests/check-qlist.c @@ -56,7 +56,7 @@ static void qobject_to_qlist_test(void) qlist =3D qlist_new(); - g_assert(qobject_to_qlist(QOBJECT(qlist)) =3D=3D qlist); + g_assert(qobject_to(QList, QOBJECT(qlist)) =3D=3D qlist); QDECREF(qlist); } @@ -71,7 +71,7 @@ static void iter_func(QObject *obj, void *opaque) g_assert(opaque =3D=3D NULL); - qi =3D qobject_to_qnum(obj); + qi =3D qobject_to(QNum, obj); g_assert(qi !=3D NULL); g_assert(qnum_get_try_int(qi, &val)); diff --git a/tests/check-qlit.c b/tests/check-qlit.c index 836f4a3090c..96bbb06f2c7 100644 --- a/tests/check-qlit.c +++ b/tests/check-qlit.c @@ -59,7 +59,7 @@ static void qlit_equal_qobject_test(void) g_assert(!qlit_equal_qobject(&qlit_foo, qobj)); - qdict_put(qobject_to_qdict(qobj), "bee", qlist_new()); + qdict_put(qobject_to(QDict, qobj), "bee", qlist_new()); g_assert(!qlit_equal_qobject(&qlit, qobj)); qobject_decref(qobj); @@ -71,20 +71,20 @@ static void qobject_from_qlit_test(void) QDict *qdict; QList *bee; - qdict =3D qobject_to_qdict(qobj); + qdict =3D qobject_to(QDict, qobj); g_assert_cmpint(qdict_get_int(qdict, "foo"), =3D=3D, 42); g_assert_cmpstr(qdict_get_str(qdict, "bar"), =3D=3D, "hello world"); g_assert(qobject_type(qdict_get(qdict, "baz")) =3D=3D QTYPE_QNULL); bee =3D qdict_get_qlist(qdict, "bee"); obj =3D qlist_pop(bee); - g_assert_cmpint(qnum_get_int(qobject_to_qnum(obj)), =3D=3D, 43); + g_assert_cmpint(qnum_get_int(qobject_to(QNum, obj)), =3D=3D, 43); qobject_decref(obj); obj =3D qlist_pop(bee); - g_assert_cmpint(qnum_get_int(qobject_to_qnum(obj)), =3D=3D, 44); + g_assert_cmpint(qnum_get_int(qobject_to(QNum, obj)), =3D=3D, 44); qobject_decref(obj); obj =3D qlist_pop(bee); - g_assert(qbool_get_bool(qobject_to_qbool(obj))); + g_assert(qbool_get_bool(qobject_to(QBool, obj))); qobject_decref(obj); qobject_decref(qobj); diff --git a/tests/check-qnum.c b/tests/check-qnum.c index 2b667f7ad77..9187da734b0 100644 --- a/tests/check-qnum.c +++ b/tests/check-qnum.c @@ -126,11 +126,11 @@ static void qobject_to_qnum_test(void) QNum *qn; qn =3D qnum_from_int(0); - g_assert(qobject_to_qnum(QOBJECT(qn)) =3D=3D qn); + g_assert(qobject_to(QNum, QOBJECT(qn)) =3D=3D qn); QDECREF(qn); qn =3D qnum_from_double(0); - g_assert(qobject_to_qnum(QOBJECT(qn)) =3D=3D qn); + g_assert(qobject_to(QNum, QOBJECT(qn)) =3D=3D qn); QDECREF(qn); } diff --git a/tests/check-qobject.c b/tests/check-qobject.c index 7a3670643cb..7629b8071b3 100644 --- a/tests/check-qobject.c +++ b/tests/check-qobject.c @@ -275,7 +275,7 @@ static void qobject_is_equal_dict_test(void) dict_different_null_key, dict_longer, dict_shorter, dict_nested); - dict_crumpled =3D qobject_to_qdict(qdict_crumple(dict_1, &local_err)); + dict_crumpled =3D qobject_to(QDict, qdict_crumple(dict_1, &local_err)); g_assert(!local_err); check_equal(dict_crumpled, dict_nested); diff --git a/tests/check-qstring.c b/tests/check-qstring.c index 112ec08967f..9c4dd3f94fc 100644 --- a/tests/check-qstring.c +++ b/tests/check-qstring.c @@ -79,7 +79,7 @@ static void qobject_to_qstring_test(void) QString *qstring; qstring =3D qstring_from_str("foo"); - g_assert(qobject_to_qstring(QOBJECT(qstring)) =3D=3D qstring); + g_assert(qobject_to(QString, QOBJECT(qstring)) =3D=3D qstring); QDECREF(qstring); } diff --git a/tests/device-introspect-test.c b/tests/device-introspect-test.c index b80058fe988..a01321aced7 100644 --- a/tests/device-introspect-test.c +++ b/tests/device-introspect-test.c @@ -52,7 +52,7 @@ static QDict *qom_type_index(QList *types) QListEntry *e; QLIST_FOREACH_ENTRY(types, e) { - QDict *d =3D qobject_to_qdict(qlist_entry_obj(e)); + QDict *d =3D qobject_to(QDict, qlist_entry_obj(e)); const char *name =3D qdict_get_str(d, "name"); QINCREF(d); qdict_put(index, name, d); @@ -85,7 +85,7 @@ static QDict *type_list_find(QList *types, const char *na= me) QListEntry *e; QLIST_FOREACH_ENTRY(types, e) { - QDict *d =3D qobject_to_qdict(qlist_entry_obj(e)); + QDict *d =3D qobject_to(QDict, qlist_entry_obj(e)); const char *ename =3D qdict_get_str(d, "name"); if (!strcmp(ename, name)) { return d; @@ -151,7 +151,7 @@ static void test_qom_list_parents(const char *parent) index =3D qom_type_index(types); QLIST_FOREACH_ENTRY(types, e) { - QDict *d =3D qobject_to_qdict(qlist_entry_obj(e)); + QDict *d =3D qobject_to(QDict, qlist_entry_obj(e)); const char *name =3D qdict_get_str(d, "name"); g_assert(qom_has_parent(index, name, parent)); @@ -173,7 +173,7 @@ static void test_qom_list_fields(void) non_abstract =3D qom_list_types(NULL, false); QLIST_FOREACH_ENTRY(all_types, e) { - QDict *d =3D qobject_to_qdict(qlist_entry_obj(e)); + QDict *d =3D qobject_to(QDict, qlist_entry_obj(e)); const char *name =3D qdict_get_str(d, "name"); bool abstract =3D qdict_haskey(d, "abstract") ? qdict_get_bool(d, "abstract") : @@ -216,8 +216,8 @@ static void test_device_intro_concrete(void) types =3D device_type_list(false); QLIST_FOREACH_ENTRY(types, entry) { - type =3D qdict_get_try_str(qobject_to_qdict(qlist_entry_obj(entry)= ), - "name"); + type =3D qdict_get_try_str(qobject_to(QDict, qlist_entry_obj(entry= )), + "name"); g_assert(type); test_one_device(type); } @@ -238,7 +238,7 @@ static void test_abstract_interfaces(void) index =3D qom_type_index(all_types); QLIST_FOREACH_ENTRY(all_types, e) { - QDict *d =3D qobject_to_qdict(qlist_entry_obj(e)); + QDict *d =3D qobject_to(QDict, qlist_entry_obj(e)); const char *name =3D qdict_get_str(d, "name"); /* diff --git a/tests/numa-test.c b/tests/numa-test.c index 68aca9cb389..0f861d8176d 100644 --- a/tests/numa-test.c +++ b/tests/numa-test.c @@ -98,7 +98,7 @@ static void test_query_cpus(const void *data) QDict *cpu, *props; int64_t cpu_idx, node; - cpu =3D qobject_to_qdict(e); + cpu =3D qobject_to(QDict, e); g_assert(qdict_haskey(cpu, "CPU")); g_assert(qdict_haskey(cpu, "props")); @@ -140,7 +140,7 @@ static void pc_numa_cpu(const void *data) QDict *cpu, *props; int64_t socket, core, thread, node; - cpu =3D qobject_to_qdict(e); + cpu =3D qobject_to(QDict, e); g_assert(qdict_haskey(cpu, "props")); props =3D qdict_get_qdict(cpu, "props"); @@ -193,7 +193,7 @@ static void spapr_numa_cpu(const void *data) QDict *cpu, *props; int64_t core, node; - cpu =3D qobject_to_qdict(e); + cpu =3D qobject_to(QDict, e); g_assert(qdict_haskey(cpu, "props")); props =3D qdict_get_qdict(cpu, "props"); @@ -236,7 +236,7 @@ static void aarch64_numa_cpu(const void *data) QDict *cpu, *props; int64_t thread, node; - cpu =3D qobject_to_qdict(e); + cpu =3D qobject_to(QDict, e); g_assert(qdict_haskey(cpu, "props")); props =3D qdict_get_qdict(cpu, "props"); diff --git a/tests/qom-test.c b/tests/qom-test.c index 9dab7ac61ec..a34ff6ba53f 100644 --- a/tests/qom-test.c +++ b/tests/qom-test.c @@ -62,9 +62,9 @@ static void test_properties(const char *path, bool recurs= e) } g_assert(qdict_haskey(response, "return")); - list =3D qobject_to_qlist(qdict_get(response, "return")); + list =3D qobject_to(QList, qdict_get(response, "return")); QLIST_FOREACH_ENTRY(list, entry) { - tuple =3D qobject_to_qdict(qlist_entry_obj(entry)); + tuple =3D qobject_to(QDict, qlist_entry_obj(entry)); bool is_child =3D strstart(qdict_get_str(tuple, "type"), "child<",= NULL); bool is_link =3D strstart(qdict_get_str(tuple, "type"), "link<", N= ULL); diff --git a/tests/test-char.c b/tests/test-char.c index b3a77af0855..c4178f95e7f 100644 --- a/tests/test-char.c +++ b/tests/test-char.c @@ -321,7 +321,7 @@ static void char_socket_test(void) g_assert(!object_property_get_bool(OBJECT(chr), "connected", &error_ab= ort)); addr =3D object_property_get_qobject(OBJECT(chr), "addr", &error_abort= ); - qdict =3D qobject_to_qdict(addr); + qdict =3D qobject_to(QDict, addr); port =3D qdict_get_str(qdict, "port"); tmp =3D g_strdup_printf("tcp:127.0.0.1:%s", port); QDECREF(qdict); diff --git a/tests/test-keyval.c b/tests/test-keyval.c index 94eb4df28d4..029f05202a8 100644 --- a/tests/test-keyval.c +++ b/tests/test-keyval.c @@ -195,7 +195,7 @@ static void check_list012(QList *qlist) g_assert(qlist); for (i =3D 0; i < ARRAY_SIZE(expected); i++) { - qstr =3D qobject_to_qstring(qlist_pop(qlist)); + qstr =3D qobject_to(QString, qlist_pop(qlist)); g_assert(qstr); g_assert_cmpstr(qstring_get_str(qstr), =3D=3D, expected[i]); QDECREF(qstr); @@ -654,12 +654,12 @@ static void test_keyval_visit_any(void) QDECREF(qdict); visit_start_struct(v, NULL, NULL, 0, &error_abort); visit_type_any(v, "a", &any, &error_abort); - qlist =3D qobject_to_qlist(any); + qlist =3D qobject_to(QList, any); g_assert(qlist); - qstr =3D qobject_to_qstring(qlist_pop(qlist)); + qstr =3D qobject_to(QString, qlist_pop(qlist)); g_assert_cmpstr(qstring_get_str(qstr), =3D=3D, "null"); QDECREF(qstr); - qstr =3D qobject_to_qstring(qlist_pop(qlist)); + qstr =3D qobject_to(QString, qlist_pop(qlist)); g_assert_cmpstr(qstring_get_str(qstr), =3D=3D, "1"); g_assert(qlist_empty(qlist)); QDECREF(qstr); diff --git a/tests/test-qga.c b/tests/test-qga.c index 5c5b661f8a3..e6ab788f31a 100644 --- a/tests/test-qga.c +++ b/tests/test-qga.c @@ -297,8 +297,8 @@ static void test_qga_get_vcpus(gconstpointer fix) /* check there is at least a cpu */ list =3D qdict_get_qlist(ret, "return"); entry =3D qlist_first(list); - g_assert(qdict_haskey(qobject_to_qdict(entry->value), "online")); - g_assert(qdict_haskey(qobject_to_qdict(entry->value), "logical-id")); + g_assert(qdict_haskey(qobject_to(QDict, entry->value), "online")); + g_assert(qdict_haskey(qobject_to(QDict, entry->value), "logical-id")); QDECREF(ret); } @@ -318,10 +318,10 @@ static void test_qga_get_fsinfo(gconstpointer fix) list =3D qdict_get_qlist(ret, "return"); entry =3D qlist_first(list); if (entry) { - g_assert(qdict_haskey(qobject_to_qdict(entry->value), "name")); - g_assert(qdict_haskey(qobject_to_qdict(entry->value), "mountpoint"= )); - g_assert(qdict_haskey(qobject_to_qdict(entry->value), "type")); - g_assert(qdict_haskey(qobject_to_qdict(entry->value), "disk")); + g_assert(qdict_haskey(qobject_to(QDict, entry->value), "name")); + g_assert(qdict_haskey(qobject_to(QDict, entry->value), "mountpoint= ")); + g_assert(qdict_haskey(qobject_to(QDict, entry->value), "type")); + g_assert(qdict_haskey(qobject_to(QDict, entry->value), "disk")); } QDECREF(ret); @@ -363,8 +363,9 @@ static void test_qga_get_memory_blocks(gconstpointer fi= x) entry =3D qlist_first(list); /* newer versions of qga may return empty list without error */ if (entry) { - g_assert(qdict_haskey(qobject_to_qdict(entry->value), "phys-in= dex")); - g_assert(qdict_haskey(qobject_to_qdict(entry->value), "online"= )); + g_assert(qdict_haskey(qobject_to(QDict, entry->value), + "phys-index")); + g_assert(qdict_haskey(qobject_to(QDict, entry->value), "online= ")); } } @@ -385,7 +386,7 @@ static void test_qga_network_get_interfaces(gconstpoint= er fix) /* check there is at least an interface */ list =3D qdict_get_qlist(ret, "return"); entry =3D qlist_first(list); - g_assert(qdict_haskey(qobject_to_qdict(entry->value), "name")); + g_assert(qdict_haskey(qobject_to(QDict, entry->value), "name")); QDECREF(ret); } diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c index 5b1cee69122..93fbbb1b733 100644 --- a/tests/test-qmp-cmds.c +++ b/tests/test-qmp-cmds.c @@ -100,7 +100,7 @@ static void test_dispatch_cmd(void) resp =3D qmp_dispatch(&qmp_commands, QOBJECT(req)); assert(resp !=3D NULL); - assert(!qdict_haskey(qobject_to_qdict(resp), "error")); + assert(!qdict_haskey(qobject_to(QDict, resp), "error")); qobject_decref(resp); QDECREF(req); @@ -117,7 +117,7 @@ static void test_dispatch_cmd_failure(void) resp =3D qmp_dispatch(&qmp_commands, QOBJECT(req)); assert(resp !=3D NULL); - assert(qdict_haskey(qobject_to_qdict(resp), "error")); + assert(qdict_haskey(qobject_to(QDict, resp), "error")); qobject_decref(resp); QDECREF(req); @@ -131,7 +131,7 @@ static void test_dispatch_cmd_failure(void) resp =3D qmp_dispatch(&qmp_commands, QOBJECT(req)); assert(resp !=3D NULL); - assert(qdict_haskey(qobject_to_qdict(resp), "error")); + assert(qdict_haskey(qobject_to(QDict, resp), "error")); qobject_decref(resp); QDECREF(req); @@ -145,7 +145,7 @@ static QObject *test_qmp_dispatch(QDict *req) resp_obj =3D qmp_dispatch(&qmp_commands, QOBJECT(req)); assert(resp_obj); - resp =3D qobject_to_qdict(resp_obj); + resp =3D qobject_to(QDict, resp_obj); assert(resp && !qdict_haskey(resp, "error")); ret =3D qdict_get(resp, "return"); assert(ret); @@ -176,7 +176,7 @@ static void test_dispatch_cmd_io(void) qdict_put(req, "arguments", args); qdict_put_str(req, "execute", "user_def_cmd2"); - ret =3D qobject_to_qdict(test_qmp_dispatch(req)); + ret =3D qobject_to(QDict, test_qmp_dispatch(req)); assert(!strcmp(qdict_get_str(ret, "string0"), "blah1")); ret_dict =3D qdict_get_qdict(ret, "dict1"); @@ -197,7 +197,7 @@ static void test_dispatch_cmd_io(void) qdict_put(req, "arguments", args3); qdict_put_str(req, "execute", "guest-get-time"); - ret3 =3D qobject_to_qnum(test_qmp_dispatch(req)); + ret3 =3D qobject_to(QNum, test_qmp_dispatch(req)); g_assert(qnum_get_try_int(ret3, &val)); g_assert_cmpint(val, =3D=3D, 66); QDECREF(ret3); diff --git a/tests/test-qmp-event.c b/tests/test-qmp-event.c index 31f35b3e66a..bb1036615fd 100644 --- a/tests/test-qmp-event.c +++ b/tests/test-qmp-event.c @@ -60,22 +60,22 @@ void qdict_cmp_do_simple(const char *key, QObject *obj1= , void *opaque) switch (qobject_type(obj1)) { case QTYPE_QBOOL: - d->result =3D (qbool_get_bool(qobject_to_qbool(obj1)) =3D=3D - qbool_get_bool(qobject_to_qbool(obj2))); + d->result =3D (qbool_get_bool(qobject_to(QBool, obj1)) =3D=3D + qbool_get_bool(qobject_to(QBool, obj2))); return; case QTYPE_QNUM: - g_assert(qnum_get_try_int(qobject_to_qnum(obj1), &val1)); - g_assert(qnum_get_try_int(qobject_to_qnum(obj2), &val2)); + g_assert(qnum_get_try_int(qobject_to(QNum, obj1), &val1)); + g_assert(qnum_get_try_int(qobject_to(QNum, obj2), &val2)); d->result =3D val1 =3D=3D val2; return; case QTYPE_QSTRING: - d->result =3D g_strcmp0(qstring_get_str(qobject_to_qstring(obj1)), - qstring_get_str(qobject_to_qstring(obj2))) = =3D=3D 0; + d->result =3D g_strcmp0(qstring_get_str(qobject_to(QString, obj1)), + qstring_get_str(qobject_to(QString, obj2))) = =3D=3D 0; return; case QTYPE_QDICT: - d_new.expect =3D qobject_to_qdict(obj2); + d_new.expect =3D qobject_to(QDict, obj2); d_new.result =3D true; - qdict_iter(qobject_to_qdict(obj1), qdict_cmp_do_simple, &d_new); + qdict_iter(qobject_to(QDict, obj1), qdict_cmp_do_simple, &d_new); d->result =3D d_new.result; return; default: diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-= visitor.c index 55db6bdef13..6dc59c62116 100644 --- a/tests/test-qobject-input-visitor.c +++ b/tests/test-qobject-input-visitor.c @@ -479,7 +479,7 @@ static void test_visitor_in_any(TestInputVisitorData *d= ata, v =3D visitor_input_test_init(data, "-42"); visit_type_any(v, NULL, &res, &error_abort); - qnum =3D qobject_to_qnum(res); + qnum =3D qobject_to(QNum, res); g_assert(qnum); g_assert(qnum_get_try_int(qnum, &val)); g_assert_cmpint(val, =3D=3D, -42); @@ -487,22 +487,22 @@ static void test_visitor_in_any(TestInputVisitorData = *data, v =3D visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true= , 'string': 'foo' }"); visit_type_any(v, NULL, &res, &error_abort); - qdict =3D qobject_to_qdict(res); + qdict =3D qobject_to(QDict, res); g_assert(qdict && qdict_size(qdict) =3D=3D 3); qobj =3D qdict_get(qdict, "integer"); g_assert(qobj); - qnum =3D qobject_to_qnum(qobj); + qnum =3D qobject_to(QNum, qobj); g_assert(qnum); g_assert(qnum_get_try_int(qnum, &val)); g_assert_cmpint(val, =3D=3D, -42); qobj =3D qdict_get(qdict, "boolean"); g_assert(qobj); - qbool =3D qobject_to_qbool(qobj); + qbool =3D qobject_to(QBool, qobj); g_assert(qbool); g_assert(qbool_get_bool(qbool) =3D=3D true); qobj =3D qdict_get(qdict, "string"); g_assert(qobj); - qstring =3D qobject_to_qstring(qobj); + qstring =3D qobject_to(QString, qobj); g_assert(qstring); g_assert_cmpstr(qstring_get_str(qstring), =3D=3D, "foo"); qobject_decref(res); diff --git a/tests/test-qobject-output-visitor.c b/tests/test-qobject-outpu= t-visitor.c index 11e8c5aa403..ecf21c0f318 100644 --- a/tests/test-qobject-output-visitor.c +++ b/tests/test-qobject-output-visitor.c @@ -66,7 +66,7 @@ static void test_visitor_out_int(TestOutputVisitorData *d= ata, visit_type_int(data->ov, NULL, &value, &error_abort); - qnum =3D qobject_to_qnum(visitor_get(data)); + qnum =3D qobject_to(QNum, visitor_get(data)); g_assert(qnum); g_assert(qnum_get_try_int(qnum, &val)); g_assert_cmpint(val, =3D=3D, value); @@ -80,7 +80,7 @@ static void test_visitor_out_bool(TestOutputVisitorData *= data, visit_type_bool(data->ov, NULL, &value, &error_abort); - qbool =3D qobject_to_qbool(visitor_get(data)); + qbool =3D qobject_to(QBool, visitor_get(data)); g_assert(qbool); g_assert(qbool_get_bool(qbool) =3D=3D value); } @@ -93,7 +93,7 @@ static void test_visitor_out_number(TestOutputVisitorData= *data, visit_type_number(data->ov, NULL, &value, &error_abort); - qnum =3D qobject_to_qnum(visitor_get(data)); + qnum =3D qobject_to(QNum, visitor_get(data)); g_assert(qnum); g_assert(qnum_get_double(qnum) =3D=3D value); } @@ -106,7 +106,7 @@ static void test_visitor_out_string(TestOutputVisitorDa= ta *data, visit_type_str(data->ov, NULL, &string, &error_abort); - qstr =3D qobject_to_qstring(visitor_get(data)); + qstr =3D qobject_to(QString, visitor_get(data)); g_assert(qstr); g_assert_cmpstr(qstring_get_str(qstr), =3D=3D, string); } @@ -120,7 +120,7 @@ static void test_visitor_out_no_string(TestOutputVisito= rData *data, /* A null string should return "" */ visit_type_str(data->ov, NULL, &string, &error_abort); - qstr =3D qobject_to_qstring(visitor_get(data)); + qstr =3D qobject_to(QString, visitor_get(data)); g_assert(qstr); g_assert_cmpstr(qstring_get_str(qstr), =3D=3D, ""); } @@ -134,7 +134,7 @@ static void test_visitor_out_enum(TestOutputVisitorData= *data, for (i =3D 0; i < ENUM_ONE__MAX; i++) { visit_type_EnumOne(data->ov, "unused", &i, &error_abort); - qstr =3D qobject_to_qstring(visitor_get(data)); + qstr =3D qobject_to(QString, visitor_get(data)); g_assert(qstr); g_assert_cmpstr(qstring_get_str(qstr), =3D=3D, EnumOne_str(i)); visitor_reset(data); @@ -167,7 +167,7 @@ static void test_visitor_out_struct(TestOutputVisitorDa= ta *data, visit_type_TestStruct(data->ov, NULL, &p, &error_abort); - qdict =3D qobject_to_qdict(visitor_get(data)); + qdict =3D qobject_to(QDict, visitor_get(data)); g_assert(qdict); g_assert_cmpint(qdict_size(qdict), =3D=3D, 3); g_assert_cmpint(qdict_get_int(qdict, "integer"), =3D=3D, 42); @@ -206,7 +206,7 @@ static void test_visitor_out_struct_nested(TestOutputVi= sitorData *data, visit_type_UserDefTwo(data->ov, "unused", &ud2, &error_abort); - qdict =3D qobject_to_qdict(visitor_get(data)); + qdict =3D qobject_to(QDict, visitor_get(data)); g_assert(qdict); g_assert_cmpint(qdict_size(qdict), =3D=3D, 2); g_assert_cmpstr(qdict_get_str(qdict, "string0"), =3D=3D, strings[0]); @@ -280,7 +280,7 @@ static void test_visitor_out_list(TestOutputVisitorData= *data, visit_type_TestStructList(data->ov, NULL, &head, &error_abort); - qlist =3D qobject_to_qlist(visitor_get(data)); + qlist =3D qobject_to(QList, visitor_get(data)); g_assert(qlist); g_assert(!qlist_empty(qlist)); @@ -289,7 +289,7 @@ static void test_visitor_out_list(TestOutputVisitorData= *data, QLIST_FOREACH_ENTRY(qlist, entry) { QDict *qdict; - qdict =3D qobject_to_qdict(entry->value); + qdict =3D qobject_to(QDict, entry->value); g_assert(qdict); g_assert_cmpint(qdict_size(qdict), =3D=3D, 3); g_assert_cmpint(qdict_get_int(qdict, "integer"), =3D=3D, value_int= + i); @@ -342,7 +342,7 @@ static void test_visitor_out_any(TestOutputVisitorData = *data, qobj =3D QOBJECT(qnum_from_int(-42)); visit_type_any(data->ov, NULL, &qobj, &error_abort); - qnum =3D qobject_to_qnum(visitor_get(data)); + qnum =3D qobject_to(QNum, visitor_get(data)); g_assert(qnum); g_assert(qnum_get_try_int(qnum, &val)); g_assert_cmpint(val, =3D=3D, -42); @@ -356,16 +356,16 @@ static void test_visitor_out_any(TestOutputVisitorDat= a *data, qobj =3D QOBJECT(qdict); visit_type_any(data->ov, NULL, &qobj, &error_abort); qobject_decref(qobj); - qdict =3D qobject_to_qdict(visitor_get(data)); + qdict =3D qobject_to(QDict, visitor_get(data)); g_assert(qdict); - qnum =3D qobject_to_qnum(qdict_get(qdict, "integer")); + qnum =3D qobject_to(QNum, qdict_get(qdict, "integer")); g_assert(qnum); g_assert(qnum_get_try_int(qnum, &val)); g_assert_cmpint(val, =3D=3D, -42); - qbool =3D qobject_to_qbool(qdict_get(qdict, "boolean")); + qbool =3D qobject_to(QBool, qdict_get(qdict, "boolean")); g_assert(qbool); g_assert(qbool_get_bool(qbool) =3D=3D true); - qstring =3D qobject_to_qstring(qdict_get(qdict, "string")); + qstring =3D qobject_to(QString, qdict_get(qdict, "string")); g_assert(qstring); g_assert_cmpstr(qstring_get_str(qstring), =3D=3D, "foo"); } @@ -382,7 +382,7 @@ static void test_visitor_out_union_flat(TestOutputVisit= orData *data, tmp->u.value1.boolean =3D true; visit_type_UserDefFlatUnion(data->ov, NULL, &tmp, &error_abort); - qdict =3D qobject_to_qdict(visitor_get(data)); + qdict =3D qobject_to(QDict, visitor_get(data)); g_assert(qdict); g_assert_cmpstr(qdict_get_str(qdict, "enum1"), =3D=3D, "value1"); g_assert_cmpstr(qdict_get_str(qdict, "string"), =3D=3D, "str"); @@ -406,7 +406,7 @@ static void test_visitor_out_alternate(TestOutputVisito= rData *data, tmp->u.i =3D 42; visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort); - qnum =3D qobject_to_qnum(visitor_get(data)); + qnum =3D qobject_to(QNum, visitor_get(data)); g_assert(qnum); g_assert(qnum_get_try_int(qnum, &val)); g_assert_cmpint(val, =3D=3D, 42); @@ -419,7 +419,7 @@ static void test_visitor_out_alternate(TestOutputVisito= rData *data, tmp->u.e =3D ENUM_ONE_VALUE1; visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort); - qstr =3D qobject_to_qstring(visitor_get(data)); + qstr =3D qobject_to(QString, visitor_get(data)); g_assert(qstr); g_assert_cmpstr(qstring_get_str(qstr), =3D=3D, "value1"); @@ -444,7 +444,7 @@ static void test_visitor_out_alternate(TestOutputVisito= rData *data, tmp->u.udfu.u.value1.boolean =3D true; visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort); - qdict =3D qobject_to_qdict(visitor_get(data)); + qdict =3D qobject_to(QDict, visitor_get(data)); g_assert(qdict); g_assert_cmpint(qdict_size(qdict), =3D=3D, 4); g_assert_cmpint(qdict_get_int(qdict, "integer"), =3D=3D, 1); @@ -466,7 +466,7 @@ static void test_visitor_out_null(TestOutputVisitorData= *data, visit_type_null(data->ov, "a", &null, &error_abort); visit_check_struct(data->ov, &error_abort); visit_end_struct(data->ov, NULL); - qdict =3D qobject_to_qdict(visitor_get(data)); + qdict =3D qobject_to(QDict, visitor_get(data)); g_assert(qdict); g_assert_cmpint(qdict_size(qdict), =3D=3D, 1); nil =3D qdict_get(qdict, "a"); @@ -610,10 +610,10 @@ static void check_native_list(QObject *qobj, QList *qlist; int i; - qdict =3D qobject_to_qdict(qobj); + qdict =3D qobject_to(QDict, qobj); g_assert(qdict); g_assert(qdict_haskey(qdict, "data")); - qlist =3D qlist_copy(qobject_to_qlist(qdict_get(qdict, "data"))); + qlist =3D qlist_copy(qobject_to(QList, qdict_get(qdict, "data"))); switch (kind) { case USER_DEF_NATIVE_LIST_UNION_KIND_U8: @@ -627,7 +627,7 @@ static void check_native_list(QObject *qobj, tmp =3D qlist_peek(qlist); g_assert(tmp); - qvalue =3D qobject_to_qnum(tmp); + qvalue =3D qobject_to(QNum, tmp); g_assert(qnum_get_try_uint(qvalue, &val)); g_assert_cmpint(val, =3D=3D, i); qobject_decref(qlist_pop(qlist)); @@ -651,7 +651,7 @@ static void check_native_list(QObject *qobj, tmp =3D qlist_peek(qlist); g_assert(tmp); - qvalue =3D qobject_to_qnum(tmp); + qvalue =3D qobject_to(QNum, tmp); g_assert(qnum_get_try_int(qvalue, &val)); g_assert_cmpint(val, =3D=3D, i); qobject_decref(qlist_pop(qlist)); @@ -663,7 +663,7 @@ static void check_native_list(QObject *qobj, QBool *qvalue; tmp =3D qlist_peek(qlist); g_assert(tmp); - qvalue =3D qobject_to_qbool(tmp); + qvalue =3D qobject_to(QBool, tmp); g_assert_cmpint(qbool_get_bool(qvalue), =3D=3D, i % 3 =3D=3D 0= ); qobject_decref(qlist_pop(qlist)); } @@ -675,7 +675,7 @@ static void check_native_list(QObject *qobj, gchar str[8]; tmp =3D qlist_peek(qlist); g_assert(tmp); - qvalue =3D qobject_to_qstring(tmp); + qvalue =3D qobject_to(QString, tmp); sprintf(str, "%d", i); g_assert_cmpstr(qstring_get_str(qvalue), =3D=3D, str); qobject_decref(qlist_pop(qlist)); @@ -690,7 +690,7 @@ static void check_native_list(QObject *qobj, tmp =3D qlist_peek(qlist); g_assert(tmp); - qvalue =3D qobject_to_qnum(tmp); + qvalue =3D qobject_to(QNum, tmp); g_string_printf(double_expected, "%.6f", (double)i / 3); g_string_printf(double_actual, "%.6f", qnum_get_double(qvalue)= ); g_assert_cmpstr(double_actual->str, =3D=3D, double_expected->s= tr); diff --git a/tests/test-x86-cpuid-compat.c b/tests/test-x86-cpuid-compat.c index 495dd1e7ef3..02e41843fc9 100644 --- a/tests/test-x86-cpuid-compat.c +++ b/tests/test-x86-cpuid-compat.c @@ -17,7 +17,7 @@ static char *get_cpu0_qom_path(void) g_assert(qdict_haskey(resp, "return")); ret =3D qdict_get_qlist(resp, "return"); - cpu0 =3D qobject_to_qdict(qlist_peek(ret)); + cpu0 =3D qobject_to(QDict, qlist_peek(ret)); path =3D g_strdup(qdict_get_str(cpu0, "qom_path")); QDECREF(resp); return path; @@ -38,7 +38,7 @@ static QObject *qom_get(const char *path, const char *pro= p) #ifdef CONFIG_HAS_GLIB_SUBPROCESS_TESTS static bool qom_get_bool(const char *path, const char *prop) { - QBool *value =3D qobject_to_qbool(qom_get(path, prop)); + QBool *value =3D qobject_to(QBool, qom_get(path, prop)); bool b =3D qbool_get_bool(value); QDECREF(value); @@ -61,7 +61,7 @@ static void test_cpuid_prop(const void *data) qtest_start(args->cmdline); path =3D get_cpu0_qom_path(); - value =3D qobject_to_qnum(qom_get(path, args->property)); + value =3D qobject_to(QNum, qom_get(path, args->property)); g_assert(qnum_get_try_int(value, &val)); g_assert_cmpint(val, =3D=3D, args->expected_value); qtest_end(); @@ -105,7 +105,7 @@ static uint32_t get_feature_word(QList *features, uint3= 2_t eax, uint32_t ecx, const QListEntry *e; for (e =3D qlist_first(features); e; e =3D qlist_next(e)) { - QDict *w =3D qobject_to_qdict(qlist_entry_obj(e)); + QDict *w =3D qobject_to(QDict, qlist_entry_obj(e)); const char *rreg =3D qdict_get_str(w, "cpuid-register"); uint32_t reax =3D qdict_get_int(w, "cpuid-input-eax"); bool has_ecx =3D qdict_haskey(w, "cpuid-input-ecx"); @@ -116,8 +116,9 @@ static uint32_t get_feature_word(QList *features, uint3= 2_t eax, uint32_t ecx, recx =3D qdict_get_int(w, "cpuid-input-ecx"); } if (eax =3D=3D reax && (!has_ecx || ecx =3D=3D recx) && !strcmp(rr= eg, reg)) { - g_assert(qnum_get_try_int(qobject_to_qnum(qdict_get(w, "featur= es")), - &val)); + g_assert(qnum_get_try_int(qobject_to(QNum, + qdict_get(w, "features")), + &val)); return val; } } @@ -133,8 +134,8 @@ static void test_feature_flag(const void *data) qtest_start(args->cmdline); path =3D get_cpu0_qom_path(); - present =3D qobject_to_qlist(qom_get(path, "feature-words")); - filtered =3D qobject_to_qlist(qom_get(path, "filtered-features")); + present =3D qobject_to(QList, qom_get(path, "feature-words")); + filtered =3D qobject_to(QList, qom_get(path, "filtered-features")); value =3D get_feature_word(present, args->in_eax, args->in_ecx, args->= reg); value |=3D get_feature_word(filtered, args->in_eax, args->in_ecx, args= ->reg); qtest_end(); diff --git a/util/keyval.c b/util/keyval.c index 212ae90d003..1c7351a233e 100644 --- a/util/keyval.c +++ b/util/keyval.c @@ -221,7 +221,7 @@ static const char *keyval_parse_one(QDict *qdict, const= char *params, if (!next) { return NULL; } - cur =3D qobject_to_qdict(next); + cur =3D qobject_to(QDict, next); assert(cur); } @@ -314,7 +314,7 @@ static QObject *keyval_listify(QDict *cur, GSList *key_= of_cur, Error **errp) has_member =3D true; } - qdict =3D qobject_to_qdict(ent->value); + qdict =3D qobject_to(QDict, ent->value); if (!qdict) { continue; } diff --git a/util/qemu-config.c b/util/qemu-config.c index c651c4826e7..20f7d1429d8 100644 --- a/util/qemu-config.c +++ b/util/qemu-config.c @@ -528,7 +528,7 @@ static void config_parse_qdict_section(QDict *options, = QemuOptsList *opts, } QLIST_FOREACH_ENTRY(list, list_entry) { - QDict *section =3D qobject_to_qdict(qlist_entry_obj(list_entry= )); + QDict *section =3D qobject_to(QDict, qlist_entry_obj(list_entr= y)); char *opt_name; if (!section) { diff --git a/util/qemu-option.c b/util/qemu-option.c index 2b412eff5e5..d0756fda58d 100644 --- a/util/qemu-option.c +++ b/util/qemu-option.c @@ -919,15 +919,15 @@ static void qemu_opts_from_qdict_1(const char *key, Q= Object *obj, void *opaque) switch (qobject_type(obj)) { case QTYPE_QSTRING: - value =3D qstring_get_str(qobject_to_qstring(obj)); + value =3D qstring_get_str(qobject_to(QString, obj)); break; case QTYPE_QNUM: - tmp =3D qnum_to_string(qobject_to_qnum(obj)); + tmp =3D qnum_to_string(qobject_to(QNum, obj)); value =3D tmp; break; case QTYPE_QBOOL: pstrcpy(buf, sizeof(buf), - qbool_get_bool(qobject_to_qbool(obj)) ? "on" : "off"); + qbool_get_bool(qobject_to(QBool, obj)) ? "on" : "off"); value =3D buf; break; default: --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 1520880535809748.7162592066627; Mon, 12 Mar 2018 11:48:55 -0700 (PDT) Received: from localhost ([::1]:33947 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSVA-0005q3-Te for importer@patchew.org; Mon, 12 Mar 2018 14:48:52 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45106) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJQ-0000cd-7P for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:45 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJO-0005tu-Nd for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:44 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:33592 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 1evSJO-0005sh-I9 for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:42 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2BB44814DF58 for ; Mon, 12 Mar 2018 18:36:42 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id 754C8215CDAC; Mon, 12 Mar 2018 18:36:41 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:35:59 -0500 Message-Id: <20180312183628.394722-9-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 12 Mar 2018 18:36:42 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 12 Mar 2018 18:36:42 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@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/36] qapi: Remove qobject_to_X() functions 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: Markus Armbruster , Max Reitz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Max Reitz They are no longer needed now. Signed-off-by: Max Reitz Reviewed-by: Alberto Garcia Message-Id: <20180224154033.29559-5-mreitz@redhat.com> Reviewed-by: Eric Blake Signed-off-by: Eric Blake --- include/qapi/qmp/qbool.h | 1 - include/qapi/qmp/qdict.h | 1 - include/qapi/qmp/qlist.h | 1 - include/qapi/qmp/qnum.h | 1 - include/qapi/qmp/qstring.h | 1 - qobject/qbool.c | 11 ----------- qobject/qdict.c | 11 ----------- qobject/qlist.c | 11 ----------- qobject/qnum.c | 11 ----------- qobject/qstring.c | 11 ----------- 10 files changed, 60 deletions(-) diff --git a/include/qapi/qmp/qbool.h b/include/qapi/qmp/qbool.h index 629c508d34f..b9a44a1bfe0 100644 --- a/include/qapi/qmp/qbool.h +++ b/include/qapi/qmp/qbool.h @@ -23,7 +23,6 @@ struct QBool { QBool *qbool_from_bool(bool value); bool qbool_get_bool(const QBool *qb); -QBool *qobject_to_qbool(const QObject *obj); bool qbool_is_equal(const QObject *x, const QObject *y); void qbool_destroy_obj(QObject *obj); diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h index 7c6d8445495..2cc3e906f7b 100644 --- a/include/qapi/qmp/qdict.h +++ b/include/qapi/qmp/qdict.h @@ -39,7 +39,6 @@ void qdict_put_obj(QDict *qdict, const char *key, QObject= *value); void qdict_del(QDict *qdict, const char *key); int qdict_haskey(const QDict *qdict, const char *key); QObject *qdict_get(const QDict *qdict, const char *key); -QDict *qobject_to_qdict(const QObject *obj); bool qdict_is_equal(const QObject *x, const QObject *y); void qdict_iter(const QDict *qdict, void (*iter)(const char *key, QObject *obj, void *opaque), diff --git a/include/qapi/qmp/qlist.h b/include/qapi/qmp/qlist.h index 5fd976a3981..5c673acb060 100644 --- a/include/qapi/qmp/qlist.h +++ b/include/qapi/qmp/qlist.h @@ -53,7 +53,6 @@ QObject *qlist_pop(QList *qlist); QObject *qlist_peek(QList *qlist); int qlist_empty(const QList *qlist); size_t qlist_size(const QList *qlist); -QList *qobject_to_qlist(const QObject *obj); bool qlist_is_equal(const QObject *x, const QObject *y); void qlist_destroy_obj(QObject *obj); diff --git a/include/qapi/qmp/qnum.h b/include/qapi/qmp/qnum.h index 15e3971c7f1..3e47475b2cb 100644 --- a/include/qapi/qmp/qnum.h +++ b/include/qapi/qmp/qnum.h @@ -68,7 +68,6 @@ double qnum_get_double(QNum *qn); char *qnum_to_string(QNum *qn); -QNum *qobject_to_qnum(const QObject *obj); bool qnum_is_equal(const QObject *x, const QObject *y); void qnum_destroy_obj(QObject *obj); diff --git a/include/qapi/qmp/qstring.h b/include/qapi/qmp/qstring.h index 98070ef3d6a..b72843fc1b0 100644 --- a/include/qapi/qmp/qstring.h +++ b/include/qapi/qmp/qstring.h @@ -30,7 +30,6 @@ const char *qstring_get_str(const QString *qstring); void qstring_append_int(QString *qstring, int64_t value); void qstring_append(QString *qstring, const char *str); void qstring_append_chr(QString *qstring, int c); -QString *qobject_to_qstring(const QObject *obj); bool qstring_is_equal(const QObject *x, const QObject *y); void qstring_destroy_obj(QObject *obj); diff --git a/qobject/qbool.c b/qobject/qbool.c index 5be6277cca8..b58249925c2 100644 --- a/qobject/qbool.c +++ b/qobject/qbool.c @@ -39,17 +39,6 @@ bool qbool_get_bool(const QBool *qb) return qb->value; } -/** - * qobject_to_qbool(): Convert a QObject into a QBool - */ -QBool *qobject_to_qbool(const QObject *obj) -{ - if (!obj || qobject_type(obj) !=3D QTYPE_QBOOL) { - return NULL; - } - return container_of(obj, QBool, base); -} - /** * qbool_is_equal(): Test whether the two QBools are equal */ diff --git a/qobject/qdict.c b/qobject/qdict.c index 1e588123d00..45c8b53361f 100644 --- a/qobject/qdict.c +++ b/qobject/qdict.c @@ -37,17 +37,6 @@ QDict *qdict_new(void) return qdict; } -/** - * qobject_to_qdict(): Convert a QObject into a QDict - */ -QDict *qobject_to_qdict(const QObject *obj) -{ - if (!obj || qobject_type(obj) !=3D QTYPE_QDICT) { - return NULL; - } - return container_of(obj, QDict, base); -} - /** * tdb_hash(): based on the hash agorithm from gdbm, via tdb * (from module-init-tools) diff --git a/qobject/qlist.c b/qobject/qlist.c index 77f19ffda78..954fe983751 100644 --- a/qobject/qlist.c +++ b/qobject/qlist.c @@ -151,17 +151,6 @@ size_t qlist_size(const QList *qlist) return count; } -/** - * qobject_to_qlist(): Convert a QObject into a QList - */ -QList *qobject_to_qlist(const QObject *obj) -{ - if (!obj || qobject_type(obj) !=3D QTYPE_QLIST) { - return NULL; - } - return container_of(obj, QList, base); -} - /** * qlist_is_equal(): Test whether the two QLists are equal * diff --git a/qobject/qnum.c b/qobject/qnum.c index ea091cfaa4b..1501c828323 100644 --- a/qobject/qnum.c +++ b/qobject/qnum.c @@ -199,17 +199,6 @@ char *qnum_to_string(QNum *qn) return NULL; } -/** - * qobject_to_qnum(): Convert a QObject into a QNum - */ -QNum *qobject_to_qnum(const QObject *obj) -{ - if (!obj || qobject_type(obj) !=3D QTYPE_QNUM) { - return NULL; - } - return container_of(obj, QNum, base); -} - /** * qnum_is_equal(): Test whether the two QNums are equal * diff --git a/qobject/qstring.c b/qobject/qstring.c index 2b2153206df..8bae529ef79 100644 --- a/qobject/qstring.c +++ b/qobject/qstring.c @@ -105,17 +105,6 @@ void qstring_append_chr(QString *qstring, int c) qstring->string[qstring->length] =3D 0; } -/** - * qobject_to_qstring(): Convert a QObject to a QString - */ -QString *qobject_to_qstring(const QObject *obj) -{ - if (!obj || qobject_type(obj) !=3D QTYPE_QSTRING) { - return NULL; - } - return container_of(obj, QString, base); -} - /** * qstring_get_str(): Return a pointer to the stored string * --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 1520880912404674.4993275349062; Mon, 12 Mar 2018 11:55:12 -0700 (PDT) Received: from localhost ([::1]:33987 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSbH-0002hK-Kw for importer@patchew.org; Mon, 12 Mar 2018 14:55:11 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45120) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJQ-0000d5-Jm for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:46 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJP-0005uf-Ay for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:44 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:33594 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 1evSJP-0005u8-4X for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:43 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B60DE814DF58; Mon, 12 Mar 2018 18:36:42 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4FE12215CDAC; Mon, 12 Mar 2018 18:36:42 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:36:00 -0500 Message-Id: <20180312183628.394722-10-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 12 Mar 2018 18:36:42 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 12 Mar 2018 18:36:42 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@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/36] qapi: Make more of qobject_to() 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: Michael Roth , Markus Armbruster , Max Reitz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Max Reitz This patch reworks some places which use either qobject_type() checks plus qobject_to(), where the latter alone is sufficient, or NULL checks plus qobject_type() checks where we can simply do a qobject_to() !=3D NULL check. Signed-off-by: Max Reitz Reviewed-by: Alberto Garcia Message-Id: <20180224154033.29559-6-mreitz@redhat.com> Reviewed-by: Eric Blake [eblake: rebase to qobject_to() parameter ordering] Signed-off-by: Eric Blake --- qapi/qobject-input-visitor.c | 4 ++-- qobject/json-parser.c | 13 +++++++------ qobject/qdict.c | 20 +++++++++++--------- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c index 0b5293385e5..a7569d5dcef 100644 --- a/qapi/qobject-input-visitor.c +++ b/qapi/qobject-input-visitor.c @@ -339,7 +339,7 @@ static GenericList *qobject_input_next_list(Visitor *v,= GenericList *tail, QObjectInputVisitor *qiv =3D to_qiv(v); StackObject *tos =3D QSLIST_FIRST(&qiv->stack); - assert(tos && tos->obj && qobject_type(tos->obj) =3D=3D QTYPE_QLIST); + assert(tos && qobject_to(QList, tos->obj)); if (!tos->entry) { return NULL; @@ -353,7 +353,7 @@ static void qobject_input_check_list(Visitor *v, Error = **errp) QObjectInputVisitor *qiv =3D to_qiv(v); StackObject *tos =3D QSLIST_FIRST(&qiv->stack); - assert(tos && tos->obj && qobject_type(tos->obj) =3D=3D QTYPE_QLIST); + assert(tos && qobject_to(QList, tos->obj)); if (tos->entry) { error_setg(errp, "Only %u list elements expected in %s", diff --git a/qobject/json-parser.c b/qobject/json-parser.c index 055c7f0272a..769b960c9fe 100644 --- a/qobject/json-parser.c +++ b/qobject/json-parser.c @@ -276,7 +276,8 @@ static void parser_context_free(JSONParserContext *ctxt) */ static int parse_pair(JSONParserContext *ctxt, QDict *dict, va_list *ap) { - QObject *key =3D NULL, *value; + QObject *value; + QString *key =3D NULL; JSONToken *peek, *token; peek =3D parser_context_peek_token(ctxt); @@ -285,8 +286,8 @@ static int parse_pair(JSONParserContext *ctxt, QDict *d= ict, va_list *ap) goto out; } - key =3D parse_value(ctxt, ap); - if (!key || qobject_type(key) !=3D QTYPE_QSTRING) { + key =3D qobject_to(QString, parse_value(ctxt, ap)); + if (!key) { parse_error(ctxt, peek, "key is not a string in object"); goto out; } @@ -308,14 +309,14 @@ static int parse_pair(JSONParserContext *ctxt, QDict = *dict, va_list *ap) goto out; } - qdict_put_obj(dict, qstring_get_str(qobject_to(QString, key)), value); + qdict_put_obj(dict, qstring_get_str(key), value); - qobject_decref(key); + QDECREF(key); return 0; out: - qobject_decref(key); + QDECREF(key); return -1; } diff --git a/qobject/qdict.c b/qobject/qdict.c index 45c8b53361f..d1997a0d8af 100644 --- a/qobject/qdict.c +++ b/qobject/qdict.c @@ -882,18 +882,20 @@ QObject *qdict_crumple(const QDict *src, Error **errp) child =3D qdict_get(two_level, prefix); if (suffix) { - if (child) { - if (qobject_type(child) !=3D QTYPE_QDICT) { + 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; } - } else { - child =3D QOBJECT(qdict_new()); - qdict_put_obj(two_level, prefix, child); + + child_dict =3D qdict_new(); + qdict_put_obj(two_level, prefix, QOBJECT(child_dict)); } + qobject_incref(ent->value); - qdict_put_obj(qobject_to(QDict, child), suffix, ent->value); + qdict_put_obj(child_dict, suffix, ent->value); } else { if (child) { error_setg(errp, "Key %s prefix is already set as a dict", @@ -913,9 +915,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)) { - - if (qobject_type(ent->value) =3D=3D QTYPE_QDICT) { - child =3D qdict_crumple(qobject_to(QDict, ent->value), errp); + QDict *dict =3D qobject_to(QDict, ent->value); + if (dict) { + child =3D qdict_crumple(dict, errp); if (!child) { goto error; } --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 1520881910493722.4438123771757; Mon, 12 Mar 2018 12:11:50 -0700 (PDT) Received: from localhost ([::1]:34104 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSrN-0000Dv-Gc for importer@patchew.org; Mon, 12 Mar 2018 15:11:49 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45250) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJU-0000hy-Oh for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJT-0005xp-KR for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:48 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:49254 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 1evSJP-0005ul-RK; Mon, 12 Mar 2018 14:36:43 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 6244B4023BB3; Mon, 12 Mar 2018 18:36:43 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id DF278215CDAC; Mon, 12 Mar 2018 18:36:42 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:36:01 -0500 Message-Id: <20180312183628.394722-11-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 12 Mar 2018 18:36:43 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 12 Mar 2018 18:36:43 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@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/36] block: Handle null backing link X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Markus Armbruster , "open list:Block layer core" , Max Reitz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Max Reitz Instead of converting all "backing": null instances into "backing": "", handle a null value directly in bdrv_open_inherit(). This enables explicitly null backing links for json:{} filenames. Signed-off-by: Max Reitz Reviewed-by: Alberto Garcia Message-Id: <20180224154033.29559-7-mreitz@redhat.com> Reviewed-by: Eric Blake [eblake: rebase to qobject_to() parameter order and qapi headers split] Signed-off-by: Eric Blake --- block.c | 5 ++++- blockdev.c | 14 -------------- tests/qemu-iotests/089 | 20 ++++++++++++++++++++ tests/qemu-iotests/089.out | 8 ++++++++ 4 files changed, 32 insertions(+), 15 deletions(-) diff --git a/block.c b/block.c index cd74da3a601..b673a004daf 100644 --- a/block.c +++ b/block.c @@ -33,6 +33,7 @@ #include "qapi/error.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qjson.h" +#include "qapi/qmp/qnull.h" #include "qapi/qmp/qstring.h" #include "qapi/qobject-output-visitor.h" #include "qapi/qapi-visit-block-core.h" @@ -2645,7 +2646,9 @@ static BlockDriverState *bdrv_open_inherit(const char= *filename, /* See cautionary note on accessing @options above */ backing =3D qdict_get_try_str(options, "backing"); - if (backing && *backing =3D=3D '\0') { + if (qobject_to(QNull, qdict_get(options, "backing")) !=3D NULL || + (backing && *backing =3D=3D '\0')) + { flags |=3D BDRV_O_NO_BACKING; qdict_del(options, "backing"); } diff --git a/blockdev.c b/blockdev.c index c9a212b3149..6a751996022 100644 --- a/blockdev.c +++ b/blockdev.c @@ -3973,7 +3973,6 @@ void qmp_blockdev_add(BlockdevOptions *options, Error= **errp) QObject *obj; Visitor *v =3D qobject_output_visitor_new(&obj); QDict *qdict; - const QDictEntry *ent; Error *local_err =3D NULL; visit_type_BlockdevOptions(v, NULL, &options, &local_err); @@ -3987,19 +3986,6 @@ void qmp_blockdev_add(BlockdevOptions *options, Erro= r **errp) qdict_flatten(qdict); - /* - * Rewrite "backing": null to "backing": "" - * TODO Rewrite "" to null instead, and perhaps not even here - */ - for (ent =3D qdict_first(qdict); ent; ent =3D qdict_next(qdict, ent)) { - char *dot =3D strrchr(ent->key, '.'); - - if (!strcmp(dot ? dot + 1 : ent->key, "backing") - && qobject_type(ent->value) =3D=3D QTYPE_QNULL) { - qdict_put(qdict, ent->key, qstring_new()); - } - } - if (!qdict_get_try_str(qdict, "node-name")) { error_setg(errp, "'node-name' must be specified for the root node"= ); goto fail; diff --git a/tests/qemu-iotests/089 b/tests/qemu-iotests/089 index 0b059aba905..aa1ba4a98e7 100755 --- a/tests/qemu-iotests/089 +++ b/tests/qemu-iotests/089 @@ -82,6 +82,26 @@ $QEMU_IO_PROG --cache $CACHEMODE \ $QEMU_IO -c 'read -P 42 0 512' "$TEST_IMG" | _filter_qemu_io +echo +echo "=3D=3D=3D Testing correct handling of 'backing':null =3D=3D=3D" +echo + +_make_test_img -b "$TEST_IMG.base" $IMG_SIZE + +# This should read 42 +$QEMU_IO -c 'read -P 42 0 512' "$TEST_IMG" | _filter_qemu_io + +# This should read 0 +$QEMU_IO -c 'read -P 0 0 512' "json:{\ + 'driver': '$IMGFMT', + 'file': { + 'driver': 'file', + 'filename': '$TEST_IMG' + }, + 'backing': null +}" | _filter_qemu_io + + # Taken from test 071 echo echo "=3D=3D=3D Testing blkdebug =3D=3D=3D" diff --git a/tests/qemu-iotests/089.out b/tests/qemu-iotests/089.out index 0bf5a13ec18..89e3e4340a4 100644 --- a/tests/qemu-iotests/089.out +++ b/tests/qemu-iotests/089.out @@ -19,6 +19,14 @@ Pattern verification failed at offset 0, 512 bytes read 512/512 bytes at offset 0 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +=3D=3D=3D Testing correct handling of 'backing':null =3D=3D=3D + +Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D67108864 backing_file= =3DTEST_DIR/t.IMGFMT.base +read 512/512 bytes at offset 0 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 512/512 bytes at offset 0 +512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) + =3D=3D=3D Testing blkdebug =3D=3D=3D Formatting 'TEST_DIR/t.IMGFMT', fmt=3DIMGFMT size=3D67108864 --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 1520881445192194.29619849482958; Mon, 12 Mar 2018 12:04:05 -0700 (PDT) Received: from localhost ([::1]:34042 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSjs-0001xi-7U for importer@patchew.org; Mon, 12 Mar 2018 15:04:04 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45249) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJU-0000hx-OQ for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJT-0005xu-MJ for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:48 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:58828 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 1evSJQ-0005v2-G4; Mon, 12 Mar 2018 14:36:44 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 0D6EE4040073; Mon, 12 Mar 2018 18:36:44 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8B088215CDAC; Mon, 12 Mar 2018 18:36:43 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:36:02 -0500 Message-Id: <20180312183628.394722-12-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Mon, 12 Mar 2018 18:36:44 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Mon, 12 Mar 2018 18:36:44 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@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/36] block: Deprecate "backing": "" X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Markus Armbruster , "open list:Block layer core" , Max Reitz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Max Reitz We have a clear replacement, so let's deprecate it. Signed-off-by: Max Reitz Reviewed-by: Eric Blake Reviewed-by: Alberto Garcia Message-Id: <20180224154033.29559-8-mreitz@redhat.com> Signed-off-by: Eric Blake --- qemu-doc.texi | 7 +++++++ qapi/block-core.json | 4 ++-- block.c | 4 ++++ qemu-options.hx | 4 ++-- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/qemu-doc.texi b/qemu-doc.texi index 39e38c87ecf..f81fe40d61f 100644 --- a/qemu-doc.texi +++ b/qemu-doc.texi @@ -2779,6 +2779,13 @@ support page sizes < 4096 any longer. The ``xlnx-ep108'' machine has been replaced by the ``xlnx-zcu102'' machin= e. The ``xlnx-zcu102'' machine has the same features and capabilites in QEMU. +@section Block device options + +@subsection "backing": "" (since 2.12.0) + +In order to prevent QEMU from automatically opening an image's backing +chain, use ``"backing": null'' instead. + @node License @appendix License diff --git a/qapi/block-core.json b/qapi/block-core.json index 524d51567a5..55dcc8bd85a 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -1090,7 +1090,7 @@ # @overlay: reference to the existing block device that will become # the overlay of @node, as part of creating the snapshot. # It must not have a current backing file (this can be -# achieved by passing "backing": "" to blockdev-add). +# achieved by passing "backing": null to blockdev-add). # # Since: 2.5 ## @@ -1238,7 +1238,7 @@ # "node-name": "node1534", # "file": { "driver": "file", # "filename": "hd1.qcow2" }, -# "backing": "" } } +# "backing": null } } # # <- { "return": {} } # diff --git a/block.c b/block.c index b673a004daf..e11f1355374 100644 --- a/block.c +++ b/block.c @@ -2649,6 +2649,10 @@ static BlockDriverState *bdrv_open_inherit(const cha= r *filename, if (qobject_to(QNull, qdict_get(options, "backing")) !=3D NULL || (backing && *backing =3D=3D '\0')) { + if (backing) { + warn_report("Use of \"backing\": \"\" is deprecated; " + "use \"backing\": null instead"); + } flags |=3D BDRV_O_NO_BACKING; qdict_del(options, "backing"); } diff --git a/qemu-options.hx b/qemu-options.hx index 6585058c6cd..991ff4016db 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -740,8 +740,8 @@ Reference to or definition of the data source block dri= ver node @item backing Reference to or definition of the backing file block device (default is ta= ken -from the image file). It is allowed to pass an empty string here in order = to -disable the default backing file. +from the image file). It is allowed to pass @code{null} here in order to d= isable +the default backing file. @item lazy-refcounts Whether to enable the lazy refcounts feature (on/off; default is taken fro= m the --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 1520881253221193.86943899951166; Mon, 12 Mar 2018 12:00:53 -0700 (PDT) Received: from localhost ([::1]:34026 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSgl-0007p2-RE for importer@patchew.org; Mon, 12 Mar 2018 15:00:51 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45189) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJS-0000fS-VC for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:48 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJR-0005w2-9J for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:46 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:33598 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 1evSJR-0005vt-2i for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:45 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A4CBF814DF58; Mon, 12 Mar 2018 18:36:44 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id 33C2A215CDAC; Mon, 12 Mar 2018 18:36:44 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:36:03 -0500 Message-Id: <20180312183628.394722-13-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 12 Mar 2018 18:36:44 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 12 Mar 2018 18:36:44 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@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/36] docs: update QMP documents for OOB commands 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: Markus Armbruster , Peter Xu , Michael Roth 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: Peter Xu Update both the developer and spec for the new QMP OOB (Out-Of-Band) command. Signed-off-by: Peter Xu Message-Id: <20180309090006.10018-2-peterx@redhat.com> Reviewed-by: Eric Blake [eblake: grammar tweaks] Signed-off-by: Eric Blake --- docs/devel/qapi-code-gen.txt | 58 ++++++++++++++++++++++++++++++++++++++++= ---- docs/interop/qmp-spec.txt | 36 +++++++++++++++++++++------ 2 files changed, 82 insertions(+), 12 deletions(-) diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt index 99d81230e26..a569d247455 100644 --- a/docs/devel/qapi-code-gen.txt +++ b/docs/devel/qapi-code-gen.txt @@ -554,9 +554,12 @@ following example objects: =3D=3D=3D Commands =3D=3D=3D +--- General Command Layout --- + Usage: { 'command': STRING, '*data': COMPLEX-TYPE-NAME-OR-DICT, '*returns': TYPE-NAME, '*boxed': true, - '*gen': false, '*success-response': false } + '*gen': false, '*success-response': false, + '*allow-oob': true } Commands are defined by using a dictionary containing several members, where three members are most common. The 'command' member is a @@ -636,6 +639,49 @@ possible, the command expression should include the op= tional key 'success-response' with boolean value false. So far, only QGA makes use of this member. +A command can be declared to support Out-Of-Band (OOB) execution. By +default, commands do not support OOB. To declare a command that +supports it, the schema includes an extra 'allow-oob' field. For +example: + + { 'command': 'migrate_recover', + 'data': { 'uri': 'str' }, 'allow-oob': true } + +To execute a command with out-of-band priority, the client specifies +the "control" field in the request, with "run-oob" set to +true. Example: + + =3D> { "execute": "command-support-oob", + "arguments": { ... }, + "control": { "run-oob": true } } + <=3D { "return": { } } + +Without it, even the commands that support out-of-band execution will +still be run in-band. + +Under normal QMP command execution, the following apply to each +command: + +- They are executed in order, +- They run only in main thread of QEMU, +- They have the BQL taken during execution. + +When a command is executed with OOB, the following changes occur: + +- They can be completed before a pending in-band command, +- They run in a dedicated monitor thread, +- They do not take the BQL during execution. + +OOB command handlers must satisfy the following conditions: + +- It executes extremely fast, +- It does not take any lock, or, it can take very small locks if all + critical regions also follow the rules for OOB command handler code, +- It does not invoke system calls that may block, +- It does not access guest RAM that may block when userfaultfd is + enabled for postcopy live migration. + +If in doubt, do not implement OOB execution support. =3D=3D=3D Events =3D=3D=3D @@ -739,10 +785,12 @@ references by name. QAPI schema definitions not reachable that way are omitted. The SchemaInfo for a command has meta-type "command", and variant -members "arg-type" and "ret-type". On the wire, the "arguments" -member of a client's "execute" command must conform to the object type -named by "arg-type". The "return" member that the server passes in a -success response conforms to the type named by "ret-type". +members "arg-type", "ret-type" and "allow-oob". On the wire, the +"arguments" member of a client's "execute" command must conform to the +object type named by "arg-type". The "return" member that the server +passes in a success response conforms to the type named by +"ret-type". When "allow-oob" is set, it means the command supports +out-of-band execution. If the command takes no arguments, "arg-type" names an object type without members. Likewise, if the command returns nothing, "ret-type" diff --git a/docs/interop/qmp-spec.txt b/docs/interop/qmp-spec.txt index f8b53560159..6fa193a80bc 100644 --- a/docs/interop/qmp-spec.txt +++ b/docs/interop/qmp-spec.txt @@ -83,16 +83,27 @@ The greeting message format is: 2.2.1 Capabilities ------------------ -As of the date this document was last revised, no server or client -capability strings have been defined. +Currently supported capabilities are: +- "oob": the QMP server supports "Out-Of-Band" (OOB) command + execution. For more details, please see the "run-oob" parameter in + the "Issuing Commands" section below. Not all commands allow this + "oob" execution. The "query-qmp-schema" command can be used to + inspect which commands support "oob" execution. + +QMP clients can get a list of supported QMP capabilities of the QMP +server in the greeting message mentioned above. By default, all the +capabilities are off. To enable any QMP capabilities, the QMP client +needs to send the "qmp_capabilities" command with an extra parameter +for the requested capabilities. 2.3 Issuing Commands -------------------- The format for command execution is: -{ "execute": json-string, "arguments": json-object, "id": json-value } +{ "execute": json-string, "arguments": json-object, "id": json-value, + "control": json-object } Where, @@ -102,10 +113,16 @@ The format for command execution is: required. Each command documents what contents will be considered valid when handling the json-argument - The "id" member is a transaction identification associated with the - command execution, it is optional and will be part of the response if - provided. The "id" member can be any json-value, although most - clients merely use a json-number incremented for each successive - command + command execution. It is required for all commands if the OOB - + capability was enabled at startup, and optional otherwise. The same + "id" field will be part of the response if provided. The "id" member + can be any json-value, although most clients merely use a + json-number incremented for each successive command +- The "control" member is optional, and currently only used for + out-of-band execution. The handling or response of an "oob" command + can overtake prior in-band commands. To enable "oob" handling of a + particular command, just provide a control field with: { "control": + { "run-oob": true } } 2.4 Commands Responses ---------------------- @@ -113,6 +130,11 @@ The format for command execution is: There are two possible responses which the Server will issue as the result of a command execution: success or error. +As long as the commands were issued with a proper "id" field, then the +same "id" field will be attached in the corresponding response message +so that requests and responses can match. Clients should drop all the +responses that have an unknown "id" field. + 2.4.1 success ------------- --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 1520881501556316.986488540648; Mon, 12 Mar 2018 12:05:01 -0700 (PDT) Received: from localhost ([::1]:34054 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSkm-0002py-I8 for importer@patchew.org; Mon, 12 Mar 2018 15:05:00 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45204) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJT-0000g9-D6 for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:48 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJS-0005wr-6a for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:47 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:38326 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 1evSJS-0005wF-0j for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:46 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 718338D6D7 for ; Mon, 12 Mar 2018 18:36:45 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id C9389215CDAC; Mon, 12 Mar 2018 18:36:44 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:36:04 -0500 Message-Id: <20180312183628.394722-14-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Mon, 12 Mar 2018 18:36:45 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Mon, 12 Mar 2018 18:36:45 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@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/36] qobject: introduce qstring_get_try_str() 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: Markus Armbruster , Peter Xu 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: Peter Xu The only difference from qstring_get_str() is that it allows the qstring to be NULL. If so, NULL is returned. CC: Eric Blake CC: Markus Armbruster Reviewed-by: Fam Zheng Reviewed-by: Stefan Hajnoczi Reviewed-by: Eric Blake Signed-off-by: Peter Xu Message-Id: <20180309090006.10018-3-peterx@redhat.com> Signed-off-by: Eric Blake --- include/qapi/qmp/qstring.h | 1 + qobject/qstring.c | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/include/qapi/qmp/qstring.h b/include/qapi/qmp/qstring.h index b72843fc1b0..38c680b7185 100644 --- a/include/qapi/qmp/qstring.h +++ b/include/qapi/qmp/qstring.h @@ -27,6 +27,7 @@ QString *qstring_from_str(const char *str); QString *qstring_from_substr(const char *str, int start, int end); size_t qstring_get_length(const QString *qstring); const char *qstring_get_str(const QString *qstring); +const char *qstring_get_try_str(const QString *qstring); void qstring_append_int(QString *qstring, int64_t value); void qstring_append(QString *qstring, const char *str); void qstring_append_chr(QString *qstring, int c); diff --git a/qobject/qstring.c b/qobject/qstring.c index 8bae529ef79..5777f0af231 100644 --- a/qobject/qstring.c +++ b/qobject/qstring.c @@ -116,6 +116,16 @@ const char *qstring_get_str(const QString *qstring) return qstring->string; } +/** + * qstring_get_try_str(): Return a pointer to the stored string + * + * NOTE: will return NULL if qstring is not provided. + */ +const char *qstring_get_try_str(const QString *qstring) +{ + return qstring ? qstring_get_str(qstring) : NULL; +} + /** * qstring_is_equal(): Test whether the two QStrings are equal */ --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 152088165679758.604239308968886; Mon, 12 Mar 2018 12:07:36 -0700 (PDT) Received: from localhost ([::1]:34072 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSnD-0004vk-0q for importer@patchew.org; Mon, 12 Mar 2018 15:07:31 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45214) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJT-0000gW-Ms for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:48 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJS-0005x4-QZ for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:47 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:40640 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 1evSJS-0005wx-LQ for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:46 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 414B476FB9 for ; Mon, 12 Mar 2018 18:36:46 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id DAAE0215CDAC; Mon, 12 Mar 2018 18:36:45 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:36:05 -0500 Message-Id: <20180312183628.394722-15-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Mon, 12 Mar 2018 18:36:46 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Mon, 12 Mar 2018 18:36:46 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@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/36] qobject: introduce qobject_get_try_str() 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: Markus Armbruster , Peter Xu 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: Peter Xu A quick way to fetch string from qobject when it's a QString. Reviewed-by: Fam Zheng Reviewed-by: Stefan Hajnoczi Signed-off-by: Peter Xu Message-Id: <20180309090006.10018-4-peterx@redhat.com> Reviewed-by: Eric Blake [eblake: rebase to qobject_to() macro] Signed-off-by: Eric Blake --- include/qapi/qmp/qstring.h | 1 + qobject/qstring.c | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/include/qapi/qmp/qstring.h b/include/qapi/qmp/qstring.h index 38c680b7185..30ae260a7fc 100644 --- a/include/qapi/qmp/qstring.h +++ b/include/qapi/qmp/qstring.h @@ -28,6 +28,7 @@ QString *qstring_from_substr(const char *str, int start, = int end); size_t qstring_get_length(const QString *qstring); const char *qstring_get_str(const QString *qstring); const char *qstring_get_try_str(const QString *qstring); +const char *qobject_get_try_str(const QObject *qstring); void qstring_append_int(QString *qstring, int64_t value); void qstring_append(QString *qstring, const char *str); void qstring_append_chr(QString *qstring, int c); diff --git a/qobject/qstring.c b/qobject/qstring.c index 5777f0af231..afca54b47ae 100644 --- a/qobject/qstring.c +++ b/qobject/qstring.c @@ -126,6 +126,17 @@ const char *qstring_get_try_str(const QString *qstring) return qstring ? qstring_get_str(qstring) : NULL; } +/** + * qobject_get_try_str(): Return a pointer to the corresponding string + * + * NOTE: the string will only be returned if the object is valid, and + * its type is QString, otherwise NULL is returned. + */ +const char *qobject_get_try_str(const QObject *qstring) +{ + return qstring_get_try_str(qobject_to(QString, qstring)); +} + /** * qstring_is_equal(): Test whether the two QStrings are equal */ --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 1520880657651640.8538504581032; Mon, 12 Mar 2018 11:50:57 -0700 (PDT) Received: from localhost ([::1]:33964 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSX1-0007Pr-HZ for importer@patchew.org; Mon, 12 Mar 2018 14:50:47 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45233) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJU-0000h6-6s for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:49 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJT-0005xZ-A4 for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:48 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:33602 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 1evSJT-0005xB-6J for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:47 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C0009814F0D2; Mon, 12 Mar 2018 18:36:46 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id 66750215CDAC; Mon, 12 Mar 2018 18:36:46 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:36:06 -0500 Message-Id: <20180312183628.394722-16-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 12 Mar 2018 18:36:46 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 12 Mar 2018 18:36:46 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@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/36] qobject: let object_property_get_str() use new API 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: =?UTF-8?q?Andreas=20F=C3=A4rber?= , Peter Xu 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: Peter Xu We can simplify object_property_get_str() using the new qobject_get_try_str(). Reviewed-by: Fam Zheng Reviewed-by: Stefan Hajnoczi Reviewed-by: Eric Blake Signed-off-by: Peter Xu Message-Id: <20180309090006.10018-5-peterx@redhat.com> [eblake: rebase context of qobject_to() macro] Signed-off-by: Eric Blake --- qom/object.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/qom/object.c b/qom/object.c index 7b3a6158fde..1c1b8cf8be0 100644 --- a/qom/object.c +++ b/qom/object.c @@ -1123,18 +1123,15 @@ char *object_property_get_str(Object *obj, const ch= ar *name, Error **errp) { QObject *ret =3D object_property_get_qobject(obj, name, errp); - QString *qstring; char *retval; if (!ret) { return NULL; } - qstring =3D qobject_to(QString, ret); - if (!qstring) { + + retval =3D g_strdup(qobject_get_try_str(ret)); + if (!retval) { error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "string"); - retval =3D NULL; - } else { - retval =3D g_strdup(qstring_get_str(qstring)); } qobject_decref(ret); --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 1520880820334681.8104519448199; Mon, 12 Mar 2018 11:53:40 -0700 (PDT) Received: from localhost ([::1]:33976 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSZn-0001S6-GD for importer@patchew.org; Mon, 12 Mar 2018 14:53:39 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45270) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJV-0000iY-FN for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJU-0005yS-E5 for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:49 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:58836 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 1evSJU-0005yA-AN for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:48 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id DD998401C9AE for ; Mon, 12 Mar 2018 18:36:47 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id E5B73215CDAC; Mon, 12 Mar 2018 18:36:46 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:36:07 -0500 Message-Id: <20180312183628.394722-17-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Mon, 12 Mar 2018 18:36:47 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Mon, 12 Mar 2018 18:36:47 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@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/36] monitor: move skip_flush into monitor_data_init 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: "Dr. David Alan Gilbert" , Peter Xu , Markus Armbruster 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: Peter Xu It's part of the data init. Collect it. Reviewed-by: Dr. David Alan Gilbert Reviewed-by: Fam Zheng Reviewed-by: Stefan Hajnoczi Signed-off-by: Peter Xu Message-Id: <20180309090006.10018-6-peterx@redhat.com> Signed-off-by: Eric Blake --- monitor.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/monitor.c b/monitor.c index c18a2f2dc98..b5acc92b735 100644 --- a/monitor.c +++ b/monitor.c @@ -570,13 +570,14 @@ static void monitor_qapi_event_init(void) static void handle_hmp_command(Monitor *mon, const char *cmdline); -static void monitor_data_init(Monitor *mon) +static void monitor_data_init(Monitor *mon, bool skip_flush) { memset(mon, 0, sizeof(Monitor)); qemu_mutex_init(&mon->out_lock); mon->outbuf =3D qstring_new(); /* Use *mon_cmds by default. */ mon->cmd_table =3D mon_cmds; + mon->skip_flush =3D skip_flush; } static void monitor_data_destroy(Monitor *mon) @@ -597,8 +598,7 @@ char *qmp_human_monitor_command(const char *command_lin= e, bool has_cpu_index, char *output =3D NULL; Monitor *old_mon, hmp; - monitor_data_init(&hmp); - hmp.skip_flush =3D true; + monitor_data_init(&hmp, true); old_mon =3D cur_mon; cur_mon =3D &hmp; @@ -4039,7 +4039,7 @@ void monitor_init(Chardev *chr, int flags) } mon =3D g_malloc(sizeof(*mon)); - monitor_data_init(mon); + monitor_data_init(mon, false); qemu_chr_fe_init(&mon->chr, chr, &error_abort); mon->flags =3D flags; --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 1520881603435225.4191679854796; Mon, 12 Mar 2018 12:06:43 -0700 (PDT) Received: from localhost ([::1]:34067 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSmQ-0004Bs-Hp for importer@patchew.org; Mon, 12 Mar 2018 15:06:42 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45281) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJV-0000ib-SM for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJU-0005yx-WC for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:49 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:38332 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 1evSJU-0005yf-ST for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:48 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 76CCE8D6D7 for ; Mon, 12 Mar 2018 18:36:48 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0E1FE215CDAC; Mon, 12 Mar 2018 18:36:47 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:36:08 -0500 Message-Id: <20180312183628.394722-18-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Mon, 12 Mar 2018 18:36:48 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Mon, 12 Mar 2018 18:36:48 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@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/36] monitor: move the cur_mon hack deeper for QMP 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: "Dr. David Alan Gilbert" , Peter Xu , Markus Armbruster 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: Peter Xu In monitor_qmp_read(), we have the hack to temporarily replace the cur_mon pointer. Now we move this hack deeper inside the QMP dispatcher routine since the Monitor pointer can be actually obtained using container_of() upon the parser object, just like most of the other JSON parser users do. This does not make much sense as a single patch. However, this will be a big step for the next patch, when the QMP dispatcher routine will be split from the QMP parser. Reviewed-by: Stefan Hajnoczi Reviewed-by: Eric Blake Signed-off-by: Peter Xu Message-Id: <20180309090006.10018-7-peterx@redhat.com> [eblake: rebase context of qobject_to() macro] Signed-off-by: Eric Blake --- monitor.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/monitor.c b/monitor.c index b5acc92b735..83e98741b4c 100644 --- a/monitor.c +++ b/monitor.c @@ -3762,7 +3762,9 @@ static void handle_qmp_command(JSONMessageParser *par= ser, GQueue *tokens) { QObject *req, *rsp =3D NULL, *id =3D NULL; QDict *qdict =3D NULL; - Monitor *mon =3D cur_mon; + MonitorQMP *mon_qmp =3D container_of(parser, MonitorQMP, parser); + Monitor *old_mon, *mon =3D container_of(mon_qmp, Monitor, qmp); + Error *err =3D NULL; req =3D json_parser_parse_err(tokens, NULL, &err); @@ -3787,8 +3789,13 @@ static void handle_qmp_command(JSONMessageParser *pa= rser, GQueue *tokens) QDECREF(req_json); } + old_mon =3D cur_mon; + cur_mon =3D mon; + rsp =3D qmp_dispatch(cur_mon->qmp.commands, req); + cur_mon =3D old_mon; + if (mon->qmp.commands =3D=3D &qmp_cap_negotiation_commands) { qdict =3D qdict_get_qdict(qobject_to(QDict, rsp), "error"); if (qdict @@ -3825,13 +3832,9 @@ err_out: static void monitor_qmp_read(void *opaque, const uint8_t *buf, int size) { - Monitor *old_mon =3D cur_mon; + Monitor *mon =3D opaque; - cur_mon =3D opaque; - - json_message_parser_feed(&cur_mon->qmp.parser, (const char *) buf, siz= e); - - cur_mon =3D old_mon; + json_message_parser_feed(&mon->qmp.parser, (const char *) buf, size); } static void monitor_read(void *opaque, const uint8_t *buf, int size) --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 1520880996867680.4192906147621; Mon, 12 Mar 2018 11:56:36 -0700 (PDT) Received: from localhost ([::1]:33996 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSca-0003wS-4y for importer@patchew.org; Mon, 12 Mar 2018 14:56:32 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45299) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJW-0000jn-Pc for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJV-0005zO-Mw for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:50 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:40644 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 1evSJV-0005z8-IC for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:49 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 24B9076FB9 for ; Mon, 12 Mar 2018 18:36:49 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9D8F0215CDAC; Mon, 12 Mar 2018 18:36:48 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:36:09 -0500 Message-Id: <20180312183628.394722-19-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Mon, 12 Mar 2018 18:36:49 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Mon, 12 Mar 2018 18:36:49 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@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/36] monitor: unify global init 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: Paolo Bonzini , "Dr. David Alan Gilbert" , Peter Xu , Markus Armbruster 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: Peter Xu There are many places where the monitor initializes its globals: - monitor_init_qmp_commands() at the very beginning - single function to init monitor_lock - in the first entry of monitor_init() using "is_first_init" Unify them a bit. monitor_lock is not used before monitor_init() (as confirmed by code analysis and gdb watchpoints); so we are safe delaying what was a constructor-time initialization of the mutex into the later first call to monitor_init(). Reviewed-by: Fam Zheng Reviewed-by: Stefan Hajnoczi Reviewed-by: Eric Blake Signed-off-by: Peter Xu Message-Id: <20180309090006.10018-8-peterx@redhat.com> Signed-off-by: Eric Blake --- include/monitor/monitor.h | 2 +- vl.c | 7 ++++++- monitor.c | 25 ++++++++++--------------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h index d1024d4bdc3..0cb0538a315 100644 --- a/include/monitor/monitor.h +++ b/include/monitor/monitor.h @@ -16,7 +16,7 @@ extern Monitor *cur_mon; bool monitor_cur_is_qmp(void); -void monitor_init_qmp_commands(void); +void monitor_init_globals(void); void monitor_init(Chardev *chr, int flags); void monitor_cleanup(void); diff --git a/vl.c b/vl.c index 3ef04ce991f..2e4fac7e4a0 100644 --- a/vl.c +++ b/vl.c @@ -3065,7 +3065,6 @@ int main(int argc, char **argv, char **envp) qemu_init_exec_dir(argv[0]); module_call_init(MODULE_INIT_QOM); - monitor_init_qmp_commands(); qemu_add_opts(&qemu_drive_opts); qemu_add_drive_opts(&qemu_legacy_drive_opts); @@ -4535,6 +4534,12 @@ int main(int argc, char **argv, char **envp) default_drive(default_floppy, snapshot, IF_FLOPPY, 0, FD_OPTS); default_drive(default_sdcard, snapshot, IF_SD, 0, SD_OPTS); + /* + * Note: qtest_enabled() (which is used in monitor_qapi_event_init()) + * depends on configure_accelerator() above. + */ + monitor_init_globals(); + if (qemu_opts_foreach(qemu_find_opts("mon"), mon_init_func, NULL, NULL)) { exit(1); diff --git a/monitor.c b/monitor.c index 83e98741b4c..71d53be1ddd 100644 --- a/monitor.c +++ b/monitor.c @@ -1003,7 +1003,7 @@ static void qmp_unregister_commands_hack(void) #endif } -void monitor_init_qmp_commands(void) +static void monitor_init_qmp_commands(void) { /* * Two command lists: @@ -3985,6 +3985,14 @@ static void sortcmdlist(void) qsort((void *)info_cmds, array_num, elem_size, compare_mon_cmd); } +void monitor_init_globals(void) +{ + monitor_init_qmp_commands(); + monitor_qapi_event_init(); + sortcmdlist(); + qemu_mutex_init(&monitor_lock); +} + /* These functions just adapt the readline interface in a typesafe way. We * could cast function pointers but that discards compiler checks. */ @@ -4025,23 +4033,10 @@ void error_vprintf_unless_qmp(const char *fmt, va_l= ist ap) } } -static void __attribute__((constructor)) monitor_lock_init(void) -{ - qemu_mutex_init(&monitor_lock); -} - void monitor_init(Chardev *chr, int flags) { - static int is_first_init =3D 1; - Monitor *mon; + Monitor *mon =3D g_malloc(sizeof(*mon)); - if (is_first_init) { - monitor_qapi_event_init(); - sortcmdlist(); - is_first_init =3D 0; - } - - mon =3D g_malloc(sizeof(*mon)); monitor_data_init(mon, false); qemu_chr_fe_init(&mon->chr, chr, &error_abort); --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 1520881156838696.291365898722; Mon, 12 Mar 2018 11:59:16 -0700 (PDT) Received: from localhost ([::1]:34009 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSfA-0006Jl-2m for importer@patchew.org; Mon, 12 Mar 2018 14:59:12 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45342) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJZ-0000o3-5u for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:54 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJW-0005zs-93 for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:53 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:38334 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 1evSJW-0005zX-44 for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:50 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B27BD8D6D7 for ; Mon, 12 Mar 2018 18:36:49 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id 49825215CDAC; Mon, 12 Mar 2018 18:36:49 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:36:10 -0500 Message-Id: <20180312183628.394722-20-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Mon, 12 Mar 2018 18:36:49 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Mon, 12 Mar 2018 18:36:49 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@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/36] monitor: let mon_list be tail queue X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Markus Armbruster , Peter Xu , "Dr. David Alan Gilbert" 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: Peter Xu It was QLIST. I want to use this list to do monitor priority job later, which need tail insertion ability. So switching to a tail queue. Reviewed-by: Fam Zheng Reviewed-by: Stefan Hajnoczi Signed-off-by: Peter Xu Message-Id: <20180309090006.10018-9-peterx@redhat.com> Signed-off-by: Eric Blake --- monitor.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/monitor.c b/monitor.c index 71d53be1ddd..63b93f83217 100644 --- a/monitor.c +++ b/monitor.c @@ -207,7 +207,7 @@ struct Monitor { void *password_opaque; mon_cmd_t *cmd_table; QLIST_HEAD(,mon_fd_t) fds; - QLIST_ENTRY(Monitor) entry; + QTAILQ_ENTRY(Monitor) entry; }; /* QMP checker flags */ @@ -216,7 +216,7 @@ struct Monitor { /* Protects mon_list, monitor_event_state. */ static QemuMutex monitor_lock; -static QLIST_HEAD(mon_list, Monitor) mon_list; +static QTAILQ_HEAD(mon_list, Monitor) mon_list; static QLIST_HEAD(mon_fdsets, MonFdset) mon_fdsets; static int mon_refcount; @@ -417,7 +417,7 @@ static void monitor_qapi_event_emit(QAPIEvent event, QD= ict *qdict) Monitor *mon; trace_monitor_protocol_event_emit(event, qdict); - QLIST_FOREACH(mon, &mon_list, entry) { + QTAILQ_FOREACH(mon, &mon_list, entry) { if (monitor_is_qmp(mon) && mon->qmp.commands !=3D &qmp_cap_negotiation_commands) { monitor_json_emitter(mon, QOBJECT(qdict)); @@ -4060,7 +4060,7 @@ void monitor_init(Chardev *chr, int flags) } qemu_mutex_lock(&monitor_lock); - QLIST_INSERT_HEAD(&mon_list, mon, entry); + QTAILQ_INSERT_HEAD(&mon_list, mon, entry); qemu_mutex_unlock(&monitor_lock); } @@ -4069,8 +4069,8 @@ void monitor_cleanup(void) Monitor *mon, *next; qemu_mutex_lock(&monitor_lock); - QLIST_FOREACH_SAFE(mon, &mon_list, entry, next) { - QLIST_REMOVE(mon, entry); + QTAILQ_FOREACH_SAFE(mon, &mon_list, entry, next) { + QTAILQ_REMOVE(&mon_list, mon, entry); monitor_data_destroy(mon); g_free(mon); } --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 1520880950759494.9132353391258; Mon, 12 Mar 2018 11:55:50 -0700 (PDT) Received: from localhost ([::1]:33991 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSbt-0003F5-SW for importer@patchew.org; Mon, 12 Mar 2018 14:55:49 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45338) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJZ-0000nr-3m for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:54 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJW-00060E-TY for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:53 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:33606 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 1evSJW-000600-OM for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:50 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4D1B6814F0D2 for ; Mon, 12 Mar 2018 18:36:50 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id D7894215CDAC; Mon, 12 Mar 2018 18:36:49 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:36:11 -0500 Message-Id: <20180312183628.394722-21-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 12 Mar 2018 18:36:50 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 12 Mar 2018 18:36:50 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@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/36] monitor: allow using IO thread for parsing 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: Markus Armbruster , Peter Xu , "Dr. David Alan Gilbert" 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: Peter Xu For each Monitor, add one field "use_io_thr" to show whether it will be using the dedicated monitor IO thread to handle input/output. When set, monitor IO parsing work will be offloaded to the dedicated monitor IO thread, rather than the original main loop thread. This only works for QMP. HMP will always be run on the main loop thread. Currently we're still keeping use_io_thr off always. Will turn it on later at some point. One thing to mention is that we cannot set use_io_thr for every QMP monitor. The problem is that MUXed typed chardevs may not work well with it now. When MUX is used, frontend of chardev can be the monitor plus something else. The only thing we know would be safe to be run outside main thread so far is the monitor frontend. All the rest of the frontends should still be run in main thread only. Signed-off-by: Peter Xu Message-Id: <20180309090006.10018-10-peterx@redhat.com> Reviewed-by: Eric Blake Signed-off-by: Eric Blake --- monitor.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--= ---- 1 file changed, 90 insertions(+), 8 deletions(-) diff --git a/monitor.c b/monitor.c index 63b93f83217..ce9f7fc8e8a 100644 --- a/monitor.c +++ b/monitor.c @@ -35,6 +35,7 @@ #include "net/net.h" #include "net/slirp.h" #include "chardev/char-fe.h" +#include "chardev/char-io.h" #include "ui/qemu-spice.h" #include "sysemu/numa.h" #include "monitor/monitor.h" @@ -79,6 +80,7 @@ #include "qapi/qapi-introspect.h" #include "sysemu/qtest.h" #include "sysemu/cpus.h" +#include "sysemu/iothread.h" #include "qemu/cutils.h" #if defined(TARGET_S390X) @@ -192,6 +194,7 @@ struct Monitor { int flags; int suspend_cnt; bool skip_flush; + bool use_io_thr; QemuMutex out_lock; QString *outbuf; @@ -210,6 +213,11 @@ struct Monitor { QTAILQ_ENTRY(Monitor) entry; }; +/* Let's add monitor global variables to this struct. */ +static struct { + IOThread *mon_iothread; +} mon_global; + /* QMP checker flags */ #define QMP_ACCEPT_UNKNOWNS 1 @@ -570,7 +578,8 @@ static void monitor_qapi_event_init(void) static void handle_hmp_command(Monitor *mon, const char *cmdline); -static void monitor_data_init(Monitor *mon, bool skip_flush) +static void monitor_data_init(Monitor *mon, bool skip_flush, + bool use_io_thr) { memset(mon, 0, sizeof(Monitor)); qemu_mutex_init(&mon->out_lock); @@ -578,6 +587,7 @@ static void monitor_data_init(Monitor *mon, bool skip_f= lush) /* Use *mon_cmds by default. */ mon->cmd_table =3D mon_cmds; mon->skip_flush =3D skip_flush; + mon->use_io_thr =3D use_io_thr; } static void monitor_data_destroy(Monitor *mon) @@ -598,7 +608,7 @@ char *qmp_human_monitor_command(const char *command_lin= e, bool has_cpu_index, char *output =3D NULL; Monitor *old_mon, hmp; - monitor_data_init(&hmp, true); + monitor_data_init(&hmp, true, false); old_mon =3D cur_mon; cur_mon =3D &hmp; @@ -3985,12 +3995,29 @@ static void sortcmdlist(void) qsort((void *)info_cmds, array_num, elem_size, compare_mon_cmd); } +static GMainContext *monitor_get_io_context(void) +{ + return iothread_get_g_main_context(mon_global.mon_iothread); +} + +static AioContext *monitor_get_aio_context(void) +{ + return iothread_get_aio_context(mon_global.mon_iothread); +} + +static void monitor_iothread_init(void) +{ + mon_global.mon_iothread =3D iothread_create("mon_iothread", + &error_abort); +} + void monitor_init_globals(void) { monitor_init_qmp_commands(); monitor_qapi_event_init(); sortcmdlist(); qemu_mutex_init(&monitor_lock); + monitor_iothread_init(); } /* These functions just adapt the readline interface in a typesafe way. We @@ -4033,11 +4060,41 @@ void error_vprintf_unless_qmp(const char *fmt, va_l= ist ap) } } +static void monitor_list_append(Monitor *mon) +{ + qemu_mutex_lock(&monitor_lock); + QTAILQ_INSERT_HEAD(&mon_list, mon, entry); + qemu_mutex_unlock(&monitor_lock); +} + +static void monitor_qmp_setup_handlers_bh(void *opaque) +{ + Monitor *mon =3D opaque; + GMainContext *context; + + if (mon->use_io_thr) { + /* + * When use_io_thr is set, we use the global shared dedicated + * IO thread for this monitor to handle input/output. + */ + context =3D monitor_get_io_context(); + /* We should have inited globals before reaching here. */ + assert(context); + } else { + /* The default main loop, which is the main thread */ + context =3D NULL; + } + + qemu_chr_fe_set_handlers(&mon->chr, monitor_can_read, monitor_qmp_read, + monitor_qmp_event, NULL, mon, context, true); + monitor_list_append(mon); +} + void monitor_init(Chardev *chr, int flags) { Monitor *mon =3D g_malloc(sizeof(*mon)); - monitor_data_init(mon, false); + monitor_data_init(mon, false, false); qemu_chr_fe_init(&mon->chr, chr, &error_abort); mon->flags =3D flags; @@ -4050,24 +4107,46 @@ void monitor_init(Chardev *chr, int flags) } if (monitor_is_qmp(mon)) { - qemu_chr_fe_set_handlers(&mon->chr, monitor_can_read, monitor_qmp_= read, - monitor_qmp_event, NULL, mon, NULL, true); qemu_chr_fe_set_echo(&mon->chr, true); json_message_parser_init(&mon->qmp.parser, handle_qmp_command); + if (mon->use_io_thr) { + /* + * We can't call qemu_chr_fe_set_handlers() directly here + * since during the procedure the chardev will be active + * and running in monitor iothread, while we'll still do + * something before returning from it, which is a possible + * race too. To avoid that, we just create a BH to setup + * the handlers. + */ + aio_bh_schedule_oneshot(monitor_get_aio_context(), + monitor_qmp_setup_handlers_bh, mon); + /* We'll add this to mon_list in the BH when setup done */ + return; + } else { + qemu_chr_fe_set_handlers(&mon->chr, monitor_can_read, + monitor_qmp_read, monitor_qmp_event, + NULL, mon, NULL, true); + } } else { qemu_chr_fe_set_handlers(&mon->chr, monitor_can_read, monitor_read, monitor_event, NULL, mon, NULL, true); } - qemu_mutex_lock(&monitor_lock); - QTAILQ_INSERT_HEAD(&mon_list, mon, entry); - qemu_mutex_unlock(&monitor_lock); + monitor_list_append(mon); } void monitor_cleanup(void) { Monitor *mon, *next; + /* + * We need to explicitly stop the iothread (but not destroy it), + * cleanup the monitor resources, then destroy the iothread since + * we need to unregister from chardev below in + * monitor_data_destroy(), and chardev is not thread-safe yet + */ + iothread_stop(mon_global.mon_iothread); + qemu_mutex_lock(&monitor_lock); QTAILQ_FOREACH_SAFE(mon, &mon_list, entry, next) { QTAILQ_REMOVE(&mon_list, mon, entry); @@ -4075,6 +4154,9 @@ void monitor_cleanup(void) g_free(mon); } qemu_mutex_unlock(&monitor_lock); + + iothread_destroy(mon_global.mon_iothread); + mon_global.mon_iothread =3D NULL; } QemuOptsList qemu_mon_opts =3D { --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 1520881466429533.2411559855586; Mon, 12 Mar 2018 12:04:26 -0700 (PDT) Received: from localhost ([::1]:34043 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSkD-0002G5-CS for importer@patchew.org; Mon, 12 Mar 2018 15:04:25 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45336) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJZ-0000no-3J for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:59 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJX-00060W-HU for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:53 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:38338 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 1evSJX-00060L-B8 for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:51 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E20098D6D7 for ; Mon, 12 Mar 2018 18:36:50 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7575D215CDAC; Mon, 12 Mar 2018 18:36:50 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:36:12 -0500 Message-Id: <20180312183628.394722-22-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Mon, 12 Mar 2018 18:36:50 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Mon, 12 Mar 2018 18:36:50 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@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/36] qmp: introduce QMPCapability 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: Markus Armbruster , Peter Xu , "Dr. David Alan Gilbert" 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: Peter Xu There were no QMP capabilities defined. Define the first capability, "oob", to allow out-of-band messages. After this patch, we will allow QMP clients to enable QMP capabilities when sending the first "qmp_capabilities" command. Originally we are starting QMP session with no arguments like: { "execute": "qmp_capabilities" } Now we can enable some QMP capabilities using (take OOB as example, which is the only capability that we support): { "execute": "qmp_capabilities", "arguments": { "enable": [ "oob" ] } } When the "arguments" key is not provided, no capability is enabled. For capability "oob", the monitor needs to be run on a dedicated IO thread, otherwise the command will fail. For example, trying to enable OOB on a MUXed typed QMP monitor will fail. One thing to mention is that QMP capabilities are per-monitor, and also when the connection is closed due to some reason, the capabilities will be reset. Also, touch up qmp-test.c to test the new bits. Signed-off-by: Peter Xu Message-Id: <20180309090006.10018-11-peterx@redhat.com> Reviewed-by: Eric Blake [eblake: touch up commit message] Signed-off-by: Eric Blake --- qapi/misc.json | 32 ++++++++++++++++++++--- monitor.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++= ---- tests/qmp-test.c | 10 +++++++- 3 files changed, 110 insertions(+), 9 deletions(-) diff --git a/qapi/misc.json b/qapi/misc.json index bcd5d10778a..b2f69eb4ece 100644 --- a/qapi/misc.json +++ b/qapi/misc.json @@ -10,21 +10,47 @@ # # Enable QMP capabilities. # -# Arguments: None. +# Arguments: +# +# @enable: An optional list of QMPCapability values to enable. The +# client must not enable any capability that is not +# mentioned in the QMP greeting message. If the field is not +# provided, it means no QMP capabilities will be enabled. +# (since 2.12) # # Example: # -# -> { "execute": "qmp_capabilities" } +# -> { "execute": "qmp_capabilities", +# "arguments": { "enable": [ "oob" ] } } # <- { "return": {} } # # Notes: This command is valid exactly when first connecting: it must be # issued before any other command will be accepted, and will fail once the # monitor is accepting other commands. (see qemu docs/interop/qmp-spec.txt) # +# The QMP client needs to explicitly enable QMP capabilities, otherwise +# all the QMP capabilities will be turned off by default. +# # Since: 0.13 # ## -{ 'command': 'qmp_capabilities' } +{ 'command': 'qmp_capabilities', + 'data': { '*enable': [ 'QMPCapability' ] } } + +## +# @QMPCapability: +# +# Enumeration of capabilities to be advertised during initial client +# connection, used for agreeing on particular QMP extension behaviors. +# +# @oob: QMP ability to support Out-Of-Band requests. +# (Please refer to qmp-spec.txt for more information on OOB) +# +# Since: 2.12 +# +## +{ 'enum': 'QMPCapability', + 'data': [ 'oob' ] } ## # @VersionTriple: diff --git a/monitor.c b/monitor.c index ce9f7fc8e8a..1a95fb372c6 100644 --- a/monitor.c +++ b/monitor.c @@ -59,6 +59,7 @@ #include "qapi/qmp/qjson.h" #include "qapi/qmp/json-streamer.h" #include "qapi/qmp/json-parser.h" +#include "qapi/qmp/qlist.h" #include "qom/object_interfaces.h" #include "trace-root.h" #include "trace/control.h" @@ -170,6 +171,7 @@ typedef struct { * mode. */ QmpCommandList *commands; + bool qmp_caps[QMP_CAPABILITY__MAX]; } MonitorQMP; /* @@ -1039,8 +1041,42 @@ static void monitor_init_qmp_commands(void) qmp_marshal_qmp_capabilities, QCO_NO_OPTIONS); } -void qmp_qmp_capabilities(Error **errp) +static void qmp_caps_check(Monitor *mon, QMPCapabilityList *list, + Error **errp) { + for (; list; list =3D list->next) { + assert(list->value < QMP_CAPABILITY__MAX); + switch (list->value) { + case QMP_CAPABILITY_OOB: + if (!mon->use_io_thr) { + /* + * Out-Of-Band only works with monitors that are + * running on dedicated IOThread. + */ + error_setg(errp, "This monitor does not support " + "Out-Of-Band (OOB)"); + return; + } + break; + default: + break; + } + } +} + +/* This function should only be called after capabilities are checked. */ +static void qmp_caps_apply(Monitor *mon, QMPCapabilityList *list) +{ + for (; list; list =3D list->next) { + mon->qmp.qmp_caps[list->value] =3D true; + } +} + +void qmp_qmp_capabilities(bool has_enable, QMPCapabilityList *enable, + Error **errp) +{ + Error *local_err =3D NULL; + if (cur_mon->qmp.commands =3D=3D &qmp_commands) { error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND, "Capabilities negotiation is already complete, command " @@ -1048,6 +1084,21 @@ void qmp_qmp_capabilities(Error **errp) return; } + /* Enable QMP capabilities provided by the client if applicable. */ + if (has_enable) { + qmp_caps_check(cur_mon, enable, &local_err); + if (local_err) { + /* + * Failed check on any of the capabilities will fail the + * entire command (and thus not apply any of the other + * capabilities that were also requested). + */ + error_propagate(errp, local_err); + return; + } + qmp_caps_apply(cur_mon, enable); + } + cur_mon->qmp.commands =3D &qmp_commands; } @@ -3893,14 +3944,29 @@ void monitor_resume(Monitor *mon) readline_show_prompt(mon->rs); } -static QObject *get_qmp_greeting(void) +static QObject *get_qmp_greeting(Monitor *mon) { + QList *cap_list =3D qlist_new(); QObject *ver =3D NULL; + QMPCapability cap; qmp_marshal_query_version(NULL, &ver, NULL); - return qobject_from_jsonf("{'QMP': {'version': %p, 'capabilities': []}= }", - ver); + for (cap =3D 0; cap < QMP_CAPABILITY__MAX; cap++) { + if (!mon->use_io_thr && cap =3D=3D QMP_CAPABILITY_OOB) { + /* Monitors that are not using IOThread won't support OOB */ + continue; + } + qlist_append(cap_list, qstring_from_str(QMPCapability_str(cap))); + } + + return qobject_from_jsonf("{'QMP': {'version': %p, 'capabilities': %p}= }", + ver, cap_list); +} + +static void monitor_qmp_caps_reset(Monitor *mon) +{ + memset(mon->qmp.qmp_caps, 0, sizeof(mon->qmp.qmp_caps)); } static void monitor_qmp_event(void *opaque, int event) @@ -3911,7 +3977,8 @@ static void monitor_qmp_event(void *opaque, int event) switch (event) { case CHR_EVENT_OPENED: mon->qmp.commands =3D &qmp_cap_negotiation_commands; - data =3D get_qmp_greeting(); + monitor_qmp_caps_reset(mon); + data =3D get_qmp_greeting(mon); monitor_json_emitter(mon, data); qobject_decref(data); mon_refcount++; diff --git a/tests/qmp-test.c b/tests/qmp-test.c index 22445d9ec25..a8384bdda3b 100644 --- a/tests/qmp-test.c +++ b/tests/qmp-test.c @@ -20,6 +20,7 @@ #include "qapi/qobject-input-visitor.h" #include "qapi/util.h" #include "qapi/visitor.h" +#include "qapi/qmp/qstring.h" const char common_args[] =3D "-nodefaults -machine none"; @@ -79,6 +80,8 @@ static void test_qmp_protocol(void) QDict *resp, *q, *ret; QList *capabilities; QTestState *qts; + const QListEntry *entry; + QString *qstr; qts =3D qtest_init_without_qmp_handshake(common_args); @@ -88,7 +91,12 @@ static void test_qmp_protocol(void) g_assert(q); test_version(qdict_get(q, "version")); capabilities =3D qdict_get_qlist(q, "capabilities"); - g_assert(capabilities && qlist_empty(capabilities)); + g_assert(capabilities); + entry =3D qlist_first(capabilities); + g_assert(entry); + qstr =3D qobject_to(QString, entry->value); + g_assert(qstr); + g_assert_cmpstr(qstring_get_str(qstr), =3D=3D, "oob"); QDECREF(resp); /* Test valid command before handshake */ --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 1520882039934575.0793298768331; Mon, 12 Mar 2018 12:13:59 -0700 (PDT) Received: from localhost ([::1]:34115 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evStS-00021b-Rs for importer@patchew.org; Mon, 12 Mar 2018 15:13:58 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45335) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJZ-0000nj-2g for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:54 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJY-00060v-1U for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:53 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:40646 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 1evSJX-00060b-TZ for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:51 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 7F0C476FB9 for ; Mon, 12 Mar 2018 18:36:51 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id 13B88215CDAC; Mon, 12 Mar 2018 18:36:51 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:36:13 -0500 Message-Id: <20180312183628.394722-23-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Mon, 12 Mar 2018 18:36:51 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Mon, 12 Mar 2018 18:36:51 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@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/36] monitor: introduce monitor_qmp_respond() 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: "Dr. David Alan Gilbert" , Peter Xu , Markus Armbruster 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: Peter Xu A tiny refactoring, preparing to split the QMP dispatcher away. Reviewed-by: Fam Zheng Reviewed-by: Stefan Hajnoczi Signed-off-by: Peter Xu Message-Id: <20180309090006.10018-12-peterx@redhat.com> Reviewed-by: Eric Blake [eblake: rebase to qobject_to() usage] Signed-off-by: Eric Blake --- monitor.c | 50 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/monitor.c b/monitor.c index 1a95fb372c6..a3412359ca8 100644 --- a/monitor.c +++ b/monitor.c @@ -3819,6 +3819,38 @@ static int monitor_can_read(void *opaque) return (mon->suspend_cnt =3D=3D 0) ? 1 : 0; } +/* + * 1. This function takes ownership of rsp, err, and id. + * 2. rsp, err, and id may be NULL. + * 3. If err !=3D NULL then rsp must be NULL. + */ +static void monitor_qmp_respond(Monitor *mon, QObject *rsp, + Error *err, QObject *id) +{ + QDict *qdict =3D NULL; + + if (err) { + assert(!rsp); + qdict =3D qdict_new(); + qdict_put_obj(qdict, "error", qmp_build_error_object(err)); + error_free(err); + rsp =3D QOBJECT(qdict); + } + + if (rsp) { + if (id) { + /* This is for the qdict below. */ + qobject_incref(id); + qdict_put_obj(qobject_to(QDict, rsp), "id", id); + } + + monitor_json_emitter(mon, rsp); + } + + qobject_decref(id); + qobject_decref(rsp); +} + static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens) { QObject *req, *rsp =3D NULL, *id =3D NULL; @@ -3870,24 +3902,8 @@ static void handle_qmp_command(JSONMessageParser *pa= rser, GQueue *tokens) } err_out: - if (err) { - qdict =3D qdict_new(); - qdict_put_obj(qdict, "error", qmp_build_error_object(err)); - error_free(err); - rsp =3D QOBJECT(qdict); - } + monitor_qmp_respond(mon, rsp, err, id); - if (rsp) { - if (id) { - qdict_put_obj(qobject_to(QDict, rsp), "id", id); - id =3D NULL; - } - - monitor_json_emitter(mon, rsp); - } - - qobject_decref(id); - qobject_decref(rsp); qobject_decref(req); } --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 1520881742309450.17357985268814; Mon, 12 Mar 2018 12:09:02 -0700 (PDT) Received: from localhost ([::1]:34081 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSoc-00067L-4s for importer@patchew.org; Mon, 12 Mar 2018 15:08:58 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45348) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJZ-0000oY-HI for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:54 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJY-00061L-KU for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:53 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:40648 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 1evSJY-000614-Gq for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:52 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 1DD7576FB9 for ; Mon, 12 Mar 2018 18:36:52 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id A3290215CDAC; Mon, 12 Mar 2018 18:36:51 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:36:14 -0500 Message-Id: <20180312183628.394722-24-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Mon, 12 Mar 2018 18:36:52 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Mon, 12 Mar 2018 18:36:52 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@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/36] monitor: let suspend_cnt be thread safe 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: Markus Armbruster , Peter Xu , "Dr. David Alan Gilbert" 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: Peter Xu Monitor code now can be run in more than one thread. Let it be thread safe when accessing suspend_cnt counter. Reviewed-by: Eric Blake Reviewed-by: Stefan Hajnoczi Signed-off-by: Peter Xu Message-Id: <20180309090006.10018-13-peterx@redhat.com> Signed-off-by: Eric Blake --- monitor.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/monitor.c b/monitor.c index a3412359ca8..608faf35c25 100644 --- a/monitor.c +++ b/monitor.c @@ -194,7 +194,7 @@ struct Monitor { CharBackend chr; int reset_seen; int flags; - int suspend_cnt; + int suspend_cnt; /* Needs to be accessed atomically */ bool skip_flush; bool use_io_thr; @@ -3816,7 +3816,7 @@ static int monitor_can_read(void *opaque) { Monitor *mon =3D opaque; - return (mon->suspend_cnt =3D=3D 0) ? 1 : 0; + return !atomic_mb_read(&mon->suspend_cnt); } /* @@ -3948,7 +3948,7 @@ int monitor_suspend(Monitor *mon) { if (!mon->rs) return -ENOTTY; - mon->suspend_cnt++; + atomic_inc(&mon->suspend_cnt); return 0; } @@ -3956,8 +3956,9 @@ void monitor_resume(Monitor *mon) { if (!mon->rs) return; - if (--mon->suspend_cnt =3D=3D 0) + if (atomic_dec_fetch(&mon->suspend_cnt) =3D=3D 0) { readline_show_prompt(mon->rs); + } } static QObject *get_qmp_greeting(Monitor *mon) @@ -4022,19 +4023,19 @@ static void monitor_event(void *opaque, int event) monitor_resume(mon); monitor_flush(mon); } else { - mon->suspend_cnt =3D 0; + atomic_mb_set(&mon->suspend_cnt, 0); } break; case CHR_EVENT_MUX_OUT: if (mon->reset_seen) { - if (mon->suspend_cnt =3D=3D 0) { + if (atomic_mb_read(&mon->suspend_cnt) =3D=3D 0) { monitor_printf(mon, "\n"); } monitor_flush(mon); monitor_suspend(mon); } else { - mon->suspend_cnt++; + atomic_inc(&mon->suspend_cnt); } qemu_mutex_lock(&mon->out_lock); mon->mux_out =3D 1; --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 1520882174113183.028005694718; Mon, 12 Mar 2018 12:16:14 -0700 (PDT) Received: from localhost ([::1]:34132 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSvd-0003uE-9j for importer@patchew.org; Mon, 12 Mar 2018 15:16:13 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45378) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJa-0000pg-By for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:55 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJZ-00061y-AG for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:54 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:33610 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 1evSJZ-00061Z-3k for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:53 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id ABFA2814F0D2 for ; Mon, 12 Mar 2018 18:36:52 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4349B215CDAC; Mon, 12 Mar 2018 18:36:52 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:36:15 -0500 Message-Id: <20180312183628.394722-25-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 12 Mar 2018 18:36:52 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 12 Mar 2018 18:36:52 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@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/36] monitor: let suspend/resume work even with QMPs 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: "Dr. David Alan Gilbert" , Peter Xu , Markus Armbruster 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: Peter Xu This patches allows QMP monitors to be suspended/resumed. One thing to mention is that for QMPs that are using IOThreads, we need an explicit kick for the IOThread in case it is sleeping. Meanwhile, we need to take special care on non-interactive HMPs. Currently only gdbserver is using that. For these monitors, we still don't allow suspend/resume operations. Since at it, add traces for the operations. Signed-off-by: Peter Xu Message-Id: <20180309090006.10018-14-peterx@redhat.com> Reviewed-by: Eric Blake Signed-off-by: Eric Blake --- monitor.c | 47 ++++++++++++++++++++++++++++++++++++++++++++--- trace-events | 1 + 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/monitor.c b/monitor.c index 608faf35c25..6b225e9fc5c 100644 --- a/monitor.c +++ b/monitor.c @@ -250,6 +250,21 @@ static inline bool monitor_is_qmp(const Monitor *mon) return (mon->flags & MONITOR_USE_CONTROL); } +/** + * Whether @mon is using readline? Note: not all HMP monitors use + * readline, e.g., gdbserver has a non-interactive HMP monitor, so + * readline is not used there. + */ +static inline bool monitor_uses_readline(const Monitor *mon) +{ + return mon->flags & MONITOR_USE_READLINE; +} + +static inline bool monitor_is_hmp_non_interactive(const Monitor *mon) +{ + return !monitor_is_qmp(mon) && !monitor_uses_readline(mon); +} + /** * Is the current monitor, if any, a QMP monitor? */ @@ -3946,19 +3961,45 @@ static void monitor_command_cb(void *opaque, const = char *cmdline, int monitor_suspend(Monitor *mon) { - if (!mon->rs) + if (monitor_is_hmp_non_interactive(mon)) { return -ENOTTY; + } + atomic_inc(&mon->suspend_cnt); + + if (monitor_is_qmp(mon)) { + /* + * Kick iothread to make sure this takes effect. It'll be + * evaluated again in prepare() of the watch object. + */ + aio_notify(iothread_get_aio_context(mon_global.mon_iothread)); + } + + trace_monitor_suspend(mon, 1); return 0; } void monitor_resume(Monitor *mon) { - if (!mon->rs) + if (monitor_is_hmp_non_interactive(mon)) { return; + } + if (atomic_dec_fetch(&mon->suspend_cnt) =3D=3D 0) { - readline_show_prompt(mon->rs); + if (monitor_is_qmp(mon)) { + /* + * For QMP monitors that are running in IOThread, let's + * kick the thread in case it's sleeping. + */ + if (mon->use_io_thr) { + aio_notify(iothread_get_aio_context(mon_global.mon_iothrea= d)); + } + } else { + assert(mon->rs); + readline_show_prompt(mon->rs); + } } + trace_monitor_suspend(mon, -1); } static QObject *get_qmp_greeting(Monitor *mon) diff --git a/trace-events b/trace-events index 89fcad0fd13..fe10c3b487c 100644 --- a/trace-events +++ b/trace-events @@ -47,6 +47,7 @@ monitor_protocol_event_emit(uint32_t event, void *data) "= event=3D%d data=3D%p" monitor_protocol_event_queue(uint32_t event, void *qdict, uint64_t rate) "= event=3D%d data=3D%p rate=3D%" PRId64 handle_hmp_command(void *mon, const char *cmdline) "mon %p cmdline: %s" handle_qmp_command(void *mon, const char *req) "mon %p req: %s" +monitor_suspend(void *ptr, int cnt) "mon %p: %d" # dma-helpers.c dma_blk_io(void *dbs, void *bs, int64_t offset, bool to_dev) "dbs=3D%p bs= =3D%p offset=3D%" PRId64 " to_dev=3D%d" --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 1520881112906531.9393335728694; Mon, 12 Mar 2018 11:58:32 -0700 (PDT) Received: from localhost ([::1]:34008 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSeW-0005kH-4C for importer@patchew.org; Mon, 12 Mar 2018 14:58:32 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45417) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJc-0000rk-0C for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:57 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJZ-00062Q-SD for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:56 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:58842 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 1evSJZ-000626-Ml for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:53 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4C0B4401C9AE for ; Mon, 12 Mar 2018 18:36:53 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id D461D215CDAC; Mon, 12 Mar 2018 18:36:52 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:36:16 -0500 Message-Id: <20180312183628.394722-26-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Mon, 12 Mar 2018 18:36:53 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Mon, 12 Mar 2018 18:36:53 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@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/36] monitor: separate QMP parser and dispatcher 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: Markus Armbruster , Peter Xu , "Dr. David Alan Gilbert" 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: Peter Xu Originally QMP goes through these steps: JSON Parser --> QMP Dispatcher --> Respond /|\ (2) (3) | (1) | \|/ (4) +--------- main thread --------+ This patch does this: JSON Parser QMP Dispatcher --> Respond /|\ | /|\ (4) | | | (2) | (3) | (5) (1) | +-----> | \|/ +--------- main thread <-------+ So the parsing job and the dispatching job is isolated now. It gives us a chance in follow up patches to totally move the parser outside. The isolation is done using one QEMUBH. Only one dispatcher QEMUBH is used for all the monitors. Reviewed-by: Stefan Hajnoczi Signed-off-by: Peter Xu Message-Id: <20180309090006.10018-15-peterx@redhat.com> Reviewed-by: Eric Blake [eblake: grammar tweaks, rebase to qobject_to()] Signed-off-by: Eric Blake --- monitor.c | 201 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---= ---- 1 file changed, 178 insertions(+), 23 deletions(-) diff --git a/monitor.c b/monitor.c index 6b225e9fc5c..07446d6b879 100644 --- a/monitor.c +++ b/monitor.c @@ -172,6 +172,13 @@ typedef struct { */ QmpCommandList *commands; bool qmp_caps[QMP_CAPABILITY__MAX]; + /* + * Protects qmp request/response queue. Please take monitor_lock + * first when used together. + */ + QemuMutex qmp_queue_lock; + /* Input queue that holds all the parsed QMP requests */ + GQueue *qmp_requests; } MonitorQMP; /* @@ -218,6 +225,8 @@ struct Monitor { /* Let's add monitor global variables to this struct. */ static struct { IOThread *mon_iothread; + /* Bottom half to dispatch the requests received from IO thread */ + QEMUBH *qmp_dispatcher_bh; } mon_global; /* QMP checker flags */ @@ -600,11 +609,13 @@ static void monitor_data_init(Monitor *mon, bool skip= _flush, { memset(mon, 0, sizeof(Monitor)); qemu_mutex_init(&mon->out_lock); + qemu_mutex_init(&mon->qmp.qmp_queue_lock); mon->outbuf =3D qstring_new(); /* Use *mon_cmds by default. */ mon->cmd_table =3D mon_cmds; mon->skip_flush =3D skip_flush; mon->use_io_thr =3D use_io_thr; + mon->qmp.qmp_requests =3D g_queue_new(); } static void monitor_data_destroy(Monitor *mon) @@ -617,6 +628,8 @@ static void monitor_data_destroy(Monitor *mon) readline_free(mon->rs); QDECREF(mon->outbuf); qemu_mutex_destroy(&mon->out_lock); + qemu_mutex_destroy(&mon->qmp.qmp_queue_lock); + g_queue_free(mon->qmp.qmp_requests); } char *qmp_human_monitor_command(const char *command_line, bool has_cpu_ind= ex, @@ -1056,6 +1069,16 @@ static void monitor_init_qmp_commands(void) qmp_marshal_qmp_capabilities, QCO_NO_OPTIONS); } +static bool qmp_cap_enabled(Monitor *mon, QMPCapability cap) +{ + return mon->qmp.qmp_caps[cap]; +} + +static bool qmp_oob_enabled(Monitor *mon) +{ + return qmp_cap_enabled(mon, QMP_CAPABILITY_OOB); +} + static void qmp_caps_check(Monitor *mon, QMPCapabilityList *list, Error **errp) { @@ -3866,30 +3889,39 @@ static void monitor_qmp_respond(Monitor *mon, QObje= ct *rsp, qobject_decref(rsp); } -static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens) +struct QMPRequest { + /* Owner of the request */ + Monitor *mon; + /* "id" field of the request */ + QObject *id; + /* Request object to be handled */ + QObject *req; + /* + * Whether we need to resume the monitor afterward. This flag is + * used to emulate the old QMP server behavior that the current + * command must be completed before execution of the next one. + */ + bool need_resume; +}; +typedef struct QMPRequest QMPRequest; + +/* + * Dispatch one single QMP request. The function will free the req_obj + * and objects inside it before return. + */ +static void monitor_qmp_dispatch_one(QMPRequest *req_obj) { - QObject *req, *rsp =3D NULL, *id =3D NULL; + Monitor *mon, *old_mon; + QObject *req, *rsp =3D NULL, *id; QDict *qdict =3D NULL; - MonitorQMP *mon_qmp =3D container_of(parser, MonitorQMP, parser); - Monitor *old_mon, *mon =3D container_of(mon_qmp, Monitor, qmp); + bool need_resume; - Error *err =3D NULL; + req =3D req_obj->req; + mon =3D req_obj->mon; + id =3D req_obj->id; + need_resume =3D req_obj->need_resume; - req =3D json_parser_parse_err(tokens, NULL, &err); - if (!req && !err) { - /* json_parser_parse_err() sucks: can fail without setting @err */ - error_setg(&err, QERR_JSON_PARSING); - } - if (err) { - goto err_out; - } - - qdict =3D qobject_to(QDict, req); - if (qdict) { - id =3D qdict_get(qdict, "id"); - qobject_incref(id); - qdict_del(qdict, "id"); - } /* else will fail qmp_dispatch() */ + g_free(req_obj); if (trace_event_get_state_backends(TRACE_HANDLE_QMP_COMMAND)) { QString *req_json =3D qobject_to_json(req); @@ -3900,7 +3932,7 @@ static void handle_qmp_command(JSONMessageParser *par= ser, GQueue *tokens) old_mon =3D cur_mon; cur_mon =3D mon; - rsp =3D qmp_dispatch(cur_mon->qmp.commands, req); + rsp =3D qmp_dispatch(mon->qmp.commands, req); cur_mon =3D old_mon; @@ -3916,12 +3948,122 @@ static void handle_qmp_command(JSONMessageParser *= parser, GQueue *tokens) } } -err_out: - monitor_qmp_respond(mon, rsp, err, id); + /* Respond if necessary */ + monitor_qmp_respond(mon, rsp, NULL, id); + + /* This pairs with the monitor_suspend() in handle_qmp_command(). */ + if (need_resume) { + monitor_resume(mon); + } qobject_decref(req); } +/* + * Pop one QMP request from monitor queues, return NULL if not found. + * We are using round-robin fashion to pop the request, to avoid + * processing commands only on a very busy monitor. To achieve that, + * when we process one request on a specific monitor, we put that + * monitor to the end of mon_list queue. + */ +static QMPRequest *monitor_qmp_requests_pop_one(void) +{ + QMPRequest *req_obj =3D NULL; + Monitor *mon; + + qemu_mutex_lock(&monitor_lock); + + QTAILQ_FOREACH(mon, &mon_list, entry) { + qemu_mutex_lock(&mon->qmp.qmp_queue_lock); + req_obj =3D g_queue_pop_head(mon->qmp.qmp_requests); + qemu_mutex_unlock(&mon->qmp.qmp_queue_lock); + if (req_obj) { + break; + } + } + + if (req_obj) { + /* + * We found one request on the monitor. Degrade this monitor's + * priority to lowest by re-inserting it to end of queue. + */ + QTAILQ_REMOVE(&mon_list, mon, entry); + QTAILQ_INSERT_TAIL(&mon_list, mon, entry); + } + + qemu_mutex_unlock(&monitor_lock); + + return req_obj; +} + +static void monitor_qmp_bh_dispatcher(void *data) +{ + QMPRequest *req_obj =3D monitor_qmp_requests_pop_one(); + + if (req_obj) { + monitor_qmp_dispatch_one(req_obj); + /* Reschedule instead of looping so the main loop stays responsive= */ + qemu_bh_schedule(mon_global.qmp_dispatcher_bh); + } +} + +static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens) +{ + QObject *req, *id =3D NULL; + QDict *qdict =3D NULL; + MonitorQMP *mon_qmp =3D container_of(parser, MonitorQMP, parser); + Monitor *mon =3D container_of(mon_qmp, Monitor, qmp); + Error *err =3D NULL; + QMPRequest *req_obj; + + req =3D json_parser_parse_err(tokens, NULL, &err); + if (!req && !err) { + /* json_parser_parse_err() sucks: can fail without setting @err */ + error_setg(&err, QERR_JSON_PARSING); + } + if (err) { + monitor_qmp_respond(mon, NULL, err, NULL); + qobject_decref(req); + return; + } + + qdict =3D qobject_to(QDict, req); + if (qdict) { + id =3D qdict_get(qdict, "id"); + qobject_incref(id); + qdict_del(qdict, "id"); + } /* else will fail qmp_dispatch() */ + + req_obj =3D g_new0(QMPRequest, 1); + req_obj->mon =3D mon; + req_obj->id =3D id; + req_obj->req =3D req; + req_obj->need_resume =3D false; + + /* + * If OOB is not enabled on the current monitor, we'll emulate the + * old behavior that we won't process the current monitor any more + * until it has responded. This helps make sure that as long as + * OOB is not enabled, the server will never drop any command. + */ + if (!qmp_oob_enabled(mon)) { + monitor_suspend(mon); + req_obj->need_resume =3D true; + } + + /* + * Put the request to the end of queue so that requests will be + * handled in time order. Ownership for req_obj, req, id, + * etc. will be delivered to the handler side. + */ + qemu_mutex_lock(&mon->qmp.qmp_queue_lock); + g_queue_push_tail(mon->qmp.qmp_requests, req_obj); + qemu_mutex_unlock(&mon->qmp.qmp_queue_lock); + + /* Kick the dispatcher routine */ + qemu_bh_schedule(mon_global.qmp_dispatcher_bh); +} + static void monitor_qmp_read(void *opaque, const uint8_t *buf, int size) { Monitor *mon =3D opaque; @@ -4134,6 +4276,15 @@ static void monitor_iothread_init(void) { mon_global.mon_iothread =3D iothread_create("mon_iothread", &error_abort); + + /* + * This MUST be on main loop thread since we have commands that + * have assumption to be run on main loop thread. It would be + * nice that one day we can remove this assumption in the future. + */ + mon_global.qmp_dispatcher_bh =3D aio_bh_new(qemu_get_aio_context(), + monitor_qmp_bh_dispatcher, + NULL); } void monitor_init_globals(void) @@ -4280,6 +4431,10 @@ void monitor_cleanup(void) } qemu_mutex_unlock(&monitor_lock); + /* QEMUBHs needs to be deleted before destroying the IOThread. */ + qemu_bh_delete(mon_global.qmp_dispatcher_bh); + mon_global.qmp_dispatcher_bh =3D NULL; + iothread_destroy(mon_global.mon_iothread); mon_global.mon_iothread =3D NULL; } --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 1520882328709176.48110789926682; Mon, 12 Mar 2018 12:18:48 -0700 (PDT) Received: from localhost ([::1]:34154 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSy7-0005qo-I8 for importer@patchew.org; Mon, 12 Mar 2018 15:18:47 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45409) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJb-0000rO-Mp for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:56 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJa-00062o-AD for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:55 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:59916 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 1evSJa-00062X-6s for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:54 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C8FF54023155 for ; Mon, 12 Mar 2018 18:36:53 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7134A215CDAC; Mon, 12 Mar 2018 18:36:53 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:36:17 -0500 Message-Id: <20180312183628.394722-27-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Mon, 12 Mar 2018 18:36:53 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Mon, 12 Mar 2018 18:36:53 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@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/36] qmp: add new event "command-dropped" 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: Markus Armbruster , Peter Xu 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: Peter Xu This event will be emitted if one QMP command is dropped. Also, declare an enum for the reasons. Reviewed-by: Fam Zheng Reviewed-by: Stefan Hajnoczi Signed-off-by: Peter Xu Message-Id: <20180309090006.10018-16-peterx@redhat.com> Reviewed-by: Eric Blake Signed-off-by: Eric Blake --- qapi/misc.json | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/qapi/misc.json b/qapi/misc.json index b2f69eb4ece..b6ebf210ba8 100644 --- a/qapi/misc.json +++ b/qapi/misc.json @@ -3242,3 +3242,40 @@ # Since: 2.9 ## { 'command': 'query-vm-generation-id', 'returns': 'GuidInfo' } + +## +# @CommandDropReason: +# +# Reasons that caused one command to be dropped. +# +# @queue-full: the command queue is full. This can only occur when +# the client sends a new non-oob command before the +# response to the previous non-oob command has been +# received. +# +# Since: 2.12 +## +{ 'enum': 'CommandDropReason', + 'data': [ 'queue-full' ] } + +## +# @COMMAND_DROPPED: +# +# Emitted when a command is dropped due to some reason. Commands can +# only be dropped when the oob capability is enabled. +# +# @id: The dropped command's "id" field. +# +# @reason: The reason why the command is dropped. +# +# Since: 2.12 +# +# Example: +# +# { "event": "COMMAND_DROPPED", +# "data": {"result": {"id": "libvirt-102", +# "reason": "queue-full" } } } +# +## +{ 'event': 'COMMAND_DROPPED' , + 'data': { 'id': 'any', 'reason': 'CommandDropReason' } } --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 1520882514836490.3956956200145; Mon, 12 Mar 2018 12:21:54 -0700 (PDT) Received: from localhost ([::1]:34173 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evT18-0008Jf-2c for importer@patchew.org; Mon, 12 Mar 2018 15:21:54 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45420) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJc-0000rr-2h for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:57 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJb-00063K-0H for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:56 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:33612 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 1evSJa-000635-Qw for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:54 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5FEF9814F0D2 for ; Mon, 12 Mar 2018 18:36:54 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id ED9BF215CDAC; Mon, 12 Mar 2018 18:36:53 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:36:18 -0500 Message-Id: <20180312183628.394722-28-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 12 Mar 2018 18:36:54 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 12 Mar 2018 18:36:54 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@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 27/36] monitor: send event when command queue full 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: Markus Armbruster , Peter Xu , "Dr. David Alan Gilbert" 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: Peter Xu Set maximum QMP command queue length to 8. If the queue is full, instead of queuing the command, we directly return a "command-dropped" event, telling the client that a specific command is dropped. Note that this flow control mechanism is only valid if OOB is enabled. If it's not, the effective queue length will always be 1, which strictly follows original behavior of QMP command handling (which never drops messages). Reviewed-by: Stefan Hajnoczi Signed-off-by: Peter Xu Message-Id: <20180309090006.10018-17-peterx@redhat.com> Reviewed-by: Eric Blake [eblake: commit message grammar, abort on failure to send event] Signed-off-by: Eric Blake --- monitor.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/monitor.c b/monitor.c index 07446d6b879..d28457d60d7 100644 --- a/monitor.c +++ b/monitor.c @@ -4007,6 +4007,8 @@ static void monitor_qmp_bh_dispatcher(void *data) } } +#define QMP_REQ_QUEUE_LEN_MAX (8) + static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens) { QObject *req, *id =3D NULL; @@ -4040,6 +4042,9 @@ static void handle_qmp_command(JSONMessageParser *par= ser, GQueue *tokens) req_obj->req =3D req; req_obj->need_resume =3D false; + /* Protect qmp_requests and fetching its length. */ + qemu_mutex_lock(&mon->qmp.qmp_queue_lock); + /* * If OOB is not enabled on the current monitor, we'll emulate the * old behavior that we won't process the current monitor any more @@ -4049,6 +4054,18 @@ static void handle_qmp_command(JSONMessageParser *pa= rser, GQueue *tokens) if (!qmp_oob_enabled(mon)) { monitor_suspend(mon); req_obj->need_resume =3D true; + } else { + /* Drop the request if queue is full. */ + if (mon->qmp.qmp_requests->length >=3D QMP_REQ_QUEUE_LEN_MAX) { + qemu_mutex_unlock(&mon->qmp.qmp_queue_lock); + qapi_event_send_command_dropped(id, + COMMAND_DROP_REASON_QUEUE_FULL, + &error_abort); + qobject_decref(id); + qobject_decref(req); + g_free(req_obj); + return; + } } /* @@ -4056,7 +4073,6 @@ static void handle_qmp_command(JSONMessageParser *par= ser, GQueue *tokens) * handled in time order. Ownership for req_obj, req, id, * etc. will be delivered to the handler side. */ - qemu_mutex_lock(&mon->qmp.qmp_queue_lock); g_queue_push_tail(mon->qmp.qmp_requests, req_obj); qemu_mutex_unlock(&mon->qmp.qmp_queue_lock); --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 1520881876727906.3016807244234; Mon, 12 Mar 2018 12:11:16 -0700 (PDT) Received: from localhost ([::1]:34102 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSqp-00089u-Sh for importer@patchew.org; Mon, 12 Mar 2018 15:11:15 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45478) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJd-0000u6-Ql for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:59 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJb-000640-TH for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:57 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:49264 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 1evSJb-00063U-MX for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:55 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 056F94000B6E; Mon, 12 Mar 2018 18:36:55 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8D768215CDAC; Mon, 12 Mar 2018 18:36:54 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:36:19 -0500 Message-Id: <20180312183628.394722-29-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 12 Mar 2018 18:36:55 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 12 Mar 2018 18:36:55 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@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 28/36] qapi: introduce new cmd option "allow-oob" 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: Markus Armbruster , Peter Xu , Michael Roth 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: Peter Xu Here "oob" stands for "Out-Of-Band". When "allow-oob" is set, it means the command allows out-of-band execution. The "oob" idea is proposed by Markus Armbruster in following thread: https://lists.gnu.org/archive/html/qemu-devel/2017-09/msg02057.html This new "allow-oob" boolean will be exposed by "query-qmp-schema" as well for command entries, so that QMP clients can know which commands can be used in out-of-band calls. For example the command "migrate" originally looks like: {"name": "migrate", "ret-type": "17", "meta-type": "command", "arg-type": "86"} And it'll be changed into: {"name": "migrate", "ret-type": "17", "allow-oob": false, "meta-type": "command", "arg-type": "86"} This patch only provides the QMP interface level changes. It does not contain the real out-of-band execution implementation yet. Suggested-by: Markus Armbruster Reviewed-by: Stefan Hajnoczi Reviewed-by: Fam Zheng Signed-off-by: Peter Xu Message-Id: <20180309090006.10018-18-peterx@redhat.com> Reviewed-by: Eric Blake [eblake: rebase on introspection done by qlit] Signed-off-by: Eric Blake --- qapi/introspect.json | 6 +++++- scripts/qapi/commands.py | 18 +++++++++++++----- scripts/qapi/common.py | 15 ++++++++++----- scripts/qapi/doc.py | 2 +- scripts/qapi/introspect.py | 7 +++++-- include/qapi/qmp/dispatch.h | 5 +++-- tests/qapi-schema/test-qapi.py | 2 +- 7 files changed, 38 insertions(+), 17 deletions(-) diff --git a/qapi/introspect.json b/qapi/introspect.json index 5b3e6e9d78b..c7f67b7d78b 100644 --- a/qapi/introspect.json +++ b/qapi/introspect.json @@ -259,12 +259,16 @@ # # @ret-type: the name of the command's result type. # +# @allow-oob: whether the command allows out-of-band execution. +# (Since: 2.12) +# # TODO: @success-response (currently irrelevant, because it's QGA, not QMP) # # Since: 2.5 ## { 'struct': 'SchemaInfoCommand', - 'data': { 'arg-type': 'str', 'ret-type': 'str' } } + 'data': { 'arg-type': 'str', 'ret-type': 'str', + 'allow-oob': 'bool' } } ## # @SchemaInfoEvent: diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py index 21a7e0dbe61..0c5da3a54d6 100644 --- a/scripts/qapi/commands.py +++ b/scripts/qapi/commands.py @@ -193,10 +193,18 @@ out: return ret -def gen_register_command(name, success_response): - options =3D 'QCO_NO_OPTIONS' +def gen_register_command(name, success_response, allow_oob): + options =3D [] + if not success_response: - options =3D 'QCO_NO_SUCCESS_RESP' + options +=3D ['QCO_NO_SUCCESS_RESP'] + if allow_oob: + options +=3D ['QCO_ALLOW_OOB'] + + if not options: + options =3D ['QCO_NO_OPTIONS'] + + options =3D " | ".join(options) ret =3D mcgen(''' qmp_register_command(cmds, "%(name)s", @@ -268,7 +276,7 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds); genc.add(gen_registry(self._regy, self._prefix)) def visit_command(self, name, info, arg_type, ret_type, - gen, success_response, boxed): + gen, success_response, boxed, allow_oob): if not gen: return self._genh.add(gen_command_decl(name, arg_type, boxed, ret_type)) @@ -277,7 +285,7 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds); self._genc.add(gen_marshal_output(ret_type)) self._genh.add(gen_marshal_decl(name)) self._genc.add(gen_marshal(name, arg_type, boxed, ret_type)) - self._regy +=3D gen_register_command(name, success_response) + self._regy +=3D gen_register_command(name, success_response, allow= _oob) def gen_commands(schema, output_dir, prefix): diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index 97e9060b674..2c05e3c2845 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -921,7 +921,8 @@ def check_exprs(exprs): elif 'command' in expr: meta =3D 'command' check_keys(expr_elem, 'command', [], - ['data', 'returns', 'gen', 'success-response', 'box= ed']) + ['data', 'returns', 'gen', 'success-response', + 'boxed', 'allow-oob']) elif 'event' in expr: meta =3D 'event' check_keys(expr_elem, 'event', [], ['data', 'boxed']) @@ -1044,7 +1045,7 @@ class QAPISchemaVisitor(object): pass def visit_command(self, name, info, arg_type, ret_type, - gen, success_response, boxed): + gen, success_response, boxed, allow_oob): pass def visit_event(self, name, info, arg_type, boxed): @@ -1421,7 +1422,7 @@ class QAPISchemaAlternateType(QAPISchemaType): class QAPISchemaCommand(QAPISchemaEntity): def __init__(self, name, info, doc, arg_type, ret_type, - gen, success_response, boxed): + gen, success_response, boxed, allow_oob): QAPISchemaEntity.__init__(self, name, info, doc) assert not arg_type or isinstance(arg_type, str) assert not ret_type or isinstance(ret_type, str) @@ -1432,6 +1433,7 @@ class QAPISchemaCommand(QAPISchemaEntity): self.gen =3D gen self.success_response =3D success_response self.boxed =3D boxed + self.allow_oob =3D allow_oob def check(self, schema): if self._arg_type_name: @@ -1455,7 +1457,8 @@ class QAPISchemaCommand(QAPISchemaEntity): def visit(self, visitor): visitor.visit_command(self.name, self.info, self.arg_type, self.ret_type, - self.gen, self.success_response, self.boxed) + self.gen, self.success_response, + self.boxed, self.allow_oob) class QAPISchemaEvent(QAPISchemaEntity): @@ -1674,6 +1677,7 @@ class QAPISchema(object): gen =3D expr.get('gen', True) success_response =3D expr.get('success-response', True) boxed =3D expr.get('boxed', False) + allow_oob =3D expr.get('allow-oob', False) if isinstance(data, OrderedDict): data =3D self._make_implicit_object_type( name, info, doc, 'arg', self._make_members(data, info)) @@ -1681,7 +1685,8 @@ class QAPISchema(object): assert len(rets) =3D=3D 1 rets =3D self._make_array_type(rets[0], info) self._def_entity(QAPISchemaCommand(name, info, doc, data, rets, - gen, success_response, boxed)) + gen, success_response, + boxed, allow_oob)) def _def_event(self, expr, info, doc): name =3D expr['event'] diff --git a/scripts/qapi/doc.py b/scripts/qapi/doc.py index 79d11bbe9b5..9b312b2c51b 100644 --- a/scripts/qapi/doc.py +++ b/scripts/qapi/doc.py @@ -227,7 +227,7 @@ class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVis= itor): body=3Dtexi_entity(doc, 'Members'))) def visit_command(self, name, info, arg_type, ret_type, - gen, success_response, boxed): + gen, success_response, boxed, allow_oob): doc =3D self.cur_doc if boxed: body =3D texi_body(doc) diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py index 1d46a6d6b6f..f9e67e8227b 100644 --- a/scripts/qapi/introspect.py +++ b/scripts/qapi/introspect.py @@ -41,6 +41,8 @@ def to_qlit(obj, level=3D0, suppress_first_indent=3DFalse= ): ret +=3D 'QLIT_QDICT(((QLitDictEntry[]) {\n' ret +=3D ',\n'.join(elts) + '\n' ret +=3D indent(level) + '}))' + elif isinstance(obj, bool): + ret +=3D 'QLIT_QBOOL(%s)' % ('true' if obj else 'false') else: assert False # not implemented return ret @@ -170,12 +172,13 @@ const QLitObject %(c_name)s =3D %(c_string)s; for m in variants.variants]}) def visit_command(self, name, info, arg_type, ret_type, - gen, success_response, boxed): + gen, success_response, boxed, allow_oob): arg_type =3D arg_type or self._schema.the_empty_object_type ret_type =3D ret_type or self._schema.the_empty_object_type self._gen_qlit(name, 'command', {'arg-type': self._use_type(arg_type), - 'ret-type': self._use_type(ret_type)}) + 'ret-type': self._use_type(ret_type), + 'allow-oob': allow_oob}) def visit_event(self, name, info, arg_type, boxed): arg_type =3D arg_type or self._schema.the_empty_object_type diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h index 1e694b5ecf9..26eb13ff417 100644 --- a/include/qapi/qmp/dispatch.h +++ b/include/qapi/qmp/dispatch.h @@ -20,8 +20,9 @@ typedef void (QmpCommandFunc)(QDict *, QObject **, Error = **); typedef enum QmpCommandOptions { - QCO_NO_OPTIONS =3D 0x0, - QCO_NO_SUCCESS_RESP =3D 0x1, + QCO_NO_OPTIONS =3D 0x0, + QCO_NO_SUCCESS_RESP =3D (1U << 0), + QCO_ALLOW_OOB =3D (1U << 1), } QmpCommandOptions; typedef struct QmpCommand diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py index 67e417e2980..10e68b01d98 100644 --- a/tests/qapi-schema/test-qapi.py +++ b/tests/qapi-schema/test-qapi.py @@ -42,7 +42,7 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor): self._print_variants(variants) def visit_command(self, name, info, arg_type, ret_type, - gen, success_response, boxed): + gen, success_response, boxed, allow_oob): print('command %s %s -> %s' % \ (name, arg_type and arg_type.name, ret_type and ret_type.nam= e)) print(' gen=3D%s success_response=3D%s boxed=3D%s' % \ --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 1520882677041159.1097318343476; Mon, 12 Mar 2018 12:24:37 -0700 (PDT) Received: from localhost ([::1]:34191 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evT3k-0002Jg-9H for importer@patchew.org; Mon, 12 Mar 2018 15:24:36 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45480) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJd-0000u7-RB for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:59 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJc-00064N-A3 for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:57 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:33614 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 1evSJc-00063l-3s for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:56 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A9A7A814F0D2; Mon, 12 Mar 2018 18:36:55 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id 303DC215CDAC; Mon, 12 Mar 2018 18:36:55 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:36:20 -0500 Message-Id: <20180312183628.394722-30-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 12 Mar 2018 18:36:55 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 12 Mar 2018 18:36:55 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@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 29/36] qmp: support out-of-band (oob) execution 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: Michael Roth , Markus Armbruster , Peter Xu , "Dr. David Alan Gilbert" 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: Peter Xu Having "allow-oob":true for a command does not mean that this command will always be run in out-of-band mode. The out-of-band quick path will only be executed if we specify the extra "run-oob" flag when sending the QMP request: { "execute": "command-that-allows-oob", "arguments": { ... }, "control": { "run-oob": true } } The "control" key is introduced to store this extra flag. "control" field is used to store arguments that are shared by all the commands, rather than command specific arguments. Let "run-oob" be the first. Note that in the patch I exported qmp_dispatch_check_obj() to be used to check the request earlier, and at the same time allowed "id" field to be there since actually we always allow that. Reviewed-by: Stefan Hajnoczi Signed-off-by: Peter Xu Message-Id: <20180309090006.10018-19-peterx@redhat.com> Reviewed-by: Eric Blake [eblake: rebase to qobject_to(), spelling fix] Signed-off-by: Eric Blake --- include/qapi/qmp/dispatch.h | 2 ++ monitor.c | 84 ++++++++++++++++++++++++++++++++++++++++-= ---- qapi/qmp-dispatch.c | 33 +++++++++++++++++- trace-events | 2 ++ 4 files changed, 111 insertions(+), 10 deletions(-) diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h index 26eb13ff417..ffb4652f716 100644 --- a/include/qapi/qmp/dispatch.h +++ b/include/qapi/qmp/dispatch.h @@ -48,6 +48,8 @@ bool qmp_command_is_enabled(const QmpCommand *cmd); const char *qmp_command_name(const QmpCommand *cmd); bool qmp_has_success_response(const QmpCommand *cmd); QObject *qmp_build_error_object(Error *err); +QDict *qmp_dispatch_check_obj(const QObject *request, Error **errp); +bool qmp_is_oob(QDict *dict); typedef void (*qmp_cmd_callback_fn)(QmpCommand *cmd, void *opaque); diff --git a/monitor.c b/monitor.c index d28457d60d7..3b7a4a5c3a7 100644 --- a/monitor.c +++ b/monitor.c @@ -1110,6 +1110,44 @@ static void qmp_caps_apply(Monitor *mon, QMPCapabili= tyList *list) } } +/* + * Return true if check successful, or false otherwise. When false is + * returned, detailed error will be in errp if provided. + */ +static bool qmp_cmd_oob_check(Monitor *mon, QDict *req, Error **errp) +{ + const char *command; + QmpCommand *cmd; + + command =3D qdict_get_try_str(req, "execute"); + if (!command) { + error_setg(errp, "Command field 'execute' missing"); + return false; + } + + cmd =3D qmp_find_command(mon->qmp.commands, command); + if (!cmd) { + error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND, + "The command %s has not been found", command); + return false; + } + + if (qmp_is_oob(req)) { + if (!qmp_oob_enabled(mon)) { + error_setg(errp, "Please enable Out-Of-Band first " + "for the session during capabilities negotiation"); + return false; + } + if (!(cmd->options & QCO_ALLOW_OOB)) { + error_setg(errp, "The command %s does not support OOB", + command); + return false; + } + } + + return true; +} + void qmp_qmp_capabilities(bool has_enable, QMPCapabilityList *enable, Error **errp) { @@ -4001,6 +4039,7 @@ static void monitor_qmp_bh_dispatcher(void *data) QMPRequest *req_obj =3D monitor_qmp_requests_pop_one(); if (req_obj) { + trace_monitor_qmp_cmd_in_band(qobject_get_try_str(req_obj->id) ?: = ""); monitor_qmp_dispatch_one(req_obj); /* Reschedule instead of looping so the main loop stays responsive= */ qemu_bh_schedule(mon_global.qmp_dispatcher_bh); @@ -4024,17 +4063,31 @@ static void handle_qmp_command(JSONMessageParser *p= arser, GQueue *tokens) error_setg(&err, QERR_JSON_PARSING); } if (err) { - monitor_qmp_respond(mon, NULL, err, NULL); - qobject_decref(req); - return; + goto err; } - qdict =3D qobject_to(QDict, req); - if (qdict) { - id =3D qdict_get(qdict, "id"); - qobject_incref(id); - qdict_del(qdict, "id"); - } /* else will fail qmp_dispatch() */ + /* Check against the request in general layout */ + qdict =3D qmp_dispatch_check_obj(req, &err); + if (!qdict) { + goto err; + } + + /* Check against OOB specific */ + if (!qmp_cmd_oob_check(mon, qdict, &err)) { + goto err; + } + + id =3D qdict_get(qdict, "id"); + + /* When OOB is enabled, the "id" field is mandatory. */ + if (qmp_oob_enabled(mon) && !id) { + error_setg(&err, "Out-Of-Band capability requires that " + "every command contains an 'id' field"); + goto err; + } + + qobject_incref(id); + qdict_del(qdict, "id"); req_obj =3D g_new0(QMPRequest, 1); req_obj->mon =3D mon; @@ -4042,6 +4095,14 @@ static void handle_qmp_command(JSONMessageParser *pa= rser, GQueue *tokens) req_obj->req =3D req; req_obj->need_resume =3D false; + if (qmp_is_oob(qdict)) { + /* Out-Of-Band (OOB) requests are executed directly in parser. */ + trace_monitor_qmp_cmd_out_of_band(qobject_get_try_str(req_obj->id) + ?: ""); + monitor_qmp_dispatch_one(req_obj); + return; + } + /* Protect qmp_requests and fetching its length. */ qemu_mutex_lock(&mon->qmp.qmp_queue_lock); @@ -4078,6 +4139,11 @@ static void handle_qmp_command(JSONMessageParser *pa= rser, GQueue *tokens) /* Kick the dispatcher routine */ qemu_bh_schedule(mon_global.qmp_dispatcher_bh); + return; + +err: + monitor_qmp_respond(mon, NULL, err, NULL); + qobject_decref(req); } static void monitor_qmp_read(void *opaque, const uint8_t *buf, int size) diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index af537f3d7d2..dd059072651 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -17,8 +17,9 @@ #include "qapi/qmp/json-parser.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qjson.h" +#include "qapi/qmp/qbool.h" -static QDict *qmp_dispatch_check_obj(const QObject *request, Error **errp) +QDict *qmp_dispatch_check_obj(const QObject *request, Error **errp) { const QDictEntry *ent; const char *arg_name; @@ -50,6 +51,14 @@ static QDict *qmp_dispatch_check_obj(const QObject *requ= est, Error **errp) "QMP input member 'arguments' must be an object= "); return NULL; } + } else if (!strcmp(arg_name, "id")) { + continue; + } else if (!strcmp(arg_name, "control")) { + if (qobject_type(arg_obj) !=3D QTYPE_QDICT) { + error_setg(errp, + "QMP input member 'control' must be a dict"); + return NULL; + } } else { error_setg(errp, "QMP input member '%s' is unexpected", arg_name); @@ -120,6 +129,28 @@ QObject *qmp_build_error_object(Error *err) error_get_pretty(err)); } +/* + * Detect whether a request should be run out-of-band, by quickly + * peeking at whether we have: { "control": { "run-oob": true } }. By + * default commands are run in-band. + */ +bool qmp_is_oob(QDict *dict) +{ + QBool *bool_obj; + + dict =3D qdict_get_qdict(dict, "control"); + if (!dict) { + return false; + } + + bool_obj =3D qobject_to(QBool, qdict_get(dict, "run-oob")); + if (!bool_obj) { + return false; + } + + return qbool_get_bool(bool_obj); +} + QObject *qmp_dispatch(QmpCommandList *cmds, QObject *request) { Error *err =3D NULL; diff --git a/trace-events b/trace-events index fe10c3b487c..bd036da278d 100644 --- a/trace-events +++ b/trace-events @@ -48,6 +48,8 @@ monitor_protocol_event_queue(uint32_t event, void *qdict,= uint64_t rate) "event=3D handle_hmp_command(void *mon, const char *cmdline) "mon %p cmdline: %s" handle_qmp_command(void *mon, const char *req) "mon %p req: %s" monitor_suspend(void *ptr, int cnt) "mon %p: %d" +monitor_qmp_cmd_in_band(const char *id) "%s" +monitor_qmp_cmd_out_of_band(const char *id) "%s" # dma-helpers.c dma_blk_io(void *dbs, void *bs, int64_t offset, bool to_dev) "dbs=3D%p bs= =3D%p offset=3D%" PRId64 " to_dev=3D%d" --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 1520882808045196.65345285191495; Mon, 12 Mar 2018 12:26:48 -0700 (PDT) Received: from localhost ([::1]:34210 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evT5m-00047u-9t for importer@patchew.org; Mon, 12 Mar 2018 15:26:42 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45493) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJe-0000ul-9X for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:59 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJc-00064l-QQ for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:58 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:49268 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 1evSJc-00064W-LG for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:56 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 426924000B6E for ; Mon, 12 Mar 2018 18:36:56 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id CD9DE215CDAC; Mon, 12 Mar 2018 18:36:55 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:36:21 -0500 Message-Id: <20180312183628.394722-31-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 12 Mar 2018 18:36:56 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 12 Mar 2018 18:36:56 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@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 30/36] qmp: isolate responses into io thread 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: Markus Armbruster , Peter Xu , "Dr. David Alan Gilbert" 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: Peter Xu For those monitors who have enabled IO thread, we'll offload the responding procedure into IO thread. The main reason is that chardev is not thread safe, and we need to do all the read/write IOs in the same thread. For use_io_thr=3Dtrue monitors, that thread is the IO thread. We do this isolation in similar pattern as what we have done to the request queue: we first create one response queue for each monitor, then instead of replying directly in the main thread, we queue the responses and kick the IO thread to do the rest of the job for us. A funny thing after doing this is that, when the QMP clients send "quit" to QEMU, it's possible that we close the IOThread even earlier than replying to that "quit". So another thing we need to do before cleaning up the monitors is that we need to flush the response queue (we don't need to do that for command queue; after all we are quitting) to make sure replies for handled commands are always flushed back to clients. Reviewed-by: Fam Zheng Reviewed-by: Stefan Hajnoczi Signed-off-by: Peter Xu Message-Id: <20180309090006.10018-20-peterx@redhat.com> Signed-off-by: Eric Blake --- monitor.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/monitor.c b/monitor.c index 3b7a4a5c3a7..905d5efc6fa 100644 --- a/monitor.c +++ b/monitor.c @@ -179,6 +179,8 @@ typedef struct { QemuMutex qmp_queue_lock; /* Input queue that holds all the parsed QMP requests */ GQueue *qmp_requests; + /* Output queue contains all the QMP responses in order */ + GQueue *qmp_responses; } MonitorQMP; /* @@ -205,6 +207,7 @@ struct Monitor { bool skip_flush; bool use_io_thr; + /* We can't access guest memory when holding the lock */ QemuMutex out_lock; QString *outbuf; guint out_watch; @@ -227,6 +230,8 @@ static struct { IOThread *mon_iothread; /* Bottom half to dispatch the requests received from IO thread */ QEMUBH *qmp_dispatcher_bh; + /* Bottom half to deliver the responses back to clients */ + QEMUBH *qmp_respond_bh; } mon_global; /* QMP checker flags */ @@ -416,7 +421,8 @@ int monitor_fprintf(FILE *stream, const char *fmt, ...) return 0; } -static void monitor_json_emitter(Monitor *mon, const QObject *data) +static void monitor_json_emitter_raw(Monitor *mon, + QObject *data) { QString *json; @@ -430,6 +436,71 @@ static void monitor_json_emitter(Monitor *mon, const Q= Object *data) QDECREF(json); } +static void monitor_json_emitter(Monitor *mon, QObject *data) +{ + if (mon->use_io_thr) { + /* + * If using IO thread, we need to queue the item so that IO + * thread will do the rest for us. Take refcount so that + * caller won't free the data (which will be finally freed in + * responder thread). + */ + qobject_incref(data); + qemu_mutex_lock(&mon->qmp.qmp_queue_lock); + g_queue_push_tail(mon->qmp.qmp_responses, (void *)data); + qemu_mutex_unlock(&mon->qmp.qmp_queue_lock); + qemu_bh_schedule(mon_global.qmp_respond_bh); + } else { + /* + * If not using monitor IO thread, then we are in main thread. + * Do the emission right away. + */ + monitor_json_emitter_raw(mon, data); + } +} + +struct QMPResponse { + Monitor *mon; + QObject *data; +}; +typedef struct QMPResponse QMPResponse; + +/* + * Return one QMPResponse. The response is only valid if + * response.data is not NULL. + */ +static QMPResponse monitor_qmp_response_pop_one(void) +{ + Monitor *mon; + QObject *data =3D NULL; + + qemu_mutex_lock(&monitor_lock); + QTAILQ_FOREACH(mon, &mon_list, entry) { + qemu_mutex_lock(&mon->qmp.qmp_queue_lock); + data =3D g_queue_pop_head(mon->qmp.qmp_responses); + qemu_mutex_unlock(&mon->qmp.qmp_queue_lock); + if (data) { + break; + } + } + qemu_mutex_unlock(&monitor_lock); + return (QMPResponse) { .mon =3D mon, .data =3D data }; +} + +static void monitor_qmp_bh_responder(void *opaque) +{ + QMPResponse response; + + while (true) { + response =3D monitor_qmp_response_pop_one(); + if (!response.data) { + break; + } + monitor_json_emitter_raw(response.mon, response.data); + qobject_decref(response.data); + } +} + static MonitorQAPIEventConf monitor_qapi_event_conf[QAPI_EVENT__MAX] =3D { /* Limit guest-triggerable events to 1 per second */ [QAPI_EVENT_RTC_CHANGE] =3D { 1000 * SCALE_MS }, @@ -616,6 +687,7 @@ static void monitor_data_init(Monitor *mon, bool skip_f= lush, mon->skip_flush =3D skip_flush; mon->use_io_thr =3D use_io_thr; mon->qmp.qmp_requests =3D g_queue_new(); + mon->qmp.qmp_responses =3D g_queue_new(); } static void monitor_data_destroy(Monitor *mon) @@ -630,6 +702,7 @@ static void monitor_data_destroy(Monitor *mon) qemu_mutex_destroy(&mon->out_lock); qemu_mutex_destroy(&mon->qmp.qmp_queue_lock); g_queue_free(mon->qmp.qmp_requests); + g_queue_free(mon->qmp.qmp_responses); } char *qmp_human_monitor_command(const char *command_line, bool has_cpu_ind= ex, @@ -4367,6 +4440,15 @@ static void monitor_iothread_init(void) mon_global.qmp_dispatcher_bh =3D aio_bh_new(qemu_get_aio_context(), monitor_qmp_bh_dispatcher, NULL); + + /* + * Unlike the dispatcher BH, this must be run on the monitor IO + * thread, so that monitors that are using IO thread will make + * sure read/write operations are all done on the IO thread. + */ + mon_global.qmp_respond_bh =3D aio_bh_new(monitor_get_aio_context(), + monitor_qmp_bh_responder, + NULL); } void monitor_init_globals(void) @@ -4505,9 +4587,19 @@ void monitor_cleanup(void) */ iothread_stop(mon_global.mon_iothread); + /* + * After we have IOThread to send responses, it's possible that + * when we stop the IOThread there are still replies queued in the + * responder queue. Flush all of them. Note that even after this + * flush it's still possible that out buffer is not flushed. + * It'll be done in below monitor_flush() as the last resort. + */ + monitor_qmp_bh_responder(NULL); + qemu_mutex_lock(&monitor_lock); QTAILQ_FOREACH_SAFE(mon, &mon_list, entry, next) { QTAILQ_REMOVE(&mon_list, mon, entry); + monitor_flush(mon); monitor_data_destroy(mon); g_free(mon); } @@ -4516,6 +4608,8 @@ void monitor_cleanup(void) /* QEMUBHs needs to be deleted before destroying the IOThread. */ qemu_bh_delete(mon_global.qmp_dispatcher_bh); mon_global.qmp_dispatcher_bh =3D NULL; + qemu_bh_delete(mon_global.qmp_respond_bh); + mon_global.qmp_respond_bh =3D NULL; iothread_destroy(mon_global.mon_iothread); mon_global.mon_iothread =3D NULL; --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 1520881273755703.7009446856422; Mon, 12 Mar 2018 12:01:13 -0700 (PDT) Received: from localhost ([::1]:34028 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSh6-0008AF-Vo for importer@patchew.org; Mon, 12 Mar 2018 15:01:13 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45488) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJe-0000uX-5g for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:59 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJd-00065C-By for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:58 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:49270 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 1evSJd-00064s-7s for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:57 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C0B514000B6E for ; Mon, 12 Mar 2018 18:36:56 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id 66BC1215CDAC; Mon, 12 Mar 2018 18:36:56 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:36:22 -0500 Message-Id: <20180312183628.394722-32-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 12 Mar 2018 18:36:56 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 12 Mar 2018 18:36:56 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@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 31/36] monitor: enable IO thread for (qmp & !mux) typed 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: "Dr. David Alan Gilbert" , Peter Xu , Markus Armbruster 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: Peter Xu Start to use dedicate IO thread for QMP monitors that are not using MUXed chardev. Reviewed-by: Fam Zheng Reviewed-by: Stefan Hajnoczi Signed-off-by: Peter Xu Message-Id: <20180309090006.10018-21-peterx@redhat.com> Signed-off-by: Eric Blake --- monitor.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/monitor.c b/monitor.c index 905d5efc6fa..dea4111e693 100644 --- a/monitor.c +++ b/monitor.c @@ -36,6 +36,7 @@ #include "net/slirp.h" #include "chardev/char-fe.h" #include "chardev/char-io.h" +#include "chardev/char-mux.h" #include "ui/qemu-spice.h" #include "sysemu/numa.h" #include "monitor/monitor.h" @@ -4533,8 +4534,10 @@ static void monitor_qmp_setup_handlers_bh(void *opaq= ue) void monitor_init(Chardev *chr, int flags) { Monitor *mon =3D g_malloc(sizeof(*mon)); + /* Enable IOThread for QMPs that are not using MUX chardev backends. */ + bool use_io_thr =3D (!CHARDEV_IS_MUX(chr)) && (flags & MONITOR_USE_CON= TROL); - monitor_data_init(mon, false, false); + monitor_data_init(mon, false, use_io_thr); qemu_chr_fe_init(&mon->chr, chr, &error_abort); mon->flags =3D flags; --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 1520882930074809.8513730859007; Mon, 12 Mar 2018 12:28:50 -0700 (PDT) Received: from localhost ([::1]:34221 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evT7o-0005vN-Fd for importer@patchew.org; Mon, 12 Mar 2018 15:28:48 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45504) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJe-0000vL-N2 for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:59 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJd-00065e-QV for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:58 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:58844 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 1evSJd-00065I-MR for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:57 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4B2FF401C9AE for ; Mon, 12 Mar 2018 18:36:57 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id E5CA3215CDAC; Mon, 12 Mar 2018 18:36:56 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:36:23 -0500 Message-Id: <20180312183628.394722-33-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Mon, 12 Mar 2018 18:36:57 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Mon, 12 Mar 2018 18:36:57 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@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 32/36] qmp: add command "x-oob-test" 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: Markus Armbruster , Peter Xu 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: Peter Xu This command is only used to test OOB functionality. It should not be used for any other purposes. Reviewed-by: Stefan Hajnoczi Reviewed-by: Fam Zheng Signed-off-by: Peter Xu Message-Id: <20180309090006.10018-22-peterx@redhat.com> Reviewed-by: Eric Blake [eblake: grammar tweak] Signed-off-by: Eric Blake --- qapi/misc.json | 18 ++++++++++++++++++ qmp.c | 16 ++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/qapi/misc.json b/qapi/misc.json index b6ebf210ba8..fc3550f3acc 100644 --- a/qapi/misc.json +++ b/qapi/misc.json @@ -3279,3 +3279,21 @@ ## { 'event': 'COMMAND_DROPPED' , 'data': { 'id': 'any', 'reason': 'CommandDropReason' } } + +## +# @x-oob-test: +# +# Test OOB functionality. When sending this command with lock=3Dtrue, +# it'll try to hang the dispatcher. When sending it with lock=3Dfalse, +# it'll try to notify the locked thread to continue. Note: it should +# only be used by QMP test program rather than anything else. +# +# Since: 2.12 +# +# Example: +# +# { "execute": "x-oob-test", +# "arguments": { "lock": true } } +## +{ 'command': 'x-oob-test', 'data' : { 'lock': 'bool' }, + 'allow-oob': true } diff --git a/qmp.c b/qmp.c index 7e606d84867..ea3760acb12 100644 --- a/qmp.c +++ b/qmp.c @@ -770,3 +770,19 @@ MemoryInfo *qmp_query_memory_size_summary(Error **errp) return mem_info; } + +static QemuSemaphore x_oob_test_sem; + +static void __attribute__((constructor)) x_oob_test_init(void) +{ + qemu_sem_init(&x_oob_test_sem, 0); +} + +void qmp_x_oob_test(bool lock, Error **errp) +{ + if (lock) { + qemu_sem_wait(&x_oob_test_sem); + } else { + qemu_sem_post(&x_oob_test_sem); + } +} --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 1520881619189439.91898922158987; Mon, 12 Mar 2018 12:06:59 -0700 (PDT) Received: from localhost ([::1]:34069 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSmg-0004Td-BX for importer@patchew.org; Mon, 12 Mar 2018 15:06:58 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45523) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJf-0000vp-7S for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:37:02 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJe-000667-AW for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:59 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:33618 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 1evSJe-00065w-7C for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:58 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C93ED814F0D2 for ; Mon, 12 Mar 2018 18:36:57 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6FA7E215CDAC; Mon, 12 Mar 2018 18:36:57 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:36:24 -0500 Message-Id: <20180312183628.394722-34-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 12 Mar 2018 18:36:57 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 12 Mar 2018 18:36:57 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@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 33/36] tests: qmp-test: verify command batching 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: Markus Armbruster , Peter Xu 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: Peter Xu OOB introduced DROP event for flow control. This should not affect old QMP clients. Add a command batching check to make sure of it. Reviewed-by: Stefan Hajnoczi Signed-off-by: Peter Xu Message-Id: <20180309090006.10018-23-peterx@redhat.com> Reviewed-by: Eric Blake Signed-off-by: Eric Blake --- tests/qmp-test.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/qmp-test.c b/tests/qmp-test.c index a8384bdda3b..fd4033a13fd 100644 --- a/tests/qmp-test.c +++ b/tests/qmp-test.c @@ -82,6 +82,7 @@ static void test_qmp_protocol(void) QTestState *qts; const QListEntry *entry; QString *qstr; + int i; qts =3D qtest_init_without_qmp_handshake(common_args); @@ -139,6 +140,27 @@ static void test_qmp_protocol(void) g_assert_cmpint(qdict_get_int(resp, "id"), =3D=3D, 2); QDECREF(resp); + /* + * Test command batching. In current test OOB is not enabled, we + * should be able to run as many commands in batch as we like. + * Using 16 (>8, which is OOB queue length) to make sure OOB won't + * break existing clients. Note: this test does not control the + * scheduling of QEMU's QMP command processing threads so it may + * not really trigger batching inside QEMU. This is just a + * best-effort test. + */ + for (i =3D 0; i < 16; i++) { + qtest_async_qmp(qts, "{ 'execute': 'query-version' }"); + } + /* Verify the replies to make sure no command is dropped. */ + for (i =3D 0; i < 16; i++) { + resp =3D qtest_qmp_receive(qts); + /* It should never be dropped. Each of them should be a reply. */ + g_assert(qdict_haskey(resp, "return")); + g_assert(!qdict_haskey(resp, "event")); + QDECREF(resp); + } + qtest_quit(qts); } --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 1520881401634955.8824227261277; Mon, 12 Mar 2018 12:03:21 -0700 (PDT) Received: from localhost ([::1]:34039 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSjA-0001ML-Rj for importer@patchew.org; Mon, 12 Mar 2018 15:03:20 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45539) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJf-0000ws-Tl for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:37:02 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJe-00066W-Si for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:59 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:49272 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 1evSJe-00066J-Nx for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:36:58 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 550D14000B6E for ; Mon, 12 Mar 2018 18:36:58 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id EE5C7215CDAC; Mon, 12 Mar 2018 18:36:57 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:36:25 -0500 Message-Id: <20180312183628.394722-35-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 12 Mar 2018 18:36:58 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 12 Mar 2018 18:36:58 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@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 34/36] tests: qmp-test: add oob test 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: Markus Armbruster , Peter Xu 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: Peter Xu Test the new OOB capability. Here we used the new "x-oob-test" command. First, we send a lock=3Dtrue and oob=3Dfalse command to hang the main thread. Then send another lock=3Dfalse and oob=3Dtrue command (which will be run inside parser this time) to free that hanged command. Reviewed-by: Stefan Hajnoczi Signed-off-by: Peter Xu Message-Id: <20180309090006.10018-24-peterx@redhat.com> Reviewed-by: Eric Blake [eblake: grammar tweaks] Signed-off-by: Eric Blake --- tests/qmp-test.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 65 insertions(+) diff --git a/tests/qmp-test.c b/tests/qmp-test.c index fd4033a13fd..17cf4ccf4c9 100644 --- a/tests/qmp-test.c +++ b/tests/qmp-test.c @@ -164,6 +164,70 @@ static void test_qmp_protocol(void) qtest_quit(qts); } +/* Tests for Out-Of-Band support. */ +static void test_qmp_oob(void) +{ + QDict *resp; + int acks =3D 0; + const char *cmd_id; + + global_qtest =3D qtest_init_without_qmp_handshake(common_args); + + /* Ignore the greeting message. */ + resp =3D qmp_receive(); + g_assert(qdict_get_qdict(resp, "QMP")); + QDECREF(resp); + + /* Try a fake capability, it should fail. */ + resp =3D qmp("{ 'execute': 'qmp_capabilities', " + " 'arguments': { 'enable': [ 'cap-does-not-exist' ] } }"); + g_assert(qdict_haskey(resp, "error")); + QDECREF(resp); + + /* Now, enable OOB in current QMP session, it should succeed. */ + resp =3D qmp("{ 'execute': 'qmp_capabilities', " + " 'arguments': { 'enable': [ 'oob' ] } }"); + g_assert(qdict_haskey(resp, "return")); + QDECREF(resp); + + /* + * Try any command that does not support OOB but with OOB flag. We + * should get failure. + */ + resp =3D qmp("{ 'execute': 'query-cpus'," + " 'control': { 'run-oob': true } }"); + g_assert(qdict_haskey(resp, "error")); + QDECREF(resp); + + /* + * First send the "x-oob-test" command with lock=3Dtrue and + * oob=3Dfalse, it should hang the dispatcher and main thread; + * later, we send another lock=3Dfalse with oob=3Dtrue to continue + * that thread processing. Finally we should receive replies from + * both commands. + */ + qmp_async("{ 'execute': 'x-oob-test'," + " 'arguments': { 'lock': true }, " + " 'id': 'lock-cmd'}"); + qmp_async("{ 'execute': 'x-oob-test', " + " 'arguments': { 'lock': false }, " + " 'control': { 'run-oob': true }, " + " 'id': 'unlock-cmd' }"); + + /* Ignore all events. Wait for 2 acks */ + while (acks < 2) { + resp =3D qmp_receive(); + cmd_id =3D qdict_get_str(resp, "id"); + if (!g_strcmp0(cmd_id, "lock-cmd") || + !g_strcmp0(cmd_id, "unlock-cmd")) { + acks++; + } + QDECREF(resp); + } + + qtest_end(); +} + static int query_error_class(const char *cmd) { static struct { @@ -343,6 +407,7 @@ int main(int argc, char *argv[]) g_test_init(&argc, &argv, NULL); qtest_add_func("qmp/protocol", test_qmp_protocol); + qtest_add_func("qmp/oob", test_qmp_oob); qmp_schema_init(&schema); add_query_tests(&schema); --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 1520883048568848.1650599003655; Mon, 12 Mar 2018 12:30:48 -0700 (PDT) Received: from localhost ([::1]:34240 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evT9j-0007el-NQ for importer@patchew.org; Mon, 12 Mar 2018 15:30:47 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45600) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJl-00013H-8R for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:37:06 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJk-000697-3b for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:37:05 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:33622 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 1evSJf-00066s-Hb; Mon, 12 Mar 2018 14:36:59 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 212BC814F0D2; Mon, 12 Mar 2018 18:36:59 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id 79158215CDAC; Mon, 12 Mar 2018 18:36:58 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:36:26 -0500 Message-Id: <20180312183628.394722-36-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 12 Mar 2018 18:36:59 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 12 Mar 2018 18:36:59 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@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 35/36] block/accounting: introduce latency histogram X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Vladimir Sementsov-Ogievskiy , "open list:Block layer core" , Max Reitz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Vladimir Sementsov-Ogievskiy Introduce latency histogram statics for block devices. For each accounted operation type, the latency region [0, +inf) is divided into subregions by several points. Then, calculate hits for each subregion. Signed-off-by: Vladimir Sementsov-Ogievskiy Message-Id: <20180309165212.97144-2-vsementsov@virtuozzo.com> Reviewed-by: Eric Blake Reviewed-by: Stefan Hajnoczi Signed-off-by: Eric Blake --- include/block/accounting.h | 35 ++++++++++++++++++ block/accounting.c | 91 ++++++++++++++++++++++++++++++++++++++++++= ++++ 2 files changed, 126 insertions(+) diff --git a/include/block/accounting.h b/include/block/accounting.h index b833d26d6c7..d1f67b10ddf 100644 --- a/include/block/accounting.h +++ b/include/block/accounting.h @@ -27,6 +27,7 @@ #include "qemu/timed-average.h" #include "qemu/thread.h" +#include "qapi/qapi-builtin-types.h" typedef struct BlockAcctTimedStats BlockAcctTimedStats; typedef struct BlockAcctStats BlockAcctStats; @@ -45,6 +46,36 @@ struct BlockAcctTimedStats { QSLIST_ENTRY(BlockAcctTimedStats) entries; }; +typedef struct BlockLatencyHistogram { + /* The following histogram is represented like this: + * + * 5| * + * 4| * + * 3| * * + * 2| * * * + * 1| * * * * + * +------------------ + * 10 50 100 + * + * BlockLatencyHistogram histogram =3D { + * .nbins =3D 4, + * .boundaries =3D {10, 50, 100}, + * .bins =3D {3, 1, 5, 2}, + * }; + * + * @boundaries array define histogram intervals as follows: + * [0, boundaries[0]), [boundaries[0], boundaries[1]), ... + * [boundaries[nbins-2], +inf) + * + * So, for example above, histogram intervals are: + * [0, 10), [10, 50), [50, 100), [100, +inf) + */ + int nbins; + uint64_t *boundaries; /* @nbins-1 numbers here + (all boundaries, except 0 and +inf) */ + uint64_t *bins; +} BlockLatencyHistogram; + struct BlockAcctStats { QemuMutex lock; uint64_t nr_bytes[BLOCK_MAX_IOTYPE]; @@ -57,6 +88,7 @@ struct BlockAcctStats { QSLIST_HEAD(, BlockAcctTimedStats) intervals; bool account_invalid; bool account_failed; + BlockLatencyHistogram latency_histogram[BLOCK_MAX_IOTYPE]; }; typedef struct BlockAcctCookie { @@ -82,5 +114,8 @@ void block_acct_merge_done(BlockAcctStats *stats, enum B= lockAcctType type, int64_t block_acct_idle_time_ns(BlockAcctStats *stats); double block_acct_queue_depth(BlockAcctTimedStats *stats, enum BlockAcctType type); +int block_latency_histogram_set(BlockAcctStats *stats, enum BlockAcctType = type, + uint64List *boundaries); +void block_latency_histograms_clear(BlockAcctStats *stats); #endif diff --git a/block/accounting.c b/block/accounting.c index 87ef5bbfaa0..70a3d9a426c 100644 --- a/block/accounting.c +++ b/block/accounting.c @@ -94,6 +94,94 @@ void block_acct_start(BlockAcctStats *stats, BlockAcctCo= okie *cookie, cookie->type =3D type; } +/* block_latency_histogram_compare_func: + * Compare @key with interval [@it[0], @it[1]). + * Return: -1 if @key < @it[0] + * 0 if @key in [@it[0], @it[1]) + * +1 if @key >=3D @it[1] + */ +static int block_latency_histogram_compare_func(const void *key, const voi= d *it) +{ + uint64_t k =3D *(uint64_t *)key; + uint64_t a =3D ((uint64_t *)it)[0]; + uint64_t b =3D ((uint64_t *)it)[1]; + + return k < a ? -1 : (k < b ? 0 : 1); +} + +static void block_latency_histogram_account(BlockLatencyHistogram *hist, + int64_t latency_ns) +{ + uint64_t *pos; + + if (hist->bins =3D=3D NULL) { + /* histogram disabled */ + return; + } + + + if (latency_ns < hist->boundaries[0]) { + hist->bins[0]++; + return; + } + + if (latency_ns >=3D hist->boundaries[hist->nbins - 2]) { + hist->bins[hist->nbins - 1]++; + return; + } + + pos =3D bsearch(&latency_ns, hist->boundaries, hist->nbins - 2, + sizeof(hist->boundaries[0]), + block_latency_histogram_compare_func); + assert(pos !=3D NULL); + + hist->bins[pos - hist->boundaries + 1]++; +} + +int block_latency_histogram_set(BlockAcctStats *stats, enum BlockAcctType = type, + uint64List *boundaries) +{ + BlockLatencyHistogram *hist =3D &stats->latency_histogram[type]; + uint64List *entry; + uint64_t *ptr; + uint64_t prev =3D 0; + int new_nbins =3D 1; + + for (entry =3D boundaries; entry; entry =3D entry->next) { + if (entry->value <=3D prev) { + return -EINVAL; + } + new_nbins++; + prev =3D entry->value; + } + + hist->nbins =3D new_nbins; + g_free(hist->boundaries); + hist->boundaries =3D g_new(uint64_t, hist->nbins - 1); + for (entry =3D boundaries, ptr =3D hist->boundaries; entry; + entry =3D entry->next, ptr++) + { + *ptr =3D entry->value; + } + + g_free(hist->bins); + hist->bins =3D g_new0(uint64_t, hist->nbins); + + return 0; +} + +void block_latency_histograms_clear(BlockAcctStats *stats) +{ + int i; + + for (i =3D 0; i < BLOCK_MAX_IOTYPE; i++) { + BlockLatencyHistogram *hist =3D &stats->latency_histogram[i]; + g_free(hist->bins); + g_free(hist->boundaries); + memset(hist, 0, sizeof(*hist)); + } +} + static void block_account_one_io(BlockAcctStats *stats, BlockAcctCookie *c= ookie, bool failed) { @@ -116,6 +204,9 @@ static void block_account_one_io(BlockAcctStats *stats,= BlockAcctCookie *cookie, stats->nr_ops[cookie->type]++; } + block_latency_histogram_account(&stats->latency_histogram[cookie->type= ], + latency_ns); + if (!failed || stats->account_failed) { stats->total_time_ns[cookie->type] +=3D latency_ns; stats->last_access_time_ns =3D time_ns; --=20 2.14.3 From nobody Fri Mar 29 06:12:19 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 152088314019423.517594872890868; Mon, 12 Mar 2018 12:32:20 -0700 (PDT) Received: from localhost ([::1]:34243 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evTB6-0008NC-8j for importer@patchew.org; Mon, 12 Mar 2018 15:32:12 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45603) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1evSJl-00013b-HD for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:37:06 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1evSJk-00069C-7q for qemu-devel@nongnu.org; Mon, 12 Mar 2018 14:37:05 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:38342 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 1evSJg-00067M-92; Mon, 12 Mar 2018 14:37:00 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D5531D144E; Mon, 12 Mar 2018 18:36:59 +0000 (UTC) Received: from red.redhat.com (ovpn-121-135.rdu2.redhat.com [10.10.121.135]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4867C215CDAC; Mon, 12 Mar 2018 18:36:59 +0000 (UTC) From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 12 Mar 2018 13:36:27 -0500 Message-Id: <20180312183628.394722-37-eblake@redhat.com> In-Reply-To: <20180312183628.394722-1-eblake@redhat.com> References: <20180312183628.394722-1-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Mon, 12 Mar 2018 18:36:59 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Mon, 12 Mar 2018 18:36:59 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'eblake@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 36/36] qapi: add block latency histogram interface X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Vladimir Sementsov-Ogievskiy , Markus Armbruster , "open list:Block layer core" , Max Reitz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Vladimir Sementsov-Ogievskiy Set (and clear) histograms through new command block-latency-histogram-set and show new statistics in query-blockstats results. For now, the command is marked experimental with prefix 'x-', to gain experience with the interface without being stuck with design decisions. Signed-off-by: Vladimir Sementsov-Ogievskiy Message-Id: <20180309165212.97144-3-vsementsov@virtuozzo.com> Reviewed-by: Eric Blake Reviewed-by: Stefan Hajnoczi [eblake: fix typos, mention x- prefix in commit message] Signed-off-by: Eric Blake --- qapi/block-core.json | 111 +++++++++++++++++++++++++++++++++++++++++++++++= +++- block/qapi.c | 41 +++++++++++++++++++ blockdev.c | 43 ++++++++++++++++++++ 3 files changed, 194 insertions(+), 1 deletion(-) diff --git a/qapi/block-core.json b/qapi/block-core.json index 55dcc8bd85a..233c8719596 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -450,6 +450,106 @@ 'data': {'*name': 'str', 'count': 'int', 'granularity': 'uint32', 'status': 'DirtyBitmapStatus'} } +## +# @BlockLatencyHistogramInfo: +# +# Block latency histogram. +# +# @boundaries: list of interval boundary values in nanoseconds, all greater +# than zero and in ascending order. +# For example, the list [10, 50, 100] produces the following +# histogram intervals: [0, 10), [10, 50), [50, 100), [100, +i= nf). +# +# @bins: list of io request counts corresponding to histogram intervals. +# len(@bins) =3D len(@boundaries) + 1 +# For the example above, @bins may be something like [3, 1, 5, 2], +# and corresponding histogram looks like: +# +# 5| * +# 4| * +# 3| * * +# 2| * * * +# 1| * * * * +# +------------------ +# 10 50 100 +# +# Since: 2.12 +## +{ 'struct': 'BlockLatencyHistogramInfo', + 'data': {'boundaries': ['uint64'], 'bins': ['uint64'] } } + +## +# @x-block-latency-histogram-set: +# +# Manage read, write and flush latency histograms for the device. +# +# If only @device parameter is specified, remove all present latency histo= grams +# for the device. Otherwise, add/reset some of (or all) latency histograms. +# +# @device: device name to set latency histogram for. +# +# @boundaries: list of interval boundary values (see description in +# BlockLatencyHistogramInfo definition). If specified, all +# latency histograms are removed, and empty ones created for = all +# io types with intervals corresponding to @boundaries (excep= t for +# io types, for which specific boundaries are set through the +# following parameters). +# +# @boundaries-read: list of interval boundary values for read latency +# histogram. If specified, old read latency histogram is +# removed, and empty one created with intervals +# corresponding to @boundaries-read. The parameter has h= igher +# priority then @boundaries. +# +# @boundaries-write: list of interval boundary values for write latency +# histogram. +# +# @boundaries-flush: list of interval boundary values for flush latency +# histogram. +# +# Returns: error if device is not found or any boundary arrays are invalid. +# +# Since: 2.12 +# +# Example: set new histograms for all io types with intervals +# [0, 10), [10, 50), [50, 100), [100, +inf): +# +# -> { "execute": "block-latency-histogram-set", +# "arguments": { "device": "drive0", +# "boundaries": [10, 50, 100] } } +# <- { "return": {} } +# +# Example: set new histogram only for write, other histograms will remain +# not changed (or not created): +# +# -> { "execute": "block-latency-histogram-set", +# "arguments": { "device": "drive0", +# "boundaries-write": [10, 50, 100] } } +# <- { "return": {} } +# +# Example: set new histograms with the following intervals: +# read, flush: [0, 10), [10, 50), [50, 100), [100, +inf) +# write: [0, 1000), [1000, 5000), [5000, +inf) +# +# -> { "execute": "block-latency-histogram-set", +# "arguments": { "device": "drive0", +# "boundaries": [10, 50, 100], +# "boundaries-write": [1000, 5000] } } +# <- { "return": {} } +# +# Example: remove all latency histograms: +# +# -> { "execute": "block-latency-histogram-set", +# "arguments": { "device": "drive0" } } +# <- { "return": {} } +## +{ 'command': 'x-block-latency-histogram-set', + 'data': {'device': 'str', + '*boundaries': ['uint64'], + '*boundaries-read': ['uint64'], + '*boundaries-write': ['uint64'], + '*boundaries-flush': ['uint64'] } } + ## # @BlockInfo: # @@ -730,6 +830,12 @@ # @timed_stats: Statistics specific to the set of previously defined # intervals of time (Since 2.5) # +# @x_rd_latency_histogram: @BlockLatencyHistogramInfo. (Since 2.12) +# +# @x_wr_latency_histogram: @BlockLatencyHistogramInfo. (Since 2.12) +# +# @x_flush_latency_histogram: @BlockLatencyHistogramInfo. (Since 2.12) +# # Since: 0.14.0 ## { 'struct': 'BlockDeviceStats', @@ -742,7 +848,10 @@ 'failed_flush_operations': 'int', 'invalid_rd_operations': 'int= ', 'invalid_wr_operations': 'int', 'invalid_flush_operations': 'in= t', 'account_invalid': 'bool', 'account_failed': 'bool', - 'timed_stats': ['BlockDeviceTimedStats'] } } + 'timed_stats': ['BlockDeviceTimedStats'], + '*x_rd_latency_histogram': 'BlockLatencyHistogramInfo', + '*x_wr_latency_histogram': 'BlockLatencyHistogramInfo', + '*x_flush_latency_histogram': 'BlockLatencyHistogramInfo' } } ## # @BlockStats: diff --git a/block/qapi.c b/block/qapi.c index f2e0aa2cbe7..04c6fc69b92 100644 --- a/block/qapi.c +++ b/block/qapi.c @@ -394,6 +394,37 @@ static void bdrv_query_info(BlockBackend *blk, BlockIn= fo **p_info, qapi_free_BlockInfo(info); } +static uint64List *uint64_list(uint64_t *list, int size) +{ + int i; + uint64List *out_list =3D NULL; + uint64List **pout_list =3D &out_list; + + for (i =3D 0; i < size; i++) { + uint64List *entry =3D g_new(uint64List, 1); + entry->value =3D list[i]; + *pout_list =3D entry; + pout_list =3D &entry->next; + } + + *pout_list =3D NULL; + + return out_list; +} + +static void bdrv_latency_histogram_stats(BlockLatencyHistogram *hist, + bool *not_null, + BlockLatencyHistogramInfo **info) +{ + *not_null =3D hist->bins !=3D NULL; + if (*not_null) { + *info =3D g_new0(BlockLatencyHistogramInfo, 1); + + (*info)->boundaries =3D uint64_list(hist->boundaries, hist->nbins = - 1); + (*info)->bins =3D uint64_list(hist->bins, hist->nbins); + } +} + static void bdrv_query_blk_stats(BlockDeviceStats *ds, BlockBackend *blk) { BlockAcctStats *stats =3D blk_get_stats(blk); @@ -459,6 +490,16 @@ static void bdrv_query_blk_stats(BlockDeviceStats *ds,= BlockBackend *blk) dev_stats->avg_wr_queue_depth =3D block_acct_queue_depth(ts, BLOCK_ACCT_WRITE); } + + bdrv_latency_histogram_stats(&stats->latency_histogram[BLOCK_ACCT_READ= ], + &ds->has_x_rd_latency_histogram, + &ds->x_rd_latency_histogram); + bdrv_latency_histogram_stats(&stats->latency_histogram[BLOCK_ACCT_WRIT= E], + &ds->has_x_wr_latency_histogram, + &ds->x_wr_latency_histogram); + bdrv_latency_histogram_stats(&stats->latency_histogram[BLOCK_ACCT_FLUS= H], + &ds->has_x_flush_latency_histogram, + &ds->x_flush_latency_histogram); } static BlockStats *bdrv_query_bds_stats(BlockDriverState *bs, diff --git a/blockdev.c b/blockdev.c index 6a751996022..69cdcc8d59d 100644 --- a/blockdev.c +++ b/blockdev.c @@ -4167,6 +4167,49 @@ void qmp_x_blockdev_set_iothread(const char *node_na= me, StrOrNull *iothread, aio_context_release(old_context); } +void qmp_x_block_latency_histogram_set( + const char *device, + bool has_boundaries, uint64List *boundaries, + bool has_boundaries_read, uint64List *boundaries_read, + bool has_boundaries_write, uint64List *boundaries_write, + bool has_boundaries_flush, uint64List *boundaries_flush, + Error **errp) +{ + BlockBackend *blk =3D blk_by_name(device); + BlockAcctStats *stats; + + if (!blk) { + error_setg(errp, "Device '%s' not found", device); + return; + } + stats =3D blk_get_stats(blk); + + if (!has_boundaries && !has_boundaries_read && !has_boundaries_write && + !has_boundaries_flush) + { + block_latency_histograms_clear(stats); + return; + } + + if (has_boundaries || has_boundaries_read) { + block_latency_histogram_set( + stats, BLOCK_ACCT_READ, + has_boundaries_read ? boundaries_read : boundaries); + } + + if (has_boundaries || has_boundaries_write) { + block_latency_histogram_set( + stats, BLOCK_ACCT_WRITE, + has_boundaries_write ? boundaries_write : boundaries); + } + + if (has_boundaries || has_boundaries_flush) { + block_latency_histogram_set( + stats, BLOCK_ACCT_FLUSH, + has_boundaries_flush ? boundaries_flush : boundaries); + } +} + QemuOptsList qemu_common_drive_opts =3D { .name =3D "drive", .head =3D QTAILQ_HEAD_INITIALIZER(qemu_common_drive_opts.head), --=20 2.14.3