All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [RFC PATCH 0/6] chardev: convert to QOM
@ 2012-10-15 19:34 Anthony Liguori
  2012-10-15 19:34 ` [Qemu-devel] [PATCH 1/6] object: add object_property_add_bool Anthony Liguori
                   ` (6 more replies)
  0 siblings, 7 replies; 13+ messages in thread
From: Anthony Liguori @ 2012-10-15 19:34 UTC (permalink / raw)
  To: qemu-devel; +Cc: Paolo Bonzini, Gerd Hoffmann, Andreas Faerber

Hi,

This has long been on my TODO list.  I wanted to put this forward since Gerd
has a chardev hotplug series.  I think there are a few good reasons to go the
QOM route here.  Most notably:

1) the conversion cleans up all of the printfs into proper error messages
2) it becomes possible to introspect available character device types
3) it becomes possible (albeit a little awkward) to programmatically query
   options for a type

There are quite a few things missing from this RFC although I think it can all
be done incrementally.  The continued items are:

A) Replace chardev properties in devices with links
B) Finish converting all usage of QemuOpts into proper properties
C) Use class methods instead of function pointers in objects
D) General cleanups

I think the main decision point here is whether we introduce a separate
chardev_add/chardev_del command or just use the qom-create command that has
been posted previously.

Please note, a few of these patches have long lines from a combination of code
motion and automated conversion via macros.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PATCH 1/6] object: add object_property_add_bool
  2012-10-15 19:34 [Qemu-devel] [RFC PATCH 0/6] chardev: convert to QOM Anthony Liguori
@ 2012-10-15 19:34 ` Anthony Liguori
  2012-10-16 15:44   ` Andreas Färber
  2012-10-23 11:30   ` Markus Armbruster
  2012-10-15 19:34 ` [Qemu-devel] [PATCH 2/6] chardev: convert to QOM (shallow pass) Anthony Liguori
                   ` (5 subsequent siblings)
  6 siblings, 2 replies; 13+ messages in thread
From: Anthony Liguori @ 2012-10-15 19:34 UTC (permalink / raw)
  To: qemu-devel; +Cc: Paolo Bonzini, Anthony Liguori, Gerd Hoffmann, Andreas Faerber

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
 include/qemu/object.h |   17 ++++++++++++++
 qom/object.c          |   58 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 75 insertions(+), 0 deletions(-)

diff --git a/include/qemu/object.h b/include/qemu/object.h
index cc75fee..f4dc2ea 100644
--- a/include/qemu/object.h
+++ b/include/qemu/object.h
@@ -947,6 +947,23 @@ void object_property_add_str(Object *obj, const char *name,
                              struct Error **errp);
 
 /**
+ * object_property_add_bool:
+ * @obj: the object to add a property to
+ * @name: the name of the property
+ * @get: the getter or NULL if the property is write-only.  This function must
+ *   return a string to be freed by g_free().
+ * @set: the setter or NULL if the property is read-only
+ * @errp: if an error occurs, a pointer to an area to store the error
+ *
+ * Add a bool property using getters/setters.  This function will add a
+ * property of type 'bool'.
+ */
+void object_property_add_bool(Object *obj, const char *name,
+                              bool (*get)(Object *, struct Error **),
+                              void (*set)(Object *, bool, struct Error **),
+                              struct Error **errp);
+
+/**
  * object_child_foreach:
  * @obj: the object whose children will be navigated
  * @fn: the iterator function to be called
diff --git a/qom/object.c b/qom/object.c
index e3e9242..efa25ee 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -1183,6 +1183,64 @@ void object_property_add_str(Object *obj, const char *name,
                         prop, errp);
 }
 
+typedef struct BoolProperty
+{
+    bool (*get)(Object *, Error **);
+    void (*set)(Object *, bool, Error **);
+} BoolProperty;
+
+static void property_get_bool(Object *obj, Visitor *v, void *opaque,
+                              const char *name, Error **errp)
+{
+    BoolProperty *prop = opaque;
+    bool value;
+
+    value = prop->get(obj, errp);
+    if (value) {
+        visit_type_bool(v, &value, name, errp);
+    }
+}
+
+static void property_set_bool(Object *obj, Visitor *v, void *opaque,
+                              const char *name, Error **errp)
+{
+    BoolProperty *prop = opaque;
+    Error *local_err = NULL;
+    bool value;
+
+    visit_type_bool(v, &value, name, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    prop->set(obj, value, errp);
+}
+
+static void property_release_bool(Object *obj, const char *name,
+                                  void *opaque)
+{
+    BoolProperty *prop = opaque;
+    g_free(prop);
+}
+
+void object_property_add_bool(Object *obj, const char *name,
+                              bool (*get)(Object *, Error **),
+                              void (*set)(Object *, bool, Error **),
+                              Error **errp)
+{
+    BoolProperty *prop = g_malloc0(sizeof(*prop));
+
+    prop->get = get;
+    prop->set = set;
+
+    object_property_add(obj, name, "bool",
+                        get ? property_get_bool : NULL,
+                        set ? property_set_bool : NULL,
+                        property_release_bool,
+                        prop, errp);
+}
+
 static char *qdev_get_type(Object *obj, Error **errp)
 {
     return g_strdup(object_get_typename(obj));
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PATCH 2/6] chardev: convert to QOM (shallow pass)
  2012-10-15 19:34 [Qemu-devel] [RFC PATCH 0/6] chardev: convert to QOM Anthony Liguori
  2012-10-15 19:34 ` [Qemu-devel] [PATCH 1/6] object: add object_property_add_bool Anthony Liguori
@ 2012-10-15 19:34 ` Anthony Liguori
  2012-10-15 19:34 ` [Qemu-devel] [PATCH 3/6] chardev: create new QOM types for each sub chardev type Anthony Liguori
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 13+ messages in thread
From: Anthony Liguori @ 2012-10-15 19:34 UTC (permalink / raw)
  To: qemu-devel; +Cc: Paolo Bonzini, Anthony Liguori, Gerd Hoffmann, Andreas Faerber

This just adds an Object to all chardev objects.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
 console.c         |    4 ++--
 qemu-char.c       |   47 ++++++++++++++++++++++++++++++-----------------
 qemu-char.h       |    6 ++++++
 spice-qemu-char.c |    2 +-
 4 files changed, 39 insertions(+), 20 deletions(-)

diff --git a/console.c b/console.c
index 3f3d254..33bf7e7 100644
--- a/console.c
+++ b/console.c
@@ -1547,7 +1547,7 @@ CharDriverState *text_console_init(QemuOpts *opts)
     unsigned width;
     unsigned height;
 
-    chr = g_malloc0(sizeof(CharDriverState));
+    chr = CHARDEV(object_new(TYPE_CHARDEV));
 
     width = qemu_opt_get_number(opts, "width", 0);
     if (width == 0)
@@ -1564,7 +1564,7 @@ CharDriverState *text_console_init(QemuOpts *opts)
     }
 
     if (!s) {
-        g_free(chr);
+        object_delete(OBJECT(chr));
         return NULL;
     }
 
diff --git a/qemu-char.c b/qemu-char.c
index b082bae..8c5a80e 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -225,7 +225,7 @@ static CharDriverState *qemu_chr_open_null(QemuOpts *opts)
 {
     CharDriverState *chr;
 
-    chr = g_malloc0(sizeof(CharDriverState));
+    chr = CHARDEV(object_new(TYPE_CHARDEV));
     chr->chr_write = null_chr_write;
     return chr;
 }
@@ -472,7 +472,7 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState *drv)
     CharDriverState *chr;
     MuxDriver *d;
 
-    chr = g_malloc0(sizeof(CharDriverState));
+    chr = CHARDEV(object_new(TYPE_CHARDEV));
     d = g_malloc0(sizeof(MuxDriver));
 
     chr->opaque = d;
@@ -623,7 +623,7 @@ static CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
     CharDriverState *chr;
     FDCharDriver *s;
 
-    chr = g_malloc0(sizeof(CharDriverState));
+    chr = CHARDEV(object_new(TYPE_CHARDEV));
     s = g_malloc0(sizeof(FDCharDriver));
     s->fd_in = fd_in;
     s->fd_out = fd_out;
@@ -999,7 +999,7 @@ static CharDriverState *qemu_chr_open_pty(QemuOpts *opts)
     tcsetattr(slave_fd, TCSAFLUSH, &tty);
     close(slave_fd);
 
-    chr = g_malloc0(sizeof(CharDriverState));
+    chr = CHARDEV(object_new(TYPE_CHARDEV));
 
     len = strlen(q_ptsname(master_fd)) + 5;
     chr->filename = g_malloc(len);
@@ -1371,7 +1371,7 @@ static CharDriverState *qemu_chr_open_pp(QemuOpts *opts)
     drv->fd = fd;
     drv->mode = IEEE1284_MODE_COMPAT;
 
-    chr = g_malloc0(sizeof(CharDriverState));
+    chr = CHARDEV(object_new(TYPE_CHARDEV));
     chr->chr_write = null_chr_write;
     chr->chr_ioctl = pp_ioctl;
     chr->chr_close = pp_close;
@@ -1432,7 +1432,7 @@ static CharDriverState *qemu_chr_open_pp(QemuOpts *opts)
         return NULL;
     }
 
-    chr = g_malloc0(sizeof(CharDriverState));
+    chr = CHARDEV(object_new(TYPE_CHARDEV));
     chr->opaque = (void *)(intptr_t)fd;
     chr->chr_write = null_chr_write;
     chr->chr_ioctl = pp_ioctl;
@@ -1658,7 +1658,7 @@ static CharDriverState *qemu_chr_open_win(QemuOpts *opts)
     CharDriverState *chr;
     WinCharState *s;
 
-    chr = g_malloc0(sizeof(CharDriverState));
+    chr = CHARDEV(object_new(TYPE_CHARDEV));
     s = g_malloc0(sizeof(WinCharState));
     chr->opaque = s;
     chr->chr_write = win_chr_write;
@@ -1666,7 +1666,7 @@ static CharDriverState *qemu_chr_open_win(QemuOpts *opts)
 
     if (win_chr_init(chr, filename) < 0) {
         g_free(s);
-        g_free(chr);
+        object_delete(OBJECT(chr));
         return NULL;
     }
     qemu_chr_generic_open(chr);
