mirror of https://github.com/xemu-project/xemu.git
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:
commit
1ba089f225
|
@ -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.
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -31,8 +31,7 @@ struct JSONToken {
|
|||
char str[];
|
||||
};
|
||||
|
||||
typedef struct JSONParserContext
|
||||
{
|
||||
typedef struct JSONParserContext {
|
||||
Error *err;
|
||||
JSONToken *current;
|
||||
GQueue *buf;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue