This is associates both QMP and HMP monitors with a character
device backend.
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Tested-by: Peter Krempa <pkrempa@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
monitor/hmp.c | 24 ++++++++++--------------
monitor/monitor-internal.h | 2 ++
monitor/monitor.c | 36 ++++++++++++++++++++++++++++++++++++
monitor/qmp.c | 33 +++++++++++++++------------------
4 files changed, 63 insertions(+), 32 deletions(-)
diff --git a/monitor/hmp.c b/monitor/hmp.c
index 1704166326..34a39b071c 100644
--- a/monitor/hmp.c
+++ b/monitor/hmp.c
@@ -1542,28 +1542,24 @@ static void monitor_readline_flush(void *opaque)
void monitor_new_hmp(const char *id, const char *chardev_id,
bool use_readline, Error **errp)
{
+ ERRP_GUARD();
MonitorHMP *mon;
g_autofree char *autoid = id ? NULL : monitor_compat_id();
- Chardev *chr;
- Object *obj;
+ Object *obj = object_new_with_props(TYPE_MONITOR_HMP,
+ object_get_objects_root(),
+ id ? id : autoid,
+ errp,
+ "chardev", chardev_id,
+ NULL);
- chr = qemu_chr_find(chardev_id);
- if (chr == NULL) {
- error_setg(errp, "chardev \"%s\" not found", chardev_id);
- return;
- }
-
- obj = object_new_with_props(TYPE_MONITOR_HMP,
- object_get_objects_root(),
- id ? id : autoid,
- errp,
- NULL);
if (!obj) {
return;
}
+
mon = MONITOR_HMP(obj);
- if (!qemu_chr_fe_init(&mon->parent_obj.chr, chr, errp)) {
+ monitor_complete(MONITOR(mon), errp);
+ if (*errp) {
object_unparent(OBJECT(mon));
return;
}
diff --git a/monitor/monitor-internal.h b/monitor/monitor-internal.h
index 05c1f2f5e0..145d52fd71 100644
--- a/monitor/monitor-internal.h
+++ b/monitor/monitor-internal.h
@@ -108,6 +108,7 @@ struct MonitorClass {
struct Monitor {
Object parent;
+ char *chardev_id;
CharFrontend chr;
int suspend_cnt; /* Needs to be accessed atomically */
bool is_qmp;
@@ -192,6 +193,7 @@ extern QmpCommandList qmp_commands, qmp_cap_negotiation_commands;
extern QemuMutex monitor_lock;
extern MonitorList mon_list;
+void monitor_complete(Monitor *mon, Error **errp);
void monitor_data_init(Monitor *mon, bool is_qmp, bool skip_flush,
bool use_io_thread);
void monitor_data_destroy(Monitor *mon);
diff --git a/monitor/monitor.c b/monitor/monitor.c
index cb0299a2f7..1648946c92 100644
--- a/monitor/monitor.c
+++ b/monitor/monitor.c
@@ -79,10 +79,31 @@ OBJECT_DEFINE_ABSTRACT_TYPE(Monitor, monitor, MONITOR, OBJECT);
static void monitor_finalize(Object *obj)
{
+ Monitor *mon = MONITOR(obj);
+
+ g_free(mon->chardev_id);
+}
+
+static char *monitor_get_chardev_id(Object *obj, Error **errp)
+{
+ Monitor *mon = MONITOR(obj);
+
+ return g_strdup(mon->chardev_id);
+}
+
+static void monitor_set_chardev_id(Object *obj, const char *str, Error **errp)
+{
+ Monitor *mon = MONITOR(obj);
+
+ g_free(mon->chardev_id);
+ mon->chardev_id = g_strdup(str);
}
static void monitor_class_init(ObjectClass *cls, const void *data)
{
+ object_class_property_add_str(cls, "chardev",
+ monitor_get_chardev_id,
+ monitor_set_chardev_id);
}
static void monitor_init(Object *obj)
@@ -738,6 +759,21 @@ char *monitor_compat_id(void)
return g_strdup_printf("compat_monitor%d", monitor_device_index++);
}
+void monitor_complete(Monitor *mon, Error **errp)
+{
+ if (mon->chardev_id) {
+ Chardev *chr = qemu_chr_find(mon->chardev_id);
+ if (chr == NULL) {
+ error_setg(errp, "chardev \"%s\" not found", mon->chardev_id);
+ return;
+ }
+
+ if (!qemu_chr_fe_init(&mon->chr, chr, errp)) {
+ return;
+ }
+ }
+}
+
int monitor_new(MonitorOptions *opts, bool allow_hmp, Error **errp)
{
ERRP_GUARD();
diff --git a/monitor/qmp.c b/monitor/qmp.c
index e2f841212b..df35b530ed 100644
--- a/monitor/qmp.c
+++ b/monitor/qmp.c
@@ -530,36 +530,33 @@ static void monitor_qmp_setup_handlers_bh(void *opaque)
void monitor_new_qmp(const char *id, const char *chardev_id,
bool pretty, Error **errp)
{
+ ERRP_GUARD();
MonitorQMP *mon;
g_autofree char *autoid = id ? NULL : monitor_compat_id();
- Chardev *chr;
- Object *obj;
+ Object *obj = object_new_with_props(TYPE_MONITOR_QMP,
+ object_get_objects_root(),
+ id ? id : autoid,
+ errp,
+ "chardev", chardev_id,
+ NULL);
- chr = qemu_chr_find(chardev_id);
- if (chr == NULL) {
- error_setg(errp, "chardev \"%s\" not found", chardev_id);
- return;
- }
-
- obj = object_new_with_props(TYPE_MONITOR_QMP,
- object_get_objects_root(),
- id ? id : autoid,
- errp,
- NULL);
if (!obj) {
return;
}
- mon = MONITOR_QMP(obj);
- if (!qemu_chr_fe_init(&mon->parent_obj.chr, chr, errp)) {
+ mon = MONITOR_QMP(obj);
+ monitor_complete(MONITOR(mon), errp);
+ if (*errp) {
object_unparent(OBJECT(mon));
return;
}
+
qemu_chr_fe_set_echo(&mon->parent_obj.chr, true);
/* Note: we run QMP monitor in I/O thread when @chr supports that */
monitor_data_init(&mon->parent_obj, true, false,
- qemu_chr_has_feature(chr, QEMU_CHAR_FEATURE_GCONTEXT));
+ qemu_chr_has_feature(mon->parent_obj.chr.chr,
+ QEMU_CHAR_FEATURE_GCONTEXT));
mon->pretty = pretty;
@@ -572,12 +569,12 @@ void monitor_new_qmp(const char *id, const char *chardev_id,
* Make sure the old iowatch is gone. It's possible when
* e.g. the chardev is in client mode, with wait=on.
*/
- remove_fd_in_watch(chr);
+ remove_fd_in_watch(mon->parent_obj.chr.chr);
/*
* Clean up listener IO sources early to prevent racy fd
* handling between the main thread and the I/O thread.
*/
- remove_listener_fd_in_watch(chr);
+ remove_listener_fd_in_watch(mon->parent_obj.chr.chr);
/*
* We can't call qemu_chr_fe_set_handlers() directly here
* since chardev might be running in the monitor I/O
--
2.55.0