* [Qemu-devel] [PULL 1/6] monitor: simplify monitor_qmp_setup_handlers_bh
2018-09-01 11:17 [Qemu-devel] [PULL 0/6] Monitor patches for 2018-09-01 Markus Armbruster
@ 2018-09-01 11:17 ` Markus Armbruster
2018-09-01 11:17 ` [Qemu-devel] [PULL 2/6] monitor: accept input on resume Markus Armbruster
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Markus Armbruster @ 2018-09-01 11:17 UTC (permalink / raw)
To: qemu-devel; +Cc: Peter Xu
From: Peter Xu <peterx@redhat.com>
When we reach monitor_qmp_setup_handlers_bh() we must be using the
IOThread then, so no need to check against it any more. Instead, we
assert.
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
Message-Id: <20180815133747.25032-2-peterx@redhat.com>
[Insufficiently useful comment dropped]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
monitor.c | 12 +++---------
1 file changed, 3 insertions(+), 9 deletions(-)
diff --git a/monitor.c b/monitor.c
index 021c11b1bf..c049776603 100644
--- a/monitor.c
+++ b/monitor.c
@@ -4631,15 +4631,9 @@ static void monitor_qmp_setup_handlers_bh(void *opaque)
Monitor *mon = opaque;
GMainContext *context;
- if (mon->use_io_thread) {
- /* Use @mon_iothread context */
- context = monitor_get_io_context();
- assert(context);
- } else {
- /* Use default main loop context */
- context = NULL;
- }
-
+ assert(mon->use_io_thread);
+ context = monitor_get_io_context();
+ assert(context);
qemu_chr_fe_set_handlers(&mon->chr, monitor_can_read, monitor_qmp_read,
monitor_qmp_event, NULL, mon, context, true);
monitor_list_append(mon);
--
2.17.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PULL 2/6] monitor: accept input on resume
2018-09-01 11:17 [Qemu-devel] [PULL 0/6] Monitor patches for 2018-09-01 Markus Armbruster
2018-09-01 11:17 ` [Qemu-devel] [PULL 1/6] monitor: simplify monitor_qmp_setup_handlers_bh Markus Armbruster
@ 2018-09-01 11:17 ` Markus Armbruster
2018-09-01 11:17 ` [Qemu-devel] [PULL 3/6] monitor: consitify qmp_send_response() QDict argument Markus Armbruster
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Markus Armbruster @ 2018-09-01 11:17 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
From: Marc-André Lureau <marcandre.lureau@redhat.com>
A chardev may stop trying to write if the associated can_read()
callback returned 0. This happens when the monitor is suspended.
The frontend is supposed to call qemu_chr_fe_accept_input() when it is
ready to accept data again.
An issue was observed with a spice port: pending commands may be
delayed, as the chardev is not flushed. Most chardev don't use the
accept_input() callback, and instead check regularly if they can
write. The ones that do use it are braille, mux, msmouse,
spice (abstract), spicevmc, spiceport, wctablet.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20180817173752.19136-1-marcandre.lureau@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
monitor.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/monitor.c b/monitor.c
index c049776603..c1add2ce09 100644
--- a/monitor.c
+++ b/monitor.c
@@ -4411,6 +4411,7 @@ void monitor_resume(Monitor *mon)
assert(mon->rs);
readline_show_prompt(mon->rs);
}
+ qemu_chr_fe_accept_input(&mon->chr);
}
trace_monitor_suspend(mon, -1);
}
--
2.17.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PULL 3/6] monitor: consitify qmp_send_response() QDict argument
2018-09-01 11:17 [Qemu-devel] [PULL 0/6] Monitor patches for 2018-09-01 Markus Armbruster
2018-09-01 11:17 ` [Qemu-devel] [PULL 1/6] monitor: simplify monitor_qmp_setup_handlers_bh Markus Armbruster
2018-09-01 11:17 ` [Qemu-devel] [PULL 2/6] monitor: accept input on resume Markus Armbruster
@ 2018-09-01 11:17 ` Markus Armbruster
2018-09-01 11:17 ` [Qemu-devel] [PULL 4/6] qmp: constify qmp_is_oob() Markus Armbruster
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Markus Armbruster @ 2018-09-01 11:17 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
From: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <20180829134043.31706-2-marcandre.lureau@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
monitor.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/monitor.c b/monitor.c
index c1add2ce09..bd0810df4d 100644
--- a/monitor.c
+++ b/monitor.c
@@ -503,9 +503,9 @@ int monitor_fprintf(FILE *stream, const char *fmt, ...)
return 0;
}
-static void qmp_send_response(Monitor *mon, QDict *rsp)
+static void qmp_send_response(Monitor *mon, const QDict *rsp)
{
- QObject *data = QOBJECT(rsp);
+ const QObject *data = QOBJECT(rsp);
QString *json;
json = mon->flags & MONITOR_USE_PRETTY ? qobject_to_json_pretty(data) :
--
2.17.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PULL 4/6] qmp: constify qmp_is_oob()
2018-09-01 11:17 [Qemu-devel] [PULL 0/6] Monitor patches for 2018-09-01 Markus Armbruster
` (2 preceding siblings ...)
2018-09-01 11:17 ` [Qemu-devel] [PULL 3/6] monitor: consitify qmp_send_response() QDict argument Markus Armbruster
@ 2018-09-01 11:17 ` Markus Armbruster
2018-09-01 11:17 ` [Qemu-devel] [PULL 5/6] Revert "qmp: isolate responses into io thread" Markus Armbruster
2018-09-01 11:17 ` [Qemu-devel] [PULL 6/6] monitor: no need to save need_resume Markus Armbruster
5 siblings, 0 replies; 7+ messages in thread
From: Markus Armbruster @ 2018-09-01 11:17 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
From: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <20180829134043.31706-3-marcandre.lureau@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
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 4e2e749faf..68a528a9aa 100644
--- a/include/qapi/qmp/dispatch.h
+++ b/include/qapi/qmp/dispatch.h
@@ -50,7 +50,7 @@ bool qmp_has_success_response(const QmpCommand *cmd);
QDict *qmp_error_response(Error *err);
QDict *qmp_dispatch(QmpCommandList *cmds, QObject *request,
bool allow_oob);
-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 d8da1a62de..1d922e04f7 100644
--- a/qapi/qmp-dispatch.c
+++ b/qapi/qmp-dispatch.c
@@ -155,7 +155,7 @@ QDict *qmp_error_response(Error *err)
/*
* Does @qdict look like a command to be run out-of-band?
*/
-bool qmp_is_oob(QDict *dict)
+bool qmp_is_oob(const QDict *dict)
{
return qdict_haskey(dict, "exec-oob")
&& !qdict_haskey(dict, "execute");
--
2.17.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PULL 5/6] Revert "qmp: isolate responses into io thread"
2018-09-01 11:17 [Qemu-devel] [PULL 0/6] Monitor patches for 2018-09-01 Markus Armbruster
` (3 preceding siblings ...)
2018-09-01 11:17 ` [Qemu-devel] [PULL 4/6] qmp: constify qmp_is_oob() Markus Armbruster
@ 2018-09-01 11:17 ` Markus Armbruster
2018-09-01 11:17 ` [Qemu-devel] [PULL 6/6] monitor: no need to save need_resume Markus Armbruster
5 siblings, 0 replies; 7+ messages in thread
From: Markus Armbruster @ 2018-09-01 11:17 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
From: Marc-André Lureau <marcandre.lureau@redhat.com>
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 the watcher in the associated
IOThread.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <20180829134043.31706-4-marcandre.lureau@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
monitor.c | 120 ++----------------------------------------------------
1 file changed, 3 insertions(+), 117 deletions(-)
diff --git a/monitor.c b/monitor.c
index bd0810df4d..25f656bf8a 100644
--- a/monitor.c
+++ b/monitor.c
@@ -182,8 +182,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;
/*
@@ -247,9 +245,6 @@ IOThread *mon_iothread;
/* Bottom half to dispatch the requests received from I/O thread */
QEMUBH *qmp_dispatcher_bh;
-/* Bottom half to deliver the responses back to clients */
-QEMUBH *qmp_respond_bh;
-
struct QMPRequest {
/* Owner of the request */
Monitor *mon;
@@ -375,19 +370,10 @@ static void monitor_qmp_cleanup_req_queue_locked(Monitor *mon)
}
}
-/* Caller must hold the mon->qmp.qmp_queue_lock */
-static void monitor_qmp_cleanup_resp_queue_locked(Monitor *mon)
-{
- while (!g_queue_is_empty(mon->qmp.qmp_responses)) {
- qobject_unref((QDict *)g_queue_pop_head(mon->qmp.qmp_responses));
- }
-}
-
static void monitor_qmp_cleanup_queues(Monitor *mon)
{
qemu_mutex_lock(&mon->qmp.qmp_queue_lock);
monitor_qmp_cleanup_req_queue_locked(mon);
- monitor_qmp_cleanup_resp_queue_locked(mon);
qemu_mutex_unlock(&mon->qmp.qmp_queue_lock);
}
@@ -518,85 +504,6 @@ static void qmp_send_response(Monitor *mon, const QDict *rsp)
qobject_unref(json);
}
-static void qmp_queue_response(Monitor *mon, QDict *rsp)
-{
- if (mon->use_io_thread) {
- /*
- * Push a reference to the response queue. The I/O thread
- * drains that queue and emits.
- */
- qemu_mutex_lock(&mon->qmp.qmp_queue_lock);
- g_queue_push_tail(mon->qmp.qmp_responses, qobject_ref(rsp));
- qemu_mutex_unlock(&mon->qmp.qmp_queue_lock);
- qemu_bh_schedule(qmp_respond_bh);
- } else {
- /*
- * Not using monitor I/O thread, i.e. we are in the main thread.
- * Emit right away.
- */
- qmp_send_response(mon, rsp);
- }
-}
-
-struct QMPResponse {
- Monitor *mon;
- QDict *data;
-};
-typedef struct QMPResponse QMPResponse;
-
-static QDict *monitor_qmp_response_pop_one(Monitor *mon)
-{
- QDict *data;
-
- 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);
-
- return data;
-}
-
-static void monitor_qmp_response_flush(Monitor *mon)
-{
- QDict *data;
-
- while ((data = monitor_qmp_response_pop_one(mon))) {
- qmp_send_response(mon, data);
- qobject_unref(data);
- }
-}
-
-/*
- * Pop a QMPResponse from any monitor's response queue into @response.
- * Return false if all the queues are empty; else true.
- */
-static bool monitor_qmp_response_pop_any(QMPResponse *response)
-{
- Monitor *mon;
- QDict *data = NULL;
-
- qemu_mutex_lock(&monitor_lock);
- QTAILQ_FOREACH(mon, &mon_list, entry) {
- data = monitor_qmp_response_pop_one(mon);
- if (data) {
- response->mon = mon;
- response->data = data;
- break;
- }
- }
- qemu_mutex_unlock(&monitor_lock);
- return data != NULL;
-}
-
-static void monitor_qmp_bh_responder(void *opaque)
-{
- QMPResponse response;
-
- while (monitor_qmp_response_pop_any(&response)) {
- qmp_send_response(response.mon, response.data);
- qobject_unref(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 },
@@ -620,7 +527,7 @@ static void monitor_qapi_event_emit(QAPIEvent event, QDict *qdict)
QTAILQ_FOREACH(mon, &mon_list, entry) {
if (monitor_is_qmp(mon)
&& mon->qmp.commands != &qmp_cap_negotiation_commands) {
- qmp_queue_response(mon, qdict);
+ qmp_send_response(mon, qdict);
}
}
}
@@ -818,7 +725,6 @@ static void monitor_data_init(Monitor *mon, bool skip_flush,
mon->skip_flush = skip_flush;
mon->use_io_thread = use_io_thread;
mon->qmp.qmp_requests = g_queue_new();
- mon->qmp.qmp_responses = g_queue_new();
}
static void monitor_data_destroy(Monitor *mon)
@@ -833,9 +739,7 @@ static void monitor_data_destroy(Monitor *mon)
qemu_mutex_destroy(&mon->mon_lock);
qemu_mutex_destroy(&mon->qmp.qmp_queue_lock);
monitor_qmp_cleanup_req_queue_locked(mon);
- monitor_qmp_cleanup_resp_queue_locked(mon);
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,
@@ -4152,7 +4056,7 @@ static void monitor_qmp_respond(Monitor *mon, QDict *rsp, QObject *id)
qdict_put_obj(rsp, "id", qobject_ref(id));
}
- qmp_queue_response(mon, rsp);
+ qmp_send_response(mon, rsp);
}
}
@@ -4445,7 +4349,7 @@ static void monitor_qmp_event(void *opaque, int event)
mon->qmp.commands = &qmp_cap_negotiation_commands;
monitor_qmp_caps_reset(mon);
data = qmp_greeting(mon);
- qmp_queue_response(mon, data);
+ qmp_send_response(mon, data);
qobject_unref(data);
mon_refcount++;
break;
@@ -4456,7 +4360,6 @@ static void monitor_qmp_event(void *opaque, int event)
* stdio, it's possible that stdout is still open when stdin
* is closed.
*/
- monitor_qmp_response_flush(mon);
monitor_qmp_cleanup_queues(mon);
json_message_parser_destroy(&mon->qmp.parser);
json_message_parser_init(&mon->qmp.parser, handle_qmp_command,
@@ -4559,15 +4462,6 @@ static void monitor_iothread_init(void)
qmp_dispatcher_bh = aio_bh_new(iohandler_get_aio_context(),
monitor_qmp_bh_dispatcher,
NULL);
-
- /*
- * The responder BH must be run in the monitor I/O thread, so that
- * monitors that are using the I/O thread have their output
- * written by the I/O thread.
- */
- qmp_respond_bh = aio_bh_new(monitor_get_aio_context(),
- monitor_qmp_bh_responder,
- NULL);
}
void monitor_init_globals(void)
@@ -4714,12 +4608,6 @@ void monitor_cleanup(void)
*/
iothread_stop(mon_iothread);
- /*
- * Flush all response queues. Note that even after this flush,
- * data may remain in output buffers.
- */
- monitor_qmp_bh_responder(NULL);
-
/* Flush output buffers and destroy monitors */
qemu_mutex_lock(&monitor_lock);
QTAILQ_FOREACH_SAFE(mon, &mon_list, entry, next) {
@@ -4733,8 +4621,6 @@ void monitor_cleanup(void)
/* QEMUBHs needs to be deleted before destroying the I/O thread */
qemu_bh_delete(qmp_dispatcher_bh);
qmp_dispatcher_bh = NULL;
- qemu_bh_delete(qmp_respond_bh);
- qmp_respond_bh = NULL;
iothread_destroy(mon_iothread);
mon_iothread = NULL;
--
2.17.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Qemu-devel] [PULL 6/6] monitor: no need to save need_resume
2018-09-01 11:17 [Qemu-devel] [PULL 0/6] Monitor patches for 2018-09-01 Markus Armbruster
` (4 preceding siblings ...)
2018-09-01 11:17 ` [Qemu-devel] [PULL 5/6] Revert "qmp: isolate responses into io thread" Markus Armbruster
@ 2018-09-01 11:17 ` Markus Armbruster
5 siblings, 0 replies; 7+ messages in thread
From: Markus Armbruster @ 2018-09-01 11:17 UTC (permalink / raw)
To: qemu-devel; +Cc: Marc-André Lureau
From: Marc-André Lureau <marcandre.lureau@redhat.com>
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 <marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <20180829134043.31706-5-marcandre.lureau@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
monitor.c | 13 ++++---------
1 file changed, 4 insertions(+), 9 deletions(-)
diff --git a/monitor.c b/monitor.c
index 25f656bf8a..cf3b629cf7 100644
--- a/monitor.c
+++ b/monitor.c
@@ -256,12 +256,6 @@ struct QMPRequest {
*/
QObject *req;
Error *err;
- /*
- * 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;
@@ -4131,11 +4125,14 @@ static void monitor_qmp_bh_dispatcher(void *data)
{
QMPRequest *req_obj = monitor_qmp_requests_pop_any();
QDict *rsp;
+ bool need_resume;
if (!req_obj) {
return;
}
+ /* qmp_oob_enabled() might change after "qmp_capabilities" */
+ need_resume = !qmp_oob_enabled(req_obj->mon);
if (req_obj->req) {
trace_monitor_qmp_cmd_in_band(qobject_get_try_str(req_obj->id) ?: "");
monitor_qmp_dispatch(req_obj->mon, req_obj->req, req_obj->id);
@@ -4147,7 +4144,7 @@ static void monitor_qmp_bh_dispatcher(void *data)
qobject_unref(rsp);
}
- if (req_obj->need_resume) {
+ if (need_resume) {
/* Pairs with the monitor_suspend() in handle_qmp_command() */
monitor_resume(req_obj->mon);
}
@@ -4195,7 +4192,6 @@ static void handle_qmp_command(void *opaque, QObject *req, Error *err)
req_obj->id = id;
req_obj->req = req;
req_obj->err = err;
- req_obj->need_resume = false;
/* Protect qmp_requests and fetching its length. */
qemu_mutex_lock(&mon->qmp.qmp_queue_lock);
@@ -4208,7 +4204,6 @@ static void handle_qmp_command(void *opaque, QObject *req, Error *err)
*/
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) {
--
2.17.1
^ permalink raw reply related [flat|nested] 7+ messages in thread