@samitouri / QOSamiQemu / commits / 1a65434329

monitor: add 'chardev' property to Monitor base class

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> Message-ID: <20260706135824.2623960-8-berrange@redhat.com> Signed-off-by: Markus Armbruster <armbru@redhat.com>

Daniel P. Berrangé committed Jul 6, 2026 at 14:57 UTC 1a65434329460e67436cf9331b8c7215efbcb74b
4 files changed +63 -32
monitor/hmp.c
+10 -14
@@ -1542,28 +1542,24 @@ static void monitor_readline_flush(void *opaque)
1542 void monitor_new_hmp(const char *id, const char *chardev_id,
1543 bool use_readline, Error **errp)
1544 {
1545 + ERRP_GUARD();
1546 MonitorHMP *mon;
1547 g_autofree char *autoid = id ? NULL : monitor_compat_id();
1547 - Chardev *chr;
1548 - Object *obj;
1548 + Object *obj = object_new_with_props(TYPE_MONITOR_HMP,
1549 + object_get_objects_root(),
1550 + id ? id : autoid,
1551 + errp,
1552 + "chardev", chardev_id,
1553 + NULL);
1554
1550 - chr = qemu_chr_find(chardev_id);
1551 - if (chr == NULL) {
1552 - error_setg(errp, "chardev \"%s\" not found", chardev_id);
1553 - return;
1554 - }
1555 -
1556 - obj = object_new_with_props(TYPE_MONITOR_HMP,
1557 - object_get_objects_root(),
1558 - id ? id : autoid,
1559 - errp,
1560 - NULL);
1555 if (!obj) {
1556 return;
1557 }
1558 +
1559 mon = MONITOR_HMP(obj);
1560
1566 - if (!qemu_chr_fe_init(&mon->parent_obj.chr, chr, errp)) {
1561 + monitor_complete(MONITOR(mon), errp);
1562 + if (*errp) {
1563 object_unparent(OBJECT(mon));
1564 return;
1565 }
monitor/monitor-internal.h
+2
@@ -108,6 +108,7 @@ struct MonitorClass {
108
109 struct Monitor {
110 Object parent;
111 + char *chardev_id;
112 CharFrontend chr;
113 int suspend_cnt; /* Needs to be accessed atomically */
114 bool is_qmp;
@@ -192,6 +193,7 @@ extern QmpCommandList qmp_commands, qmp_cap_negotiation_commands;
193 extern QemuMutex monitor_lock;
194 extern MonitorList mon_list;
195
196 +void monitor_complete(Monitor *mon, Error **errp);
197 void monitor_data_init(Monitor *mon, bool is_qmp, bool skip_flush,
198 bool use_io_thread);
199 void monitor_data_destroy(Monitor *mon);
monitor/monitor.c
+36
@@ -79,10 +79,31 @@ OBJECT_DEFINE_ABSTRACT_TYPE(Monitor, monitor, MONITOR, OBJECT);
79
80 static void monitor_finalize(Object *obj)
81 {
82 + Monitor *mon = MONITOR(obj);
83 +
84 + g_free(mon->chardev_id);
85 +}
86 +
87 +static char *monitor_get_chardev_id(Object *obj, Error **errp)
88 +{
89 + Monitor *mon = MONITOR(obj);
90 +
91 + return g_strdup(mon->chardev_id);
92 +}
93 +
94 +static void monitor_set_chardev_id(Object *obj, const char *str, Error **errp)
95 +{
96 + Monitor *mon = MONITOR(obj);
97 +
98 + g_free(mon->chardev_id);
99 + mon->chardev_id = g_strdup(str);
100 }
101
102 static void monitor_class_init(ObjectClass *cls, const void *data)
103 {
104 + object_class_property_add_str(cls, "chardev",
105 + monitor_get_chardev_id,
106 + monitor_set_chardev_id);
107 }
108
109 static void monitor_init(Object *obj)
@@ -738,6 +759,21 @@ char *monitor_compat_id(void)
759 return g_strdup_printf("compat_monitor%d", monitor_device_index++);
760 }
761
762 +void monitor_complete(Monitor *mon, Error **errp)
763 +{
764 + if (mon->chardev_id) {
765 + Chardev *chr = qemu_chr_find(mon->chardev_id);
766 + if (chr == NULL) {
767 + error_setg(errp, "chardev \"%s\" not found", mon->chardev_id);
768 + return;
769 + }
770 +
771 + if (!qemu_chr_fe_init(&mon->chr, chr, errp)) {
772 + return;
773 + }
774 + }
775 +}
776 +
777 int monitor_new(MonitorOptions *opts, bool allow_hmp, Error **errp)
778 {
779 ERRP_GUARD();
monitor/qmp.c
+15 -18
@@ -530,36 +530,33 @@ static void monitor_qmp_setup_handlers_bh(void *opaque)
530 void monitor_new_qmp(const char *id, const char *chardev_id,
531 bool pretty, Error **errp)
532 {
533 + ERRP_GUARD();
534 MonitorQMP *mon;
535 g_autofree char *autoid = id ? NULL : monitor_compat_id();
535 - Chardev *chr;
536 - Object *obj;
536 + Object *obj = object_new_with_props(TYPE_MONITOR_QMP,
537 + object_get_objects_root(),
538 + id ? id : autoid,
539 + errp,
540 + "chardev", chardev_id,
541 + NULL);
542
538 - chr = qemu_chr_find(chardev_id);
539 - if (chr == NULL) {
540 - error_setg(errp, "chardev \"%s\" not found", chardev_id);
541 - return;
542 - }
543 -
544 - obj = object_new_with_props(TYPE_MONITOR_QMP,
545 - object_get_objects_root(),
546 - id ? id : autoid,
547 - errp,
548 - NULL);
543 if (!obj) {
544 return;
545 }
552 - mon = MONITOR_QMP(obj);
546
554 - if (!qemu_chr_fe_init(&mon->parent_obj.chr, chr, errp)) {
547 + mon = MONITOR_QMP(obj);
548 + monitor_complete(MONITOR(mon), errp);
549 + if (*errp) {
550 object_unparent(OBJECT(mon));
551 return;
552 }
553 +
554 qemu_chr_fe_set_echo(&mon->parent_obj.chr, true);
555
556 /* Note: we run QMP monitor in I/O thread when @chr supports that */
557 monitor_data_init(&mon->parent_obj, true, false,
562 - qemu_chr_has_feature(chr, QEMU_CHAR_FEATURE_GCONTEXT));
558 + qemu_chr_has_feature(mon->parent_obj.chr.chr,
559 + QEMU_CHAR_FEATURE_GCONTEXT));
560
561 mon->pretty = pretty;
562
@@ -572,12 +569,12 @@ void monitor_new_qmp(const char *id, const char *chardev_id,
569 * Make sure the old iowatch is gone. It's possible when
570 * e.g. the chardev is in client mode, with wait=on.
571 */
575 - remove_fd_in_watch(chr);
572 + remove_fd_in_watch(mon->parent_obj.chr.chr);
573 /*
574 * Clean up listener IO sources early to prevent racy fd
575 * handling between the main thread and the I/O thread.
576 */
580 - remove_listener_fd_in_watch(chr);
577 + remove_listener_fd_in_watch(mon->parent_obj.chr.chr);
578 /*
579 * We can't call qemu_chr_fe_set_handlers() directly here
580 * since chardev might be running in the monitor I/O