This is associates both QMP and HMP monitors with a character
device backend.

Reviewed-by: Marc-André Lureau <[email protected]>
Tested-by: Peter Krempa <[email protected]>
Signed-off-by: Daniel P. Berrangé <[email protected]>
---
 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

Reply via email to