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>
This commit is contained in:
Daniel P. Berrangé
2026-07-06 14:57:55 +01:00
committed by Markus Armbruster
parent 7e3ce81383
commit 1a65434329
4 changed files with 63 additions and 32 deletions

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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();

View File

@@ -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