@@ -1758,7 +1758,7 @@ static CharDriverState *qemu_chr_open_win_pipe(QemuOpts *opts)
     CharDriverState *chr;
     WinCharState *s;
 
-    chr = g_malloc0(sizeof(CharDriverState));
+    chr = CHARDEV(object_new(TYPE_CHARDEV));
     s = g_malloc0(sizeof(WinCharState));
     chr->opaque = s;
     chr->chr_write = win_chr_write;
@@ -1766,7 +1766,7 @@ static CharDriverState *qemu_chr_open_win_pipe(QemuOpts *opts)
 
     if (win_chr_pipe_init(chr, filename) < 0) {
         g_free(s);
-        g_free(chr);
+        object_delete(OBJECT(chr));
         return NULL;
     }
     qemu_chr_generic_open(chr);
@@ -1778,7 +1778,7 @@ static CharDriverState *qemu_chr_open_win_file(HANDLE fd_out)
     CharDriverState *chr;
     WinCharState *s;
 
-    chr = g_malloc0(sizeof(CharDriverState));
+    chr = CHARDEV(object_new(TYPE_CHARDEV));
     s = g_malloc0(sizeof(WinCharState));
     s->hcom = fd_out;
     chr->opaque = s;
@@ -1940,7 +1940,7 @@ static void win_stdio_close(CharDriverState *chr)
     }
 
     g_free(chr->opaque);
-    g_free(chr);
+    object_delete(OBJECT(chr));
     stdio_nb_clients--;
 }
 
@@ -2099,7 +2099,7 @@ static CharDriverState *qemu_chr_open_udp(QemuOpts *opts)
     NetCharDriver *s = NULL;
     int fd = -1;
 
-    chr = g_malloc0(sizeof(CharDriverState));
+    chr = CHARDEV(object_new(TYPE_CHARDEV));
     s = g_malloc0(sizeof(NetCharDriver));
 
     fd = inet_dgram_opts(opts);
@@ -2118,7 +2118,7 @@ static CharDriverState *qemu_chr_open_udp(QemuOpts *opts)
     return chr;
 
 return_err:
-    g_free(chr);
+    object_delete(OBJECT(chr));
     g_free(s);
     if (fd >= 0) {
         closesocket(fd);
@@ -2443,7 +2443,7 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
     if (!is_listen)
         is_waitconnect = 0;
 
-    chr = g_malloc0(sizeof(CharDriverState));
+    chr = CHARDEV(object_new(TYPE_CHARDEV));
     s = g_malloc0(sizeof(TCPCharDriver));
 
     if (is_unix) {
@@ -2520,7 +2520,7 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
     if (fd >= 0)
         closesocket(fd);
     g_free(s);
-    g_free(chr);
+    object_delete(OBJECT(chr));
     return NULL;
 }
 
@@ -2858,7 +2858,7 @@ void qemu_chr_delete(CharDriverState *chr)
         chr->chr_close(chr);
     g_free(chr->filename);
     g_free(chr->label);
-    g_free(chr);
+    object_delete(OBJECT(chr));
 }
 
 ChardevInfoList *qmp_query_chardev(Error **errp)
@@ -2900,3 +2900,16 @@ CharDriverState *qemu_char_get_next_serial(void)
     return serial_hds[next_serial++];
 }
 
+static const TypeInfo chardev_info = {
+    .name = TYPE_CHARDEV,
+    .parent = TYPE_OBJECT,
+    .instance_size = sizeof(CharDriverState),
+    .class_size = sizeof(ObjectClass),
+};
+
+static void register_types(void)
+{
+    type_register_static(&chardev_info);
+}
+
+type_init(register_types);
diff --git a/qemu-char.h b/qemu-char.h
index 486644b..229b16d 100644
--- a/qemu-char.h
+++ b/qemu-char.h
@@ -1,6 +1,7 @@
 #ifndef QEMU_CHAR_H
 #define QEMU_CHAR_H
 
+#include "qemu/object.h"
 #include "qemu-common.h"
 #include "qemu-queue.h"
 #include "qemu-option.h"
@@ -50,9 +51,14 @@ typedef struct {
 #define CHR_TIOCM_DTR	0x002
 #define CHR_TIOCM_RTS	0x004
 
+#define TYPE_CHARDEV "chardev"
+#define CHARDEV(obj) OBJECT_CHECK(CharDriverState, (obj), TYPE_CHARDEV)
+
 typedef void IOEventHandler(void *opaque, int event);
 
 struct CharDriverState {
+    Object parent_obj;
+
     void (*init)(struct CharDriverState *s);
     int (*chr_write)(struct CharDriverState *s, const uint8_t *buf, int len);
     void (*chr_update_read_handler)(struct CharDriverState *s);
diff --git a/spice-qemu-char.c b/spice-qemu-char.c
index 09aa22d..4badddc 100644
--- a/spice-qemu-char.c
+++ b/spice-qemu-char.c
@@ -214,7 +214,7 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
         return NULL;
     }
 
-    chr = g_malloc0(sizeof(CharDriverState));
+    chr = CHARDEV(object_new(TYPE_CHARDEV));
     s = g_malloc0(sizeof(SpiceCharDriver));
     s->chr = chr;
     s->debug = debug;
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PATCH 3/6] chardev: create new QOM types for each sub chardev type
  2012-10-15 19:34 [Qemu-devel] [RFC PATCH 0/6] chardev: convert to QOM Anthony Liguori
  2012-10-15 19:34 ` [Qemu-devel] [PATCH 1/6] object: add object_property_add_bool Anthony Liguori
  2012-10-15 19:34 ` [Qemu-devel] [PATCH 2/6] chardev: convert to QOM (shallow pass) Anthony Liguori
@ 2012-10-15 19:34 ` Anthony Liguori
  2012-10-15 19:34 ` [Qemu-devel] [PATCH 4/6] chardev: implement realize Anthony Liguori
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 13+ messages in thread
From: Anthony Liguori @ 2012-10-15 19:34 UTC (permalink / raw)
  To: qemu-devel; +Cc: Paolo Bonzini, Anthony Liguori, Gerd Hoffmann, Andreas Faerber

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
 console.c         |   10 +-
 console.h         |    2 +-
 hw/msmouse.c      |    7 +-
 hw/msmouse.h      |    2 +-
 qemu-char.c       |  479 +++++++++++++++++++++++++++++++++++++++--------------
 qemu-char.h       |   13 ++
 spice-qemu-char.c |   31 ++--
 7 files changed, 388 insertions(+), 156 deletions(-)

diff --git a/console.c b/console.c
index 33bf7e7..a3e426a 100644
--- a/console.c
+++ b/console.c
@@ -1540,15 +1540,12 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
         chr->init(chr);
 }
 
-CharDriverState *text_console_init(QemuOpts *opts)
+void text_console_init(CharDriverState *chr, QemuOpts *opts, Error **errp)
 {
-    CharDriverState *chr;
     TextConsole *s;
     unsigned width;
     unsigned height;
 
-    chr = CHARDEV(object_new(TYPE_CHARDEV));
-
     width = qemu_opt_get_number(opts, "width", 0);
     if (width == 0)
         width = qemu_opt_get_number(opts, "cols", 0) * FONT_WIDTH;
@@ -1564,8 +1561,8 @@ CharDriverState *text_console_init(QemuOpts *opts)
     }
 
     if (!s) {
-        object_delete(OBJECT(chr));
-        return NULL;
+        error_setg(errp, "failed to initialize console");
+        return;
     }
 
     s->chr = chr;
@@ -1573,7 +1570,6 @@ CharDriverState *text_console_init(QemuOpts *opts)
     s->g_height = height;
     chr->opaque = s;
     chr->chr_set_echo = text_console_set_echo;
-    return chr;
 }
 
 void text_consoles_set_display(DisplayState *ds)
diff --git a/console.h b/console.h
index f990684..5e08cfe 100644
--- a/console.h
+++ b/console.h
@@ -361,7 +361,7 @@ void vga_hw_text_update(console_ch_t *chardata);
 
 int is_graphic_console(void);
 int is_fixedsize_console(void);
-CharDriverState *text_console_init(QemuOpts *opts);
+void text_console_init(CharDriverState *chr, QemuOpts *opts, Error **errp);
 void text_consoles_set_display(DisplayState *ds);
 void console_select(unsigned int index);
 void console_color_init(DisplayState *ds);
diff --git a/hw/msmouse.c b/hw/msmouse.c
index 9c492a4..34c8eb6 100644
--- a/hw/msmouse.c
+++ b/hw/msmouse.c
@@ -64,15 +64,10 @@ static void msmouse_chr_close (struct CharDriverState *chr)
     g_free (chr);
 }
 
-CharDriverState *qemu_chr_open_msmouse(QemuOpts *opts)
+void qemu_chr_open_msmouse(CharDriverState *chr, QemuOpts *opts, Error **errp)
 {
-    CharDriverState *chr;
-
-    chr = g_malloc0(sizeof(CharDriverState));
     chr->chr_write = msmouse_chr_write;
     chr->chr_close = msmouse_chr_close;
 
     qemu_add_mouse_event_handler(msmouse_event, chr, 0, "QEMU Microsoft Mouse");
-
-    return chr;
 }
diff --git a/hw/msmouse.h b/hw/msmouse.h
index 456cb21..2bf79e7 100644
--- a/hw/msmouse.h
+++ b/hw/msmouse.h
@@ -1,2 +1,2 @@
 /* msmouse.c */
-CharDriverState *qemu_chr_open_msmouse(QemuOpts *opts);
+void qemu_chr_open_msmouse(CharDriverState *chr, QemuOpts *opts, Error **errp);
diff --git a/qemu-char.c b/qemu-char.c
index 8c5a80e..866c560 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -221,13 +221,9 @@ static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
     return len;
 }
 
-static CharDriverState *qemu_chr_open_null(QemuOpts *opts)
+static void qemu_chr_open_null(CharDriverState *chr, QemuOpts *opts, Error **errp)
 {
-    CharDriverState *chr;
-
-    chr = CHARDEV(object_new(TYPE_CHARDEV));
     chr->chr_write = null_chr_write;
-    return chr;
 }
 
 /* MUX driver for serial I/O splitting */
