From nobody Sat May 18 22:14:54 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=1554826356; cv=none; d=zoho.com; s=zohoarc; b=JlJ9lgl19ZW+1PrlQZnrL07YRc42NrwrYeK67R4z6w8O7J5xn6QlzlLBG1e2AeYZonaYDM8y480wVil0miGBe3DOzpHoZM+gkF0FlIitnrvsFfWoD/q6+pYStOcE5+HGvdvXAox0mYCvaBtXlk97v9Ir/z8xxW8QkFaazpCjpC8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1554826356; 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=zbGtQdMfCvkx2dA5vOandf1VLRP9bfwdzcWAfN8nIr4=; b=apqRKRewKgbq0Y4uTKE/xnBKY+d2wsrhv2ntNPYo72bWvvDBnU1pMBoMRcW0aFzwI0V4ygr1DB6jP7WsF+tvp3lkiwKkwpsi9kdeJx0dN6IqFS/uPqnx50nmpp4rb+PoWArLEE0+72X6zuHw+c6OVn5f7klsiVIy1WmCMBrbTxg= 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 1554826356916172.34592858613257; Tue, 9 Apr 2019 09:12:36 -0700 (PDT) Received: from localhost ([127.0.0.1]:45645 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtMN-0003Xh-MJ for importer@patchew.org; Tue, 09 Apr 2019 12:12:31 -0400 Received: from eggs.gnu.org ([209.51.188.92]:55365) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtKS-0001wp-9C for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:10:33 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hDtKQ-0004Q1-ON for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:10:32 -0400 Received: from mx1.redhat.com ([209.132.183.28]:50918) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hDtKQ-0004M2-C6 for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:10:30 -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 62160369CA; Tue, 9 Apr 2019 16:10:22 +0000 (UTC) Received: from localhost (ovpn-112-27.ams2.redhat.com [10.36.112.27]) by smtp.corp.redhat.com (Postfix) with ESMTP id 50DCF5D9C9; Tue, 9 Apr 2019 16:10:17 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Tue, 9 Apr 2019 18:09:50 +0200 Message-Id: <20190409161009.6322-2-marcandre.lureau@redhat.com> In-Reply-To: <20190409161009.6322-1-marcandre.lureau@redhat.com> References: <20190409161009.6322-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.30]); Tue, 09 Apr 2019 16:10:22 +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 v4 01/20] qmp: constify QmpCommand and list X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Michael Roth , Markus Armbruster , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , "Dr. David Alan Gilbert" 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.c | 4 ++-- qapi/qmp-dispatch.c | 6 +++--- qapi/qmp-registry.c | 6 +++--- qga/commands.c | 2 +- qga/main.c | 6 +++--- 6 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.c b/monitor.c index 4807bbe811..abc5bdc4ba 100644 --- a/monitor.c +++ b/monitor.c @@ -174,7 +174,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 */ /* @@ -1071,7 +1071,7 @@ static void hmp_info_help(Monitor *mon, const QDict *= qdict) 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/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 c0d77c79c4..5b144b9250 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.21.0.196.g041f5ea1cf From nobody Sat May 18 22:14:54 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=1554826360; cv=none; d=zoho.com; s=zohoarc; b=USi5usTt+gdOTgtm+Oc/zRWs1Ax51XiMG+0LqLU76zuREHrHvupDcZSvj2VXOfHog0dM2t7SRPsKxBdHd4SOXoklB16IPqHo0vnXQ2pGBEaYXxeSqeNmVhmw/lAqFLfSij1NINWJQrzc8qD0Ohb/FYjG+Pic7qBFFfISVq9ra1w= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1554826360; 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=xZnrNWn0C+TETVvZ+zQQXs8JcZx43Zk3xOC7vX8ZARM=; b=mH8SfwtmNkhQDM7lRPlMjZT9Ue5E8Yf5LHdTVRUNOevG/t+SM1rJM4ie+Rimgar1gEH1C+UjdpZyOO6w4sLDI6uaa10phHY3mpHasWw6LPTP04stJbrErHj+d11C3+cPwG8e8MTy5bolUVXoiIJczmKo4KF7VxLCQMCwEmoukZg= 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 1554826360506281.4558483840392; Tue, 9 Apr 2019 09:12:40 -0700 (PDT) Received: from localhost ([127.0.0.1]:45647 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtMN-0003Y2-DV for importer@patchew.org; Tue, 09 Apr 2019 12:12:31 -0400 Received: from eggs.gnu.org ([209.51.188.92]:55404) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtKU-0001wz-3c for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:10:35 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hDtKS-0004Qc-6v for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:10:34 -0400 Received: from mx1.redhat.com ([209.132.183.28]:54690) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hDtKQ-0004Oq-JN for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:10:30 -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 085463008CE5; Tue, 9 Apr 2019 16:10:28 +0000 (UTC) Received: from localhost (ovpn-112-27.ams2.redhat.com [10.36.112.27]) by smtp.corp.redhat.com (Postfix) with ESMTP id BF5329F6F; Tue, 9 Apr 2019 16:10:23 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Tue, 9 Apr 2019 18:09:51 +0200 Message-Id: <20190409161009.6322-3-marcandre.lureau@redhat.com> In-Reply-To: <20190409161009.6322-1-marcandre.lureau@redhat.com> References: <20190409161009.6322-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.48]); Tue, 09 Apr 2019 16:10:28 +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 v4 02/20] json-lexer: make it safe to call destroy multiple times X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Michael Roth , Markus Armbruster , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , "Dr. David Alan Gilbert" 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.21.0.196.g041f5ea1cf From nobody Sat May 18 22:14:54 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=1554826368; cv=none; d=zoho.com; s=zohoarc; b=JRqTt+MnI6JPBq94JgMjnQbG/lsH8Bz+oyOK+ytjrT4jDF5onmCcLSa8+nuQfao/uaRNCS8YEeox2sEzt7loMgtN3OOS+DLrKuQdFunso5ki9gqxw/47j6+y9jo5IO6QnqMDvNobAYtH0EtTiiILZUSZwp65+tisRGZH/7oW2do= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1554826368; 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=8tKhD3VqrukgDt0Ughx0VHzFa5vw7yz9rokmZSyfT8o=; b=Ep9qBDYAbYR0tPbFQB2Co1mgfEeXorMf3BT7kYHZvUBTSjwcAr0BijlRi5QA4InUBgixwfVLLiv0kK3bjXfxJYhepc0mnI3cUkw5P9w4NiJqOhsboGHu9p0xCO1mhEN77vr8/T/Pp76yF4FSSR7R1mbxZ3xM4JzJA80sDXeAG0M= 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 1554826368029397.9344884644962; Tue, 9 Apr 2019 09:12:48 -0700 (PDT) Received: from localhost ([127.0.0.1]:45651 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtMa-0003l2-RG for importer@patchew.org; Tue, 09 Apr 2019 12:12:44 -0400 Received: from eggs.gnu.org ([209.51.188.92]:55468) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtKa-000250-J9 for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:10:42 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hDtKZ-0004V6-1l for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:10:40 -0400 Received: from mx1.redhat.com ([209.132.183.28]:34958) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hDtKY-0004UY-Mg for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:10:38 -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 E9E8130D8DA2; Tue, 9 Apr 2019 16:10:37 +0000 (UTC) Received: from localhost (ovpn-112-27.ams2.redhat.com [10.36.112.27]) by smtp.corp.redhat.com (Postfix) with ESMTP id 74C8C1A917; Tue, 9 Apr 2019 16:10:29 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Tue, 9 Apr 2019 18:09:52 +0200 Message-Id: <20190409161009.6322-4-marcandre.lureau@redhat.com> In-Reply-To: <20190409161009.6322-1-marcandre.lureau@redhat.com> References: <20190409161009.6322-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.43]); Tue, 09 Apr 2019 16:10:37 +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 v4 03/20] qmp: add QmpSession X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Michael Roth , Markus Armbruster , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , "Dr. David Alan Gilbert" 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.c | 18 ++++++++++-------- qapi/qmp-dispatch.c | 15 ++++++++++++--- qga/main.c | 5 ++++- tests/test-qmp-cmds.c | 28 ++++++++++++++++++++++------ 5 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.c b/monitor.c index abc5bdc4ba..a07175b4f8 100644 --- a/monitor.c +++ b/monitor.c @@ -174,7 +174,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 */ /* @@ -520,7 +520,7 @@ static void monitor_qapi_event_emit(QAPIEvent event, QD= ict *qdict) trace_monitor_protocol_event_emit(event, qdict); QTAILQ_FOREACH(mon, &mon_list, entry) { if (monitor_is_qmp(mon) - && mon->qmp.commands !=3D &qmp_cap_negotiation_commands) { + && mon->qmp.session.cmds !=3D &qmp_cap_negotiation_commands) { qmp_send_response(mon, qdict); } } @@ -729,6 +729,7 @@ static void monitor_data_destroy(Monitor *mon) g_free(mon->mon_cpu_path); qemu_chr_fe_deinit(&mon->chr, false); if (monitor_is_qmp(mon)) { + qmp_session_destroy(&mon->qmp.session); json_message_parser_destroy(&mon->qmp.parser); } readline_free(mon->rs); @@ -1090,7 +1091,7 @@ CommandInfoList *qmp_query_commands(Error **errp) { CommandInfoList *list =3D NULL; =20 - qmp_for_each_command(cur_mon->qmp.commands, query_commands_cb, &list); + qmp_for_each_command(cur_mon->qmp.session.cmds, query_commands_cb, &li= st); =20 return list; } @@ -1207,7 +1208,7 @@ static bool qmp_caps_accept(Monitor *mon, QMPCapabili= tyList *list, void qmp_qmp_capabilities(bool has_enable, QMPCapabilityList *enable, Error **errp) { - if (cur_mon->qmp.commands =3D=3D &qmp_commands) { + if (cur_mon->qmp.session.cmds =3D=3D &qmp_commands) { error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND, "Capabilities negotiation is already complete, command " "ignored"); @@ -1218,7 +1219,7 @@ void qmp_qmp_capabilities(bool has_enable, QMPCapabil= ityList *enable, return; } =20 - cur_mon->qmp.commands =3D &qmp_commands; + cur_mon->qmp.session.cmds =3D &qmp_commands; } =20 /* Set the current CPU defined by the user. Callers must hold BQL. */ @@ -4121,11 +4122,11 @@ static void monitor_qmp_dispatch(Monitor *mon, QObj= ect *req) old_mon =3D cur_mon; cur_mon =3D mon; =20 - rsp =3D qmp_dispatch(mon->qmp.commands, req, qmp_oob_enabled(mon)); + rsp =3D qmp_dispatch(&mon->qmp.session, req, qmp_oob_enabled(mon)); =20 cur_mon =3D old_mon; =20 - if (mon->qmp.commands =3D=3D &qmp_cap_negotiation_commands) { + if (mon->qmp.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"), @@ -4399,7 +4400,7 @@ static void monitor_qmp_event(void *opaque, int event) =20 switch (event) { case CHR_EVENT_OPENED: - mon->qmp.commands =3D &qmp_cap_negotiation_commands; + qmp_session_init(&mon->qmp.session, &qmp_cap_negotiation_commands); monitor_qmp_caps_reset(mon); data =3D qmp_greeting(mon); qmp_send_response(mon, data); @@ -4414,6 +4415,7 @@ static void monitor_qmp_event(void *opaque, int event) * is closed. */ monitor_qmp_cleanup_queues(mon); + qmp_session_destroy(&mon->qmp.session); json_message_parser_destroy(&mon->qmp.parser); json_message_parser_init(&mon->qmp.parser, handle_qmp_command, mon, NULL); 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 5b144b9250..bf0082df90 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 630b1b9bac..7c39ec1657 100644 --- a/tests/test-qmp-cmds.c +++ b/tests/test-qmp-cmds.c @@ -113,44 +113,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 @@ -164,36 +172,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.21.0.196.g041f5ea1cf From nobody Sat May 18 22:14:54 2024 Delivered-To: importer@patchew.org Received-SPF: temperror (zoho.com: Error in retrieving data from DNS) 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=temperror (zoho.com: Error in retrieving data from DNS) 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=1554826544; cv=none; d=zoho.com; s=zohoarc; b=OmL4GWpFwX8a+wHeNrpRV+jaIWB7/3sFEItILVUPYdOxuq6Jbu7BKXFa1tlLjlNAK+JwtJxdKnnWsn1eVFbnEyq8qoxf+bqC02spIQQNOgX3MU0pNHaI8RcmEamba3x9XPZ+lgcUzOfORoAyykPkM+kLnWb1Qyq234tl8VHP6+M= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1554826544; 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=J62C76gcQnPJhQpoQMjiiqUJHjGxJHW0aDz1DxBE5MA=; b=QJxmKP5Ac1SNGzM82tftOJ4qzJG7c2Exan2Sy6sr10tVGJP67mXxBIcFbExHcu0vN6jJMxEmVzCZL2iGoAnRA3iZmTjJWWXMTB+61STXwgJImtzIuwXV1tmWjgLz2NZFvc4yjHCgd+2OlKuEjegCboKXdh12fLnNXXOxjvA+4o8= ARC-Authentication-Results: i=1; mx.zoho.com; spf=temperror (zoho.com: Error in retrieving data from DNS) 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 (209.51.188.17 [209.51.188.17]) by mx.zohomail.com with SMTPS id 1554826544942760.1616747287443; Tue, 9 Apr 2019 09:15:44 -0700 (PDT) Received: from localhost ([127.0.0.1]:45674 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtPA-0005zI-DJ for importer@patchew.org; Tue, 09 Apr 2019 12:15:24 -0400 Received: from eggs.gnu.org ([209.51.188.92]:55495) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtKd-00028t-Hh for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:10:45 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hDtKb-0004X6-QX for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:10:43 -0400 Received: from mx1.redhat.com ([209.132.183.28]:47283) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hDtKb-0004WI-Dz for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:10:41 -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 A6A04C04F4DF; Tue, 9 Apr 2019 16:10:40 +0000 (UTC) Received: from localhost (ovpn-112-27.ams2.redhat.com [10.36.112.27]) by smtp.corp.redhat.com (Postfix) with ESMTP id D8E9F6198C; Tue, 9 Apr 2019 16:10:39 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Tue, 9 Apr 2019 18:09:53 +0200 Message-Id: <20190409161009.6322-5-marcandre.lureau@redhat.com> In-Reply-To: <20190409161009.6322-1-marcandre.lureau@redhat.com> References: <20190409161009.6322-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.31]); Tue, 09 Apr 2019 16:10:40 +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 v4 04/20] QmpSession: add a return callback X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Michael Roth , Markus Armbruster , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , "Dr. David Alan Gilbert" 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.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.c b/monitor.c index a07175b4f8..c23ba76f78 100644 --- a/monitor.c +++ b/monitor.c @@ -4101,45 +4101,35 @@ static int monitor_can_read(void *opaque) return !atomic_mb_read(&mon->suspend_cnt); } =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(Monitor *mon, QDict *rsp) +static void dispatch_return_cb(QmpSession *session, QDict *rsp) { - if (rsp) { - qmp_send_response(mon, rsp); + Monitor *mon =3D container_of(session, Monitor, qmp.session); + + if (mon->qmp.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(Monitor *mon, QObject *req) { Monitor *old_mon; - QDict *rsp; - QDict *error; =20 old_mon =3D cur_mon; cur_mon =3D mon; =20 - rsp =3D qmp_dispatch(&mon->qmp.session, req, qmp_oob_enabled(mon)); + qmp_dispatch(&mon->qmp.session, req, qmp_oob_enabled(mon)); =20 cur_mon =3D old_mon; - - if (mon->qmp.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 /* @@ -4210,7 +4200,7 @@ static 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 @@ -4400,7 +4390,8 @@ static void monitor_qmp_event(void *opaque, int event) =20 switch (event) { case CHR_EVENT_OPENED: - qmp_session_init(&mon->qmp.session, &qmp_cap_negotiation_commands); + qmp_session_init(&mon->qmp.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 bf0082df90..2a929936db 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 7c39ec1657..3f41cc45bb 100644 --- a/tests/test-qmp-cmds.c +++ b/tests/test-qmp-cmds.c @@ -109,22 +109,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); } @@ -133,82 +134,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.21.0.196.g041f5ea1cf From nobody Sat May 18 22:14:54 2024 Delivered-To: importer@patchew.org Received-SPF: temperror (zoho.com: Error in retrieving data from DNS) 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=temperror (zoho.com: Error in retrieving data from DNS) 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=1554826544; cv=none; d=zoho.com; s=zohoarc; b=KkjdVcFXkCVeu7yN5yklZ0+925WoxzgFDuJ5McI3/IM7tldcO8WaSZeBGYDkQ7nmCbhCirVrGWMBNo1kVRttVSPKvBYfYrHjGo5PAPwlXk4uAxmc7Tv2keYFtQW4O80I90EaWmGBq+g9kqAnWfZuzsbAWHRYWJPKlYiWmAyQnVw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1554826544; 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=PKkRXE2Aes6ZRuqqMqGZk8dvmg9e/vQiiFuccSbgg5Q=; b=Dnzfx2bf1ffkq41bBRxPWa7SPgZkIgr7wXSJ0Ov1DYUGjrAxGZA71O8ZDMZqmKzdB4Osx/uoNKEgEkv7ytV09qneJHfnxOg5ydxaxcIUT8rzXW0HWcu2DCBTjLd76z0qK6x5Rp4sTIkAPprUk8kvnVssPPViwiTRDubte58giHs= ARC-Authentication-Results: i=1; mx.zoho.com; spf=temperror (zoho.com: Error in retrieving data from DNS) 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 (209.51.188.17 [209.51.188.17]) by mx.zohomail.com with SMTPS id 1554826544761867.2632942521694; Tue, 9 Apr 2019 09:15:44 -0700 (PDT) Received: from localhost ([127.0.0.1]:45672 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtP9-0005z3-3k for importer@patchew.org; Tue, 09 Apr 2019 12:15:23 -0400 Received: from eggs.gnu.org ([209.51.188.92]:55533) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtKj-0002J7-Jg for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:10:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hDtKi-0004b2-EZ for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:10:49 -0400 Received: from mx1.redhat.com ([209.132.183.28]:42982) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hDtKi-0004aO-2G for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:10:48 -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 511C9308FF0E; Tue, 9 Apr 2019 16:10:47 +0000 (UTC) Received: from localhost (ovpn-112-27.ams2.redhat.com [10.36.112.27]) by smtp.corp.redhat.com (Postfix) with ESMTP id AF6C45D9C9; Tue, 9 Apr 2019 16:10:42 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Tue, 9 Apr 2019 18:09:54 +0200 Message-Id: <20190409161009.6322-6-marcandre.lureau@redhat.com> In-Reply-To: <20190409161009.6322-1-marcandre.lureau@redhat.com> References: <20190409161009.6322-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.49]); Tue, 09 Apr 2019 16: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 v4 05/20] QmpSession: add json parser and use it in qga X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Michael Roth , Markus Armbruster , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , "Dr. David Alan Gilbert" 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 2a929936db..9cd27fc4b8 100644 --- a/qga/main.c +++ b/qga/main.c @@ -18,7 +18,6 @@ #include #include #endif -#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.21.0.196.g041f5ea1cf From nobody Sat May 18 22:14:54 2024 Delivered-To: importer@patchew.org Received-SPF: temperror (zoho.com: Error in retrieving data from DNS) 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=temperror (zoho.com: Error in retrieving data from DNS) 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=1554826544; cv=none; d=zoho.com; s=zohoarc; b=HoKgZLWnd9pqHa5juHcpsrI4CaqsG93yZwB0UWwReRCx2d7sCHJA7hcXIqvqeinr48/C5S2OayfzRZFZSKpcqikys+Rk2WWE5NNQnNOrvvujFdSMGRU39GbelKycXco7vltv9NfWRKhsytive+6EcyDLM4AmQcuz6C8EjVGRBXw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1554826544; 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=yLB+I3GhFpvUtu0HxEeHu1zd5mcXE88mg0cJtO8+614=; b=NzV3UUICmWkQGfbkODhqWBv52EUBdr08gDwdIWPVOv5l7UDF8PbKwXcg1Ac0Zqcv1l1Rv5kZj96XgzPS8/87iBITPfYdb+AsKZ9S/wWzHyQG22cbIf+NkUFFuQ3YFN63pAtfQDP/OPmTn6PeuBBwRb4rJO5TH9YmYvawYhXQYBY= ARC-Authentication-Results: i=1; mx.zoho.com; spf=temperror (zoho.com: Error in retrieving data from DNS) 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 (209.51.188.17 [209.51.188.17]) by mx.zohomail.com with SMTPS id 1554826544937717.0166348570243; Tue, 9 Apr 2019 09:15:44 -0700 (PDT) Received: from localhost ([127.0.0.1]:45670 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtPA-0005ye-8T for importer@patchew.org; Tue, 09 Apr 2019 12:15:24 -0400 Received: from eggs.gnu.org ([209.51.188.92]:55567) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtKq-0002Qc-Ea for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:10:57 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hDtKo-0004eX-VL for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:10:56 -0400 Received: from mx1.redhat.com ([209.132.183.28]:56344) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hDtKo-0004e9-Jx for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:10:54 -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 D0C9BC02492F; Tue, 9 Apr 2019 16:10:53 +0000 (UTC) Received: from localhost (ovpn-112-27.ams2.redhat.com [10.36.112.27]) by smtp.corp.redhat.com (Postfix) with ESMTP id AE43D17F23; Tue, 9 Apr 2019 16:10:48 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Tue, 9 Apr 2019 18:09:55 +0200 Message-Id: <20190409161009.6322-7-marcandre.lureau@redhat.com> In-Reply-To: <20190409161009.6322-1-marcandre.lureau@redhat.com> References: <20190409161009.6322-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.32]); Tue, 09 Apr 2019 16:10: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 v4 06/20] monitor: use qmp session to parse json feed X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Michael Roth , Markus Armbruster , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , "Dr. David Alan Gilbert" 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.c | 16 +++++----------- qapi/qmp-dispatch.c | 4 +++- qga/main.c | 2 +- qobject/json-streamer.c | 3 +-- tests/test-qmp-cmds.c | 11 ++++++----- 7 files changed, 21 insertions(+), 23 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.c b/monitor.c index c23ba76f78..71aad8d1ae 100644 --- a/monitor.c +++ b/monitor.c @@ -59,7 +59,6 @@ #include "qapi/qmp/qnum.h" #include "qapi/qmp/qstring.h" #include "qapi/qmp/qjson.h" -#include "qapi/qmp/json-parser.h" #include "qapi/qmp/qlist.h" #include "qom/object_interfaces.h" #include "trace-root.h" @@ -167,7 +166,6 @@ struct MonFdset { }; =20 typedef struct { - JSONMessageParser parser; /* * When a client connects, we're in capabilities negotiation mode. * @commands is &qmp_cap_negotiation_commands then. When command @@ -730,7 +728,6 @@ static void monitor_data_destroy(Monitor *mon) qemu_chr_fe_deinit(&mon->chr, false); if (monitor_is_qmp(mon)) { qmp_session_destroy(&mon->qmp.session); - json_message_parser_destroy(&mon->qmp.parser); } readline_free(mon->rs); qobject_unref(mon->outbuf); @@ -4216,7 +4213,7 @@ static void monitor_qmp_bh_dispatcher(void *data) =20 static void handle_qmp_command(void *opaque, QObject *req, Error *err) { - Monitor *mon =3D opaque; + Monitor *mon =3D container_of(opaque, Monitor, qmp); QObject *id =3D NULL; QDict *qdict; QMPRequest *req_obj; @@ -4278,7 +4275,7 @@ static void monitor_qmp_read(void *opaque, const uint= 8_t *buf, int size) { Monitor *mon =3D opaque; =20 - json_message_parser_feed(&mon->qmp.parser, (const char *) buf, size); + qmp_session_feed(&mon->qmp.session, (const char *) buf, size); } =20 static void monitor_read(void *opaque, const uint8_t *buf, int size) @@ -4391,7 +4388,9 @@ static void monitor_qmp_event(void *opaque, int event) switch (event) { case CHR_EVENT_OPENED: qmp_session_init(&mon->qmp.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); @@ -4407,9 +4406,6 @@ static void monitor_qmp_event(void *opaque, int event) */ monitor_qmp_cleanup_queues(mon); qmp_session_destroy(&mon->qmp.session); - json_message_parser_destroy(&mon->qmp.parser); - json_message_parser_init(&mon->qmp.parser, handle_qmp_command, - mon, NULL); mon_refcount--; monitor_fdsets_cleanup(); break; @@ -4615,8 +4611,6 @@ void monitor_init(Chardev *chr, int flags) =20 if (monitor_is_qmp(mon)) { qemu_chr_fe_set_echo(&mon->chr, true); - json_message_parser_init(&mon->qmp.parser, handle_qmp_command, - mon, NULL); if (mon->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 9cd27fc4b8..14e418f9a5 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 3f41cc45bb..b4d0b0440a 100644 --- a/tests/test-qmp-cmds.c +++ b/tests/test-qmp-cmds.c @@ -121,7 +121,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); @@ -135,7 +135,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); @@ -157,7 +157,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); @@ -183,7 +184,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); @@ -204,7 +205,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.21.0.196.g041f5ea1cf From nobody Sat May 18 22:14:54 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=1554826712; cv=none; d=zoho.com; s=zohoarc; b=YJRlUoDmzcsACdhxNyh02r2G1qom6JP9H/I3i2T8aFo9V1JgAPHxvV7DSnYQenJDVXmtvQ1CjpH0lD9S/yFV+FPdg3YTDPmtJ7vS38mYcjkrB3iLpJ2OdVq3b734FZTC1DjafXX9+naExLXetuYj92PqtkWJFpNIkCCJ33yx26M= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1554826712; 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=PYaarz20y5T6a+CtnFFiJBLnr64zepgskspaksIVgXY=; b=eubttrp1kQTzT47l/Z1IWIDb44qA5hqTalOcP6LsGhc3n9X6RdAwMAjsuxZIJ07kVoOWbAVTHXS2jWGOWbVgMzkHe2EjtmqjKyGON8z+6ovV08YaLSZ1jVrY4ph2z/+Fhj2BTq+gj8K0BQ9OmSjyP9gerxQgKiSMQ1CZKK8ZSIA= 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 1554826712481532.5709377288697; Tue, 9 Apr 2019 09:18:32 -0700 (PDT) Received: from localhost ([127.0.0.1]:45727 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtS9-0008Qq-AK for importer@patchew.org; Tue, 09 Apr 2019 12:18:29 -0400 Received: from eggs.gnu.org ([209.51.188.92]:55587) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtKy-0002ZF-3V for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:05 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hDtKv-0004hG-T2 for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:03 -0400 Received: from mx1.redhat.com ([209.132.183.28]:45508) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hDtKv-0004gh-Jc for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:01 -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 85A98D4E72; Tue, 9 Apr 2019 16:11:00 +0000 (UTC) Received: from localhost (ovpn-112-27.ams2.redhat.com [10.36.112.27]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7F3F99F6E; Tue, 9 Apr 2019 16:10:55 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Tue, 9 Apr 2019 18:09:56 +0200 Message-Id: <20190409161009.6322-8-marcandre.lureau@redhat.com> In-Reply-To: <20190409161009.6322-1-marcandre.lureau@redhat.com> References: <20190409161009.6322-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.38]); Tue, 09 Apr 2019 16:11:00 +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 v4 07/20] qga: simplify dispatch_return_cb X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Michael Roth , Markus Armbruster , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , "Dr. David Alan Gilbert" 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 14e418f9a5..51ab418128 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.21.0.196.g041f5ea1cf From nobody Sat May 18 22:14:54 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=1554826713; cv=none; d=zoho.com; s=zohoarc; b=KvxDhnHrq2VhKRU2jmdx+Kc7NGUUqUuo1G+u8Q7xTvqORPjI5KbQ0iClpuR3DCqyOr5Y2YwexVON3g8+FlqwsqroWc+5tbi+QigjSovGJ4gRWWM6A2P8X9bOsqhq++lugaj2a+Fy1yOW2AEJuAq05frLrsK7vC9EvZnvzs571/k= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1554826713; 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=4hhI+A9iNFr8zhebQJLBavXLIbYaT8580QQGSoDEx5Y=; b=D+h/WEvWBZWGarGZ2HHwbXanNO2NdXCFsZzQ63VxwTN2631bH6kkqaHe975wuJ9Ezxdw9Pmxhe5F9z6Pr75VwEA3jm8SEuaaHx0JMrc/wlNtWuOIZ+kEsGEhxFreX2d+BEMXF59LHJOokl/UjflRUen80v7Xp1ykzxRz3RSrU68= 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 155482671393885.80171845195889; Tue, 9 Apr 2019 09:18:33 -0700 (PDT) Received: from localhost ([127.0.0.1]:45729 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtS9-0008RC-R2 for importer@patchew.org; Tue, 09 Apr 2019 12:18:29 -0400 Received: from eggs.gnu.org ([209.51.188.92]:55619) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtLE-0002nN-KS for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:21 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hDtLD-0004pJ-At for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:20 -0400 Received: from mx1.redhat.com ([209.132.183.28]:42248) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hDtL5-0004jB-5w for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:14 -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 8BEAC7D0E0; Tue, 9 Apr 2019 16:11:06 +0000 (UTC) Received: from localhost (ovpn-112-27.ams2.redhat.com [10.36.112.27]) by smtp.corp.redhat.com (Postfix) with ESMTP id D5DA35DA2A; Tue, 9 Apr 2019 16:11:01 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Tue, 9 Apr 2019 18:09:57 +0200 Message-Id: <20190409161009.6322-9-marcandre.lureau@redhat.com> In-Reply-To: <20190409161009.6322-1-marcandre.lureau@redhat.com> References: <20190409161009.6322-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]); Tue, 09 Apr 2019 16:11:06 +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 v4 08/20] QmpSession: introduce QmpReturn X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Michael Roth , Markus Armbruster , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , "Dr. David Alan Gilbert" 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.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.c b/monitor.c index 71aad8d1ae..b1c4647a37 100644 --- a/monitor.c +++ b/monitor.c @@ -4175,7 +4175,6 @@ static QMPRequest *monitor_qmp_requests_pop_any_with_= lock(void) static void monitor_qmp_bh_dispatcher(void *data) { QMPRequest *req_obj =3D monitor_qmp_requests_pop_any_with_lock(); - QDict *rsp; bool need_resume; Monitor *mon; =20 @@ -4194,11 +4193,10 @@ static 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->qmp.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.21.0.196.g041f5ea1cf From nobody Sat May 18 22:14:54 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=1554826543; cv=none; d=zoho.com; s=zohoarc; b=MpGQ5EDN9SByLOf+Xudlu+mS/CmNgiakn6YnB6tIhWqO7O605qALK5sUCe1SVx4m04DUiXk/Mye3fqxeZzI3Kzos6zEXyMILj/Ewnpyqn5ZwL9K+TzzT7dhQzU7yJDE4bbIylZNSbj0y5r9SFiPQO/BzAhUZx3ZlnxTLX5rmZUw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1554826543; 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=WDowAQK/7pJPaCr0TUKMoxQz31Cm8hgV4mSUyMe4NfI=; b=a4a5yItHKXPUl2Otw5ASVvHTUkx7RXM3fPn1f2qtH7oyTF3kKbKmnkrNJz4V01bmIdCSKoyc+7hjpMCJueDfqTgO0Nk0nct564YtsTONqAc0zFpLTxCGVZRuh/MApm1YKfvZR3G6sVD0E0ncI+qlNkwqIdILMmlLmMXcQiiF+hU= 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 (209.51.188.17 [209.51.188.17]) by mx.zohomail.com with SMTPS id 1554826543186497.15791867398013; Tue, 9 Apr 2019 09:15:43 -0700 (PDT) Received: from localhost ([127.0.0.1]:45684 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtPL-0006AT-2p for importer@patchew.org; Tue, 09 Apr 2019 12:15:35 -0400 Received: from eggs.gnu.org ([209.51.188.92]:55635) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtLG-0002oa-1L for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:22 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hDtLE-0004qE-MV for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:22 -0400 Received: from mx1.redhat.com ([209.132.183.28]:33822) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hDtLE-0004na-Dl for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:20 -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 167B7C050012; Tue, 9 Apr 2019 16:11:15 +0000 (UTC) Received: from localhost (ovpn-112-27.ams2.redhat.com [10.36.112.27]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4DD7A17AB5; Tue, 9 Apr 2019 16:11:08 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Tue, 9 Apr 2019 18:09:58 +0200 Message-Id: <20190409161009.6322-10-marcandre.lureau@redhat.com> In-Reply-To: <20190409161009.6322-1-marcandre.lureau@redhat.com> References: <20190409161009.6322-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.31]); Tue, 09 Apr 2019 16:11:15 +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 v4 09/20] qmp: simplify qmp_return_error() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Michael Roth , Markus Armbruster , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , "Dr. David Alan Gilbert" 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.21.0.196.g041f5ea1cf From nobody Sat May 18 22:14:54 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=1554826725; cv=none; d=zoho.com; s=zohoarc; b=nIGGuZgfrp4bMxRaIcSR6wAXy9y7NN7nCJ5SiJDrRbx/Oo71msJCDxlpJby8gNxtdSu0MtwMxoYeJ2XAysADzzISPPzm5kmV4ynSaDnzE8zIFmdc12On1dwGlOdQkAO4M6DyP5xwL0VVSAwg4nh6cV42yo47zN3UhexxjFm35bI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1554826725; 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=gW4664kRhj/Tuyczv6zJ1uRxcFrmXC7XSYFo0xNv8H8=; b=OwCaxsCfgRVVWbaWAFL569a5DEM4OzL9XwuZDfUBvsCB41lnqOIwrMjvdObFpoT92hRv29tyG68IwSMFrJWJqL8HBjtUVs+kFSPHuRHWDp6uLnfLSp6GER0lMMWa2u/b/ELUxpGsKqblzB/V3tdqiCr5BLGkbXih8YUj9sW5Ips= 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 1554826725903733.1312713029448; Tue, 9 Apr 2019 09:18:45 -0700 (PDT) Received: from localhost ([127.0.0.1]:45733 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtSM-0000Bl-PW for importer@patchew.org; Tue, 09 Apr 2019 12:18:42 -0400 Received: from eggs.gnu.org ([209.51.188.92]:55781) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtLf-0003Gm-UT for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:49 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hDtLe-00058l-Kr for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:47 -0400 Received: from mx1.redhat.com ([209.132.183.28]:34412) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hDtLe-00057d-9G for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:46 -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 81B68307B4BA; Tue, 9 Apr 2019 16:11:21 +0000 (UTC) Received: from localhost (ovpn-112-27.ams2.redhat.com [10.36.112.27]) by smtp.corp.redhat.com (Postfix) with ESMTP id C7E445D719; Tue, 9 Apr 2019 16:11:16 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Tue, 9 Apr 2019 18:09:59 +0200 Message-Id: <20190409161009.6322-11-marcandre.lureau@redhat.com> In-Reply-To: <20190409161009.6322-1-marcandre.lureau@redhat.com> References: <20190409161009.6322-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.46]); Tue, 09 Apr 2019 16: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 v4 10/20] QmpSession: keep a queue of pending commands X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Michael Roth , Markus Armbruster , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , "Dr. David Alan Gilbert" 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.21.0.196.g041f5ea1cf From nobody Sat May 18 22:14:54 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=1554826907; cv=none; d=zoho.com; s=zohoarc; b=SEdytwppgcH/W5IvV66HgGAUS0nC4x34Y44C0Kw0+5aGTLQfqP+ouQqkYujxdKayoxVe4kXneJ680l+778gpn91nhr0ebQsxfWx+I1hJFTUg4RrmfADoGVVd0s8HszTc04Fw0Ete5aPtr5WzdFPhfwXzLC8n3E9/oXB45A1p5ak= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1554826907; 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=uLGGK2v2MYbvKTMEY4yF0oLHnWajtTAn2VcG9vpD3h0=; b=ls2vCXJbB9gOQwHHzMa6hTXjLwSmeinjo9FtTomu6gHO5g7Ixaz3UTzWAjE5BKq7jlxgpCx90B59Aclfco2XWcP8zU5wGeBM+GfXjaCeWGaIbFaLhpa3ve0J2BhaXoYimFslJ1+sQNgjQ7FGCdj1mVkSNG3NfrGxFK5bQCUwFPY= 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 (209.51.188.17 [209.51.188.17]) by mx.zohomail.com with SMTPS id 1554826907225783.3820280124146; Tue, 9 Apr 2019 09:21:47 -0700 (PDT) Received: from localhost ([127.0.0.1]:45785 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtV6-0002c3-Au for importer@patchew.org; Tue, 09 Apr 2019 12:21:32 -0400 Received: from eggs.gnu.org ([209.51.188.92]:55692) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtLR-00032e-RO for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:35 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hDtLN-0004xe-Oi for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:31 -0400 Received: from mx1.redhat.com ([209.132.183.28]:33046) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hDtLN-0004wB-3c for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:29 -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 BE259859FF; Tue, 9 Apr 2019 16:11:27 +0000 (UTC) Received: from localhost (ovpn-112-27.ams2.redhat.com [10.36.112.27]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4AAB93844; Tue, 9 Apr 2019 16:11:23 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Tue, 9 Apr 2019 18:10:00 +0200 Message-Id: <20190409161009.6322-12-marcandre.lureau@redhat.com> In-Reply-To: <20190409161009.6322-1-marcandre.lureau@redhat.com> References: <20190409161009.6322-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.26]); Tue, 09 Apr 2019 16:11:27 +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 v4 11/20] QmpSession: return orderly X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Michael Roth , Markus Armbruster , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , "Dr. David Alan Gilbert" 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 b4d0b0440a..c4593552e3 100644 --- a/tests/test-qmp-cmds.c +++ b/tests/test-qmp-cmds.c @@ -327,6 +327,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) { @@ -340,6 +372,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.21.0.196.g041f5ea1cf From nobody Sat May 18 22:14:54 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=1554826713; cv=none; d=zoho.com; s=zohoarc; b=eRI82uiyeJv31SN+7bWuhwp8geVRHc7QR844sRZxzZyHvZXvrRQzkE8igVGikHs2LFXYq8XPUM2d0QNIiwKQgv8kqCk/+tw0iUKSjDzJsSZir2Hj82sx2+uUphZ1xD61OTvqtfOhMq9ABI0DC3Vvu7zTN49XL31IkBWgA7MrXRM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1554826713; 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=RgTo9iEa9AZn6LhmKeP4zNgjYX+37RvP8R0LkybfNAM=; b=hX9szLp8Ifj6PDJyUURMsOAKydalCpEazyekDvRo7diGBdcTus47BHjEGDQIgr40Sb53TVx84AgZ1H5/2xG+h/5jpl6PmP6v3qJrz7Vrsrf2lr90H6aNGKJCFvJCIZr5gR4qYcqbwNJJjUKRKzf7LO4fYd+IzOvA5R9dhckwvxI= 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 1554826713351787.9822488806677; Tue, 9 Apr 2019 09:18:33 -0700 (PDT) Received: from localhost ([127.0.0.1]:45731 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtS9-0008RM-79 for importer@patchew.org; Tue, 09 Apr 2019 12:18:29 -0400 Received: from eggs.gnu.org ([209.51.188.92]:55711) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtLT-00034p-Et for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hDtLS-00050w-5L for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:35 -0400 Received: from mx1.redhat.com ([209.132.183.28]:33088) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hDtLR-0004xm-Ph for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:34 -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 A40AE88ACB; Tue, 9 Apr 2019 16:11:29 +0000 (UTC) Received: from localhost (ovpn-112-27.ams2.redhat.com [10.36.112.27]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1F39261998; Tue, 9 Apr 2019 16:11:28 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Tue, 9 Apr 2019 18:10:01 +0200 Message-Id: <20190409161009.6322-13-marcandre.lureau@redhat.com> In-Reply-To: <20190409161009.6322-1-marcandre.lureau@redhat.com> References: <20190409161009.6322-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.26]); Tue, 09 Apr 2019 16:11:29 +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 v4 12/20] qmp: introduce asynchronous command type X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Michael Roth , Markus Armbruster , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , "Dr. David Alan Gilbert" 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.21.0.196.g041f5ea1cf From nobody Sat May 18 22:14:54 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=1554826907; cv=none; d=zoho.com; s=zohoarc; b=fik68shblbUhnwjteLut6Jj1A3Wuhr1y9SbgorgtPEr0Sj4uB6ymQnz0fw2Fncl4rvN0czKKJGC+JbMVmw/pOZYT9jd1G1ueI5upv1JJMhk5COVDXx/pZPXfia/Jx49pYuWQereVWRlSQXncpHWDTi3ylvpe4v9MsDg9NGrlMQk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1554826907; 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=b+19sYsHXnU61LGZMWXaD+UH0YIKSeMEVugKzi8+PfQ=; b=lqNTB9OYE+yQVgg45UPuP+lVIJ2VTZNAIR+nUMuDGDtS9cIuku/RuOYrUQBPCW7beieRdyu88LY2JaOrpzcD9EF79Yh2enwnh05/bnNwLLneTHhZ1/OTEfWr9FQCmACMgMC6gGL9EzoDB/s++Kjj+NZ3tqL0bmHQk5WTlUfmbro= 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 (209.51.188.17 [209.51.188.17]) by mx.zohomail.com with SMTPS id 1554826907380569.0878323988761; Tue, 9 Apr 2019 09:21:47 -0700 (PDT) Received: from localhost ([127.0.0.1]:45787 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtV9-0002ee-TP for importer@patchew.org; Tue, 09 Apr 2019 12:21:35 -0400 Received: from eggs.gnu.org ([209.51.188.92]:55721) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtLV-000371-M3 for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:39 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hDtLS-000512-9Q for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:37 -0400 Received: from mx1.redhat.com ([209.132.183.28]:34022) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hDtLR-0004zW-SJ for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:34 -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 34851C130709; Tue, 9 Apr 2019 16:11:32 +0000 (UTC) Received: from localhost (ovpn-112-27.ams2.redhat.com [10.36.112.27]) by smtp.corp.redhat.com (Postfix) with ESMTP id 728C45D722; Tue, 9 Apr 2019 16:11:31 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Tue, 9 Apr 2019 18:10:02 +0200 Message-Id: <20190409161009.6322-14-marcandre.lureau@redhat.com> In-Reply-To: <20190409161009.6322-1-marcandre.lureau@redhat.com> References: <20190409161009.6322-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.31]); Tue, 09 Apr 2019 16: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 v4 13/20] scripts: learn 'async' qapi commands X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Michael Roth , Markus Armbruster , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , "Dr. David Alan Gilbert" 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/test-qmp-cmds.c | 60 ++++++++++ tests/qapi-schema/qapi-schema-test.json | 5 + tests/qapi-schema/qapi-schema-test.out | 8 ++ tests/qapi-schema/test-qapi.py | 8 +- 8 files changed, 218 insertions(+), 35 deletions(-) diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py index 6d66bf6aa3..74a7ec112c 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= ync): + if async: + extra =3D "QmpReturn *qret" + else: + extra =3D 'Error **errp' + + if async: + 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, async): + if async: + 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, async): return mcgen(''' %(proto)s; ''', - proto=3Dbuild_marshal_proto(name)) + proto=3Dbuild_marshal_proto(name, async)) =20 =20 -def gen_marshal(name, arg_type, boxed, ret_type): +def gen_marshal(name, arg_type, boxed, ret_type, async): 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, async)) =20 - if ret_type: + if ret_type and not async: 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 async: + 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 async: + 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, + async): 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 async: + options +=3D ['QCO_ASYNC'] =20 if not options: options =3D ['QCO_NO_OPTIONS'] =20 options =3D " | ".join(options) =20 + if async: + 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 @@ -278,7 +374,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, + async): if not gen: return # FIXME: If T is a user-defined type, the user is responsible @@ -292,11 +389,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, async)) + self._genh.add(gen_marshal_decl(name, async)) + self._genc.add(gen_marshal(name, arg_type, boxed, ret_type, as= ync)) + if async 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, + async)) =20 =20 def gen_commands(schema, output_dir, prefix): diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index f07869ec73..1bca5fc150 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -993,7 +993,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' @@ -1136,7 +1136,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, + async): pass =20 def visit_event(self, name, info, ifcond, arg_type, boxed): @@ -1533,7 +1534,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, + async): 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) @@ -1546,6 +1548,7 @@ class QAPISchemaCommand(QAPISchemaEntity): self.boxed =3D boxed self.allow_oob =3D allow_oob self.allow_preconfig =3D allow_preconfig + self.async =3D async =20 def check(self, schema): QAPISchemaEntity.check(self, schema) @@ -1572,7 +1575,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.async) =20 =20 class QAPISchemaEvent(QAPISchemaEntity): @@ -1820,6 +1823,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') + async =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)) @@ -1828,7 +1832,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, + async)) =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 5c8c136899..0f51a7bff3 100755 --- a/scripts/qapi/doc.py +++ b/scripts/qapi/doc.py @@ -236,7 +236,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, + async): 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 f7f2ca07e4..7f3ea88c72 100644 --- a/scripts/qapi/introspect.py +++ b/scripts/qapi/introspect.py @@ -202,7 +202,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, + async): 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/test-qmp-cmds.c b/tests/test-qmp-cmds.c index c4593552e3..58cd09ab08 100644 --- a/tests/test-qmp-cmds.c +++ b/tests/test-qmp-cmds.c @@ -36,6 +36,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); @@ -360,6 +382,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); @@ -373,6 +432,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(); diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qa= pi-schema-test.json index 0952c68734..d10ce39215 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 77fb1e1aa9..d652ebf75d 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 d21fca01fc..0d0cef479c 100644 --- a/tests/qapi-schema/test-qapi.py +++ b/tests/qapi-schema/test-qapi.py @@ -55,12 +55,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, + async): 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 async else '')) self._print_if(ifcond) =20 def visit_event(self, name, info, ifcond, arg_type, boxed): --=20 2.21.0.196.g041f5ea1cf From nobody Sat May 18 22:14:54 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=1554827064; cv=none; d=zoho.com; s=zohoarc; b=ZrTP7XOWg2m7PKkTZPWHbQ7h6JPzi8Q6kgLd+RWYBoYwnK6FiOkhZPMY6j5QafZpdqs0qGcLc0cV4M4aSiRe/yMsqH2w6cxv5sedMQgEMXEMvaW5LIzF7cS7DPeaCTY4G8czTahArMBTdIL+sAvLNEST/icjOI9+wHQSo+ujgRY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1554827064; 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=tDSODlDCItXTvBpwRRkIhfUOjVPPED8Yqjsvh4E9HPk=; b=dQ+qQ99a1y0uD4bp6asnjGLohubqqUuPY9JD1h8dRRHrbKIEn1q2OdpESbpceeYbGvMoKaShoahMKgXtW0yzRL3fyZ2gWPsrymUhjpDT/jW1tGbHAivqMDQw6qiJa6yEtOEbNCZ34g7tu0XCjXaYUjkS3tYONb2zNP/4KEh66OA= 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 1554827064570578.6906099342507; Tue, 9 Apr 2019 09:24:24 -0700 (PDT) Received: from localhost ([127.0.0.1]:45821 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtXo-00055g-En for importer@patchew.org; Tue, 09 Apr 2019 12:24:20 -0400 Received: from eggs.gnu.org ([209.51.188.92]:55734) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtLb-0003CM-5w for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:44 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hDtLZ-00054R-Nd for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:43 -0400 Received: from mx1.redhat.com ([209.132.183.28]:60750) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hDtLZ-000541-CS for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:41 -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 9F208330278; Tue, 9 Apr 2019 16:11:40 +0000 (UTC) Received: from localhost (ovpn-112-27.ams2.redhat.com [10.36.112.27]) by smtp.corp.redhat.com (Postfix) with ESMTP id 05E2F5D961; Tue, 9 Apr 2019 16:11:33 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Tue, 9 Apr 2019 18:10:03 +0200 Message-Id: <20190409161009.6322-15-marcandre.lureau@redhat.com> In-Reply-To: <20190409161009.6322-1-marcandre.lureau@redhat.com> References: <20190409161009.6322-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.29]); Tue, 09 Apr 2019 16:11:40 +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 v4 14/20] qmp: add qmp_return_is_cancelled() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Michael Roth , Markus Armbruster , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , "Dr. David Alan Gilbert" 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 58cd09ab08..97958a9d78 100644 --- a/tests/test-qmp-cmds.c +++ b/tests/test-qmp-cmds.c @@ -36,17 +36,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 @@ -419,6 +431,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); @@ -433,6 +469,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.21.0.196.g041f5ea1cf From nobody Sat May 18 22:14:54 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=1554826960; cv=none; d=zoho.com; s=zohoarc; b=SaIqtQsS3IWc5K9/uz2+5S9kquJClWNn2dc1FhODcVhkuP/m0vl7rV20N3tQrYFRvkqA5Z4jLvOeO4f+0BrM4DXIz3bLesh8gH8bUpSfZfWWuLkJhkFMknWvmqfMhnkaa8qyeNmEV9ryA6UNlEV1X9XsQ7EnYq+9FIT9FSnDsjk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1554826960; 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=sI4O5y9M0ZI/qza8XNPO8qWd8xo4e6MlNT/1WIYyUwk=; b=Nm5bIsewbgMUyiZOAVDHYsX7bYwvRAJWNhI/3gjLMv5yZDAaAZ2ilVWBRYbbeZh5BCJ6aHu66cyHdppXxXhsOZ64rO2RNxQzYaC45OpwshcjWRas/Tq1LyeFiZ1K4BSG2LUW2ThZvQU7ROn4M0doM3PKl09n84zM5LFe6aEnZfM= 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 155482696084890.51143612720023; Tue, 9 Apr 2019 09:22:40 -0700 (PDT) Received: from localhost ([127.0.0.1]:45794 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtW9-0003X3-P8 for importer@patchew.org; Tue, 09 Apr 2019 12:22:37 -0400 Received: from eggs.gnu.org ([209.51.188.92]:55750) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtLe-0003FI-8c for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:47 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hDtLd-00057T-2x for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:46 -0400 Received: from mx1.redhat.com ([209.132.183.28]:50330) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hDtLb-00055s-9B for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11: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 843B1308CF9A; Tue, 9 Apr 2019 16:11:42 +0000 (UTC) Received: from localhost (ovpn-112-27.ams2.redhat.com [10.36.112.27]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1C0535D9C9; Tue, 9 Apr 2019 16:11:41 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Tue, 9 Apr 2019 18:10:04 +0200 Message-Id: <20190409161009.6322-16-marcandre.lureau@redhat.com> In-Reply-To: <20190409161009.6322-1-marcandre.lureau@redhat.com> References: <20190409161009.6322-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.44]); Tue, 09 Apr 2019 16: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 v4 15/20] monitor: add qmp_return_get_monitor() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Michael Roth , Markus Armbruster , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , "Dr. David Alan Gilbert" 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.c | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h index c1b40a9cac..5f25cd2616 100644 --- a/include/monitor/monitor.h +++ b/include/monitor/monitor.h @@ -5,6 +5,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; =20 @@ -51,4 +52,6 @@ int monitor_fdset_dup_fd_find(int dup_fd); void monitor_vfprintf(FILE *stream, const char *fmt, va_list ap) GCC_FMT_ATTR(2, 0); =20 +Monitor *qmp_return_get_monitor(QmpReturn *qret); + #endif /* MONITOR_H */ diff --git a/monitor.c b/monitor.c index b1c4647a37..76bc2f8c7c 100644 --- a/monitor.c +++ b/monitor.c @@ -324,6 +324,12 @@ bool monitor_cur_is_qmp(void) return cur_mon && monitor_is_qmp(cur_mon); } =20 +Monitor *qmp_return_get_monitor(QmpReturn *qret) +{ + return qret->session ? + container_of(qret->session, Monitor, qmp.session) : NULL; +} + void monitor_read_command(Monitor *mon, int show_prompt) { if (!mon->rs) --=20 2.21.0.196.g041f5ea1cf From nobody Sat May 18 22:14:54 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=1554827061; cv=none; d=zoho.com; s=zohoarc; b=f3b6eKii52eNSMBHWA+fkhIAF8UTDz5UxmaHCHeSlV+FdClEaiOiPCW8yEjzvESkpq2yI3m3PnKel5NlvmwHPnNbgsS9dceHBS2s1zlG6AMqu4318Pk8GSvls2lklBsuRl2l9hyWLxqfvCYzoEFz62dt444y1xFMjtitoHugAEs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1554827061; 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=iDjI5OuMwl5JR/zchYO7v8Kg3Pnns8CjMR0SylXQEnM=; b=Ykn5jXe6HwaEUK6CJDoIb/UvvOquKTsHJaD6PcqRUCT0pVpFTzzJQRbaFGd9V9l4CrK0hvdLIcXSgufZfXgdYriYK+FseCqSxUOWDYF8nOIdEbQBQKk7E2niTZgKre/XkiIKBk4hsdNhvf09n18oxdmMluaDsECFV/3UtT0iPDs= 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 1554827061985891.4958820270723; Tue, 9 Apr 2019 09:24:21 -0700 (PDT) Received: from localhost ([127.0.0.1]:45819 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtXl-00051f-V8 for importer@patchew.org; Tue, 09 Apr 2019 12:24:17 -0400 Received: from eggs.gnu.org ([209.51.188.92]:55778) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtLf-0003Gl-Tp for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:48 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hDtLe-00058X-Dx for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:47 -0400 Received: from mx1.redhat.com ([209.132.183.28]:43656) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hDtLd-00057I-D1 for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:46 -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 9D73630B96D1; Tue, 9 Apr 2019 16:11:44 +0000 (UTC) Received: from localhost (ovpn-112-27.ams2.redhat.com [10.36.112.27]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1DCFA5D960; Tue, 9 Apr 2019 16:11:43 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Tue, 9 Apr 2019 18:10:05 +0200 Message-Id: <20190409161009.6322-17-marcandre.lureau@redhat.com> In-Reply-To: <20190409161009.6322-1-marcandre.lureau@redhat.com> References: <20190409161009.6322-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.49]); Tue, 09 Apr 2019 16:11:44 +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 v4 16/20] console: add graphic_hw_update_done() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Michael Roth , Markus Armbruster , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , "Dr. David Alan Gilbert" 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 --- include/ui/console.h | 2 ++ hw/display/qxl-render.c | 9 +++++++-- hw/display/qxl.c | 1 + ui/console.c | 9 +++++++++ 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/include/ui/console.h b/include/ui/console.h index fef900db76..9415adadfe 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -364,6 +364,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); @@ -379,6 +380,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/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 c8ce5781e0..884e24766c 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -1182,6 +1182,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/ui/console.c b/ui/console.c index 6d2282d3e9..3a7f71021f 100644 --- a/ui/console.c +++ b/ui/console.c @@ -258,13 +258,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.21.0.196.g041f5ea1cf From nobody Sat May 18 22:14:54 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=1554827122; cv=none; d=zoho.com; s=zohoarc; b=iyEFRQVZh1AhLffgN+i04H5nwoN9M+5Fk703wzfHq+j+cZwqxrkrHSFi3uWabdptRrdL4aTCF+7U9/bdh0vSz/MZj26RjwyJmV+Eo0d21uawV3SN8XscxuNEaap8mMX0IBEv+UQl4Tk5yMzgevDvb9KpQC6DKei0lag/t9IHhh8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1554827122; 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=CzOtvVxSm6u6wT3Y7PY+IQn26/mMdOPqDBL2DReQbl4=; b=YO2UaF1Mo3mfAparmyrWzG2In14JhAvCzcKoKCH24BXOpov3dH6f6YQNSzc/bsPbLefrVYthZYDKGR9a3m7LuxGhG6ajR2N2E0dpqsGjAXs1tvsgj8VVQVXxFBEr8ADhGuvdzErcJQ0P4qTqdGkgs1LAhWjX6iITlAwxn39eOaA= 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 1554827122252894.0159872319472; Tue, 9 Apr 2019 09:25:22 -0700 (PDT) Received: from localhost ([127.0.0.1]:45825 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtYl-0005xi-2w for importer@patchew.org; Tue, 09 Apr 2019 12:25:19 -0400 Received: from eggs.gnu.org ([209.51.188.92]:55801) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtLh-0003J1-GO for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hDtLg-0005A3-2v for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:49 -0400 Received: from mx1.redhat.com ([209.132.183.28]:8084) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hDtLf-00058r-AZ for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:48 -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 8F44DC049E22; Tue, 9 Apr 2019 16:11:46 +0000 (UTC) Received: from localhost (ovpn-112-27.ams2.redhat.com [10.36.112.27]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0B3DC5D9C9; Tue, 9 Apr 2019 16:11:45 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Tue, 9 Apr 2019 18:10:06 +0200 Message-Id: <20190409161009.6322-18-marcandre.lureau@redhat.com> In-Reply-To: <20190409161009.6322-1-marcandre.lureau@redhat.com> References: <20190409161009.6322-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]); Tue, 09 Apr 2019 16:11:46 +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 v4 17/20] console: make screendump asynchronous X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Michael Roth , Markus Armbruster , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , "Dr. David Alan Gilbert" 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 --- qapi/ui.json | 3 +- include/ui/console.h | 3 ++ hmp.c | 2 +- ui/console.c | 103 +++++++++++++++++++++++++++++++++++++++---- 4 files changed, 100 insertions(+), 11 deletions(-) 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/include/ui/console.h b/include/ui/console.h index 9415adadfe..2649c3cbfe 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/hmp.c b/hmp.c index 8eec768088..9428c90c5d 100644 --- a/hmp.c +++ b/hmp.c @@ -2380,7 +2380,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/ui/console.c b/ui/console.c index 3a7f71021f..620cd14b80 100644 --- a/ui/console.c +++ b/ui/console.c @@ -32,6 +32,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 @@ -116,6 +117,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 @@ -166,6 +173,8 @@ struct QemuConsole { uint8_t out_fifo_buf[16]; QEMUTimer *kbd_timer; =20 + QLIST_HEAD(, qmp_screendump) qmp_screendumps; + QTAILQ_ENTRY(QemuConsole) next; }; =20 @@ -192,6 +201,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) { @@ -258,8 +269,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) @@ -355,30 +406,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) { @@ -389,6 +451,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) { @@ -1293,6 +1377,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.21.0.196.g041f5ea1cf From nobody Sat May 18 22:14:54 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=1554827218; cv=none; d=zoho.com; s=zohoarc; b=EeHm44RhmjUhRMwM2t/rJUjcsbMrrFp7d5+dixf+8JNQ+uNKiGipiGl4R5vYSct0tAIV0wWPrin66UBOG2Mp4my36YeKt1mm+pJQpJnzhZ9xCCm+U/Wd5L+4cpae7b3GvnM4+RlLkINDWpCKyKoIF+eWRGShdjm0DsHOpfO4XPs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1554827218; 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=TL/FH3c/ChvgOpP5ZS9z1AMSI080wJj1VcAs+ulAp9M=; b=Kc2uy9W6aeJoM4aTi9VuQX/wVaQrxyxSqcUPPVys9jvFxlOMjiJHtS8N24FSYWmw6usFfh7CH33agbZEdhng4TI4BPEjg7c7F6ePWZgjqNmuOW7ChfKnKL1yKSAmccgtlddzTPDmoErq6odKwbrB/3sxFyDf4UvLK6Gf7KlKgeA= 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 (209.51.188.17 [209.51.188.17]) by mx.zohomail.com with SMTPS id 1554827218837924.2900010839294; Tue, 9 Apr 2019 09:26:58 -0700 (PDT) Received: from localhost ([127.0.0.1]:45887 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtaD-0007VT-8d for importer@patchew.org; Tue, 09 Apr 2019 12:26:49 -0400 Received: from eggs.gnu.org ([209.51.188.92]:55828) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtLk-0003Uk-TB for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:53 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hDtLk-0005Cf-02 for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:52 -0400 Received: from mx1.redhat.com ([209.132.183.28]:57136) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hDtLj-0005C0-Jt for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:51 -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 D50ABC05E14C; Tue, 9 Apr 2019 16:11:50 +0000 (UTC) Received: from localhost (ovpn-112-27.ams2.redhat.com [10.36.112.27]) by smtp.corp.redhat.com (Postfix) with ESMTP id 576C917CFB; Tue, 9 Apr 2019 16:11:47 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Tue, 9 Apr 2019 18:10:07 +0200 Message-Id: <20190409161009.6322-19-marcandre.lureau@redhat.com> In-Reply-To: <20190409161009.6322-1-marcandre.lureau@redhat.com> References: <20190409161009.6322-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.32]); Tue, 09 Apr 2019 16:11:50 +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 v4 18/20] monitor: start making qmp_human_monitor_command() asynchronous X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Michael Roth , Markus Armbruster , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , "Dr. David Alan Gilbert" 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 --- qapi/misc.json | 3 ++- monitor.c | 14 ++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/qapi/misc.json b/qapi/misc.json index 8b3ca4fdd3..f8fd4824fb 100644 --- a/qapi/misc.json +++ b/qapi/misc.json @@ -1344,7 +1344,8 @@ ## { 'command': 'human-monitor-command', 'data': {'command-line': 'str', '*cpu-index': 'int'}, - 'returns': 'str' } + 'returns': 'str', + 'async': true } =20 ## # @ObjectPropertyInfo: diff --git a/monitor.c b/monitor.c index 76bc2f8c7c..477ccd852d 100644 --- a/monitor.c +++ b/monitor.c @@ -743,8 +743,8 @@ static void monitor_data_destroy(Monitor *mon) g_queue_free(mon->qmp.qmp_requests); } =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, hmp; @@ -757,15 +757,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.mon_lock); if (qstring_get_length(hmp.outbuf) > 0) { @@ -775,9 +775,11 @@ char *qmp_human_monitor_command(const char *command_li= ne, bool has_cpu_index, } qemu_mutex_unlock(&hmp.mon_lock); =20 + qmp_human_monitor_command_return(qret, output); + out: + cur_mon =3D old_mon; monitor_data_destroy(&hmp); - return output; } =20 static int compare_cmd(const char *name, const char *list) --=20 2.21.0.196.g041f5ea1cf From nobody Sat May 18 22:14:54 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=1554827351; cv=none; d=zoho.com; s=zohoarc; b=NRdsuh6ocQ8FHDMJI6tRbwCjmt3yBLcoOe1tCQ/kaSyg0tiVthWKzv/KoXTKzI+LVKH9O8xX4d+w4yzwfp70jDbfrKxDDT1BfrhMPXQ2AB/1FCj1gvVf+rPitaD510Xb1ht8P+7x+2swd3Ma/cEQ1Ggp3OpckwwFPM4EGiOh1VI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1554827351; 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=XZGd9d0vLCBJCozasey+rwG+vS9RoBUNfEaMhpf2C0M=; b=PxJsG8hjQ1XPuVAW5nWLcpPLsjzRL7B7IP1vIToQFf0CcMY6J/sd6bqLiBre6h3LdCXVSevkbSuGA7Qu4q2g2FTVkHmDY2OzXKeNnCJmufqcovjB465fbx991M1KO4Uc6zVSZNnTw17MZFkuBSt+zO5wreDL1gzPe+wY4bepwDs= 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 1554827351271330.8677183998984; Tue, 9 Apr 2019 09:29:11 -0700 (PDT) Received: from localhost ([127.0.0.1]:45910 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtcS-0001Fs-87 for importer@patchew.org; Tue, 09 Apr 2019 12:29:08 -0400 Received: from eggs.gnu.org ([209.51.188.92]:55868) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtLq-0003aU-5u for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:59 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hDtLo-0005FX-QE for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:58 -0400 Received: from mx1.redhat.com ([209.132.183.28]:32890) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hDtLo-0005Ew-FB for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:11:56 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B27CE2CD7F1; Tue, 9 Apr 2019 16:11:55 +0000 (UTC) Received: from localhost (ovpn-112-27.ams2.redhat.com [10.36.112.27]) by smtp.corp.redhat.com (Postfix) with ESMTP id 490F75C223; Tue, 9 Apr 2019 16:11:52 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Tue, 9 Apr 2019 18:10:08 +0200 Message-Id: <20190409161009.6322-20-marcandre.lureau@redhat.com> In-Reply-To: <20190409161009.6322-1-marcandre.lureau@redhat.com> References: <20190409161009.6322-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Tue, 09 Apr 2019 16:11:55 +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 v4 19/20] monitor: teach HMP about asynchronous commands X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Michael Roth , Markus Armbruster , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , "Dr. David Alan Gilbert" 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 --- monitor.c | 103 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 82 insertions(+), 21 deletions(-) diff --git a/monitor.c b/monitor.c index 477ccd852d..4943c7635c 100644 --- a/monitor.c +++ b/monitor.c @@ -130,13 +130,17 @@ typedef struct mon_cmd_t { 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 * used, and cmd of 1st level plays the role of help function. */ struct mon_cmd_t *sub_table; void (*command_completion)(ReadLineState *rs, int nb_args, const char = *str); + bool async; } mon_cmd_t; =20 /* file descriptors passed via SCM_RIGHTS */ @@ -207,6 +211,7 @@ struct Monitor { int suspend_cnt; /* Needs to be accessed atomically */ bool skip_flush; bool use_io_thread; + QmpReturn *for_qmp_command; =20 /* * State used only in the thread "owning" the monitor. @@ -707,7 +712,7 @@ static void monitor_qapi_event_init(void) qapi_event_throttle_equal); } =20 -static void handle_hmp_command(Monitor *mon, const char *cmdline); +static bool handle_hmp_command(Monitor *mon, const char *cmdline); =20 static void monitor_iothread_init(void); =20 @@ -743,16 +748,70 @@ static void monitor_data_destroy(Monitor *mon) g_queue_free(mon->qmp.qmp_requests); } =20 +static void free_hmp_monitor(void *opaque) +{ + Monitor *hmp =3D opaque; + + qmp_session_destroy(&hmp->qmp.session); + monitor_data_destroy(hmp); + g_free(hmp); +} + +static AioContext *monitor_get_aio_context(void) +{ + return iothread_get_aio_context(mon_iothread); +} + +static void qmp_human_monitor_command_finish(Monitor *hmp, QmpReturn *qret) +{ + char *output; + + qemu_mutex_lock(&hmp->mon_lock); + if (qstring_get_length(hmp->outbuf) > 0) { + output =3D g_strdup(qstring_get_str(hmp->outbuf)); + } else { + output =3D g_strdup(""); + } + qemu_mutex_unlock(&hmp->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) +{ + Monitor *hmp =3D container_of(session, Monitor, qmp.session); + QDict *err =3D qdict_get_qdict(rsp, "error"); + Monitor *old_mon =3D cur_mon; + + cur_mon =3D hmp; + 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); + } + cur_mon =3D old_mon; +} + 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, hmp; + Monitor *old_mon, *hmp =3D g_new0(Monitor, 1); =20 - monitor_data_init(&hmp, true, false); + monitor_data_init(hmp, true, false); + qmp_session_init(&hmp->qmp.session, NULL, NULL, hmp_dispatch_return_cb= ); + hmp->for_qmp_command =3D qret; =20 old_mon =3D cur_mon; - cur_mon =3D &hmp; + cur_mon =3D hmp; =20 if (has_cpu_index) { int ret =3D monitor_set_cpu(cpu_index); @@ -761,25 +820,17 @@ void qmp_human_monitor_command(const char *command_li= ne, bool has_cpu_index, error_setg(&err, QERR_INVALID_PARAMETER_VALUE, "cpu-index", "a CPU number"); qmp_return_error(qret, err); + monitor_data_destroy(hmp); goto out; } } =20 - handle_hmp_command(&hmp, command_line); - - qemu_mutex_lock(&hmp.mon_lock); - if (qstring_get_length(hmp.outbuf) > 0) { - output =3D g_strdup(qstring_get_str(hmp.outbuf)); - } else { - output =3D g_strdup(""); + if (!handle_hmp_command(hmp, command_line)) { + qmp_human_monitor_command_finish(hmp, qret); } - qemu_mutex_unlock(&hmp.mon_lock); - - qmp_human_monitor_command_return(qret, output); =20 out: cur_mon =3D old_mon; - monitor_data_destroy(&hmp); } =20 static int compare_cmd(const char *name, const char *list) @@ -3438,7 +3489,7 @@ fail: return NULL; } =20 -static void handle_hmp_command(Monitor *mon, const char *cmdline) +static bool handle_hmp_command(Monitor *mon, const char *cmdline) { QDict *qdict; const mon_cmd_t *cmd; @@ -3448,7 +3499,7 @@ static void handle_hmp_command(Monitor *mon, const ch= ar *cmdline) =20 cmd =3D monitor_parse_command(mon, cmdline, &cmdline, mon->cmd_table); if (!cmd) { - return; + return false; } =20 qdict =3D monitor_parse_arguments(mon, &cmdline, cmd); @@ -3458,11 +3509,19 @@ static void handle_hmp_command(Monitor *mon, const = char *cmdline) } monitor_printf(mon, "Try \"help %.*s\" for more information\n", (int)(cmdline - cmd_start), cmd_start); - return; + return false; } =20 - cmd->cmd(mon, qdict); + if (cmd->async) { + QmpReturn *qret =3D qmp_return_new(&mon->qmp.session, NULL); + monitor_suspend(mon); + cmd->async_cmd(mon, qdict, qret); + } else { + cmd->cmd(mon, qdict); + } qobject_unref(qdict); + + return cmd->async; } =20 static void cmd_completion(Monitor *mon, const char *name, const char *lis= t) @@ -4638,6 +4697,8 @@ void monitor_init(Chardev *chr, int flags) NULL, mon, NULL, true); } } else { + qmp_session_init(&mon->qmp.session, + NULL, NULL, hmp_dispatch_return_cb); qemu_chr_fe_set_handlers(&mon->chr, monitor_can_read, monitor_read, monitor_event, NULL, mon, NULL, true); } --=20 2.21.0.196.g041f5ea1cf From nobody Sat May 18 22:14:54 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=1554827457; cv=none; d=zoho.com; s=zohoarc; b=muzqPaI3kNJJqWaS3R3IwiCR4xzs4XDkodnxlpSCAGRErxFKMYAakeaqcTSn6iqTlWCF1slqOoiQl6kuxkpXd262lElcRZG533vmJdbJa4niDiBWvfz+SNVjSjolCtI8Iw1PLnzgDX/S3ShFxFYMh7u/hBliHCphyHVO6thcoOU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1554827457; 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=u8lA2eJGWshu1rw0f3Y6TGHVuq3mP03mQmn+0054PUc=; b=GMq5cSqm5uTALr5avTDbJYs7q9+4DjBEQt3CuRM3zmA6P6/VsxhnH8fYKOlbonwf6VjJQLW7tmU2DsnU9k9e0M6XYs5w5Zz5ydwfGOiqEgGDksY9smepcPRRcsBkFh3igq3lTWIEYCHCa2/+TAip2NPvS8KB+XiID79Y4o7FRZE= 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 155482745726978.25243300092382; Tue, 9 Apr 2019 09:30:57 -0700 (PDT) Received: from localhost ([127.0.0.1]:46015 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDteC-0002ui-B3 for importer@patchew.org; Tue, 09 Apr 2019 12:30:56 -0400 Received: from eggs.gnu.org ([209.51.188.92]:55964) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1hDtM1-0003kV-Af for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:12:10 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hDtM0-0005N9-4P for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12:12:09 -0400 Received: from mx1.redhat.com ([209.132.183.28]:47426) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hDtLz-0005MV-P5 for qemu-devel@nongnu.org; Tue, 09 Apr 2019 12: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 9DEE98125A; Tue, 9 Apr 2019 16:11:57 +0000 (UTC) Received: from localhost (ovpn-112-27.ams2.redhat.com [10.36.112.27]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2A0FD17AD8; Tue, 9 Apr 2019 16:11:56 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Tue, 9 Apr 2019 18:10:09 +0200 Message-Id: <20190409161009.6322-21-marcandre.lureau@redhat.com> In-Reply-To: <20190409161009.6322-1-marcandre.lureau@redhat.com> References: <20190409161009.6322-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.25]); Tue, 09 Apr 2019 16:12:02 +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 v4 20/20] hmp: call the asynchronous QMP screendump to fix outdated/glitches X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Michael Roth , Markus Armbruster , Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , "Dr. David Alan Gilbert" 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.h | 3 ++- hmp.c | 6 ++---- ui/console.c | 22 ---------------------- hmp-commands.hx | 3 ++- 4 files changed, 6 insertions(+), 28 deletions(-) diff --git a/hmp.h b/hmp.h index 43617f2646..4059c8bea9 100644 --- a/hmp.h +++ b/hmp.h @@ -16,6 +16,7 @@ =20 #include "qemu-common.h" #include "qemu/readline.h" +#include "qapi/qmp/dispatch.h" =20 void hmp_info_name(Monitor *mon, const QDict *qdict); void hmp_info_version(Monitor *mon, const QDict *qdict); @@ -102,7 +103,7 @@ void hmp_netdev_del(Monitor *mon, const QDict *qdict); void hmp_getfd(Monitor *mon, const QDict *qdict); void hmp_closefd(Monitor *mon, const QDict *qdict); void hmp_sendkey(Monitor *mon, const QDict *qdict); -void hmp_screendump(Monitor *mon, const QDict *qdict); +void hmp_screendump_async(Monitor *mon, const QDict *qdict, QmpReturn *qre= t); void hmp_nbd_server_start(Monitor *mon, const QDict *qdict); void hmp_nbd_server_add(Monitor *mon, const QDict *qdict); void hmp_nbd_server_remove(Monitor *mon, const QDict *qdict); diff --git a/hmp.c b/hmp.c index 9428c90c5d..60d2bc1c76 100644 --- a/hmp.c +++ b/hmp.c @@ -2373,15 +2373,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 620cd14b80..c259cf68aa 100644 --- a/ui/console.c +++ b/ui/console.c @@ -429,28 +429,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, diff --git a/hmp-commands.hx b/hmp-commands.hx index 9b4035965c..638b59e764 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 --=20 2.21.0.196.g041f5ea1cf