From nobody Mon Apr 29 15:02:43 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1563217840; cv=none; d=zoho.com; s=zohoarc; b=gLE/W+YJePA3pX5mbMSvl70daDqKHi5Mu0tzDu8jPPYdzlAQVaJ5r6Idjgkq/2iJroW+8L2neFfKm9VAijoh+/fpw0zRSGf+NHabRR+bBtvhWavgKHIBNoefTa5nBlD1NiW2rlVx1bk6TI5eTzLdvj1vfmkpx31GHx3deJz369o= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1563217840; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=VV/yqDhtFMC52a8sjalU2ut+XoW5b7fCb2Hmygdnf4k=; b=JthRUWvq5jkQA4cxAoOMWFOWtCRQ63FRNB4ivyREAX1tBuKPiug2+97VA878eWghuXXSLeV7sKdC5H+v8nCCu2jKQw1ViP09IHHZhMoLKBevlKXpEWVYFVxoyUp+Jz7KlyPKahooL6FhsquYQ7MNT4eO/2A3SURX0q+A/MQuxxs= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1563217840746387.36543891414294; Mon, 15 Jul 2019 12:10:40 -0700 (PDT) Received: from localhost ([::1]:42004 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6Mx-00030k-OJ for importer@patchew.org; Mon, 15 Jul 2019 15:10:39 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39479) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6Ml-0002LX-Di for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:10:28 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hn6Mk-0002kx-1K for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:10:27 -0400 Received: from mx1.redhat.com ([209.132.183.28]:54990) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hn6Mj-0002kA-Ox for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:10:25 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 1A10781F0E; Mon, 15 Jul 2019 19:10:25 +0000 (UTC) Received: from localhost (ovpn-112-18.ams2.redhat.com [10.36.112.18]) by smtp.corp.redhat.com (Postfix) with ESMTP id E044C5DA34; Mon, 15 Jul 2019 19:10:18 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Mon, 15 Jul 2019 23:09:42 +0400 Message-Id: <20190715191001.1188-2-marcandre.lureau@redhat.com> In-Reply-To: <20190715191001.1188-1-marcandre.lureau@redhat.com> References: <20190715191001.1188-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Mon, 15 Jul 2019 19:10:25 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v5 01/20] qmp: constify QmpCommand and list X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Markus Armbruster , Michael Roth , "Dr. David Alan Gilbert" , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Since 0b69f6f72ce47a37a749b056b6d5ec64c61f11e8 "qapi: remove qmp_unregister_command()", the command list can be declared const. Signed-off-by: Marc-Andr=C3=A9 Lureau --- include/qapi/qmp/dispatch.h | 9 +++++---- monitor/misc.c | 2 +- monitor/monitor-internal.h | 2 +- qapi/qmp-dispatch.c | 6 +++--- qapi/qmp-registry.c | 6 +++--- qga/commands.c | 2 +- qga/main.c | 6 +++--- 7 files changed, 17 insertions(+), 16 deletions(-) diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h index 9aa426a398..5a9cf82472 100644 --- a/include/qapi/qmp/dispatch.h +++ b/include/qapi/qmp/dispatch.h @@ -39,7 +39,8 @@ typedef QTAILQ_HEAD(QmpCommandList, QmpCommand) QmpComman= dList; =20 void qmp_register_command(QmpCommandList *cmds, const char *name, QmpCommandFunc *fn, QmpCommandOptions options); -QmpCommand *qmp_find_command(QmpCommandList *cmds, const char *name); +const QmpCommand *qmp_find_command(const QmpCommandList *cmds, + const char *name); void qmp_disable_command(QmpCommandList *cmds, const char *name); void qmp_enable_command(QmpCommandList *cmds, const char *name); =20 @@ -47,13 +48,13 @@ bool qmp_command_is_enabled(const QmpCommand *cmd); const char *qmp_command_name(const QmpCommand *cmd); bool qmp_has_success_response(const QmpCommand *cmd); QDict *qmp_error_response(Error *err); -QDict *qmp_dispatch(QmpCommandList *cmds, QObject *request, +QDict *qmp_dispatch(const QmpCommandList *cmds, QObject *request, bool allow_oob); bool qmp_is_oob(const QDict *dict); =20 -typedef void (*qmp_cmd_callback_fn)(QmpCommand *cmd, void *opaque); +typedef void (*qmp_cmd_callback_fn)(const QmpCommand *cmd, void *opaque); =20 -void qmp_for_each_command(QmpCommandList *cmds, qmp_cmd_callback_fn fn, +void qmp_for_each_command(const QmpCommandList *cmds, qmp_cmd_callback_fn = fn, void *opaque); =20 #endif diff --git a/monitor/misc.c b/monitor/misc.c index 00338c002a..a0fc5111c5 100644 --- a/monitor/misc.c +++ b/monitor/misc.c @@ -230,7 +230,7 @@ static void hmp_info_help(Monitor *mon, const QDict *qd= ict) help_cmd(mon, "info"); } =20 -static void query_commands_cb(QmpCommand *cmd, void *opaque) +static void query_commands_cb(const QmpCommand *cmd, void *opaque) { CommandInfoList *info, **list =3D opaque; =20 diff --git a/monitor/monitor-internal.h b/monitor/monitor-internal.h index 7760b22ba3..b0a028dbf8 100644 --- a/monitor/monitor-internal.h +++ b/monitor/monitor-internal.h @@ -133,7 +133,7 @@ typedef struct { * qmp_capabilities succeeds, we go into command mode, and * @command becomes &qmp_commands. */ - QmpCommandList *commands; + const QmpCommandList *commands; bool capab_offered[QMP_CAPABILITY__MAX]; /* capabilities offered */ bool capab[QMP_CAPABILITY__MAX]; /* offered and accepted */ /* diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index e2c366e09e..f9d43046aa 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -75,14 +75,14 @@ static QDict *qmp_dispatch_check_obj(const QObject *req= uest, bool allow_oob, return dict; } =20 -static QObject *do_qmp_dispatch(QmpCommandList *cmds, QObject *request, +static QObject *do_qmp_dispatch(const QmpCommandList *cmds, QObject *reque= st, bool allow_oob, Error **errp) { Error *local_err =3D NULL; bool oob; const char *command; QDict *args, *dict; - QmpCommand *cmd; + const QmpCommand *cmd; QObject *ret =3D NULL; =20 dict =3D qmp_dispatch_check_obj(request, allow_oob, errp); @@ -163,7 +163,7 @@ bool qmp_is_oob(const QDict *dict) && !qdict_haskey(dict, "execute"); } =20 -QDict *qmp_dispatch(QmpCommandList *cmds, QObject *request, +QDict *qmp_dispatch(const QmpCommandList *cmds, QObject *request, bool allow_oob) { Error *err =3D NULL; diff --git a/qapi/qmp-registry.c b/qapi/qmp-registry.c index ca00f74795..d0f9a1d3e3 100644 --- a/qapi/qmp-registry.c +++ b/qapi/qmp-registry.c @@ -27,7 +27,7 @@ void qmp_register_command(QmpCommandList *cmds, const cha= r *name, QTAILQ_INSERT_TAIL(cmds, cmd, node); } =20 -QmpCommand *qmp_find_command(QmpCommandList *cmds, const char *name) +const QmpCommand *qmp_find_command(const QmpCommandList *cmds, const char = *name) { QmpCommand *cmd; =20 @@ -77,10 +77,10 @@ bool qmp_has_success_response(const QmpCommand *cmd) return !(cmd->options & QCO_NO_SUCCESS_RESP); } =20 -void qmp_for_each_command(QmpCommandList *cmds, qmp_cmd_callback_fn fn, +void qmp_for_each_command(const QmpCommandList *cmds, qmp_cmd_callback_fn = fn, void *opaque) { - QmpCommand *cmd; + const QmpCommand *cmd; =20 QTAILQ_FOREACH(cmd, cmds, node) { fn(cmd, opaque); diff --git a/qga/commands.c b/qga/commands.c index 0c7d1385c2..05e9ab6c3d 100644 --- a/qga/commands.c +++ b/qga/commands.c @@ -54,7 +54,7 @@ void qmp_guest_ping(Error **errp) slog("guest-ping called"); } =20 -static void qmp_command_info(QmpCommand *cmd, void *opaque) +static void qmp_command_info(const QmpCommand *cmd, void *opaque) { GuestAgentInfo *info =3D opaque; GuestAgentCommandInfo *cmd_info; diff --git a/qga/main.c b/qga/main.c index c35c2a2120..f23614528e 100644 --- a/qga/main.c +++ b/qga/main.c @@ -359,7 +359,7 @@ static gint ga_strcmp(gconstpointer str1, gconstpointer= str2) } =20 /* disable commands that aren't safe for fsfreeze */ -static void ga_disable_non_whitelisted(QmpCommand *cmd, void *opaque) +static void ga_disable_non_whitelisted(const QmpCommand *cmd, void *opaque) { bool whitelisted =3D false; int i =3D 0; @@ -378,7 +378,7 @@ static void ga_disable_non_whitelisted(QmpCommand *cmd,= void *opaque) } =20 /* [re-]enable all commands, except those explicitly blacklisted by user */ -static void ga_enable_non_blacklisted(QmpCommand *cmd, void *opaque) +static void ga_enable_non_blacklisted(const QmpCommand *cmd, void *opaque) { GList *blacklist =3D opaque; const char *name =3D qmp_command_name(cmd); @@ -918,7 +918,7 @@ int64_t ga_get_fd_handle(GAState *s, Error **errp) return handle; } =20 -static void ga_print_cmd(QmpCommand *cmd, void *opaque) +static void ga_print_cmd(const QmpCommand *cmd, void *opaque) { printf("%s\n", qmp_command_name(cmd)); } --=20 2.22.0.428.g6d5b264208 From nobody Mon Apr 29 15:02:43 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1563217854; cv=none; d=zoho.com; s=zohoarc; b=BDXVNspTGH2olGvJHOWW17RiW4Dv3FFg8/fFxlI0qF7YRODb6p2DameoY47q7XwYE2ddyvE4VYDBX5LmP7zs2LlIPNv8U1vhKO35ufOhu2RBlnmfNAYDaE8kw04n4woJ+uWJWtPKbBxjoMBpyeM0SV0z7iNZNCNSH0UpvgJwoDY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1563217854; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=647+0CbFUGiZ1x/M/Ugd1jTM3wNcotRCVli1EXX4YYE=; b=ROvRePwgHETrIHYKuJGs4duNPsuTMBLwDL2PWThyQ/DHYTJGvpVH39+o+c78kF88gN+1gpdAC5lbWYJNoh70F8cxNOVrHhvwAB47N+l5xa5r4/EhklRaASDjew4qa6+7QdEqMJl2zekHPSuLd7JQ/2VtU8LDJObouHOfl22KuFY= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1563217854172100.43967993316664; Mon, 15 Jul 2019 12:10:54 -0700 (PDT) Received: from localhost ([::1]:42010 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6N9-0003sh-Sy for importer@patchew.org; Mon, 15 Jul 2019 15:10:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39563) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6Mw-00036S-Ec for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:10:40 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hn6Mv-0002vm-I1 for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:10:38 -0400 Received: from mx1.redhat.com ([209.132.183.28]:46586) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hn6Mv-0002ue-Cp for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:10:37 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B24CA3082B46; Mon, 15 Jul 2019 19:10:36 +0000 (UTC) Received: from localhost (ovpn-112-18.ams2.redhat.com [10.36.112.18]) by smtp.corp.redhat.com (Postfix) with ESMTP id CE033600C1; Mon, 15 Jul 2019 19:10:30 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Mon, 15 Jul 2019 23:09:43 +0400 Message-Id: <20190715191001.1188-3-marcandre.lureau@redhat.com> In-Reply-To: <20190715191001.1188-1-marcandre.lureau@redhat.com> References: <20190715191001.1188-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.45]); Mon, 15 Jul 2019 19:10:36 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v5 02/20] json-lexer: make it safe to call destroy multiple times X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Markus Armbruster , Michael Roth , "Dr. David Alan Gilbert" , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" We can easily avoid the burden of checking if the lexer was initialized prior to calling destroy by the caller, let's do it. This allows simplification in state tracking with the following patch, "qmp: add QmpSession" can call qmp_session_destroy() multiple times, which in turns calls json_lexer_destroy(). Signed-off-by: Marc-Andr=C3=A9 Lureau --- qobject/json-lexer.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/qobject/json-lexer.c b/qobject/json-lexer.c index 632320d72d..fa7a2c43a8 100644 --- a/qobject/json-lexer.c +++ b/qobject/json-lexer.c @@ -361,5 +361,8 @@ void json_lexer_flush(JSONLexer *lexer) =20 void json_lexer_destroy(JSONLexer *lexer) { - g_string_free(lexer->token, true); + if (lexer->token) { + g_string_free(lexer->token, true); + lexer->token =3D NULL; + } } --=20 2.22.0.428.g6d5b264208 From nobody Mon Apr 29 15:02:43 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1563217865; cv=none; d=zoho.com; s=zohoarc; b=SmwPQW9YZjOIqWukgSJCPkJDDMu0SS7rwKQEAjL93Qz9SsMD/PQJmvw3YhmGYNRSzD+NnzX4b8KxDGCfszrDUcJQE/KyXNqTxZfdPwoqy3+IIiDAOEYQY/HW0+HcSRQpq0JayeEk+xcqpxvOD9rnl5VqKm9NnwwhqgMKLYiXsVM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1563217865; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=FA6+oNb+0VUwN0V/XQWayjlsIPxjivBI9Um3KRptMB8=; b=HMCtYzR8S0Xjd1xA1MUnlBoOvDWASZBAuSkN+mxlvq0IbrOKbypl72Ub7zvrPG+MDWImpuT2vNuM7GIRN5Tk62HIo9I0mGAg55TNP1LHpHGnN+IbU7HLDPpkKG769bDJU4c1NRtGGc6D7FQmo8XKxpOR2J6+XNXTwPnJLUKzEdA= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1563217865412411.0718744161719; Mon, 15 Jul 2019 12:11:05 -0700 (PDT) Received: from localhost ([::1]:42016 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6NM-0004i7-FN for importer@patchew.org; Mon, 15 Jul 2019 15:11:04 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39691) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6N8-0003xX-H4 for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:10:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hn6N6-00032W-OH for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:10:50 -0400 Received: from mx1.redhat.com ([209.132.183.28]:57202) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hn6N6-00031P-GH for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:10:48 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D038359441; Mon, 15 Jul 2019 19:10:47 +0000 (UTC) Received: from localhost (ovpn-112-18.ams2.redhat.com [10.36.112.18]) by smtp.corp.redhat.com (Postfix) with ESMTP id A059519C78; Mon, 15 Jul 2019 19:10:41 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Mon, 15 Jul 2019 23:09:44 +0400 Message-Id: <20190715191001.1188-4-marcandre.lureau@redhat.com> In-Reply-To: <20190715191001.1188-1-marcandre.lureau@redhat.com> References: <20190715191001.1188-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Mon, 15 Jul 2019 19:10:47 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v5 03/20] qmp: add QmpSession X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Markus Armbruster , Michael Roth , "Dr. David Alan Gilbert" , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" This structure will hold various data related to a QMP client session: the list of commands, the parser, the callbacks, the pending operations... Signed-off-by: Marc-Andr=C3=A9 Lureau --- include/qapi/qmp/dispatch.h | 10 +++++++++- monitor/misc.c | 6 +++--- monitor/monitor-internal.h | 2 +- monitor/monitor.c | 2 +- monitor/qmp.c | 8 +++++--- qapi/qmp-dispatch.c | 15 ++++++++++++--- qga/main.c | 5 ++++- tests/test-qmp-cmds.c | 28 ++++++++++++++++++++++------ 8 files changed, 57 insertions(+), 19 deletions(-) diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h index 5a9cf82472..3b53cfd788 100644 --- a/include/qapi/qmp/dispatch.h +++ b/include/qapi/qmp/dispatch.h @@ -37,10 +37,18 @@ typedef struct QmpCommand =20 typedef QTAILQ_HEAD(QmpCommandList, QmpCommand) QmpCommandList; =20 +typedef struct QmpSession QmpSession; + +struct QmpSession { + const QmpCommandList *cmds; +}; + void qmp_register_command(QmpCommandList *cmds, const char *name, QmpCommandFunc *fn, QmpCommandOptions options); const QmpCommand *qmp_find_command(const QmpCommandList *cmds, const char *name); +void qmp_session_init(QmpSession *session, const QmpCommandList *cmds); +void qmp_session_destroy(QmpSession *session); void qmp_disable_command(QmpCommandList *cmds, const char *name); void qmp_enable_command(QmpCommandList *cmds, const char *name); =20 @@ -48,7 +56,7 @@ bool qmp_command_is_enabled(const QmpCommand *cmd); const char *qmp_command_name(const QmpCommand *cmd); bool qmp_has_success_response(const QmpCommand *cmd); QDict *qmp_error_response(Error *err); -QDict *qmp_dispatch(const QmpCommandList *cmds, QObject *request, +QDict *qmp_dispatch(QmpSession *session, QObject *request, bool allow_oob); bool qmp_is_oob(const QDict *dict); =20 diff --git a/monitor/misc.c b/monitor/misc.c index a0fc5111c5..a23c1b8ba4 100644 --- a/monitor/misc.c +++ b/monitor/misc.c @@ -253,7 +253,7 @@ CommandInfoList *qmp_query_commands(Error **errp) assert(monitor_is_qmp(cur_mon)); mon =3D container_of(cur_mon, MonitorQMP, common); =20 - qmp_for_each_command(mon->commands, query_commands_cb, &list); + qmp_for_each_command(mon->session.cmds, query_commands_cb, &list); =20 return list; } @@ -363,7 +363,7 @@ void qmp_qmp_capabilities(bool has_enable, QMPCapabilit= yList *enable, assert(monitor_is_qmp(cur_mon)); mon =3D container_of(cur_mon, MonitorQMP, common); =20 - if (mon->commands =3D=3D &qmp_commands) { + if (mon->session.cmds =3D=3D &qmp_commands) { error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND, "Capabilities negotiation is already complete, command " "ignored"); @@ -374,7 +374,7 @@ void qmp_qmp_capabilities(bool has_enable, QMPCapabilit= yList *enable, return; } =20 - mon->commands =3D &qmp_commands; + mon->session.cmds =3D &qmp_commands; } =20 /* Set the current CPU defined by the user. Callers must hold BQL. */ diff --git a/monitor/monitor-internal.h b/monitor/monitor-internal.h index b0a028dbf8..65d587eafb 100644 --- a/monitor/monitor-internal.h +++ b/monitor/monitor-internal.h @@ -133,7 +133,7 @@ typedef struct { * qmp_capabilities succeeds, we go into command mode, and * @command becomes &qmp_commands. */ - const QmpCommandList *commands; + QmpSession session; bool capab_offered[QMP_CAPABILITY__MAX]; /* capabilities offered */ bool capab[QMP_CAPABILITY__MAX]; /* offered and accepted */ /* diff --git a/monitor/monitor.c b/monitor/monitor.c index 3ef28171c0..9d918c9952 100644 --- a/monitor/monitor.c +++ b/monitor/monitor.c @@ -262,7 +262,7 @@ static void monitor_qapi_event_emit(QAPIEvent event, QD= ict *qdict) } =20 qmp_mon =3D container_of(mon, MonitorQMP, common); - if (qmp_mon->commands !=3D &qmp_cap_negotiation_commands) { + if (qmp_mon->session.cmds !=3D &qmp_cap_negotiation_commands) { qmp_send_response(qmp_mon, qdict); } } diff --git a/monitor/qmp.c b/monitor/qmp.c index e1b196217d..dd72a0d8cf 100644 --- a/monitor/qmp.c +++ b/monitor/qmp.c @@ -117,11 +117,11 @@ static void monitor_qmp_dispatch(MonitorQMP *mon, QOb= ject *req) old_mon =3D cur_mon; cur_mon =3D &mon->common; =20 - rsp =3D qmp_dispatch(mon->commands, req, qmp_oob_enabled(mon)); + rsp =3D qmp_dispatch(&mon->session, req, qmp_oob_enabled(mon)); =20 cur_mon =3D old_mon; =20 - if (mon->commands =3D=3D &qmp_cap_negotiation_commands) { + if (mon->session.cmds =3D=3D &qmp_cap_negotiation_commands) { error =3D qdict_get_qdict(rsp, "error"); if (error && !g_strcmp0(qdict_get_try_str(error, "class"), @@ -318,7 +318,7 @@ static void monitor_qmp_event(void *opaque, int event) =20 switch (event) { case CHR_EVENT_OPENED: - mon->commands =3D &qmp_cap_negotiation_commands; + qmp_session_init(&mon->session, &qmp_cap_negotiation_commands); monitor_qmp_caps_reset(mon); data =3D qmp_greeting(mon); qmp_send_response(mon, data); @@ -333,6 +333,7 @@ static void monitor_qmp_event(void *opaque, int event) * is closed. */ monitor_qmp_cleanup_queues(mon); + qmp_session_destroy(&mon->session); json_message_parser_destroy(&mon->parser); json_message_parser_init(&mon->parser, handle_qmp_command, mon, NULL); @@ -344,6 +345,7 @@ static void monitor_qmp_event(void *opaque, int event) =20 void monitor_data_destroy_qmp(MonitorQMP *mon) { + qmp_session_destroy(&mon->session); json_message_parser_destroy(&mon->parser); qemu_mutex_destroy(&mon->qmp_queue_lock); monitor_qmp_cleanup_req_queue_locked(mon); diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index f9d43046aa..98a82ac33c 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -163,15 +163,24 @@ bool qmp_is_oob(const QDict *dict) && !qdict_haskey(dict, "execute"); } =20 -QDict *qmp_dispatch(const QmpCommandList *cmds, QObject *request, - bool allow_oob) +void qmp_session_init(QmpSession *session, const QmpCommandList *cmds) +{ + session->cmds =3D cmds; +} + +void qmp_session_destroy(QmpSession *session) +{ + session->cmds =3D NULL; +} + +QDict *qmp_dispatch(QmpSession *session, QObject *request, bool allow_oob) { Error *err =3D NULL; QDict *dict =3D qobject_to(QDict, request); QObject *ret, *id =3D dict ? qdict_get(dict, "id") : NULL; QDict *rsp; =20 - ret =3D do_qmp_dispatch(cmds, request, allow_oob, &err); + ret =3D do_qmp_dispatch(session->cmds, request, allow_oob, &err); if (err) { rsp =3D qmp_error_response(err); } else if (ret) { diff --git a/qga/main.c b/qga/main.c index f23614528e..61190db5f3 100644 --- a/qga/main.c +++ b/qga/main.c @@ -74,6 +74,7 @@ typedef struct GAPersistentState { typedef struct GAConfig GAConfig; =20 struct GAState { + QmpSession session; JSONMessageParser parser; GMainLoop *main_loop; GAChannel *channel; @@ -572,7 +573,7 @@ static void process_event(void *opaque, QObject *obj, E= rror *err) } =20 g_debug("processing command"); - rsp =3D qmp_dispatch(&ga_commands, obj, false); + rsp =3D qmp_dispatch(&s->session, obj, false); =20 end: ret =3D send_response(s, rsp); @@ -1338,6 +1339,7 @@ static GAState *initialize_agent(GAConfig *config, in= t socket_activation) ga_command_state_init(s, s->command_state); ga_command_state_init_all(s->command_state); json_message_parser_init(&s->parser, process_event, s, NULL); + qmp_session_init(&s->session, &ga_commands); =20 #ifndef _WIN32 if (!register_signal_handlers()) { @@ -1369,6 +1371,7 @@ static void cleanup_agent(GAState *s) CloseHandle(s->wakeup_event); #endif if (s->command_state) { + qmp_session_destroy(&s->session); ga_command_state_cleanup_all(s->command_state); ga_command_state_free(s->command_state); json_message_parser_destroy(&s->parser); diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c index ab389f42da..e2fe04ee8b 100644 --- a/tests/test-qmp-cmds.c +++ b/tests/test-qmp-cmds.c @@ -119,44 +119,52 @@ __org_qemu_x_Union1 *qmp___org_qemu_x_command(__org_q= emu_x_EnumList *a, /* test commands with no input and no return value */ static void test_dispatch_cmd(void) { + QmpSession session =3D { 0, }; QDict *req =3D qdict_new(); QDict *resp; =20 + qmp_session_init(&session, &qmp_commands); qdict_put_str(req, "execute", "user_def_cmd"); =20 - resp =3D qmp_dispatch(&qmp_commands, QOBJECT(req), false); + resp =3D qmp_dispatch(&session, QOBJECT(req), false); assert(resp !=3D NULL); assert(!qdict_haskey(resp, "error")); =20 qobject_unref(resp); qobject_unref(req); + qmp_session_destroy(&session); } =20 static void test_dispatch_cmd_oob(void) { + QmpSession session =3D { 0, }; QDict *req =3D qdict_new(); QDict *resp; =20 + qmp_session_init(&session, &qmp_commands); qdict_put_str(req, "exec-oob", "test-flags-command"); =20 - resp =3D qmp_dispatch(&qmp_commands, QOBJECT(req), true); + resp =3D qmp_dispatch(&session, QOBJECT(req), true); assert(resp !=3D NULL); assert(!qdict_haskey(resp, "error")); =20 qobject_unref(resp); qobject_unref(req); + qmp_session_destroy(&session); } =20 /* test commands that return an error due to invalid parameters */ static void test_dispatch_cmd_failure(void) { + QmpSession session =3D { 0, }; QDict *req =3D qdict_new(); QDict *args =3D qdict_new(); QDict *resp; =20 + qmp_session_init(&session, &qmp_commands); qdict_put_str(req, "execute", "user_def_cmd2"); =20 - resp =3D qmp_dispatch(&qmp_commands, QOBJECT(req), false); + resp =3D qmp_dispatch(&session, QOBJECT(req), false); assert(resp !=3D NULL); assert(qdict_haskey(resp, "error")); =20 @@ -170,36 +178,44 @@ static void test_dispatch_cmd_failure(void) =20 qdict_put_str(req, "execute", "user_def_cmd"); =20 - resp =3D qmp_dispatch(&qmp_commands, QOBJECT(req), false); + resp =3D qmp_dispatch(&session, QOBJECT(req), false); assert(resp !=3D NULL); assert(qdict_haskey(resp, "error")); =20 qobject_unref(resp); qobject_unref(req); + qmp_session_destroy(&session); } =20 static void test_dispatch_cmd_success_response(void) { + QmpSession session =3D { 0, }; QDict *req =3D qdict_new(); QDict *resp; =20 + qmp_session_init(&session, &qmp_commands); qdict_put_str(req, "execute", "cmd-success-response"); - resp =3D qmp_dispatch(&qmp_commands, QOBJECT(req), false); + resp =3D qmp_dispatch(&session, QOBJECT(req), false); g_assert_null(resp); qobject_unref(req); + qmp_session_destroy(&session); } =20 + static QObject *test_qmp_dispatch(QDict *req) { + QmpSession session =3D { 0, }; QDict *resp; QObject *ret; =20 - resp =3D qmp_dispatch(&qmp_commands, QOBJECT(req), false); + qmp_session_init(&session, &qmp_commands); + resp =3D qmp_dispatch(&session, QOBJECT(req), false); assert(resp && !qdict_haskey(resp, "error")); ret =3D qdict_get(resp, "return"); assert(ret); qobject_ref(ret); qobject_unref(resp); + qmp_session_destroy(&session); return ret; } =20 --=20 2.22.0.428.g6d5b264208 From nobody Mon Apr 29 15:02:43 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1563217880; cv=none; d=zoho.com; s=zohoarc; b=btwU9UXEX1hjhaxvxpMEgjFovk7HlNaO1UEOQ5scIcHFWbg+TEewS5XtpFJtNC5UPkOUeOCTzou0zaFzjpZG2LsTJbf81zxwDiEDS1KJXhWbexaQOWarqH1lSl9dzqaSKGczFSr3c3sdEQGTLDmA/jaAIZwhF+MZrugAZ1ikwFg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1563217880; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=Lx1gN3cTPr7dM2WxMfm6V5DvQQg/in0bGgJvUOFH8Zc=; b=ALi2cRTX2oUdAImWwkqhdF7FdOf/9mgMH28pmu0Mstz/Tg+1tdxX6qfDVW0rpUN8eEx8J9zd/AjuNJydFJXRyiD0ruW3fy8vLW/LdIn0xEUORJvmgwSbSxPOpQd4M4v1eyM6H+m3Z5Kvp3fUnFtTmUJde5SJhMzjEbcgTSDGsQw= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 156321788007613.900227804916312; Mon, 15 Jul 2019 12:11:20 -0700 (PDT) Received: from localhost ([::1]:42024 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6Na-0005a4-Nu for importer@patchew.org; Mon, 15 Jul 2019 15:11:18 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39783) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6NJ-0004hk-Hn for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:11:03 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hn6NH-0003C0-Mv for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:11:01 -0400 Received: from mx1.redhat.com ([209.132.183.28]:40600) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hn6NH-0003Ba-Ew for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:10:59 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C332BC057F2F; Mon, 15 Jul 2019 19:10:58 +0000 (UTC) Received: from localhost (ovpn-112-18.ams2.redhat.com [10.36.112.18]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7099C5D784; Mon, 15 Jul 2019 19:10:52 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Mon, 15 Jul 2019 23:09:45 +0400 Message-Id: <20190715191001.1188-5-marcandre.lureau@redhat.com> In-Reply-To: <20190715191001.1188-1-marcandre.lureau@redhat.com> References: <20190715191001.1188-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Mon, 15 Jul 2019 19:10:58 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v5 04/20] QmpSession: add a return callback X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Markus Armbruster , Michael Roth , "Dr. David Alan Gilbert" , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Introduce a return_cb to allow delaying finishing the dispatch and sending the response asynchronously. For now, this is just modifying qmp_dispatch() to call the callback synchronously. Signed-off-by: Marc-Andr=C3=A9 Lureau --- include/qapi/qmp/dispatch.h | 10 ++++-- monitor/qmp.c | 47 ++++++++++--------------- qapi/qmp-dispatch.c | 22 +++++++++--- qga/main.c | 34 +++++++++++------- tests/test-qmp-cmds.c | 69 ++++++++++++++++++------------------- 5 files changed, 98 insertions(+), 84 deletions(-) diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h index 3b53cfd788..d1ce631a93 100644 --- a/include/qapi/qmp/dispatch.h +++ b/include/qapi/qmp/dispatch.h @@ -38,16 +38,20 @@ typedef struct QmpCommand typedef QTAILQ_HEAD(QmpCommandList, QmpCommand) QmpCommandList; =20 typedef struct QmpSession QmpSession; +typedef void (QmpDispatchReturn) (QmpSession *session, QDict *rsp); =20 struct QmpSession { const QmpCommandList *cmds; + QmpDispatchReturn *return_cb; }; =20 void qmp_register_command(QmpCommandList *cmds, const char *name, QmpCommandFunc *fn, QmpCommandOptions options); const QmpCommand *qmp_find_command(const QmpCommandList *cmds, const char *name); -void qmp_session_init(QmpSession *session, const QmpCommandList *cmds); +void qmp_session_init(QmpSession *session, + const QmpCommandList *cmds, + QmpDispatchReturn *return_cb); void qmp_session_destroy(QmpSession *session); void qmp_disable_command(QmpCommandList *cmds, const char *name); void qmp_enable_command(QmpCommandList *cmds, const char *name); @@ -56,8 +60,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); QDict *qmp_error_response(Error *err); -QDict *qmp_dispatch(QmpSession *session, QObject *request, - bool allow_oob); +void qmp_dispatch(QmpSession *session, QObject *request, + bool allow_oob); bool qmp_is_oob(const QDict *dict); =20 typedef void (*qmp_cmd_callback_fn)(const QmpCommand *cmd, void *opaque); diff --git a/monitor/qmp.c b/monitor/qmp.c index dd72a0d8cf..b215cb70f3 100644 --- a/monitor/qmp.c +++ b/monitor/qmp.c @@ -96,45 +96,35 @@ void qmp_send_response(MonitorQMP *mon, const QDict *rs= p) qobject_unref(json); } =20 -/* - * Emit QMP response @rsp with ID @id to @mon. - * Null @rsp can only happen for commands with QCO_NO_SUCCESS_RESP. - * Nothing is emitted then. - */ -static void monitor_qmp_respond(MonitorQMP *mon, QDict *rsp) +static void dispatch_return_cb(QmpSession *session, QDict *rsp) { - if (rsp) { - qmp_send_response(mon, rsp); + MonitorQMP *mon =3D container_of(session, MonitorQMP, session); + + if (mon->session.cmds =3D=3D &qmp_cap_negotiation_commands) { + QDict *error =3D qdict_get_qdict(rsp, "error"); + if (error + && !g_strcmp0(qdict_get_try_str(error, "class"), + QapiErrorClass_str(ERROR_CLASS_COMMAND_NOT_FOUND= ))) { + /* Provide a more useful error message */ + qdict_del(error, "desc"); + qdict_put_str(error, "desc", "Expecting capabilities negotiati= on" + " with 'qmp_capabilities'"); + } } + + qmp_send_response(mon, rsp); } =20 static void monitor_qmp_dispatch(MonitorQMP *mon, QObject *req) { Monitor *old_mon; - QDict *rsp; - QDict *error; =20 old_mon =3D cur_mon; cur_mon =3D &mon->common; =20 - rsp =3D qmp_dispatch(&mon->session, req, qmp_oob_enabled(mon)); + qmp_dispatch(&mon->session, req, qmp_oob_enabled(mon)); =20 cur_mon =3D old_mon; - - if (mon->session.cmds =3D=3D &qmp_cap_negotiation_commands) { - error =3D qdict_get_qdict(rsp, "error"); - if (error - && !g_strcmp0(qdict_get_try_str(error, "class"), - QapiErrorClass_str(ERROR_CLASS_COMMAND_NOT_FOUND))) { - /* Provide a more useful error message */ - qdict_del(error, "desc"); - qdict_put_str(error, "desc", "Expecting capabilities negotiati= on" - " with 'qmp_capabilities'"); - } - } - - monitor_qmp_respond(mon, rsp); - qobject_unref(rsp); } =20 /* @@ -211,7 +201,7 @@ void monitor_qmp_bh_dispatcher(void *data) assert(req_obj->err); rsp =3D qmp_error_response(req_obj->err); req_obj->err =3D NULL; - monitor_qmp_respond(mon, rsp); + qmp_send_response(req_obj->mon, rsp); qobject_unref(rsp); } =20 @@ -318,7 +308,8 @@ static void monitor_qmp_event(void *opaque, int event) =20 switch (event) { case CHR_EVENT_OPENED: - qmp_session_init(&mon->session, &qmp_cap_negotiation_commands); + qmp_session_init(&mon->session, + &qmp_cap_negotiation_commands, dispatch_return_cb= ); monitor_qmp_caps_reset(mon); data =3D qmp_greeting(mon); qmp_send_response(mon, data); diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 98a82ac33c..37b058cf97 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -163,17 +163,28 @@ bool qmp_is_oob(const QDict *dict) && !qdict_haskey(dict, "execute"); } =20 -void qmp_session_init(QmpSession *session, const QmpCommandList *cmds) +void qmp_session_init(QmpSession *session, + const QmpCommandList *cmds, + QmpDispatchReturn *return_cb) { + assert(return_cb); + assert(!session->return_cb); + session->cmds =3D cmds; + session->return_cb =3D return_cb; } =20 void qmp_session_destroy(QmpSession *session) { + if (!session->return_cb) { + return; + } + session->cmds =3D NULL; + session->return_cb =3D NULL; } =20 -QDict *qmp_dispatch(QmpSession *session, QObject *request, bool allow_oob) +void qmp_dispatch(QmpSession *session, QObject *request, bool allow_oob) { Error *err =3D NULL; QDict *dict =3D qobject_to(QDict, request); @@ -188,12 +199,13 @@ QDict *qmp_dispatch(QmpSession *session, QObject *req= uest, bool allow_oob) qdict_put_obj(rsp, "return", ret); } else { /* Can only happen for commands with QCO_NO_SUCCESS_RESP */ - rsp =3D NULL; + return; } =20 - if (rsp && id) { + if (id) { qdict_put_obj(rsp, "id", qobject_ref(id)); } =20 - return rsp; + session->return_cb(session, rsp); + qobject_unref(rsp); } diff --git a/qga/main.c b/qga/main.c index 61190db5f3..c291d06491 100644 --- a/qga/main.c +++ b/qga/main.c @@ -558,29 +558,37 @@ static int send_response(GAState *s, const QDict *rsp) return 0; } =20 +static void dispatch_return_cb(QmpSession *session, QDict *rsp) +{ + GAState *s =3D container_of(session, GAState, session); + int ret =3D send_response(s, rsp); + if (ret < 0) { + g_warning("error sending response: %s", strerror(-ret)); + } +} + /* handle requests/control events coming in over the channel */ static void process_event(void *opaque, QObject *obj, Error *err) { GAState *s =3D opaque; - QDict *rsp; int ret; =20 g_debug("process_event: called"); assert(!obj !=3D !err); - if (err) { - rsp =3D qmp_error_response(err); - goto end; - } =20 - g_debug("processing command"); - rsp =3D qmp_dispatch(&s->session, obj, false); + if (err) { + QDict *rsp =3D qmp_error_response(err); =20 -end: - ret =3D send_response(s, rsp); - if (ret < 0) { - g_warning("error sending error response: %s", strerror(-ret)); + ret =3D send_response(s, rsp); + if (ret < 0) { + g_warning("error sending error response: %s", strerror(-ret)); + } + qobject_unref(rsp); + } else { + g_debug("processing command"); + qmp_dispatch(&s->session, obj, false); } - qobject_unref(rsp); + qobject_unref(obj); } =20 @@ -1339,7 +1347,7 @@ static GAState *initialize_agent(GAConfig *config, in= t socket_activation) ga_command_state_init(s, s->command_state); ga_command_state_init_all(s->command_state); json_message_parser_init(&s->parser, process_event, s, NULL); - qmp_session_init(&s->session, &ga_commands); + qmp_session_init(&s->session, &ga_commands, dispatch_return_cb); =20 #ifndef _WIN32 if (!register_signal_handlers()) { diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c index e2fe04ee8b..7b3bccc091 100644 --- a/tests/test-qmp-cmds.c +++ b/tests/test-qmp-cmds.c @@ -115,22 +115,23 @@ __org_qemu_x_Union1 *qmp___org_qemu_x_command(__org_q= emu_x_EnumList *a, return ret; } =20 +static void dispatch_cmd_return(QmpSession *session, QDict *resp) +{ + assert(resp !=3D NULL); + assert(!qdict_haskey(resp, "error")); +} =20 /* test commands with no input and no return value */ static void test_dispatch_cmd(void) { QmpSession session =3D { 0, }; QDict *req =3D qdict_new(); - QDict *resp; =20 - qmp_session_init(&session, &qmp_commands); + qmp_session_init(&session, &qmp_commands, dispatch_cmd_return); qdict_put_str(req, "execute", "user_def_cmd"); =20 - resp =3D qmp_dispatch(&session, QOBJECT(req), false); - assert(resp !=3D NULL); - assert(!qdict_haskey(resp, "error")); + qmp_dispatch(&session, QOBJECT(req), false); =20 - qobject_unref(resp); qobject_unref(req); qmp_session_destroy(&session); } @@ -139,82 +140,80 @@ static void test_dispatch_cmd_oob(void) { QmpSession session =3D { 0, }; QDict *req =3D qdict_new(); - QDict *resp; =20 - qmp_session_init(&session, &qmp_commands); + qmp_session_init(&session, &qmp_commands, dispatch_cmd_return); qdict_put_str(req, "exec-oob", "test-flags-command"); =20 - resp =3D qmp_dispatch(&session, QOBJECT(req), true); - assert(resp !=3D NULL); - assert(!qdict_haskey(resp, "error")); + qmp_dispatch(&session, QOBJECT(req), true); =20 - qobject_unref(resp); qobject_unref(req); qmp_session_destroy(&session); } =20 +static void dispatch_cmd_failure_return(QmpSession *session, QDict *resp) +{ + assert(resp !=3D NULL); + assert(qdict_haskey(resp, "error")); +} + /* test commands that return an error due to invalid parameters */ static void test_dispatch_cmd_failure(void) { QmpSession session =3D { 0, }; QDict *req =3D qdict_new(); QDict *args =3D qdict_new(); - QDict *resp; =20 - qmp_session_init(&session, &qmp_commands); + qmp_session_init(&session, &qmp_commands, dispatch_cmd_failure_return); qdict_put_str(req, "execute", "user_def_cmd2"); =20 - resp =3D qmp_dispatch(&session, QOBJECT(req), false); - assert(resp !=3D NULL); - assert(qdict_haskey(resp, "error")); + qmp_dispatch(&session, QOBJECT(req), false); =20 - qobject_unref(resp); qobject_unref(req); =20 /* check that with extra arguments it throws an error */ req =3D qdict_new(); qdict_put_int(args, "a", 66); qdict_put(req, "arguments", args); - qdict_put_str(req, "execute", "user_def_cmd"); =20 - resp =3D qmp_dispatch(&session, QOBJECT(req), false); - assert(resp !=3D NULL); - assert(qdict_haskey(resp, "error")); + qmp_dispatch(&session, QOBJECT(req), false); =20 - qobject_unref(resp); qobject_unref(req); qmp_session_destroy(&session); } =20 +static QObject *dispatch_ret; + static void test_dispatch_cmd_success_response(void) { QmpSession session =3D { 0, }; QDict *req =3D qdict_new(); - QDict *resp; =20 - qmp_session_init(&session, &qmp_commands); + qmp_session_init(&session, &qmp_commands, (QmpDispatchReturn *)abort); qdict_put_str(req, "execute", "cmd-success-response"); - resp =3D qmp_dispatch(&session, QOBJECT(req), false); - g_assert_null(resp); + + qmp_dispatch(&session, QOBJECT(req), false); + qobject_unref(req); qmp_session_destroy(&session); } =20 +static void dispatch_return(QmpSession *session, QDict *resp) +{ + assert(resp && !qdict_haskey(resp, "error")); + dispatch_ret =3D qdict_get(resp, "return"); + qobject_ref(dispatch_ret); +} =20 static QObject *test_qmp_dispatch(QDict *req) { QmpSession session =3D { 0, }; - QDict *resp; QObject *ret; =20 - qmp_session_init(&session, &qmp_commands); - resp =3D qmp_dispatch(&session, QOBJECT(req), false); - assert(resp && !qdict_haskey(resp, "error")); - ret =3D qdict_get(resp, "return"); - assert(ret); - qobject_ref(ret); - qobject_unref(resp); + qmp_session_init(&session, &qmp_commands, dispatch_return); + qmp_dispatch(&session, QOBJECT(req), false); + ret =3D dispatch_ret; + dispatch_ret =3D NULL; qmp_session_destroy(&session); return ret; } --=20 2.22.0.428.g6d5b264208 From nobody Mon Apr 29 15:02:43 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1563217888; cv=none; d=zoho.com; s=zohoarc; b=Ly+j41HR5d2IMTZcmaSEoUQW8U0mC0jLqmas8OJQQgG3AIFC8NX40Be8Kxh8W7DMb3ZerhZ9vy9yRKnLudV6cP2WQ9JzmR516Zt3rJCktF/Dxd+NY0uiz3rWFW3+sxawP5o52BKEVgCjyqyrSt3Re+SMR1PmigFHVnJUv3h/0OA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1563217888; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=1oGzPVzBq6h+kJntZS4iPG05RnU/yvQ9RbCI9a+Lnd0=; b=CXI96d5NIRe5pBtUMszI2l25ynNSb6xmou+EnQNqSoT5wKmKFbVJ9NxwzilghBPtQ5RcASaQj6SzD3T0fLZSjd115cXIJ7l68/3IQ5Iq923SJ18bF2/ZYOWt1zh0DmKiWsfeFpb0XV94BnGC/Cd5W0YjmF6jjXQpGJBK+8IkESg= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1563217888121755.5564524381733; Mon, 15 Jul 2019 12:11:28 -0700 (PDT) Received: from localhost ([::1]:42026 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6Nj-0006Fy-7A for importer@patchew.org; Mon, 15 Jul 2019 15:11:27 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39823) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6NS-0005NE-VM for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:11:12 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hn6NR-0003G1-LG for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:11:10 -0400 Received: from mx1.redhat.com ([209.132.183.28]:51036) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hn6NR-0003Fa-Dd for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:11:09 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9D84C882EF; Mon, 15 Jul 2019 19:11:08 +0000 (UTC) Received: from localhost (ovpn-112-18.ams2.redhat.com [10.36.112.18]) by smtp.corp.redhat.com (Postfix) with ESMTP id 807351992C; Mon, 15 Jul 2019 19:11:03 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Mon, 15 Jul 2019 23:09:46 +0400 Message-Id: <20190715191001.1188-6-marcandre.lureau@redhat.com> In-Reply-To: <20190715191001.1188-1-marcandre.lureau@redhat.com> References: <20190715191001.1188-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Mon, 15 Jul 2019 19:11:08 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v5 05/20] QmpSession: add json parser and use it in qga X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Markus Armbruster , Michael Roth , "Dr. David Alan Gilbert" , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Move JSON parser to QmpSession, and implement a simple handler to check the parsed tokens and call qmp_dispatch(). This is enough for a simple QMP client, like QGA. The QEMU monitor has more complicated handling of dispatching which will be addressed in a following patch to benefit from more common code. Signed-off-by: Marc-Andr=C3=A9 Lureau --- include/qapi/qmp/dispatch.h | 7 +++++++ qapi/qmp-dispatch.c | 19 +++++++++++++++++++ qga/main.c | 31 +------------------------------ 3 files changed, 27 insertions(+), 30 deletions(-) diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h index d1ce631a93..c84edff7d2 100644 --- a/include/qapi/qmp/dispatch.h +++ b/include/qapi/qmp/dispatch.h @@ -15,6 +15,7 @@ #define QAPI_QMP_DISPATCH_H =20 #include "qemu/queue.h" +#include "qapi/qmp/json-parser.h" =20 typedef void (QmpCommandFunc)(QDict *, QObject **, Error **); =20 @@ -42,6 +43,7 @@ typedef void (QmpDispatchReturn) (QmpSession *session, QD= ict *rsp); =20 struct QmpSession { const QmpCommandList *cmds; + JSONMessageParser parser; QmpDispatchReturn *return_cb; }; =20 @@ -52,6 +54,11 @@ const QmpCommand *qmp_find_command(const QmpCommandList = *cmds, void qmp_session_init(QmpSession *session, const QmpCommandList *cmds, QmpDispatchReturn *return_cb); +static inline void +qmp_session_feed(QmpSession *session, const char *buf, size_t count) +{ + json_message_parser_feed(&session->parser, buf, count); +} void qmp_session_destroy(QmpSession *session); void qmp_disable_command(QmpCommandList *cmds, const char *name); void qmp_enable_command(QmpCommandList *cmds, const char *name); diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 37b058cf97..803ec626cd 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -163,6 +163,23 @@ bool qmp_is_oob(const QDict *dict) && !qdict_haskey(dict, "execute"); } =20 +static void qmp_json_emit(void *opaque, QObject *obj, Error *err) +{ + QmpSession *session =3D opaque; + + assert(!obj !=3D !err); + + if (err) { + QDict *rsp =3D qmp_error_response(err); + session->return_cb(session, rsp); + qobject_unref(rsp); + } else { + qmp_dispatch(session, obj, false); + } + + qobject_unref(obj); +} + void qmp_session_init(QmpSession *session, const QmpCommandList *cmds, QmpDispatchReturn *return_cb) @@ -170,6 +187,7 @@ void qmp_session_init(QmpSession *session, assert(return_cb); assert(!session->return_cb); =20 + json_message_parser_init(&session->parser, qmp_json_emit, session, NUL= L); session->cmds =3D cmds; session->return_cb =3D return_cb; } @@ -182,6 +200,7 @@ void qmp_session_destroy(QmpSession *session) =20 session->cmds =3D NULL; session->return_cb =3D NULL; + json_message_parser_destroy(&session->parser); } =20 void qmp_dispatch(QmpSession *session, QObject *request, bool allow_oob) diff --git a/qga/main.c b/qga/main.c index c291d06491..057368eb16 100644 --- a/qga/main.c +++ b/qga/main.c @@ -19,7 +19,6 @@ #include #endif #include "qemu-common.h" -#include "qapi/qmp/json-parser.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qjson.h" #include "qapi/qmp/qstring.h" @@ -75,7 +74,6 @@ typedef struct GAConfig GAConfig; =20 struct GAState { QmpSession session; - JSONMessageParser parser; GMainLoop *main_loop; GAChannel *channel; bool virtio; /* fastpath to check for virtio to deal with poll() quirk= s */ @@ -567,31 +565,6 @@ static void dispatch_return_cb(QmpSession *session, QD= ict *rsp) } } =20 -/* handle requests/control events coming in over the channel */ -static void process_event(void *opaque, QObject *obj, Error *err) -{ - GAState *s =3D opaque; - int ret; - - g_debug("process_event: called"); - assert(!obj !=3D !err); - - if (err) { - QDict *rsp =3D qmp_error_response(err); - - ret =3D send_response(s, rsp); - if (ret < 0) { - g_warning("error sending error response: %s", strerror(-ret)); - } - qobject_unref(rsp); - } else { - g_debug("processing command"); - qmp_dispatch(&s->session, obj, false); - } - - qobject_unref(obj); -} - /* false return signals GAChannel to close the current client connection */ static gboolean channel_event_cb(GIOCondition condition, gpointer data) { @@ -607,7 +580,7 @@ static gboolean channel_event_cb(GIOCondition condition= , gpointer data) case G_IO_STATUS_NORMAL: buf[count] =3D 0; g_debug("read data, count: %d, data: %s", (int)count, buf); - json_message_parser_feed(&s->parser, (char *)buf, (int)count); + qmp_session_feed(&s->session, (char *)buf, (int)count); break; case G_IO_STATUS_EOF: g_debug("received EOF"); @@ -1346,7 +1319,6 @@ static GAState *initialize_agent(GAConfig *config, in= t socket_activation) s->command_state =3D ga_command_state_new(); ga_command_state_init(s, s->command_state); ga_command_state_init_all(s->command_state); - json_message_parser_init(&s->parser, process_event, s, NULL); qmp_session_init(&s->session, &ga_commands, dispatch_return_cb); =20 #ifndef _WIN32 @@ -1382,7 +1354,6 @@ static void cleanup_agent(GAState *s) qmp_session_destroy(&s->session); ga_command_state_cleanup_all(s->command_state); ga_command_state_free(s->command_state); - json_message_parser_destroy(&s->parser); } g_free(s->pstate_filepath); g_free(s->state_filepath_isfrozen); --=20 2.22.0.428.g6d5b264208 From nobody Mon Apr 29 15:02:43 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1563217902; cv=none; d=zoho.com; s=zohoarc; b=dxXo5BE+yPI0W0X0nW6/rG9bEHGHbGZH7yHQN4mG43a2TuYLfaED+wuzIZ04sy+p53cDcxGFJbH86VVQ0E38zAoVuLY0j/Mu9o07MD9I7Xst/EsIq0hitmtFmR6hzo6vLEZ6MzlpyUC3eFMoZ0AnkdBbmxlxGzrQRV3fAVhe1wE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1563217902; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=tLCpGuDu4VCjnK+ibIrT7XJqKqm5t/ITT9tQ6HaRH1w=; b=deBg/YzGeC9kzKVVp+g3Yf2KwMcOgGfs0+QrSv8y5kb2GrCwr132hvrtjcfWtvtNTpnp506/E9RQANCMhMF3t2lRVOYDJvsIz3ylwFtduxoI23q+0bMXlrBb6/0SkL0nsWp/8ELmcdEQBfjZO+p/XGEvOcxfHzsRpouUCTvMZbI= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1563217902693762.3542505720644; Mon, 15 Jul 2019 12:11:42 -0700 (PDT) Received: from localhost ([::1]:42036 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6Nx-0007CT-GV for importer@patchew.org; Mon, 15 Jul 2019 15:11:41 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39873) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6Nh-0006OL-1B for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:11:26 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hn6Ne-0003Jf-Cu for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:11:24 -0400 Received: from mx1.redhat.com ([209.132.183.28]:56972) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hn6Ne-0003JI-4U for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:11:22 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5D4833082129; Mon, 15 Jul 2019 19:11:21 +0000 (UTC) Received: from localhost (ovpn-112-18.ams2.redhat.com [10.36.112.18]) by smtp.corp.redhat.com (Postfix) with ESMTP id 491AE5B681; Mon, 15 Jul 2019 19:11:12 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Mon, 15 Jul 2019 23:09:47 +0400 Message-Id: <20190715191001.1188-7-marcandre.lureau@redhat.com> In-Reply-To: <20190715191001.1188-1-marcandre.lureau@redhat.com> References: <20190715191001.1188-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.42]); Mon, 15 Jul 2019 19:11:21 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v5 06/20] monitor: use qmp session to parse json feed X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Markus Armbruster , Michael Roth , "Dr. David Alan Gilbert" , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Use the QmpSession json parser introduced in previous patch to generalize the handling in both qemu & qemu-ga. Unfortunately, since the introduction of OOB, it's not as common as it was before that. We may want to move some of OOB logic in common qmp-dispatch.c/QmpSession though. The QEMU monitor has peculiar handling of the stream of commands, for OOB command processing, which can be solved by overriding the json emit callback. Signed-off-by: Marc-Andr=C3=A9 Lureau --- include/qapi/qmp/dispatch.h | 1 + include/qapi/qmp/json-parser.h | 7 ++++--- monitor/monitor-internal.h | 1 - monitor/qmp.c | 13 +++++-------- qapi/qmp-dispatch.c | 4 +++- qga/main.c | 2 +- qobject/json-streamer.c | 3 +-- tests/test-qmp-cmds.c | 11 ++++++----- 8 files changed, 21 insertions(+), 21 deletions(-) diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h index c84edff7d2..b3ca6c9ff2 100644 --- a/include/qapi/qmp/dispatch.h +++ b/include/qapi/qmp/dispatch.h @@ -53,6 +53,7 @@ const QmpCommand *qmp_find_command(const QmpCommandList *= cmds, const char *name); void qmp_session_init(QmpSession *session, const QmpCommandList *cmds, + JSONMessageEmit *emit, QmpDispatchReturn *return_cb); static inline void qmp_session_feed(QmpSession *session, const char *buf, size_t count) diff --git a/include/qapi/qmp/json-parser.h b/include/qapi/qmp/json-parser.h index 7345a9bd5c..6f168e8007 100644 --- a/include/qapi/qmp/json-parser.h +++ b/include/qapi/qmp/json-parser.h @@ -14,6 +14,8 @@ #ifndef QAPI_QMP_JSON_PARSER_H #define QAPI_QMP_JSON_PARSER_H =20 +typedef void (JSONMessageEmit)(void *opaque, QObject *json, Error *err); + typedef struct JSONLexer { int start_state, state; GString *token; @@ -21,7 +23,7 @@ typedef struct JSONLexer { } JSONLexer; =20 typedef struct JSONMessageParser { - void (*emit)(void *opaque, QObject *json, Error *err); + JSONMessageEmit *emit; void *opaque; va_list *ap; JSONLexer lexer; @@ -32,8 +34,7 @@ typedef struct JSONMessageParser { } JSONMessageParser; =20 void json_message_parser_init(JSONMessageParser *parser, - void (*emit)(void *opaque, QObject *json, - Error *err), + JSONMessageEmit *emit, void *opaque, va_list *ap); =20 void json_message_parser_feed(JSONMessageParser *parser, diff --git a/monitor/monitor-internal.h b/monitor/monitor-internal.h index 65d587eafb..65cf668b20 100644 --- a/monitor/monitor-internal.h +++ b/monitor/monitor-internal.h @@ -125,7 +125,6 @@ struct MonitorHMP { =20 typedef struct { Monitor common; - JSONMessageParser parser; bool pretty; /* * When a client connects, we're in capabilities negotiation mode. diff --git a/monitor/qmp.c b/monitor/qmp.c index b215cb70f3..cd29494e28 100644 --- a/monitor/qmp.c +++ b/monitor/qmp.c @@ -217,7 +217,7 @@ void monitor_qmp_bh_dispatcher(void *data) =20 static void handle_qmp_command(void *opaque, QObject *req, Error *err) { - MonitorQMP *mon =3D opaque; + MonitorQMP *mon =3D container_of(opaque, MonitorQMP, session); QObject *id =3D NULL; QDict *qdict; QMPRequest *req_obj; @@ -279,7 +279,7 @@ static void monitor_qmp_read(void *opaque, const uint8_= t *buf, int size) { MonitorQMP *mon =3D opaque; =20 - json_message_parser_feed(&mon->parser, (const char *) buf, size); + qmp_session_feed(&mon->session, (const char *) buf, size); } =20 static QDict *qmp_greeting(MonitorQMP *mon) @@ -309,7 +309,9 @@ static void monitor_qmp_event(void *opaque, int event) switch (event) { case CHR_EVENT_OPENED: qmp_session_init(&mon->session, - &qmp_cap_negotiation_commands, dispatch_return_cb= ); + &qmp_cap_negotiation_commands, + handle_qmp_command, + dispatch_return_cb); monitor_qmp_caps_reset(mon); data =3D qmp_greeting(mon); qmp_send_response(mon, data); @@ -325,9 +327,6 @@ static void monitor_qmp_event(void *opaque, int event) */ monitor_qmp_cleanup_queues(mon); qmp_session_destroy(&mon->session); - json_message_parser_destroy(&mon->parser); - json_message_parser_init(&mon->parser, handle_qmp_command, - mon, NULL); mon_refcount--; monitor_fdsets_cleanup(); break; @@ -337,7 +336,6 @@ static void monitor_qmp_event(void *opaque, int event) void monitor_data_destroy_qmp(MonitorQMP *mon) { qmp_session_destroy(&mon->session); - json_message_parser_destroy(&mon->parser); qemu_mutex_destroy(&mon->qmp_queue_lock); monitor_qmp_cleanup_req_queue_locked(mon); g_queue_free(mon->qmp_requests); @@ -373,7 +371,6 @@ void monitor_init_qmp(Chardev *chr, bool pretty) qemu_chr_fe_init(&mon->common.chr, chr, &error_abort); qemu_chr_fe_set_echo(&mon->common.chr, true); =20 - json_message_parser_init(&mon->parser, handle_qmp_command, mon, NULL); if (mon->common.use_io_thread) { /* * Make sure the old iowatch is gone. It's possible when diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 803ec626cd..f2c376d005 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -182,12 +182,14 @@ static void qmp_json_emit(void *opaque, QObject *obj,= Error *err) =20 void qmp_session_init(QmpSession *session, const QmpCommandList *cmds, + JSONMessageEmit *emit, QmpDispatchReturn *return_cb) { assert(return_cb); assert(!session->return_cb); =20 - json_message_parser_init(&session->parser, qmp_json_emit, session, NUL= L); + json_message_parser_init(&session->parser, emit ?: qmp_json_emit, + session, NULL); session->cmds =3D cmds; session->return_cb =3D return_cb; } diff --git a/qga/main.c b/qga/main.c index 057368eb16..b005550c70 100644 --- a/qga/main.c +++ b/qga/main.c @@ -1319,7 +1319,7 @@ static GAState *initialize_agent(GAConfig *config, in= t socket_activation) s->command_state =3D ga_command_state_new(); ga_command_state_init(s, s->command_state); ga_command_state_init_all(s->command_state); - qmp_session_init(&s->session, &ga_commands, dispatch_return_cb); + qmp_session_init(&s->session, &ga_commands, NULL, dispatch_return_cb); =20 #ifndef _WIN32 if (!register_signal_handlers()) { diff --git a/qobject/json-streamer.c b/qobject/json-streamer.c index 47dd7ea576..2a440f2a9e 100644 --- a/qobject/json-streamer.c +++ b/qobject/json-streamer.c @@ -100,8 +100,7 @@ out_emit: } =20 void json_message_parser_init(JSONMessageParser *parser, - void (*emit)(void *opaque, QObject *json, - Error *err), + JSONMessageEmit *emit, void *opaque, va_list *ap) { parser->emit =3D emit; diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c index 7b3bccc091..8e46f88f6f 100644 --- a/tests/test-qmp-cmds.c +++ b/tests/test-qmp-cmds.c @@ -127,7 +127,7 @@ static void test_dispatch_cmd(void) QmpSession session =3D { 0, }; QDict *req =3D qdict_new(); =20 - qmp_session_init(&session, &qmp_commands, dispatch_cmd_return); + qmp_session_init(&session, &qmp_commands, NULL, dispatch_cmd_return); qdict_put_str(req, "execute", "user_def_cmd"); =20 qmp_dispatch(&session, QOBJECT(req), false); @@ -141,7 +141,7 @@ static void test_dispatch_cmd_oob(void) QmpSession session =3D { 0, }; QDict *req =3D qdict_new(); =20 - qmp_session_init(&session, &qmp_commands, dispatch_cmd_return); + qmp_session_init(&session, &qmp_commands, NULL, dispatch_cmd_return); qdict_put_str(req, "exec-oob", "test-flags-command"); =20 qmp_dispatch(&session, QOBJECT(req), true); @@ -163,7 +163,8 @@ static void test_dispatch_cmd_failure(void) QDict *req =3D qdict_new(); QDict *args =3D qdict_new(); =20 - qmp_session_init(&session, &qmp_commands, dispatch_cmd_failure_return); + qmp_session_init(&session, &qmp_commands, NULL, + dispatch_cmd_failure_return); qdict_put_str(req, "execute", "user_def_cmd2"); =20 qmp_dispatch(&session, QOBJECT(req), false); @@ -189,7 +190,7 @@ static void test_dispatch_cmd_success_response(void) QmpSession session =3D { 0, }; QDict *req =3D qdict_new(); =20 - qmp_session_init(&session, &qmp_commands, (QmpDispatchReturn *)abort); + qmp_session_init(&session, &qmp_commands, NULL, (QmpDispatchReturn *)a= bort); qdict_put_str(req, "execute", "cmd-success-response"); =20 qmp_dispatch(&session, QOBJECT(req), false); @@ -210,7 +211,7 @@ static QObject *test_qmp_dispatch(QDict *req) QmpSession session =3D { 0, }; QObject *ret; =20 - qmp_session_init(&session, &qmp_commands, dispatch_return); + qmp_session_init(&session, &qmp_commands, NULL, dispatch_return); qmp_dispatch(&session, QOBJECT(req), false); ret =3D dispatch_ret; dispatch_ret =3D NULL; --=20 2.22.0.428.g6d5b264208 From nobody Mon Apr 29 15:02:43 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1563217910; cv=none; d=zoho.com; s=zohoarc; b=Rt0F+dXNyxssWLIj65kkH5wQWJJIen1EqeAPaLn/lmMq/UjOjMb6avesl6hohzIzvAbV9UMxR6XP2tt5mRIiA+uhn/bevANmWjzPsLtWDqM2Xac7vr7xFps9626QDuCN81R44wE6xVjt8SJy15nU3cP2ymXfYR7RP0DkwU5m8Rs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1563217910; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=FvkrOUCWgCJHd7zQNICgdvtDiL1NMuZWlXvW1Xn8nJU=; b=hoNVA1YBbX6qoz6Zc7h117pEKSNCO1KajKtPbTX/0rCBpdAqrDsIDlA65+3G0RDEoKkHQl/rt9ontGdxC+P3eTt/z1vxr9vBXn4qGFnTASGNz88MnLVl66BWEGYw+AVxaUCbniiIQxX4QOpgqTzvh8S44st2nHeIUDkyNxdOHv0= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1563217910836916.1528179271891; Mon, 15 Jul 2019 12:11:50 -0700 (PDT) Received: from localhost ([::1]:42038 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6O5-0007vO-VB for importer@patchew.org; Mon, 15 Jul 2019 15:11:49 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39898) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6Nq-00072q-0h for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:11:34 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hn6Np-0003Md-3V for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:11:33 -0400 Received: from mx1.redhat.com ([209.132.183.28]:57692) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hn6No-0003MU-Uj for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:11:33 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4D5C559461; Mon, 15 Jul 2019 19:11:32 +0000 (UTC) Received: from localhost (ovpn-112-18.ams2.redhat.com [10.36.112.18]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7C36560BEC; Mon, 15 Jul 2019 19:11:26 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Mon, 15 Jul 2019 23:09:48 +0400 Message-Id: <20190715191001.1188-8-marcandre.lureau@redhat.com> In-Reply-To: <20190715191001.1188-1-marcandre.lureau@redhat.com> References: <20190715191001.1188-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Mon, 15 Jul 2019 19:11:32 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v5 07/20] qga: simplify dispatch_return_cb X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Markus Armbruster , Michael Roth , "Dr. David Alan Gilbert" , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Fold send_response(). qobject_to_json() can't return NULL (it will crash if allocation failed, either in memcpy() or abort from g_realloc()). Signed-off-by: Marc-Andr=C3=A9 Lureau --- qga/main.c | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/qga/main.c b/qga/main.c index b005550c70..66fe7ac3de 100644 --- a/qga/main.c +++ b/qga/main.c @@ -522,8 +522,9 @@ fail: #endif } =20 -static int send_response(GAState *s, const QDict *rsp) +static void dispatch_return_cb(QmpSession *session, QDict *rsp) { + GAState *s =3D container_of(session, GAState, session); const char *buf; QString *payload_qstr, *response_qstr; GIOStatus status; @@ -531,9 +532,6 @@ static int send_response(GAState *s, const QDict *rsp) g_assert(rsp && s->channel); =20 payload_qstr =3D qobject_to_json(QOBJECT(rsp)); - if (!payload_qstr) { - return -EINVAL; - } =20 if (s->delimit_response) { s->delimit_response =3D false; @@ -550,18 +548,7 @@ static int send_response(GAState *s, const QDict *rsp) status =3D ga_channel_write_all(s->channel, buf, strlen(buf)); qobject_unref(response_qstr); if (status !=3D G_IO_STATUS_NORMAL) { - return -EIO; - } - - return 0; -} - -static void dispatch_return_cb(QmpSession *session, QDict *rsp) -{ - GAState *s =3D container_of(session, GAState, session); - int ret =3D send_response(s, rsp); - if (ret < 0) { - g_warning("error sending response: %s", strerror(-ret)); + g_warning("Failed sending response"); } } =20 --=20 2.22.0.428.g6d5b264208 From nobody Mon Apr 29 15:02:43 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1563217926; cv=none; d=zoho.com; s=zohoarc; b=WGgHwhctPDpdLdLF3o+ph2zwX0oUrQCCI8HomZYljPKtjVn9g18k5+JLjTPYwqe2JX0iiN/Fo572gAOE5iyrue9+V94W2S/NSsme4zuNDc9DEKkc9LdzubnAr2guWI5gkHiH496KgNiMuLRCHV9A3TtEeZlzDLEEGJ7Iwb4r4aU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1563217926; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=U6CJvcU22EFIf/m03D5EVT3aabqdAVY3CkXLDkG7jTY=; b=fLxMFKgvWgHQsqpQc/4VJGJ1288Ep+d97qNSuxRhpmibhivWlaxS6B4cotVOSwrp56vlSpO7ZvXNUvDBKWK73OoQZ8PANLPtn3yznPoVPzO+I0XhrFABtKPm+sAQUnMyBIGoixi5V1a+4T78BBTWDIQYSBaQ2R8Gn446vAnnW+s= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1563217926389376.8825667607807; Mon, 15 Jul 2019 12:12:06 -0700 (PDT) Received: from localhost ([::1]:42048 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6OK-0000XJ-Vo for importer@patchew.org; Mon, 15 Jul 2019 15:12:04 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39941) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6O3-00083I-C8 for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:11:48 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hn6O1-0003TL-VU for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:11:47 -0400 Received: from mx1.redhat.com ([209.132.183.28]:57152) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hn6O1-0003ST-Ne for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:11:45 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B30173082128; Mon, 15 Jul 2019 19:11:42 +0000 (UTC) Received: from localhost (ovpn-112-18.ams2.redhat.com [10.36.112.18]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9BA9C5D96F; Mon, 15 Jul 2019 19:11:36 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Mon, 15 Jul 2019 23:09:49 +0400 Message-Id: <20190715191001.1188-9-marcandre.lureau@redhat.com> In-Reply-To: <20190715191001.1188-1-marcandre.lureau@redhat.com> References: <20190715191001.1188-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.42]); Mon, 15 Jul 2019 19:11:42 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v5 08/20] QmpSession: introduce QmpReturn X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Markus Armbruster , Michael Roth , "Dr. David Alan Gilbert" , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" QmpReturn (and associated functions) is used during synchronous dispatch return for now. It helps to factor out some code for handling a reply context. In the following patches, the QmpReturn will be the basis upon which asynchronous reply will be handled: it will hold the context for a QMP command reply. Signed-off-by: Marc-Andr=C3=A9 Lureau --- include/qapi/qmp/dispatch.h | 34 ++++++++++++++++- monitor/qmp.c | 6 +-- qapi/qmp-dispatch.c | 74 ++++++++++++++++++++++--------------- 3 files changed, 79 insertions(+), 35 deletions(-) diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h index b3ca6c9ff2..6c0d21968e 100644 --- a/include/qapi/qmp/dispatch.h +++ b/include/qapi/qmp/dispatch.h @@ -17,6 +17,8 @@ #include "qemu/queue.h" #include "qapi/qmp/json-parser.h" =20 +typedef struct QmpReturn QmpReturn; + typedef void (QmpCommandFunc)(QDict *, QObject **, Error **); =20 typedef enum QmpCommandOptions @@ -47,6 +49,37 @@ struct QmpSession { QmpDispatchReturn *return_cb; }; =20 +struct QmpReturn { + QmpSession *session; + QDict *rsp; +}; + +/** + * qmp_return_new: + * + * Allocates and initializes a QmpReturn. + */ +QmpReturn *qmp_return_new(QmpSession *session, const QObject *req); + +/** + * qmp_return_free: + * + * Free a QmpReturn. This shouldn't be needed if you actually return + * with qmp_return{_error}. + */ +void qmp_return_free(QmpReturn *qret); + +/** + * qmp_return{_error}: + * + * Construct the command reply, and call the + * return_cb() associated with the session. + * + * Finally, free the QmpReturn. + */ +void qmp_return(QmpReturn *qret, QObject *rsp); +void qmp_return_error(QmpReturn *qret, Error *err); + void qmp_register_command(QmpCommandList *cmds, const char *name, QmpCommandFunc *fn, QmpCommandOptions options); const QmpCommand *qmp_find_command(const QmpCommandList *cmds, @@ -67,7 +100,6 @@ void qmp_enable_command(QmpCommandList *cmds, const char= *name); bool qmp_command_is_enabled(const QmpCommand *cmd); const char *qmp_command_name(const QmpCommand *cmd); bool qmp_has_success_response(const QmpCommand *cmd); -QDict *qmp_error_response(Error *err); void qmp_dispatch(QmpSession *session, QObject *request, bool allow_oob); bool qmp_is_oob(const QDict *dict); diff --git a/monitor/qmp.c b/monitor/qmp.c index cd29494e28..056ad7b68b 100644 --- a/monitor/qmp.c +++ b/monitor/qmp.c @@ -179,7 +179,6 @@ static QMPRequest *monitor_qmp_requests_pop_any_with_lo= ck(void) void monitor_qmp_bh_dispatcher(void *data) { QMPRequest *req_obj =3D monitor_qmp_requests_pop_any_with_lock(); - QDict *rsp; bool need_resume; MonitorQMP *mon; =20 @@ -198,11 +197,10 @@ void monitor_qmp_bh_dispatcher(void *data) trace_monitor_qmp_cmd_in_band(qobject_get_try_str(id) ?: ""); monitor_qmp_dispatch(mon, req_obj->req); } else { + QmpSession *session =3D &req_obj->mon->session; assert(req_obj->err); - rsp =3D qmp_error_response(req_obj->err); + qmp_return_error(qmp_return_new(session, req_obj->req), req_obj->e= rr); req_obj->err =3D NULL; - qmp_send_response(req_obj->mon, rsp); - qobject_unref(rsp); } =20 if (need_resume) { diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index f2c376d005..405cb291b1 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -19,6 +19,46 @@ #include "qapi/qmp/qbool.h" #include "sysemu/sysemu.h" =20 +QmpReturn *qmp_return_new(QmpSession *session, const QObject *request) +{ + QmpReturn *qret =3D g_new0(QmpReturn, 1); + const QDict *req =3D qobject_to(QDict, request); + QObject *id =3D req ? qdict_get(req, "id") : NULL; + + qret->session =3D session; + qret->rsp =3D qdict_new(); + if (id) { + qobject_ref(id); + qdict_put_obj(qret->rsp, "id", id); + } + + return qret; +} + +void qmp_return_free(QmpReturn *qret) +{ + qobject_unref(qret->rsp); + g_free(qret); +} + +void qmp_return(QmpReturn *qret, QObject *rsp) +{ + qdict_put_obj(qret->rsp, "return", rsp ?: QOBJECT(qdict_new())); + qret->session->return_cb(qret->session, qret->rsp); + qmp_return_free(qret); +} + +void qmp_return_error(QmpReturn *qret, Error *err) +{ + qdict_put_obj(qret->rsp, "error", + qobject_from_jsonf_nofail("{ 'class': %s, 'desc': %s }", + QapiErrorClass_str(error_get_class(err)), + error_get_pretty(err))); + error_free(err); + qret->session->return_cb(qret->session, qret->rsp); + qmp_return_free(qret); +} + static QDict *qmp_dispatch_check_obj(const QObject *request, bool allow_oo= b, Error **errp) { @@ -143,17 +183,6 @@ static QObject *do_qmp_dispatch(const QmpCommandList *= cmds, QObject *request, return ret; } =20 -QDict *qmp_error_response(Error *err) -{ - QDict *rsp; - - rsp =3D qdict_from_jsonf_nofail("{ 'error': { 'class': %s, 'desc': %s = } }", - QapiErrorClass_str(error_get_class(err)), - error_get_pretty(err)); - error_free(err); - return rsp; -} - /* * Does @qdict look like a command to be run out-of-band? */ @@ -170,9 +199,7 @@ static void qmp_json_emit(void *opaque, QObject *obj, E= rror *err) assert(!obj !=3D !err); =20 if (err) { - QDict *rsp =3D qmp_error_response(err); - session->return_cb(session, rsp); - qobject_unref(rsp); + qmp_return_error(qmp_return_new(session, obj), err); } else { qmp_dispatch(session, obj, false); } @@ -208,25 +235,12 @@ void qmp_session_destroy(QmpSession *session) void qmp_dispatch(QmpSession *session, QObject *request, bool allow_oob) { Error *err =3D NULL; - QDict *dict =3D qobject_to(QDict, request); - QObject *ret, *id =3D dict ? qdict_get(dict, "id") : NULL; - QDict *rsp; + QObject *ret; =20 ret =3D do_qmp_dispatch(session->cmds, request, allow_oob, &err); if (err) { - rsp =3D qmp_error_response(err); + qmp_return_error(qmp_return_new(session, request), err); } else if (ret) { - rsp =3D qdict_new(); - qdict_put_obj(rsp, "return", ret); - } else { - /* Can only happen for commands with QCO_NO_SUCCESS_RESP */ - return; + qmp_return(qmp_return_new(session, request), ret); } - - if (id) { - qdict_put_obj(rsp, "id", qobject_ref(id)); - } - - session->return_cb(session, rsp); - qobject_unref(rsp); } --=20 2.22.0.428.g6d5b264208 From nobody Mon Apr 29 15:02:43 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1563217933; cv=none; d=zoho.com; s=zohoarc; b=W7GB41dqr+yjG9mZv0cMYhaI5sD82zyQDICfzLyjJBdTwRNJxsi794It+LWB9WbEJmUpw31nbe6NLIjA2VThTfpXcCJfsCc+LEphAhxYaH6FKbm4yopN9N5QpobCP6aSyl9wyKVGA2hopVXXEdB8mxJWhDdAV2S4xWG1iaKscmg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1563217933; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=G9s00W3HlYbXqvidVH9cGebj+fySiXkn6cvKK6s8rek=; b=JZb1IzME4/QyN/C372Rn7qFq+ZJFM+VXGq2KSBo898SHPW2F2nZfO8/hQoKLqkbqvDUyHONPgrtzBaaPezj0Y09w9WSHYVMECWifXgw1+1bcbMxGcPEhY7OzUTiuSWIXGjfYAi89nHaUU1GaZZ7KunACMGtELW+fHuOMl3yIKcs= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1563217933100376.12152039887394; Mon, 15 Jul 2019 12:12:13 -0700 (PDT) Received: from localhost ([::1]:42050 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6OR-00015q-U3 for importer@patchew.org; Mon, 15 Jul 2019 15:12:11 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:39966) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6OB-0000Dv-Mp for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:11:56 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hn6OA-0003Vg-Ho for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:11:55 -0400 Received: from mx1.redhat.com ([209.132.183.28]:47132) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hn6OA-0003VF-CC for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:11:54 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 1F0FF3087939; Mon, 15 Jul 2019 19:11:53 +0000 (UTC) Received: from localhost (ovpn-112-18.ams2.redhat.com [10.36.112.18]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5233D19C78; Mon, 15 Jul 2019 19:11:46 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Mon, 15 Jul 2019 23:09:50 +0400 Message-Id: <20190715191001.1188-10-marcandre.lureau@redhat.com> In-Reply-To: <20190715191001.1188-1-marcandre.lureau@redhat.com> References: <20190715191001.1188-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.45]); Mon, 15 Jul 2019 19:11:53 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v5 09/20] qmp: simplify qmp_return_error() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Markus Armbruster , Michael Roth , "Dr. David Alan Gilbert" , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" It's simple, probably more efficient, to hand-craft the dict. Signed-off-by: Marc-Andr=C3=A9 Lureau --- qapi/qmp-dispatch.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 405cb291b1..5f75dc27bd 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -50,10 +50,10 @@ void qmp_return(QmpReturn *qret, QObject *rsp) =20 void qmp_return_error(QmpReturn *qret, Error *err) { - qdict_put_obj(qret->rsp, "error", - qobject_from_jsonf_nofail("{ 'class': %s, 'desc': %s }", - QapiErrorClass_str(error_get_class(err)), - error_get_pretty(err))); + QDict *qdict =3D qdict_new(); + qdict_put_str(qdict, "class", QapiErrorClass_str(error_get_class(err))= ); + qdict_put_str(qdict, "desc", error_get_pretty(err)); + qdict_put_obj(qret->rsp, "error", QOBJECT(qdict)); error_free(err); qret->session->return_cb(qret->session, qret->rsp); qmp_return_free(qret); --=20 2.22.0.428.g6d5b264208 From nobody Mon Apr 29 15:02:43 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1563217944; cv=none; d=zoho.com; s=zohoarc; b=JoelLxgsRh99/HhFWw1BPgx7fk7FBcw1KV30SkrN/SrvTjVjBE54Q1GoX3v58W6I4UQXJhx1I2KMIpx7sxtHcZqEAg/o+xhcqVE414+EOLi6Ow18weKFztvsRuykhhbZeR8QDwccCHLVq8/m/NHF1vWsqE0Hvko8LL/tKL3K740= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1563217944; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=k3b6cd0Sqnl5KyKdbyE0jJeFIUBnwFsdtMleGb0cEFQ=; b=E0VxoFhN5wZhN2DLXXqBrQfAz87pVr+inGeT1iaqtyEuWhgrxxjYCb+vn7SG5gYYIZaR7svhM4Ve8b9yDa+29EY8rouYT5tajPI4EcLKlnXD9aPV3XNWBOEllWpjFdeamsFKvc6urrMXq0TFDxjfqpMAlAc6UN1IBYsFDree0Ms= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1563217944937111.81156182863594; Mon, 15 Jul 2019 12:12:24 -0700 (PDT) Received: from localhost ([::1]:42059 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6Od-00028K-To for importer@patchew.org; Mon, 15 Jul 2019 15:12:23 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:40026) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6OP-0001HB-Sx for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:12:10 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hn6OO-0003bA-Ho for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:12:09 -0400 Received: from mx1.redhat.com ([209.132.183.28]:38412) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hn6ON-0003Zc-QJ for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:12:08 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A17D4308A9E2; Mon, 15 Jul 2019 19:12:03 +0000 (UTC) Received: from localhost (ovpn-112-18.ams2.redhat.com [10.36.112.18]) by smtp.corp.redhat.com (Postfix) with ESMTP id CE2F56085B; Mon, 15 Jul 2019 19:11:57 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Mon, 15 Jul 2019 23:09:51 +0400 Message-Id: <20190715191001.1188-11-marcandre.lureau@redhat.com> In-Reply-To: <20190715191001.1188-1-marcandre.lureau@redhat.com> References: <20190715191001.1188-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.41]); Mon, 15 Jul 2019 19:12:03 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v5 10/20] QmpSession: keep a queue of pending commands X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Markus Armbruster , Michael Roth , "Dr. David Alan Gilbert" , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" The following commit will introduce asynchronous commands. Let's keep the session aware of the pending commands, so we can do interesting things like order the replies, or cancel pending operations when the client is gone. The queue needs a lock, since QmpReturn may be called from any thread. Signed-off-by: Marc-Andr=C3=A9 Lureau --- include/qapi/qmp/dispatch.h | 4 ++++ qapi/qmp-dispatch.c | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h index 6c0d21968e..7c9de9780d 100644 --- a/include/qapi/qmp/dispatch.h +++ b/include/qapi/qmp/dispatch.h @@ -16,6 +16,7 @@ =20 #include "qemu/queue.h" #include "qapi/qmp/json-parser.h" +#include "qemu/thread.h" =20 typedef struct QmpReturn QmpReturn; =20 @@ -47,11 +48,14 @@ struct QmpSession { const QmpCommandList *cmds; JSONMessageParser parser; QmpDispatchReturn *return_cb; + QemuMutex pending_lock; + QTAILQ_HEAD(, QmpReturn) pending; }; =20 struct QmpReturn { QmpSession *session; QDict *rsp; + QTAILQ_ENTRY(QmpReturn) entry; }; =20 /** diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 5f75dc27bd..4699a6715b 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -32,11 +32,24 @@ QmpReturn *qmp_return_new(QmpSession *session, const QO= bject *request) qdict_put_obj(qret->rsp, "id", id); } =20 + qemu_mutex_lock(&session->pending_lock); + QTAILQ_INSERT_TAIL(&session->pending, qret, entry); + qemu_mutex_unlock(&session->pending_lock); + return qret; } =20 void qmp_return_free(QmpReturn *qret) { + QmpSession *session =3D qret->session; + + if (session) { + qemu_mutex_lock(&session->pending_lock); + } + QTAILQ_REMOVE(&session->pending, qret, entry); + if (session) { + qemu_mutex_unlock(&session->pending_lock); + } qobject_unref(qret->rsp); g_free(qret); } @@ -44,7 +57,9 @@ void qmp_return_free(QmpReturn *qret) void qmp_return(QmpReturn *qret, QObject *rsp) { qdict_put_obj(qret->rsp, "return", rsp ?: QOBJECT(qdict_new())); - qret->session->return_cb(qret->session, qret->rsp); + if (qret->session) { + qret->session->return_cb(qret->session, qret->rsp); + } qmp_return_free(qret); } =20 @@ -55,7 +70,9 @@ void qmp_return_error(QmpReturn *qret, Error *err) qdict_put_str(qdict, "desc", error_get_pretty(err)); qdict_put_obj(qret->rsp, "error", QOBJECT(qdict)); error_free(err); - qret->session->return_cb(qret->session, qret->rsp); + if (qret->session) { + qret->session->return_cb(qret->session, qret->rsp); + } qmp_return_free(qret); } =20 @@ -219,17 +236,28 @@ void qmp_session_init(QmpSession *session, session, NULL); session->cmds =3D cmds; session->return_cb =3D return_cb; + qemu_mutex_init(&session->pending_lock); + QTAILQ_INIT(&session->pending); } =20 void qmp_session_destroy(QmpSession *session) { + QmpReturn *ret, *next; + if (!session->return_cb) { return; } =20 + qemu_mutex_lock(&session->pending_lock); + QTAILQ_FOREACH_SAFE(ret, &session->pending, entry, next) { + ret->session =3D NULL; + QTAILQ_REMOVE(&session->pending, ret, entry); + } + qemu_mutex_unlock(&session->pending_lock); session->cmds =3D NULL; session->return_cb =3D NULL; json_message_parser_destroy(&session->parser); + qemu_mutex_destroy(&session->pending_lock); } =20 void qmp_dispatch(QmpSession *session, QObject *request, bool allow_oob) --=20 2.22.0.428.g6d5b264208 From nobody Mon Apr 29 15:02:43 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1563217963; cv=none; d=zoho.com; s=zohoarc; b=PQbZcYsR49ZGPF/Q33hl+TQh2A5HkGBf4HYuXhWGSAZBkS/aT78xQOZ8HoxqFyXK9kw9I29ZIqaRUSkgfFTtQPw+dqdJJm/sP7RfxpZwuVCxPN/OuEAHKKxgCgf62/JXg1BrDHmkjcv/vUKQ7TS5sTEDcr5Tor62SFYaG9AdzIg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1563217963; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=BxzhfR/NjxpUMfatTobZInSacVhq8DAvP6hwSrZaSXQ=; b=i15NsDvjE7CPK8rJPirBGQp0NixClNJjbL7yCIOU/JN0CQMwyFbk3oYLQNSFIwXuL2t0JXQfR7lNJhYi8rlDGPUAChpTbyyTclujlKbtZZBAwqhFciIplksecGyrc6+et7YPfGleKcHTogyH3W7mW4dXtj4wutQAmElXErBVGxQ= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1563217963815220.07096182421924; Mon, 15 Jul 2019 12:12:43 -0700 (PDT) Received: from localhost ([::1]:42066 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6Ow-0003JM-FO for importer@patchew.org; Mon, 15 Jul 2019 15:12:42 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:40080) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6OV-0001iK-NS for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:12:16 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hn6OS-0003dB-TB for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:12:15 -0400 Received: from mx1.redhat.com ([209.132.183.28]:55612) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hn6OS-0003cn-LL for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:12:12 -0400 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 03BB03082E0F; Mon, 15 Jul 2019 19:12:12 +0000 (UTC) Received: from localhost (ovpn-112-18.ams2.redhat.com [10.36.112.18]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0E18A60BEC; Mon, 15 Jul 2019 19:12:07 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Mon, 15 Jul 2019 23:09:52 +0400 Message-Id: <20190715191001.1188-12-marcandre.lureau@redhat.com> In-Reply-To: <20190715191001.1188-1-marcandre.lureau@redhat.com> References: <20190715191001.1188-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.46]); Mon, 15 Jul 2019 19:12:12 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v5 11/20] QmpSession: return orderly X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Markus Armbruster , Michael Roth , "Dr. David Alan Gilbert" , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" QEMU will gain support for asynchronous commands, and may thus finish commands in various order. However, the clients expect replies in order. Let's enforce ordering of replies in QmpReturn: starting from the older command, process each pending QmpReturn, and return until reaching one that is unfinished. Or if the command is OOB, it should return immediately. Signed-off-by: Marc-Andr=C3=A9 Lureau --- include/qapi/qmp/dispatch.h | 2 ++ qapi/qmp-dispatch.c | 61 ++++++++++++++++++++++++++++++------- tests/test-qmp-cmds.c | 33 ++++++++++++++++++++ 3 files changed, 85 insertions(+), 11 deletions(-) diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h index 7c9de9780d..92d6fd1afb 100644 --- a/include/qapi/qmp/dispatch.h +++ b/include/qapi/qmp/dispatch.h @@ -55,6 +55,8 @@ struct QmpSession { struct QmpReturn { QmpSession *session; QDict *rsp; + bool oob; + bool finished; QTAILQ_ENTRY(QmpReturn) entry; }; =20 diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 4699a6715b..546a6c9f7b 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -25,6 +25,7 @@ QmpReturn *qmp_return_new(QmpSession *session, const QObj= ect *request) const QDict *req =3D qobject_to(QDict, request); QObject *id =3D req ? qdict_get(req, "id") : NULL; =20 + qret->oob =3D req ? qmp_is_oob(req) : false; qret->session =3D session; qret->rsp =3D qdict_new(); if (id) { @@ -39,6 +40,15 @@ QmpReturn *qmp_return_new(QmpSession *session, const QOb= ject *request) return qret; } =20 +static void qmp_return_free_with_lock(QmpReturn *qret) +{ + if (qret->session) { + QTAILQ_REMOVE(&qret->session->pending, qret, entry); + } + qobject_unref(qret->rsp); + g_free(qret); +} + void qmp_return_free(QmpReturn *qret) { QmpSession *session =3D qret->session; @@ -46,21 +56,53 @@ void qmp_return_free(QmpReturn *qret) if (session) { qemu_mutex_lock(&session->pending_lock); } - QTAILQ_REMOVE(&session->pending, qret, entry); + + qmp_return_free_with_lock(qret); + if (session) { qemu_mutex_unlock(&session->pending_lock); } - qobject_unref(qret->rsp); - g_free(qret); +} + +static void qmp_return_orderly(QmpReturn *qret) +{ + QmpSession *session =3D qret->session; + QmpReturn *ret, *next; + + if (!session) { + /* the session was destroyed before return, discard */ + qmp_return_free(qret); + return; + } + if (qret->oob) { + session->return_cb(session, qret->rsp); + qmp_return_free(qret); + return; + } + + qret->finished =3D true; + + qemu_mutex_lock(&session->pending_lock); + /* + * Process the list of pending and call return_cb until reaching + * an unfinished. + */ + QTAILQ_FOREACH_SAFE(ret, &session->pending, entry, next) { + if (!ret->finished) { + break; + } + session->return_cb(session, ret->rsp); + ret->session =3D session; + qmp_return_free_with_lock(ret); + } + + qemu_mutex_unlock(&session->pending_lock); } =20 void qmp_return(QmpReturn *qret, QObject *rsp) { qdict_put_obj(qret->rsp, "return", rsp ?: QOBJECT(qdict_new())); - if (qret->session) { - qret->session->return_cb(qret->session, qret->rsp); - } - qmp_return_free(qret); + qmp_return_orderly(qret); } =20 void qmp_return_error(QmpReturn *qret, Error *err) @@ -70,10 +112,7 @@ void qmp_return_error(QmpReturn *qret, Error *err) qdict_put_str(qdict, "desc", error_get_pretty(err)); qdict_put_obj(qret->rsp, "error", QOBJECT(qdict)); error_free(err); - if (qret->session) { - qret->session->return_cb(qret->session, qret->rsp); - } - qmp_return_free(qret); + qmp_return_orderly(qret); } =20 static QDict *qmp_dispatch_check_obj(const QObject *request, bool allow_oo= b, diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c index 8e46f88f6f..ece8726e96 100644 --- a/tests/test-qmp-cmds.c +++ b/tests/test-qmp-cmds.c @@ -333,6 +333,38 @@ static void test_dealloc_partial(void) qapi_free_UserDefTwo(ud2); } =20 +typedef struct QmpReturnOrderly { + QmpSession session; + int returns; +} QmpReturnOrderly; + +static void dispatch_return_orderly(QmpSession *session, QDict *resp) +{ + QmpReturnOrderly *o =3D container_of(session, QmpReturnOrderly, sessio= n); + + o->returns++; +} + +static void test_qmp_return_orderly(void) +{ + QDict *dict =3D qdict_new(); + QmpReturnOrderly o =3D { { 0 }, }; + QmpReturn *r1, *r2, *r3; + + qmp_session_init(&o.session, &qmp_commands, NULL, dispatch_return_orde= rly); + r1 =3D qmp_return_new(&o.session, NULL); + qdict_put_str(dict, "exec-oob", "test"); + r2 =3D qmp_return_new(&o.session, QOBJECT(dict)); + r3 =3D qmp_return_new(&o.session, NULL); + qmp_return(r3, NULL); + g_assert_cmpint(o.returns, =3D=3D, 0); + qmp_return(r2, NULL); + g_assert_cmpint(o.returns, =3D=3D, 1); + qmp_return(r1, NULL); + g_assert_cmpint(o.returns, =3D=3D, 3); + qmp_session_destroy(&o.session); + qobject_unref(dict); +} =20 int main(int argc, char **argv) { @@ -346,6 +378,7 @@ int main(int argc, char **argv) test_dispatch_cmd_success_response); g_test_add_func("/qmp/dealloc_types", test_dealloc_types); g_test_add_func("/qmp/dealloc_partial", test_dealloc_partial); + g_test_add_func("/qmp/return_orderly", test_qmp_return_orderly); =20 test_qmp_init_marshal(&qmp_commands); g_test_run(); --=20 2.22.0.428.g6d5b264208 From nobody Mon Apr 29 15:02:43 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1563217964; cv=none; d=zoho.com; s=zohoarc; b=WtO2/iwQjkhIJ6VabkySxHXLEabdMIKXppb1tICir3uBcExBEN3wmk47riZTogqUPZ65JcFnlstYO+iseE/92rtXdlULILQnig75Lm7CI84abhBYbMc5ZSKIfsUPIPkD6+QeUioUMqQgrPAM9ty1D7LzTncHL2wc6+/xNQmeC/M= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1563217964; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=D+m83MtH/T80+kcvbX9i4O2NR3xddUYvhiI2iW/sAss=; b=cIikWPURUFUGgA7InF+fg5s/8N+8AaHVCmsNZtsnI23binQvCDkPdfD11ZjwesS57APpFdKhmb/W5ZPZajBOPFZf6O7/VTkXwXHZ3lGHMKQz33qrrLbLj4Z4qGJ7iEaP3GtccTwbzo6RD07gRpAqxxkAWqzPeuOkOuaD9lUsRSk= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 156321796463397.78600328358482; Mon, 15 Jul 2019 12:12:44 -0700 (PDT) Received: from localhost ([::1]:42068 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6Ox-0003Oj-CN for importer@patchew.org; Mon, 15 Jul 2019 15:12:43 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:40124) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6Of-0002RT-ND for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:12:26 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hn6Oe-0003gd-EW for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:12:25 -0400 Received: from mx1.redhat.com ([209.132.183.28]:58198) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hn6Oe-0003gT-3B for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:12:24 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 69D3859461; Mon, 15 Jul 2019 19:12:23 +0000 (UTC) Received: from localhost (ovpn-112-18.ams2.redhat.com [10.36.112.18]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4484319C78; Mon, 15 Jul 2019 19:12:16 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Mon, 15 Jul 2019 23:09:53 +0400 Message-Id: <20190715191001.1188-13-marcandre.lureau@redhat.com> In-Reply-To: <20190715191001.1188-1-marcandre.lureau@redhat.com> References: <20190715191001.1188-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Mon, 15 Jul 2019 19:12:23 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v5 12/20] qmp: introduce asynchronous command type X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Markus Armbruster , Michael Roth , "Dr. David Alan Gilbert" , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Add a new type of command, QmpCommandFuncAsync: those commands can return later thanks to QmpReturn. This commit introduces the new type and register function and teach qmp_dipatch() to call it without qmp_return(). The async_fn callback will be responsible for calling qmp_return(), either synchronously or asynchronously. Signed-off-by: Marc-Andr=C3=A9 Lureau --- include/qapi/qmp/dispatch.h | 10 +++++++++- qapi/qmp-dispatch.c | 27 ++++++++++++++++----------- qapi/qmp-registry.c | 27 ++++++++++++++++++++++++--- 3 files changed, 49 insertions(+), 15 deletions(-) diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h index 92d6fd1afb..6aef0abc70 100644 --- a/include/qapi/qmp/dispatch.h +++ b/include/qapi/qmp/dispatch.h @@ -21,6 +21,7 @@ typedef struct QmpReturn QmpReturn; =20 typedef void (QmpCommandFunc)(QDict *, QObject **, Error **); +typedef void (QmpCommandAsyncFunc)(QDict *, QmpReturn *); =20 typedef enum QmpCommandOptions { @@ -28,12 +29,16 @@ typedef enum QmpCommandOptions QCO_NO_SUCCESS_RESP =3D (1U << 0), QCO_ALLOW_OOB =3D (1U << 1), QCO_ALLOW_PRECONFIG =3D (1U << 2), + QCO_ASYNC =3D (1U << 3), } QmpCommandOptions; =20 typedef struct QmpCommand { const char *name; - QmpCommandFunc *fn; + union { + QmpCommandFunc *fn; + QmpCommandAsyncFunc *async_fn; + }; QmpCommandOptions options; QTAILQ_ENTRY(QmpCommand) node; bool enabled; @@ -88,6 +93,9 @@ void qmp_return_error(QmpReturn *qret, Error *err); =20 void qmp_register_command(QmpCommandList *cmds, const char *name, QmpCommandFunc *fn, QmpCommandOptions options); +void qmp_register_async_command(QmpCommandList *cmds, const char *name, + QmpCommandAsyncFunc *fn, + QmpCommandOptions options); const QmpCommand *qmp_find_command(const QmpCommandList *cmds, const char *name); void qmp_session_init(QmpSession *session, diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 546a6c9f7b..1f493af67a 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -171,7 +171,7 @@ static QDict *qmp_dispatch_check_obj(const QObject *req= uest, bool allow_oob, return dict; } =20 -static QObject *do_qmp_dispatch(const QmpCommandList *cmds, QObject *reque= st, +static QObject *do_qmp_dispatch(QmpSession *session, QObject *request, bool allow_oob, Error **errp) { Error *local_err =3D NULL; @@ -193,7 +193,7 @@ static QObject *do_qmp_dispatch(const QmpCommandList *c= mds, QObject *request, command =3D qdict_get_str(dict, "exec-oob"); oob =3D true; } - cmd =3D qmp_find_command(cmds, command); + cmd =3D qmp_find_command(session->cmds, command); if (cmd =3D=3D NULL) { error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND, "The command %s has not been found", command); @@ -224,14 +224,19 @@ static QObject *do_qmp_dispatch(const QmpCommandList = *cmds, QObject *request, qobject_ref(args); } =20 - cmd->fn(args, &ret, &local_err); - if (local_err) { - error_propagate(errp, local_err); - } else if (cmd->options & QCO_NO_SUCCESS_RESP) { - g_assert(!ret); - } else if (!ret) { - /* TODO turn into assertion */ - ret =3D QOBJECT(qdict_new()); + + if (cmd->options & QCO_ASYNC) { + cmd->async_fn(args, qmp_return_new(session, request)); + } else { + cmd->fn(args, &ret, &local_err); + if (local_err) { + error_propagate(errp, local_err); + } else if (cmd->options & QCO_NO_SUCCESS_RESP) { + g_assert(!ret); + } else if (!ret) { + /* TODO turn into assertion */ + ret =3D QOBJECT(qdict_new()); + } } =20 qobject_unref(args); @@ -304,7 +309,7 @@ void qmp_dispatch(QmpSession *session, QObject *request= , bool allow_oob) Error *err =3D NULL; QObject *ret; =20 - ret =3D do_qmp_dispatch(session->cmds, request, allow_oob, &err); + ret =3D do_qmp_dispatch(session, request, allow_oob, &err); if (err) { qmp_return_error(qmp_return_new(session, request), err); } else if (ret) { diff --git a/qapi/qmp-registry.c b/qapi/qmp-registry.c index d0f9a1d3e3..0f3d521ce5 100644 --- a/qapi/qmp-registry.c +++ b/qapi/qmp-registry.c @@ -15,16 +15,37 @@ #include "qemu/osdep.h" #include "qapi/qmp/dispatch.h" =20 -void qmp_register_command(QmpCommandList *cmds, const char *name, - QmpCommandFunc *fn, QmpCommandOptions options) + +static QmpCommand *qmp_command_new(QmpCommandList *cmds, const char *name, + QmpCommandOptions options) { QmpCommand *cmd =3D g_malloc0(sizeof(*cmd)); =20 cmd->name =3D name; - cmd->fn =3D fn; cmd->enabled =3D true; cmd->options =3D options; QTAILQ_INSERT_TAIL(cmds, cmd, node); + + return cmd; +} + + +void qmp_register_command(QmpCommandList *cmds, const char *name, + QmpCommandFunc *fn, QmpCommandOptions options) +{ + QmpCommand *cmd =3D qmp_command_new(cmds, name, options); + + assert(!(options & QCO_ASYNC)); + cmd->fn =3D fn; +} + +void qmp_register_async_command(QmpCommandList *cmds, const char *name, + QmpCommandAsyncFunc *fn, QmpCommandOptions opt= ions) +{ + QmpCommand *cmd =3D qmp_command_new(cmds, name, options); + + assert(options & QCO_ASYNC); + cmd->async_fn =3D fn; } =20 const QmpCommand *qmp_find_command(const QmpCommandList *cmds, const char = *name) --=20 2.22.0.428.g6d5b264208 From nobody Mon Apr 29 15:02:43 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1563217983; cv=none; d=zoho.com; s=zohoarc; b=e9oqOZ3wOVodn7T4iLb8HmxNfkETOi9FOo6gZFItpt+jD3l6qSrJ8kexi4jX97M4PNQmBDzasxuGz34CFz9/BU+hDNljaQWltPTaQ+QSWNvmHzJdfcqHI+f/N33YifnF6D4vv6bJX4bO0TKSNkcqqNG6brfGEataas912pBUOPk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1563217983; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=K18zSeTbdYNZSCdjnSZ8fjOb5fZhswNtNy4uDOegP4k=; b=L+GJikGv7TGSeKSMfCMzB9CnFirXcc86I9xkzJOtuVAksb5p7tYhmSB1YiWop9qREAXzv750uBSq3kR9GnZHPpXB1oIPeP/lXZNqaf136C6o4QwVZnmVVxoG5bG2TR4buoIX90h6flsdLU0LdgLCmNBQoebLMC5TvdI2IkIKUWU= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1563217983249569.2063527469015; Mon, 15 Jul 2019 12:13:03 -0700 (PDT) Received: from localhost ([::1]:42080 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6PG-0004q4-5w for importer@patchew.org; Mon, 15 Jul 2019 15:13:02 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:40148) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6Op-00038F-Bf for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:12:37 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hn6Om-0003iM-Sd for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:12:35 -0400 Received: from mx1.redhat.com ([209.132.183.28]:55836) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hn6Om-0003hy-KF for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:12:32 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D2D4883F51; Mon, 15 Jul 2019 19:12:30 +0000 (UTC) Received: from localhost (ovpn-112-18.ams2.redhat.com [10.36.112.18]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7475819C68; Mon, 15 Jul 2019 19:12:28 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Mon, 15 Jul 2019 23:09:54 +0400 Message-Id: <20190715191001.1188-14-marcandre.lureau@redhat.com> In-Reply-To: <20190715191001.1188-1-marcandre.lureau@redhat.com> References: <20190715191001.1188-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Mon, 15 Jul 2019 19:12:30 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v5 13/20] scripts: learn 'async' qapi commands X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Markus Armbruster , Michael Roth , "Dr. David Alan Gilbert" , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Commands with the 'async' key will be registered as async type (see related commit), and will allow a synchronous (in scope callback) or asynchronous return (out-of-scope when ready, in idle etc) by keeping the given QmpReturn and calling qmp_return function later. Ex: { 'command': 'foo-async, 'data': {'arg': 'str'}, 'returns': 'Foo', 'async': true } generates the following marshaller: void qmp_marshal_foo_async(QDict *args, QmpReturn *qret) { Error *err =3D NULL; Visitor *v; q_obj_foo_async_arg arg =3D {0}; v =3D qmp_input_visitor_new(QOBJECT(args), true); visit_start_struct(v, NULL, NULL, 0, &err); if (err) { goto out; } visit_type_q_obj_foo_async_arg_members(v, &arg, &err); if (!err) { visit_check_struct(v, &err); } visit_end_struct(v, NULL); if (err) { goto out; } qmp_foo_async(arg.arg, qret); out: if (err) { qmp_return_error(qret, err); } visit_free(v); v =3D qapi_dealloc_visitor_new(); visit_start_struct(v, NULL, NULL, 0, NULL); visit_type_q_obj_foo_async_arg_members(v, &arg, NULL); visit_end_struct(v, NULL); visit_free(v); } and a return helper: void qmp_foo_async_return(QmpReturn *qret, Foo *ret_in) { Error *err =3D NULL; QObject *ret_out =3D NULL; qmp_marshal_output_Foo(ret_in, &ret_out, &err); if (err) { qmp_return_error(qret, err); } else { qmp_return(qret, ret_out); } } The dispatched function may call the return helper within the calling scope or delay the return. To return an error, it can call qmp_return_error() directly instead. Signed-off-by: Marc-Andr=C3=A9 Lureau --- scripts/qapi/commands.py | 151 ++++++++++++++++++++---- scripts/qapi/common.py | 15 ++- scripts/qapi/doc.py | 3 +- scripts/qapi/introspect.py | 3 +- tests/qapi-schema/qapi-schema-test.json | 5 + tests/qapi-schema/qapi-schema-test.out | 8 ++ tests/qapi-schema/test-qapi.py | 8 +- tests/test-qmp-cmds.c | 60 ++++++++++ 8 files changed, 218 insertions(+), 35 deletions(-) diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py index b929e07be4..4c200c04ca 100644 --- a/scripts/qapi/commands.py +++ b/scripts/qapi/commands.py @@ -16,18 +16,36 @@ See the COPYING file in the top-level directory. from qapi.common import * =20 =20 -def gen_command_decl(name, arg_type, boxed, ret_type): - return mcgen(''' -%(c_type)s qmp_%(c_name)s(%(params)s); +def gen_command_decl(name, arg_type, boxed, ret_type, success_response, as= yn): + if asyn: + extra =3D "QmpReturn *qret" + else: + extra =3D 'Error **errp' + + if asyn: + ret =3D mcgen(''' +void qmp_%(name)s(%(params)s); ''', - c_type=3D(ret_type and ret_type.c_type()) or 'void', - c_name=3Dc_name(name), - params=3Dbuild_params(arg_type, boxed, 'Error **errp')) + name=3Dc_name(name), + params=3Dbuild_params(arg_type, boxed, extra)) + if success_response: + ret +=3D mcgen(''' +void qmp_%(name)s_return(QmpReturn *qret%(c_type)s); +''', + c_type=3D(", " + ret_type.c_type() if ret_type els= e ""), + name=3Dc_name(name)) =20 + return ret + else: + return mcgen(''' +%(c_type)s qmp_%(c_name)s(%(params)s); +''', + c_type=3D(ret_type and ret_type.c_type()) or 'void', + c_name=3Dc_name(name), + params=3Dbuild_params(arg_type, boxed, extra)) =20 -def gen_call(name, arg_type, boxed, ret_type): - ret =3D '' =20 +def gen_argstr(arg_type, boxed): argstr =3D '' if boxed: assert arg_type and not arg_type.is_empty() @@ -39,6 +57,13 @@ def gen_call(name, arg_type, boxed, ret_type): argstr +=3D 'arg.has_%s, ' % c_name(memb.name) argstr +=3D 'arg.%s, ' % c_name(memb.name) =20 + return argstr + + +def gen_call(name, arg_type, boxed, ret_type): + ret =3D '' + + argstr =3D gen_argstr(arg_type, boxed) lhs =3D '' if ret_type: lhs =3D 'retval =3D ' @@ -60,6 +85,50 @@ def gen_call(name, arg_type, boxed, ret_type): return ret =20 =20 +def gen_async_call(name, arg_type, boxed): + argstr =3D gen_argstr(arg_type, boxed) + + push_indent() + ret =3D mcgen(''' + +qmp_%(c_name)s(%(args)sqret); +''', + c_name=3Dc_name(name), args=3Dargstr) + + pop_indent() + return ret + + +def gen_async_return(name, ret_type): + if ret_type: + return mcgen(''' + +void qmp_%(c_name)s_return(QmpReturn *qret, %(ret_type)s ret_in) +{ + Error *err =3D NULL; + QObject *ret_out =3D NULL; + + qmp_marshal_output_%(ret_c_name)s(ret_in, &ret_out, &err); + + if (err) { + qmp_return_error(qret, err); + } else { + qmp_return(qret, ret_out); + } +} +''', + c_name=3Dc_name(name), + ret_type=3Dret_type.c_type(), ret_c_name=3Dret_type.c= _name()) + else: + return mcgen(''' + +void qmp_%(c_name)s_return(QmpReturn *qret) +{ + qmp_return(qret, QOBJECT(qdict_new())); +} +''', + c_name=3Dc_name(name)) + def gen_marshal_output(ret_type): return mcgen(''' =20 @@ -83,19 +152,22 @@ static void qmp_marshal_output_%(c_name)s(%(c_type)s r= et_in, QObject **ret_out, c_type=3Dret_type.c_type(), c_name=3Dret_type.c_name()) =20 =20 -def build_marshal_proto(name): - return ('void qmp_marshal_%s(QDict *args, QObject **ret, Error **errp)' - % c_name(name)) +def build_marshal_proto(name, asyn): + if asyn: + tmpl =3D 'void qmp_marshal_%s(QDict *args, QmpReturn *qret)' + else: + tmpl =3D 'void qmp_marshal_%s(QDict *args, QObject **ret, Error **= errp)' + return tmpl % c_name(name) =20 =20 -def gen_marshal_decl(name): +def gen_marshal_decl(name, asyn): return mcgen(''' %(proto)s; ''', - proto=3Dbuild_marshal_proto(name)) + proto=3Dbuild_marshal_proto(name, asyn)) =20 =20 -def gen_marshal(name, arg_type, boxed, ret_type): +def gen_marshal(name, arg_type, boxed, ret_type, asyn): have_args =3D arg_type and not arg_type.is_empty() =20 ret =3D mcgen(''' @@ -104,9 +176,9 @@ def gen_marshal(name, arg_type, boxed, ret_type): { Error *err =3D NULL; ''', - proto=3Dbuild_marshal_proto(name)) + proto=3Dbuild_marshal_proto(name, asyn)) =20 - if ret_type: + if ret_type and not asyn: ret +=3D mcgen(''' %(c_type)s retval; ''', @@ -153,12 +225,28 @@ def gen_marshal(name, arg_type, boxed, ret_type): } ''') =20 - ret +=3D gen_call(name, arg_type, boxed, ret_type) + if asyn: + ret +=3D gen_async_call(name, arg_type, boxed) + else: + ret +=3D gen_call(name, arg_type, boxed, ret_type) =20 ret +=3D mcgen(''' =20 out: +''') + + if asyn: + ret +=3D mcgen(''' + if (err) { + qmp_return_error(qret, err); + } +''') + else: + ret +=3D mcgen(''' error_propagate(errp, err); +''') + + ret +=3D mcgen(''' visit_free(v); ''') =20 @@ -193,7 +281,8 @@ out: return ret =20 =20 -def gen_register_command(name, success_response, allow_oob, allow_preconfi= g): +def gen_register_command(name, success_response, allow_oob, allow_preconfi= g, + asyn): options =3D [] =20 if not success_response: @@ -202,17 +291,24 @@ def gen_register_command(name, success_response, allo= w_oob, allow_preconfig): options +=3D ['QCO_ALLOW_OOB'] if allow_preconfig: options +=3D ['QCO_ALLOW_PRECONFIG'] + if asyn: + options +=3D ['QCO_ASYNC'] =20 if not options: options =3D ['QCO_NO_OPTIONS'] =20 options =3D " | ".join(options) =20 + if asyn: + regfn =3D 'qmp_register_async_command' + else: + regfn =3D 'qmp_register_command' + ret =3D mcgen(''' - qmp_register_command(cmds, "%(name)s", + %(regfn)s(cmds, "%(name)s", qmp_marshal_%(c_name)s, %(opts)s); ''', - name=3Dname, c_name=3Dc_name(name), + regfn=3Dregfn, name=3Dname, c_name=3Dc_name(name), opts=3Doptions) return ret =20 @@ -276,7 +372,8 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds); genc.add(gen_registry(self._regy.get_content(), self._prefix)) =20 def visit_command(self, name, info, ifcond, arg_type, ret_type, gen, - success_response, boxed, allow_oob, allow_preconfig): + success_response, boxed, allow_oob, allow_preconfig, + asyn): if not gen: return # FIXME: If T is a user-defined type, the user is responsible @@ -290,11 +387,15 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmd= s); self._genh, self._genc, self._regy): self._genc.add(gen_marshal_output(ret_type)) with ifcontext(ifcond, self._genh, self._genc, self._regy): - self._genh.add(gen_command_decl(name, arg_type, boxed, ret_typ= e)) - self._genh.add(gen_marshal_decl(name)) - self._genc.add(gen_marshal(name, arg_type, boxed, ret_type)) + self._genh.add(gen_command_decl(name, arg_type, boxed, ret_typ= e, + success_response, asyn)) + self._genh.add(gen_marshal_decl(name, asyn)) + self._genc.add(gen_marshal(name, arg_type, boxed, ret_type, as= yn)) + if asyn and success_response: + self._genc.add(gen_async_return(name, ret_type)) self._regy.add(gen_register_command(name, success_response, - allow_oob, allow_preconfig= )) + allow_oob, allow_preconfig, + asyn)) =20 =20 def gen_commands(schema, output_dir, prefix): diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index d61bfdc526..1f698e91d1 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -1138,7 +1138,7 @@ def check_exprs(exprs): meta =3D 'command' check_keys(expr_elem, 'command', [], ['data', 'returns', 'gen', 'success-response', - 'boxed', 'allow-oob', 'allow-preconfig', 'if']) + 'boxed', 'allow-oob', 'allow-preconfig', 'if', 'as= ync']) normalize_members(expr.get('data')) elif 'event' in expr: meta =3D 'event' @@ -1283,7 +1283,8 @@ class QAPISchemaVisitor(object): pass =20 def visit_command(self, name, info, ifcond, arg_type, ret_type, gen, - success_response, boxed, allow_oob, allow_preconfig): + success_response, boxed, allow_oob, allow_preconfig, + asyn): pass =20 def visit_event(self, name, info, ifcond, arg_type, boxed): @@ -1697,7 +1698,8 @@ class QAPISchemaAlternateType(QAPISchemaType): =20 class QAPISchemaCommand(QAPISchemaEntity): def __init__(self, name, info, doc, ifcond, arg_type, ret_type, - gen, success_response, boxed, allow_oob, allow_preconfig): + gen, success_response, boxed, allow_oob, allow_preconfig, + asyn): QAPISchemaEntity.__init__(self, name, info, doc, ifcond) assert not arg_type or isinstance(arg_type, str) assert not ret_type or isinstance(ret_type, str) @@ -1710,6 +1712,7 @@ class QAPISchemaCommand(QAPISchemaEntity): self.boxed =3D boxed self.allow_oob =3D allow_oob self.allow_preconfig =3D allow_preconfig + self.asyn =3D asyn =20 def check(self, schema): QAPISchemaEntity.check(self, schema) @@ -1736,7 +1739,7 @@ class QAPISchemaCommand(QAPISchemaEntity): self.arg_type, self.ret_type, self.gen, self.success_response, self.boxed, self.allow_oob, - self.allow_preconfig) + self.allow_preconfig, self.asyn) =20 =20 class QAPISchemaEvent(QAPISchemaEntity): @@ -1989,6 +1992,7 @@ class QAPISchema(object): allow_oob =3D expr.get('allow-oob', False) allow_preconfig =3D expr.get('allow-preconfig', False) ifcond =3D expr.get('if') + asyn =3D expr.get('async', False) if isinstance(data, OrderedDict): data =3D self._make_implicit_object_type( name, info, doc, ifcond, 'arg', self._make_members(data, i= nfo)) @@ -1997,7 +2001,8 @@ class QAPISchema(object): rets =3D self._make_array_type(rets[0], info) self._def_entity(QAPISchemaCommand(name, info, doc, ifcond, data, = rets, gen, success_response, - boxed, allow_oob, allow_preconf= ig)) + boxed, allow_oob, allow_preconf= ig, + asyn)) =20 def _def_event(self, expr, info, doc): name =3D expr['event'] diff --git a/scripts/qapi/doc.py b/scripts/qapi/doc.py index 5fc0fc7e06..6fe280448a 100755 --- a/scripts/qapi/doc.py +++ b/scripts/qapi/doc.py @@ -249,7 +249,8 @@ class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVis= itor): body=3Dtexi_entity(doc, 'Members', ifcond))) =20 def visit_command(self, name, info, ifcond, arg_type, ret_type, gen, - success_response, boxed, allow_oob, allow_preconfig): + success_response, boxed, allow_oob, allow_preconfig, + asyn): 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 f62cf0a2e1..e618e36d38 100644 --- a/scripts/qapi/introspect.py +++ b/scripts/qapi/introspect.py @@ -206,7 +206,8 @@ const QLitObject %(c_name)s =3D %(c_string)s; for m in variants.variants]}, ifcond) =20 def visit_command(self, name, info, ifcond, arg_type, ret_type, gen, - success_response, boxed, allow_oob, allow_preconfig): + success_response, boxed, allow_oob, allow_preconfig, + asyn): arg_type =3D arg_type or self._schema.the_empty_object_type ret_type =3D ret_type or self._schema.the_empty_object_type obj =3D {'arg-type': self._use_type(arg_type), diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qa= pi-schema-test.json index c6d59acc3e..593eefa10b 100644 --- a/tests/qapi-schema/qapi-schema-test.json +++ b/tests/qapi-schema/qapi-schema-test.json @@ -143,6 +143,11 @@ =20 { 'command': 'cmd-success-response', 'data': {}, 'success-response': false= } =20 +{ 'command': 'cmd-async', 'data': {'filename': 'str'}, + 'returns': 'Empty2', 'async': true } +{ 'command': 'cmd-success-response-async', 'data': {'filename': 'str'}, + 'async': true, 'success-response': false} + # Returning a non-dictionary requires a name from the whitelist { 'command': 'guest-get-time', 'data': {'a': 'int', '*b': 'int' }, 'returns': 'int' } diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qap= i-schema-test.out index 85d510bc00..75aee842b9 100644 --- a/tests/qapi-schema/qapi-schema-test.out +++ b/tests/qapi-schema/qapi-schema-test.out @@ -208,6 +208,14 @@ command user_def_cmd2 q_obj_user_def_cmd2-arg -> UserD= efTwo gen=3DTrue success_response=3DTrue boxed=3DFalse oob=3DFalse preconfig= =3DFalse command cmd-success-response None -> None gen=3DTrue success_response=3DFalse boxed=3DFalse oob=3DFalse preconfig= =3DFalse +object q_obj_cmd-async-arg + member filename: str optional=3DFalse +command cmd-async q_obj_cmd-async-arg -> Empty2 + gen=3DTrue success_response=3DTrue boxed=3DFalse oob=3DFalse preconfig= =3DFalse async=3DTrue +object q_obj_cmd-success-response-async-arg + member filename: str optional=3DFalse +command cmd-success-response-async q_obj_cmd-success-response-async-arg ->= None + gen=3DTrue success_response=3DFalse boxed=3DFalse oob=3DFalse preconfig= =3DFalse async=3DTrue object q_obj_guest-get-time-arg member a: int optional=3DFalse member b: int optional=3DTrue diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py index b0f770b9bd..c88cc91763 100644 --- a/tests/qapi-schema/test-qapi.py +++ b/tests/qapi-schema/test-qapi.py @@ -60,12 +60,14 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor): self._print_if(ifcond) =20 def visit_command(self, name, info, ifcond, arg_type, ret_type, gen, - success_response, boxed, allow_oob, allow_preconfig): + success_response, boxed, allow_oob, allow_preconfig, + asyn): print('command %s %s -> %s' % (name, arg_type and arg_type.name, ret_type and ret_type.name)) - print(' gen=3D%s success_response=3D%s boxed=3D%s oob=3D%s preco= nfig=3D%s' - % (gen, success_response, boxed, allow_oob, allow_preconfig)) + print(' gen=3D%s success_response=3D%s boxed=3D%s oob=3D%s preco= nfig=3D%s%s' + % (gen, success_response, boxed, allow_oob, allow_preconfig, + ' async=3DTrue' if asyn else '')) self._print_if(ifcond) =20 def visit_event(self, name, info, ifcond, arg_type, boxed): diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c index ece8726e96..f567ac2fb0 100644 --- a/tests/test-qmp-cmds.c +++ b/tests/test-qmp-cmds.c @@ -34,6 +34,28 @@ void qmp_cmd_success_response(Error **errp) { } =20 +static gboolean cmd_async_idle(gpointer user_data) +{ + QmpReturn *qret =3D user_data; + + qmp_cmd_async_return(qret, g_new0(Empty2, 1)); + + return G_SOURCE_REMOVE; +} + +void qmp_cmd_async(const char *filename, QmpReturn *qret) +{ + g_idle_add(cmd_async_idle, qret); +} + +void qmp_cmd_success_response_async(const char *filename, QmpReturn *qret) +{ + Error *err =3D NULL; + + error_setg(&err, "no response, but error ok"); + qmp_return_error(qret, err); +} + Empty2 *qmp_user_def_cmd0(Error **errp) { return g_new0(Empty2, 1); @@ -366,6 +388,43 @@ static void test_qmp_return_orderly(void) qobject_unref(dict); } =20 +typedef struct QmpReturnAsync { + QmpSession session; + GMainLoop *loop; +} QmpReturnAsync; + +static void dispatch_return_async(QmpSession *session, QDict *resp) +{ + QmpReturnAsync *a =3D container_of(session, QmpReturnAsync, session); + + g_main_loop_quit(a->loop); + g_main_loop_unref(a->loop); + a->loop =3D NULL; +} + +static void test_qmp_return_async(void) +{ + QmpReturnAsync a =3D { { 0, } , }; + QDict *args =3D qdict_new(); + QDict *req =3D qdict_new(); + + a.loop =3D g_main_loop_new(NULL, TRUE); + qmp_session_init(&a.session, &qmp_commands, + NULL, dispatch_return_async); + + qdict_put_str(args, "filename", "test-filename"); + qdict_put_str(req, "execute", "cmd-async"); + qdict_put(req, "arguments", args); + qmp_dispatch(&a.session, QOBJECT(req), false); + g_assert(a.loop); + + g_main_loop_run(a.loop); + g_assert(!a.loop); + + qmp_session_destroy(&a.session); + qobject_unref(req); +} + int main(int argc, char **argv) { g_test_init(&argc, &argv, NULL); @@ -379,6 +438,7 @@ int main(int argc, char **argv) g_test_add_func("/qmp/dealloc_types", test_dealloc_types); g_test_add_func("/qmp/dealloc_partial", test_dealloc_partial); g_test_add_func("/qmp/return_orderly", test_qmp_return_orderly); + g_test_add_func("/qmp/return_async", test_qmp_return_async); =20 test_qmp_init_marshal(&qmp_commands); g_test_run(); --=20 2.22.0.428.g6d5b264208 From nobody Mon Apr 29 15:02:43 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1563218000; cv=none; d=zoho.com; s=zohoarc; b=bAfo81uaN4RpCCVF0ALVRA9A9y30cxrA1k8XBrgOUJM7TY6NtekEwAJ5l9ocy/5EGimptQNMq/z3wB9581A+qYzhAMDf+43NVxgcjEl1UfhpnepsyR9FPQR7wpGDuIKgm+2vpNTxhmOIf1HpE/KPpwj6zlz/RZ0rpefoeUSrMQ0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1563218000; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=afo/SK0vXrkpVKP1I7D5D1nXlUys+ttJezmyI8Wx+hM=; b=RGHb4z9xX6+vJDAe1ueuW988RMNPy5VxAkHaOi8HOcHq+2AeLrScI9ejGyFbfxp+hBMbaaMl1Zk5xF8kfKDq/0isENmgLi36dHKDJDTe1moI1VENTMCUkHMS5HZiPl9V37WauWWHQQK+tBeyIvGW8Z3Tt9Ml+6t4dNo2wsHN8CI= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1563218000266130.07505112111005; Mon, 15 Jul 2019 12:13:20 -0700 (PDT) Received: from localhost ([::1]:42088 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6PW-0005wF-VV for importer@patchew.org; Mon, 15 Jul 2019 15:13:18 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:40178) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6P1-00043S-DT for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:12:49 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hn6Oy-0003lB-Vo for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:12:47 -0400 Received: from mx1.redhat.com ([209.132.183.28]:62510) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hn6Oy-0003kY-Nh for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:12:44 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 0E6D781F11; Mon, 15 Jul 2019 19:12:42 +0000 (UTC) Received: from localhost (ovpn-112-18.ams2.redhat.com [10.36.112.18]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3AFE219C78; Mon, 15 Jul 2019 19:12:35 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Mon, 15 Jul 2019 23:09:55 +0400 Message-Id: <20190715191001.1188-15-marcandre.lureau@redhat.com> In-Reply-To: <20190715191001.1188-1-marcandre.lureau@redhat.com> References: <20190715191001.1188-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Mon, 15 Jul 2019 19:12:42 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v5 14/20] qmp: add qmp_return_is_cancelled() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Markus Armbruster , Michael Roth , "Dr. David Alan Gilbert" , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" If the client is gone, and the session finished, no need to return. The async handler can use this information to avoid unnecessary work and exit earlier. Signed-off-by: Marc-Andr=C3=A9 Lureau --- include/qapi/qmp/dispatch.h | 8 ++++++++ qapi/qmp-dispatch.c | 10 ++++++++++ tests/test-qmp-cmds.c | 39 ++++++++++++++++++++++++++++++++++++- 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h index 6aef0abc70..6673902e95 100644 --- a/include/qapi/qmp/dispatch.h +++ b/include/qapi/qmp/dispatch.h @@ -91,6 +91,14 @@ void qmp_return_free(QmpReturn *qret); void qmp_return(QmpReturn *qret, QObject *rsp); void qmp_return_error(QmpReturn *qret, Error *err); =20 +/* + * @qmp_return_is_cancelled: + * + * Return true if the QmpReturn is cancelled, and free the QmpReturn + * in this case. + */ +bool qmp_return_is_cancelled(QmpReturn *qret); + void qmp_register_command(QmpCommandList *cmds, const char *name, QmpCommandFunc *fn, QmpCommandOptions options); void qmp_register_async_command(QmpCommandList *cmds, const char *name, diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 1f493af67a..8653c17901 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -64,6 +64,16 @@ void qmp_return_free(QmpReturn *qret) } } =20 +bool qmp_return_is_cancelled(QmpReturn *qret) +{ + if (!qret->session) { + qmp_return_free(qret); + return true; + } + + return false; +} + static void qmp_return_orderly(QmpReturn *qret) { QmpSession *session =3D qret->session; diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c index f567ac2fb0..d4c27f0be1 100644 --- a/tests/test-qmp-cmds.c +++ b/tests/test-qmp-cmds.c @@ -34,17 +34,29 @@ void qmp_cmd_success_response(Error **errp) { } =20 +static GMainLoop *loop; + static gboolean cmd_async_idle(gpointer user_data) { QmpReturn *qret =3D user_data; =20 - qmp_cmd_async_return(qret, g_new0(Empty2, 1)); + if (!qret->session) { + g_assert(qmp_return_is_cancelled(qret)); + g_main_loop_quit(loop); + g_main_loop_unref(loop); + loop =3D NULL; + } else { + qmp_cmd_async_return(qret, g_new0(Empty2, 1)); + } =20 return G_SOURCE_REMOVE; } =20 void qmp_cmd_async(const char *filename, QmpReturn *qret) { + if (g_str_equal(filename, "cancel")) { + qmp_session_destroy(qret->session); + } g_idle_add(cmd_async_idle, qret); } =20 @@ -425,6 +437,30 @@ static void test_qmp_return_async(void) qobject_unref(req); } =20 +static void test_qmp_return_async_cancel(void) +{ + QmpReturnAsync a =3D { { 0, }, }; + QDict *args =3D qdict_new(); + QDict *req =3D qdict_new(); + + a.loop =3D g_main_loop_new(NULL, TRUE); + qmp_session_init(&a.session, &qmp_commands, + NULL, dispatch_return_async); + + qdict_put_str(args, "filename", "cancel"); + qdict_put_str(req, "execute", "cmd-async"); + qdict_put(req, "arguments", args); + qmp_dispatch(&a.session, QOBJECT(req), false); + g_assert(a.loop); + + loop =3D a.loop; + g_main_loop_run(loop); + g_assert(!loop); + + qmp_session_destroy(&a.session); + qobject_unref(req); +} + int main(int argc, char **argv) { g_test_init(&argc, &argv, NULL); @@ -439,6 +475,7 @@ int main(int argc, char **argv) g_test_add_func("/qmp/dealloc_partial", test_dealloc_partial); g_test_add_func("/qmp/return_orderly", test_qmp_return_orderly); g_test_add_func("/qmp/return_async", test_qmp_return_async); + g_test_add_func("/qmp/return_async_cancel", test_qmp_return_async_canc= el); =20 test_qmp_init_marshal(&qmp_commands); g_test_run(); --=20 2.22.0.428.g6d5b264208 From nobody Mon Apr 29 15:02:43 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1563218006; cv=none; d=zoho.com; s=zohoarc; b=Jyzqf6WuUl52HpI4W5AYMDKiukxBI4HltCMHVMC2gJ43tBLBAHccwDUprBODMZb4UMzgWaGwNYKh5U76pCGAOF/phUf/eXbm/5QQk0/P5J/v6rc8N6qPv/mn2IBdYbP03xbtDdzotF0RkXY3Fn7r6lrNk2d/FlhcKD0t5Xe/IS4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1563218006; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=KhIIE1DpGdQ8XOdXMpfcErx/liz03PgH2ZIILqNpILQ=; b=aJwgmzdQzGuGmGOUSq+EvnlUxBGwMEpRJSDCN0cgMwEDDBVlyHPiQVZ4pNijJbMONPHOZkH3Zz+u2A5hMmxmHF4oS0MlZB8IZyxhfts0O+viyt5c8xfRfSGJKNev2zu3cMwZN5wVB12UzR5VJPvvyWbTZSSjO0OLvI4h9aMxGp8= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1563218006138277.2960284826054; Mon, 15 Jul 2019 12:13:26 -0700 (PDT) Received: from localhost ([::1]:42090 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6Pc-0006Mf-Im for importer@patchew.org; Mon, 15 Jul 2019 15:13:24 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:40209) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6PB-0004ii-Om for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:12:58 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hn6P9-0003nz-N4 for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:12:56 -0400 Received: from mx1.redhat.com ([209.132.183.28]:38768) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hn6P9-0003n7-H0 for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:12:55 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D49E8308A958; Mon, 15 Jul 2019 19:12:52 +0000 (UTC) Received: from localhost (ovpn-112-18.ams2.redhat.com [10.36.112.18]) by smtp.corp.redhat.com (Postfix) with ESMTP id 49129600C4; Mon, 15 Jul 2019 19:12:46 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Mon, 15 Jul 2019 23:09:56 +0400 Message-Id: <20190715191001.1188-16-marcandre.lureau@redhat.com> In-Reply-To: <20190715191001.1188-1-marcandre.lureau@redhat.com> References: <20190715191001.1188-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.41]); Mon, 15 Jul 2019 19:12:52 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v5 15/20] monitor: add qmp_return_get_monitor() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Markus Armbruster , Michael Roth , "Dr. David Alan Gilbert" , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" If necessary, add an helper that can be used to retrieve the associated monitor. This is useful for asynchronous commands that may have to update cur_mon for various reasons. Signed-off-by: Marc-Andr=C3=A9 Lureau --- include/monitor/monitor.h | 3 +++ monitor/qmp.c | 11 +++++++++++ 2 files changed, 14 insertions(+) diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h index a81eeff5f8..6a2907a366 100644 --- a/include/monitor/monitor.h +++ b/include/monitor/monitor.h @@ -4,6 +4,7 @@ #include "block/block.h" #include "qapi/qapi-types-misc.h" #include "qemu/readline.h" +#include "qapi/qmp/dispatch.h" =20 extern __thread Monitor *cur_mon; typedef struct MonitorHMP MonitorHMP; @@ -43,4 +44,6 @@ int monitor_fdset_dup_fd_add(int64_t fdset_id, int dup_fd= ); void monitor_fdset_dup_fd_remove(int dup_fd); int64_t monitor_fdset_dup_fd_find(int dup_fd); =20 +Monitor *qmp_return_get_monitor(QmpReturn *qret); + #endif /* MONITOR_H */ diff --git a/monitor/qmp.c b/monitor/qmp.c index 056ad7b68b..df8b9d8d4f 100644 --- a/monitor/qmp.c +++ b/monitor/qmp.c @@ -390,3 +390,14 @@ void monitor_init_qmp(Chardev *chr, bool pretty) monitor_list_append(&mon->common); } } + +Monitor *qmp_return_get_monitor(QmpReturn *qret) +{ + MonitorQMP *mon; + + if (!qret->session) { + return NULL; + } + mon =3D container_of(qret->session, MonitorQMP, session); + return &mon->common; +} --=20 2.22.0.428.g6d5b264208 From nobody Mon Apr 29 15:02:43 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1563218033; cv=none; d=zoho.com; s=zohoarc; b=MOgFunUdDqlfht2V8p8bmX8l7OT2wbxomOKty/icvcs/kHw6+4FLV0YAWiFsLAiMBjYSGGaemvG6uusrIW0fLipieVh2R7bPDN6Et8k7DQ69dQaD8v+mOoWJzmZU34aJRxTQQnaT8obXtsjkt2y9ooMB+HQdtZGAUEJ1ahLDxAc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1563218033; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=fW3jlMDGgiYxPXiXy/aKc0jF24DVjtDv7ZIumMZszRU=; b=mU2M5f1zqW/aj8FnznblD2jdJlVslPKvsHrOi+hwrq1elp2nKvBk63evHU99nmlNQEVviKBkMF9WDVUzTRaHV4CvwYquG8fHmB+h1+hV1qhTAbNAF+Nv4AQq5hl4w0FCca5jXIRXCNfICrRxHa0+Cf6VqGOkWunfKh3iCRtrIrY= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1563218033052517.1524218407017; Mon, 15 Jul 2019 12:13:53 -0700 (PDT) Received: from localhost ([::1]:42104 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6Q1-00086Y-HL for importer@patchew.org; Mon, 15 Jul 2019 15:13:49 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:40254) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6PP-0005ix-HD for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:13:12 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hn6PL-0003va-Jg for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:13:10 -0400 Received: from mx1.redhat.com ([209.132.183.28]:56530) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hn6PJ-0003tv-Kc for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:13:07 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id BF94628DE; Mon, 15 Jul 2019 19:13:03 +0000 (UTC) Received: from localhost (ovpn-112-18.ams2.redhat.com [10.36.112.18]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6AD755D784; Mon, 15 Jul 2019 19:12:57 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Mon, 15 Jul 2019 23:09:57 +0400 Message-Id: <20190715191001.1188-17-marcandre.lureau@redhat.com> In-Reply-To: <20190715191001.1188-1-marcandre.lureau@redhat.com> References: <20190715191001.1188-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Mon, 15 Jul 2019 19:13:03 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v5 16/20] console: add graphic_hw_update_done() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Markus Armbruster , Michael Roth , "Dr. David Alan Gilbert" , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Add a function to be called when a graphic update is done. Declare the QXL renderer as async: render_update_cookie_num counts the number of outstanding updates, and graphic_hw_update_done() is called when it reaches none. Signed-off-by: Marc-Andr=C3=A9 Lureau Reviewed-by: Gerd Hoffmann --- hw/display/qxl-render.c | 9 +++++++-- hw/display/qxl.c | 1 + include/ui/console.h | 2 ++ ui/console.c | 9 +++++++++ 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/hw/display/qxl-render.c b/hw/display/qxl-render.c index 14ad2b352d..102fa0b7e9 100644 --- a/hw/display/qxl-render.c +++ b/hw/display/qxl-render.c @@ -108,7 +108,7 @@ static void qxl_render_update_area_unlocked(PCIQXLDevic= e *qxl) qxl->guest_primary.surface= .mem, MEMSLOT_GROUP_GUEST); if (!qxl->guest_primary.data) { - return; + goto end; } qxl_set_rect_to_surface(qxl, &qxl->dirty[0]); qxl->num_dirty_rects =3D 1; @@ -136,7 +136,7 @@ static void qxl_render_update_area_unlocked(PCIQXLDevic= e *qxl) } =20 if (!qxl->guest_primary.data) { - return; + goto end; } for (i =3D 0; i < qxl->num_dirty_rects; i++) { if (qemu_spice_rect_is_empty(qxl->dirty+i)) { @@ -157,6 +157,11 @@ static void qxl_render_update_area_unlocked(PCIQXLDevi= ce *qxl) qxl->dirty[i].bottom - qxl->dirty[i].top); } qxl->num_dirty_rects =3D 0; + +end: + if (qxl->render_update_cookie_num =3D=3D 0) { + graphic_hw_update_done(qxl->ssd.dcl.con); + } } =20 /* diff --git a/hw/display/qxl.c b/hw/display/qxl.c index 98c7410032..188399acd1 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -1178,6 +1178,7 @@ static const QXLInterface qxl_interface =3D { =20 static const GraphicHwOps qxl_ops =3D { .gfx_update =3D qxl_hw_update, + .gfx_update_async =3D true, }; =20 static void qxl_enter_vga_mode(PCIQXLDevice *d) diff --git a/include/ui/console.h b/include/ui/console.h index f981696848..281f9c145b 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -365,6 +365,7 @@ static inline void console_write_ch(console_ch_t *dest,= uint32_t ch) typedef struct GraphicHwOps { void (*invalidate)(void *opaque); void (*gfx_update)(void *opaque); + bool gfx_update_async; /* if true, calls graphic_hw_update_done() */ void (*text_update)(void *opaque, console_ch_t *text); void (*update_interval)(void *opaque, uint64_t interval); int (*ui_info)(void *opaque, uint32_t head, QemuUIInfo *info); @@ -380,6 +381,7 @@ void graphic_console_set_hwops(QemuConsole *con, void graphic_console_close(QemuConsole *con); =20 void graphic_hw_update(QemuConsole *con); +void graphic_hw_update_done(QemuConsole *con); void graphic_hw_invalidate(QemuConsole *con); void graphic_hw_text_update(QemuConsole *con, console_ch_t *chardata); void graphic_hw_gl_block(QemuConsole *con, bool block); diff --git a/ui/console.c b/ui/console.c index 82d1ddac9c..3c941528d2 100644 --- a/ui/console.c +++ b/ui/console.c @@ -259,13 +259,22 @@ static void gui_setup_refresh(DisplayState *ds) ds->have_text =3D have_text; } =20 +void graphic_hw_update_done(QemuConsole *con) +{ +} + void graphic_hw_update(QemuConsole *con) { + bool async =3D false; if (!con) { con =3D active_console; } if (con && con->hw_ops->gfx_update) { con->hw_ops->gfx_update(con->hw); + async =3D con->hw_ops->gfx_update_async; + } + if (!async) { + graphic_hw_update_done(con); } } =20 --=20 2.22.0.428.g6d5b264208 From nobody Mon Apr 29 15:02:43 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1563218033; cv=none; d=zoho.com; s=zohoarc; b=hcgIZFDNZ3Y7IypJQsp4fTw1xrEEdXDAlUwEUW7ti9SuyzVjkWD5eGHFQ+rNC0am1AjQCn9k8QNCGM7i3gCUIgO/uDhfpm3VVhPTz6OjfhZdWXJlGaVvA9T7N96S37nv3SbuGoS5WJ9/k6o/9jq3sR+TEAn3rdKSS+ZF3VG4g5M= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1563218033; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=lJfA4+w6/54lHGiooGa00/pW2Cdkw4hZXdBWk72XA/s=; b=nCbSfqgEVVfiC7FoALrEgQ9EwpWtl7PfSzzfih9EYmmFsvcX1VPq59dRvPHD2us4JGtn+N/1DNSVc6OIbKnMjIMLNZANIruHAvLBF8ZV4Wja7gvVh+TgoA+G30Vz10PcpS7U4QhnvuG5c4FyrYbS6qx0+NLFgHfhBDomH2TTRBk= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1563218033856154.8875909528805; Mon, 15 Jul 2019 12:13:53 -0700 (PDT) Received: from localhost ([::1]:42106 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6Q3-00086w-Gm for importer@patchew.org; Mon, 15 Jul 2019 15:13:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:40292) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6Pa-0006W2-5C for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:13:26 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hn6PV-0003zM-Dt for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:13:22 -0400 Received: from mx1.redhat.com ([209.132.183.28]:40392) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hn6PU-0003yD-E8 for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:13:17 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 3B41930832C9; Mon, 15 Jul 2019 19:13:14 +0000 (UTC) Received: from localhost (ovpn-112-18.ams2.redhat.com [10.36.112.18]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2BF8D19C68; Mon, 15 Jul 2019 19:13:07 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Mon, 15 Jul 2019 23:09:58 +0400 Message-Id: <20190715191001.1188-18-marcandre.lureau@redhat.com> In-Reply-To: <20190715191001.1188-1-marcandre.lureau@redhat.com> References: <20190715191001.1188-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.44]); Mon, 15 Jul 2019 19:13:14 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v5 17/20] console: make screendump asynchronous X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Markus Armbruster , Michael Roth , "Dr. David Alan Gilbert" , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Make screendump asynchronous to provide correct screendumps. For now, HMP doesn't have async support, so it has to remain synchronous and potentially incorrect to avoid races (following patches will add HMP asynchronous commands) Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=3D1230527 Signed-off-by: Marc-Andr=C3=A9 Lureau --- include/ui/console.h | 3 ++ monitor/hmp-cmds.c | 2 +- qapi/ui.json | 3 +- ui/console.c | 103 +++++++++++++++++++++++++++++++++++++++---- 4 files changed, 100 insertions(+), 11 deletions(-) diff --git a/include/ui/console.h b/include/ui/console.h index 281f9c145b..a1935557cc 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -74,6 +74,9 @@ typedef struct MouseTransformInfo { } MouseTransformInfo; =20 void hmp_mouse_set(Monitor *mon, const QDict *qdict); +void hmp_screendump_sync(const char *filename, + bool has_device, const char *device, + bool has_head, int64_t head, Error **errp); =20 /* keysym is a unicode code except for special keys (see QEMU_KEY_xxx constants) */ diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c index 5ca3ebe942..50a25a1ddc 100644 --- a/monitor/hmp-cmds.c +++ b/monitor/hmp-cmds.c @@ -2341,7 +2341,7 @@ void hmp_screendump(Monitor *mon, const QDict *qdict) int64_t head =3D qdict_get_try_int(qdict, "head", 0); Error *err =3D NULL; =20 - qmp_screendump(filename, id !=3D NULL, id, id !=3D NULL, head, &err); + hmp_screendump_sync(filename, id !=3D NULL, id, id !=3D NULL, head, &e= rr); hmp_handle_error(mon, &err); } =20 diff --git a/qapi/ui.json b/qapi/ui.json index 59e412139a..cbb3979172 100644 --- a/qapi/ui.json +++ b/qapi/ui.json @@ -96,7 +96,8 @@ # ## { 'command': 'screendump', - 'data': {'filename': 'str', '*device': 'str', '*head': 'int'} } + 'data': {'filename': 'str', '*device': 'str', '*head': 'int'}, + 'async': true } =20 ## # =3D=3D Spice diff --git a/ui/console.c b/ui/console.c index 3c941528d2..29c850c31c 100644 --- a/ui/console.c +++ b/ui/console.c @@ -33,6 +33,7 @@ #include "chardev/char-fe.h" #include "trace.h" #include "exec/memory.h" +#include "monitor/monitor.h" =20 #define DEFAULT_BACKSCROLL 512 #define CONSOLE_CURSOR_PERIOD 500 @@ -117,6 +118,12 @@ typedef enum { TEXT_CONSOLE_FIXED_SIZE } console_type_t; =20 +struct qmp_screendump { + gchar *filename; + QmpReturn *ret; + QLIST_ENTRY(qmp_screendump) link; +}; + struct QemuConsole { Object parent; =20 @@ -167,6 +174,8 @@ struct QemuConsole { uint8_t out_fifo_buf[16]; QEMUTimer *kbd_timer; =20 + QLIST_HEAD(, qmp_screendump) qmp_screendumps; + QTAILQ_ENTRY(QemuConsole) next; }; =20 @@ -193,6 +202,8 @@ static void dpy_refresh(DisplayState *s); static DisplayState *get_alloc_displaystate(void); static void text_console_update_cursor_timer(void); static void text_console_update_cursor(void *opaque); +static void ppm_save(const char *filename, DisplaySurface *ds, + Error **errp); =20 static void gui_update(void *opaque) { @@ -259,8 +270,48 @@ static void gui_setup_refresh(DisplayState *ds) ds->have_text =3D have_text; } =20 +static void qmp_screendump_finish(QemuConsole *con, struct qmp_screendump = *dump) +{ + Error *err =3D NULL; + DisplaySurface *surface; + Monitor *prev_mon =3D cur_mon; + + if (qmp_return_is_cancelled(dump->ret)) { + goto cleanup; + } + + cur_mon =3D qmp_return_get_monitor(dump->ret); + surface =3D qemu_console_surface(con); + if (!surface) { + error_setg(&err, "no surface"); + } else { + /* + * FIXME: async save with coroutine? it would have to copy or + * lock the surface. + */ + ppm_save(dump->filename, surface, &err); + } + + if (err) { + qmp_return_error(dump->ret, err); + } else { + qmp_screendump_return(dump->ret); + } + cur_mon =3D prev_mon; + +cleanup: + g_free(dump->filename); + QLIST_REMOVE(dump, link); + g_free(dump); +} + void graphic_hw_update_done(QemuConsole *con) { + struct qmp_screendump *dump, *next; + + QLIST_FOREACH_SAFE(dump, &con->qmp_screendumps, link, next) { + qmp_screendump_finish(con, dump); + } } =20 void graphic_hw_update(QemuConsole *con) @@ -356,30 +407,41 @@ write_err: goto out; } =20 -void qmp_screendump(const char *filename, bool has_device, const char *dev= ice, - bool has_head, int64_t head, Error **errp) + +static QemuConsole *get_console(bool has_device, const char *device, + bool has_head, int64_t head, Error **errp) { - QemuConsole *con; - DisplaySurface *surface; + QemuConsole *con =3D NULL; =20 if (has_device) { con =3D qemu_console_lookup_by_device_name(device, has_head ? head= : 0, errp); - if (!con) { - return; - } } else { if (has_head) { error_setg(errp, "'head' must be specified together with 'devi= ce'"); - return; + return NULL; } con =3D qemu_console_lookup_by_index(0); if (!con) { error_setg(errp, "There is no console to take a screendump fro= m"); - return; } } =20 + return con; +} + +void hmp_screendump_sync(const char *filename, + bool has_device, const char *device, + bool has_head, int64_t head, Error **errp) +{ + DisplaySurface *surface; + QemuConsole *con =3D get_console(has_device, device, has_head, head, e= rrp); + + if (!con) { + return; + } + /* This may not complete the drawing with Spice, you may have + * glitches or outdated dumps, use qmp instead! */ graphic_hw_update(con); surface =3D qemu_console_surface(con); if (!surface) { @@ -390,6 +452,28 @@ void qmp_screendump(const char *filename, bool has_dev= ice, const char *device, ppm_save(filename, surface, errp); } =20 +void qmp_screendump(const char *filename, + bool has_device, const char *device, + bool has_head, int64_t head, + QmpReturn *qret) +{ + Error *err =3D NULL; + struct qmp_screendump *dump =3D NULL; + QemuConsole *con =3D get_console(has_device, device, has_head, head, &= err); + + if (!con) { + qmp_return_error(qret, err); + return; + } + + dump =3D g_new(struct qmp_screendump, 1); + dump->filename =3D g_strdup(filename); + dump->ret =3D qret; + QLIST_INSERT_HEAD(&con->qmp_screendumps, dump, link); + + graphic_hw_update(con); +} + void graphic_hw_text_update(QemuConsole *con, console_ch_t *chardata) { if (!con) { @@ -1300,6 +1384,7 @@ static QemuConsole *new_console(DisplayState *ds, con= sole_type_t console_type, obj =3D object_new(TYPE_QEMU_CONSOLE); s =3D QEMU_CONSOLE(obj); s->head =3D head; + QLIST_INIT(&s->qmp_screendumps); object_property_add_link(obj, "device", TYPE_DEVICE, (Object **)&s->device, object_property_allow_set_link, --=20 2.22.0.428.g6d5b264208 From nobody Mon Apr 29 15:02:43 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1563218056; cv=none; d=zoho.com; s=zohoarc; b=XlPqjwX/gP8AjR4o/1X5FizJpswD2Qr/j33cqntaWM4Rkw3iVKD6vZBjaTrvGuZJhAlyq3A1w7g/lzHDrH0EcYwLPLCMOgS1TBxoSUHB6vPNG6X0TEZDXWZiRnu6PfJ4q46s02dbGvKUNieaC/BV9dyM9RHeoiAY4/GVSKj+s5U= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1563218056; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=+tzVlHhTYfpjW7MhNCWVBtE32T/h6h8405h9uOZVfv8=; b=Ut3wXREKfAXQwP0wZjHJboQT6SD6JlC/Q+nrg2Io24IpsEK7/niIV16ta8pZr03+h7wrvTLctb4EC0v7K2tPdBDDyz2UMc3hjIXVfhHFHZAF6BZIBoGYMhBVfx0H3g4DMrh4D4e0wQnJOrqTAs3L0MTsHyVw9zSU3RCfPucQnug= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1563218056459943.8544377331453; Mon, 15 Jul 2019 12:14:16 -0700 (PDT) Received: from localhost ([::1]:42118 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6QQ-0001n1-8e for importer@patchew.org; Mon, 15 Jul 2019 15:14:14 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:40327) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6Pg-00070v-LQ for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:13:30 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hn6Pe-00042g-NN for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:13:27 -0400 Received: from mx1.redhat.com ([209.132.183.28]:39060) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hn6Pe-00041o-IA for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:13:26 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id DF0DC308A958; Mon, 15 Jul 2019 19:13:24 +0000 (UTC) Received: from localhost (ovpn-112-18.ams2.redhat.com [10.36.112.18]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4AC625B681; Mon, 15 Jul 2019 19:13:18 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Mon, 15 Jul 2019 23:09:59 +0400 Message-Id: <20190715191001.1188-19-marcandre.lureau@redhat.com> In-Reply-To: <20190715191001.1188-1-marcandre.lureau@redhat.com> References: <20190715191001.1188-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.41]); Mon, 15 Jul 2019 19:13:24 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v5 18/20] monitor: start making qmp_human_monitor_command() asynchronous X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Markus Armbruster , Michael Roth , "Dr. David Alan Gilbert" , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" This prepares the work for HMP commands to be asynchronous. Start making QMP human-monitor-command asynchronous, although QmpReturn is used synchronously on error or after handle_hmp_command(). Signed-off-by: Marc-Andr=C3=A9 Lureau --- monitor/misc.c | 14 ++++++++------ qapi/misc.json | 3 ++- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/monitor/misc.c b/monitor/misc.c index a23c1b8ba4..0645667e1b 100644 --- a/monitor/misc.c +++ b/monitor/misc.c @@ -115,8 +115,8 @@ static QLIST_HEAD(, MonFdset) mon_fdsets; =20 static HMPCommand hmp_info_cmds[]; =20 -char *qmp_human_monitor_command(const char *command_line, bool has_cpu_ind= ex, - int64_t cpu_index, Error **errp) +void qmp_human_monitor_command(const char *command_line, bool has_cpu_inde= x, + int64_t cpu_index, QmpReturn *qret) { char *output =3D NULL; Monitor *old_mon; @@ -130,15 +130,15 @@ char *qmp_human_monitor_command(const char *command_l= ine, bool has_cpu_index, if (has_cpu_index) { int ret =3D monitor_set_cpu(cpu_index); if (ret < 0) { - cur_mon =3D old_mon; - error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "cpu-index", + Error *err =3D NULL; + error_setg(&err, QERR_INVALID_PARAMETER_VALUE, "cpu-index", "a CPU number"); + qmp_return_error(qret, err); goto out; } } =20 handle_hmp_command(&hmp, command_line); - cur_mon =3D old_mon; =20 qemu_mutex_lock(&hmp.common.mon_lock); if (qstring_get_length(hmp.common.outbuf) > 0) { @@ -148,9 +148,11 @@ char *qmp_human_monitor_command(const char *command_li= ne, bool has_cpu_index, } qemu_mutex_unlock(&hmp.common.mon_lock); =20 + qmp_human_monitor_command_return(qret, output); + out: + cur_mon =3D old_mon; monitor_data_destroy(&hmp.common); - return output; } =20 /** diff --git a/qapi/misc.json b/qapi/misc.json index a7fba7230c..8c6ca46b8b 100644 --- a/qapi/misc.json +++ b/qapi/misc.json @@ -1047,7 +1047,8 @@ ## { 'command': 'human-monitor-command', 'data': {'command-line': 'str', '*cpu-index': 'int'}, - 'returns': 'str' } + 'returns': 'str', + 'async': true } =20 ## # @change: --=20 2.22.0.428.g6d5b264208 From nobody Mon Apr 29 15:02:43 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1563218048; cv=none; d=zoho.com; s=zohoarc; b=NO6/U7TN2yEh+CtacJYTOq9tshe5EoCoFzF2Fm+LHciSuppcF/PIti5eNAVzie4HGDWxsgbdrOuLNB/4WQchZuNyffkXKu+fEO5IW5WIp5c+FoJFcbecDB2hppzQT+FVQQ37AR7jM2hJMqmbl7PHn0r/AodweKl78Y0BTE12A4c= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1563218048; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=nT6zZQ0VQJJ0MIxKizdP+5zAwLJp6hV5RyZTzayIpIE=; b=S6NgL60ETWY0g1C4Pii7cBa4D/E0cbY5YOzsVDq94X1+ASGa8ikQIwmc/WHohQFiDTv4ry3rtNeMmVY0zF0TTgkIp0AZKqHAiEmffEJ8ouNacYuSTxi9EZULXztnKJLwmM00NlSfvskW+hfuEcfHUSNce5mLYq+ODbQvZMtmAzE= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1563218048049407.3644425500903; Mon, 15 Jul 2019 12:14:08 -0700 (PDT) Received: from localhost ([::1]:42111 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6QG-0000vU-Md for importer@patchew.org; Mon, 15 Jul 2019 15:14:04 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:40409) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6Pr-0007nQ-6u for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:13:41 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hn6Pn-00045V-G2 for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:13:39 -0400 Received: from mx1.redhat.com ([209.132.183.28]:48722) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hn6Pn-00044M-7q for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:13:35 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8D2A6C036744; Mon, 15 Jul 2019 19:13:33 +0000 (UTC) Received: from localhost (ovpn-112-18.ams2.redhat.com [10.36.112.18]) by smtp.corp.redhat.com (Postfix) with ESMTP id 00D865D96F; Mon, 15 Jul 2019 19:13:29 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Mon, 15 Jul 2019 23:10:00 +0400 Message-Id: <20190715191001.1188-20-marcandre.lureau@redhat.com> In-Reply-To: <20190715191001.1188-1-marcandre.lureau@redhat.com> References: <20190715191001.1188-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Mon, 15 Jul 2019 19:13:33 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v5 19/20] monitor: teach HMP about asynchronous commands X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Markus Armbruster , Michael Roth , "Dr. David Alan Gilbert" , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" Similar to how we handle both synchronous and asynchronous commands in QMP, HMP gains a new async_cmd() that will allow the command to complete asynchronously. For interactive reasons, and command ordering, the HMP monitor is suspended until the asynchronous command completes. It is expected that HMP async commands will be implemented re-using QMP async commands counterparts, so it reuses the QmpSession/QmpReturn for context handling (instead of introducing HmpSession/HmpReturn and having to convert from one to the other as we call QMP counterparts). hmp_dispatch_return_cb() will handle printing the result to the current monitor. It may have different ways to print the QmpReturn result to the current monitor. Currently, only error reporting is implemented. QMP human-monitor-command is modified to deal with an async HMP commands too. It creates a temporary session, and the return callback will return asynchronously to the original QMP command and destroy the temporary monitor when hmp->for_qmp_command is set. Signed-off-by: Marc-Andr=C3=A9 Lureau --- include/monitor/monitor.h | 2 +- monitor/hmp.c | 110 +++++++++++++++++++++++++++++++++++-- monitor/misc.c | 40 -------------- monitor/monitor-internal.h | 9 ++- monitor/qmp.c | 14 +++-- 5 files changed, 123 insertions(+), 52 deletions(-) diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h index 6a2907a366..5968b52fe2 100644 --- a/include/monitor/monitor.h +++ b/include/monitor/monitor.h @@ -44,6 +44,6 @@ int monitor_fdset_dup_fd_add(int64_t fdset_id, int dup_fd= ); void monitor_fdset_dup_fd_remove(int dup_fd); int64_t monitor_fdset_dup_fd_find(int dup_fd); =20 -Monitor *qmp_return_get_monitor(QmpReturn *qret); +Monitor *qmp_return_get_monitor(QmpReturn *qret, bool hmp); =20 #endif /* MONITOR_H */ diff --git a/monitor/hmp.c b/monitor/hmp.c index 5223661e82..b2b6dce8fb 100644 --- a/monitor/hmp.c +++ b/monitor/hmp.c @@ -26,11 +26,15 @@ #include #include "monitor-internal.h" #include "qapi/error.h" +#include "qapi/qapi-commands-misc.h" +#include "qapi/qmp/qerror.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qnum.h" +#include "qapi/qmp/qstring.h" #include "qemu/config-file.h" #include "qemu/ctype.h" #include "qemu/cutils.h" +#include "qemu/error-report.h" #include "qemu/log.h" #include "qemu/option.h" #include "qemu/units.h" @@ -38,6 +42,8 @@ #include "sysemu/sysemu.h" #include "trace.h" =20 +static bool handle_hmp_command(MonitorHMP *mon, const char *cmdline); + static void monitor_command_cb(void *opaque, const char *cmdline, void *readline_opaque) { @@ -1056,7 +1062,7 @@ fail: return NULL; } =20 -void handle_hmp_command(MonitorHMP *mon, const char *cmdline) +static bool handle_hmp_command(MonitorHMP *mon, const char *cmdline) { QDict *qdict; const HMPCommand *cmd; @@ -1066,7 +1072,7 @@ void handle_hmp_command(MonitorHMP *mon, const char *= cmdline) =20 cmd =3D monitor_parse_command(mon, cmdline, &cmdline, hmp_cmds); if (!cmd) { - return; + return false; } =20 qdict =3D monitor_parse_arguments(&mon->common, &cmdline, cmd); @@ -1076,11 +1082,19 @@ void handle_hmp_command(MonitorHMP *mon, const char= *cmdline) } monitor_printf(&mon->common, "Try \"help %.*s\" for more informati= on\n", (int)(cmdline - cmd_start), cmd_start); - return; + return false; } =20 - cmd->cmd(&mon->common, qdict); + if (cmd->async) { + QmpReturn *qret =3D qmp_return_new(&mon->qmp_session, NULL); + monitor_suspend(&mon->common); + cmd->async_cmd(&mon->common, qdict, qret); + } else { + cmd->cmd(&mon->common, qdict); + } qobject_unref(qdict); + + return cmd->async; } =20 static void cmd_completion(MonitorHMP *mon, const char *name, const char *= list) @@ -1395,6 +1409,59 @@ static void monitor_readline_flush(void *opaque) monitor_flush(&mon->common); } =20 +static void free_hmp_monitor(void *opaque) +{ + MonitorHMP *hmp =3D opaque; + + qmp_session_destroy(&hmp->qmp_session); + monitor_data_destroy(&hmp->common); + g_free(hmp); +} + +static AioContext *monitor_get_aio_context(void) +{ + return iothread_get_aio_context(mon_iothread); +} + +static void qmp_human_monitor_command_finish(MonitorHMP *hmp, QmpReturn *q= ret) +{ + char *output; + + qemu_mutex_lock(&hmp->common.mon_lock); + if (qstring_get_length(hmp->common.outbuf) > 0) { + output =3D g_strdup(qstring_get_str(hmp->common.outbuf)); + } else { + output =3D g_strdup(""); + } + qemu_mutex_unlock(&hmp->common.mon_lock); + + qmp_human_monitor_command_return(qret, output); + + if (hmp->for_qmp_command) { + aio_bh_schedule_oneshot(monitor_get_aio_context(), + free_hmp_monitor, hmp); + } +} + +static void hmp_dispatch_return_cb(QmpSession *session, QDict *rsp) +{ + MonitorHMP *hmp =3D container_of(session, MonitorHMP, qmp_session); + QDict *err =3D qdict_get_qdict(rsp, "error"); + Monitor *old_mon =3D cur_mon; + + cur_mon =3D &hmp->common; + if (err) { + error_report("%s", qdict_get_str(err, "desc")); + } /* XXX: else, report depending on command */ + + if (hmp->for_qmp_command) { + qmp_human_monitor_command_finish(hmp, hmp->for_qmp_command); + } else { + monitor_resume(&hmp->common); + } + cur_mon =3D old_mon; +} + void monitor_init_hmp(Chardev *chr, bool use_readline) { MonitorHMP *mon =3D g_new0(MonitorHMP, 1); @@ -1411,7 +1478,42 @@ void monitor_init_hmp(Chardev *chr, bool use_readlin= e) monitor_read_command(mon, 0); } =20 + qmp_session_init(&mon->qmp_session, + NULL, NULL, hmp_dispatch_return_cb); qemu_chr_fe_set_handlers(&mon->common.chr, monitor_can_read, monitor_r= ead, monitor_event, NULL, &mon->common, NULL, true= ); monitor_list_append(&mon->common); } + +void qmp_human_monitor_command(const char *command_line, bool has_cpu_inde= x, + int64_t cpu_index, QmpReturn *qret) +{ + Monitor *old_mon; + MonitorHMP *hmp =3D g_new0(MonitorHMP, 1); + + monitor_data_init(&hmp->common, false, true, false); + qmp_session_init(&hmp->qmp_session, NULL, NULL, hmp_dispatch_return_cb= ); + hmp->for_qmp_command =3D qret; + + old_mon =3D cur_mon; + cur_mon =3D &hmp->common; + + if (has_cpu_index) { + int ret =3D monitor_set_cpu(cpu_index); + if (ret < 0) { + Error *err =3D NULL; + error_setg(&err, QERR_INVALID_PARAMETER_VALUE, "cpu-index", + "a CPU number"); + qmp_return_error(qret, err); + free_hmp_monitor(hmp); + goto out; + } + } + + if (!handle_hmp_command(hmp, command_line)) { + qmp_human_monitor_command_finish(hmp, qret); + } + +out: + cur_mon =3D old_mon; +} diff --git a/monitor/misc.c b/monitor/misc.c index 0645667e1b..19a2919154 100644 --- a/monitor/misc.c +++ b/monitor/misc.c @@ -115,46 +115,6 @@ static QLIST_HEAD(, MonFdset) mon_fdsets; =20 static HMPCommand hmp_info_cmds[]; =20 -void qmp_human_monitor_command(const char *command_line, bool has_cpu_inde= x, - int64_t cpu_index, QmpReturn *qret) -{ - char *output =3D NULL; - Monitor *old_mon; - MonitorHMP hmp =3D {}; - - monitor_data_init(&hmp.common, false, true, false); - - old_mon =3D cur_mon; - cur_mon =3D &hmp.common; - - if (has_cpu_index) { - int ret =3D monitor_set_cpu(cpu_index); - if (ret < 0) { - Error *err =3D NULL; - error_setg(&err, QERR_INVALID_PARAMETER_VALUE, "cpu-index", - "a CPU number"); - qmp_return_error(qret, err); - goto out; - } - } - - handle_hmp_command(&hmp, command_line); - - qemu_mutex_lock(&hmp.common.mon_lock); - if (qstring_get_length(hmp.common.outbuf) > 0) { - output =3D g_strdup(qstring_get_str(hmp.common.outbuf)); - } else { - output =3D g_strdup(""); - } - qemu_mutex_unlock(&hmp.common.mon_lock); - - qmp_human_monitor_command_return(qret, output); - -out: - cur_mon =3D old_mon; - monitor_data_destroy(&hmp.common); -} - /** * Is @name in the '|' separated list of names @list? */ diff --git a/monitor/monitor-internal.h b/monitor/monitor-internal.h index 65cf668b20..cab2712187 100644 --- a/monitor/monitor-internal.h +++ b/monitor/monitor-internal.h @@ -73,7 +73,10 @@ typedef struct HMPCommand { const char *params; const char *help; const char *flags; /* p=3Dpreconfig */ - void (*cmd)(Monitor *mon, const QDict *qdict); + union { + void (*cmd)(Monitor *mon, const QDict *qdict); + void (*async_cmd)(Monitor *mon, const QDict *qdict, QmpReturn *qre= t); + }; /* * @sub_table is a list of 2nd level of commands. If it does not exist, * cmd should be used. If it exists, sub_table[?].cmd should be @@ -81,6 +84,7 @@ typedef struct HMPCommand { */ struct HMPCommand *sub_table; void (*command_completion)(ReadLineState *rs, int nb_args, const char = *str); + bool async; } HMPCommand; =20 struct Monitor { @@ -121,6 +125,8 @@ struct MonitorHMP { * These members can be safely accessed without locks. */ ReadLineState *rs; + QmpReturn *for_qmp_command; + QmpSession qmp_session; }; =20 typedef struct { @@ -176,7 +182,6 @@ void monitor_qmp_bh_dispatcher(void *data); =20 int get_monitor_def(int64_t *pval, const char *name); void help_cmd(Monitor *mon, const char *name); -void handle_hmp_command(MonitorHMP *mon, const char *cmdline); int hmp_compare_cmd(const char *name, const char *list); =20 #endif diff --git a/monitor/qmp.c b/monitor/qmp.c index df8b9d8d4f..cadaf77515 100644 --- a/monitor/qmp.c +++ b/monitor/qmp.c @@ -391,13 +391,17 @@ void monitor_init_qmp(Chardev *chr, bool pretty) } } =20 -Monitor *qmp_return_get_monitor(QmpReturn *qret) +Monitor *qmp_return_get_monitor(QmpReturn *qret, bool hmp) { - MonitorQMP *mon; - if (!qret->session) { return NULL; } - mon =3D container_of(qret->session, MonitorQMP, session); - return &mon->common; + + if (hmp) { + MonitorHMP *hmp =3D container_of(qret->session, MonitorHMP, qmp_se= ssion); + return &hmp->common; + } else { + MonitorQMP *qmp =3D container_of(qret->session, MonitorQMP, sessio= n); + return &qmp->common; + } } --=20 2.22.0.428.g6d5b264208 From nobody Mon Apr 29 15:02:43 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1563218066; cv=none; d=zoho.com; s=zohoarc; b=nb0/d8rJTbJZlCLPtwH1dfXoqQupTFo6/oHmrauIBzZLIsZFEacDYQIXTOD61omE/uGQnOyKg/xNvFAnKZY8Kmz6AbyLvICNGadwTQBrLpaVyub8PS1nFjdHVyCH3MquH0TTiaUDVv2v/A0qNQ9ZMc1gMZf7yVYvlGiClpWRqcI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1563218066; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=/Zwk8FUbsNiWHGXPchO63g/U/EvdMfSQ31bowtINQIA=; b=JqH8JSI9i71P/82DwRqzVphgc1XRO282rL4Gyp7KM7zdBkIIRyKeZeC5izbhCrzrtQr/3Zs2RAUVYnAUkPvssq2bPxZVYjbvvk4J6hX0KV6Mw4Pvs6qs922rTFVJJGOndhIp3S9dGI0HI6TMJwTo6Vg+2q5j+wxTY7zoNPu0l90= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1563218066478419.82794686031525; Mon, 15 Jul 2019 12:14:26 -0700 (PDT) Received: from localhost ([::1]:42124 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6Qb-0002gP-Fh for importer@patchew.org; Mon, 15 Jul 2019 15:14:25 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:40443) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hn6Pz-0008J5-4g for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:13:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hn6Pv-00048M-Ur for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:13:46 -0400 Received: from mx1.redhat.com ([209.132.183.28]:56360) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hn6Pv-00047u-NC for qemu-devel@nongnu.org; Mon, 15 Jul 2019 15:13:43 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 0BB0883F51; Mon, 15 Jul 2019 19:13:42 +0000 (UTC) Received: from localhost (ovpn-112-18.ams2.redhat.com [10.36.112.18]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4A4F24F676; Mon, 15 Jul 2019 19:13:37 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Mon, 15 Jul 2019 23:10:01 +0400 Message-Id: <20190715191001.1188-21-marcandre.lureau@redhat.com> In-Reply-To: <20190715191001.1188-1-marcandre.lureau@redhat.com> References: <20190715191001.1188-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Mon, 15 Jul 2019 19:13:42 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v5 20/20] hmp: call the asynchronous QMP screendump to fix outdated/glitches X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Markus Armbruster , Michael Roth , "Dr. David Alan Gilbert" , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Type: text/plain; charset="utf-8" In order to fix the bad screendumps (same as rhbz#1230527), call into the asynchonous version of the QMP command. Signed-off-by: Marc-Andr=C3=A9 Lureau --- hmp-commands.hx | 3 ++- include/ui/console.h | 5 ++--- monitor/hmp-cmds.c | 6 ++---- ui/console.c | 24 +----------------------- 4 files changed, 7 insertions(+), 31 deletions(-) diff --git a/hmp-commands.hx b/hmp-commands.hx index bfa5681dd2..fa559d6a4e 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -278,7 +278,8 @@ ETEXI .params =3D "filename [device [head]]", .help =3D "save screen from head 'head' of display device 'd= evice' " "into PPM image 'filename'", - .cmd =3D hmp_screendump, + .async_cmd =3D hmp_screendump_async, + .async =3D true, }, =20 STEXI diff --git a/include/ui/console.h b/include/ui/console.h index a1935557cc..d0a2a2066f 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -6,6 +6,7 @@ #include "qemu/notify.h" #include "qemu/error-report.h" #include "qapi/qapi-types-ui.h" +#include "qapi/qmp/dispatch.h" =20 #ifdef CONFIG_OPENGL # include @@ -74,9 +75,7 @@ typedef struct MouseTransformInfo { } MouseTransformInfo; =20 void hmp_mouse_set(Monitor *mon, const QDict *qdict); -void hmp_screendump_sync(const char *filename, - bool has_device, const char *device, - bool has_head, int64_t head, Error **errp); +void hmp_screendump_async(Monitor *mon, const QDict *qdict, QmpReturn *qre= t); =20 /* keysym is a unicode code except for special keys (see QEMU_KEY_xxx constants) */ diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c index 50a25a1ddc..e2af0e6307 100644 --- a/monitor/hmp-cmds.c +++ b/monitor/hmp-cmds.c @@ -2334,15 +2334,13 @@ err_out: goto out; } =20 -void hmp_screendump(Monitor *mon, const QDict *qdict) +void hmp_screendump_async(Monitor *mon, const QDict *qdict, QmpReturn *qre= t) { const char *filename =3D qdict_get_str(qdict, "filename"); const char *id =3D qdict_get_try_str(qdict, "device"); int64_t head =3D qdict_get_try_int(qdict, "head", 0); - Error *err =3D NULL; =20 - hmp_screendump_sync(filename, id !=3D NULL, id, id !=3D NULL, head, &e= rr); - hmp_handle_error(mon, &err); + qmp_screendump(filename, id !=3D NULL, id, id !=3D NULL, head, qret); } =20 void hmp_nbd_server_start(Monitor *mon, const QDict *qdict) diff --git a/ui/console.c b/ui/console.c index 29c850c31c..7436b153b9 100644 --- a/ui/console.c +++ b/ui/console.c @@ -280,7 +280,7 @@ static void qmp_screendump_finish(QemuConsole *con, str= uct qmp_screendump *dump) goto cleanup; } =20 - cur_mon =3D qmp_return_get_monitor(dump->ret); + cur_mon =3D qmp_return_get_monitor(dump->ret, true); surface =3D qemu_console_surface(con); if (!surface) { error_setg(&err, "no surface"); @@ -430,28 +430,6 @@ static QemuConsole *get_console(bool has_device, const= char *device, return con; } =20 -void hmp_screendump_sync(const char *filename, - bool has_device, const char *device, - bool has_head, int64_t head, Error **errp) -{ - DisplaySurface *surface; - QemuConsole *con =3D get_console(has_device, device, has_head, head, e= rrp); - - if (!con) { - return; - } - /* This may not complete the drawing with Spice, you may have - * glitches or outdated dumps, use qmp instead! */ - graphic_hw_update(con); - surface =3D qemu_console_surface(con); - if (!surface) { - error_setg(errp, "no surface"); - return; - } - - ppm_save(filename, surface, errp); -} - void qmp_screendump(const char *filename, bool has_device, const char *device, bool has_head, int64_t head, --=20 2.22.0.428.g6d5b264208