@@ -618,12 +614,10 @@ static void fd_chr_close(struct CharDriverState *chr)
 }
 
 /* open a character device to a unix fd */
-static CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
+static void qemu_chr_open_fd(CharDriverState *chr, int fd_in, int fd_out)
 {
-    CharDriverState *chr;
     FDCharDriver *s;
 
-    chr = CHARDEV(object_new(TYPE_CHARDEV));
     s = g_malloc0(sizeof(FDCharDriver));
     s->fd_in = fd_in;
     s->fd_out = fd_out;
@@ -633,31 +627,30 @@ static CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
     chr->chr_close = fd_chr_close;
 
     qemu_chr_generic_open(chr);
-
-    return chr;
 }
 
-static CharDriverState *qemu_chr_open_file_out(QemuOpts *opts)
+static void qemu_chr_open_file_out(CharDriverState *chr, QemuOpts *opts, Error **errp)
 {
     int fd_out;
 
     TFR(fd_out = qemu_open(qemu_opt_get(opts, "path"),
                       O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, 0666));
     if (fd_out < 0) {
-        return NULL;
+        error_setg(errp, "Failed to open file `%s'", qemu_opt_get(opts, "path"));
+    } else {
+        qemu_chr_open_fd(chr, -1, fd_out);
     }
-    return qemu_chr_open_fd(-1, fd_out);
 }
 
-static CharDriverState *qemu_chr_open_pipe(QemuOpts *opts)
+static void qemu_chr_open_pipe(CharDriverState *chr, QemuOpts *opts, Error **errp)
 {
     int fd_in, fd_out;
     char filename_in[256], filename_out[256];
     const char *filename = qemu_opt_get(opts, "path");
 
     if (filename == NULL) {
-        fprintf(stderr, "chardev: pipe: no filename given\n");
-        return NULL;
+        error_setg(errp, "chardev: pipe: no filename given\n");
+        return;
     }
 
     snprintf(filename_in, 256, "%s.in", filename);
@@ -671,10 +664,11 @@ static CharDriverState *qemu_chr_open_pipe(QemuOpts *opts)
 	    close(fd_out);
         TFR(fd_in = fd_out = qemu_open(filename, O_RDWR | O_BINARY));
         if (fd_in < 0) {
-            return NULL;
+            error_setg(errp, "Failed to open file `%s'", filename);
+            return;
         }
     }
-    return qemu_chr_open_fd(fd_in, fd_out);
+    qemu_chr_open_fd(chr, fd_in, fd_out);
 }
 
 
@@ -765,12 +759,11 @@ static void qemu_chr_close_stdio(struct CharDriverState *chr)
     fd_chr_close(chr);
 }
 
-static CharDriverState *qemu_chr_open_stdio(QemuOpts *opts)
+static void qemu_chr_open_stdio(CharDriverState *chr, QemuOpts *opts, Error **errp)
 {
-    CharDriverState *chr;
-
     if (stdio_nb_clients >= STDIO_MAX_CLIENTS) {
-        return NULL;
+        error_setg(errp, "too many stdio chardevs");
+        return;
     }
     if (stdio_nb_clients == 0) {
         old_fd0_flags = fcntl(0, F_GETFL);
@@ -779,7 +772,7 @@ static CharDriverState *qemu_chr_open_stdio(QemuOpts *opts)
         atexit(term_exit);
     }
 
-    chr = qemu_chr_open_fd(0, 1);
+    qemu_chr_open_fd(chr, 0, 1);
     chr->chr_close = qemu_chr_close_stdio;
     chr->chr_set_echo = qemu_chr_set_echo_stdio;
     qemu_set_fd_handler2(0, stdio_read_poll, stdio_read, NULL, chr);
@@ -787,8 +780,6 @@ static CharDriverState *qemu_chr_open_stdio(QemuOpts *opts)
     stdio_allow_signal = qemu_opt_get_bool(opts, "signal",
                                            display_type != DT_NOGRAPHIC);
     qemu_chr_fe_set_echo(chr, false);
-
-    return chr;
 }
 
 #ifdef __sun__
@@ -975,9 +966,8 @@ static void pty_chr_close(struct CharDriverState *chr)
     qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
 }
 
-static CharDriverState *qemu_chr_open_pty(QemuOpts *opts)
+static void qemu_chr_open_pty(CharDriverState *chr, QemuOpts *opts, Error **errp)
 {
-    CharDriverState *chr;
     PtyCharDriver *s;
     struct termios tty;
     int master_fd, slave_fd, len;
@@ -990,7 +980,8 @@ static CharDriverState *qemu_chr_open_pty(QemuOpts *opts)
 #endif
 
     if (openpty(&master_fd, &slave_fd, pty_name, NULL, NULL) < 0) {
-        return NULL;
+        error_setg(errp, "failed to openpty");
+        return;
     }
 
     /* Set raw attributes on the pty. */
@@ -999,8 +990,6 @@ static CharDriverState *qemu_chr_open_pty(QemuOpts *opts)
     tcsetattr(slave_fd, TCSAFLUSH, &tty);
     close(slave_fd);
 
-    chr = CHARDEV(object_new(TYPE_CHARDEV));
-
     len = strlen(q_ptsname(master_fd)) + 5;
     chr->filename = g_malloc(len);
     snprintf(chr->filename, len, "pty:%s", q_ptsname(master_fd));
@@ -1015,8 +1004,6 @@ static CharDriverState *qemu_chr_open_pty(QemuOpts *opts)
 
     s->fd = master_fd;
     s->timer = qemu_new_timer_ms(rt_clock, pty_chr_timer, chr);
-
-    return chr;
 }
 
 static void tty_serial_init(int fd, int speed,
@@ -1217,26 +1204,25 @@ static void qemu_chr_close_tty(CharDriverState *chr)
     }
 }
 
-static CharDriverState *qemu_chr_open_tty(QemuOpts *opts)
+static void qemu_chr_open_tty(CharDriverState *chr, QemuOpts *opts, Error **errp)
 {
     const char *filename = qemu_opt_get(opts, "path");
-    CharDriverState *chr;
     int fd;
 
     TFR(fd = qemu_open(filename, O_RDWR | O_NONBLOCK));
     if (fd < 0) {
-        return NULL;
+        error_setg(errp, "Failed to open file `%s'", filename);
+        return;
     }
     tty_serial_init(fd, 115200, 'N', 8, 1);
-    chr = qemu_chr_open_fd(fd, fd);
+    qemu_chr_open_fd(chr, fd, fd);
     chr->chr_ioctl = tty_serial_ioctl;
     chr->chr_close = qemu_chr_close_tty;
-    return chr;
 }
 #else  /* ! __linux__ && ! __sun__ */
-static CharDriverState *qemu_chr_open_pty(QemuOpts *opts)
+static void qemu_chr_open_pty(CharDriverState *chr, QemuOpts *opts, Error **errp)
 {
-    return NULL;
+    error_setg(errp, "pty chardev not supported on this platform");
 }
 #endif /* __linux__ || __sun__ */
 
@@ -1350,36 +1336,34 @@ static void pp_close(CharDriverState *chr)
     qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
 }
 
-static CharDriverState *qemu_chr_open_pp(QemuOpts *opts)
+static void qemu_chr_open_pp(CharDriverState *chr, QemuOpts *opts, Error **errp)
 {
     const char *filename = qemu_opt_get(opts, "path");
-    CharDriverState *chr;
     ParallelCharDriver *drv;
     int fd;
 
     TFR(fd = qemu_open(filename, O_RDWR));
     if (fd < 0) {
-        return NULL;
+        error_setg(errp, "Could not open filename `%s'", filename);
+        return;
     }
 
     if (ioctl(fd, PPCLAIM) < 0) {
         close(fd);
-        return NULL;
+        error_setg(errp, "Failed to claim parallel port");
+        return;
     }
 
     drv = g_malloc0(sizeof(ParallelCharDriver));
     drv->fd = fd;
     drv->mode = IEEE1284_MODE_COMPAT;
 
-    chr = CHARDEV(object_new(TYPE_CHARDEV));
     chr->chr_write = null_chr_write;
     chr->chr_ioctl = pp_ioctl;
     chr->chr_close = pp_close;
     chr->opaque = drv;
 
     qemu_chr_generic_open(chr);
-
-    return chr;
 }
 #endif /* __linux__ */
 
@@ -1421,22 +1405,20 @@ static int pp_ioctl(CharDriverState *chr, int cmd, void *arg)
     return 0;
 }
 
-static CharDriverState *qemu_chr_open_pp(QemuOpts *opts)
+static void qemu_chr_open_pp(CharDriverState *chr, QemuOpts *opts, Error **errp)
 {
     const char *filename = qemu_opt_get(opts, "path");
-    CharDriverState *chr;
     int fd;
 
     fd = qemu_open(filename, O_RDWR);
     if (fd < 0) {
-        return NULL;
+        error_setg(errp, "Failed to open file `%s'", filename);
+        return;
     }
 
-    chr = CHARDEV(object_new(TYPE_CHARDEV));
     chr->opaque = (void *)(intptr_t)fd;
     chr->chr_write = null_chr_write;
     chr->chr_ioctl = pp_ioctl;
-    return chr;
 }
 #endif
 
@@ -1752,13 +1734,11 @@ static int win_chr_pipe_init(CharDriverState *chr, const char *filename)
 }
 
 
-static CharDriverState *qemu_chr_open_win_pipe(QemuOpts *opts)
+static void qemu_chr_open_win_pipe(CharDriverState *chr, QemuOpts *opts, Error **errp)
 {
     const char *filename = qemu_opt_get(opts, "path");
-    CharDriverState *chr;
     WinCharState *s;
 
-    chr = CHARDEV(object_new(TYPE_CHARDEV));
     s = g_malloc0(sizeof(WinCharState));
     chr->opaque = s;
     chr->chr_write = win_chr_write;
@@ -1766,33 +1746,29 @@ static CharDriverState *qemu_chr_open_win_pipe(QemuOpts *opts)
 
     if (win_chr_pipe_init(chr, filename) < 0) {
         g_free(s);
-        object_delete(OBJECT(chr));
-        return NULL;
+        error_setg(errp, "failed to initialize pipe");
+        return;
     }
     qemu_chr_generic_open(chr);
-    return chr;
 }
 
