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:
committed by
Markus Armbruster
parent
7e3ce81383
commit
1a65434329
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user