From patchwork Mon Mar 26 15:08:39 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891052 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408yPK1ZWzz9s21 for ; Tue, 27 Mar 2018 02:15:01 +1100 (AEDT) Received: from localhost ([::1]:57293 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tpq-0001Mm-LX for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:14:58 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54814) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tkg-00057A-LS for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:40 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0Tke-0002ij-Hq for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:38 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:38270 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0Tke-0002fO-CR for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:36 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 535527705F; Mon, 26 Mar 2018 15:09:28 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id DA3567C55; Mon, 26 Mar 2018 15:09:27 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:08:39 +0200 Message-Id: <20180326150916.9602-2-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Mon, 26 Mar 2018 15:09:28 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Mon, 26 Mar 2018 15:09:28 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 01/38] HACK: add back OOB X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" This adds back temporarily OOB for the sake of automated testing and for the rest of the patches that are based upon OOB, as well as a few pending fixes squashed together. Revert "qapi: Force UTF8 encoding when parsing qapi files" This reverts commit 39615354fc07af34e04ab5efb5b6d478b0d24e32. Revert "Revert "monitor: enable IO thread for (qmp & !mux) typed"" This reverts commit a4f90923b520f1dc0a768634877eb412e5052c26. Revert "Revert "tests: qmp-test: verify command batching"" This reverts commit cc797607c03722871a030f8a64d800a8df93b5b2. Revert "Revert "tests: qmp-test: add oob test"" This reverts commit 4fd78ad7934bbd002da8ea420ce16f73ad23f417. monitor: fix expected qmp_capabilities error description regression Fix regression introduced in commit cf869d53172920536a14180a83292b240e9d0545: Before: {"execute":"foo"} {"error": {"class": "CommandNotFound", "desc": "Expecting capabilities negotiation with 'qmp_capabilities'"}} After: {"execute":"foo"} {"error": {"class": "CommandNotFound", "desc": "The command foo has not been found"}} Because qmp_cmd_oob_check() happens before monitor_qmp_dispatch_one(). Move the error manipulation code to monitor_qmp_respond() instead. migration: fix pfd leak Fix leak spotted by ASAN: Direct leak of 16 byte(s) in 1 object(s) allocated from: #0 0x7fe1abb80a38 in __interceptor_calloc (/lib64/libasan.so.4+0xdea38) #1 0x7fe1aaf1bf75 in g_malloc0 ../glib/gmem.c:124 #2 0x7fe1aaf1c249 in g_malloc0_n ../glib/gmem.c:355 #3 0x55f4841cfaa9 in postcopy_ram_fault_thread /home/elmarco/src/qemu/migration/postcopy-ram.c:596 #4 0x55f48479447b in qemu_thread_start /home/elmarco/src/qemu/util/qemu-thread-posix.c:504 #5 0x7fe1a043550a in start_thread (/lib64/libpthread.so.0+0x750a) Regression introduced with commit 00fa4fc85b00f1a8a810068d158a7a66e88658eb. Signed-off-by: Marc-André Lureau --- migration/postcopy-ram.c | 1 + monitor.c | 30 +++++++------ tests/qmp-test.c | 97 +++++++++++++++++++++++++++++++++++++++- tests/Makefile.include | 6 +-- 4 files changed, 116 insertions(+), 18 deletions(-) diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c index efd77939af..4a0b33b373 100644 --- a/migration/postcopy-ram.c +++ b/migration/postcopy-ram.c @@ -754,6 +754,7 @@ static void *postcopy_ram_fault_thread(void *opaque) } } trace_postcopy_ram_fault_thread_exit(); + g_free(pfd); return NULL; } diff --git a/monitor.c b/monitor.c index 77f4c41cfa..d57bbbb134 100644 --- a/monitor.c +++ b/monitor.c @@ -36,6 +36,7 @@ #include "net/slirp.h" #include "chardev/char-fe.h" #include "chardev/char-io.h" +#include "chardev/char-mux.h" #include "ui/qemu-spice.h" #include "sysemu/numa.h" #include "monitor/monitor.h" @@ -3996,6 +3997,18 @@ static void monitor_qmp_respond(Monitor *mon, QObject *rsp, qdict_put_obj(qobject_to(QDict, rsp), "id", id); } + if (mon->qmp.commands == &qmp_cap_negotiation_commands) { + qdict = qdict_get_qdict(qobject_to(QDict, rsp), "error"); + if (qdict + && !g_strcmp0(qdict_get_try_str(qdict, "class"), + QapiErrorClass_str(ERROR_CLASS_COMMAND_NOT_FOUND))) { + /* Provide a more useful error message */ + qdict_del(qdict, "desc"); + qdict_put_str(qdict, "desc", "Expecting capabilities" + " negotiation with 'qmp_capabilities'"); + } + } + monitor_json_emitter(mon, rsp); } @@ -4027,7 +4040,6 @@ static void monitor_qmp_dispatch_one(QMPRequest *req_obj) { Monitor *mon, *old_mon; QObject *req, *rsp = NULL, *id; - QDict *qdict = NULL; bool need_resume; req = req_obj->req; @@ -4050,18 +4062,6 @@ static void monitor_qmp_dispatch_one(QMPRequest *req_obj) cur_mon = old_mon; - if (mon->qmp.commands == &qmp_cap_negotiation_commands) { - qdict = qdict_get_qdict(qobject_to(QDict, rsp), "error"); - if (qdict - && !g_strcmp0(qdict_get_try_str(qdict, "class"), - QapiErrorClass_str(ERROR_CLASS_COMMAND_NOT_FOUND))) { - /* Provide a more useful error message */ - qdict_del(qdict, "desc"); - qdict_put_str(qdict, "desc", "Expecting capabilities negotiation" - " with 'qmp_capabilities'"); - } - } - /* Respond if necessary */ monitor_qmp_respond(mon, rsp, NULL, id); @@ -4536,8 +4536,10 @@ static void monitor_qmp_setup_handlers_bh(void *opaque) void monitor_init(Chardev *chr, int flags) { Monitor *mon = g_malloc(sizeof(*mon)); + /* Enable IOThread for QMPs that are not using MUX chardev backends. */ + bool use_io_thr = (!CHARDEV_IS_MUX(chr)) && (flags & MONITOR_USE_CONTROL); - monitor_data_init(mon, false, false); + monitor_data_init(mon, false, use_io_thr); qemu_chr_fe_init(&mon->chr, chr, &error_abort); mon->flags = flags; diff --git a/tests/qmp-test.c b/tests/qmp-test.c index 558e83540c..07c0b87e27 100644 --- a/tests/qmp-test.c +++ b/tests/qmp-test.c @@ -80,6 +80,9 @@ static void test_qmp_protocol(void) QDict *resp, *q, *ret; QList *capabilities; QTestState *qts; + const QListEntry *entry; + QString *qstr; + int i; qts = qtest_init_without_qmp_handshake(common_args); @@ -89,7 +92,13 @@ static void test_qmp_protocol(void) g_assert(q); test_version(qdict_get(q, "version")); capabilities = qdict_get_qlist(q, "capabilities"); - g_assert(capabilities && qlist_empty(capabilities)); + g_assert(capabilities); + entry = qlist_first(capabilities); + g_assert(entry); + qstr = qobject_to(QString, entry->value); + g_assert(qstr); + g_assert_cmpstr(qstring_get_str(qstr), ==, "oob"); + QDECREF(resp); /* Test valid command before handshake */ resp = qtest_qmp(qts, "{ 'execute': 'query-version' }"); @@ -131,9 +140,94 @@ static void test_qmp_protocol(void) g_assert_cmpint(qdict_get_int(resp, "id"), ==, 2); QDECREF(resp); + /* + * Test command batching. In current test OOB is not enabled, we + * should be able to run as many commands in batch as we like. + * Using 16 (>8, which is OOB queue length) to make sure OOB won't + * break existing clients. Note: this test does not control the + * scheduling of QEMU's QMP command processing threads so it may + * not really trigger batching inside QEMU. This is just a + * best-effort test. + */ + for (i = 0; i < 16; i++) { + qtest_async_qmp(qts, "{ 'execute': 'query-version' }"); + } + /* Verify the replies to make sure no command is dropped. */ + for (i = 0; i < 16; i++) { + resp = qtest_qmp_receive(qts); + /* It should never be dropped. Each of them should be a reply. */ + g_assert(qdict_haskey(resp, "return")); + g_assert(!qdict_haskey(resp, "event")); + QDECREF(resp); + } + qtest_quit(qts); } +/* Tests for Out-Of-Band support. */ +static void test_qmp_oob(void) +{ + QDict *resp; + int acks = 0; + const char *cmd_id; + + global_qtest = qtest_init_without_qmp_handshake(common_args); + + /* Ignore the greeting message. */ + resp = qmp_receive(); + g_assert(qdict_get_qdict(resp, "QMP")); + QDECREF(resp); + + /* Try a fake capability, it should fail. */ + resp = qmp("{ 'execute': 'qmp_capabilities', " + " 'arguments': { 'enable': [ 'cap-does-not-exist' ] } }"); + g_assert(qdict_haskey(resp, "error")); + QDECREF(resp); + + /* Now, enable OOB in current QMP session, it should succeed. */ + resp = qmp("{ 'execute': 'qmp_capabilities', " + " 'arguments': { 'enable': [ 'oob' ] } }"); + g_assert(qdict_haskey(resp, "return")); + QDECREF(resp); + + /* + * Try any command that does not support OOB but with OOB flag. We + * should get failure. + */ + resp = qmp("{ 'execute': 'query-cpus'," + " 'control': { 'run-oob': true } }"); + g_assert(qdict_haskey(resp, "error")); + QDECREF(resp); + + /* + * First send the "x-oob-test" command with lock=true and + * oob=false, it should hang the dispatcher and main thread; + * later, we send another lock=false with oob=true to continue + * that thread processing. Finally we should receive replies from + * both commands. + */ + qmp_async("{ 'execute': 'x-oob-test'," + " 'arguments': { 'lock': true }, " + " 'id': 'lock-cmd'}"); + qmp_async("{ 'execute': 'x-oob-test', " + " 'arguments': { 'lock': false }, " + " 'control': { 'run-oob': true }, " + " 'id': 'unlock-cmd' }"); + + /* Ignore all events. Wait for 2 acks */ + while (acks < 2) { + resp = qmp_receive(); + cmd_id = qdict_get_str(resp, "id"); + if (!g_strcmp0(cmd_id, "lock-cmd") || + !g_strcmp0(cmd_id, "unlock-cmd")) { + acks++; + } + QDECREF(resp); + } + + qtest_end(); +} + static int query_error_class(const char *cmd) { static struct { @@ -318,6 +412,7 @@ int main(int argc, char *argv[]) g_test_init(&argc, &argv, NULL); qtest_add_func("qmp/protocol", test_qmp_protocol); + qtest_add_func("qmp/oob", test_qmp_oob); qmp_schema_init(&schema); add_query_tests(&schema); diff --git a/tests/Makefile.include b/tests/Makefile.include index eb218a9539..0b277036df 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -669,13 +669,13 @@ tests/test-qapi-events.c tests/test-qapi-events.h \ tests/test-qapi-introspect.c tests/test-qapi-introspect.h: \ tests/test-qapi-gen-timestamp ; tests/test-qapi-gen-timestamp: $(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(qapi-py) - $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-gen.py \ + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-gen.py \ -o tests -p "test-" $<, \ "GEN","$(@:%-timestamp=%)") @>$@ tests/qapi-schema/doc-good.test.texi: $(SRC_PATH)/tests/qapi-schema/doc-good.json $(qapi-py) - $(call quiet-command,$(PYTHON_UTF8) $(SRC_PATH)/scripts/qapi-gen.py \ + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-gen.py \ -o tests/qapi-schema -p "doc-good-" $<, \ "GEN","$@") @mv tests/qapi-schema/doc-good-qapi-doc.texi $@ @@ -927,7 +927,7 @@ check-tests/qemu-iotests-quick.sh: tests/qemu-iotests-quick.sh qemu-img$(EXESUF) .PHONY: $(patsubst %, check-%, $(check-qapi-schema-y)) $(patsubst %, check-%, $(check-qapi-schema-y)): check-%.json: $(SRC_PATH)/%.json $(call quiet-command, PYTHONPATH=$(SRC_PATH)/scripts \ - $(PYTHON_UTF8) $(SRC_PATH)/tests/qapi-schema/test-qapi.py \ + $(PYTHON) $(SRC_PATH)/tests/qapi-schema/test-qapi.py \ $^ >$*.test.out 2>$*.test.err; \ echo $$? >$*.test.exit, \ "TEST","$*.out") From patchwork Mon Mar 26 15:08:40 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891045 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408yJ32KXYz9s31 for ; Tue, 27 Mar 2018 02:10:27 +1100 (AEDT) Received: from localhost ([::1]:57264 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0TlQ-00058H-OY for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:10:24 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54763) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tkc-00054x-Hp for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:38 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0TkZ-0002fv-Dk for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:34 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:38271 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0TkZ-0002fQ-9Q for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:31 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id BCE83EB713; Mon, 26 Mar 2018 15:09:29 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id 601BE2026E03; Mon, 26 Mar 2018 15:09:29 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:08:40 +0200 Message-Id: <20180326150916.9602-3-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Mon, 26 Mar 2018 15:09:29 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Mon, 26 Mar 2018 15:09:29 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 02/38] qmp-shell: learn to send commands with quoted arguments 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: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Use shlex to split the CLI command, respecting quoted arguments, and also comments. This allows to call for ex: (QEMU) human-monitor-command command-line="screendump /dev/null" {"execute": "human-monitor-command", "arguments": {"command-line": "screendump /dev/null"}} Signed-off-by: Marc-André Lureau Reviewed-by: Eduardo Habkost --- scripts/qmp/qmp-shell | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/qmp/qmp-shell b/scripts/qmp/qmp-shell index be449de621..af7033c765 100755 --- a/scripts/qmp/qmp-shell +++ b/scripts/qmp/qmp-shell @@ -73,6 +73,7 @@ import sys import os import errno import atexit +import shlex class QMPCompleter(list): def complete(self, text, state): @@ -218,7 +219,7 @@ class QMPShell(qmp.QEMUMonitorProtocol): < command-name > [ arg-name1=arg1 ] ... [ arg-nameN=argN ] """ - cmdargs = cmdline.split() + cmdargs = shlex.split(cmdline) # Transactional CLI entry/exit: if cmdargs[0] == 'transaction(': From patchwork Mon Mar 26 15:08:41 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891044 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408yJ14F7qz9s2t for ; Tue, 27 Mar 2018 02:10:24 +1100 (AEDT) Received: from localhost ([::1]:57263 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0TlM-00056W-IQ for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:10:20 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54761) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tkc-00054w-He for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:35 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0TkZ-0002g8-Q0 for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:34 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:57182 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0TkZ-0002fr-K3 for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:31 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4D5FB84256; Mon, 26 Mar 2018 15:09:31 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id D1A08215CDAE; Mon, 26 Mar 2018 15:09:30 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:08:41 +0200 Message-Id: <20180326150916.9602-4-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Mon, 26 Mar 2018 15:09:31 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Mon, 26 Mar 2018 15:09:31 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 03/38] Revert "qmp: isolate responses into io thread" X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" This reverts commit abe3cd0ff7f774966da6842620806ab7576fe4f3. There is no need to add an additional queue to send the reply to the IOThread, because QMP response is thread safe, and chardev write path is thread safe. It will schedule watcher in the associated IOThread. Signed-off-by: Marc-André Lureau --- monitor.c | 96 +------------------------------------------------------ 1 file changed, 1 insertion(+), 95 deletions(-) diff --git a/monitor.c b/monitor.c index d57bbbb134..59920ea872 100644 --- a/monitor.c +++ b/monitor.c @@ -180,8 +180,6 @@ typedef struct { QemuMutex qmp_queue_lock; /* Input queue that holds all the parsed QMP requests */ GQueue *qmp_requests; - /* Output queue contains all the QMP responses in order */ - GQueue *qmp_responses; } MonitorQMP; /* @@ -208,7 +206,6 @@ struct Monitor { bool skip_flush; bool use_io_thr; - /* We can't access guest memory when holding the lock */ QemuMutex out_lock; QString *outbuf; guint out_watch; @@ -231,8 +228,6 @@ static struct { IOThread *mon_iothread; /* Bottom half to dispatch the requests received from IO thread */ QEMUBH *qmp_dispatcher_bh; - /* Bottom half to deliver the responses back to clients */ - QEMUBH *qmp_respond_bh; } mon_global; /* QMP checker flags */ @@ -422,8 +417,7 @@ int monitor_fprintf(FILE *stream, const char *fmt, ...) return 0; } -static void monitor_json_emitter_raw(Monitor *mon, - QObject *data) +static void monitor_json_emitter(Monitor *mon, const QObject *data) { QString *json; @@ -437,71 +431,6 @@ static void monitor_json_emitter_raw(Monitor *mon, QDECREF(json); } -static void monitor_json_emitter(Monitor *mon, QObject *data) -{ - if (mon->use_io_thr) { - /* - * If using IO thread, we need to queue the item so that IO - * thread will do the rest for us. Take refcount so that - * caller won't free the data (which will be finally freed in - * responder thread). - */ - qobject_incref(data); - qemu_mutex_lock(&mon->qmp.qmp_queue_lock); - g_queue_push_tail(mon->qmp.qmp_responses, (void *)data); - qemu_mutex_unlock(&mon->qmp.qmp_queue_lock); - qemu_bh_schedule(mon_global.qmp_respond_bh); - } else { - /* - * If not using monitor IO thread, then we are in main thread. - * Do the emission right away. - */ - monitor_json_emitter_raw(mon, data); - } -} - -struct QMPResponse { - Monitor *mon; - QObject *data; -}; -typedef struct QMPResponse QMPResponse; - -/* - * Return one QMPResponse. The response is only valid if - * response.data is not NULL. - */ -static QMPResponse monitor_qmp_response_pop_one(void) -{ - Monitor *mon; - QObject *data = NULL; - - qemu_mutex_lock(&monitor_lock); - QTAILQ_FOREACH(mon, &mon_list, entry) { - qemu_mutex_lock(&mon->qmp.qmp_queue_lock); - data = g_queue_pop_head(mon->qmp.qmp_responses); - qemu_mutex_unlock(&mon->qmp.qmp_queue_lock); - if (data) { - break; - } - } - qemu_mutex_unlock(&monitor_lock); - return (QMPResponse) { .mon = mon, .data = data }; -} - -static void monitor_qmp_bh_responder(void *opaque) -{ - QMPResponse response; - - while (true) { - response = monitor_qmp_response_pop_one(); - if (!response.data) { - break; - } - monitor_json_emitter_raw(response.mon, response.data); - qobject_decref(response.data); - } -} - static MonitorQAPIEventConf monitor_qapi_event_conf[QAPI_EVENT__MAX] = { /* Limit guest-triggerable events to 1 per second */ [QAPI_EVENT_RTC_CHANGE] = { 1000 * SCALE_MS }, @@ -688,7 +617,6 @@ static void monitor_data_init(Monitor *mon, bool skip_flush, mon->skip_flush = skip_flush; mon->use_io_thr = use_io_thr; mon->qmp.qmp_requests = g_queue_new(); - mon->qmp.qmp_responses = g_queue_new(); } static void monitor_data_destroy(Monitor *mon) @@ -703,7 +631,6 @@ static void monitor_data_destroy(Monitor *mon) qemu_mutex_destroy(&mon->out_lock); qemu_mutex_destroy(&mon->qmp.qmp_queue_lock); g_queue_free(mon->qmp.qmp_requests); - g_queue_free(mon->qmp.qmp_responses); } char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index, @@ -4443,15 +4370,6 @@ static void monitor_iothread_init(void) mon_global.qmp_dispatcher_bh = aio_bh_new(qemu_get_aio_context(), monitor_qmp_bh_dispatcher, NULL); - - /* - * Unlike the dispatcher BH, this must be run on the monitor IO - * thread, so that monitors that are using IO thread will make - * sure read/write operations are all done on the IO thread. - */ - mon_global.qmp_respond_bh = aio_bh_new(monitor_get_aio_context(), - monitor_qmp_bh_responder, - NULL); } void monitor_init_globals(void) @@ -4597,19 +4515,9 @@ void monitor_cleanup(void) */ iothread_stop(mon_global.mon_iothread); - /* - * After we have IOThread to send responses, it's possible that - * when we stop the IOThread there are still replies queued in the - * responder queue. Flush all of them. Note that even after this - * flush it's still possible that out buffer is not flushed. - * It'll be done in below monitor_flush() as the last resort. - */ - monitor_qmp_bh_responder(NULL); - qemu_mutex_lock(&monitor_lock); QTAILQ_FOREACH_SAFE(mon, &mon_list, entry, next) { QTAILQ_REMOVE(&mon_list, mon, entry); - monitor_flush(mon); monitor_data_destroy(mon); g_free(mon); } @@ -4618,8 +4526,6 @@ void monitor_cleanup(void) /* QEMUBHs needs to be deleted before destroying the IOThread. */ qemu_bh_delete(mon_global.qmp_dispatcher_bh); mon_global.qmp_dispatcher_bh = NULL; - qemu_bh_delete(mon_global.qmp_respond_bh); - mon_global.qmp_respond_bh = NULL; iothread_destroy(mon_global.mon_iothread); mon_global.mon_iothread = NULL; From patchwork Mon Mar 26 15:08:42 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891047 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408yL72hMCz9s21 for ; Tue, 27 Mar 2018 02:12:15 +1100 (AEDT) Received: from localhost ([::1]:57281 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0TnA-0006xo-Qv for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:12:12 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54762) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tkc-00054y-Hr for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:35 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0Tkb-0002gp-67 for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:34 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:47462 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0Tkb-0002gd-0Z for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:33 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A7D29401DE69; Mon, 26 Mar 2018 15:09:32 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id 585CB202322B; Mon, 26 Mar 2018 15:09:32 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:08:42 +0200 Message-Id: <20180326150916.9602-5-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Mon, 26 Mar 2018 15:09:32 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Mon, 26 Mar 2018 15:09:32 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 04/38] monitor: no need to save need_resume 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: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" There is no need for per-command need_resume granularity, it should resume after running an non-oob command on oob-disabled monitor. Signed-off-by: Marc-André Lureau --- monitor.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/monitor.c b/monitor.c index 59920ea872..2428c7fcd4 100644 --- a/monitor.c +++ b/monitor.c @@ -3950,12 +3950,6 @@ struct QMPRequest { QObject *id; /* Request object to be handled */ QObject *req; - /* - * Whether we need to resume the monitor afterward. This flag is - * used to emulate the old QMP server behavior that the current - * command must be completed before execution of the next one. - */ - bool need_resume; }; typedef struct QMPRequest QMPRequest; @@ -3963,7 +3957,7 @@ typedef struct QMPRequest QMPRequest; * Dispatch one single QMP request. The function will free the req_obj * and objects inside it before return. */ -static void monitor_qmp_dispatch_one(QMPRequest *req_obj) +static void monitor_qmp_dispatch_one(QMPRequest *req_obj, bool oob_cmd) { Monitor *mon, *old_mon; QObject *req, *rsp = NULL, *id; @@ -3972,7 +3966,7 @@ static void monitor_qmp_dispatch_one(QMPRequest *req_obj) req = req_obj->req; mon = req_obj->mon; id = req_obj->id; - need_resume = req_obj->need_resume; + need_resume = !oob_cmd && !qmp_oob_enabled(mon); g_free(req_obj); @@ -4043,7 +4037,7 @@ static void monitor_qmp_bh_dispatcher(void *data) if (req_obj) { trace_monitor_qmp_cmd_in_band(qobject_get_try_str(req_obj->id) ?: ""); - monitor_qmp_dispatch_one(req_obj); + monitor_qmp_dispatch_one(req_obj, false); /* Reschedule instead of looping so the main loop stays responsive */ qemu_bh_schedule(mon_global.qmp_dispatcher_bh); } @@ -4096,13 +4090,12 @@ static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens) req_obj->mon = mon; req_obj->id = id; req_obj->req = req; - req_obj->need_resume = false; if (qmp_is_oob(qdict)) { /* Out-Of-Band (OOB) requests are executed directly in parser. */ trace_monitor_qmp_cmd_out_of_band(qobject_get_try_str(req_obj->id) ?: ""); - monitor_qmp_dispatch_one(req_obj); + monitor_qmp_dispatch_one(req_obj, true); return; } @@ -4117,7 +4110,6 @@ static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens) */ if (!qmp_oob_enabled(mon)) { monitor_suspend(mon); - req_obj->need_resume = true; } else { /* Drop the request if queue is full. */ if (mon->qmp.qmp_requests->length >= QMP_REQ_QUEUE_LEN_MAX) { From patchwork Mon Mar 26 15:08:43 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891057 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408ySs50qlz9s21 for ; Tue, 27 Mar 2018 02:18:05 +1100 (AEDT) Received: from localhost ([::1]:57315 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tsp-0003zf-5S for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:18:03 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54785) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tkd-00055V-LZ for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:42 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0Tkc-0002hk-Nl for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:35 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:36624 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0Tkc-0002hK-K5 for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:34 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4362C40711B2; Mon, 26 Mar 2018 15:09:34 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id E1BFB215CDAE; Mon, 26 Mar 2018 15:09:33 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:08:43 +0200 Message-Id: <20180326150916.9602-6-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 26 Mar 2018 15:09:34 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 26 Mar 2018 15:09:34 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 05/38] monitor: further simplify previous patch 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: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Move the resume code to the non-oob path. This patch could eventually be squashed with the previous patch. Signed-off-by: Marc-André Lureau --- monitor.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/monitor.c b/monitor.c index 2428c7fcd4..a8dcfa283e 100644 --- a/monitor.c +++ b/monitor.c @@ -3957,16 +3957,14 @@ typedef struct QMPRequest QMPRequest; * Dispatch one single QMP request. The function will free the req_obj * and objects inside it before return. */ -static void monitor_qmp_dispatch_one(QMPRequest *req_obj, bool oob_cmd) +static void monitor_qmp_dispatch_one(QMPRequest *req_obj) { Monitor *mon, *old_mon; QObject *req, *rsp = NULL, *id; - bool need_resume; req = req_obj->req; mon = req_obj->mon; id = req_obj->id; - need_resume = !oob_cmd && !qmp_oob_enabled(mon); g_free(req_obj); @@ -3986,11 +3984,6 @@ static void monitor_qmp_dispatch_one(QMPRequest *req_obj, bool oob_cmd) /* Respond if necessary */ monitor_qmp_respond(mon, rsp, NULL, id); - /* This pairs with the monitor_suspend() in handle_qmp_command(). */ - if (need_resume) { - monitor_resume(mon); - } - qobject_decref(req); } @@ -4036,8 +4029,14 @@ static void monitor_qmp_bh_dispatcher(void *data) QMPRequest *req_obj = monitor_qmp_requests_pop_one(); if (req_obj) { + Monitor *mon = req_obj->mon; + bool need_resume = !qmp_oob_enabled(mon); trace_monitor_qmp_cmd_in_band(qobject_get_try_str(req_obj->id) ?: ""); - monitor_qmp_dispatch_one(req_obj, false); + monitor_qmp_dispatch_one(req_obj); + /* This pairs with the monitor_suspend() in handle_qmp_command(). */ + if (need_resume) { + monitor_resume(mon); + } /* Reschedule instead of looping so the main loop stays responsive */ qemu_bh_schedule(mon_global.qmp_dispatcher_bh); } @@ -4095,7 +4094,7 @@ static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens) /* Out-Of-Band (OOB) requests are executed directly in parser. */ trace_monitor_qmp_cmd_out_of_band(qobject_get_try_str(req_obj->id) ?: ""); - monitor_qmp_dispatch_one(req_obj, true); + monitor_qmp_dispatch_one(req_obj); return; } From patchwork Mon Mar 26 15:08:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891051 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408yNK5n0bz9s2t for ; Tue, 27 Mar 2018 02:14:09 +1100 (AEDT) Received: from localhost ([::1]:57289 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tp1-0000E1-33 for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:14:07 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54825) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tki-00058d-6C for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:43 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0Tke-0002iR-Ab for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:40 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:36628 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0Tke-0002iI-6a for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:36 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A222E40711D4; Mon, 26 Mar 2018 15:09:35 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5572B7C50; Mon, 26 Mar 2018 15:09:35 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:08:44 +0200 Message-Id: <20180326150916.9602-7-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 26 Mar 2018 15:09:35 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 26 Mar 2018 15:09:35 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 06/38] monitor: no need to remove desc before replacing it 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: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" The following qdict_put() line does replace the value, as the documentation says. Signed-off-by: Marc-André Lureau --- monitor.c | 1 - 1 file changed, 1 deletion(-) diff --git a/monitor.c b/monitor.c index a8dcfa283e..5889a32231 100644 --- a/monitor.c +++ b/monitor.c @@ -3930,7 +3930,6 @@ static void monitor_qmp_respond(Monitor *mon, QObject *rsp, && !g_strcmp0(qdict_get_try_str(qdict, "class"), QapiErrorClass_str(ERROR_CLASS_COMMAND_NOT_FOUND))) { /* Provide a more useful error message */ - qdict_del(qdict, "desc"); qdict_put_str(qdict, "desc", "Expecting capabilities" " negotiation with 'qmp_capabilities'"); } From patchwork Mon Mar 26 15:08:45 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891061 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408yXc0LGqz9s21 for ; Tue, 27 Mar 2018 02:21:20 +1100 (AEDT) Received: from localhost ([::1]:57333 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tvx-0006pC-C8 for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:21:17 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54842) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tkl-0005B9-6P for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:44 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0Tkf-0002jE-GS for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:43 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:47466 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0Tkf-0002j4-BZ for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:37 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 0E4AD401DE69; Mon, 26 Mar 2018 15:09:37 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id B0E45D7DFA; Mon, 26 Mar 2018 15:09:36 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:08:45 +0200 Message-Id: <20180326150916.9602-8-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Mon, 26 Mar 2018 15:09:37 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Mon, 26 Mar 2018 15:09:37 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 07/38] json-parser: always set an error if return NULL 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: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Let's make json_parser_parse_err() suck less, and simplify caller error handling. Signed-off-by: Marc-André Lureau --- monitor.c | 4 ---- qobject/json-parser.c | 7 ++++++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/monitor.c b/monitor.c index 5889a32231..e9d0c4d172 100644 --- a/monitor.c +++ b/monitor.c @@ -4053,10 +4053,6 @@ static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens) QMPRequest *req_obj; req = json_parser_parse_err(tokens, NULL, &err); - if (!req && !err) { - /* json_parser_parse_err() sucks: can fail without setting @err */ - error_setg(&err, QERR_JSON_PARSING); - } if (err) { goto err; } diff --git a/qobject/json-parser.c b/qobject/json-parser.c index 769b960c9f..c39cd8e4d7 100644 --- a/qobject/json-parser.c +++ b/qobject/json-parser.c @@ -591,7 +591,12 @@ QObject *json_parser_parse_err(GQueue *tokens, va_list *ap, Error **errp) result = parse_value(ctxt, ap); - error_propagate(errp, ctxt->err); + if (!result && !ctxt->err) { + /* TODO: improve error reporting */ + error_setg(errp, "Failed to parse JSON"); + } else { + error_propagate(errp, ctxt->err); + } parser_context_free(ctxt); From patchwork Mon Mar 26 15:08:46 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891050 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408yML1zkpz9s21 for ; Tue, 27 Mar 2018 02:13:18 +1100 (AEDT) Received: from localhost ([::1]:57287 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0ToB-0007uX-Kf for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:13:15 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54856) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tkm-0005EM-JJ for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:45 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0Tkg-0002kF-Sx for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:44 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:57190 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0Tkg-0002jx-Ob for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:38 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 6C464722C6; Mon, 26 Mar 2018 15:09:38 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1EEBC2026E03; Mon, 26 Mar 2018 15:09:38 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:08:46 +0200 Message-Id: <20180326150916.9602-9-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Mon, 26 Mar 2018 15:09:38 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Mon, 26 Mar 2018 15:09:38 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 08/38] json-lexer: make it safe to call 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: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" We can easily avoid the burden of checking if the lexer was initialized prior to calling destroy by the caller, let's do it. Signed-off-by: Marc-André 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 980ba159d6..0eaba43a2c 100644 --- a/qobject/json-lexer.c +++ b/qobject/json-lexer.c @@ -386,5 +386,8 @@ int json_lexer_flush(JSONLexer *lexer) void json_lexer_destroy(JSONLexer *lexer) { - g_string_free(lexer->token, true); + if (lexer->token) { + g_string_free(lexer->token, true); + lexer->token = NULL; + } } From patchwork Mon Mar 26 15:08:47 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891046 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408yJC1SHzz9s2t for ; Tue, 27 Mar 2018 02:10:35 +1100 (AEDT) Received: from localhost ([::1]:57266 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0TlY-0005He-6k for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:10:32 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54844) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tkl-0005BO-D6 for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:44 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0Tki-0002l1-Fe for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:43 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:47472 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0Tki-0002kk-Ac for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:40 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 019D8401DE69; Mon, 26 Mar 2018 15:09:40 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id 867DE2026E03; Mon, 26 Mar 2018 15:09:39 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:08:47 +0200 Message-Id: <20180326150916.9602-10-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Mon, 26 Mar 2018 15:09:40 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Mon, 26 Mar 2018 15:09:40 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 09/38] json: remove useless return value from lexer/parser 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: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" The lexer always returns 0 when char feeding. Furthermore, none of the caller care about the return value. Signed-off-by: Marc-André Lureau Reviewed-by: Markus Armbruster --- include/qapi/qmp/json-lexer.h | 4 ++-- include/qapi/qmp/json-streamer.h | 4 ++-- qobject/json-lexer.c | 23 ++++++++--------------- qobject/json-streamer.c | 8 ++++---- 4 files changed, 16 insertions(+), 23 deletions(-) diff --git a/include/qapi/qmp/json-lexer.h b/include/qapi/qmp/json-lexer.h index afee7828cd..66ccf0357c 100644 --- a/include/qapi/qmp/json-lexer.h +++ b/include/qapi/qmp/json-lexer.h @@ -47,9 +47,9 @@ struct JSONLexer void json_lexer_init(JSONLexer *lexer, JSONLexerEmitter func); -int json_lexer_feed(JSONLexer *lexer, const char *buffer, size_t size); +void json_lexer_feed(JSONLexer *lexer, const char *buffer, size_t size); -int json_lexer_flush(JSONLexer *lexer); +void json_lexer_flush(JSONLexer *lexer); void json_lexer_destroy(JSONLexer *lexer); diff --git a/include/qapi/qmp/json-streamer.h b/include/qapi/qmp/json-streamer.h index 00d8a23af8..cb808cf27d 100644 --- a/include/qapi/qmp/json-streamer.h +++ b/include/qapi/qmp/json-streamer.h @@ -36,10 +36,10 @@ typedef struct JSONMessageParser void json_message_parser_init(JSONMessageParser *parser, void (*func)(JSONMessageParser *, GQueue *)); -int json_message_parser_feed(JSONMessageParser *parser, +void json_message_parser_feed(JSONMessageParser *parser, const char *buffer, size_t size); -int json_message_parser_flush(JSONMessageParser *parser); +void json_message_parser_flush(JSONMessageParser *parser); void json_message_parser_destroy(JSONMessageParser *parser); diff --git a/qobject/json-lexer.c b/qobject/json-lexer.c index 0eaba43a2c..89ccb180cc 100644 --- a/qobject/json-lexer.c +++ b/qobject/json-lexer.c @@ -290,7 +290,7 @@ void json_lexer_init(JSONLexer *lexer, JSONLexerEmitter func) lexer->x = lexer->y = 0; } -static int json_lexer_feed_char(JSONLexer *lexer, char ch, bool flush) +static void json_lexer_feed_char(JSONLexer *lexer, char ch, bool flush) { int char_consumed, new_state; @@ -344,7 +344,7 @@ static int json_lexer_feed_char(JSONLexer *lexer, char ch, bool flush) g_string_truncate(lexer->token, 0); new_state = IN_START; lexer->state = new_state; - return 0; + return; default: break; } @@ -359,29 +359,22 @@ static int json_lexer_feed_char(JSONLexer *lexer, char ch, bool flush) g_string_truncate(lexer->token, 0); lexer->state = IN_START; } - - return 0; } -int json_lexer_feed(JSONLexer *lexer, const char *buffer, size_t size) +void json_lexer_feed(JSONLexer *lexer, const char *buffer, size_t size) { size_t i; for (i = 0; i < size; i++) { - int err; - - err = json_lexer_feed_char(lexer, buffer[i], false); - if (err < 0) { - return err; - } + json_lexer_feed_char(lexer, buffer[i], false); } - - return 0; } -int json_lexer_flush(JSONLexer *lexer) +void json_lexer_flush(JSONLexer *lexer) { - return lexer->state == IN_START ? 0 : json_lexer_feed_char(lexer, 0, true); + if (lexer->state != IN_START) { + json_lexer_feed_char(lexer, 0, true); + } } void json_lexer_destroy(JSONLexer *lexer) diff --git a/qobject/json-streamer.c b/qobject/json-streamer.c index c51c2021f9..78dfff2aa0 100644 --- a/qobject/json-streamer.c +++ b/qobject/json-streamer.c @@ -118,15 +118,15 @@ void json_message_parser_init(JSONMessageParser *parser, json_lexer_init(&parser->lexer, json_message_process_token); } -int json_message_parser_feed(JSONMessageParser *parser, +void json_message_parser_feed(JSONMessageParser *parser, const char *buffer, size_t size) { - return json_lexer_feed(&parser->lexer, buffer, size); + json_lexer_feed(&parser->lexer, buffer, size); } -int json_message_parser_flush(JSONMessageParser *parser) +void json_message_parser_flush(JSONMessageParser *parser) { - return json_lexer_flush(&parser->lexer); + json_lexer_flush(&parser->lexer); } void json_message_parser_destroy(JSONMessageParser *parser) From patchwork Mon Mar 26 15:08:48 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891065 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408ycC2Jnhz9s37 for ; Tue, 27 Mar 2018 02:24:27 +1100 (AEDT) Received: from localhost ([::1]:57348 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tyx-000162-LI for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:24:23 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54894) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tkp-0005I5-NN for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:48 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0Tko-0002o8-Pz for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:47 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:48728 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0Tko-0002nv-LA for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:46 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4E9D34040070; Mon, 26 Mar 2018 15:09:46 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5DBEF10B0F20; Mon, 26 Mar 2018 15:09:41 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:08:48 +0200 Message-Id: <20180326150916.9602-11-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Mon, 26 Mar 2018 15:09:46 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Mon, 26 Mar 2018 15:09:46 +0000 (UTC) for IP:'10.11.54.3' DOMAIN:'int-mx03.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 10/38] tests: add a few qemu-qmp tests 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: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" These 2 tests exhibited two qmp bugs that were fixed in 2.7 (series from commit e64c75a9752c5d0fd64eb2e684c656a5ea7d03c6 to commit 1382d4abdf9619985e4078e37e49e487cea9935e) Signed-off-by: Marc-André Lureau --- tests/qmp-test.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/tests/qmp-test.c b/tests/qmp-test.c index 07c0b87e27..642f46a332 100644 --- a/tests/qmp-test.c +++ b/tests/qmp-test.c @@ -224,7 +224,50 @@ static void test_qmp_oob(void) } QDECREF(resp); } + qtest_end(); +} + +static void test_object_add_without_props(void) +{ + QDict *ret, *error; + const gchar *klass, *desc; + + qtest_start("-machine none"); + ret = qmp("{'execute': 'object-add'," + " 'arguments': { 'qom-type': 'memory-backend-ram', 'id': 'ram1' } }"); + g_assert_nonnull(ret); + + error = qdict_get_qdict(ret, "error"); + klass = qdict_get_try_str(error, "class"); + desc = qdict_get_try_str(error, "desc"); + + g_assert_cmpstr(klass, ==, "GenericError"); + g_assert_cmpstr(desc, ==, "can't create backend with size 0"); + + QDECREF(ret); + qtest_end(); +} + +static void test_qom_set_without_value(void) +{ + QDict *ret, *error; + const gchar *klass, *desc; + + qtest_start("-machine none"); + + ret = qmp("{'execute': 'qom-set'," + " 'arguments': { 'path': '/machine', 'property': 'rtc-time' } }"); + g_assert_nonnull(ret); + + error = qdict_get_qdict(ret, "error"); + klass = qdict_get_try_str(error, "class"); + desc = qdict_get_try_str(error, "desc"); + + g_assert_cmpstr(klass, ==, "GenericError"); + g_assert_cmpstr(desc, ==, "Parameter 'value' is missing"); + + QDECREF(ret); qtest_end(); } @@ -411,13 +454,19 @@ int main(int argc, char *argv[]) g_test_init(&argc, &argv, NULL); + qtest_add_func("qmp/object-add-without-props", + test_object_add_without_props); + qtest_add_func("qmp/qom-set-without-value", + test_qom_set_without_value); qtest_add_func("qmp/protocol", test_qmp_protocol); qtest_add_func("qmp/oob", test_qmp_oob); + qmp_schema_init(&schema); add_query_tests(&schema); ret = g_test_run(); qmp_schema_cleanup(&schema); + return ret; } From patchwork Mon Mar 26 15:08:49 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891049 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408yMD0PsMz9s2t for ; Tue, 27 Mar 2018 02:13:12 +1100 (AEDT) Received: from localhost ([::1]:57285 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0To5-0007nC-Fv for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:13:09 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54924) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tky-0005Qb-8Y for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:00 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0Tkv-0002rt-4C for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:56 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:48734 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0Tku-0002ri-Va for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:53 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A36F9406803F; Mon, 26 Mar 2018 15:09:52 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id 65956D7DFA; Mon, 26 Mar 2018 15:09:47 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:08:49 +0200 Message-Id: <20180326150916.9602-12-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Mon, 26 Mar 2018 15:09:52 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Mon, 26 Mar 2018 15:09:52 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 11/38] tests: change /0.15/* tests to /qmp/* X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Presumably 0.15 was the version it was first introduced, but qmp keeps evolving. There is no point in having that version as test prefix, 'qmp' makes more sense here. Signed-off-by: Marc-André Lureau Reviewed-by: Eric Blake Reviewed-by: Markus Armbruster --- tests/test-qmp-cmds.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c index 93fbbb1b73..b49e9dd029 100644 --- a/tests/test-qmp-cmds.c +++ b/tests/test-qmp-cmds.c @@ -273,11 +273,11 @@ int main(int argc, char **argv) { g_test_init(&argc, &argv, NULL); - g_test_add_func("/0.15/dispatch_cmd", test_dispatch_cmd); - g_test_add_func("/0.15/dispatch_cmd_failure", test_dispatch_cmd_failure); - g_test_add_func("/0.15/dispatch_cmd_io", test_dispatch_cmd_io); - g_test_add_func("/0.15/dealloc_types", test_dealloc_types); - g_test_add_func("/0.15/dealloc_partial", test_dealloc_partial); + g_test_add_func("/qmp/dispatch_cmd", test_dispatch_cmd); + g_test_add_func("/qmp/dispatch_cmd_failure", test_dispatch_cmd_failure); + g_test_add_func("/qmp/dispatch_cmd_io", test_dispatch_cmd_io); + g_test_add_func("/qmp/dealloc_types", test_dealloc_types); + g_test_add_func("/qmp/dealloc_partial", test_dealloc_partial); test_qmp_init_marshal(&qmp_commands); g_test_run(); From patchwork Mon Mar 26 15:08:50 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891053 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408yQM0w5Gz9s21 for ; Tue, 27 Mar 2018 02:15:55 +1100 (AEDT) Received: from localhost ([::1]:57299 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tqi-0002Ce-Jm for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:15:52 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54971) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tl2-0005VK-Pr for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:01 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0Tkw-0002sV-JD for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:00 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:38284 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0Tkw-0002sH-Dg for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:54 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 1677C7B4AD; Mon, 26 Mar 2018 15:09:54 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id B552CD7DFA; Mon, 26 Mar 2018 15:09:53 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:08:50 +0200 Message-Id: <20180326150916.9602-13-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Mon, 26 Mar 2018 15:09:54 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Mon, 26 Mar 2018 15:09:54 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 12/38] tests: add a qmp success-response test X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Verify the usage of this schema feature and the API behaviour. This should be the only case where qmp_dispatch() returns NULL without error. Signed-off-by: Marc-André Lureau --- tests/test-qmp-cmds.c | 17 +++++++++++++++++ tests/qapi-schema/qapi-schema-test.json | 2 ++ tests/qapi-schema/qapi-schema-test.out | 2 ++ 3 files changed, 21 insertions(+) diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c index b49e9dd029..02cbaf41a2 100644 --- a/tests/test-qmp-cmds.c +++ b/tests/test-qmp-cmds.c @@ -16,6 +16,10 @@ void qmp_user_def_cmd(Error **errp) { } +void qmp_cmd_success_response(Error **errp) +{ +} + Empty2 *qmp_user_def_cmd0(Error **errp) { return g_new0(Empty2, 1); @@ -137,6 +141,17 @@ static void test_dispatch_cmd_failure(void) QDECREF(req); } +static void test_dispatch_cmd_success_response(void) +{ + QDict *req = qdict_new(); + QObject *resp; + + qdict_put_str(req, "execute", "cmd-success-response"); + resp = qmp_dispatch(&qmp_commands, QOBJECT(req)); + assert(resp == NULL); + QDECREF(req); +} + static QObject *test_qmp_dispatch(QDict *req) { QObject *resp_obj; @@ -276,6 +291,8 @@ int main(int argc, char **argv) g_test_add_func("/qmp/dispatch_cmd", test_dispatch_cmd); g_test_add_func("/qmp/dispatch_cmd_failure", test_dispatch_cmd_failure); g_test_add_func("/qmp/dispatch_cmd_io", test_dispatch_cmd_io); + g_test_add_func("/qmp/dispatch_cmd_success_response", + 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); diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json index c72dbd8050..96ff3a8e47 100644 --- a/tests/qapi-schema/qapi-schema-test.json +++ b/tests/qapi-schema/qapi-schema-test.json @@ -132,6 +132,8 @@ 'data': {'ud1a': 'UserDefOne', '*ud1b': 'UserDefOne'}, 'returns': 'UserDefTwo' } +{ 'command': 'cmd-success-response', 'data': {}, '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/qapi-schema-test.out index 012e7fc06a..cd3642be34 100644 --- a/tests/qapi-schema/qapi-schema-test.out +++ b/tests/qapi-schema/qapi-schema-test.out @@ -153,6 +153,8 @@ object q_obj_user_def_cmd2-arg member ud1b: UserDefOne optional=True command user_def_cmd2 q_obj_user_def_cmd2-arg -> UserDefTwo gen=True success_response=True boxed=False +command cmd-success-response None -> None + gen=True success_response=False boxed=False object q_obj_guest-get-time-arg member a: int optional=False member b: int optional=True From patchwork Mon Mar 26 15:08:51 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891071 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408ygg5973z9s2B for ; Tue, 27 Mar 2018 02:27:27 +1100 (AEDT) Received: from localhost ([::1]:57367 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0U1t-0003xi-5a for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:27:25 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54935) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tkz-0005RK-3q for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:58 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0Tky-0002t6-2h for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:57 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:57200 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0Tkx-0002sw-T2 for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:55 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8AF7E722C5; Mon, 26 Mar 2018 15:09:55 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id 354E7202322B; Mon, 26 Mar 2018 15:09:55 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:08:51 +0200 Message-Id: <20180326150916.9602-14-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Mon, 26 Mar 2018 15:09:55 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Mon, 26 Mar 2018 15:09:55 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 13/38] qga: process_event() simplification X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Simplify the code around qmp_dispatch(). Make qmp_dispatch_check_obj() a pre-requirement, same as qemu monitor. Have a single send_response() point. Signed-off-by: Marc-André Lureau --- qga/main.c | 67 +++++++++++++++++++----------------------------------- 1 file changed, 23 insertions(+), 44 deletions(-) diff --git a/qga/main.c b/qga/main.c index df1888edc1..71468e68c2 100644 --- a/qga/main.c +++ b/qga/main.c @@ -579,67 +579,46 @@ static int send_response(GAState *s, QObject *payload) return 0; } -static void process_command(GAState *s, QDict *req) -{ - QObject *rsp = NULL; - int ret; - - g_assert(req); - g_debug("processing command"); - rsp = qmp_dispatch(&ga_commands, QOBJECT(req)); - if (rsp) { - ret = send_response(s, rsp); - if (ret < 0) { - g_warning("error sending response: %s", strerror(-ret)); - } - qobject_decref(rsp); - } -} - /* handle requests/control events coming in over the channel */ static void process_event(JSONMessageParser *parser, GQueue *tokens) { GAState *s = container_of(parser, GAState, parser); - QDict *qdict; + QObject *req, *rsp = NULL; Error *err = NULL; int ret; g_assert(s && parser); g_debug("process_event: called"); - qdict = qobject_to(QDict, json_parser_parse_err(tokens, NULL, &err)); - if (err || !qdict) { - QDECREF(qdict); - qdict = qdict_new(); - if (!err) { - g_warning("failed to parse event: unknown error"); - error_setg(&err, QERR_JSON_PARSING); - } else { - g_warning("failed to parse event: %s", error_get_pretty(err)); - } + + req = json_parser_parse_err(tokens, NULL, &err); + if (err) { + goto end; + } + + qmp_dispatch_check_obj(req, &err); + if (err) { + goto end; + } + + g_debug("processing command"); + rsp = qmp_dispatch(&ga_commands, req); + +end: + if (err) { + QDict *qdict = qdict_new(); qdict_put_obj(qdict, "error", qmp_build_error_object(err)); error_free(err); + rsp = QOBJECT(qdict); } - - /* handle host->guest commands */ - if (qdict_haskey(qdict, "execute")) { - process_command(s, qdict); - } else { - if (!qdict_haskey(qdict, "error")) { - QDECREF(qdict); - qdict = qdict_new(); - g_warning("unrecognized payload format"); - error_setg(&err, QERR_UNSUPPORTED); - qdict_put_obj(qdict, "error", qmp_build_error_object(err)); - error_free(err); - } - ret = send_response(s, QOBJECT(qdict)); + if (rsp) { + ret = send_response(s, rsp); if (ret < 0) { g_warning("error sending error response: %s", strerror(-ret)); } + qobject_decref(rsp); } - - QDECREF(qdict); + qobject_decref(req); } /* false return signals GAChannel to close the current client connection */ From patchwork Mon Mar 26 15:08:52 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891076 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408ykz57Jmz9s2B for ; Tue, 27 Mar 2018 02:30:19 +1100 (AEDT) Received: from localhost ([::1]:57382 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0U4f-0006Rh-3Y for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:30:17 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54950) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tl0-0005St-Me for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:59 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0Tkz-0002u1-Ei for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:58 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:52740 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0Tkz-0002tl-9E for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:57 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E558F8182D01; Mon, 26 Mar 2018 15:09:56 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id 999F27C50; Mon, 26 Mar 2018 15:09:56 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:08:52 +0200 Message-Id: <20180326150916.9602-15-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 26 Mar 2018 15:09:56 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 26 Mar 2018 15:09:56 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 14/38] monitor: simplify monitor_qmp_respond() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Since the error path is at a single location, we can create the response object there, simplifying argument handling. While at it, also simplify id ownership: no need for the extra reference count. Signed-off-by: Marc-André Lureau --- monitor.c | 58 ++++++++++++++++++++----------------------------------- 1 file changed, 21 insertions(+), 37 deletions(-) diff --git a/monitor.c b/monitor.c index e9d0c4d172..0d01e17398 100644 --- a/monitor.c +++ b/monitor.c @@ -3899,46 +3899,27 @@ static int monitor_can_read(void *opaque) return !atomic_mb_read(&mon->suspend_cnt); } -/* - * 1. This function takes ownership of rsp, err, and id. - * 2. rsp, err, and id may be NULL. - * 3. If err != NULL then rsp must be NULL. - */ -static void monitor_qmp_respond(Monitor *mon, QObject *rsp, - Error *err, QObject *id) +/* take the ownership of rsp & id */ +static void monitor_qmp_respond(Monitor *mon, QObject *rsp, QObject *id) { - QDict *qdict = NULL; - - if (err) { - assert(!rsp); - qdict = qdict_new(); - qdict_put_obj(qdict, "error", qmp_build_error_object(err)); - error_free(err); - rsp = QOBJECT(qdict); - } - - if (rsp) { - if (id) { - /* This is for the qdict below. */ - qobject_incref(id); - qdict_put_obj(qobject_to(QDict, rsp), "id", id); - } + if (!rsp) { + return; + } - if (mon->qmp.commands == &qmp_cap_negotiation_commands) { - qdict = qdict_get_qdict(qobject_to(QDict, rsp), "error"); - if (qdict - && !g_strcmp0(qdict_get_try_str(qdict, "class"), + if (id) { + qdict_put_obj(qobject_to(QDict, rsp), "id", id); + } + if (mon->qmp.commands == &qmp_cap_negotiation_commands) { + QDict *qdict = qdict_get_qdict(qobject_to(QDict, rsp), "error"); + if (qdict + && !g_strcmp0(qdict_get_try_str(qdict, "class"), QapiErrorClass_str(ERROR_CLASS_COMMAND_NOT_FOUND))) { - /* Provide a more useful error message */ - qdict_put_str(qdict, "desc", "Expecting capabilities" - " negotiation with 'qmp_capabilities'"); - } + /* Provide a more useful error message */ + qdict_put_str(qdict, "desc", "Expecting capabilities" + " negotiation with 'qmp_capabilities'"); } - - monitor_json_emitter(mon, rsp); } - - qobject_decref(id); + monitor_json_emitter(mon, rsp); qobject_decref(rsp); } @@ -3981,7 +3962,7 @@ static void monitor_qmp_dispatch_one(QMPRequest *req_obj) cur_mon = old_mon; /* Respond if necessary */ - monitor_qmp_respond(mon, rsp, NULL, id); + monitor_qmp_respond(mon, rsp, id); qobject_decref(req); } @@ -4131,7 +4112,10 @@ static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens) return; err: - monitor_qmp_respond(mon, NULL, err, NULL); + qdict = qdict_new(); + qdict_put_obj(qdict, "error", qmp_build_error_object(err)); + error_free(err); + monitor_qmp_respond(mon, QOBJECT(qdict), id); qobject_decref(req); } From patchwork Mon Mar 26 15:08:53 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891055 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408yRZ19rnz9s21 for ; Tue, 27 Mar 2018 02:16:58 +1100 (AEDT) Received: from localhost ([::1]:57310 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Trj-00037I-JZ for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:16:55 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54968) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tl2-0005Uw-Bg for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:06 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0Tl0-0002v3-UT for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:00 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:38298 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0Tl0-0002uf-OZ for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:09:58 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 703D577067; Mon, 26 Mar 2018 15:09:58 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0917F202322B; Mon, 26 Mar 2018 15:09:57 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:08:53 +0200 Message-Id: <20180326150916.9602-16-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Mon, 26 Mar 2018 15:09:58 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Mon, 26 Mar 2018 15:09:58 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 15/38] qmp: pass and return a QDict to qmp_dispatch() 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: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" qmp_dispatch_check_obj() now must be called before calling qmp_dispatch() and returns a dict. Change qmp_dispatch() arguments, clarifying the expected qobject types, and simplifying a bit the rest of the code. Signed-off-by: Marc-André Lureau --- include/qapi/qmp/dispatch.h | 2 +- monitor.c | 24 +++++++++++++----------- qapi/qmp-dispatch.c | 15 +++++---------- qga/main.c | 18 +++++++++--------- tests/test-qmp-cmds.c | 36 +++++++++++++++--------------------- 5 files changed, 43 insertions(+), 52 deletions(-) diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h index ffb4652f71..8e0ac29300 100644 --- a/include/qapi/qmp/dispatch.h +++ b/include/qapi/qmp/dispatch.h @@ -40,7 +40,7 @@ void qmp_register_command(QmpCommandList *cmds, const char *name, QmpCommandFunc *fn, QmpCommandOptions options); void qmp_unregister_command(QmpCommandList *cmds, const char *name); QmpCommand *qmp_find_command(QmpCommandList *cmds, const char *name); -QObject *qmp_dispatch(QmpCommandList *cmds, QObject *request); +QDict *qmp_dispatch(QmpCommandList *cmds, QDict *request); void qmp_disable_command(QmpCommandList *cmds, const char *name); void qmp_enable_command(QmpCommandList *cmds, const char *name); diff --git a/monitor.c b/monitor.c index 0d01e17398..471c57e88c 100644 --- a/monitor.c +++ b/monitor.c @@ -3900,17 +3900,17 @@ static int monitor_can_read(void *opaque) } /* take the ownership of rsp & id */ -static void monitor_qmp_respond(Monitor *mon, QObject *rsp, QObject *id) +static void monitor_qmp_respond(Monitor *mon, QDict *rsp, QObject *id) { if (!rsp) { return; } if (id) { - qdict_put_obj(qobject_to(QDict, rsp), "id", id); + qdict_put_obj(rsp, "id", id); } if (mon->qmp.commands == &qmp_cap_negotiation_commands) { - QDict *qdict = qdict_get_qdict(qobject_to(QDict, rsp), "error"); + QDict *qdict = qdict_get_qdict(rsp, "error"); if (qdict && !g_strcmp0(qdict_get_try_str(qdict, "class"), QapiErrorClass_str(ERROR_CLASS_COMMAND_NOT_FOUND))) { @@ -3919,8 +3919,8 @@ static void monitor_qmp_respond(Monitor *mon, QObject *rsp, QObject *id) " negotiation with 'qmp_capabilities'"); } } - monitor_json_emitter(mon, rsp); - qobject_decref(rsp); + monitor_json_emitter(mon, QOBJECT(rsp)); + QDECREF(rsp); } struct QMPRequest { @@ -3929,7 +3929,7 @@ struct QMPRequest { /* "id" field of the request */ QObject *id; /* Request object to be handled */ - QObject *req; + QDict *req; }; typedef struct QMPRequest QMPRequest; @@ -3940,7 +3940,8 @@ typedef struct QMPRequest QMPRequest; static void monitor_qmp_dispatch_one(QMPRequest *req_obj) { Monitor *mon, *old_mon; - QObject *req, *rsp = NULL, *id; + QDict *req, *rsp = NULL; + QObject *id; req = req_obj->req; mon = req_obj->mon; @@ -3949,7 +3950,7 @@ static void monitor_qmp_dispatch_one(QMPRequest *req_obj) g_free(req_obj); if (trace_event_get_state_backends(TRACE_HANDLE_QMP_COMMAND)) { - QString *req_json = qobject_to_json(req); + QString *req_json = qobject_to_json(QOBJECT(req)); trace_handle_qmp_command(mon, qstring_get_str(req_json)); QDECREF(req_json); } @@ -3964,7 +3965,8 @@ static void monitor_qmp_dispatch_one(QMPRequest *req_obj) /* Respond if necessary */ monitor_qmp_respond(mon, rsp, id); - qobject_decref(req); + + QDECREF(req); } /* @@ -4064,7 +4066,7 @@ static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens) req_obj = g_new0(QMPRequest, 1); req_obj->mon = mon; req_obj->id = id; - req_obj->req = req; + req_obj->req = qdict; if (qmp_is_oob(qdict)) { /* Out-Of-Band (OOB) requests are executed directly in parser. */ @@ -4115,7 +4117,7 @@ err: qdict = qdict_new(); qdict_put_obj(qdict, "error", qmp_build_error_object(err)); error_free(err); - monitor_qmp_respond(mon, QOBJECT(qdict), id); + monitor_qmp_respond(mon, qdict, id); qobject_decref(req); } diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index dd05907265..66596b66a0 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -74,20 +74,15 @@ QDict *qmp_dispatch_check_obj(const QObject *request, Error **errp) return dict; } -static QObject *do_qmp_dispatch(QmpCommandList *cmds, QObject *request, +static QObject *do_qmp_dispatch(QmpCommandList *cmds, QDict *dict, Error **errp) { Error *local_err = NULL; const char *command; - QDict *args, *dict; + QDict *args; QmpCommand *cmd; QObject *ret = NULL; - dict = qmp_dispatch_check_obj(request, errp); - if (!dict) { - return NULL; - } - command = qdict_get_str(dict, "execute"); cmd = qmp_find_command(cmds, command); if (cmd == NULL) { @@ -151,13 +146,13 @@ bool qmp_is_oob(QDict *dict) return qbool_get_bool(bool_obj); } -QObject *qmp_dispatch(QmpCommandList *cmds, QObject *request) +QDict *qmp_dispatch(QmpCommandList *cmds, QDict *req) { Error *err = NULL; QObject *ret; QDict *rsp; - ret = do_qmp_dispatch(cmds, request, &err); + ret = do_qmp_dispatch(cmds, req, &err); rsp = qdict_new(); if (err) { @@ -170,5 +165,5 @@ QObject *qmp_dispatch(QmpCommandList *cmds, QObject *request) return NULL; } - return QOBJECT(rsp); + return rsp; } diff --git a/qga/main.c b/qga/main.c index 71468e68c2..04f7dad0b3 100644 --- a/qga/main.c +++ b/qga/main.c @@ -583,7 +583,8 @@ static int send_response(GAState *s, QObject *payload) static void process_event(JSONMessageParser *parser, GQueue *tokens) { GAState *s = container_of(parser, GAState, parser); - QObject *req, *rsp = NULL; + QObject *obj; + QDict *req, *rsp = NULL; Error *err = NULL; int ret; @@ -591,12 +592,12 @@ static void process_event(JSONMessageParser *parser, GQueue *tokens) g_debug("process_event: called"); - req = json_parser_parse_err(tokens, NULL, &err); + obj = json_parser_parse_err(tokens, NULL, &err); if (err) { goto end; } - qmp_dispatch_check_obj(req, &err); + req = qmp_dispatch_check_obj(obj, &err); if (err) { goto end; } @@ -606,19 +607,18 @@ static void process_event(JSONMessageParser *parser, GQueue *tokens) end: if (err) { - QDict *qdict = qdict_new(); - qdict_put_obj(qdict, "error", qmp_build_error_object(err)); + rsp = qdict_new(); + qdict_put_obj(rsp, "error", qmp_build_error_object(err)); error_free(err); - rsp = QOBJECT(qdict); } if (rsp) { - ret = send_response(s, rsp); + ret = send_response(s, QOBJECT(rsp)); if (ret < 0) { g_warning("error sending error response: %s", strerror(-ret)); } - qobject_decref(rsp); + QDECREF(rsp); } - qobject_decref(req); + qobject_decref(obj); } /* false return signals GAChannel to close the current client connection */ diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c index 02cbaf41a2..52e2738a93 100644 --- a/tests/test-qmp-cmds.c +++ b/tests/test-qmp-cmds.c @@ -97,16 +97,15 @@ __org_qemu_x_Union1 *qmp___org_qemu_x_command(__org_qemu_x_EnumList *a, /* test commands with no input and no return value */ static void test_dispatch_cmd(void) { - QDict *req = qdict_new(); - QObject *resp; + QDict *resp, *req = qdict_new(); qdict_put_str(req, "execute", "user_def_cmd"); - resp = qmp_dispatch(&qmp_commands, QOBJECT(req)); + resp = qmp_dispatch(&qmp_commands, req); assert(resp != NULL); - assert(!qdict_haskey(qobject_to(QDict, resp), "error")); + assert(!qdict_haskey(resp, "error")); - qobject_decref(resp); + QDECREF(resp); QDECREF(req); } @@ -114,16 +113,15 @@ static void test_dispatch_cmd(void) static void test_dispatch_cmd_failure(void) { QDict *req = qdict_new(); - QDict *args = qdict_new(); - QObject *resp; + QDict *resp, *args = qdict_new(); qdict_put_str(req, "execute", "user_def_cmd2"); - resp = qmp_dispatch(&qmp_commands, QOBJECT(req)); + resp = qmp_dispatch(&qmp_commands, req); assert(resp != NULL); - assert(qdict_haskey(qobject_to(QDict, resp), "error")); + assert(qdict_haskey(resp, "error")); - qobject_decref(resp); + QDECREF(resp); QDECREF(req); /* check that with extra arguments it throws an error */ @@ -133,39 +131,35 @@ static void test_dispatch_cmd_failure(void) qdict_put_str(req, "execute", "user_def_cmd"); - resp = qmp_dispatch(&qmp_commands, QOBJECT(req)); + resp = qmp_dispatch(&qmp_commands, req); assert(resp != NULL); - assert(qdict_haskey(qobject_to(QDict, resp), "error")); + assert(qdict_haskey(resp, "error")); - qobject_decref(resp); + QDECREF(resp); QDECREF(req); } static void test_dispatch_cmd_success_response(void) { - QDict *req = qdict_new(); - QObject *resp; + QDict *resp, *req = qdict_new(); qdict_put_str(req, "execute", "cmd-success-response"); - resp = qmp_dispatch(&qmp_commands, QOBJECT(req)); + resp = qmp_dispatch(&qmp_commands, req); assert(resp == NULL); QDECREF(req); } static QObject *test_qmp_dispatch(QDict *req) { - QObject *resp_obj; QDict *resp; QObject *ret; - resp_obj = qmp_dispatch(&qmp_commands, QOBJECT(req)); - assert(resp_obj); - resp = qobject_to(QDict, resp_obj); + resp = qmp_dispatch(&qmp_commands, req); assert(resp && !qdict_haskey(resp, "error")); ret = qdict_get(resp, "return"); assert(ret); qobject_incref(ret); - qobject_decref(resp_obj); + QDECREF(resp); return ret; } From patchwork Mon Mar 26 15:08:54 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891060 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408yWD6S9Sz9s21 for ; Tue, 27 Mar 2018 02:20:08 +1100 (AEDT) Received: from localhost ([::1]:57324 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tuo-0005k1-9A for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:20:06 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55022) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0TlB-0005dX-5d for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:14 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0Tl7-0002xr-UB for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:09 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:52750 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0Tl7-0002xe-Og for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:05 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 6764E8182D2E; Mon, 26 Mar 2018 15:10:05 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8885910B0F20; Mon, 26 Mar 2018 15:09:59 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:08:54 +0200 Message-Id: <20180326150916.9602-17-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 26 Mar 2018 15:10:05 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 26 Mar 2018 15:10:05 +0000 (UTC) for IP:'10.11.54.3' DOMAIN:'int-mx03.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 16/38] qmp: move 'id' copy to qmp_dispatch() 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: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" This is convenient for other QMP users such as QGA and tests and simplifies a bit the qemu monitor code, and avoids modifying the request. Signed-off-by: Marc-André Lureau --- monitor.c | 23 ++++++----------------- qapi/qmp-dispatch.c | 5 +++++ tests/test-qmp-cmds.c | 17 +++++++++++++++++ 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/monitor.c b/monitor.c index 471c57e88c..ddcc3a5748 100644 --- a/monitor.c +++ b/monitor.c @@ -3899,16 +3899,9 @@ static int monitor_can_read(void *opaque) return !atomic_mb_read(&mon->suspend_cnt); } -/* take the ownership of rsp & id */ -static void monitor_qmp_respond(Monitor *mon, QDict *rsp, QObject *id) +/* take the ownership of rsp */ +static void monitor_qmp_respond(Monitor *mon, QDict *rsp) { - if (!rsp) { - return; - } - - if (id) { - qdict_put_obj(rsp, "id", id); - } if (mon->qmp.commands == &qmp_cap_negotiation_commands) { QDict *qdict = qdict_get_qdict(rsp, "error"); if (qdict @@ -3941,11 +3934,9 @@ static void monitor_qmp_dispatch_one(QMPRequest *req_obj) { Monitor *mon, *old_mon; QDict *req, *rsp = NULL; - QObject *id; req = req_obj->req; mon = req_obj->mon; - id = req_obj->id; g_free(req_obj); @@ -3963,7 +3954,9 @@ static void monitor_qmp_dispatch_one(QMPRequest *req_obj) cur_mon = old_mon; /* Respond if necessary */ - monitor_qmp_respond(mon, rsp, id); + if (rsp) { + monitor_qmp_respond(mon, rsp); + } QDECREF(req); @@ -4060,9 +4053,6 @@ static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens) goto err; } - qobject_incref(id); - qdict_del(qdict, "id"); - req_obj = g_new0(QMPRequest, 1); req_obj->mon = mon; req_obj->id = id; @@ -4094,7 +4084,6 @@ static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens) qapi_event_send_command_dropped(id, COMMAND_DROP_REASON_QUEUE_FULL, &error_abort); - qobject_decref(id); qobject_decref(req); g_free(req_obj); return; @@ -4117,7 +4106,7 @@ err: qdict = qdict_new(); qdict_put_obj(qdict, "error", qmp_build_error_object(err)); error_free(err); - monitor_qmp_respond(mon, qdict, id); + monitor_qmp_respond(mon, qdict); qobject_decref(req); } diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 66596b66a0..4be0648809 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -151,10 +151,15 @@ QDict *qmp_dispatch(QmpCommandList *cmds, QDict *req) Error *err = NULL; QObject *ret; QDict *rsp; + QObject *id = qdict_get(req, "id"); ret = do_qmp_dispatch(cmds, req, &err); rsp = qdict_new(); + if (id) { + qobject_incref(id); + qdict_put_obj(rsp, "id", id); + } if (err) { qdict_put_obj(rsp, "error", qmp_build_error_object(err)); error_free(err); diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c index 52e2738a93..58d948b01f 100644 --- a/tests/test-qmp-cmds.c +++ b/tests/test-qmp-cmds.c @@ -277,6 +277,22 @@ static void test_dealloc_partial(void) qapi_free_UserDefTwo(ud2); } +static void test_dispatch_cmd_id(void) +{ + QDict *resp, *req = qdict_new(); + + qdict_put_str(req, "execute", "user_def_cmd"); + qdict_put_str(req, "id", "ID42"); + + resp = qmp_dispatch(&qmp_commands, req); + assert(resp != NULL); + assert(!qdict_haskey(resp, "error")); + assert(!strcmp(qdict_get_str(resp, "id"), "ID42")); + + QDECREF(resp); + QDECREF(req); +} + int main(int argc, char **argv) { @@ -287,6 +303,7 @@ int main(int argc, char **argv) g_test_add_func("/qmp/dispatch_cmd_io", test_dispatch_cmd_io); g_test_add_func("/qmp/dispatch_cmd_success_response", test_dispatch_cmd_success_response); + g_test_add_func("/qmp/dispatch_cmd_id", test_dispatch_cmd_id); g_test_add_func("/qmp/dealloc_types", test_dealloc_types); g_test_add_func("/qmp/dealloc_partial", test_dealloc_partial); From patchwork Mon Mar 26 15:08:55 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891058 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408yV00n12z9s21 for ; Tue, 27 Mar 2018 02:19:04 +1100 (AEDT) Received: from localhost ([::1]:57318 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Ttl-0004kE-FH for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:19:01 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55021) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0TlB-0005dW-5Q for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:10 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0Tl9-0002yr-A3 for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:09 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:52756 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0Tl9-0002yW-5t for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:07 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id CE93A8182D2E; Mon, 26 Mar 2018 15:10:06 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7B3AE202699A; Mon, 26 Mar 2018 15:10:06 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:08:55 +0200 Message-Id: <20180326150916.9602-18-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 26 Mar 2018 15:10:06 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 26 Mar 2018 15:10:06 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 17/38] qmp: constify qmp_is_oob() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Marc-André Lureau --- include/qapi/qmp/dispatch.h | 2 +- qapi/qmp-dispatch.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h index 8e0ac29300..79fe7f18e0 100644 --- a/include/qapi/qmp/dispatch.h +++ b/include/qapi/qmp/dispatch.h @@ -49,7 +49,7 @@ const char *qmp_command_name(const QmpCommand *cmd); bool qmp_has_success_response(const QmpCommand *cmd); QObject *qmp_build_error_object(Error *err); QDict *qmp_dispatch_check_obj(const QObject *request, Error **errp); -bool qmp_is_oob(QDict *dict); +bool qmp_is_oob(const QDict *dict); typedef void (*qmp_cmd_callback_fn)(QmpCommand *cmd, void *opaque); diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 4be0648809..e8a14eb845 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -129,7 +129,7 @@ QObject *qmp_build_error_object(Error *err) * peeking at whether we have: { "control": { "run-oob": true } }. By * default commands are run in-band. */ -bool qmp_is_oob(QDict *dict) +bool qmp_is_oob(const QDict *dict) { QBool *bool_obj; From patchwork Mon Mar 26 15:08:56 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891062 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408yYm1ltTz9s2B for ; Tue, 27 Mar 2018 02:22:20 +1100 (AEDT) Received: from localhost ([::1]:57339 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Twv-0007l2-JJ for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:22:17 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55039) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0TlC-0005er-J9 for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:16 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0TlB-0002zY-1Y for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:10 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:36644 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0TlA-0002zK-Rj for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:08 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 7E1864270949; Mon, 26 Mar 2018 15:10:08 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1816B10B0F20; Mon, 26 Mar 2018 15:10:07 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:08:56 +0200 Message-Id: <20180326150916.9602-19-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 26 Mar 2018 15:10:08 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 26 Mar 2018 15:10:08 +0000 (UTC) for IP:'10.11.54.3' DOMAIN:'int-mx03.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 18/38] 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: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" This structure will hold various data related to a QMP session: the list of commands, the parser, the callbacks, the pending operations etc... Signed-off-by: Marc-André Lureau --- include/qapi/qmp/dispatch.h | 10 +++++++++- monitor.c | 20 +++++++++++--------- qapi/qmp-dispatch.c | 14 ++++++++++++-- qga/main.c | 6 ++++-- tests/test-qmp-cmds.c | 28 ++++++++++++++++++++++------ 5 files changed, 58 insertions(+), 20 deletions(-) diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h index 79fe7f18e0..10ba0745c7 100644 --- a/include/qapi/qmp/dispatch.h +++ b/include/qapi/qmp/dispatch.h @@ -36,11 +36,19 @@ typedef struct QmpCommand typedef QTAILQ_HEAD(QmpCommandList, QmpCommand) QmpCommandList; +typedef struct QmpSession QmpSession; + +struct QmpSession { + QmpCommandList *cmds; +}; + void qmp_register_command(QmpCommandList *cmds, const char *name, QmpCommandFunc *fn, QmpCommandOptions options); void qmp_unregister_command(QmpCommandList *cmds, const char *name); QmpCommand *qmp_find_command(QmpCommandList *cmds, const char *name); -QDict *qmp_dispatch(QmpCommandList *cmds, QDict *request); +void qmp_session_init(QmpSession *session, QmpCommandList *cmds); +void qmp_session_destroy(QmpSession *session); +QDict *qmp_dispatch(QmpSession *session, QDict *request); void qmp_disable_command(QmpCommandList *cmds, const char *name); void qmp_enable_command(QmpCommandList *cmds, const char *name); diff --git a/monitor.c b/monitor.c index ddcc3a5748..b90f8566c8 100644 --- a/monitor.c +++ b/monitor.c @@ -171,7 +171,7 @@ typedef struct { * When command qmp_capabilities succeeds, we go into command * mode. */ - QmpCommandList *commands; + QmpSession session; bool qmp_caps[QMP_CAPABILITY__MAX]; /* * Protects qmp request/response queue. Please take monitor_lock @@ -454,7 +454,7 @@ static void monitor_qapi_event_emit(QAPIEvent event, QDict *qdict) trace_monitor_protocol_event_emit(event, qdict); QTAILQ_FOREACH(mon, &mon_list, entry) { if (monitor_is_qmp(mon) - && mon->qmp.commands != &qmp_cap_negotiation_commands) { + && mon->qmp.session.cmds != &qmp_cap_negotiation_commands) { monitor_json_emitter(mon, QOBJECT(qdict)); } } @@ -624,6 +624,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); @@ -961,7 +962,7 @@ CommandInfoList *qmp_query_commands(Error **errp) { CommandInfoList *list = NULL; - qmp_for_each_command(cur_mon->qmp.commands, query_commands_cb, &list); + qmp_for_each_command(cur_mon->qmp.session.cmds, query_commands_cb, &list); return list; } @@ -1129,7 +1130,7 @@ static bool qmp_cmd_oob_check(Monitor *mon, QDict *req, Error **errp) return false; } - cmd = qmp_find_command(mon->qmp.commands, command); + cmd = qmp_find_command(mon->qmp.session.cmds, command); if (!cmd) { error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND, "The command %s has not been found", command); @@ -1157,7 +1158,7 @@ void qmp_qmp_capabilities(bool has_enable, QMPCapabilityList *enable, { Error *local_err = NULL; - if (cur_mon->qmp.commands == &qmp_commands) { + if (cur_mon->qmp.session.cmds == &qmp_commands) { error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND, "Capabilities negotiation is already complete, command " "ignored"); @@ -1179,7 +1180,7 @@ void qmp_qmp_capabilities(bool has_enable, QMPCapabilityList *enable, qmp_caps_apply(cur_mon, enable); } - cur_mon->qmp.commands = &qmp_commands; + cur_mon->qmp.session.cmds = &qmp_commands; } /* set the current CPU defined by the user */ @@ -3902,7 +3903,7 @@ static int monitor_can_read(void *opaque) /* take the ownership of rsp */ static void monitor_qmp_respond(Monitor *mon, QDict *rsp) { - if (mon->qmp.commands == &qmp_cap_negotiation_commands) { + if (mon->qmp.session.cmds == &qmp_cap_negotiation_commands) { QDict *qdict = qdict_get_qdict(rsp, "error"); if (qdict && !g_strcmp0(qdict_get_try_str(qdict, "class"), @@ -3949,7 +3950,7 @@ static void monitor_qmp_dispatch_one(QMPRequest *req_obj) old_mon = cur_mon; cur_mon = mon; - rsp = qmp_dispatch(mon->qmp.commands, req); + rsp = qmp_dispatch(&mon->qmp.session, req); cur_mon = old_mon; @@ -4222,7 +4223,7 @@ static void monitor_qmp_event(void *opaque, int event) switch (event) { case CHR_EVENT_OPENED: - mon->qmp.commands = &qmp_cap_negotiation_commands; + qmp_session_init(&mon->qmp.session, &qmp_cap_negotiation_commands); monitor_qmp_caps_reset(mon); data = get_qmp_greeting(mon); monitor_json_emitter(mon, data); @@ -4230,6 +4231,7 @@ static void monitor_qmp_event(void *opaque, int event) mon_refcount++; break; case CHR_EVENT_CLOSED: + qmp_session_destroy(&mon->qmp.session); json_message_parser_destroy(&mon->qmp.parser); json_message_parser_init(&mon->qmp.parser, handle_qmp_command); mon_refcount--; diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index e8a14eb845..7fd4e41b26 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -146,14 +146,24 @@ bool qmp_is_oob(const QDict *dict) return qbool_get_bool(bool_obj); } -QDict *qmp_dispatch(QmpCommandList *cmds, QDict *req) +void qmp_session_init(QmpSession *session, QmpCommandList *cmds) +{ + session->cmds = cmds; +} + +void qmp_session_destroy(QmpSession *session) +{ + session->cmds = NULL; +} + +QDict *qmp_dispatch(QmpSession *session, QDict *req) { Error *err = NULL; QObject *ret; QDict *rsp; QObject *id = qdict_get(req, "id"); - ret = do_qmp_dispatch(cmds, req, &err); + ret = do_qmp_dispatch(session->cmds, req, &err); rsp = qdict_new(); if (id) { diff --git a/qga/main.c b/qga/main.c index 04f7dad0b3..b5d7cc9e8f 100644 --- a/qga/main.c +++ b/qga/main.c @@ -71,6 +71,7 @@ typedef struct GAPersistentState { } GAPersistentState; struct GAState { + QmpSession session; JSONMessageParser parser; GMainLoop *main_loop; GAChannel *channel; @@ -603,7 +604,7 @@ static void process_event(JSONMessageParser *parser, GQueue *tokens) } g_debug("processing command"); - rsp = qmp_dispatch(&ga_commands, req); + rsp = qmp_dispatch(&s->session, req); end: if (err) { @@ -1304,7 +1305,7 @@ static int run_agent(GAState *s, GAConfig *config, int 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); - + qmp_session_init(&s->session, &ga_commands); #ifndef _WIN32 if (!register_signal_handlers()) { g_critical("failed to register signal handlers"); @@ -1424,6 +1425,7 @@ int main(int argc, char **argv) end: 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 58d948b01f..0c1fecb281 100644 --- a/tests/test-qmp-cmds.c +++ b/tests/test-qmp-cmds.c @@ -97,27 +97,32 @@ __org_qemu_x_Union1 *qmp___org_qemu_x_command(__org_qemu_x_EnumList *a, /* test commands with no input and no return value */ static void test_dispatch_cmd(void) { + QmpSession session = { 0, }; QDict *resp, *req = qdict_new(); + qmp_session_init(&session, &qmp_commands); qdict_put_str(req, "execute", "user_def_cmd"); - resp = qmp_dispatch(&qmp_commands, req); + resp = qmp_dispatch(&session, req); assert(resp != NULL); assert(!qdict_haskey(resp, "error")); QDECREF(resp); QDECREF(req); + qmp_session_destroy(&session); } /* test commands that return an error due to invalid parameters */ static void test_dispatch_cmd_failure(void) { + QmpSession session = { 0, }; QDict *req = qdict_new(); QDict *resp, *args = qdict_new(); + qmp_session_init(&session, &qmp_commands); qdict_put_str(req, "execute", "user_def_cmd2"); - resp = qmp_dispatch(&qmp_commands, req); + resp = qmp_dispatch(&session, req); assert(resp != NULL); assert(qdict_haskey(resp, "error")); @@ -131,35 +136,43 @@ static void test_dispatch_cmd_failure(void) qdict_put_str(req, "execute", "user_def_cmd"); - resp = qmp_dispatch(&qmp_commands, req); + resp = qmp_dispatch(&session, req); assert(resp != NULL); assert(qdict_haskey(resp, "error")); QDECREF(resp); QDECREF(req); + qmp_session_destroy(&session); } static void test_dispatch_cmd_success_response(void) { + QmpSession session = { 0, }; QDict *resp, *req = qdict_new(); + qmp_session_init(&session, &qmp_commands); qdict_put_str(req, "execute", "cmd-success-response"); - resp = qmp_dispatch(&qmp_commands, req); + resp = qmp_dispatch(&session, req); assert(resp == NULL); QDECREF(req); + qmp_session_destroy(&session); } + static QObject *test_qmp_dispatch(QDict *req) { + QmpSession session = { 0, }; QDict *resp; QObject *ret; - resp = qmp_dispatch(&qmp_commands, req); + qmp_session_init(&session, &qmp_commands); + resp = qmp_dispatch(&session, req); assert(resp && !qdict_haskey(resp, "error")); ret = qdict_get(resp, "return"); assert(ret); qobject_incref(ret); QDECREF(resp); + qmp_session_destroy(&session); return ret; } @@ -279,18 +292,21 @@ static void test_dealloc_partial(void) static void test_dispatch_cmd_id(void) { + QmpSession session = { 0, }; QDict *resp, *req = qdict_new(); + qmp_session_init(&session, &qmp_commands); qdict_put_str(req, "execute", "user_def_cmd"); qdict_put_str(req, "id", "ID42"); - resp = qmp_dispatch(&qmp_commands, req); + resp = qmp_dispatch(&session, req); assert(resp != NULL); assert(!qdict_haskey(resp, "error")); assert(!strcmp(qdict_get_str(resp, "id"), "ID42")); QDECREF(resp); QDECREF(req); + qmp_session_destroy(&session); } From patchwork Mon Mar 26 15:08:57 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891067 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408ydK4Flyz9s2B for ; Tue, 27 Mar 2018 02:25:25 +1100 (AEDT) Received: from localhost ([::1]:57352 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tzv-00023v-2P for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:25:23 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55098) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0TlL-0005o7-81 for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:21 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0TlC-00030T-La for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:19 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:48746 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0TlC-00030D-Gm for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:10 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 333524040074; Mon, 26 Mar 2018 15:10:10 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id 981B2202322B; Mon, 26 Mar 2018 15:10:09 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:08:57 +0200 Message-Id: <20180326150916.9602-20-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Mon, 26 Mar 2018 15:10:10 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Mon, 26 Mar 2018 15:10:10 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 19/38] QmpSession: add a 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: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" The introduced return_cb will allow to delay finishing the dispatch and sending the response asynchronously. For now, this is just modifying qmp_dispatch() to call the callback synchronously, and return void. Signed-off-by: Marc-André Lureau --- include/qapi/qmp/dispatch.h | 8 +++- monitor.c | 52 +++++++++++----------- qapi/qmp-dispatch.c | 19 ++++++-- qga/main.c | 25 ++++++----- tests/test-qmp-cmds.c | 86 ++++++++++++++++++------------------- 5 files changed, 101 insertions(+), 89 deletions(-) diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h index 10ba0745c7..7bf0b6a437 100644 --- a/include/qapi/qmp/dispatch.h +++ b/include/qapi/qmp/dispatch.h @@ -37,8 +37,10 @@ typedef struct QmpCommand typedef QTAILQ_HEAD(QmpCommandList, QmpCommand) QmpCommandList; typedef struct QmpSession QmpSession; +typedef void (QmpDispatchReturn) (QmpSession *session, QDict *rsp); struct QmpSession { + QmpDispatchReturn *return_cb; QmpCommandList *cmds; }; @@ -46,9 +48,11 @@ void qmp_register_command(QmpCommandList *cmds, const char *name, QmpCommandFunc *fn, QmpCommandOptions options); void qmp_unregister_command(QmpCommandList *cmds, const char *name); QmpCommand *qmp_find_command(QmpCommandList *cmds, const char *name); -void qmp_session_init(QmpSession *session, QmpCommandList *cmds); +void qmp_session_init(QmpSession *session, + QmpCommandList *cmds, QmpDispatchReturn *return_cb); + void qmp_session_destroy(QmpSession *session); -QDict *qmp_dispatch(QmpSession *session, QDict *request); +void qmp_dispatch(QmpSession *session, QDict *request); void qmp_disable_command(QmpCommandList *cmds, const char *name); void qmp_enable_command(QmpCommandList *cmds, const char *name); diff --git a/monitor.c b/monitor.c index b90f8566c8..93ecb03d04 100644 --- a/monitor.c +++ b/monitor.c @@ -3900,23 +3900,6 @@ static int monitor_can_read(void *opaque) return !atomic_mb_read(&mon->suspend_cnt); } -/* take the ownership of rsp */ -static void monitor_qmp_respond(Monitor *mon, QDict *rsp) -{ - if (mon->qmp.session.cmds == &qmp_cap_negotiation_commands) { - QDict *qdict = qdict_get_qdict(rsp, "error"); - if (qdict - && !g_strcmp0(qdict_get_try_str(qdict, "class"), - QapiErrorClass_str(ERROR_CLASS_COMMAND_NOT_FOUND))) { - /* Provide a more useful error message */ - qdict_put_str(qdict, "desc", "Expecting capabilities" - " negotiation with 'qmp_capabilities'"); - } - } - monitor_json_emitter(mon, QOBJECT(rsp)); - QDECREF(rsp); -} - struct QMPRequest { /* Owner of the request */ Monitor *mon; @@ -3927,6 +3910,24 @@ struct QMPRequest { }; typedef struct QMPRequest QMPRequest; +static void dispatch_return_cb(QmpSession *session, QDict *rsp) +{ + Monitor *mon = container_of(session, Monitor, qmp.session); + + if (mon->qmp.session.cmds == &qmp_cap_negotiation_commands) { + QDict *qdict = qdict = qdict_get_qdict(rsp, "error"); + if (qdict + && !g_strcmp0(qdict_get_try_str(qdict, "class"), + QapiErrorClass_str(ERROR_CLASS_COMMAND_NOT_FOUND))) { + /* Provide a more useful error message */ + qdict_put_str(qdict, "desc", "Expecting capabilities negotiation" + " with 'qmp_capabilities'"); + } + } + + monitor_json_emitter(mon, QOBJECT(rsp)); +} + /* * Dispatch one single QMP request. The function will free the req_obj * and objects inside it before return. @@ -3934,7 +3935,7 @@ typedef struct QMPRequest QMPRequest; static void monitor_qmp_dispatch_one(QMPRequest *req_obj) { Monitor *mon, *old_mon; - QDict *req, *rsp = NULL; + QDict *req; req = req_obj->req; mon = req_obj->mon; @@ -3950,16 +3951,9 @@ static void monitor_qmp_dispatch_one(QMPRequest *req_obj) old_mon = cur_mon; cur_mon = mon; - rsp = qmp_dispatch(&mon->qmp.session, req); + qmp_dispatch(&mon->qmp.session, req); cur_mon = old_mon; - - /* Respond if necessary */ - if (rsp) { - monitor_qmp_respond(mon, rsp); - } - - QDECREF(req); } @@ -4107,7 +4101,8 @@ err: qdict = qdict_new(); qdict_put_obj(qdict, "error", qmp_build_error_object(err)); error_free(err); - monitor_qmp_respond(mon, qdict); + monitor_json_emitter(mon, QOBJECT(qdict)); + QDECREF(qdict); qobject_decref(req); } @@ -4223,7 +4218,8 @@ 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); + qmp_session_init(&mon->qmp.session, + &qmp_cap_negotiation_commands, dispatch_return_cb); monitor_qmp_caps_reset(mon); data = get_qmp_greeting(mon); monitor_json_emitter(mon, data); diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 7fd4e41b26..5274aa59cc 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -146,17 +146,27 @@ bool qmp_is_oob(const QDict *dict) return qbool_get_bool(bool_obj); } -void qmp_session_init(QmpSession *session, QmpCommandList *cmds) +void qmp_session_init(QmpSession *session, + QmpCommandList *cmds, QmpDispatchReturn *return_cb) { + assert(return_cb); + assert(!session->return_cb); + session->cmds = cmds; + session->return_cb = return_cb; } void qmp_session_destroy(QmpSession *session) { + if (!session->return_cb) { + return; + } + session->cmds = NULL; + session->return_cb = NULL; } -QDict *qmp_dispatch(QmpSession *session, QDict *req) +void qmp_dispatch(QmpSession *session, QDict *req) { Error *err = NULL; QObject *ret; @@ -177,8 +187,9 @@ QDict *qmp_dispatch(QmpSession *session, QDict *req) qdict_put_obj(rsp, "return", ret); } else { QDECREF(rsp); - return NULL; + return; } - return rsp; + session->return_cb(session, rsp); + QDECREF(rsp); } diff --git a/qga/main.c b/qga/main.c index b5d7cc9e8f..46349395ba 100644 --- a/qga/main.c +++ b/qga/main.c @@ -580,14 +580,22 @@ static int send_response(GAState *s, QObject *payload) return 0; } +static void dispatch_return_cb(QmpSession *session, QDict *rsp) +{ + GAState *s = container_of(session, GAState, session); + int ret = send_response(s, QOBJECT(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(JSONMessageParser *parser, GQueue *tokens) { GAState *s = container_of(parser, GAState, parser); QObject *obj; - QDict *req, *rsp = NULL; + QDict *req; Error *err = NULL; - int ret; g_assert(s && parser); @@ -604,19 +612,14 @@ static void process_event(JSONMessageParser *parser, GQueue *tokens) } g_debug("processing command"); - rsp = qmp_dispatch(&s->session, req); + qmp_dispatch(&s->session, req); end: if (err) { - rsp = qdict_new(); + QDict *rsp = qdict_new(); qdict_put_obj(rsp, "error", qmp_build_error_object(err)); error_free(err); - } - if (rsp) { - ret = send_response(s, QOBJECT(rsp)); - if (ret < 0) { - g_warning("error sending error response: %s", strerror(-ret)); - } + dispatch_return_cb(&s->session, rsp); QDECREF(rsp); } qobject_decref(obj); @@ -1305,7 +1308,7 @@ static int run_agent(GAState *s, GAConfig *config, int 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); - qmp_session_init(&s->session, &ga_commands); + qmp_session_init(&s->session, &ga_commands, dispatch_return_cb); #ifndef _WIN32 if (!register_signal_handlers()) { g_critical("failed to register signal handlers"); diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c index 0c1fecb281..5e6e75b133 100644 --- a/tests/test-qmp-cmds.c +++ b/tests/test-qmp-cmds.c @@ -93,85 +93,83 @@ __org_qemu_x_Union1 *qmp___org_qemu_x_command(__org_qemu_x_EnumList *a, return ret; } +static void dispatch_cmd_return(QmpSession *session, QDict *resp) +{ + assert(resp != NULL); + assert(!qdict_haskey(resp, "error")); +} /* test commands with no input and no return value */ static void test_dispatch_cmd(void) { QmpSession session = { 0, }; - QDict *resp, *req = qdict_new(); + QDict *req = qdict_new(); - qmp_session_init(&session, &qmp_commands); + qmp_session_init(&session, &qmp_commands, dispatch_cmd_return); qdict_put_str(req, "execute", "user_def_cmd"); - - resp = qmp_dispatch(&session, req); - assert(resp != NULL); - assert(!qdict_haskey(resp, "error")); - - QDECREF(resp); + qmp_dispatch(&session, req); QDECREF(req); qmp_session_destroy(&session); } +static void dispatch_cmd_failure_return(QmpSession *session, QDict *resp) +{ + assert(resp != 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 = { 0, }; QDict *req = qdict_new(); - QDict *resp, *args = qdict_new(); + QDict *args = qdict_new(); - qmp_session_init(&session, &qmp_commands); + qmp_session_init(&session, &qmp_commands, dispatch_cmd_failure_return); qdict_put_str(req, "execute", "user_def_cmd2"); - - resp = qmp_dispatch(&session, req); - assert(resp != NULL); - assert(qdict_haskey(resp, "error")); - - QDECREF(resp); + qmp_dispatch(&session, req); QDECREF(req); /* check that with extra arguments it throws an error */ req = qdict_new(); qdict_put_int(args, "a", 66); qdict_put(req, "arguments", args); - qdict_put_str(req, "execute", "user_def_cmd"); - - resp = qmp_dispatch(&session, req); - assert(resp != NULL); - assert(qdict_haskey(resp, "error")); - - QDECREF(resp); + qmp_dispatch(&session, req); QDECREF(req); qmp_session_destroy(&session); } +static QObject *dispatch_ret; + static void test_dispatch_cmd_success_response(void) { QmpSession session = { 0, }; - QDict *resp, *req = qdict_new(); + QDict *req = qdict_new(); - qmp_session_init(&session, &qmp_commands); + qmp_session_init(&session, &qmp_commands, (QmpDispatchReturn *)abort); qdict_put_str(req, "execute", "cmd-success-response"); - resp = qmp_dispatch(&session, req); - assert(resp == NULL); + qmp_dispatch(&session, req); QDECREF(req); qmp_session_destroy(&session); } +static void dispatch_return(QmpSession *session, QDict *resp) +{ + assert(resp && !qdict_haskey(resp, "error")); + dispatch_ret = qdict_get(resp, "return"); + qobject_incref(dispatch_ret); +} static QObject *test_qmp_dispatch(QDict *req) { QmpSession session = { 0, }; - QDict *resp; QObject *ret; - qmp_session_init(&session, &qmp_commands); - resp = qmp_dispatch(&session, req); - assert(resp && !qdict_haskey(resp, "error")); - ret = qdict_get(resp, "return"); - assert(ret); - qobject_incref(ret); - QDECREF(resp); + qmp_session_init(&session, &qmp_commands, dispatch_return); + qmp_dispatch(&session, req); + ret = dispatch_ret; + dispatch_ret = NULL; qmp_session_destroy(&session); return ret; } @@ -290,21 +288,21 @@ static void test_dealloc_partial(void) qapi_free_UserDefTwo(ud2); } +static void dispatch_return_id42(QmpSession *session, QDict *resp) +{ + assert(!qdict_haskey(resp, "error")); + assert(!strcmp(qdict_get_str(resp, "id"), "ID42")); +} + static void test_dispatch_cmd_id(void) { QmpSession session = { 0, }; - QDict *resp, *req = qdict_new(); + QDict *req = qdict_new(); - qmp_session_init(&session, &qmp_commands); + qmp_session_init(&session, &qmp_commands, dispatch_return_id42); qdict_put_str(req, "execute", "user_def_cmd"); qdict_put_str(req, "id", "ID42"); - - resp = qmp_dispatch(&session, req); - assert(resp != NULL); - assert(!qdict_haskey(resp, "error")); - assert(!strcmp(qdict_get_str(resp, "id"), "ID42")); - - QDECREF(resp); + qmp_dispatch(&session, req); QDECREF(req); qmp_session_destroy(&session); } From patchwork Mon Mar 26 15:08:58 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891059 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408yVv1q35z9s2t for ; Tue, 27 Mar 2018 02:19:51 +1100 (AEDT) Received: from localhost ([::1]:57322 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0TuW-0005RR-MY for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:19:48 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55063) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0TlF-0005hg-Mx for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:20 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0TlE-00031O-6v for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:13 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:47498 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0TlE-000312-1P for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:12 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B0010401DE65; Mon, 26 Mar 2018 15:10:11 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3F8AD215CDAE; Mon, 26 Mar 2018 15:10:11 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:08:58 +0200 Message-Id: <20180326150916.9602-21-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Mon, 26 Mar 2018 15:10:11 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Mon, 26 Mar 2018 15:10:11 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 20/38] 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: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" 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 adressed in following patch to benefit more common code. Signed-off-by: Marc-André Lureau --- include/qapi/qmp/dispatch.h | 9 ++++++++ monitor.c | 7 ++----- qapi/qmp-dispatch.c | 32 +++++++++++++++++++++++++++++ qga/main.c | 41 +------------------------------------ 4 files changed, 44 insertions(+), 45 deletions(-) diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h index 7bf0b6a437..cd425b8574 100644 --- a/include/qapi/qmp/dispatch.h +++ b/include/qapi/qmp/dispatch.h @@ -15,6 +15,7 @@ #define QAPI_QMP_DISPATCH_H #include "qemu/queue.h" +#include "qapi/qmp/json-streamer.h" typedef void (QmpCommandFunc)(QDict *, QObject **, Error **); @@ -40,6 +41,7 @@ typedef struct QmpSession QmpSession; typedef void (QmpDispatchReturn) (QmpSession *session, QDict *rsp); struct QmpSession { + JSONMessageParser parser; QmpDispatchReturn *return_cb; QmpCommandList *cmds; }; @@ -48,9 +50,16 @@ void qmp_register_command(QmpCommandList *cmds, const char *name, QmpCommandFunc *fn, QmpCommandOptions options); void qmp_unregister_command(QmpCommandList *cmds, const char *name); QmpCommand *qmp_find_command(QmpCommandList *cmds, const char *name); + void qmp_session_init(QmpSession *session, 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_dispatch(QmpSession *session, QDict *request); void qmp_disable_command(QmpCommandList *cmds, const char *name); diff --git a/monitor.c b/monitor.c index 93ecb03d04..66046d4854 100644 --- a/monitor.c +++ b/monitor.c @@ -3934,11 +3934,8 @@ static void dispatch_return_cb(QmpSession *session, QDict *rsp) */ static void monitor_qmp_dispatch_one(QMPRequest *req_obj) { - Monitor *mon, *old_mon; - QDict *req; - - req = req_obj->req; - mon = req_obj->mon; + Monitor *old_mon, *mon = req_obj->mon; + QDict *req = req_obj->req; g_free(req_obj); diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 5274aa59cc..5352b25e90 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -146,12 +146,43 @@ bool qmp_is_oob(const QDict *dict) return qbool_get_bool(bool_obj); } +static void qmp_json_parser_emit(JSONMessageParser *parser, GQueue *tokens) +{ + QmpSession *session = container_of(parser, QmpSession, parser); + QObject *obj; + QDict *req; + Error *err = NULL; + + obj = json_parser_parse_err(tokens, NULL, &err); + if (err) { + goto end; + } + + req = qmp_dispatch_check_obj(obj, &err); + if (err) { + goto end; + } + + qmp_dispatch(session, req); + +end: + if (err) { + QDict *rsp = qdict_new(); + qdict_put_obj(rsp, "error", qmp_build_error_object(err)); + error_free(err); + session->return_cb(session, rsp); + QDECREF(rsp); + } + qobject_decref(obj); +} + void qmp_session_init(QmpSession *session, QmpCommandList *cmds, QmpDispatchReturn *return_cb) { assert(return_cb); assert(!session->return_cb); + json_message_parser_init(&session->parser, qmp_json_parser_emit); session->cmds = cmds; session->return_cb = return_cb; } @@ -164,6 +195,7 @@ void qmp_session_destroy(QmpSession *session) session->cmds = NULL; session->return_cb = NULL; + json_message_parser_destroy(&session->parser); } void qmp_dispatch(QmpSession *session, QDict *req) diff --git a/qga/main.c b/qga/main.c index 46349395ba..ce7efff3b4 100644 --- a/qga/main.c +++ b/qga/main.c @@ -72,7 +72,6 @@ typedef struct GAPersistentState { struct GAState { QmpSession session; - JSONMessageParser parser; GMainLoop *main_loop; GAChannel *channel; bool virtio; /* fastpath to check for virtio to deal with poll() quirks */ @@ -589,42 +588,6 @@ static void dispatch_return_cb(QmpSession *session, QDict *rsp) } } -/* handle requests/control events coming in over the channel */ -static void process_event(JSONMessageParser *parser, GQueue *tokens) -{ - GAState *s = container_of(parser, GAState, parser); - QObject *obj; - QDict *req; - Error *err = NULL; - - g_assert(s && parser); - - g_debug("process_event: called"); - - obj = json_parser_parse_err(tokens, NULL, &err); - if (err) { - goto end; - } - - req = qmp_dispatch_check_obj(obj, &err); - if (err) { - goto end; - } - - g_debug("processing command"); - qmp_dispatch(&s->session, req); - -end: - if (err) { - QDict *rsp = qdict_new(); - qdict_put_obj(rsp, "error", qmp_build_error_object(err)); - error_free(err); - dispatch_return_cb(&s->session, rsp); - QDECREF(rsp); - } - qobject_decref(obj); -} - /* false return signals GAChannel to close the current client connection */ static gboolean channel_event_cb(GIOCondition condition, gpointer data) { @@ -639,7 +602,7 @@ static gboolean channel_event_cb(GIOCondition condition, gpointer data) case G_IO_STATUS_NORMAL: buf[count] = 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, buf, count); break; case G_IO_STATUS_EOF: g_debug("received EOF"); @@ -1307,7 +1270,6 @@ static int run_agent(GAState *s, GAConfig *config, int socket_activation) s->command_state = 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); qmp_session_init(&s->session, &ga_commands, dispatch_return_cb); #ifndef _WIN32 if (!register_signal_handlers()) { @@ -1431,7 +1393,6 @@ end: 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); } if (s->channel) { ga_channel_free(s->channel); From patchwork Mon Mar 26 15:08:59 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891063 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408yZf2G75z9s2B for ; Tue, 27 Mar 2018 02:23:06 +1100 (AEDT) Received: from localhost ([::1]:57342 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Txf-0008Pz-Of for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:23:03 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55107) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0TlM-0005ps-7w for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:21 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0TlF-000329-Qe for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:20 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:36648 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0TlF-00031t-Lj for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:13 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4A6E44075392; Mon, 26 Mar 2018 15:10:13 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id D189F215CDAE; Mon, 26 Mar 2018 15:10:12 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:08:59 +0200 Message-Id: <20180326150916.9602-22-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 26 Mar 2018 15:10:13 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 26 Mar 2018 15:10:13 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 21/38] QmpSession: add a dispatch 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: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" In order to accomodate for QEMU monitor needs, allow to customize dispatching after JSON parsing. The default (for QGA and tests) can be simply qmp_dispatch(). Signed-off-by: Marc-André Lureau --- include/qapi/qmp/dispatch.h | 6 +++++- monitor.c | 4 +++- qapi/qmp-dispatch.c | 8 ++++++-- qga/main.c | 2 +- tests/test-qmp-cmds.c | 12 +++++++----- 5 files changed, 22 insertions(+), 10 deletions(-) diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h index cd425b8574..5329d0052a 100644 --- a/include/qapi/qmp/dispatch.h +++ b/include/qapi/qmp/dispatch.h @@ -38,10 +38,12 @@ typedef struct QmpCommand typedef QTAILQ_HEAD(QmpCommandList, QmpCommand) QmpCommandList; typedef struct QmpSession QmpSession; +typedef void (QmpDispatch) (QmpSession *session, QDict *request); typedef void (QmpDispatchReturn) (QmpSession *session, QDict *rsp); struct QmpSession { JSONMessageParser parser; + QmpDispatch *dispatch_cb; QmpDispatchReturn *return_cb; QmpCommandList *cmds; }; @@ -52,7 +54,9 @@ void qmp_unregister_command(QmpCommandList *cmds, const char *name); QmpCommand *qmp_find_command(QmpCommandList *cmds, const char *name); void qmp_session_init(QmpSession *session, - QmpCommandList *cmds, QmpDispatchReturn *return_cb); + QmpCommandList *cmds, + QmpDispatch *dispatch_cb, + QmpDispatchReturn *return_cb); static inline void qmp_session_feed(QmpSession *session, const char *buf, size_t count) diff --git a/monitor.c b/monitor.c index 66046d4854..ae8c055df0 100644 --- a/monitor.c +++ b/monitor.c @@ -4216,7 +4216,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, + NULL, /* XXX: not in use yet, but in following patch */ + dispatch_return_cb); monitor_qmp_caps_reset(mon); data = get_qmp_greeting(mon); monitor_json_emitter(mon, data); diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 5352b25e90..53d099d303 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -163,7 +163,7 @@ static void qmp_json_parser_emit(JSONMessageParser *parser, GQueue *tokens) goto end; } - qmp_dispatch(session, req); + session->dispatch_cb(session, req); end: if (err) { @@ -177,13 +177,16 @@ end: } void qmp_session_init(QmpSession *session, - QmpCommandList *cmds, QmpDispatchReturn *return_cb) + QmpCommandList *cmds, + QmpDispatch *dispatch_cb, + QmpDispatchReturn *return_cb) { assert(return_cb); assert(!session->return_cb); json_message_parser_init(&session->parser, qmp_json_parser_emit); session->cmds = cmds; + session->dispatch_cb = dispatch_cb; session->return_cb = return_cb; } @@ -194,6 +197,7 @@ void qmp_session_destroy(QmpSession *session) } session->cmds = NULL; + session->dispatch_cb = NULL; session->return_cb = NULL; json_message_parser_destroy(&session->parser); } diff --git a/qga/main.c b/qga/main.c index ce7efff3b4..dbb8f2cbbe 100644 --- a/qga/main.c +++ b/qga/main.c @@ -1270,7 +1270,7 @@ static int run_agent(GAState *s, GAConfig *config, int socket_activation) s->command_state = 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, qmp_dispatch, dispatch_return_cb); #ifndef _WIN32 if (!register_signal_handlers()) { g_critical("failed to register signal handlers"); diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c index 5e6e75b133..5246650f71 100644 --- a/tests/test-qmp-cmds.c +++ b/tests/test-qmp-cmds.c @@ -105,7 +105,7 @@ static void test_dispatch_cmd(void) QmpSession session = { 0, }; QDict *req = qdict_new(); - qmp_session_init(&session, &qmp_commands, dispatch_cmd_return); + qmp_session_init(&session, &qmp_commands, qmp_dispatch, dispatch_cmd_return); qdict_put_str(req, "execute", "user_def_cmd"); qmp_dispatch(&session, req); QDECREF(req); @@ -125,7 +125,8 @@ static void test_dispatch_cmd_failure(void) QDict *req = qdict_new(); QDict *args = qdict_new(); - qmp_session_init(&session, &qmp_commands, dispatch_cmd_failure_return); + qmp_session_init(&session, &qmp_commands, qmp_dispatch, + dispatch_cmd_failure_return); qdict_put_str(req, "execute", "user_def_cmd2"); qmp_dispatch(&session, req); QDECREF(req); @@ -147,7 +148,8 @@ static void test_dispatch_cmd_success_response(void) QmpSession session = { 0, }; QDict *req = qdict_new(); - qmp_session_init(&session, &qmp_commands, (QmpDispatchReturn *)abort); + qmp_session_init(&session, &qmp_commands, qmp_dispatch, + (QmpDispatchReturn *)abort); qdict_put_str(req, "execute", "cmd-success-response"); qmp_dispatch(&session, req); QDECREF(req); @@ -166,7 +168,7 @@ static QObject *test_qmp_dispatch(QDict *req) QmpSession session = { 0, }; QObject *ret; - qmp_session_init(&session, &qmp_commands, dispatch_return); + qmp_session_init(&session, &qmp_commands, qmp_dispatch, dispatch_return); qmp_dispatch(&session, req); ret = dispatch_ret; dispatch_ret = NULL; @@ -299,7 +301,7 @@ static void test_dispatch_cmd_id(void) QmpSession session = { 0, }; QDict *req = qdict_new(); - qmp_session_init(&session, &qmp_commands, dispatch_return_id42); + qmp_session_init(&session, &qmp_commands, qmp_dispatch, dispatch_return_id42); qdict_put_str(req, "execute", "user_def_cmd"); qdict_put_str(req, "id", "ID42"); qmp_dispatch(&session, req); From patchwork Mon Mar 26 15:09:00 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891069 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408yfB1XnCz9s37 for ; Tue, 27 Mar 2018 02:26:10 +1100 (AEDT) Received: from localhost ([::1]:57360 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0U0d-0002uk-IX for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:26:07 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55123) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0TlN-0005sf-P5 for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:22 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0TlH-00034y-RB for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:21 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:52760 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0TlH-00034V-Kt for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:15 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4B5798182D38; Mon, 26 Mar 2018 15:10:15 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id D3F2421A4699; Mon, 26 Mar 2018 15:10:14 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:09:00 +0200 Message-Id: <20180326150916.9602-23-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 26 Mar 2018 15:10:15 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 26 Mar 2018 15:10:15 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 22/38] monitor: use QmpSession parsing and common dispatch code X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" The previous patch allow to factorize some code out of monitor, and reuse the JSON parsing in QmpSession. Signed-off-by: Marc-André Lureau --- monitor.c | 50 ++++++++++++++++---------------------------------- 1 file changed, 16 insertions(+), 34 deletions(-) diff --git a/monitor.c b/monitor.c index ae8c055df0..94ad366c2d 100644 --- a/monitor.c +++ b/monitor.c @@ -58,8 +58,6 @@ #include "qapi/qmp/qnum.h" #include "qapi/qmp/qstring.h" #include "qapi/qmp/qjson.h" -#include "qapi/qmp/json-streamer.h" -#include "qapi/qmp/json-parser.h" #include "qapi/qmp/qlist.h" #include "qom/object_interfaces.h" #include "trace-root.h" @@ -625,7 +623,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); QDECREF(mon->outbuf); @@ -4011,32 +4008,20 @@ static void monitor_qmp_bh_dispatcher(void *data) #define QMP_REQ_QUEUE_LEN_MAX (8) -static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens) +static void qmp_dispatch_cb(QmpSession *session, QDict *req) { - QObject *req, *id = NULL; - QDict *qdict = NULL; - MonitorQMP *mon_qmp = container_of(parser, MonitorQMP, parser); - Monitor *mon = container_of(mon_qmp, Monitor, qmp); + QDict *rsp; + QObject *id; + Monitor *mon = container_of(session, Monitor, qmp.session); Error *err = NULL; QMPRequest *req_obj; - req = json_parser_parse_err(tokens, NULL, &err); - if (err) { - goto err; - } - - /* Check against the request in general layout */ - qdict = qmp_dispatch_check_obj(req, &err); - if (!qdict) { - goto err; - } - /* Check against OOB specific */ - if (!qmp_cmd_oob_check(mon, qdict, &err)) { + if (!qmp_cmd_oob_check(mon, req, &err)) { goto err; } - id = qdict_get(qdict, "id"); + id = qdict_get(req, "id"); /* When OOB is enabled, the "id" field is mandatory. */ if (qmp_oob_enabled(mon) && !id) { @@ -4045,12 +4030,13 @@ static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens) goto err; } + QINCREF(req); req_obj = g_new0(QMPRequest, 1); req_obj->mon = mon; req_obj->id = id; - req_obj->req = qdict; + req_obj->req = req; - if (qmp_is_oob(qdict)) { + if (qmp_is_oob(req)) { /* Out-Of-Band (OOB) requests are executed directly in parser. */ trace_monitor_qmp_cmd_out_of_band(qobject_get_try_str(req_obj->id) ?: ""); @@ -4076,7 +4062,7 @@ static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens) qapi_event_send_command_dropped(id, COMMAND_DROP_REASON_QUEUE_FULL, &error_abort); - qobject_decref(req); + QDECREF(req); g_free(req_obj); return; } @@ -4095,19 +4081,18 @@ static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens) return; err: - qdict = qdict_new(); - qdict_put_obj(qdict, "error", qmp_build_error_object(err)); + rsp = qdict_new(); + qdict_put_obj(rsp, "error", qmp_build_error_object(err)); error_free(err); - monitor_json_emitter(mon, QOBJECT(qdict)); - QDECREF(qdict); - qobject_decref(req); + monitor_json_emitter(mon, QOBJECT(rsp)); + QDECREF(rsp); } static void monitor_qmp_read(void *opaque, const uint8_t *buf, int size) { Monitor *mon = opaque; - json_message_parser_feed(&mon->qmp.parser, (const char *) buf, size); + qmp_session_feed(&mon->qmp.session, (const char *) buf, size); } static void monitor_read(void *opaque, const uint8_t *buf, int size) @@ -4217,7 +4202,7 @@ static void monitor_qmp_event(void *opaque, int event) case CHR_EVENT_OPENED: qmp_session_init(&mon->qmp.session, &qmp_cap_negotiation_commands, - NULL, /* XXX: not in use yet, but in following patch */ + qmp_dispatch_cb, dispatch_return_cb); monitor_qmp_caps_reset(mon); data = get_qmp_greeting(mon); @@ -4227,8 +4212,6 @@ static void monitor_qmp_event(void *opaque, int event) break; case CHR_EVENT_CLOSED: qmp_session_destroy(&mon->qmp.session); - json_message_parser_destroy(&mon->qmp.parser); - json_message_parser_init(&mon->qmp.parser, handle_qmp_command); mon_refcount--; monitor_fdsets_cleanup(); break; @@ -4429,7 +4412,6 @@ void monitor_init(Chardev *chr, int flags) if (monitor_is_qmp(mon)) { qemu_chr_fe_set_echo(&mon->chr, true); - json_message_parser_init(&mon->qmp.parser, handle_qmp_command); if (mon->use_io_thr) { /* * Make sure the old iowatch is gone. It's possible when From patchwork Mon Mar 26 15:09:01 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891073 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408yjd0Nmqz9s2B for ; Tue, 27 Mar 2018 02:29:09 +1100 (AEDT) Received: from localhost ([::1]:57377 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0U3W-0005Pc-FZ for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:29:06 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55164) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0TlT-0005zm-Mf for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:33 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0TlO-0003Ak-V9 for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:27 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:36656 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0TlO-0003AW-Pg for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:22 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 728DD4072CFD; Mon, 26 Mar 2018 15:10:22 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3301FD7DFA; Mon, 26 Mar 2018 15:10:17 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:09:01 +0200 Message-Id: <20180326150916.9602-24-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 26 Mar 2018 15:10:22 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 26 Mar 2018 15:10:22 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 23/38] 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: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" QmpReturn and associated functions are used internally for synchronous dispatch return for now. They will be used for returning in an asynchronous way, by holding the pre-prepared response, and having some bookkeeping in QmpSession. They also help to factor out a bit of code preparing the json reply and calling the return_cb. Signed-off-by: Marc-André Lureau --- include/qapi/qmp/dispatch.h | 33 +++++++++++++++++++ monitor.c | 7 +--- qapi/qmp-dispatch.c | 65 ++++++++++++++++++++++++------------- 3 files changed, 76 insertions(+), 29 deletions(-) diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h index 5329d0052a..7ca8ab17d9 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-streamer.h" +typedef struct QmpReturn QmpReturn; + typedef void (QmpCommandFunc)(QDict *, QObject **, Error **); typedef enum QmpCommandOptions @@ -48,6 +50,37 @@ struct QmpSession { QmpCommandList *cmds; }; +struct QmpReturn { + QmpSession *session; + QDict *rsp; +}; + +/* + * @qmp_return_new: + * + * Allocates and initializes a QmpReturn. + */ +QmpReturn *qmp_return_new(QmpSession *session, const QDict *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); void qmp_unregister_command(QmpCommandList *cmds, const char *name); diff --git a/monitor.c b/monitor.c index 94ad366c2d..73a06d4156 100644 --- a/monitor.c +++ b/monitor.c @@ -4010,7 +4010,6 @@ static void monitor_qmp_bh_dispatcher(void *data) static void qmp_dispatch_cb(QmpSession *session, QDict *req) { - QDict *rsp; QObject *id; Monitor *mon = container_of(session, Monitor, qmp.session); Error *err = NULL; @@ -4081,11 +4080,7 @@ static void qmp_dispatch_cb(QmpSession *session, QDict *req) return; err: - rsp = qdict_new(); - qdict_put_obj(rsp, "error", qmp_build_error_object(err)); - error_free(err); - monitor_json_emitter(mon, QOBJECT(rsp)); - QDECREF(rsp); + qmp_return_error(qmp_return_new(session, req), err); } static void monitor_qmp_read(void *opaque, const uint8_t *buf, int size) diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 53d099d303..7b57fa7987 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -19,6 +19,42 @@ #include "qapi/qmp/qjson.h" #include "qapi/qmp/qbool.h" +QmpReturn *qmp_return_new(QmpSession *session, const QDict *req) +{ + QmpReturn *qret = g_new0(QmpReturn, 1); + QObject *id = req ? qdict_get(req, "id") : NULL; + + qret->session = session; + qret->rsp = qdict_new(); + if (id) { + qobject_incref(id); + qdict_put_obj(qret->rsp, "id", id); + } + + return qret; +} + +void qmp_return_free(QmpReturn *qret) +{ + QDECREF(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", qmp_build_error_object(err)); + error_free(err); + qret->session->return_cb(qret->session, qret->rsp); + qmp_return_free(qret); +} + QDict *qmp_dispatch_check_obj(const QObject *request, Error **errp) { const QDictEntry *ent; @@ -150,7 +186,7 @@ static void qmp_json_parser_emit(JSONMessageParser *parser, GQueue *tokens) { QmpSession *session = container_of(parser, QmpSession, parser); QObject *obj; - QDict *req; + QDict *req = NULL; Error *err = NULL; obj = json_parser_parse_err(tokens, NULL, &err); @@ -167,11 +203,7 @@ static void qmp_json_parser_emit(JSONMessageParser *parser, GQueue *tokens) end: if (err) { - QDict *rsp = qdict_new(); - qdict_put_obj(rsp, "error", qmp_build_error_object(err)); - error_free(err); - session->return_cb(session, rsp); - QDECREF(rsp); + qmp_return_error(qmp_return_new(session, req), err); } qobject_decref(obj); } @@ -204,28 +236,15 @@ void qmp_session_destroy(QmpSession *session) void qmp_dispatch(QmpSession *session, QDict *req) { + QmpReturn *qret = qmp_return_new(session, req); Error *err = NULL; QObject *ret; - QDict *rsp; - QObject *id = qdict_get(req, "id"); ret = do_qmp_dispatch(session->cmds, req, &err); - - rsp = qdict_new(); - if (id) { - qobject_incref(id); - qdict_put_obj(rsp, "id", id); - } if (err) { - qdict_put_obj(rsp, "error", qmp_build_error_object(err)); - error_free(err); + assert(!ret); + qmp_return_error(qret, err); } else if (ret) { - qdict_put_obj(rsp, "return", ret); - } else { - QDECREF(rsp); - return; + qmp_return(qret, ret); } - - session->return_cb(session, rsp); - QDECREF(rsp); } From patchwork Mon Mar 26 15:09:02 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891064 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408yZy3b0lz9s2B for ; Tue, 27 Mar 2018 02:23:22 +1100 (AEDT) Received: from localhost ([::1]:57344 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Txv-0000At-V9 for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:23:20 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55166) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0TlT-0005zq-Of for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:28 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0TlQ-0003Bn-BD for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:27 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:52764 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0TlQ-0003BP-71 for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:24 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D6F848182D2A; Mon, 26 Mar 2018 15:10:23 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id 886262026985; Mon, 26 Mar 2018 15:10:23 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:09:02 +0200 Message-Id: <20180326150916.9602-25-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 26 Mar 2018 15:10:23 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 26 Mar 2018 15:10:23 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 24/38] qmp: remove qmp_build_error_object() 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: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Now that we have a single caller, we may as well fold the function. Signed-off-by: Marc-André Lureau --- include/qapi/qmp/dispatch.h | 1 - qapi/qmp-dispatch.c | 12 ++++-------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h index 7ca8ab17d9..c5ac3bd41e 100644 --- a/include/qapi/qmp/dispatch.h +++ b/include/qapi/qmp/dispatch.h @@ -105,7 +105,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); -QObject *qmp_build_error_object(Error *err); QDict *qmp_dispatch_check_obj(const QObject *request, Error **errp); bool qmp_is_oob(const QDict *dict); diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 7b57fa7987..c6089de616 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -49,7 +49,10 @@ void qmp_return(QmpReturn *qret, QObject *rsp) void qmp_return_error(QmpReturn *qret, Error *err) { - qdict_put_obj(qret->rsp, "error", qmp_build_error_object(err)); + qdict_put_obj(qret->rsp, "error", + qobject_from_jsonf("{ '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); @@ -153,13 +156,6 @@ static QObject *do_qmp_dispatch(QmpCommandList *cmds, QDict *dict, return ret; } -QObject *qmp_build_error_object(Error *err) -{ - return qobject_from_jsonf("{ 'class': %s, 'desc': %s }", - QapiErrorClass_str(error_get_class(err)), - error_get_pretty(err)); -} - /* * Detect whether a request should be run out-of-band, by quickly * peeking at whether we have: { "control": { "run-oob": true } }. By From patchwork Mon Mar 26 15:09:03 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891082 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408ytP6yQ3z9s2t for ; Tue, 27 Mar 2018 02:36:45 +1100 (AEDT) Received: from localhost ([::1]:57420 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0UAt-0003zt-9D for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:36:43 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55241) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tlc-00068H-Fj for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:37 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0TlW-0003FJ-R2 for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:36 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:36666 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0TlW-0003Ez-M6 for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:30 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 57B6B42EF0DA; Mon, 26 Mar 2018 15:10:30 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id E89A010B0F20; Mon, 26 Mar 2018 15:10:24 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:09:03 +0200 Message-Id: <20180326150916.9602-26-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 26 Mar 2018 15:10:30 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 26 Mar 2018 15:10:30 +0000 (UTC) for IP:'10.11.54.3' DOMAIN:'int-mx03.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 25/38] qmp: remove need for qobject_from_jsonf() 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: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Marc-André Lureau --- qapi/qmp-dispatch.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index c6089de616..92079c0621 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -49,10 +49,11 @@ void qmp_return(QmpReturn *qret, QObject *rsp) void qmp_return_error(QmpReturn *qret, Error *err) { - qdict_put_obj(qret->rsp, "error", - qobject_from_jsonf("{ 'class': %s, 'desc': %s }", - QapiErrorClass_str(error_get_class(err)), - error_get_pretty(err))); + QDict *qdict = 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); From patchwork Mon Mar 26 15:09:04 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891077 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408yn744g2z9s2B for ; Tue, 27 Mar 2018 02:32:11 +1100 (AEDT) Received: from localhost ([::1]:57393 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0U6T-00081L-2z for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:32:09 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55209) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0TlZ-00065Y-Jg for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0TlY-0003GI-J5 for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:33 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:57280 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0TlY-0003Fs-2w for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:32 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B8376A27EB; Mon, 26 Mar 2018 15:10:31 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id 67A6A215CDAE; Mon, 26 Mar 2018 15:10:31 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:09:04 +0200 Message-Id: <20180326150916.9602-27-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Mon, 26 Mar 2018 15:10:31 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Mon, 26 Mar 2018 15:10:31 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 26/38] qmp: fold do_qmp_dispatch() in qmp_dispatch() 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: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" qmp_dispatch() is now a simple wrapper for do_qmp_dispatch(). In order to prepare for following asynchronous function, merge the two functions, which result in less code. Signed-off-by: Marc-André Lureau --- qapi/qmp-dispatch.c | 62 ++++++++++++++++++--------------------------- 1 file changed, 25 insertions(+), 37 deletions(-) diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 92079c0621..4a73cf88b3 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -114,47 +114,50 @@ QDict *qmp_dispatch_check_obj(const QObject *request, Error **errp) return dict; } -static QObject *do_qmp_dispatch(QmpCommandList *cmds, QDict *dict, - Error **errp) +void qmp_dispatch(QmpSession *session, QDict *req) { - Error *local_err = NULL; const char *command; - QDict *args; + QDict *args = NULL; QmpCommand *cmd; - QObject *ret = NULL; + Error *err = NULL; - command = qdict_get_str(dict, "execute"); - cmd = qmp_find_command(cmds, command); + command = qdict_get_str(req, "execute"); + cmd = qmp_find_command(session->cmds, command); if (cmd == NULL) { - error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND, + error_set(&err, ERROR_CLASS_COMMAND_NOT_FOUND, "The command %s has not been found", command); - return NULL; + goto end; } if (!cmd->enabled) { - error_setg(errp, "The command %s has been disabled for this instance", + error_setg(&err, "The command %s has been disabled for this instance", command); - return NULL; + goto end; } - if (!qdict_haskey(dict, "arguments")) { + if (!qdict_haskey(req, "arguments")) { args = qdict_new(); } else { - args = qdict_get_qdict(dict, "arguments"); + args = qdict_get_qdict(req, "arguments"); QINCREF(args); } - 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) { - ret = QOBJECT(qdict_new()); + { + QObject *ret = NULL; + cmd->fn(args, &ret, &err); + if (err || cmd->options & QCO_NO_SUCCESS_RESP) { + assert(!ret); + goto end; + } else if (!ret) { + ret = QOBJECT(qdict_new()); + } + qmp_return(qmp_return_new(session, req), ret); } +end: + if (err) { + qmp_return_error(qmp_return_new(session, req), err); + } QDECREF(args); - - return ret; } /* @@ -230,18 +233,3 @@ void qmp_session_destroy(QmpSession *session) session->return_cb = NULL; json_message_parser_destroy(&session->parser); } - -void qmp_dispatch(QmpSession *session, QDict *req) -{ - QmpReturn *qret = qmp_return_new(session, req); - Error *err = NULL; - QObject *ret; - - ret = do_qmp_dispatch(session->cmds, req, &err); - if (err) { - assert(!ret); - qmp_return_error(qret, err); - } else if (ret) { - qmp_return(qret, ret); - } -} From patchwork Mon Mar 26 15:09:05 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891074 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408yk62tSBz9s2B for ; Tue, 27 Mar 2018 02:29:34 +1100 (AEDT) Received: from localhost ([::1]:57378 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0U3v-0005r7-Py for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:29:31 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55244) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tlc-00068Z-Ps for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:37 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0Tla-0003Hm-98 for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:36 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:52772 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0TlZ-0003HU-W1 for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:34 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9EC0F82F33BB; Mon, 26 Mar 2018 15:10:33 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id 401FD215CDAE; Mon, 26 Mar 2018 15:10:32 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:09:05 +0200 Message-Id: <20180326150916.9602-28-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 26 Mar 2018 15:10:33 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Mon, 26 Mar 2018 15:10:33 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 27/38] 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: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" The following commit will introduce asynchronous commands. Let's keep the client 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 QmpSession may be used from multiple threads. Signed-off-by: Marc-André 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 c5ac3bd41e..94a272a5fb 100644 --- a/include/qapi/qmp/dispatch.h +++ b/include/qapi/qmp/dispatch.h @@ -15,6 +15,7 @@ #define QAPI_QMP_DISPATCH_H #include "qemu/queue.h" +#include "qemu/thread.h" #include "qapi/qmp/json-streamer.h" typedef struct QmpReturn QmpReturn; @@ -48,11 +49,14 @@ struct QmpSession { QmpDispatch *dispatch_cb; QmpDispatchReturn *return_cb; QmpCommandList *cmds; + QemuMutex pending_lock; + QTAILQ_HEAD(, QmpReturn) pending; }; struct QmpReturn { QmpSession *session; QDict *rsp; + QTAILQ_ENTRY(QmpReturn) entry; }; /* diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 4a73cf88b3..2c162642cb 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -31,11 +31,24 @@ QmpReturn *qmp_return_new(QmpSession *session, const QDict *req) qdict_put_obj(qret->rsp, "id", id); } + qemu_mutex_lock(&session->pending_lock); + QTAILQ_INSERT_TAIL(&session->pending, qret, entry); + qemu_mutex_unlock(&session->pending_lock); + return qret; } void qmp_return_free(QmpReturn *qret) { + QmpSession *session = qret->session; + + if (session) { + qemu_mutex_lock(&session->pending_lock); + } + QTAILQ_REMOVE(&session->pending, qret, entry); + if (session) { + qemu_mutex_unlock(&session->pending_lock); + } QDECREF(qret->rsp); g_free(qret); } @@ -43,7 +56,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); } @@ -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); } @@ -220,16 +237,27 @@ void qmp_session_init(QmpSession *session, session->cmds = cmds; session->dispatch_cb = dispatch_cb; session->return_cb = return_cb; + qemu_mutex_init(&session->pending_lock); + QTAILQ_INIT(&session->pending); } void qmp_session_destroy(QmpSession *session) { + QmpReturn *ret, *next; + if (!session->return_cb) { return; } + qemu_mutex_lock(&session->pending_lock); + QTAILQ_FOREACH_SAFE(ret, &session->pending, entry, next) { + ret->session = NULL; + QTAILQ_REMOVE(&session->pending, ret, entry); + } + qemu_mutex_unlock(&session->pending_lock); session->cmds = NULL; session->dispatch_cb = NULL; session->return_cb = NULL; json_message_parser_destroy(&session->parser); + qemu_mutex_destroy(&session->pending_lock); } From patchwork Mon Mar 26 15:09:06 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891075 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408ykD4sjxz9s2B for ; Tue, 27 Mar 2018 02:29:40 +1100 (AEDT) Received: from localhost ([::1]:57380 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0U42-0005uf-5h for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:29:38 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55267) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tld-00069Y-R3 for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:43 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0Tlc-0003JC-Dk for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:37 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:38356 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0Tlc-0003IV-2T for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:36 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B0E99EBFFE; Mon, 26 Mar 2018 15:10:35 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id 48FDE10B0F20; Mon, 26 Mar 2018 15:10:35 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:09:06 +0200 Message-Id: <20180326150916.9602-29-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Mon, 26 Mar 2018 15:10:35 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Mon, 26 Mar 2018 15:10:35 +0000 (UTC) for IP:'10.11.54.3' DOMAIN:'int-mx03.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 28/38] 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: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" 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é Lureau --- include/qapi/qmp/dispatch.h | 1 + qapi/qmp-dispatch.c | 59 ++++++++++++++++++++++++++++++------- tests/test-qmp-cmds.c | 36 ++++++++++++++++++++++ 3 files changed, 85 insertions(+), 11 deletions(-) diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h index 94a272a5fb..f6db06c164 100644 --- a/include/qapi/qmp/dispatch.h +++ b/include/qapi/qmp/dispatch.h @@ -56,6 +56,7 @@ struct QmpSession { struct QmpReturn { QmpSession *session; QDict *rsp; + bool oob; QTAILQ_ENTRY(QmpReturn) entry; }; diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 2c162642cb..aa8b71a2c0 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -24,6 +24,7 @@ QmpReturn *qmp_return_new(QmpSession *session, const QDict *req) QmpReturn *qret = g_new0(QmpReturn, 1); QObject *id = req ? qdict_get(req, "id") : NULL; + qret->oob = req ? qmp_is_oob(req) : false; qret->session = session; qret->rsp = qdict_new(); if (id) { @@ -38,6 +39,15 @@ QmpReturn *qmp_return_new(QmpSession *session, const QDict *req) return qret; } +static void qmp_return_free_with_lock(QmpReturn *qret) +{ + if (qret->session) { + QTAILQ_REMOVE(&qret->session->pending, qret, entry); + } + QDECREF(qret->rsp); + g_free(qret); +} + void qmp_return_free(QmpReturn *qret) { QmpSession *session = qret->session; @@ -45,21 +55,51 @@ 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); } - QDECREF(qret->rsp); - g_free(qret); +} + +static void qmp_return_orderly(QmpReturn *qret) +{ + QmpSession *session = qret->session; + QmpReturn *ret, *next; + + if (!session) { + /* the client was destroyed before return, discard */ + qmp_return_free(qret); + return; + } + if (qret->oob) { + session->return_cb(session, qret->rsp); + qmp_return_free(qret); + return; + } + + /* mark as finished */ + qret->session = NULL; + + qemu_mutex_lock(&session->pending_lock); + /* process the list of pending and return until reaching an unfinshed */ + QTAILQ_FOREACH_SAFE(ret, &session->pending, entry, next) { + if (ret->session) { + goto end; + } + session->return_cb(session, ret->rsp); + ret->session = session; + qmp_return_free_with_lock(ret); + } +end: + qemu_mutex_unlock(&session->pending_lock); } 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); } void qmp_return_error(QmpReturn *qret, Error *err) @@ -70,10 +110,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); } QDict *qmp_dispatch_check_obj(const QObject *request, Error **errp) diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c index 5246650f71..eeaac03d50 100644 --- a/tests/test-qmp-cmds.c +++ b/tests/test-qmp-cmds.c @@ -309,6 +309,41 @@ static void test_dispatch_cmd_id(void) qmp_session_destroy(&session); } +typedef struct QmpReturnOrderly { + QmpSession session; + int returns; +} QmpReturnOrderly; + +static void dispatch_return_orderly(QmpSession *session, QDict *resp) +{ + QmpReturnOrderly *o = container_of(session, QmpReturnOrderly, session); + + o->returns++; +} + +static void test_qmp_return_orderly(void) +{ + QDict *dict = qdict_new(); + QDict *ctrl = qdict_new(); + QmpReturnOrderly o = { 0, }; + QmpReturn *r1, *r2, *r3; + + qmp_session_init(&o.session, &qmp_commands, + qmp_dispatch, dispatch_return_orderly); + r1 = qmp_return_new(&o.session, NULL); + qdict_put_bool(ctrl, "run-oob", true); + qdict_put_obj(dict, "control", QOBJECT(ctrl)); + r2 = qmp_return_new(&o.session, dict); + r3 = qmp_return_new(&o.session, NULL); + qmp_return(r3, NULL); + g_assert_cmpint(o.returns, ==, 0); + qmp_return(r2, NULL); + g_assert_cmpint(o.returns, ==, 1); + qmp_return(r1, NULL); + g_assert_cmpint(o.returns, ==, 3); + qmp_session_destroy(&o.session); + QDECREF(dict); +} int main(int argc, char **argv) { @@ -322,6 +357,7 @@ int main(int argc, char **argv) g_test_add_func("/qmp/dispatch_cmd_id", test_dispatch_cmd_id); 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); test_qmp_init_marshal(&qmp_commands); g_test_run(); From patchwork Mon Mar 26 15:09:07 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891079 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408ynx3hd4z9s2B for ; Tue, 27 Mar 2018 02:32:53 +1100 (AEDT) Received: from localhost ([::1]:57397 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0U79-0000Jt-0X for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:32:51 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55320) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tlj-0006GZ-Sp for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:47 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0Tld-0003KS-Sm for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:43 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:48776 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0Tld-0003K4-J3 for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:37 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 3CB0C406FA25; Mon, 26 Mar 2018 15:10:37 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id C52FF10B0F20; Mon, 26 Mar 2018 15:10:36 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:09:07 +0200 Message-Id: <20180326150916.9602-30-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Mon, 26 Mar 2018 15:10:37 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Mon, 26 Mar 2018 15:10:37 +0000 (UTC) for IP:'10.11.54.3' DOMAIN:'int-mx03.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 29/38] 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: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" 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(). Signed-off-by: Marc-André Lureau --- include/qapi/qmp/dispatch.h | 9 ++++++++- qapi/qmp-dispatch.c | 4 +++- qapi/qmp-registry.c | 27 ++++++++++++++++++++++++--- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h index f6db06c164..e426317346 100644 --- a/include/qapi/qmp/dispatch.h +++ b/include/qapi/qmp/dispatch.h @@ -21,18 +21,23 @@ typedef struct QmpReturn QmpReturn; typedef void (QmpCommandFunc)(QDict *, QObject **, Error **); +typedef void (QmpCommandAsyncFunc)(QDict *, QmpReturn *); typedef enum QmpCommandOptions { QCO_NO_OPTIONS = 0x0, QCO_NO_SUCCESS_RESP = (1U << 0), QCO_ALLOW_OOB = (1U << 1), + QCO_ASYNC = (1U << 2), } QmpCommandOptions; 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,8 @@ void qmp_return_error(QmpReturn *qret, Error *err); 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); void qmp_unregister_command(QmpCommandList *cmds, const char *name); QmpCommand *qmp_find_command(QmpCommandList *cmds, const char *name); diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index aa8b71a2c0..f7d9931734 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -195,7 +195,9 @@ void qmp_dispatch(QmpSession *session, QDict *req) QINCREF(args); } - { + if (cmd->options & QCO_ASYNC) { + cmd->async_fn(args, qmp_return_new(session, req)); + } else { QObject *ret = NULL; cmd->fn(args, &ret, &err); if (err || cmd->options & QCO_NO_SUCCESS_RESP) { diff --git a/qapi/qmp-registry.c b/qapi/qmp-registry.c index 5af484cd9a..180b1c1e69 100644 --- a/qapi/qmp-registry.c +++ b/qapi/qmp-registry.c @@ -15,16 +15,37 @@ #include "qemu/osdep.h" #include "qapi/qmp/dispatch.h" -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 = g_malloc0(sizeof(*cmd)); cmd->name = name; - cmd->fn = fn; cmd->enabled = true; cmd->options = options; QTAILQ_INSERT_TAIL(cmds, cmd, node); + + return cmd; +} + + +void qmp_register_command(QmpCommandList *cmds, const char *name, + QmpCommandFunc *fn, QmpCommandOptions options) +{ + QmpCommand *cmd = qmp_command_new(cmds, name, options); + + assert(!(options & QCO_ASYNC)); + cmd->fn = fn; +} + +void qmp_register_async_command(QmpCommandList *cmds, const char *name, + QmpCommandAsyncFunc *fn, QmpCommandOptions options) +{ + QmpCommand *cmd = qmp_command_new(cmds, name, options); + + assert(options & QCO_ASYNC); + cmd->async_fn = fn; } void qmp_unregister_command(QmpCommandList *cmds, const char *name) From patchwork Mon Mar 26 15:09:08 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891070 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408yfn27yLz9s2B for ; Tue, 27 Mar 2018 02:26:41 +1100 (AEDT) Received: from localhost ([::1]:57363 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0U18-0003LH-PM for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:26:38 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55306) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tlh-0006Da-Ps for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:43 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0Tlf-0003LY-Ju for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:41 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:36674 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0Tlf-0003L3-Dt for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:39 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 1116842BE1D7; Mon, 26 Mar 2018 15:10:39 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7FC0D10B0F20; Mon, 26 Mar 2018 15:10:38 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:09:08 +0200 Message-Id: <20180326150916.9602-31-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 26 Mar 2018 15:10:39 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 26 Mar 2018 15:10:39 +0000 (UTC) for IP:'10.11.54.3' DOMAIN:'int-mx03.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 30/38] 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: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" 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 (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 = NULL; Visitor *v; q_obj_foo_async_arg arg = {0}; v = 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 = 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 return helper: void qmp_foo_async_return(QmpReturn *qret, Foo *ret_in) { Error *err = NULL; QObject *ret_out = 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 should call qmp_return_error(). Signed-off-by: Marc-André Lureau --- scripts/qapi/commands.py | 149 ++++++++++++++++++++---- scripts/qapi/common.py | 12 +- scripts/qapi/doc.py | 2 +- scripts/qapi/introspect.py | 2 +- 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 | 7 +- 8 files changed, 210 insertions(+), 35 deletions(-) mode change 100644 => 100755 scripts/qapi/doc.py diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py index 0c5da3a54d..a292164169 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 * -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, async): + if async: + extra = "QmpReturn *qret" + else: + extra = 'Error **errp' + + if async: + ret = mcgen(''' +void qmp_%(name)s(%(params)s); ''', - c_type=(ret_type and ret_type.c_type()) or 'void', - c_name=c_name(name), - params=build_params(arg_type, boxed, 'Error **errp')) + name=c_name(name), + params=build_params(arg_type, boxed, extra)) + if success_response: + ret += mcgen(''' +void qmp_%(name)s_return(QmpReturn *qret%(c_type)s); +''', + c_type=(", " + ret_type.c_type() if ret_type else ""), + name=c_name(name)) + return ret + else: + return mcgen(''' +%(c_type)s qmp_%(c_name)s(%(params)s); +''', + c_type=(ret_type and ret_type.c_type()) or 'void', + c_name=c_name(name), + params=build_params(arg_type, boxed, extra)) -def gen_call(name, arg_type, boxed, ret_type): - ret = '' +def gen_argstr(arg_type, boxed): argstr = '' 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 += 'arg.has_%s, ' % c_name(memb.name) argstr += 'arg.%s, ' % c_name(memb.name) + return argstr + + +def gen_call(name, arg_type, boxed, ret_type): + ret = '' + + argstr = gen_argstr(arg_type, boxed) lhs = '' if ret_type: lhs = 'retval = ' @@ -60,6 +85,50 @@ def gen_call(name, arg_type, boxed, ret_type): return ret +def gen_async_call(name, arg_type, boxed): + argstr = gen_argstr(arg_type, boxed) + + push_indent() + ret = mcgen(''' + +qmp_%(c_name)s(%(args)sqret); +''', + c_name=c_name(name), args=argstr) + + 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 = NULL; + QObject *ret_out = 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=c_name(name), + ret_type=ret_type.c_type(), ret_c_name=ret_type.c_name()) + else: + return mcgen(''' + +void qmp_%(c_name)s_return(QmpReturn *qret) +{ + qmp_return(qret, QOBJECT(qdict_new())); +} +''', + c_name=c_name(name)) + def gen_marshal_output(ret_type): return mcgen(''' @@ -83,19 +152,22 @@ static void qmp_marshal_output_%(c_name)s(%(c_type)s ret_in, QObject **ret_out, c_type=ret_type.c_type(), c_name=ret_type.c_name()) -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 = 'void qmp_marshal_%s(QDict *args, QmpReturn *qret)' + else: + tmpl = 'void qmp_marshal_%s(QDict *args, QObject **ret, Error **errp)' + return tmpl % c_name(name) -def gen_marshal_decl(name): +def gen_marshal_decl(name, async): return mcgen(''' %(proto)s; ''', - proto=build_marshal_proto(name)) + proto=build_marshal_proto(name, async)) -def gen_marshal(name, arg_type, boxed, ret_type): +def gen_marshal(name, arg_type, boxed, ret_type, async): have_args = arg_type and not arg_type.is_empty() ret = mcgen(''' @@ -104,9 +176,9 @@ def gen_marshal(name, arg_type, boxed, ret_type): { Error *err = NULL; ''', - proto=build_marshal_proto(name)) + proto=build_marshal_proto(name, async)) - if ret_type: + if ret_type and not async: ret += mcgen(''' %(c_type)s retval; ''', @@ -153,12 +225,28 @@ def gen_marshal(name, arg_type, boxed, ret_type): } ''') - ret += gen_call(name, arg_type, boxed, ret_type) + if async: + ret += gen_async_call(name, arg_type, boxed) + else: + ret += gen_call(name, arg_type, boxed, ret_type) ret += mcgen(''' out: +''') + + if async: + ret += mcgen(''' + if (err) { + qmp_return_error(qret, err); + } +''') + else: + ret += mcgen(''' error_propagate(errp, err); +''') + + ret += mcgen(''' visit_free(v); ''') @@ -193,24 +281,31 @@ out: return ret -def gen_register_command(name, success_response, allow_oob): +def gen_register_command(name, success_response, allow_oob, async): options = [] if not success_response: options += ['QCO_NO_SUCCESS_RESP'] if allow_oob: options += ['QCO_ALLOW_OOB'] + if async: + options += ['QCO_ASYNC'] if not options: options = ['QCO_NO_OPTIONS'] options = " | ".join(options) + if async: + regfn = 'qmp_register_async_command' + else: + regfn = 'qmp_register_command' + ret = mcgen(''' - qmp_register_command(cmds, "%(name)s", + %(regfn)s(cmds, "%(name)s", qmp_marshal_%(c_name)s, %(opts)s); ''', - name=name, c_name=c_name(name), + regfn=regfn, name=name, c_name=c_name(name), opts=options) return ret @@ -276,16 +371,20 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds); genc.add(gen_registry(self._regy, self._prefix)) def visit_command(self, name, info, arg_type, ret_type, - gen, success_response, boxed, allow_oob): + gen, success_response, boxed, allow_oob, async): if not gen: return - self._genh.add(gen_command_decl(name, arg_type, boxed, ret_type)) + self._genh.add(gen_command_decl(name, arg_type, boxed, ret_type, + success_response, async)) if ret_type and ret_type not in self._visited_ret_types[self._genc]: self._visited_ret_types[self._genc].add(ret_type) self._genc.add(gen_marshal_output(ret_type)) - self._genh.add(gen_marshal_decl(name)) - self._genc.add(gen_marshal(name, arg_type, boxed, ret_type)) - self._regy += gen_register_command(name, success_response, allow_oob) + if async and success_response: + self._genc.add(gen_async_return(name, ret_type)) + self._genh.add(gen_marshal_decl(name, async)) + self._genc.add(gen_marshal(name, arg_type, boxed, ret_type, async)) + self._regy += gen_register_command(name, success_response, + allow_oob, async) def gen_commands(schema, output_dir, prefix): diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index 2c05e3c284..109562ccb4 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -922,7 +922,7 @@ def check_exprs(exprs): meta = 'command' check_keys(expr_elem, 'command', [], ['data', 'returns', 'gen', 'success-response', - 'boxed', 'allow-oob']) + 'boxed', 'allow-oob', 'async']) elif 'event' in expr: meta = 'event' check_keys(expr_elem, 'event', [], ['data', 'boxed']) @@ -1045,7 +1045,7 @@ class QAPISchemaVisitor(object): pass def visit_command(self, name, info, arg_type, ret_type, - gen, success_response, boxed, allow_oob): + gen, success_response, boxed, allow_oob, async): pass def visit_event(self, name, info, arg_type, boxed): @@ -1422,7 +1422,7 @@ class QAPISchemaAlternateType(QAPISchemaType): class QAPISchemaCommand(QAPISchemaEntity): def __init__(self, name, info, doc, arg_type, ret_type, - gen, success_response, boxed, allow_oob): + gen, success_response, boxed, allow_oob, async): QAPISchemaEntity.__init__(self, name, info, doc) assert not arg_type or isinstance(arg_type, str) assert not ret_type or isinstance(ret_type, str) @@ -1434,6 +1434,7 @@ class QAPISchemaCommand(QAPISchemaEntity): self.success_response = success_response self.boxed = boxed self.allow_oob = allow_oob + self.async = async def check(self, schema): if self._arg_type_name: @@ -1458,7 +1459,7 @@ class QAPISchemaCommand(QAPISchemaEntity): visitor.visit_command(self.name, self.info, self.arg_type, self.ret_type, self.gen, self.success_response, - self.boxed, self.allow_oob) + self.boxed, self.allow_oob, self.async) class QAPISchemaEvent(QAPISchemaEntity): @@ -1678,6 +1679,7 @@ class QAPISchema(object): success_response = expr.get('success-response', True) boxed = expr.get('boxed', False) allow_oob = expr.get('allow-oob', False) + async = expr.get('async', False) if isinstance(data, OrderedDict): data = self._make_implicit_object_type( name, info, doc, 'arg', self._make_members(data, info)) @@ -1686,7 +1688,7 @@ class QAPISchema(object): rets = self._make_array_type(rets[0], info) self._def_entity(QAPISchemaCommand(name, info, doc, data, rets, gen, success_response, - boxed, allow_oob)) + boxed, allow_oob, async)) def _def_event(self, expr, info, doc): name = expr['event'] diff --git a/scripts/qapi/doc.py b/scripts/qapi/doc.py old mode 100644 new mode 100755 index 9b312b2c51..33b26e2bef --- a/scripts/qapi/doc.py +++ b/scripts/qapi/doc.py @@ -227,7 +227,7 @@ class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor): body=texi_entity(doc, 'Members'))) def visit_command(self, name, info, arg_type, ret_type, - gen, success_response, boxed, allow_oob): + gen, success_response, boxed, allow_oob, async): doc = self.cur_doc if boxed: body = texi_body(doc) diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py index f9e67e8227..5de60d0357 100644 --- a/scripts/qapi/introspect.py +++ b/scripts/qapi/introspect.py @@ -172,7 +172,7 @@ const QLitObject %(c_name)s = %(c_string)s; for m in variants.variants]}) def visit_command(self, name, info, arg_type, ret_type, - gen, success_response, boxed, allow_oob): + gen, success_response, boxed, allow_oob, async): arg_type = arg_type or self._schema.the_empty_object_type ret_type = ret_type or self._schema.the_empty_object_type self._gen_qlit(name, 'command', diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c index eeaac03d50..f1e6cde990 100644 --- a/tests/test-qmp-cmds.c +++ b/tests/test-qmp-cmds.c @@ -20,6 +20,28 @@ void qmp_cmd_success_response(Error **errp) { } +static gboolean cmd_async_idle(gpointer user_data) +{ + QmpReturn *qret = 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 = 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); @@ -345,6 +367,43 @@ static void test_qmp_return_orderly(void) QDECREF(dict); } +typedef struct QmpReturnAsync { + QmpSession session; + GMainLoop *loop; +} QmpReturnAsync; + +static void dispatch_return_async(QmpSession *session, QDict *resp) +{ + QmpReturnAsync *a = container_of(session, QmpReturnAsync, session); + + g_main_loop_quit(a->loop); + g_main_loop_unref(a->loop); + a->loop = NULL; +} + +static void test_qmp_return_async(void) +{ + QmpReturnAsync a = { 0, }; + QDict *args = qdict_new(); + QDict *req = qdict_new(); + + a.loop = g_main_loop_new(NULL, TRUE); + qmp_session_init(&a.session, &qmp_commands, + qmp_dispatch, 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, req); + g_assert(a.loop); + + g_main_loop_run(a.loop); + g_assert(!a.loop); + + qmp_session_destroy(&a.session); + QDECREF(req); +} + int main(int argc, char **argv) { g_test_init(&argc, &argv, NULL); @@ -358,6 +417,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); test_qmp_init_marshal(&qmp_commands); g_test_run(); diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json index 96ff3a8e47..383369cd58 100644 --- a/tests/qapi-schema/qapi-schema-test.json +++ b/tests/qapi-schema/qapi-schema-test.json @@ -134,6 +134,11 @@ { 'command': 'cmd-success-response', 'data': {}, 'success-response': false } +{ '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/qapi-schema-test.out index cd3642be34..aa18f2c811 100644 --- a/tests/qapi-schema/qapi-schema-test.out +++ b/tests/qapi-schema/qapi-schema-test.out @@ -155,6 +155,14 @@ command user_def_cmd2 q_obj_user_def_cmd2-arg -> UserDefTwo gen=True success_response=True boxed=False command cmd-success-response None -> None gen=True success_response=False boxed=False +object q_obj_cmd-async-arg + member filename: str optional=False +command cmd-async q_obj_cmd-async-arg -> Empty2 + gen=True success_response=True boxed=False async=True +object q_obj_cmd-success-response-async-arg + member filename: str optional=False +command cmd-success-response-async q_obj_cmd-success-response-async-arg -> None + gen=True success_response=False boxed=False async=True object q_obj_guest-get-time-arg member a: int optional=False member b: int optional=True diff --git a/tests/qapi-schema/test-qapi.py b/tests/qapi-schema/test-qapi.py index 10e68b01d9..491bdc73dd 100644 --- a/tests/qapi-schema/test-qapi.py +++ b/tests/qapi-schema/test-qapi.py @@ -42,11 +42,12 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor): self._print_variants(variants) def visit_command(self, name, info, arg_type, ret_type, - gen, success_response, boxed, allow_oob): + gen, success_response, boxed, allow_oob, async): print('command %s %s -> %s' % \ (name, arg_type and arg_type.name, ret_type and ret_type.name)) - print(' gen=%s success_response=%s boxed=%s' % \ - (gen, success_response, boxed)) + print(' gen=%s success_response=%s boxed=%s%s' % \ + (gen, success_response, boxed, + ' async=True' if async else '')) def visit_event(self, name, info, arg_type, boxed): print('event %s %s' % (name, arg_type and arg_type.name)) From patchwork Mon Mar 26 15:09:09 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891085 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408yxp3Vkwz9s2B for ; Tue, 27 Mar 2018 02:39:42 +1100 (AEDT) Received: from localhost ([::1]:57439 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0UDj-0006ZB-Tg for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:39:39 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55344) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tln-0006Ky-5I for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:48 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0Tlm-0003Q1-1S for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:47 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:57308 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0Tll-0003Po-Sz for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:45 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8B95D722C4; Mon, 26 Mar 2018 15:10:45 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1E3837C55; Mon, 26 Mar 2018 15:10:39 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:09:09 +0200 Message-Id: <20180326150916.9602-32-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Mon, 26 Mar 2018 15:10:45 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Mon, 26 Mar 2018 15:10:45 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 31/38] 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: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" 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é Lureau --- include/qapi/qmp/dispatch.h | 8 ++++++++ qapi/qmp-dispatch.c | 10 ++++++++++ 2 files changed, 18 insertions(+) diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h index e426317346..6ee82371a2 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); +/* + * @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 f7d9931734..99f5128170 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -63,6 +63,16 @@ void qmp_return_free(QmpReturn *qret) } } +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 = qret->session; From patchwork Mon Mar 26 15:09:10 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891078 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408ynq2Ytdz9s2B for ; Tue, 27 Mar 2018 02:32:47 +1100 (AEDT) Received: from localhost ([::1]:57396 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0U72-0000Da-Op for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:32:44 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55459) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tm0-0006Wy-EC for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:11:04 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0Tls-0003VM-Oo for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:11:00 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:47536 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0Tls-0003V3-Jo for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:52 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 400B3401DE65; Mon, 26 Mar 2018 15:10:52 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id 36D6310B0F20; Mon, 26 Mar 2018 15:10:47 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:09:10 +0200 Message-Id: <20180326150916.9602-33-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Mon, 26 Mar 2018 15:10:52 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Mon, 26 Mar 2018 15:10:52 +0000 (UTC) for IP:'10.11.54.3' DOMAIN:'int-mx03.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 32/38] 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: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" 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é 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 0cb0538a31..2052a6b4e4 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" extern Monitor *cur_mon; @@ -46,4 +47,6 @@ int monitor_fdset_dup_fd_add(int64_t fdset_id, int dup_fd); void monitor_fdset_dup_fd_remove(int dup_fd); int monitor_fdset_dup_fd_find(int dup_fd); +Monitor *qmp_return_get_monitor(QmpReturn *qret); + #endif /* MONITOR_H */ diff --git a/monitor.c b/monitor.c index 73a06d4156..f7826f5626 100644 --- a/monitor.c +++ b/monitor.c @@ -281,6 +281,12 @@ bool monitor_cur_is_qmp(void) return cur_mon && monitor_is_qmp(cur_mon); } +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) From patchwork Mon Mar 26 15:09:11 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891087 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408z0z0npfz9s1r for ; Tue, 27 Mar 2018 02:42:27 +1100 (AEDT) Received: from localhost ([::1]:57456 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0UGO-00013m-Ga for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:42:24 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55434) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tly-0006VJ-Rr for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:11:00 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0Tlu-0003XI-Gl for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:58 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:48790 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0Tlu-0003WK-BS for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:54 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 011644068026; Mon, 26 Mar 2018 15:10:54 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8C97710B0F20; Mon, 26 Mar 2018 15:10:53 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:09:11 +0200 Message-Id: <20180326150916.9602-34-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Mon, 26 Mar 2018 15:10:54 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Mon, 26 Mar 2018 15:10:54 +0000 (UTC) for IP:'10.11.54.3' DOMAIN:'int-mx03.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 33/38] console: graphic_hw_update return true if async 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: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" qxl_render_update() returns true if the update is deferred. Let the caller know if the update is immediate or async. Signed-off-by: Marc-André Lureau --- hw/display/qxl.h | 2 +- include/ui/console.h | 3 ++- hw/display/qxl-render.c | 5 +++-- hw/display/qxl.c | 8 ++++---- ui/console.c | 14 ++++++++++++-- 5 files changed, 22 insertions(+), 10 deletions(-) diff --git a/hw/display/qxl.h b/hw/display/qxl.h index 089696ef62..cc4f83f990 100644 --- a/hw/display/qxl.h +++ b/hw/display/qxl.h @@ -169,7 +169,7 @@ int qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext); /* qxl-render.c */ void qxl_render_resize(PCIQXLDevice *qxl); -void qxl_render_update(PCIQXLDevice *qxl); +bool qxl_render_update(PCIQXLDevice *qxl); int qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext); void qxl_render_update_area_done(PCIQXLDevice *qxl, QXLCookie *cookie); void qxl_render_update_area_bh(void *opaque); diff --git a/include/ui/console.h b/include/ui/console.h index 6d2c052068..d2b6c46a62 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -374,6 +374,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)(void *opaque); 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); @@ -388,7 +389,7 @@ void graphic_console_set_hwops(QemuConsole *con, void *opaque); void graphic_console_close(QemuConsole *con); -void graphic_hw_update(QemuConsole *con); +bool graphic_hw_update(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 e7ac4f8789..62574173a2 100644 --- a/hw/display/qxl-render.c +++ b/hw/display/qxl-render.c @@ -163,7 +163,7 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl) * callbacks are called by spice_server thread, deferring to bh called from the * io thread. */ -void qxl_render_update(PCIQXLDevice *qxl) +bool qxl_render_update(PCIQXLDevice *qxl) { QXLCookie *cookie; @@ -172,7 +172,7 @@ void qxl_render_update(PCIQXLDevice *qxl) if (!runstate_is_running() || !qxl->guest_primary.commands) { qxl_render_update_area_unlocked(qxl); qemu_mutex_unlock(&qxl->ssd.lock); - return; + return false; } qxl->guest_primary.commands = 0; @@ -183,6 +183,7 @@ void qxl_render_update(PCIQXLDevice *qxl) qxl_set_rect_to_surface(qxl, &cookie->u.render.area); qxl_spice_update_area(qxl, 0, &cookie->u.render.area, NULL, 0, 1 /* clear_dirty_region */, QXL_ASYNC, cookie); + return true; } void qxl_render_update_area_bh(void *opaque) diff --git a/hw/display/qxl.c b/hw/display/qxl.c index a71714ccb4..7dda2ae576 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -136,7 +136,7 @@ static void qxl_reset_memslots(PCIQXLDevice *d); static void qxl_reset_surfaces(PCIQXLDevice *d); static void qxl_ring_set_dirty(PCIQXLDevice *qxl); -static void qxl_hw_update(void *opaque); +static bool qxl_hw_update_async(void *opaque); void qxl_set_guest_bug(PCIQXLDevice *qxl, const char *msg, ...) { @@ -1167,7 +1167,7 @@ static const QXLInterface qxl_interface = { }; static const GraphicHwOps qxl_ops = { - .gfx_update = qxl_hw_update, + .gfx_update_async = qxl_hw_update_async, }; static void qxl_enter_vga_mode(PCIQXLDevice *d) @@ -1889,11 +1889,11 @@ static void qxl_send_events(PCIQXLDevice *d, uint32_t events) /* graphics console */ -static void qxl_hw_update(void *opaque) +static bool qxl_hw_update_async(void *opaque) { PCIQXLDevice *qxl = opaque; - qxl_render_update(qxl); + return qxl_render_update(qxl); } static void qxl_dirty_one_surface(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, diff --git a/ui/console.c b/ui/console.c index 530a491987..0774cd3366 100644 --- a/ui/console.c +++ b/ui/console.c @@ -256,14 +256,24 @@ static void gui_setup_refresh(DisplayState *ds) ds->have_text = have_text; } -void graphic_hw_update(QemuConsole *con) +bool graphic_hw_update(QemuConsole *con) { if (!con) { con = active_console; } - if (con && con->hw_ops->gfx_update) { + + if (!con) { + return false; + } + + if (con->hw_ops->gfx_update_async) { + return con->hw_ops->gfx_update_async(con->hw); + } else if (con->hw_ops->gfx_update) { con->hw_ops->gfx_update(con->hw); + return false; } + + return false; } void graphic_hw_gl_block(QemuConsole *con, bool block) From patchwork Mon Mar 26 15:09:12 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891086 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408z0b0nn2z9s37 for ; Tue, 27 Mar 2018 02:42:05 +1100 (AEDT) Received: from localhost ([::1]:57453 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0UG2-0000aN-4q for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:42:02 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55422) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tlx-0006UE-OL for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:11:01 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0Tlv-0003Zd-Sf for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:57 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:57320 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0Tlv-0003Z6-OL for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:55 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 628B5722C5; Mon, 26 Mar 2018 15:10:55 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id 14B74D7DFA; Mon, 26 Mar 2018 15:10:54 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:09:12 +0200 Message-Id: <20180326150916.9602-35-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Mon, 26 Mar 2018 15:10:55 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Mon, 26 Mar 2018 15:10:55 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 34/38] 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: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Add a function to be called when an async graphic update is done. Signed-off-by: Marc-André Lureau --- include/ui/console.h | 1 + hw/display/qxl-render.c | 9 +++++++-- ui/console.c | 4 ++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/include/ui/console.h b/include/ui/console.h index d2b6c46a62..fc21621656 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -390,6 +390,7 @@ void graphic_console_set_hwops(QemuConsole *con, void graphic_console_close(QemuConsole *con); bool 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 62574173a2..08722d2833 100644 --- a/hw/display/qxl-render.c +++ b/hw/display/qxl-render.c @@ -106,7 +106,7 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *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 = 1; @@ -134,7 +134,7 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl) } if (!qxl->guest_primary.data) { - return; + goto end; } for (i = 0; i < qxl->num_dirty_rects; i++) { if (qemu_spice_rect_is_empty(qxl->dirty+i)) { @@ -155,6 +155,11 @@ static void qxl_render_update_area_unlocked(PCIQXLDevice *qxl) qxl->dirty[i].bottom - qxl->dirty[i].top); } qxl->num_dirty_rects = 0; + +end: + if (qxl->render_update_cookie_num == 0) { + graphic_hw_update_done(qxl->ssd.dcl.con); + } } /* diff --git a/ui/console.c b/ui/console.c index 0774cd3366..29234605a7 100644 --- a/ui/console.c +++ b/ui/console.c @@ -256,6 +256,10 @@ static void gui_setup_refresh(DisplayState *ds) ds->have_text = have_text; } +void graphic_hw_update_done(QemuConsole *con) +{ +} + bool graphic_hw_update(QemuConsole *con) { if (!con) { From patchwork Mon Mar 26 15:09:13 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891080 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408ysl0C4wz9s3F for ; Tue, 27 Mar 2018 02:36:11 +1100 (AEDT) Received: from localhost ([::1]:57419 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0UAK-0003Uc-GK for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:36:08 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55445) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tlz-0006W1-GH for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:11:01 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0Tlx-0003bO-SB for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:59 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:47546 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0Tlx-0003b6-L8 for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:57 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4F082401DE69; Mon, 26 Mar 2018 15:10:57 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7E928202322B; Mon, 26 Mar 2018 15:10:56 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:09:13 +0200 Message-Id: <20180326150916.9602-36-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Mon, 26 Mar 2018 15:10:57 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Mon, 26 Mar 2018 15:10:57 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 35/38] 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: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Make screendump asynchronous to provide correct screendumps. HMP doesn't have async support, so it has to remain synchronous and potentially incorrect to avoid potential races. Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1230527 Signed-off-by: Marc-André Lureau --- qapi/ui.json | 3 +- include/ui/console.h | 3 ++ hmp.c | 2 +- ui/console.c | 99 ++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 96 insertions(+), 11 deletions(-) diff --git a/qapi/ui.json b/qapi/ui.json index 5d01ad4304..4d2c326fb9 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 } ## # == Spice diff --git a/include/ui/console.h b/include/ui/console.h index fc21621656..0c02190963 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -74,6 +74,9 @@ struct MouseTransformInfo { }; 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); /* keysym is a unicode code except for special keys (see QEMU_KEY_xxx constants) */ diff --git a/hmp.c b/hmp.c index 679467d85a..da9008fe63 100644 --- a/hmp.c +++ b/hmp.c @@ -2144,7 +2144,7 @@ void hmp_screendump(Monitor *mon, const QDict *qdict) int64_t head = qdict_get_try_int(qdict, "head", 0); Error *err = NULL; - qmp_screendump(filename, id != NULL, id, id != NULL, head, &err); + hmp_screendump_sync(filename, id != NULL, id, id != NULL, head, &err); hmp_handle_error(mon, &err); } diff --git a/ui/console.c b/ui/console.c index 29234605a7..da51861191 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" #define DEFAULT_BACKSCROLL 512 #define CONSOLE_CURSOR_PERIOD 500 @@ -116,6 +117,12 @@ typedef enum { TEXT_CONSOLE_FIXED_SIZE } console_type_t; +struct qmp_screendump { + gchar *filename; + QmpReturn *ret; + QLIST_ENTRY(qmp_screendump) link; +}; + struct QemuConsole { Object parent; @@ -165,6 +172,8 @@ struct QemuConsole { QEMUFIFO out_fifo; uint8_t out_fifo_buf[16]; QEMUTimer *kbd_timer; + + QLIST_HEAD(, qmp_screendump) qmp_screendumps; }; struct DisplayState { @@ -190,6 +199,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); static void gui_update(void *opaque) { @@ -256,8 +267,42 @@ static void gui_setup_refresh(DisplayState *ds) ds->have_text = have_text; } +static void qmp_screendump_finish(QemuConsole *con, const char *filename, + QmpReturn *ret) +{ + Error *err = NULL; + DisplaySurface *surface; + Monitor *prev_mon = cur_mon; + + if (qmp_return_is_cancelled(ret)) { + return; + } + + cur_mon = qmp_return_get_monitor(ret); + surface = qemu_console_surface(con); + + /* FIXME: async save with coroutine? it would have to copy or lock + * the surface. */ + ppm_save(filename, surface, &err); + + if (err) { + qmp_return_error(ret, err); + } else { + qmp_screendump_return(ret); + } + cur_mon = prev_mon; +} + 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->filename, dump->ret); + g_free(dump->filename); + QLIST_REMOVE(dump, link); + g_free(dump); + } } bool graphic_hw_update(QemuConsole *con) @@ -358,35 +403,70 @@ write_err: goto out; } -void qmp_screendump(const char *filename, bool has_device, const char *device, - 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 = NULL; if (has_device) { con = 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 'device'"); - return; + return NULL; } con = qemu_console_lookup_by_index(0); if (!con) { error_setg(errp, "There is no console to take a screendump from"); - return; } } + 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 = get_console(has_device, device, has_head, head, errp); + + 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 = qemu_console_surface(con); ppm_save(filename, surface, errp); } +void qmp_screendump(const char *filename, + bool has_device, const char *device, + bool has_head, int64_t head, + QmpReturn *qret) +{ + Error *err = NULL; + bool async; + QemuConsole *con = get_console(has_device, device, has_head, head, &err); + + if (!con) { + qmp_return_error(qret, err); + return; + } + async = graphic_hw_update(con); + if (async) { + struct qmp_screendump *dump = g_new(struct qmp_screendump, 1); + dump->filename = g_strdup(filename); + dump->ret = qret; + QLIST_INSERT_HEAD(&con->qmp_screendumps, dump, link); + } else { + qmp_screendump_finish(con, filename, qret); + } +} + void graphic_hw_text_update(QemuConsole *con, console_ch_t *chardata) { if (!con) { @@ -1280,6 +1360,7 @@ static QemuConsole *new_console(DisplayState *ds, console_type_t console_type, obj = object_new(TYPE_QEMU_CONSOLE); s = QEMU_CONSOLE(obj); s->head = head; + QLIST_INIT(&s->qmp_screendumps); object_property_add_link(obj, "device", TYPE_DEVICE, (Object **)&s->device, object_property_allow_set_link, From patchwork Mon Mar 26 15:09:14 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891083 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408yx85PpQz9s2B for ; Tue, 27 Mar 2018 02:39:08 +1100 (AEDT) Received: from localhost ([::1]:57432 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0UDC-00064r-8X for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:39:06 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55454) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tm0-0006Wh-6m for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:11:01 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0Tlz-0003cZ-Bu for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:11:00 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:36686 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0Tlz-0003c1-1D for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:10:59 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id AC16E406E8A4; Mon, 26 Mar 2018 15:10:58 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5C2C3215CDAE; Mon, 26 Mar 2018 15:10:58 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:09:14 +0200 Message-Id: <20180326150916.9602-37-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 26 Mar 2018 15:10:58 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 26 Mar 2018 15:10:58 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 36/38] 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: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" This prepares the work for HMP commands to be asynchronous. For now this will and the return synchronously. Signed-off-by: Marc-André 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 5636f4a149..04e704eb6c 100644 --- a/qapi/misc.json +++ b/qapi/misc.json @@ -1307,7 +1307,8 @@ ## { 'command': 'human-monitor-command', 'data': {'command-line': 'str', '*cpu-index': 'int'}, - 'returns': 'str' } + 'returns': 'str', + 'async': true } ## # @ObjectPropertyInfo: diff --git a/monitor.c b/monitor.c index f7826f5626..e11c0abdca 100644 --- a/monitor.c +++ b/monitor.c @@ -637,8 +637,8 @@ static void monitor_data_destroy(Monitor *mon) g_queue_free(mon->qmp.qmp_requests); } -char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index, - int64_t cpu_index, Error **errp) +void qmp_human_monitor_command(const char *command_line, bool has_cpu_index, + int64_t cpu_index, QmpReturn *qret) { char *output = NULL; Monitor *old_mon, hmp; @@ -651,15 +651,15 @@ char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index, if (has_cpu_index) { int ret = monitor_set_cpu(cpu_index); if (ret < 0) { - cur_mon = old_mon; - error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "cpu-index", + Error *err = NULL; + error_setg(&err, QERR_INVALID_PARAMETER_VALUE, "cpu-index", "a CPU number"); + qmp_return_error(qret, err); goto out; } } handle_hmp_command(&hmp, command_line); - cur_mon = old_mon; qemu_mutex_lock(&hmp.out_lock); if (qstring_get_length(hmp.outbuf) > 0) { @@ -669,9 +669,11 @@ char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index, } qemu_mutex_unlock(&hmp.out_lock); + qmp_human_monitor_command_return(qret, output); + out: monitor_data_destroy(&hmp); - return output; + cur_mon = old_mon; } static int compare_cmd(const char *name, const char *list) From patchwork Mon Mar 26 15:09:15 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891089 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408z3k0lxQz9s1r for ; Tue, 27 Mar 2018 02:44:50 +1100 (AEDT) Received: from localhost ([::1]:57473 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0UIh-0003A3-HL for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:44:47 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55517) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0Tm8-0006g0-Rc for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:11:10 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0Tm5-0003fR-LV for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:11:08 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:36690 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0Tm5-0003fA-G9 for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:11:05 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2B22B406E971; Mon, 26 Mar 2018 15:11:05 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id C9CA3D7DFA; Mon, 26 Mar 2018 15:10:59 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:09:15 +0200 Message-Id: <20180326150916.9602-38-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 26 Mar 2018 15:11:05 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.7]); Mon, 26 Mar 2018 15:11:05 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 37/38] 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: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" 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. Note that QMP human-monitor-command is modified to deal with it, by using a specialized QmpSession return callback to destroy the temporary HMP monitor. Signed-off-by: Marc-André Lureau --- monitor.c | 106 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 79 insertions(+), 27 deletions(-) diff --git a/monitor.c b/monitor.c index e11c0abdca..018bd9280f 100644 --- a/monitor.c +++ b/monitor.c @@ -127,13 +127,17 @@ typedef struct mon_cmd_t { const char *args_type; const char *params; const char *help; - void (*cmd)(Monitor *mon, const QDict *qdict); + union { + void (*cmd)(Monitor *mon, const QDict *qdict); + void (*async_cmd)(Monitor *mon, const QDict *qdict, QmpReturn *qret); + }; /* @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; /* file descriptors passed via SCM_RIGHTS */ @@ -203,6 +207,7 @@ struct Monitor { int suspend_cnt; /* Needs to be accessed atomically */ bool skip_flush; bool use_io_thr; + QmpReturn *for_qmp_command; QemuMutex out_lock; QString *outbuf; @@ -607,7 +612,7 @@ static void monitor_qapi_event_init(void) qmp_event_set_func_emit(monitor_qapi_event_queue); } -static void handle_hmp_command(Monitor *mon, const char *cmdline); +static bool handle_hmp_command(Monitor *mon, const char *cmdline); static void monitor_data_init(Monitor *mon, bool skip_flush, bool use_io_thr) @@ -637,16 +642,68 @@ static void monitor_data_destroy(Monitor *mon) g_queue_free(mon->qmp.qmp_requests); } +static void free_temporary_hmp(void *opaque) +{ + Monitor *hmp = 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_global.mon_iothread); +} + +static void qmp_human_monitor_command_finish(Monitor *hmp, QmpReturn *qret) +{ + char *output; + + if (qstring_get_length(hmp->outbuf) > 0) { + output = g_strdup(qstring_get_str(hmp->outbuf)); + } else { + output = g_strdup(""); + } + + qmp_human_monitor_command_return(qret, output); + + if (hmp->for_qmp_command) { + aio_bh_schedule_oneshot(monitor_get_aio_context(), + free_temporary_hmp, hmp); + } +} + +static void hmp_dispatch_return_cb(QmpSession *session, QDict *rsp) +{ + Monitor *hmp = container_of(session, Monitor, qmp.session); + QDict *err = qdict_get_qdict(rsp, "error"); + Monitor *old_mon = cur_mon; + + cur_mon = 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 = old_mon; +} + void qmp_human_monitor_command(const char *command_line, bool has_cpu_index, int64_t cpu_index, QmpReturn *qret) { - char *output = NULL; - Monitor *old_mon, hmp; + Monitor *old_mon, *hmp = g_new0(Monitor, 1); - 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 = qret; old_mon = cur_mon; - cur_mon = &hmp; + cur_mon = hmp; if (has_cpu_index) { int ret = monitor_set_cpu(cpu_index); @@ -659,20 +716,11 @@ void qmp_human_monitor_command(const char *command_line, bool has_cpu_index, } } - handle_hmp_command(&hmp, command_line); - - qemu_mutex_lock(&hmp.out_lock); - if (qstring_get_length(hmp.outbuf) > 0) { - output = g_strdup(qstring_get_str(hmp.outbuf)); - } else { - output = g_strdup(""); + if (!handle_hmp_command(hmp, command_line)) { + qmp_human_monitor_command_finish(hmp, qret); } - qemu_mutex_unlock(&hmp.out_lock); - - qmp_human_monitor_command_return(qret, output); out: - monitor_data_destroy(&hmp); cur_mon = old_mon; } @@ -3244,7 +3292,7 @@ fail: return NULL; } -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; @@ -3253,18 +3301,25 @@ static void handle_hmp_command(Monitor *mon, const char *cmdline) cmd = monitor_parse_command(mon, cmdline, &cmdline, mon->cmd_table); if (!cmd) { - return; + return false; } qdict = monitor_parse_arguments(mon, &cmdline, cmd); if (!qdict) { monitor_printf(mon, "Try \"help %s\" for more information\n", cmd->name); - return; + return false; + } + if (cmd->async) { + QmpReturn *qret = qmp_return_new(&mon->qmp.session, NULL); + monitor_suspend(mon); + cmd->async_cmd(mon, qdict, qret); + } else { + cmd->cmd(mon, qdict); } - - cmd->cmd(mon, qdict); QDECREF(qdict); + + return cmd->async; } static void cmd_completion(Monitor *mon, const char *name, const char *list) @@ -4296,11 +4351,6 @@ static GMainContext *monitor_get_io_context(void) return iothread_get_g_main_context(mon_global.mon_iothread); } -static AioContext *monitor_get_aio_context(void) -{ - return iothread_get_aio_context(mon_global.mon_iothread); -} - static void monitor_iothread_init(void) { mon_global.mon_iothread = iothread_create("mon_iothread", @@ -4439,6 +4489,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); } From patchwork Mon Mar 26 15:09:16 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= X-Patchwork-Id: 891088 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 408z3H4knWz9s1r for ; Tue, 27 Mar 2018 02:44:27 +1100 (AEDT) Received: from localhost ([::1]:57470 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0UIL-0002kk-4N for incoming@patchwork.ozlabs.org; Mon, 26 Mar 2018 11:44:25 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55525) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f0TmB-0006iB-55 for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:11:12 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f0Tm7-0003gC-1b for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:11:11 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:38380 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1f0Tm6-0003fo-TB for qemu-devel@nongnu.org; Mon, 26 Mar 2018 11:11:06 -0400 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8B2257705F; Mon, 26 Mar 2018 15:11:06 +0000 (UTC) Received: from localhost (ovpn-112-61.ams2.redhat.com [10.36.112.61]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3CE41215CDAE; Mon, 26 Mar 2018 15:11:06 +0000 (UTC) From: =?utf-8?q?Marc-Andr=C3=A9_Lureau?= To: qemu-devel@nongnu.org Date: Mon, 26 Mar 2018 17:09:16 +0200 Message-Id: <20180326150916.9602-39-marcandre.lureau@redhat.com> In-Reply-To: <20180326150916.9602-1-marcandre.lureau@redhat.com> References: <20180326150916.9602-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Mon, 26 Mar 2018 15:11:06 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Mon, 26 Mar 2018 15:11:06 +0000 (UTC) for IP:'10.11.54.6' DOMAIN:'int-mx06.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'marcandre.lureau@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH v3 38/38] 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: Eduardo Habkost , Juan Quintela , Markus Armbruster , "Dr. David Alan Gilbert" , Gerd Hoffmann , Cleber Rosa , =?utf-8?q?Marc-A?= =?utf-8?q?ndr=C3=A9_Lureau?= , Michael Roth Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" 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é Lureau --- hmp.h | 3 ++- hmp.c | 6 ++---- ui/console.c | 17 ----------------- hmp-commands.hx | 3 ++- 4 files changed, 6 insertions(+), 23 deletions(-) diff --git a/hmp.h b/hmp.h index 4e2ec375b0..6ad43b7828 100644 --- a/hmp.h +++ b/hmp.h @@ -16,6 +16,7 @@ #include "qemu-common.h" #include "qemu/readline.h" +#include "qapi/qmp/dispatch.h" void hmp_info_name(Monitor *mon, const QDict *qdict); void hmp_info_version(Monitor *mon, const QDict *qdict); @@ -96,7 +97,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 *qret); 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 da9008fe63..ca1ee8e146 100644 --- a/hmp.c +++ b/hmp.c @@ -2137,15 +2137,13 @@ err_out: goto out; } -void hmp_screendump(Monitor *mon, const QDict *qdict) +void hmp_screendump_async(Monitor *mon, const QDict *qdict, QmpReturn *qret) { const char *filename = qdict_get_str(qdict, "filename"); const char *id = qdict_get_try_str(qdict, "device"); int64_t head = qdict_get_try_int(qdict, "head", 0); - Error *err = NULL; - hmp_screendump_sync(filename, id != NULL, id, id != NULL, head, &err); - hmp_handle_error(mon, &err); + qmp_screendump(filename, id != NULL, id, id != NULL, head, qret); } void hmp_nbd_server_start(Monitor *mon, const QDict *qdict) diff --git a/ui/console.c b/ui/console.c index da51861191..f1cbbd6317 100644 --- a/ui/console.c +++ b/ui/console.c @@ -426,23 +426,6 @@ static QemuConsole *get_console(bool has_device, const char *device, 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 = get_console(has_device, device, has_head, head, errp); - - 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 = qemu_console_surface(con); - 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 35d862a5d2..4911fc6474 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -258,7 +258,8 @@ ETEXI .params = "filename [device [head]]", .help = "save screen from head 'head' of display device 'device' " "into PPM image 'filename'", - .cmd = hmp_screendump, + .async_cmd = hmp_screendump_async, + .async = true, }, STEXI