Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/813730/?format=api
{ "id": 813730, "url": "http://patchwork.ozlabs.org/api/patches/813730/?format=api", "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/1505375436-28439-12-git-send-email-peterx@redhat.com/", "project": { "id": 14, "url": "http://patchwork.ozlabs.org/api/projects/14/?format=api", "name": "QEMU Development", "link_name": "qemu-devel", "list_id": "qemu-devel.nongnu.org", "list_email": "qemu-devel@nongnu.org", "web_url": "", "scm_url": "", "webscm_url": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<1505375436-28439-12-git-send-email-peterx@redhat.com>", "list_archive_url": null, "date": "2017-09-14T07:50:32", "name": "[RFC,11/15] monitor: separate QMP parser and dispatcher", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "c7b6136333d12869fefd453f1d9dd1603fe0db5c", "submitter": { "id": 67717, "url": "http://patchwork.ozlabs.org/api/people/67717/?format=api", "name": "Peter Xu", "email": "peterx@redhat.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/1505375436-28439-12-git-send-email-peterx@redhat.com/mbox/", "series": [ { "id": 3043, "url": "http://patchwork.ozlabs.org/api/series/3043/?format=api", "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/list/?series=3043", "date": "2017-09-14T07:50:21", "name": "QMP: out-of-band (OOB) execution support", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/3043/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/813730/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/813730/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>", "X-Original-To": "incoming@patchwork.ozlabs.org", "Delivered-To": "patchwork-incoming@bilbo.ozlabs.org", "Authentication-Results": [ "ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=nongnu.org\n\t(client-ip=2001:4830:134:3::11; helo=lists.gnu.org;\n\tenvelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n\treceiver=<UNKNOWN>)", "ext-mx04.extmail.prod.ext.phx2.redhat.com;\n\tdmarc=none (p=none dis=none) header.from=redhat.com", "ext-mx04.extmail.prod.ext.phx2.redhat.com;\n\tspf=fail smtp.mailfrom=peterx@redhat.com" ], "Received": [ "from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11])\n\t(using TLSv1 with cipher AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xt9q71PFfz9sRm\n\tfor <incoming@patchwork.ozlabs.org>;\n\tThu, 14 Sep 2017 17:57:07 +1000 (AEST)", "from localhost ([::1]:46207 helo=lists.gnu.org)\n\tby lists.gnu.org with esmtp (Exim 4.71) (envelope-from\n\t<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>)\n\tid 1dsP1F-0003LN-8s\n\tfor incoming@patchwork.ozlabs.org; Thu, 14 Sep 2017 03:57:05 -0400", "from eggs.gnu.org ([2001:4830:134:3::10]:52614)\n\tby lists.gnu.org with esmtp (Exim 4.71)\n\t(envelope-from <peterx@redhat.com>) id 1dsOwQ-0007Ef-Fp\n\tfor qemu-devel@nongnu.org; Thu, 14 Sep 2017 03:52:09 -0400", "from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71)\n\t(envelope-from <peterx@redhat.com>) id 1dsOwO-0007qN-MI\n\tfor qemu-devel@nongnu.org; Thu, 14 Sep 2017 03:52:06 -0400", "from mx1.redhat.com ([209.132.183.28]:43400)\n\tby eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32)\n\t(Exim 4.71) (envelope-from <peterx@redhat.com>) id 1dsOwO-0007o1-BN\n\tfor qemu-devel@nongnu.org; Thu, 14 Sep 2017 03:52:04 -0400", "from smtp.corp.redhat.com\n\t(int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12])\n\t(using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby mx1.redhat.com (Postfix) with ESMTPS id 409F87EA89;\n\tThu, 14 Sep 2017 07:52:03 +0000 (UTC)", "from pxdev.xzpeter.org.com (dhcp-15-224.nay.redhat.com\n\t[10.66.15.224])\n\tby smtp.corp.redhat.com (Postfix) with ESMTP id 09CF570132;\n\tThu, 14 Sep 2017 07:51:58 +0000 (UTC)" ], "DMARC-Filter": "OpenDMARC Filter v1.3.2 mx1.redhat.com 409F87EA89", "From": "Peter Xu <peterx@redhat.com>", "To": "qemu-devel@nongnu.org", "Date": "Thu, 14 Sep 2017 15:50:32 +0800", "Message-Id": "<1505375436-28439-12-git-send-email-peterx@redhat.com>", "In-Reply-To": "<1505375436-28439-1-git-send-email-peterx@redhat.com>", "References": "<1505375436-28439-1-git-send-email-peterx@redhat.com>", "X-Scanned-By": "MIMEDefang 2.79 on 10.5.11.12", "X-Greylist": "Sender IP whitelisted, not delayed by milter-greylist-4.5.16\n\t(mx1.redhat.com [10.5.110.28]);\n\tThu, 14 Sep 2017 07:52:03 +0000 (UTC)", "X-detected-operating-system": "by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic]\n\t[fuzzy]", "X-Received-From": "209.132.183.28", "Subject": "[Qemu-devel] [RFC 11/15] monitor: separate QMP parser and dispatcher", "X-BeenThere": "qemu-devel@nongnu.org", "X-Mailman-Version": "2.1.21", "Precedence": "list", "List-Id": "<qemu-devel.nongnu.org>", "List-Unsubscribe": "<https://lists.nongnu.org/mailman/options/qemu-devel>,\n\t<mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>", "List-Archive": "<http://lists.nongnu.org/archive/html/qemu-devel/>", "List-Post": "<mailto:qemu-devel@nongnu.org>", "List-Help": "<mailto:qemu-devel-request@nongnu.org?subject=help>", "List-Subscribe": "<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n\t<mailto:qemu-devel-request@nongnu.org?subject=subscribe>", "Cc": "Laurent Vivier <lvivier@redhat.com>, Fam Zheng <famz@redhat.com>, Juan\n\tQuintela <quintela@redhat.com>, Markus Armbruster <armbru@redhat.com>,\n\tpeterx@redhat.com, mdroth@linux.vnet.ibm.com,\n\tStefan Hajnoczi <shajnocz@redhat.com>, =?utf-8?q?Marc-Andr=C3=A9_Lure?=\n\t=?utf-8?q?au?= <marcandre.lureau@gmail.com>,\n\tPaolo Bonzini <pbonzini@redhat.com>, \"Dr . David Alan Gilbert\"\n\t<dgilbert@redhat.com>", "Errors-To": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org", "Sender": "\"Qemu-devel\"\n\t<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>" }, "content": "Originally QMP is going throw these steps:\n\n JSON Parser --> QMP Dispatcher --> Respond\n /|\\ (2) (3) |\n (1) | \\|/ (4)\n +--------- main thread --------+\n\nThis patch does this:\n\n JSON Parser QMP Dispatcher --> Respond\n /|\\ | /|\\ (4) |\n | | (2) | (3) | (5)\n (1) | +-----> | \\|/\n +--------- main thread <-------+\n\nSo the parsing job and the dispatching job is isolated now. It gives us\na chance in following up patches to totally move the parser outside.\n\nThe isloation is done using one QEMUBH. Only one dispatcher BH for all\nthe monitors.\n\nSigned-off-by: Peter Xu <peterx@redhat.com>\n---\n monitor.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++------------\n 1 file changed, 99 insertions(+), 23 deletions(-)", "diff": "diff --git a/monitor.c b/monitor.c\nindex aa0c384..f649d6a 100644\n--- a/monitor.c\n+++ b/monitor.c\n@@ -213,6 +213,10 @@ struct MonitorGlobal {\n QemuThread mon_io_thread;\n GMainContext *mon_context;\n GMainLoop *mon_loop;\n+ /* Bottom half to dispatch the requests received from IO thread */\n+ QEMUBH *qmp_dispatcher_bh;\n+ /* Input queue that hangs all the parsed QMP requests */\n+ GQueue *qmp_requests;\n };\n \n static struct MonitorGlobal mon_global;\n@@ -3858,29 +3862,31 @@ static void monitor_qmp_respond(Monitor *mon, QObject *rsp,\n qobject_decref(rsp);\n }\n \n-static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens,\n- void *opaque)\n+struct QMPRequest {\n+ /* Owner of the request */\n+ Monitor *mon;\n+ /* \"id\" field of the request */\n+ QObject *id;\n+ /* Request object to be handled */\n+ QObject *req;\n+};\n+typedef struct QMPRequest QMPRequest;\n+\n+/*\n+ * Dispatch one single QMP request. The function will free the req_obj\n+ * and objects inside it before return.\n+ */\n+static void monitor_qmp_dispatch_one(QMPRequest *req_obj)\n {\n- QObject *req, *rsp = NULL, *id = NULL;\n+ Monitor *mon, *old_mon;\n+ QObject *req, *rsp = NULL, *id;\n QDict *qdict = NULL;\n- Monitor *mon = opaque, *old_mon;\n- Error *err = NULL;\n \n- req = json_parser_parse_err(tokens, NULL, &err);\n- if (!req && !err) {\n- /* json_parser_parse_err() sucks: can fail without setting @err */\n- error_setg(&err, QERR_JSON_PARSING);\n- }\n- if (err) {\n- goto err_out;\n- }\n+ req = req_obj->req;\n+ mon = req_obj->mon;\n+ id = req_obj->id;\n \n- qdict = qobject_to_qdict(req);\n- if (qdict) {\n- id = qdict_get(qdict, \"id\");\n- qobject_incref(id);\n- qdict_del(qdict, \"id\");\n- } /* else will fail qmp_dispatch() */\n+ g_free(req_obj);\n \n if (trace_event_get_state_backends(TRACE_HANDLE_QMP_COMMAND)) {\n QString *req_json = qobject_to_json(req);\n@@ -3891,7 +3897,7 @@ static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens,\n old_mon = cur_mon;\n cur_mon = mon;\n \n- rsp = qmp_dispatch(cur_mon->qmp.commands, req);\n+ rsp = qmp_dispatch(mon->qmp.commands, req);\n \n cur_mon = old_mon;\n \n@@ -3907,12 +3913,66 @@ static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens,\n }\n }\n \n-err_out:\n- monitor_qmp_respond(mon, rsp, err, id);\n-\n+ /* Respond if necessary */\n+ monitor_qmp_respond(mon, rsp, NULL, id);\n qobject_decref(req);\n }\n \n+static void monitor_qmp_bh_dispatcher(void *data)\n+{\n+ QMPRequest *req_obj;\n+\n+ while (true) {\n+ req_obj = g_queue_pop_head(mon_global.qmp_requests);\n+ if (!req_obj) {\n+ break;\n+ }\n+ monitor_qmp_dispatch_one(req_obj);\n+ }\n+}\n+\n+static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens,\n+ void *opaque)\n+{\n+ QObject *req, *id = NULL;\n+ QDict *qdict = NULL;\n+ Monitor *mon = opaque;\n+ Error *err = NULL;\n+ QMPRequest *req_obj;\n+\n+ req = json_parser_parse_err(tokens, NULL, &err);\n+ if (!req && !err) {\n+ /* json_parser_parse_err() sucks: can fail without setting @err */\n+ error_setg(&err, QERR_JSON_PARSING);\n+ }\n+ if (err) {\n+ monitor_qmp_respond(mon, NULL, err, NULL);\n+ qobject_decref(req);\n+ }\n+\n+ qdict = qobject_to_qdict(req);\n+ if (qdict) {\n+ id = qdict_get(qdict, \"id\");\n+ qobject_incref(id);\n+ qdict_del(qdict, \"id\");\n+ } /* else will fail qmp_dispatch() */\n+\n+ req_obj = g_new0(QMPRequest, 1);\n+ req_obj->mon = mon;\n+ req_obj->id = id;\n+ req_obj->req = req;\n+\n+ /*\n+ * Put the request to the end of queue so that requests will be\n+ * handled in time order. Ownership for req_obj, req, id,\n+ * etc. will be delivered to the handler side.\n+ */\n+ g_queue_push_tail(mon_global.qmp_requests, req_obj);\n+\n+ /* Kick the dispatcher routine */\n+ qemu_bh_schedule(mon_global.qmp_dispatcher_bh);\n+}\n+\n static void monitor_qmp_read(void *opaque, const uint8_t *buf, int size)\n {\n Monitor *mon = opaque;\n@@ -4085,6 +4145,16 @@ static void monitor_io_thread_init(void)\n mon_global.mon_loop = g_main_loop_new(mon_global.mon_context, TRUE);\n qemu_thread_create(&mon_global.mon_io_thread, \"mon-io-thr\",\n monitor_io_thread, NULL, QEMU_THREAD_JOINABLE);\n+\n+ /*\n+ * This MUST be on main loop thread since we have commands that\n+ * have assumption to be run on main loop thread (Yeah, we'd\n+ * better remove this assumption in the future).\n+ */\n+ mon_global.qmp_dispatcher_bh = aio_bh_new(qemu_get_aio_context(),\n+ monitor_qmp_bh_dispatcher,\n+ NULL);\n+ mon_global.qmp_requests = g_queue_new();\n }\n \n void monitor_init_globals(void)\n@@ -4213,6 +4283,12 @@ void monitor_cleanup(void)\n qemu_mutex_unlock(&monitor_lock);\n \n monitor_io_thread_destroy();\n+\n+ qemu_bh_delete(mon_global.qmp_dispatcher_bh);\n+ mon_global.qmp_dispatcher_bh = NULL;\n+\n+ g_queue_free(mon_global.qmp_requests);\n+ mon_global.qmp_requests = NULL;\n }\n \n QemuOptsList qemu_mon_opts = {\n", "prefixes": [ "RFC", "11/15" ] }