-static CharDriverState *qemu_chr_open_win_file(HANDLE fd_out)
+static void qemu_chr_open_win_file(CharDriverState *chr, HANDLE fd_out)
 {
-    CharDriverState *chr;
     WinCharState *s;
 
-    chr = CHARDEV(object_new(TYPE_CHARDEV));
     s = g_malloc0(sizeof(WinCharState));
     s->hcom = fd_out;
     chr->opaque = s;
     chr->chr_write = win_chr_write;
     qemu_chr_generic_open(chr);
-    return chr;
 }
 
-static CharDriverState *qemu_chr_open_win_con(QemuOpts *opts)
+static void qemu_chr_open_win_con(CharDriverState *chr, QemuOpts *opts, Error **errp)
 {
-    return qemu_chr_open_win_file(GetStdHandle(STD_OUTPUT_HANDLE));
+    qemu_chr_open_win_file(chr, GetStdHandle(STD_OUTPUT_HANDLE));
 }
 
-static CharDriverState *qemu_chr_open_win_file_out(QemuOpts *opts)
+static void qemu_chr_open_win_file_out(CharDriverState *chr, QemuOpts *opts, Error **errp)
 {
     const char *file_out = qemu_opt_get(opts, "path");
     HANDLE fd_out;
@@ -1803,7 +1779,7 @@ static CharDriverState *qemu_chr_open_win_file_out(QemuOpts *opts)
         return NULL;
     }
 
-    return qemu_chr_open_win_file(fd_out);
+    qemu_chr_open_win_file(chr, fd_out);
 }
 
 static int win_stdio_write(CharDriverState *chr, const uint8_t *buf, int len)
@@ -1944,9 +1920,8 @@ static void win_stdio_close(CharDriverState *chr)
     stdio_nb_clients--;
 }
 
-static CharDriverState *qemu_chr_open_win_stdio(QemuOpts *opts)
+static void qemu_chr_open_win_stdio(CharDriverState *chr, QemuOpts *opts, Error **errp)
 {
-    CharDriverState   *chr;
     WinStdioCharState *stdio;
     DWORD              dwMode;
     int                is_console = 0;
@@ -1956,13 +1931,12 @@ static CharDriverState *qemu_chr_open_win_stdio(QemuOpts *opts)
         return NULL;
     }
 
-    chr   = g_malloc0(sizeof(CharDriverState));
     stdio = g_malloc0(sizeof(WinStdioCharState));
 
     stdio->hStdIn = GetStdHandle(STD_INPUT_HANDLE);
     if (stdio->hStdIn == INVALID_HANDLE_VALUE) {
-        fprintf(stderr, "cannot open stdio: invalid handle\n");
-        exit(1);
+        error_setg(errp, "cannot open stdio: invalid handle");
+        return;
     }
 
     is_console = GetConsoleMode(stdio->hStdIn, &dwMode) != 0;
@@ -1975,7 +1949,7 @@ static CharDriverState *qemu_chr_open_win_stdio(QemuOpts *opts)
         if (is_console) {
             if (qemu_add_wait_object(stdio->hStdIn,
                                      win_stdio_wait_func, chr)) {
-                fprintf(stderr, "qemu_add_wait_object: failed\n");
+                error_setg(errp, "qemu_add_wait_object: failed");
             }
         } else {
             DWORD   dwId;
@@ -1988,12 +1962,13 @@ static CharDriverState *qemu_chr_open_win_stdio(QemuOpts *opts)
             if (stdio->hInputThread == INVALID_HANDLE_VALUE
                 || stdio->hInputReadyEvent == INVALID_HANDLE_VALUE
                 || stdio->hInputDoneEvent == INVALID_HANDLE_VALUE) {
-                fprintf(stderr, "cannot create stdio thread or event\n");
-                exit(1);
+                error_setg(errp, "cannot create stdio thread or event");
+                return;
             }
             if (qemu_add_wait_object(stdio->hInputReadyEvent,
                                      win_stdio_thread_wait_func, chr)) {
-                fprintf(stderr, "qemu_add_wait_object: failed\n");
+                error_setg(errp, "qemu_add_wait_object: failed");
+                return;
             }
         }
     }
@@ -2011,8 +1986,6 @@ static CharDriverState *qemu_chr_open_win_stdio(QemuOpts *opts)
 
     chr->chr_set_echo = qemu_chr_set_echo_win_stdio;
     qemu_chr_fe_set_echo(chr, false);
-
-    return chr;
 }
 #endif /* !_WIN32 */
 
@@ -2093,18 +2066,15 @@ static void udp_chr_close(CharDriverState *chr)
     qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
 }
 
-static CharDriverState *qemu_chr_open_udp(QemuOpts *opts)
+static void qemu_chr_open_udp(CharDriverState *chr, QemuOpts *opts, Error **errp)
 {
-    CharDriverState *chr = NULL;
     NetCharDriver *s = NULL;
     int fd = -1;
 
-    chr = CHARDEV(object_new(TYPE_CHARDEV));
     s = g_malloc0(sizeof(NetCharDriver));
 
     fd = inet_dgram_opts(opts);
     if (fd < 0) {
-        fprintf(stderr, "inet_dgram_opts failed\n");
         goto return_err;
     }
 
@@ -2115,15 +2085,15 @@ static CharDriverState *qemu_chr_open_udp(QemuOpts *opts)
     chr->chr_write = udp_chr_write;
     chr->chr_update_read_handler = udp_chr_update_read_handler;
     chr->chr_close = udp_chr_close;
-    return chr;
+
+    return;
 
 return_err:
-    object_delete(OBJECT(chr));
     g_free(s);
     if (fd >= 0) {
         closesocket(fd);
     }
-    return NULL;
+    error_setg(errp, "failed to initialize udp socket");
 }
 
 /***********************************************************/
@@ -2319,7 +2289,10 @@ static void tcp_chr_read(void *opaque)
 #ifndef _WIN32
 CharDriverState *qemu_chr_open_eventfd(int eventfd)
 {
-    return qemu_chr_open_fd(eventfd, eventfd);
+    CharDriverState *chr;
+    chr = CHARDEV(object_new(TYPE_CHARDEV));
+    qemu_chr_open_fd(chr, eventfd, eventfd);
+    return chr;
 }
 #endif
 
@@ -2424,9 +2397,8 @@ static void tcp_chr_close(CharDriverState *chr)
     qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
 }
 
-static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
+static void qemu_chr_open_socket(CharDriverState *chr, QemuOpts *opts, Error **errp)
 {
-    CharDriverState *chr = NULL;
     TCPCharDriver *s = NULL;
     int fd = -1;
     int is_listen;
@@ -2443,7 +2415,6 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
     if (!is_listen)
         is_waitconnect = 0;
 
-    chr = CHARDEV(object_new(TYPE_CHARDEV));
     s = g_malloc0(sizeof(TCPCharDriver));
 
     if (is_unix) {
@@ -2514,14 +2485,13 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
         tcp_chr_accept(chr);
         socket_set_nonblock(s->listen_fd);
     }
-    return chr;
+    return;
 
  fail:
     if (fd >= 0)
         closesocket(fd);
     g_free(s);
-    object_delete(OBJECT(chr));
-    return NULL;
+    error_setg(errp, "Failed to initialize char driver");
 }
 
 /***********************************************************/
@@ -2716,49 +2686,278 @@ fail:
     return NULL;
 }
 
