QMP patches patches for 2021-02-04

-----BEGIN PGP SIGNATURE-----
 
 iQJGBAABCAAwFiEENUvIs9frKmtoZ05fOHC0AOuRhlMFAmAb5tsSHGFybWJydUBy
 ZWRoYXQuY29tAAoJEDhwtADrkYZTQMsQAJSlE7ns788RRhPH79kPh9yTFp8/DCWD
 vzNesSCMVp3o7a9DBPf2U2+oxHvF5HsLJG+2eqftouqlT4DWUtfYsBFPCsaHyPry
 KCAvrb3smP4GjedI5xpseyLKeW/c5SmNdwqahAD8ma/hAtJnoTBblphne88jYxj9
 Q2l/dUzQuIgPy+jZ2DjxQYam9Vu2l3svNLvMGMe5L6/TAcSoNJV3jJ14Wz7GjoL2
 If2LaHsvStFgMAniL16kv4OGd5c4jOy1QFdLGQQAbxavJsHQPhXGlq7xYRudXcdX
 vn2HH6WQHCfwFfxkPAqOgund3Bf/LacODD9+oNUhhWgeZUiZZfVGvHjmODp2gzHa
 b7m3YogIYHdr8taYemwEzuuhOR9I1gE/v4UvTokd3eXRY6HhkjTpwWjV06Codrhq
 DKAPcjRZ1Q4XZVWAURZBz7icGXc15EuuneC6ygIZDrR1Ez73xfJ82WUscNx6MujX
 8pOPgNmQtVCRqMFRlfvZl1cVCu9Qh/1pkeDDWjR80OxvNB4iYQKfvB1GLxZJL3Vx
 zsH8oVajd+8sXdUyUA1JTM5r7b9/6TJOlktHhZ9F3TDDVbwhmcBPgTWvRa139SVf
 SUkAMZjBFx/lsuuR8S3aOG+NftYQZs3TjPqWBklpXe1nEwOxjBipPDAZMq5xccVf
 DVrE5Ay2/1T0
 =l1y4
 -----END PGP SIGNATURE-----

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>
This commit is contained in:
Peter Maydell 2021-02-04 14:15:35 +00:00
commit 1ba089f225
7 changed files with 55 additions and 21 deletions

View File

@ -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.

View File

@ -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"

View File

@ -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);

View File

@ -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"

View File

@ -31,8 +31,7 @@ struct JSONToken {
char str[];
};
typedef struct JSONParserContext
{
typedef struct JSONParserContext {
Error *err;
JSONToken *current;
GQueue *buf;

View File

@ -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;
}

View File

@ -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;