diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2021-02-04 14:15:35 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2021-02-04 14:15:35 +0000 |
commit | 1ba089f2255bfdb071be3ce6ac6c3069e8012179 (patch) | |
tree | 4fb5645e5c3db6ceca5d12e5980345a51fe2af1b | |
parent | db754f8ccaf2f073c9aed46a4389e9c0c2080399 (diff) | |
parent | 88daf0996cd0488e93e67bcb0af258f2c24f117a (diff) |
Merge remote-tracking branch 'remotes/armbru/tags/pull-qmp-2021-02-04' into staging
QMP patches patches for 2021-02-04
# gpg: Signature made Thu 04 Feb 2021 12:21:47 GMT
# gpg: using RSA key 354BC8B3D7EB2A6B68674E5F3870B400EB918653
# gpg: issuer "armbru@redhat.com"
# gpg: Good signature from "Markus Armbruster <armbru@redhat.com>" [full]
# gpg: aka "Markus Armbruster <armbru@pond.sub.org>" [full]
# Primary key fingerprint: 354B C8B3 D7EB 2A6B 6867 4E5F 3870 B400 EB91 8653
* remotes/armbru/tags/pull-qmp-2021-02-04:
qmp: Resume OOB-enabled monitor before processing the request
qmp: Add more tracepoints
qmp: Fix up comments after commit 9ce44e2ce2
docs/interop/qmp-spec: Document the request queue limit
qobject: braces {} are necessary for all arms of this statement
qobject: spaces required around that operators
qobject: code indent should never use tabs
qobject: open brace '{' following struct go on the same line
monitor/qmp-cmds.c: Don't include ui/vnc.h
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | docs/interop/qmp-spec.txt | 8 | ||||
-rw-r--r-- | monitor/qmp-cmds.c | 2 | ||||
-rw-r--r-- | monitor/qmp.c | 44 | ||||
-rw-r--r-- | monitor/trace-events | 4 | ||||
-rw-r--r-- | qobject/json-parser.c | 3 | ||||
-rw-r--r-- | qobject/qdict.c | 12 | ||||
-rw-r--r-- | qobject/qjson.c | 3 |
7 files changed, 55 insertions, 21 deletions
diff --git a/docs/interop/qmp-spec.txt b/docs/interop/qmp-spec.txt index cdf5842555..b0e8351d5b 100644 --- a/docs/interop/qmp-spec.txt +++ b/docs/interop/qmp-spec.txt @@ -133,9 +133,11 @@ to pass "id" with out-of-band commands. Passing it with all commands is recommended for clients that accept capability "oob". If the client sends in-band commands faster than the server can -execute them, the server will stop reading the requests from the QMP -channel until the request queue length is reduced to an acceptable -range. +execute them, the server will stop reading requests until the request +queue length is reduced to an acceptable range. + +To ensure commands to be executed out-of-band get read and executed, +the client should have at most eight in-band commands in flight. Only a few commands support out-of-band execution. The ones that do have "allow-oob": true in output of query-qmp-schema. diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c index 990936136c..c7df8c0ee2 100644 --- a/monitor/qmp-cmds.c +++ b/monitor/qmp-cmds.c @@ -23,7 +23,7 @@ #include "qemu/uuid.h" #include "chardev/char.h" #include "ui/qemu-spice.h" -#include "ui/vnc.h" +#include "ui/console.h" #include "sysemu/kvm.h" #include "sysemu/runstate.h" #include "sysemu/runstate-action.h" diff --git a/monitor/qmp.c b/monitor/qmp.c index 8f91af32be..43880fa623 100644 --- a/monitor/qmp.c +++ b/monitor/qmp.c @@ -79,7 +79,7 @@ static void monitor_qmp_cleanup_queue_and_resume(MonitorQMP *mon) qemu_mutex_lock(&mon->qmp_queue_lock); /* - * Same condition as in monitor_qmp_bh_dispatcher(), but before + * Same condition as in monitor_qmp_dispatcher_co(), but before * removing an element from the queue (hence no `- 1`). * Also, the queue should not be empty either, otherwise the * monitor hasn't been suspended yet (or was already resumed). @@ -113,6 +113,7 @@ void qmp_send_response(MonitorQMP *mon, const QDict *rsp) json = qobject_to_json_pretty(data, mon->pretty); assert(json != NULL); + trace_monitor_qmp_respond(mon, json->str); g_string_append_c(json, '\n'); monitor_puts(&mon->common, json->str); @@ -213,7 +214,7 @@ void coroutine_fn monitor_qmp_dispatcher_co(void *data) { QMPRequest *req_obj = NULL; QDict *rsp; - bool need_resume; + bool oob_enabled; MonitorQMP *mon; while (true) { @@ -251,6 +252,9 @@ void coroutine_fn monitor_qmp_dispatcher_co(void *data) } } + trace_monitor_qmp_in_band_dequeue(req_obj, + req_obj->mon->qmp_requests->length); + if (qatomic_xchg(&qmp_dispatcher_co_busy, true) == true) { /* * Someone rescheduled us (probably because a new requests @@ -269,11 +273,32 @@ void coroutine_fn monitor_qmp_dispatcher_co(void *data) aio_co_schedule(qemu_get_aio_context(), qmp_dispatcher_co); qemu_coroutine_yield(); + /* + * @req_obj has a request, we hold req_obj->mon->qmp_queue_lock + */ + mon = req_obj->mon; - /* qmp_oob_enabled() might change after "qmp_capabilities" */ - need_resume = !qmp_oob_enabled(mon) || - mon->qmp_requests->length == QMP_REQ_QUEUE_LEN_MAX - 1; + + /* + * We need to resume the monitor if handle_qmp_command() + * suspended it. Two cases: + * 1. OOB enabled: mon->qmp_requests has no more space + * Resume right away, so that OOB commands can get executed while + * this request is being processed. + * 2. OOB disabled: always + * Resume only after we're done processing the request, + * We need to save qmp_oob_enabled() for later, because + * qmp_qmp_capabilities() can change it. + */ + oob_enabled = qmp_oob_enabled(mon); + if (oob_enabled + && mon->qmp_requests->length == QMP_REQ_QUEUE_LEN_MAX - 1) { + monitor_resume(&mon->common); + } + qemu_mutex_unlock(&mon->qmp_queue_lock); + + /* Process request */ if (req_obj->req) { if (trace_event_get_state(TRACE_MONITOR_QMP_CMD_IN_BAND)) { QDict *qdict = qobject_to(QDict, req_obj->req); @@ -287,16 +312,17 @@ void coroutine_fn monitor_qmp_dispatcher_co(void *data) monitor_qmp_dispatch(mon, req_obj->req); } else { assert(req_obj->err); + trace_monitor_qmp_err_in_band(error_get_pretty(req_obj->err)); rsp = qmp_error_response(req_obj->err); req_obj->err = NULL; monitor_qmp_respond(mon, rsp); qobject_unref(rsp); } - if (need_resume) { - /* Pairs with the monitor_suspend() in handle_qmp_command() */ + if (!oob_enabled) { monitor_resume(&mon->common); } + qmp_request_free(req_obj); /* @@ -349,7 +375,7 @@ static void handle_qmp_command(void *opaque, QObject *req, Error *err) /* * Suspend the monitor when we can't queue more requests after - * this one. Dequeuing in monitor_qmp_bh_dispatcher() or + * this one. Dequeuing in monitor_qmp_dispatcher_co() or * monitor_qmp_cleanup_queue_and_resume() will resume it. * Note that when OOB is disabled, we queue at most one command, * for backward compatibility. @@ -364,6 +390,8 @@ static void handle_qmp_command(void *opaque, QObject *req, Error *err) * handled in time order. Ownership for req_obj, req, * etc. will be delivered to the handler side. */ + trace_monitor_qmp_in_band_enqueue(req_obj, mon, + mon->qmp_requests->length); assert(mon->qmp_requests->length < QMP_REQ_QUEUE_LEN_MAX); g_queue_push_tail(mon->qmp_requests, req_obj); qemu_mutex_unlock(&mon->qmp_queue_lock); diff --git a/monitor/trace-events b/monitor/trace-events index 0365ac4d99..348dcfca9b 100644 --- a/monitor/trace-events +++ b/monitor/trace-events @@ -10,6 +10,10 @@ monitor_protocol_event_queue(uint32_t event, void *qdict, uint64_t rate) "event= monitor_suspend(void *ptr, int cnt) "mon %p: %d" # qmp.c +monitor_qmp_in_band_enqueue(void *req, void *mon, unsigned len) "%p mon %p len %u" +monitor_qmp_in_band_dequeue(void *req, unsigned len) "%p len %u" monitor_qmp_cmd_in_band(const char *id) "%s" +monitor_qmp_err_in_band(const char *desc) "%s" monitor_qmp_cmd_out_of_band(const char *id) "%s" +monitor_qmp_respond(void *mon, const char *json) "mon %p resp: %s" handle_qmp_command(void *mon, const char *req) "mon %p req: %s" diff --git a/qobject/json-parser.c b/qobject/json-parser.c index d351039b10..008b326fb8 100644 --- a/qobject/json-parser.c +++ b/qobject/json-parser.c @@ -31,8 +31,7 @@ struct JSONToken { char str[]; }; -typedef struct JSONParserContext -{ +typedef struct JSONParserContext { Error *err; JSONToken *current; GQueue *buf; diff --git a/qobject/qdict.c b/qobject/qdict.c index d84443391e..0216ca7ac1 100644 --- a/qobject/qdict.c +++ b/qobject/qdict.c @@ -39,12 +39,13 @@ QDict *qdict_new(void) */ static unsigned int tdb_hash(const char *name) { - unsigned value; /* Used to compute the hash value. */ - unsigned i; /* Used to cycle through random values. */ + unsigned value; /* Used to compute the hash value. */ + unsigned i; /* Used to cycle through random values. */ /* Set the initial value from the key size. */ - for (value = 0x238F13AF * strlen(name), i=0; name[i]; i++) - value = (value + (((const unsigned char *)name)[i] << (i*5 % 24))); + for (value = 0x238F13AF * strlen(name), i = 0; name[i]; i++) { + value = (value + (((const unsigned char *)name)[i] << (i * 5 % 24))); + } return (1103515243 * value + 12345); } @@ -93,8 +94,9 @@ static QDictEntry *qdict_find(const QDict *qdict, QDictEntry *entry; QLIST_FOREACH(entry, &qdict->table[bucket], next) - if (!strcmp(entry->key, key)) + if (!strcmp(entry->key, key)) { return entry; + } return NULL; } diff --git a/qobject/qjson.c b/qobject/qjson.c index bcc376e626..167fcb429c 100644 --- a/qobject/qjson.c +++ b/qobject/qjson.c @@ -22,8 +22,7 @@ #include "qapi/qmp/qnum.h" #include "qapi/qmp/qstring.h" -typedef struct JSONParsingState -{ +typedef struct JSONParsingState { JSONMessageParser parser; QObject *result; Error *err; |