-static const struct {
-    const char *name;
-    CharDriverState *(*open)(QemuOpts *opts);
-} backend_table[] = {
-    { .name = "null",      .open = qemu_chr_open_null },
-    { .name = "socket",    .open = qemu_chr_open_socket },
-    { .name = "udp",       .open = qemu_chr_open_udp },
-    { .name = "msmouse",   .open = qemu_chr_open_msmouse },
-    { .name = "vc",        .open = text_console_init },
+#define TYPE_CHARDEV_NULL "chardev-null"
+#define CHARDEV_NULL OBJECT_CHECK(CharDriverState, (obj), TYPE_CHARDEV_NULL)
+
+static void chardev_null_class_init(ObjectClass *klass, void *data)
+{
+    CharDriverClass *cdc = CHARDEV_CLASS(klass);
+
+    cdc->open = qemu_chr_open_null;
+}
+
+static const TypeInfo chardev_null_info = {
+    .name = TYPE_CHARDEV_NULL,
+    .parent = TYPE_CHARDEV,
+    .class_init = chardev_null_class_init,
+};
+
+#define TYPE_CHARDEV_socket "chardev-socket"
+#define CHARDEV_socket OBJECT_CHECK(CharDriverState, (obj), TYPE_CHARDEV_socket)
+
+static void chardev_socket_class_init(ObjectClass *klass, void *data)
+{
+    CharDriverClass *cdc = CHARDEV_CLASS(klass);
+
+    cdc->open = qemu_chr_open_socket;
+}
+
+static const TypeInfo chardev_socket_info = {
+    .name = TYPE_CHARDEV_socket,
+    .parent = TYPE_CHARDEV,
+    .class_init = chardev_socket_class_init,
+};
+
+#define TYPE_CHARDEV_udp "chardev-udp"
+#define CHARDEV_udp OBJECT_CHECK(CharDriverState, (obj), TYPE_CHARDEV_udp)
+
+static void chardev_udp_class_init(ObjectClass *klass, void *data)
+{
+    CharDriverClass *cdc = CHARDEV_CLASS(klass);
+
+    cdc->open = qemu_chr_open_udp;
+}
+
+static const TypeInfo chardev_udp_info = {
+    .name = TYPE_CHARDEV_udp,
+    .parent = TYPE_CHARDEV,
+    .class_init = chardev_udp_class_init,
+};
+
+#define TYPE_CHARDEV_msmouse "chardev-msmouse"
+#define CHARDEV_msmouse OBJECT_CHECK(CharDriverState, (obj), TYPE_CHARDEV_msmouse)
+
+static void chardev_msmouse_class_init(ObjectClass *klass, void *data)
+{
+    CharDriverClass *cdc = CHARDEV_CLASS(klass);
+
+    cdc->open = qemu_chr_open_msmouse;
+}
+
+static const TypeInfo chardev_msmouse_info = {
+    .name = TYPE_CHARDEV_msmouse,
+    .parent = TYPE_CHARDEV,
+    .class_init = chardev_msmouse_class_init,
+};
+
+#define TYPE_CHARDEV_vc "chardev-vc"
+#define CHARDEV_vc OBJECT_CHECK(CharDriverState, (obj), TYPE_CHARDEV_vc)
+
+static void chardev_vc_class_init(ObjectClass *klass, void *data)
+{
+    CharDriverClass *cdc = CHARDEV_CLASS(klass);
+
+    cdc->open = text_console_init;
+}
+
+static const TypeInfo chardev_vc_info = {
+    .name = TYPE_CHARDEV_vc,
+    .parent = TYPE_CHARDEV,
+    .class_init = chardev_vc_class_init,
+};
+
+#ifdef _WIN32
+#define TYPE_CHARDEV_console "chardev-console"
+#define CHARDEV_console OBJECT_CHECK(CharDriverState, (obj), TYPE_CHARDEV_console)
+
+static void chardev_console_class_init(ObjectClass *klass, void *data)
+{
+    CharDriverClass *cdc = CHARDEV_CLASS(klass);
+
+    cdc->open = qemu_chr_open_win_con;
+}
+
+static const TypeInfo chardev_console_info = {
+    .name = TYPE_CHARDEV_console,
+    .parent = TYPE_CHARDEV,
+    .class_init = chardev_console_class_init,
+};
+
+#define TYPE_CHARDEV_serial "chardev-serial"
+#define CHARDEV_serial OBJECT_CHECK(CharDriverState, (obj), TYPE_CHARDEV_serial)
+
+static void chardev_serial_class_init(ObjectClass *klass, void *data)
+{
+    CharDriverClass *cdc = CHARDEV_CLASS(klass);
+
+    cdc->open = qemu_chr_open_win;
+}
+
+static const TypeInfo chardev_serial_info = {
+    .name = TYPE_CHARDEV_serial,
+    .parent = TYPE_CHARDEV,
+    .class_init = chardev_serial_class_init,
+};
+#else
+#define TYPE_CHARDEV_pty "chardev-pty"
+#define CHARDEV_pty OBJECT_CHECK(CharDriverState, (obj), TYPE_CHARDEV_pty)
+
+static void chardev_pty_class_init(ObjectClass *klass, void *data)
+{
+    CharDriverClass *cdc = CHARDEV_CLASS(klass);
+
+    cdc->open = qemu_chr_open_pty;
+}
+
+static const TypeInfo chardev_pty_info = {
+    .name = TYPE_CHARDEV_pty,
+    .parent = TYPE_CHARDEV,
+    .class_init = chardev_pty_class_init,
+};
+#endif
+
+#define TYPE_CHARDEV_file "chardev-file"
+#define CHARDEV_file OBJECT_CHECK(CharDriverState, (obj), TYPE_CHARDEV_file)
+
+static void chardev_file_class_init(ObjectClass *klass, void *data)
+{
+    CharDriverClass *cdc = CHARDEV_CLASS(klass);
+
+#ifdef _WIN32
+    cdc->open = qemu_chr_open_win_file_out;
+#else
+    cdc->open = qemu_chr_open_file_out;
+#endif
+}
+
+static const TypeInfo chardev_file_info = {
+    .name = TYPE_CHARDEV_file,
+    .parent = TYPE_CHARDEV,
+    .class_init = chardev_file_class_init,
+};
+
+#define TYPE_CHARDEV_pipe "chardev-pipe"
+#define CHARDEV_pipe OBJECT_CHECK(CharDriverState, (obj), TYPE_CHARDEV_pipe)
+
+static void chardev_pipe_class_init(ObjectClass *klass, void *data)
+{
+    CharDriverClass *cdc = CHARDEV_CLASS(klass);
+
+#ifdef _WIN32
+    cdc->open = qemu_chr_open_win_pipe;
+#else
+    cdc->open = qemu_chr_open_pipe;
+#endif
+}
+
+static const TypeInfo chardev_pipe_info = {
+    .name = TYPE_CHARDEV_pipe,
+    .parent = TYPE_CHARDEV,
+    .class_init = chardev_pipe_class_init,
+};
+
+#define TYPE_CHARDEV_stdio "chardev-stdio"
+#define CHARDEV_stdio OBJECT_CHECK(CharDriverState, (obj), TYPE_CHARDEV_stdio)
+
+static void chardev_stdio_class_init(ObjectClass *klass, void *data)
+{
+    CharDriverClass *cdc = CHARDEV_CLASS(klass);
+
 #ifdef _WIN32
-    { .name = "file",      .open = qemu_chr_open_win_file_out },
-    { .name = "pipe",      .open = qemu_chr_open_win_pipe },
-    { .name = "console",   .open = qemu_chr_open_win_con },
-    { .name = "serial",    .open = qemu_chr_open_win },
-    { .name = "stdio",     .open = qemu_chr_open_win_stdio },
+    cdc->open = qemu_chr_open_win_stdio;
 #else
-    { .name = "file",      .open = qemu_chr_open_file_out },
-    { .name = "pipe",      .open = qemu_chr_open_pipe },
-    { .name = "pty",       .open = qemu_chr_open_pty },
-    { .name = "stdio",     .open = qemu_chr_open_stdio },
+    cdc->open = qemu_chr_open_stdio;
 #endif
+}
+
+static const TypeInfo chardev_stdio_info = {
+    .name = TYPE_CHARDEV_stdio,
+    .parent = TYPE_CHARDEV,
+    .class_init = chardev_stdio_class_init,
+};
+
 #ifdef CONFIG_BRLAPI
-    { .name = "braille",   .open = chr_baum_init },
+#define TYPE_CHARDEV_braille "chardev-braille"
+#define CHARDEV_braille OBJECT_CHECK(CharDriverState, (obj), TYPE_CHARDEV_braille)
+
+static void chardev_braille_class_init(ObjectClass *klass, void *data)
+{
+    CharDriverClass *cdc = CHARDEV_CLASS(klass);
+
+    cdc->open = chr_baum_init;
+}
+
+static const TypeInfo chardev_braille_info = {
+    .name = TYPE_CHARDEV_braille,
+    .parent = TYPE_CHARDEV,
+    .class_init = chardev_braille_class_init,
+};
 #endif
+
 #if defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \
     || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \
     || defined(__FreeBSD_kernel__)
-    { .name = "tty",       .open = qemu_chr_open_tty },
+#define TYPE_CHARDEV_tty "chardev-tty"
+#define CHARDEV_tty OBJECT_CHECK(CharDriverState, (obj), TYPE_CHARDEV_tty)
+
+static void chardev_tty_class_init(ObjectClass *klass, void *data)
+{
+    CharDriverClass *cdc = CHARDEV_CLASS(klass);
+
+    cdc->open = qemu_chr_open_tty;
+}
+
+static const TypeInfo chardev_tty_info = {
+    .name = TYPE_CHARDEV_tty,
+    .parent = TYPE_CHARDEV,
+    .class_init = chardev_tty_class_init,
+};
 #endif
+
 #if defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__) \
     || defined(__FreeBSD_kernel__)
-    { .name = "parport",   .open = qemu_chr_open_pp },
+#define TYPE_CHARDEV_parport "chardev-parport"
+#define CHARDEV_parport OBJECT_CHECK(CharDriverState, (obj), TYPE_CHARDEV_parport)
+
+static void chardev_parport_class_init(ObjectClass *klass, void *data)
+{
+    CharDriverClass *cdc = CHARDEV_CLASS(klass);
+
+    cdc->open = qemu_chr_open_pp;
+}
+
+static const TypeInfo chardev_parport_info = {
+    .name = TYPE_CHARDEV_parport,
+    .parent = TYPE_CHARDEV,
+    .class_init = chardev_parport_class_init,
+};
 #endif
+
 #ifdef CONFIG_SPICE
-    { .name = "spicevmc",     .open = qemu_chr_open_spice },
-#endif
+#define TYPE_CHARDEV_spicevmc "chardev-spicevmc"
+#define CHARDEV_spicevmc OBJECT_CHECK(CharDriverState, (obj), TYPE_CHARDEV_spicevmc)
+
+static void chardev_spicevmc_class_init(ObjectClass *klass, void *data)
+{
+    CharDriverClass *cdc = CHARDEV_CLASS(klass);
+
+    cdc->open = qemu_chr_open_spice;
+}
+
+static const TypeInfo chardev_spicevmc_info = {
+    .name = TYPE_CHARDEV_spicevmc,
+    .parent = TYPE_CHARDEV,
+    .class_init = chardev_spicevmc_class_init,
 };
+#endif
 
 CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
-                                    void (*init)(struct CharDriverState *s))
+                                        void (*init)(struct CharDriverState *s))
 {
     CharDriverState *chr;
-    int i;
+    CharDriverClass *cdc;
+    Error *err = NULL;
+    gchar *class_name;
 
     if (qemu_opts_id(opts) == NULL) {
         fprintf(stderr, "chardev: no id specified\n");
@@ -2770,20 +2969,28 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
                 qemu_opts_id(opts));
         return NULL;
     }
