From: Li Zhang <[email protected]> For some scenarios, it needs to hot-add a monitor device. But QEMU doesn't support hotplug yet. It also works by adding a monitor with null backend by default and then change its backend to socket by QMP command "chardev-change".
So this patch is to support monitor chardev hotswap with QMP. Signed-off-by: Li Zhang <[email protected]> --- monitor/monitor-internal.h | 3 +++ monitor/monitor.c | 2 +- monitor/qmp.c | 42 +++++++++++++++++++++++++++++++++++--- 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/monitor/monitor-internal.h b/monitor/monitor-internal.h index 40903d6386..2df6dd21de 100644 --- a/monitor/monitor-internal.h +++ b/monitor/monitor-internal.h @@ -186,4 +186,7 @@ int hmp_compare_cmd(const char *name, const char *list); void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data, Error **errp); +gboolean monitor_unblocked(GIOChannel *chan, GIOCondition cond, + void *opaque); + #endif diff --git a/monitor/monitor.c b/monitor/monitor.c index e94f532cf5..2d255bab18 100644 --- a/monitor/monitor.c +++ b/monitor/monitor.c @@ -157,7 +157,7 @@ static inline bool monitor_is_hmp_non_interactive(const Monitor *mon) static void monitor_flush_locked(Monitor *mon); -static gboolean monitor_unblocked(GIOChannel *chan, GIOCondition cond, +gboolean monitor_unblocked(GIOChannel *chan, GIOCondition cond, void *opaque) { Monitor *mon = opaque; diff --git a/monitor/qmp.c b/monitor/qmp.c index 2326bd7f9b..55cfb230d9 100644 --- a/monitor/qmp.c +++ b/monitor/qmp.c @@ -44,6 +44,7 @@ struct QMPRequest { Error *err; }; typedef struct QMPRequest QMPRequest; +static void monitor_qmp_set_handlers_bh(void *opaque); QmpCommandList qmp_commands, qmp_cap_negotiation_commands; @@ -480,7 +481,35 @@ void monitor_data_destroy_qmp(MonitorQMP *mon) g_queue_free(mon->qmp_requests); } -static void monitor_qmp_setup_handlers_bh(void *opaque) +static int monitor_qmp_change(void *opaque) +{ + MonitorQMP *mon = opaque; + + mon->common.use_io_thread = + qemu_chr_has_feature(mon->common.chr.chr, QEMU_CHAR_FEATURE_GCONTEXT); + + if (mon->common.use_io_thread) { + aio_bh_schedule_oneshot(iothread_get_aio_context(mon_iothread), + monitor_qmp_set_handlers_bh, mon); + } else { + qemu_chr_fe_set_handlers(&mon->common.chr, monitor_can_read, + monitor_qmp_read, monitor_qmp_event, + monitor_qmp_change, &mon->common, NULL, true); + } + + if (mon->common.out_watch) { + g_source_remove(mon->common.out_watch); + qemu_mutex_lock(&mon->common.mon_lock); + mon->common.out_watch = + qemu_chr_fe_add_watch(&mon->common.chr, G_IO_OUT | G_IO_HUP, + monitor_unblocked, &mon->common); + qemu_mutex_unlock(&mon->common.mon_lock); + } + + return 0; +} + +static void monitor_qmp_set_handlers_bh(void *opaque) { MonitorQMP *mon = opaque; GMainContext *context; @@ -490,7 +519,14 @@ static void monitor_qmp_setup_handlers_bh(void *opaque) assert(context); qemu_chr_fe_set_handlers(&mon->common.chr, monitor_can_read, monitor_qmp_read, monitor_qmp_event, - NULL, &mon->common, context, true); + monitor_qmp_change, &mon->common, context, true); + +} + +static void monitor_qmp_setup_handlers_bh(void *opaque) +{ + MonitorQMP *mon = opaque; + monitor_qmp_set_handlers_bh(mon); monitor_list_append(&mon->common); } @@ -531,7 +567,7 @@ void monitor_init_qmp(Chardev *chr, bool pretty, Error **errp) } else { qemu_chr_fe_set_handlers(&mon->common.chr, monitor_can_read, monitor_qmp_read, monitor_qmp_event, - NULL, &mon->common, NULL, true); + monitor_qmp_change, &mon->common, NULL, true); monitor_list_append(&mon->common); } } -- 2.25.1
