summary refs log tree commit diff stats
path: root/chardev/char.c
diff options
context:
space:
mode:
Diffstat (limited to 'chardev/char.c')
-rw-r--r--chardev/char.c50
1 files changed, 32 insertions, 18 deletions
diff --git a/chardev/char.c b/chardev/char.c
index 674c097fbe..5456fb2e3a 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -45,6 +45,11 @@
 static QTAILQ_HEAD(ChardevHead, Chardev) chardevs =
     QTAILQ_HEAD_INITIALIZER(chardevs);
 
+static Object *get_chardevs_root(void)
+{
+    return container_get(object_get_root(), "/chardevs");
+}
+
 void qemu_chr_be_event(Chardev *s, int event)
 {
     CharBackend *be = s->be;
@@ -413,6 +418,9 @@ static void char_finalize(Object *obj)
 {
     Chardev *chr = CHARDEV(obj);
 
+    if (QTAILQ_IN_USE(chr, next)) {
+        QTAILQ_REMOVE(&chardevs, chr, next);
+    }
     if (chr->be) {
         chr->be->chr = NULL;
     }
@@ -946,7 +954,7 @@ Chardev *qemu_chr_new_from_opts(QemuOpts *opts,
         backend->u.mux.data->chardev = g_strdup(bid);
         mux = qemu_chardev_add(id, TYPE_CHARDEV_MUX, backend, errp);
         if (mux == NULL) {
-            qemu_chr_delete(chr);
+            object_unparent(OBJECT(chr));
             chr = NULL;
             goto out;
         }
@@ -1060,12 +1068,6 @@ void qemu_chr_fe_disconnect(CharBackend *be)
     }
 }
 
-void qemu_chr_delete(Chardev *chr)
-{
-    QTAILQ_REMOVE(&chardevs, chr, next);
-    object_unref(OBJECT(chr));
-}
-
 ChardevInfoList *qmp_query_chardev(Error **errp)
 {
     ChardevInfoList *chr_list = NULL;
@@ -1225,22 +1227,23 @@ void qemu_chr_set_feature(Chardev *chr,
 }
 
 Chardev *qemu_chardev_new(const char *id, const char *typename,
-                          ChardevBackend *backend, Error **errp)
+                          ChardevBackend *backend,
+                          Error **errp)
 {
+    Object *obj;
     Chardev *chr = NULL;
     Error *local_err = NULL;
     bool be_opened = true;
 
     assert(g_str_has_prefix(typename, "chardev-"));
 
-    chr = CHARDEV(object_new(typename));
+    obj = object_new(typename);
+    chr = CHARDEV(obj);
     chr->label = g_strdup(id);
 
     qemu_char_open(chr, backend, &be_opened, &local_err);
     if (local_err) {
-        error_propagate(errp, local_err);
-        object_unref(OBJECT(chr));
-        return NULL;
+        goto end;
     }
 
     if (!chr->filename) {
@@ -1250,6 +1253,21 @@ Chardev *qemu_chardev_new(const char *id, const char *typename,
         qemu_chr_be_event(chr, CHR_EVENT_OPENED);
     }
 
+    if (id) {
+        object_property_add_child(get_chardevs_root(), id, obj, &local_err);
+        if (local_err) {
+            goto end;
+        }
+        object_unref(obj);
+    }
+
+end:
+    if (local_err) {
+        error_propagate(errp, local_err);
+        object_unref(obj);
+        return NULL;
+    }
+
     return chr;
 }
 
@@ -1298,16 +1316,12 @@ void qmp_chardev_remove(const char *id, Error **errp)
             "Chardev '%s' cannot be unplugged in record/replay mode", id);
         return;
     }
-    qemu_chr_delete(chr);
+    object_unparent(OBJECT(chr));
 }
 
 void qemu_chr_cleanup(void)
 {
-    Chardev *chr, *tmp;
-
-    QTAILQ_FOREACH_SAFE(chr, &chardevs, next, tmp) {
-        qemu_chr_delete(chr);
-    }
+    object_unparent(get_chardevs_root());
 }
 
 static void register_types(void)