-    for (i = 0; i < ARRAY_SIZE(backend_table); i++) {
-        if (strcmp(backend_table[i].name, qemu_opt_get(opts, "backend")) == 0)
-            break;
-    }
-    if (i == ARRAY_SIZE(backend_table)) {
+
+    class_name = g_strdup_printf("chardev-%s", qemu_opt_get(opts, "backend"));
+    if (object_class_by_name(class_name) == NULL) {
         fprintf(stderr, "chardev: backend \"%s\" not found\n",
                 qemu_opt_get(opts, "backend"));
+        g_free(class_name);
         return NULL;
     }
 
-    chr = backend_table[i].open(opts);
-    if (!chr) {
-        fprintf(stderr, "chardev: opening backend \"%s\" failed\n",
-                qemu_opt_get(opts, "backend"));
+    chr = CHARDEV(object_new(class_name));
+
+    cdc = CHARDEV_GET_CLASS(chr);
+    g_assert(cdc->open != NULL);
+
+    cdc->open(chr, opts, &err);
+
+    g_free(class_name);
+
+    if (err) {
+        qerror_report_err(err);
+        error_free(err);
+        object_delete(OBJECT(chr));
         return NULL;
     }
 
@@ -2904,12 +3111,34 @@ static const TypeInfo chardev_info = {
     .name = TYPE_CHARDEV,
     .parent = TYPE_OBJECT,
     .instance_size = sizeof(CharDriverState),
-    .class_size = sizeof(ObjectClass),
+    .class_size = sizeof(CharDriverClass),
 };
 
 static void register_types(void)
 {
     type_register_static(&chardev_info);
+    type_register_static(&chardev_null_info);
+    type_register_static(&chardev_socket_info);
+    type_register_static(&chardev_udp_info);
+    type_register_static(&chardev_msmouse_info);
+    type_register_static(&chardev_vc_info);
+#ifdef _WIN32
+    type_register_static(&chardev_console_info);
+    type_register_static(&chardev_serial_info);
+#else
+    type_register_static(&chardev_pty_info);
+#endif
+    type_register_static(&chardev_file_info);
+    type_register_static(&chardev_pipe_info);
+    type_register_static(&chardev_stdio_info);
+#ifdef CONFIG_BRLAPI
+    type_register_static(&chardev_braille_info);
+#endif
+    type_register_static(&chardev_tty_info);
+    type_register_static(&chardev_parport_info);
+#ifdef CONFIG_SPICE
+    type_register_static(&chardev_spicevmc_info);
+#endif
 }
 
 type_init(register_types);
diff --git a/qemu-char.h b/qemu-char.h
index 229b16d..df7957d 100644
--- a/qemu-char.h
+++ b/qemu-char.h
@@ -53,9 +53,22 @@ typedef struct {
 
 #define TYPE_CHARDEV "chardev"
 #define CHARDEV(obj) OBJECT_CHECK(CharDriverState, (obj), TYPE_CHARDEV)
+#define CHARDEV_CLASS(klass) \
+    OBJECT_CLASS_CHECK(CharDriverClass, (klass), TYPE_CHARDEV)
+#define CHARDEV_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(CharDriverClass, (obj), TYPE_CHARDEV)
 
 typedef void IOEventHandler(void *opaque, int event);
 
+typedef struct CharDriverClass CharDriverClass;
+
+struct CharDriverClass
+{
+    ObjectClass parent_class;
+
+    void (*open)(struct CharDriverState *chr, QemuOpts *opts, Error **errp);
+};
+
 struct CharDriverState {
     Object parent_obj;
 
diff --git a/spice-qemu-char.c b/spice-qemu-char.c
index 4badddc..381171e 100644
--- a/spice-qemu-char.c
+++ b/spice-qemu-char.c
@@ -171,26 +171,26 @@ static void spice_chr_guest_close(struct CharDriverState *chr)
     vmc_unregister_interface(s);
 }
 
-static void print_allowed_subtypes(void)
+static char *get_allowed_subtypes(void)
 {
+    char *ret = NULL;
     const char** psubtype;
     int i;
 
-    fprintf(stderr, "allowed names: ");
     for(i=0, psubtype = spice_server_char_device_recognized_subtypes();
         *psubtype != NULL; ++psubtype, ++i) {
         if (i == 0) {
-            fprintf(stderr, "%s", *psubtype);
+            ret = g_strdup(*psubtype);
         } else {
-            fprintf(stderr, ", %s", *psubtype);
+            char *old = ret;
+            ret = g_strdup("%s, %s", ret, *psubtype);
+            g_free(old);
         }
     }
-    fprintf(stderr, "\n");
 }
 
-CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
+void qemu_chr_open_spice(CharDriverState *chr, QemuOpts *opts, Error **errp)
 {
-    CharDriverState *chr;
     SpiceCharDriver *s;
     const char* name = qemu_opt_get(opts, "name");
     uint32_t debug = qemu_opt_get_number(opts, "debug", 0);
@@ -198,9 +198,10 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
     const char *subtype = NULL;
 
     if (name == NULL) {
-        fprintf(stderr, "spice-qemu-char: missing name parameter\n");
-        print_allowed_subtypes();
-        return NULL;
+        char *names = get_allowed_subtypes();
+        error_setg(errp, "spice-qemu-char: missing name parameter, allowed names: %s", names);
+        g_free(names);
+        return;
     }
     for(;*psubtype != NULL; ++psubtype) {
         if (strcmp(name, *psubtype) == 0) {
@@ -209,12 +210,12 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
         }
     }
     if (subtype == NULL) {
-        fprintf(stderr, "spice-qemu-char: unsupported name: %s\n", name);
-        print_allowed_subtypes();
-        return NULL;
+        char *names = get_allowed_subtypes();
+        error_setg(errp, "spice-qemu-char: unsupported, allowed names: %s", names);
+        g_free(names);
+        return;
     }
 
-    chr = CHARDEV(object_new(TYPE_CHARDEV));
     s = g_malloc0(sizeof(SpiceCharDriver));
     s->chr = chr;
     s->debug = debug;
@@ -232,6 +233,4 @@ CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
         qemu_chr_generic_open(chr);
     }
 #endif
-
-    return chr;
 }
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PATCH 4/6] chardev: implement realize
  2012-10-15 19:34 [Qemu-devel] [RFC PATCH 0/6] chardev: convert to QOM Anthony Liguori
                   ` (2 preceding siblings ...)
  2012-10-15 19:34 ` [Qemu-devel] [PATCH 3/6] chardev: create new QOM types for each sub chardev type Anthony Liguori
@ 2012-10-15 19:34 ` Anthony Liguori
  2012-10-15 19:34 ` [Qemu-devel] [PATCH 5/6] chardev: switch the easy backends to realize Anthony Liguori
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 13+ messages in thread
From: Anthony Liguori @ 2012-10-15 19:34 UTC (permalink / raw)
  To: qemu-devel; +Cc: Paolo Bonzini, Anthony Liguori, Gerd Hoffmann, Andreas Faerber

This can be used to initialize an object independently of setting properties.
This makes the 'open' method legacy.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
 qemu-char.c |   48 +++++++++++++++++++++++++++++++++++++++++++++---
 qemu-char.h |    3 +++
 2 files changed, 48 insertions(+), 3 deletions(-)

diff --git a/qemu-char.c b/qemu-char.c
index 866c560..e9a81c7 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2981,9 +2981,13 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
     chr = CHARDEV(object_new(class_name));
 
     cdc = CHARDEV_GET_CLASS(chr);
-    g_assert(cdc->open != NULL);
-
-    cdc->open(chr, opts, &err);
+    if (cdc->open) {
+        cdc->open(chr, opts, &err);
+    } else {
+        if (!err) {
+            object_property_set_bool(OBJECT(chr), true, "realized", &err);
+        }
+    }
 
     g_free(class_name);
 
@@ -3107,11 +3111,49 @@ CharDriverState *qemu_char_get_next_serial(void)
     return serial_hds[next_serial++];
 }
 
+static bool chardev_get_realized(Object *obj, Error **errp)
+{
+    CharDriverState *chr = CHARDEV(obj);
+
+    return chr->realized;
+}
+
+static void chardev_set_realized(Object *obj, bool value, Error **errp)
+{
+    CharDriverState *chr = CHARDEV(obj);
+    CharDriverClass *cdc = CHARDEV_GET_CLASS(chr);
+
+    if (chr->realized == value) {
+        return;
+    }
+
+    if (!value && chr->realized) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+    } else {
+        Error *local_err = NULL;
+
+        g_assert(cdc->realize);
+        cdc->realize(chr, &local_err);
+        if (local_err) {
+            error_propagate(errp, local_err);
+        } else {
+            chr->realized = true;
+        }
+    }
+}
+
+static void chardev_initfn(Object *obj)
+{
+    object_property_add_bool(obj, "realized", chardev_get_realized,
+                             chardev_set_realized, NULL);
+}
+
 static const TypeInfo chardev_info = {
     .name = TYPE_CHARDEV,
     .parent = TYPE_OBJECT,
     .instance_size = sizeof(CharDriverState),
     .class_size = sizeof(CharDriverClass),
+    .instance_init = chardev_initfn,
 };
 
 static void register_types(void)
diff --git a/qemu-char.h b/qemu-char.h
index df7957d..be2a410 100644
--- a/qemu-char.h
+++ b/qemu-char.h
@@ -66,7 +66,9 @@ struct CharDriverClass
 {
     ObjectClass parent_class;
 
+    /* Objects should implement only one of these two methods */
     void (*open)(struct CharDriverState *chr, QemuOpts *opts, Error **errp);
+    void (*realize)(struct CharDriverState *chr, QemuOpts *opts, Error **errp);
 };
 
 struct CharDriverState {
@@ -94,6 +96,7 @@ struct CharDriverState {
     int opened;
     int avail_connections;
     QTAILQ_ENTRY(CharDriverState) next;
+    bool realized;
 };
 
 /**
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PATCH 5/6] chardev: switch the easy backends to realize
  2012-10-15 19:34 [Qemu-devel] [RFC PATCH 0/6] chardev: convert to QOM Anthony Liguori
                   ` (3 preceding siblings ...)
  2012-10-15 19:34 ` [Qemu-devel] [PATCH 4/6] chardev: implement realize Anthony Liguori
@ 2012-10-15 19:34 ` Anthony Liguori
  2012-10-15 19:34 ` [Qemu-devel] [PATCH 6/6] chardev: convert file backend " Anthony Liguori
  2012-10-17  8:07 ` [Qemu-devel] [RFC PATCH 0/6] chardev: convert to QOM Gerd Hoffmann
  6 siblings, 0 replies; 13+ messages in thread
From: Anthony Liguori @ 2012-10-15 19:34 UTC (permalink / raw)
  To: qemu-devel; +Cc: Paolo Bonzini, Anthony Liguori, Gerd Hoffmann, Andreas Faerber

For backends that take no options, switching to realize is trivially easy.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
 qemu-char.c |   12 ++++++------
 qemu-char.h |    2 +-
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/qemu-char.c b/qemu-char.c
index e9a81c7..bc0fdbe 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -221,7 +221,7 @@ static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
     return len;
 }
 
-static void qemu_chr_open_null(CharDriverState *chr, QemuOpts *opts, Error **errp)
+static void qemu_chr_open_null(CharDriverState *chr, Error **errp)
 {
     chr->chr_write = null_chr_write;
 }
@@ -1763,7 +1763,7 @@ static void qemu_chr_open_win_file(CharDriverState *chr, HANDLE fd_out)
     qemu_chr_generic_open(chr);
 }
 
-static void qemu_chr_open_win_con(CharDriverState *chr, QemuOpts *opts, Error **errp)
+static void qemu_chr_open_win_con(CharDriverState *chr, Error **errp)
 {
     qemu_chr_open_win_file(chr, GetStdHandle(STD_OUTPUT_HANDLE));
 }
@@ -1920,7 +1920,7 @@ static void win_stdio_close(CharDriverState *chr)
     stdio_nb_clients--;
 }
 
-static void qemu_chr_open_win_stdio(CharDriverState *chr, QemuOpts *opts, Error **errp)
+static void qemu_chr_open_win_stdio(CharDriverState *chr, Error **errp)
 {
     WinStdioCharState *stdio;
     DWORD              dwMode;
@@ -2693,7 +2693,7 @@ static void chardev_null_class_init(ObjectClass *klass, void *data)
 {
     CharDriverClass *cdc = CHARDEV_CLASS(klass);
 
-    cdc->open = qemu_chr_open_null;
+    cdc->realize = qemu_chr_open_null;
 }
 
 static const TypeInfo chardev_null_info = {
@@ -2774,7 +2774,7 @@ static void chardev_console_class_init(ObjectClass *klass, void *data)
 {
     CharDriverClass *cdc = CHARDEV_CLASS(klass);
 
-    cdc->open = qemu_chr_open_win_con;
+    cdc->realize = qemu_chr_open_win_con;
 }
 
 static const TypeInfo chardev_console_info = {
@@ -2864,7 +2864,7 @@ static void chardev_stdio_class_init(ObjectClass *klass, void *data)
     CharDriverClass *cdc = CHARDEV_CLASS(klass);
 
 #ifdef _WIN32
-    cdc->open = qemu_chr_open_win_stdio;
+    cdc->realize = qemu_chr_open_win_stdio;
 #else
     cdc->open = qemu_chr_open_stdio;
 #endif
diff --git a/qemu-char.h b/qemu-char.h
index be2a410..9e15dcd 100644
--- a/qemu-char.h
+++ b/qemu-char.h
@@ -68,7 +68,7 @@ struct CharDriverClass
 
     /* Objects should implement only one of these two methods */
     void (*open)(struct CharDriverState *chr, QemuOpts *opts, Error **errp);
-    void (*realize)(struct CharDriverState *chr, QemuOpts *opts, Error **errp);
+    void (*realize)(struct CharDriverState *chr, Error **errp);
 };
 
 struct CharDriverState {
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PATCH 6/6] chardev: convert file backend to realize
  2012-10-15 19:34 [Qemu-devel] [RFC PATCH 0/6] chardev: convert to QOM Anthony Liguori
                   ` (4 preceding siblings ...)
  2012-10-15 19:34 ` [Qemu-devel] [PATCH 5/6] chardev: switch the easy backends to realize Anthony Liguori
@ 2012-10-15 19:34 ` Anthony Liguori
  2012-10-16 15:52   ` Paolo Bonzini
  2012-10-17  8:07 ` [Qemu-devel] [RFC PATCH 0/6] chardev: convert to QOM Gerd Hoffmann
  6 siblings, 1 reply; 13+ messages in thread
From: Anthony Liguori @ 2012-10-15 19:34 UTC (permalink / raw)
  To: qemu-devel; +Cc: Paolo Bonzini, Anthony Liguori, Gerd Hoffmann, Andreas Faerber

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
---
 qemu-char.c |   89 +++++++++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 75 insertions(+), 14 deletions(-)

diff --git a/qemu-char.c b/qemu-char.c
index bc0fdbe..93a515f 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -540,9 +540,14 @@ static int stdio_nb_clients;
 
 #ifndef _WIN32
 
+#define TYPE_CHARDEV_FILE "chardev-file"
+#define CHARDEV_FILE(obj) OBJECT_CHECK(FDCharDriver, (obj), TYPE_CHARDEV_FILE)
+
 typedef struct {
+    CharDriverState parent_obj;
     int fd_in, fd_out;
     int max_size;
+    char *path;
 } FDCharDriver;
 
 
@@ -609,19 +614,20 @@ static void fd_chr_close(struct CharDriverState *chr)
         }
     }
 
-    g_free(s);
+    g_free(s->path);
+    if ((void *)s != (void *)chr) {
+        g_free(s);
+    }
     qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
 }
 
 /* open a character device to a unix fd */
-static void qemu_chr_open_fd(CharDriverState *chr, int fd_in, int fd_out)
+static void qemu_chr_init_fd(CharDriverState *chr, int fd_in, int fd_out)
 {
-    FDCharDriver *s;
+    FDCharDriver *s = chr->opaque;
 
-    s = g_malloc0(sizeof(FDCharDriver));
     s->fd_in = fd_in;
     s->fd_out = fd_out;
-    chr->opaque = s;
     chr->chr_write = fd_chr_write;
     chr->chr_update_read_handler = fd_chr_update_read_handler;
     chr->chr_close = fd_chr_close;
@@ -629,19 +635,69 @@ static void qemu_chr_open_fd(CharDriverState *chr, int fd_in, int fd_out)
     qemu_chr_generic_open(chr);
 }
 
-static void qemu_chr_open_file_out(CharDriverState *chr, QemuOpts *opts, Error **errp)
+static void qemu_chr_open_fd(CharDriverState *chr, int fd_in, int fd_out)
+{
+    FDCharDriver *s;
+
+    s = g_malloc0(sizeof(FDCharDriver));
+    chr->opaque = s;
+    qemu_chr_init_fd(chr, fd_in, fd_out);
+}
+
+static void qemu_chr_open_file_out(CharDriverState *chr, Error **errp)
 {
+    FDCharDriver *s = chr->opaque;
     int fd_out;
 
-    TFR(fd_out = qemu_open(qemu_opt_get(opts, "path"),
-                      O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, 0666));
+    if (s->path == NULL || s->path[0] == 0) {
+        error_setg(errp, "'path' property must be set");
+        return;
+    }
+
+    TFR(fd_out = qemu_open(s->path, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, 0666));
     if (fd_out < 0) {
-        error_setg(errp, "Failed to open file `%s'", qemu_opt_get(opts, "path"));
+        error_setg(errp, "Failed to open file `%s'", s->path);
+        return;
     } else {
         qemu_chr_open_fd(chr, -1, fd_out);
     }
 }
 
+static char *chardev_file_get_path(Object *obj, Error **errp)
+{
+    CharDriverState *chr = CHARDEV(obj);
+    FDCharDriver *s = chr->opaque;
+
+    return s->path ? g_strdup(s->path) : g_strdup("");
+}
+
+static void chardev_file_set_path(Object *obj, const char *value, Error **errp)
+{
+    CharDriverState *chr = CHARDEV(obj);
+    FDCharDriver *s = chr->opaque;
+
+    if (chr->realized) {
+        error_set(errp, QERR_PERMISSION_DENIED);
+        return;
+    }
+
+    if (s->path) {
+        g_free(s->path);
+    }
+
+    s->path = g_strdup(value);
+}
+
+static void chardev_file_initfn(Object *obj)
+{
+    CharDriverState *chr = CHARDEV(obj);
+
+    object_property_add_str(obj, "path", chardev_file_get_path, chardev_file_set_path, NULL);
+#ifndef _WIN32
+    chr->opaque = CHARDEV_FILE(obj);
+#endif
+}
+
 static void qemu_chr_open_pipe(CharDriverState *chr, QemuOpts *opts, Error **errp)
 {
     int fd_in, fd_out;
@@ -2816,9 +2872,6 @@ static const TypeInfo chardev_pty_info = {
 };
 #endif
 
-#define TYPE_CHARDEV_file "chardev-file"
-#define CHARDEV_file OBJECT_CHECK(CharDriverState, (obj), TYPE_CHARDEV_file)
-
 static void chardev_file_class_init(ObjectClass *klass, void *data)
 {
     CharDriverClass *cdc = CHARDEV_CLASS(klass);
@@ -2826,14 +2879,18 @@ static void chardev_file_class_init(ObjectClass *klass, void *data)
 #ifdef _WIN32
     cdc->open = qemu_chr_open_win_file_out;
 #else
-    cdc->open = qemu_chr_open_file_out;
+    cdc->realize = qemu_chr_open_file_out;
 #endif
 }
 
 static const TypeInfo chardev_file_info = {
-    .name = TYPE_CHARDEV_file,
+    .name = TYPE_CHARDEV_FILE,
     .parent = TYPE_CHARDEV,
     .class_init = chardev_file_class_init,
+    .instance_init = chardev_file_initfn,
+#ifndef _WIN32
+    .instance_size = sizeof(FDCharDriver),
+#endif
 };
 
 #define TYPE_CHARDEV_pipe "chardev-pipe"
@@ -2984,6 +3041,10 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
     if (cdc->open) {
         cdc->open(chr, opts, &err);
     } else {
+        if (strcmp(class_name, TYPE_CHARDEV_FILE) == 0) {
+            object_property_set_str(OBJECT(chr), qemu_opt_get(opts, "path"), "path", &err);
+        }
+
         if (!err) {
             object_property_set_bool(OBJECT(chr), true, "realized", &err);
         }
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH 1/6] object: add object_property_add_bool
  2012-10-15 19:34 ` [Qemu-devel] [PATCH 1/6] object: add object_property_add_bool Anthony Liguori
@ 2012-10-16 15:44   ` Andreas Färber
  2012-10-23 11:30   ` Markus Armbruster
  1 sibling, 0 replies; 13+ messages in thread
From: Andreas Färber @ 2012-10-16 15:44 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Paolo Bonzini, qemu-devel, Gerd Hoffmann

Am 15.10.2012 21:34, schrieb Anthony Liguori:
> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>

This feels like a resend or v2. I remember discussing whether an opaque
might be a good idea and we decided not to lacking an immanent use case.

Reviewed-by: Andreas Färber <afaerber@suse.de>

Andreas

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH 6/6] chardev: convert file backend to realize
  2012-10-15 19:34 ` [Qemu-devel] [PATCH 6/6] chardev: convert file backend " Anthony Liguori
@ 2012-10-16 15:52   ` Paolo Bonzini
  2012-10-16 19:44     ` Anthony Liguori
  0 siblings, 1 reply; 13+ messages in thread
From: Paolo Bonzini @ 2012-10-16 15:52 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: qemu-devel, Andreas Faerber, Gerd Hoffmann

Il 15/10/2012 21:34, Anthony Liguori ha scritto:
> +static char *chardev_file_get_path(Object *obj, Error **errp)
> +{
> +    CharDriverState *chr = CHARDEV(obj);
> +    FDCharDriver *s = chr->opaque;
> +
> +    return s->path ? g_strdup(s->path) : g_strdup("");
> +}
> +
> +static void chardev_file_set_path(Object *obj, const char *value, Error **errp)
> +{
> +    CharDriverState *chr = CHARDEV(obj);
> +    FDCharDriver *s = chr->opaque;
> +
> +    if (chr->realized) {
> +        error_set(errp, QERR_PERMISSION_DENIED);
> +        return;
> +    }
> +
> +    if (s->path) {
> +        g_free(s->path);
> +    }
> +
> +    s->path = g_strdup(value);
> +}
> +
> +static void chardev_file_initfn(Object *obj)
> +{
> +    CharDriverState *chr = CHARDEV(obj);
> +
> +    object_property_add_str(obj, "path", chardev_file_get_path, chardev_file_set_path, NULL);
> +#ifndef _WIN32
> +    chr->opaque = CHARDEV_FILE(obj);
> +#endif
> +}
> +

IMHO this really really calls for pushing static properties and realized
up to Object...

Paolo

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH 6/6] chardev: convert file backend to realize
  2012-10-16 15:52   ` Paolo Bonzini
@ 2012-10-16 19:44     ` Anthony Liguori
  0 siblings, 0 replies; 13+ messages in thread
From: Anthony Liguori @ 2012-10-16 19:44 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-devel, Andreas Faerber, Gerd Hoffmann

Paolo Bonzini <pbonzini@redhat.com> writes:

> Il 15/10/2012 21:34, Anthony Liguori ha scritto:
>> +static char *chardev_file_get_path(Object *obj, Error **errp)
>> +{
>> +    CharDriverState *chr = CHARDEV(obj);
>> +    FDCharDriver *s = chr->opaque;
>> +
>> +    return s->path ? g_strdup(s->path) : g_strdup("");
>> +}
>> +
>> +static void chardev_file_set_path(Object *obj, const char *value, Error **errp)
>> +{
>> +    CharDriverState *chr = CHARDEV(obj);
>> +    FDCharDriver *s = chr->opaque;
>> +
>> +    if (chr->realized) {
>> +        error_set(errp, QERR_PERMISSION_DENIED);
>> +        return;
>> +    }
>> +
>> +    if (s->path) {
>> +        g_free(s->path);
>> +    }
>> +
>> +    s->path = g_strdup(value);
>> +}
>> +
>> +static void chardev_file_initfn(Object *obj)
>> +{
>> +    CharDriverState *chr = CHARDEV(obj);
>> +
>> +    object_property_add_str(obj, "path", chardev_file_get_path, chardev_file_set_path, NULL);
>> +#ifndef _WIN32
>> +    chr->opaque = CHARDEV_FILE(obj);
>> +#endif
>> +}
>> +
>
> IMHO this really really calls for pushing static properties and realized
> up to Object...

I agree actually.  But this doesn't add anything to Object, this just
adds a new set of properties that are implemented entirely in terms of
the existing property infrastructure.

What I don't want to do though is push the notion of "realize" to
Object.  Instead, we should have a mechanism to "lock" read/write
properties so they no longer are mutable.  This should not affect the
object's state but rather the individual property state.

IOW, we shouldn't be adding anything to Object to do this.

Regards,

Anthony Liguori

>
> Paolo

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 0/6] chardev: convert to QOM
  2012-10-15 19:34 [Qemu-devel] [RFC PATCH 0/6] chardev: convert to QOM Anthony Liguori
                   ` (5 preceding siblings ...)
  2012-10-15 19:34 ` [Qemu-devel] [PATCH 6/6] chardev: convert file backend " Anthony Liguori
@ 2012-10-17  8:07 ` Gerd Hoffmann
  2012-10-17 14:44   ` Anthony Liguori
  6 siblings, 1 reply; 13+ messages in thread
From: Gerd Hoffmann @ 2012-10-17  8:07 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Paolo Bonzini, qemu-devel, Andreas Faerber

  Hi,

> I think the main decision point here is whether we introduce a separate
> chardev_add/chardev_del command or just use the qom-create command that has
> been posted previously.

Do you have a git tree with this series + qom-create to look at and play
with?

thanks,
  Gerd

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 0/6] chardev: convert to QOM
  2012-10-17  8:07 ` [Qemu-devel] [RFC PATCH 0/6] chardev: convert to QOM Gerd Hoffmann
@ 2012-10-17 14:44   ` Anthony Liguori
  0 siblings, 0 replies; 13+ messages in thread
From: Anthony Liguori @ 2012-10-17 14:44 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: Paolo Bonzini, qemu-devel, Andreas Faerber

Gerd Hoffmann <kraxel@redhat.com> writes:

>   Hi,
>
>> I think the main decision point here is whether we introduce a separate
>> chardev_add/chardev_del command or just use the qom-create command that has
>> been posted previously.
>
> Do you have a git tree with this series + qom-create to look at and play
> with?

https://github.com/aliguori/qemu/tree/chardev-qom.1

I haven't tried the qom-new command from Markus but I've also included
the -object option that I posted a while ago.  That seems to work.
Here's an example command line:

$ x86_64-softmmu/qemu-system-x86_64 \
     -object chardev-file,path=foo.txt,label=chr0,id=chr0,realized=on \
     -device isa-serial,index=0,chardev=chr0 -hda ~/images/linux.img \
     -snapshot -enable-kvm

A couple caveats:

- The label/id duplication is ugly.  The need to use label disappears
  though once we switch devices over to using links.

- Some error checking is needed to deal with trying to use an unrealized
  chardev.

- It may still make sense to have a chardev-add operation but I think
  that operation should work in terms of something like qom-new.
  Probably with some special casing to fix the container path to
  /backends/chardev and also to deal with automatically setting label
  based on id.  It may make sense to also always set realized explicitly
  to 'on' in chardev-add.

Regards,

Anthony Liguori

>
> thanks,
>   Gerd

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH 1/6] object: add object_property_add_bool
  2012-10-15 19:34 ` [Qemu-devel] [PATCH 1/6] object: add object_property_add_bool Anthony Liguori
  2012-10-16 15:44   ` Andreas Färber
@ 2012-10-23 11:30   ` Markus Armbruster
  1 sibling, 0 replies; 13+ messages in thread
From: Markus Armbruster @ 2012-10-23 11:30 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Paolo Bonzini, qemu-devel, Andreas Faerber, Gerd Hoffmann

Anthony Liguori <aliguori@us.ibm.com> writes:

> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
> ---
>  include/qemu/object.h |   17 ++++++++++++++
>  qom/object.c          |   58 +++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 75 insertions(+), 0 deletions(-)
>
> diff --git a/include/qemu/object.h b/include/qemu/object.h
> index cc75fee..f4dc2ea 100644
> --- a/include/qemu/object.h
> +++ b/include/qemu/object.h
> @@ -947,6 +947,23 @@ void object_property_add_str(Object *obj, const char *name,
>                               struct Error **errp);
>  
>  /**
> + * object_property_add_bool:
> + * @obj: the object to add a property to
> + * @name: the name of the property
> + * @get: the getter or NULL if the property is write-only.  This function must
> + *   return a string to be freed by g_free().

Pasto.  It returns a bool.

> + * @set: the setter or NULL if the property is read-only
> + * @errp: if an error occurs, a pointer to an area to store the error
> + *
> + * Add a bool property using getters/setters.  This function will add a
> + * property of type 'bool'.
> + */
> +void object_property_add_bool(Object *obj, const char *name,
> +                              bool (*get)(Object *, struct Error **),
> +                              void (*set)(Object *, bool, struct Error **),
> +                              struct Error **errp);
> +
> +/**
>   * object_child_foreach:
>   * @obj: the object whose children will be navigated
>   * @fn: the iterator function to be called
[...]

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2012-10-23 11:30 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-10-15 19:34 [Qemu-devel] [RFC PATCH 0/6] chardev: convert to QOM Anthony Liguori
2012-10-15 19:34 ` [Qemu-devel] [PATCH 1/6] object: add object_property_add_bool Anthony Liguori
2012-10-16 15:44   ` Andreas Färber
2012-10-23 11:30   ` Markus Armbruster
2012-10-15 19:34 ` [Qemu-devel] [PATCH 2/6] chardev: convert to QOM (shallow pass) Anthony Liguori
2012-10-15 19:34 ` [Qemu-devel] [PATCH 3/6] chardev: create new QOM types for each sub chardev type Anthony Liguori
2012-10-15 19:34 ` [Qemu-devel] [PATCH 4/6] chardev: implement realize Anthony Liguori
2012-10-15 19:34 ` [Qemu-devel] [PATCH 5/6] chardev: switch the easy backends to realize Anthony Liguori
2012-10-15 19:34 ` [Qemu-devel] [PATCH 6/6] chardev: convert file backend " Anthony Liguori
2012-10-16 15:52   ` Paolo Bonzini
2012-10-16 19:44     ` Anthony Liguori
2012-10-17  8:07 ` [Qemu-devel] [RFC PATCH 0/6] chardev: convert to QOM Gerd Hoffmann
2012-10-17 14:44   ` Anthony Liguori

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.