* [Qemu-devel] [PATCH v2 0/5] Monitor commands for object-add/del @ 2013-12-17 11:25 Paolo Bonzini 2013-12-17 11:26 ` [Qemu-devel] [PATCH v2 1/5] rng: initialize file descriptor to -1 Paolo Bonzini ` (6 more replies) 0 siblings, 7 replies; 13+ messages in thread From: Paolo Bonzini @ 2013-12-17 11:25 UTC (permalink / raw) To: qemu-devel; +Cc: imammedo, stefanha, lcapitulino These allow hotplugging (and hot-unplugging without leaking an object) virtio-rng devices. They can also be used for memory hotplug. v1->v2: fix mistyped underscores in qapi-schema.json Paolo Bonzini (5): rng: initialize file descriptor to -1 qom: fix leak for objects created with -object qom: catch errors in object_property_add_child monitor: add object-add (QMP) and object_add (HMP) command monitor: add object-del (QMP) and object_del (HMP) command backends/rng-random.c | 4 +-- hmp-commands.hx | 28 ++++++++++++++++++ hmp.c | 67 ++++++++++++++++++++++++++++++++++++++++++ hmp.h | 2 ++ include/monitor/monitor.h | 3 ++ include/qapi/visitor.h | 3 +- include/qemu/typedefs.h | 2 ++ qapi-schema.json | 34 ++++++++++++++++++++++ qmp-commands.hx | 51 ++++++++++++++++++++++++++++++++ qmp.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++ qom/object.c | 9 ++++-- vl.c | 3 +- 12 files changed, 273 insertions(+), 7 deletions(-) -- 1.8.4.2 ^ permalink raw reply [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v2 1/5] rng: initialize file descriptor to -1 2013-12-17 11:25 [Qemu-devel] [PATCH v2 0/5] Monitor commands for object-add/del Paolo Bonzini @ 2013-12-17 11:26 ` Paolo Bonzini 2013-12-17 11:26 ` [Qemu-devel] [PATCH v2 2/5] qom: fix leak for objects created with -object Paolo Bonzini ` (5 subsequent siblings) 6 siblings, 0 replies; 13+ messages in thread From: Paolo Bonzini @ 2013-12-17 11:26 UTC (permalink / raw) To: qemu-devel; +Cc: imammedo, stefanha, lcapitulino The file descriptor is never initialized to -1, which makes rng-random close stdin if an object is created and immediately destroyed. If we change it to -1, we also need to protect qemu_set_fd_handler from receiving a bogus file descriptor. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- backends/rng-random.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backends/rng-random.c b/backends/rng-random.c index 68dfc8a..136499d 100644 --- a/backends/rng-random.c +++ b/backends/rng-random.c @@ -123,15 +123,15 @@ static void rng_random_init(Object *obj) NULL); s->filename = g_strdup("/dev/random"); + s->fd = -1; } static void rng_random_finalize(Object *obj) { RndRandom *s = RNG_RANDOM(obj); - qemu_set_fd_handler(s->fd, NULL, NULL, NULL); - if (s->fd != -1) { + qemu_set_fd_handler(s->fd, NULL, NULL, NULL); qemu_close(s->fd); } -- 1.8.4.2 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v2 2/5] qom: fix leak for objects created with -object 2013-12-17 11:25 [Qemu-devel] [PATCH v2 0/5] Monitor commands for object-add/del Paolo Bonzini 2013-12-17 11:26 ` [Qemu-devel] [PATCH v2 1/5] rng: initialize file descriptor to -1 Paolo Bonzini @ 2013-12-17 11:26 ` Paolo Bonzini 2013-12-17 11:26 ` [Qemu-devel] [PATCH v2 3/5] qom: catch errors in object_property_add_child Paolo Bonzini ` (4 subsequent siblings) 6 siblings, 0 replies; 13+ messages in thread From: Paolo Bonzini @ 2013-12-17 11:26 UTC (permalink / raw) To: qemu-devel; +Cc: imammedo, stefanha, lcapitulino The object must be unref-ed when its variable goes out of scope. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- vl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vl.c b/vl.c index 8d5d874..6917fd1 100644 --- a/vl.c +++ b/vl.c @@ -2807,12 +2807,13 @@ static int object_create(QemuOpts *opts, void *opaque) obj = object_new(type); if (qemu_opt_foreach(opts, object_set_property, obj, 1) < 0) { + object_unref(obj); return -1; } object_property_add_child(container_get(object_get_root(), "/objects"), id, obj, NULL); - + object_unref(obj); return 0; } -- 1.8.4.2 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v2 3/5] qom: catch errors in object_property_add_child 2013-12-17 11:25 [Qemu-devel] [PATCH v2 0/5] Monitor commands for object-add/del Paolo Bonzini 2013-12-17 11:26 ` [Qemu-devel] [PATCH v2 1/5] rng: initialize file descriptor to -1 Paolo Bonzini 2013-12-17 11:26 ` [Qemu-devel] [PATCH v2 2/5] qom: fix leak for objects created with -object Paolo Bonzini @ 2013-12-17 11:26 ` Paolo Bonzini 2013-12-17 11:26 ` [Qemu-devel] [PATCH v2 4/5] monitor: add object-add (QMP) and object_add (HMP) command Paolo Bonzini ` (3 subsequent siblings) 6 siblings, 0 replies; 13+ messages in thread From: Paolo Bonzini @ 2013-12-17 11:26 UTC (permalink / raw) To: qemu-devel; +Cc: imammedo, stefanha, lcapitulino Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- qom/object.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/qom/object.c b/qom/object.c index fc19cf6..68fe07a 100644 --- a/qom/object.c +++ b/qom/object.c @@ -988,17 +988,22 @@ static void object_finalize_child_property(Object *obj, const char *name, void object_property_add_child(Object *obj, const char *name, Object *child, Error **errp) { + Error *local_err = NULL; gchar *type; type = g_strdup_printf("child<%s>", object_get_typename(OBJECT(child))); object_property_add(obj, name, type, object_get_child_property, - NULL, object_finalize_child_property, child, errp); - + NULL, object_finalize_child_property, child, &local_err); + if (error_is_set(&local_err)) { + error_propagate(errp, local_err); + goto out; + } object_ref(child); g_assert(child->parent == NULL); child->parent = obj; +out: g_free(type); } -- 1.8.4.2 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v2 4/5] monitor: add object-add (QMP) and object_add (HMP) command 2013-12-17 11:25 [Qemu-devel] [PATCH v2 0/5] Monitor commands for object-add/del Paolo Bonzini ` (2 preceding siblings ...) 2013-12-17 11:26 ` [Qemu-devel] [PATCH v2 3/5] qom: catch errors in object_property_add_child Paolo Bonzini @ 2013-12-17 11:26 ` Paolo Bonzini 2013-12-17 11:54 ` Peter Crosthwaite 2013-12-17 11:26 ` [Qemu-devel] [PATCH v2 5/5] monitor: add object-del (QMP) and object_del " Paolo Bonzini ` (2 subsequent siblings) 6 siblings, 1 reply; 13+ messages in thread From: Paolo Bonzini @ 2013-12-17 11:26 UTC (permalink / raw) To: qemu-devel; +Cc: imammedo, stefanha, lcapitulino Add two commands that are the monitor counterparts of -object. The commands have the same Visitor-based implementation, but use different kinds of visitors so that the HMP command has a DWIM string-based syntax, while the QMP variant accepts a stricter JSON-based properties dictionary. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- hmp-commands.hx | 14 +++++++++++ hmp.c | 58 ++++++++++++++++++++++++++++++++++++++++++++ hmp.h | 1 + include/monitor/monitor.h | 3 +++ include/qapi/visitor.h | 3 +-- include/qemu/typedefs.h | 2 ++ qapi-schema.json | 20 +++++++++++++++ qmp-commands.hx | 27 +++++++++++++++++++++ qmp.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 188 insertions(+), 2 deletions(-) diff --git a/hmp-commands.hx b/hmp-commands.hx index caae5ad..0563b33 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1243,6 +1243,20 @@ STEXI Remove host network device. ETEXI + { + .name = "object_add", + .args_type = "object:O", + .params = "[qom-type=]type,id=str[,prop=value][,...]", + .help = "create QOM object", + .mhandler.cmd = hmp_object_add, + }, + +STEXI +@item object_add +@findex object_add +Create QOM object. +ETEXI + #ifdef CONFIG_SLIRP { .name = "hostfwd_add", diff --git a/hmp.c b/hmp.c index 32ee285..a1669ab 100644 --- a/hmp.c +++ b/hmp.c @@ -21,6 +21,7 @@ #include "qmp-commands.h" #include "qemu/sockets.h" #include "monitor/monitor.h" +#include "qapi/opts-visitor.h" #include "ui/console.h" #include "block/qapi.h" #include "qemu-io.h" @@ -1354,6 +1355,63 @@ void hmp_netdev_del(Monitor *mon, const QDict *qdict) hmp_handle_error(mon, &err); } +void hmp_object_add(Monitor *mon, const QDict *qdict) +{ + Error *err = NULL; + QemuOpts *opts; + char *type = NULL; + char *id = NULL; + void *dummy = NULL; + OptsVisitor *ov; + QDict *pdict; + + opts = qemu_opts_from_qdict(qemu_find_opts("object"), qdict, &err); + if (error_is_set(&err)) { + goto out; + } + + ov = opts_visitor_new(opts); + pdict = qdict_clone_shallow(qdict); + + visit_start_struct(opts_get_visitor(ov), &dummy, NULL, NULL, 0, &err); + if (error_is_set(&err)) { + goto out_clean; + } + + qdict_del(pdict, "qom-type"); + visit_type_str(opts_get_visitor(ov), &type, "qom-type", &err); + if (error_is_set(&err)) { + goto out_clean; + } + + qdict_del(pdict, "id"); + visit_type_str(opts_get_visitor(ov), &id, "id", &err); + if (error_is_set(&err)) { + goto out_clean; + } + + object_add(type, id, pdict, opts_get_visitor(ov), &err); + if (error_is_set(&err)) { + goto out_clean; + } + visit_end_struct(opts_get_visitor(ov), &err); + if (error_is_set(&err)) { + qmp_object_del(id, NULL); + } + +out_clean: + opts_visitor_cleanup(ov); + + QDECREF(pdict); + qemu_opts_del(opts); + g_free(id); + g_free(type); + g_free(dummy); + +out: + hmp_handle_error(mon, &err); +} + void hmp_getfd(Monitor *mon, const QDict *qdict) { const char *fdname = qdict_get_str(qdict, "fdname"); diff --git a/hmp.h b/hmp.h index 54cf71f..521449b 100644 --- a/hmp.h +++ b/hmp.h @@ -89,5 +89,6 @@ void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict); void hmp_chardev_add(Monitor *mon, const QDict *qdict); void hmp_chardev_remove(Monitor *mon, const QDict *qdict); void hmp_qemu_io(Monitor *mon, const QDict *qdict); +void hmp_object_add(Monitor *mon, const QDict *qdict); #endif diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h index 10fa0e3..22d8b8f 100644 --- a/include/monitor/monitor.h +++ b/include/monitor/monitor.h @@ -93,6 +93,9 @@ int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func, int qmp_qom_set(Monitor *mon, const QDict *qdict, QObject **ret); int qmp_qom_get(Monitor *mon, const QDict *qdict, QObject **ret); +int qmp_object_add(Monitor *mon, const QDict *qdict, QObject **ret); +void object_add(const char *type, const char *id, const QDict *qdict, + Visitor *v, Error **errp); AddfdInfo *monitor_fdset_add_fd(int fd, bool has_fdset_id, int64_t fdset_id, bool has_opaque, const char *opaque, diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h index 48a2a2e..29da211 100644 --- a/include/qapi/visitor.h +++ b/include/qapi/visitor.h @@ -13,6 +13,7 @@ #ifndef QAPI_VISITOR_CORE_H #define QAPI_VISITOR_CORE_H +#include "qemu/typedefs.h" #include "qapi/qmp/qobject.h" #include "qapi/error.h" #include <stdlib.h> @@ -26,8 +27,6 @@ typedef struct GenericList struct GenericList *next; } GenericList; -typedef struct Visitor Visitor; - void visit_start_handle(Visitor *v, void **obj, const char *kind, const char *name, Error **errp); void visit_end_handle(Visitor *v, Error **errp); diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h index a4c1b84..4524496 100644 --- a/include/qemu/typedefs.h +++ b/include/qemu/typedefs.h @@ -10,6 +10,8 @@ typedef struct QEMUBH QEMUBH; typedef struct AioContext AioContext; +typedef struct Visitor Visitor; + struct Monitor; typedef struct Monitor Monitor; typedef struct MigrationParams MigrationParams; diff --git a/qapi-schema.json b/qapi-schema.json index 83fa485..111463b 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -2759,6 +2759,26 @@ { 'command': 'netdev_del', 'data': {'id': 'str'} } ## +# @object-add: +# +# Create a QOM object. +# +# @qom-type: the class name for the object to be created +# +# @id: the name of the new object +# +# @props: #optional a dictionary of properties to be passed to the backend +# +# Returns: Nothing on success +# Error if @qom-type is not a valid class name +# +# Since: 2.0 +## +{ 'command': 'object-add', + 'data': {'qom-type': 'str', 'id': 'str', '*props': 'dict'}, + 'gen': 'no' } + +## # @NetdevNoneOptions # # Use it alone to have zero network devices. diff --git a/qmp-commands.hx b/qmp-commands.hx index fba15cd..d09ea53 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -879,6 +879,33 @@ Example: EQMP { + .name = "object-add", + .args_type = "qom-type:s,id:s,props:q?", + .mhandler.cmd_new = qmp_object_add, + }, + +SQMP +object-add +---------- + +Create QOM object. + +Arguments: + +- "qom-type": the object's QOM type, i.e. the class name (json-string) +- "id": the object's ID, must be unique (json-string) +- "props": a dictionary of object property values (optional, json-dict) + +Example: + +-> { "execute": "object-add", "arguments": { "qom-type": "rng-random", "id": "rng1", + "props": { "filename": "/dev/hwrng" } } } +<- { "return": {} } + +EQMP + + + { .name = "block_resize", .args_type = "device:B,size:o", .mhandler.cmd_new = qmp_marshal_input_block_resize, diff --git a/qmp.c b/qmp.c index 4c149b3..255c55f 100644 --- a/qmp.c +++ b/qmp.c @@ -24,6 +24,8 @@ #include "hw/qdev.h" #include "sysemu/blockdev.h" #include "qom/qom-qobject.h" +#include "qapi/qmp/qobject.h" +#include "qapi/qmp-input-visitor.h" #include "hw/boards.h" NameInfo *qmp_query_name(Error **errp) @@ -529,3 +531,63 @@ void qmp_add_client(const char *protocol, const char *fdname, error_setg(errp, "protocol '%s' is invalid", protocol); close(fd); } + +void object_add(const char *type, const char *id, const QDict *qdict, + Visitor *v, Error **errp) +{ + Object *obj; + const QDictEntry *e; + Error *local_err = NULL; + + if (!object_class_by_name(type)) { + error_setg(errp, "invalid class name"); + return; + } + + obj = object_new(type); + if (qdict) { + for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) { + object_property_set(obj, v, e->key, &local_err); + if (error_is_set(&local_err)) { + error_propagate(errp, local_err); + object_unref(obj); + return; + } + } + } + + object_property_add_child(container_get(object_get_root(), "/objects"), + id, obj, errp); + object_unref(obj); +} + +int qmp_object_add(Monitor *mon, const QDict *qdict, QObject **ret) +{ + const char *type = qdict_get_str(qdict, "qom-type"); + const char *id = qdict_get_str(qdict, "id"); + QObject *props = qdict_get(qdict, "props"); + const QDict *pdict = NULL; + Error *local_err = NULL; + QmpInputVisitor *qiv; + + if (props) { + pdict = qobject_to_qdict(props); + if (!pdict) { + error_set(&local_err, QERR_INVALID_PARAMETER_TYPE, "props", "dict"); + goto out; + } + } + + qiv = qmp_input_visitor_new(props); + object_add(type, id, pdict, qmp_input_get_visitor(qiv), &local_err); + qmp_input_visitor_cleanup(qiv); + +out: + if (local_err) { + qerror_report_err(local_err); + error_free(local_err); + return -1; + } + + return 0; +} -- 1.8.4.2 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v2 4/5] monitor: add object-add (QMP) and object_add (HMP) command 2013-12-17 11:26 ` [Qemu-devel] [PATCH v2 4/5] monitor: add object-add (QMP) and object_add (HMP) command Paolo Bonzini @ 2013-12-17 11:54 ` Peter Crosthwaite 2013-12-17 12:24 ` Paolo Bonzini 0 siblings, 1 reply; 13+ messages in thread From: Peter Crosthwaite @ 2013-12-17 11:54 UTC (permalink / raw) To: Paolo Bonzini Cc: Igor Mammedov, qemu-devel@nongnu.org Developers, Stefan Hajnoczi, lcapitulino On Tue, Dec 17, 2013 at 9:26 PM, Paolo Bonzini <pbonzini@redhat.com> wrote: > Add two commands that are the monitor counterparts of -object. The commands > have the same Visitor-based implementation, but use different kinds of > visitors so that the HMP command has a DWIM string-based syntax, while > the QMP variant accepts a stricter JSON-based properties dictionary. > > Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> > --- > hmp-commands.hx | 14 +++++++++++ > hmp.c | 58 ++++++++++++++++++++++++++++++++++++++++++++ > hmp.h | 1 + > include/monitor/monitor.h | 3 +++ > include/qapi/visitor.h | 3 +-- > include/qemu/typedefs.h | 2 ++ > qapi-schema.json | 20 +++++++++++++++ > qmp-commands.hx | 27 +++++++++++++++++++++ > qmp.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++ > 9 files changed, 188 insertions(+), 2 deletions(-) > > diff --git a/hmp-commands.hx b/hmp-commands.hx > index caae5ad..0563b33 100644 > --- a/hmp-commands.hx > +++ b/hmp-commands.hx > @@ -1243,6 +1243,20 @@ STEXI > Remove host network device. > ETEXI > > + { > + .name = "object_add", > + .args_type = "object:O", > + .params = "[qom-type=]type,id=str[,prop=value][,...]", > + .help = "create QOM object", > + .mhandler.cmd = hmp_object_add, > + }, > + > +STEXI > +@item object_add > +@findex object_add > +Create QOM object. > +ETEXI > + > #ifdef CONFIG_SLIRP > { > .name = "hostfwd_add", > diff --git a/hmp.c b/hmp.c > index 32ee285..a1669ab 100644 > --- a/hmp.c > +++ b/hmp.c > @@ -21,6 +21,7 @@ > #include "qmp-commands.h" > #include "qemu/sockets.h" > #include "monitor/monitor.h" > +#include "qapi/opts-visitor.h" > #include "ui/console.h" > #include "block/qapi.h" > #include "qemu-io.h" > @@ -1354,6 +1355,63 @@ void hmp_netdev_del(Monitor *mon, const QDict *qdict) > hmp_handle_error(mon, &err); > } > > +void hmp_object_add(Monitor *mon, const QDict *qdict) > +{ > + Error *err = NULL; > + QemuOpts *opts; > + char *type = NULL; > + char *id = NULL; > + void *dummy = NULL; > + OptsVisitor *ov; > + QDict *pdict; > + > + opts = qemu_opts_from_qdict(qemu_find_opts("object"), qdict, &err); > + if (error_is_set(&err)) { > + goto out; > + } > + > + ov = opts_visitor_new(opts); > + pdict = qdict_clone_shallow(qdict); > + > + visit_start_struct(opts_get_visitor(ov), &dummy, NULL, NULL, 0, &err); > + if (error_is_set(&err)) { > + goto out_clean; > + } So I have been thinking about repeated if(error_is_set(&err)) { goto foo; } and how to reduce its verbosity in situations like this. Can it be solved with a simple semantic: "Error ** accepting APIs will perform no action if the Error ** argument is already set." In this case we would patch visit_foo to just return if error_is_set(errp). Then we can delete these three LOC... > + > + qdict_del(pdict, "qom-type"); > + visit_type_str(opts_get_visitor(ov), &type, "qom-type", &err); > + if (error_is_set(&err)) { > + goto out_clean; > + } > + and these > + qdict_del(pdict, "id"); > + visit_type_str(opts_get_visitor(ov), &id, "id", &err); > + if (error_is_set(&err)) { > + goto out_clean; > + } and these > + > + object_add(type, id, pdict, opts_get_visitor(ov), &err); > + if (error_is_set(&err)) { > + goto out_clean; > + } And leave just the last one which will catch and report the first-occured error as desired. Out of scope of the series of course. Regards, Peter > + visit_end_struct(opts_get_visitor(ov), &err); > + if (error_is_set(&err)) { > + qmp_object_del(id, NULL); > + } > + > +out_clean: > + opts_visitor_cleanup(ov); > + > + QDECREF(pdict); > + qemu_opts_del(opts); > + g_free(id); > + g_free(type); > + g_free(dummy); > + > +out: > + hmp_handle_error(mon, &err); > +} > + > void hmp_getfd(Monitor *mon, const QDict *qdict) > { > const char *fdname = qdict_get_str(qdict, "fdname"); > diff --git a/hmp.h b/hmp.h > index 54cf71f..521449b 100644 > --- a/hmp.h > +++ b/hmp.h > @@ -89,5 +89,6 @@ void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict); > void hmp_chardev_add(Monitor *mon, const QDict *qdict); > void hmp_chardev_remove(Monitor *mon, const QDict *qdict); > void hmp_qemu_io(Monitor *mon, const QDict *qdict); > +void hmp_object_add(Monitor *mon, const QDict *qdict); > > #endif > diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h > index 10fa0e3..22d8b8f 100644 > --- a/include/monitor/monitor.h > +++ b/include/monitor/monitor.h > @@ -93,6 +93,9 @@ int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func, > int qmp_qom_set(Monitor *mon, const QDict *qdict, QObject **ret); > > int qmp_qom_get(Monitor *mon, const QDict *qdict, QObject **ret); > +int qmp_object_add(Monitor *mon, const QDict *qdict, QObject **ret); > +void object_add(const char *type, const char *id, const QDict *qdict, > + Visitor *v, Error **errp); > > AddfdInfo *monitor_fdset_add_fd(int fd, bool has_fdset_id, int64_t fdset_id, > bool has_opaque, const char *opaque, > diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h > index 48a2a2e..29da211 100644 > --- a/include/qapi/visitor.h > +++ b/include/qapi/visitor.h > @@ -13,6 +13,7 @@ > #ifndef QAPI_VISITOR_CORE_H > #define QAPI_VISITOR_CORE_H > > +#include "qemu/typedefs.h" > #include "qapi/qmp/qobject.h" > #include "qapi/error.h" > #include <stdlib.h> > @@ -26,8 +27,6 @@ typedef struct GenericList > struct GenericList *next; > } GenericList; > > -typedef struct Visitor Visitor; > - > void visit_start_handle(Visitor *v, void **obj, const char *kind, > const char *name, Error **errp); > void visit_end_handle(Visitor *v, Error **errp); > diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h > index a4c1b84..4524496 100644 > --- a/include/qemu/typedefs.h > +++ b/include/qemu/typedefs.h > @@ -10,6 +10,8 @@ typedef struct QEMUBH QEMUBH; > > typedef struct AioContext AioContext; > > +typedef struct Visitor Visitor; > + > struct Monitor; > typedef struct Monitor Monitor; > typedef struct MigrationParams MigrationParams; > diff --git a/qapi-schema.json b/qapi-schema.json > index 83fa485..111463b 100644 > --- a/qapi-schema.json > +++ b/qapi-schema.json > @@ -2759,6 +2759,26 @@ > { 'command': 'netdev_del', 'data': {'id': 'str'} } > > ## > +# @object-add: > +# > +# Create a QOM object. > +# > +# @qom-type: the class name for the object to be created > +# > +# @id: the name of the new object > +# > +# @props: #optional a dictionary of properties to be passed to the backend > +# > +# Returns: Nothing on success > +# Error if @qom-type is not a valid class name > +# > +# Since: 2.0 > +## > +{ 'command': 'object-add', > + 'data': {'qom-type': 'str', 'id': 'str', '*props': 'dict'}, > + 'gen': 'no' } > + > +## > # @NetdevNoneOptions > # > # Use it alone to have zero network devices. > diff --git a/qmp-commands.hx b/qmp-commands.hx > index fba15cd..d09ea53 100644 > --- a/qmp-commands.hx > +++ b/qmp-commands.hx > @@ -879,6 +879,33 @@ Example: > EQMP > > { > + .name = "object-add", > + .args_type = "qom-type:s,id:s,props:q?", > + .mhandler.cmd_new = qmp_object_add, > + }, > + > +SQMP > +object-add > +---------- > + > +Create QOM object. > + > +Arguments: > + > +- "qom-type": the object's QOM type, i.e. the class name (json-string) > +- "id": the object's ID, must be unique (json-string) > +- "props": a dictionary of object property values (optional, json-dict) > + > +Example: > + > +-> { "execute": "object-add", "arguments": { "qom-type": "rng-random", "id": "rng1", > + "props": { "filename": "/dev/hwrng" } } } > +<- { "return": {} } > + > +EQMP > + > + > + { > .name = "block_resize", > .args_type = "device:B,size:o", > .mhandler.cmd_new = qmp_marshal_input_block_resize, > diff --git a/qmp.c b/qmp.c > index 4c149b3..255c55f 100644 > --- a/qmp.c > +++ b/qmp.c > @@ -24,6 +24,8 @@ > #include "hw/qdev.h" > #include "sysemu/blockdev.h" > #include "qom/qom-qobject.h" > +#include "qapi/qmp/qobject.h" > +#include "qapi/qmp-input-visitor.h" > #include "hw/boards.h" > > NameInfo *qmp_query_name(Error **errp) > @@ -529,3 +531,63 @@ void qmp_add_client(const char *protocol, const char *fdname, > error_setg(errp, "protocol '%s' is invalid", protocol); > close(fd); > } > + > +void object_add(const char *type, const char *id, const QDict *qdict, > + Visitor *v, Error **errp) > +{ > + Object *obj; > + const QDictEntry *e; > + Error *local_err = NULL; > + > + if (!object_class_by_name(type)) { > + error_setg(errp, "invalid class name"); > + return; > + } > + > + obj = object_new(type); > + if (qdict) { > + for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) { > + object_property_set(obj, v, e->key, &local_err); > + if (error_is_set(&local_err)) { > + error_propagate(errp, local_err); > + object_unref(obj); > + return; > + } > + } > + } > + > + object_property_add_child(container_get(object_get_root(), "/objects"), > + id, obj, errp); > + object_unref(obj); > +} > + > +int qmp_object_add(Monitor *mon, const QDict *qdict, QObject **ret) > +{ > + const char *type = qdict_get_str(qdict, "qom-type"); > + const char *id = qdict_get_str(qdict, "id"); > + QObject *props = qdict_get(qdict, "props"); > + const QDict *pdict = NULL; > + Error *local_err = NULL; > + QmpInputVisitor *qiv; > + > + if (props) { > + pdict = qobject_to_qdict(props); > + if (!pdict) { > + error_set(&local_err, QERR_INVALID_PARAMETER_TYPE, "props", "dict"); > + goto out; > + } > + } > + > + qiv = qmp_input_visitor_new(props); > + object_add(type, id, pdict, qmp_input_get_visitor(qiv), &local_err); > + qmp_input_visitor_cleanup(qiv); > + > +out: > + if (local_err) { > + qerror_report_err(local_err); > + error_free(local_err); > + return -1; > + } > + > + return 0; > +} > -- > 1.8.4.2 > > > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v2 4/5] monitor: add object-add (QMP) and object_add (HMP) command 2013-12-17 11:54 ` Peter Crosthwaite @ 2013-12-17 12:24 ` Paolo Bonzini 2013-12-17 12:38 ` Peter Crosthwaite 0 siblings, 1 reply; 13+ messages in thread From: Paolo Bonzini @ 2013-12-17 12:24 UTC (permalink / raw) To: Peter Crosthwaite Cc: Igor Mammedov, qemu-devel@nongnu.org Developers, Stefan Hajnoczi, lcapitulino Il 17/12/2013 12:54, Peter Crosthwaite ha scritto: >> + visit_start_struct(opts_get_visitor(ov), &dummy, NULL, NULL, 0, &err); >> + if (error_is_set(&err)) { >> + goto out_clean; >> + } > > So I have been thinking about repeated if(error_is_set(&err)) { goto > foo; } and how to reduce its verbosity in situations like this. Can it > be solved with a simple semantic: > > "Error ** accepting APIs will perform no action if the Error ** > argument is already set." I think this is a case where verbosity <<< ease of use. In this case, the caller code is particularly simple, but what if I needed to dereference the return value of the first called function, to get the argument to the second? You would still need an "if". Paolo > In this case we would patch visit_foo to just return if > error_is_set(errp). Then we can delete these three LOC... > >> + >> + qdict_del(pdict, "qom-type"); >> + visit_type_str(opts_get_visitor(ov), &type, "qom-type", &err); >> + if (error_is_set(&err)) { >> + goto out_clean; >> + } >> + > > and these > >> + qdict_del(pdict, "id"); >> + visit_type_str(opts_get_visitor(ov), &id, "id", &err); >> + if (error_is_set(&err)) { >> + goto out_clean; >> + } > > and these > >> + >> + object_add(type, id, pdict, opts_get_visitor(ov), &err); >> + if (error_is_set(&err)) { >> + goto out_clean; >> + } > > And leave just the last one which will catch and report the > first-occured error as desired. > > Out of scope of the series of course. > > Regards, > Peter > >> + visit_end_struct(opts_get_visitor(ov), &err); >> + if (error_is_set(&err)) { >> + qmp_object_del(id, NULL); >> + } >> + >> +out_clean: >> + opts_visitor_cleanup(ov); >> + >> + QDECREF(pdict); >> + qemu_opts_del(opts); >> + g_free(id); >> + g_free(type); >> + g_free(dummy); >> + >> +out: >> + hmp_handle_error(mon, &err); >> +} >> + >> void hmp_getfd(Monitor *mon, const QDict *qdict) >> { >> const char *fdname = qdict_get_str(qdict, "fdname"); >> diff --git a/hmp.h b/hmp.h >> index 54cf71f..521449b 100644 >> --- a/hmp.h >> +++ b/hmp.h >> @@ -89,5 +89,6 @@ void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict); >> void hmp_chardev_add(Monitor *mon, const QDict *qdict); >> void hmp_chardev_remove(Monitor *mon, const QDict *qdict); >> void hmp_qemu_io(Monitor *mon, const QDict *qdict); >> +void hmp_object_add(Monitor *mon, const QDict *qdict); >> >> #endif >> diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h >> index 10fa0e3..22d8b8f 100644 >> --- a/include/monitor/monitor.h >> +++ b/include/monitor/monitor.h >> @@ -93,6 +93,9 @@ int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func, >> int qmp_qom_set(Monitor *mon, const QDict *qdict, QObject **ret); >> >> int qmp_qom_get(Monitor *mon, const QDict *qdict, QObject **ret); >> +int qmp_object_add(Monitor *mon, const QDict *qdict, QObject **ret); >> +void object_add(const char *type, const char *id, const QDict *qdict, >> + Visitor *v, Error **errp); >> >> AddfdInfo *monitor_fdset_add_fd(int fd, bool has_fdset_id, int64_t fdset_id, >> bool has_opaque, const char *opaque, >> diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h >> index 48a2a2e..29da211 100644 >> --- a/include/qapi/visitor.h >> +++ b/include/qapi/visitor.h >> @@ -13,6 +13,7 @@ >> #ifndef QAPI_VISITOR_CORE_H >> #define QAPI_VISITOR_CORE_H >> >> +#include "qemu/typedefs.h" >> #include "qapi/qmp/qobject.h" >> #include "qapi/error.h" >> #include <stdlib.h> >> @@ -26,8 +27,6 @@ typedef struct GenericList >> struct GenericList *next; >> } GenericList; >> >> -typedef struct Visitor Visitor; >> - >> void visit_start_handle(Visitor *v, void **obj, const char *kind, >> const char *name, Error **errp); >> void visit_end_handle(Visitor *v, Error **errp); >> diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h >> index a4c1b84..4524496 100644 >> --- a/include/qemu/typedefs.h >> +++ b/include/qemu/typedefs.h >> @@ -10,6 +10,8 @@ typedef struct QEMUBH QEMUBH; >> >> typedef struct AioContext AioContext; >> >> +typedef struct Visitor Visitor; >> + >> struct Monitor; >> typedef struct Monitor Monitor; >> typedef struct MigrationParams MigrationParams; >> diff --git a/qapi-schema.json b/qapi-schema.json >> index 83fa485..111463b 100644 >> --- a/qapi-schema.json >> +++ b/qapi-schema.json >> @@ -2759,6 +2759,26 @@ >> { 'command': 'netdev_del', 'data': {'id': 'str'} } >> >> ## >> +# @object-add: >> +# >> +# Create a QOM object. >> +# >> +# @qom-type: the class name for the object to be created >> +# >> +# @id: the name of the new object >> +# >> +# @props: #optional a dictionary of properties to be passed to the backend >> +# >> +# Returns: Nothing on success >> +# Error if @qom-type is not a valid class name >> +# >> +# Since: 2.0 >> +## >> +{ 'command': 'object-add', >> + 'data': {'qom-type': 'str', 'id': 'str', '*props': 'dict'}, >> + 'gen': 'no' } >> + >> +## >> # @NetdevNoneOptions >> # >> # Use it alone to have zero network devices. >> diff --git a/qmp-commands.hx b/qmp-commands.hx >> index fba15cd..d09ea53 100644 >> --- a/qmp-commands.hx >> +++ b/qmp-commands.hx >> @@ -879,6 +879,33 @@ Example: >> EQMP >> >> { >> + .name = "object-add", >> + .args_type = "qom-type:s,id:s,props:q?", >> + .mhandler.cmd_new = qmp_object_add, >> + }, >> + >> +SQMP >> +object-add >> +---------- >> + >> +Create QOM object. >> + >> +Arguments: >> + >> +- "qom-type": the object's QOM type, i.e. the class name (json-string) >> +- "id": the object's ID, must be unique (json-string) >> +- "props": a dictionary of object property values (optional, json-dict) >> + >> +Example: >> + >> +-> { "execute": "object-add", "arguments": { "qom-type": "rng-random", "id": "rng1", >> + "props": { "filename": "/dev/hwrng" } } } >> +<- { "return": {} } >> + >> +EQMP >> + >> + >> + { >> .name = "block_resize", >> .args_type = "device:B,size:o", >> .mhandler.cmd_new = qmp_marshal_input_block_resize, >> diff --git a/qmp.c b/qmp.c >> index 4c149b3..255c55f 100644 >> --- a/qmp.c >> +++ b/qmp.c >> @@ -24,6 +24,8 @@ >> #include "hw/qdev.h" >> #include "sysemu/blockdev.h" >> #include "qom/qom-qobject.h" >> +#include "qapi/qmp/qobject.h" >> +#include "qapi/qmp-input-visitor.h" >> #include "hw/boards.h" >> >> NameInfo *qmp_query_name(Error **errp) >> @@ -529,3 +531,63 @@ void qmp_add_client(const char *protocol, const char *fdname, >> error_setg(errp, "protocol '%s' is invalid", protocol); >> close(fd); >> } >> + >> +void object_add(const char *type, const char *id, const QDict *qdict, >> + Visitor *v, Error **errp) >> +{ >> + Object *obj; >> + const QDictEntry *e; >> + Error *local_err = NULL; >> + >> + if (!object_class_by_name(type)) { >> + error_setg(errp, "invalid class name"); >> + return; >> + } >> + >> + obj = object_new(type); >> + if (qdict) { >> + for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) { >> + object_property_set(obj, v, e->key, &local_err); >> + if (error_is_set(&local_err)) { >> + error_propagate(errp, local_err); >> + object_unref(obj); >> + return; >> + } >> + } >> + } >> + >> + object_property_add_child(container_get(object_get_root(), "/objects"), >> + id, obj, errp); >> + object_unref(obj); >> +} >> + >> +int qmp_object_add(Monitor *mon, const QDict *qdict, QObject **ret) >> +{ >> + const char *type = qdict_get_str(qdict, "qom-type"); >> + const char *id = qdict_get_str(qdict, "id"); >> + QObject *props = qdict_get(qdict, "props"); >> + const QDict *pdict = NULL; >> + Error *local_err = NULL; >> + QmpInputVisitor *qiv; >> + >> + if (props) { >> + pdict = qobject_to_qdict(props); >> + if (!pdict) { >> + error_set(&local_err, QERR_INVALID_PARAMETER_TYPE, "props", "dict"); >> + goto out; >> + } >> + } >> + >> + qiv = qmp_input_visitor_new(props); >> + object_add(type, id, pdict, qmp_input_get_visitor(qiv), &local_err); >> + qmp_input_visitor_cleanup(qiv); >> + >> +out: >> + if (local_err) { >> + qerror_report_err(local_err); >> + error_free(local_err); >> + return -1; >> + } >> + >> + return 0; >> +} >> -- >> 1.8.4.2 >> >> >> ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v2 4/5] monitor: add object-add (QMP) and object_add (HMP) command 2013-12-17 12:24 ` Paolo Bonzini @ 2013-12-17 12:38 ` Peter Crosthwaite 2013-12-17 13:07 ` Markus Armbruster 0 siblings, 1 reply; 13+ messages in thread From: Peter Crosthwaite @ 2013-12-17 12:38 UTC (permalink / raw) To: Paolo Bonzini Cc: Igor Mammedov, qemu-devel@nongnu.org Developers, Stefan Hajnoczi, lcapitulino On Tue, Dec 17, 2013 at 10:24 PM, Paolo Bonzini <pbonzini@redhat.com> wrote: > Il 17/12/2013 12:54, Peter Crosthwaite ha scritto: >>> + visit_start_struct(opts_get_visitor(ov), &dummy, NULL, NULL, 0, &err); >>> + if (error_is_set(&err)) { >>> + goto out_clean; >>> + } >> >> So I have been thinking about repeated if(error_is_set(&err)) { goto >> foo; } and how to reduce its verbosity in situations like this. Can it >> be solved with a simple semantic: >> >> "Error ** accepting APIs will perform no action if the Error ** >> argument is already set." > > I think this is a case where verbosity <<< ease of use. > > In this case, the caller code is particularly simple, but what if I > needed to dereference the return value of the first called function, to > get the argument to the second? You would still need an "if". > Yes thats right. This isn't going to work universally and callers will always have the responsibility of knowing whether they can continue or not. But it will help a lot for repetitive collections of similar independent functions calls. The ultimate example is probably the device tree API calls in hw/ppc/e500.c. I want to patch the device tree API to be nice and Error**ified (for my own future reasons) but I sure don't want to have to patch e500 to check every qemu_devtree_foo API call with these 3 LOC. TBH i'll probably just preserve current behavior using &error_abort in next rev of that series, but it should be possible to do less verbose caller-customized collective error handling in some way. Regards, Peter ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v2 4/5] monitor: add object-add (QMP) and object_add (HMP) command 2013-12-17 12:38 ` Peter Crosthwaite @ 2013-12-17 13:07 ` Markus Armbruster 2013-12-17 21:56 ` Peter Crosthwaite 0 siblings, 1 reply; 13+ messages in thread From: Markus Armbruster @ 2013-12-17 13:07 UTC (permalink / raw) To: Peter Crosthwaite Cc: Paolo Bonzini, lcapitulino, qemu-devel@nongnu.org Developers, Stefan Hajnoczi, Igor Mammedov Peter Crosthwaite <peter.crosthwaite@xilinx.com> writes: > On Tue, Dec 17, 2013 at 10:24 PM, Paolo Bonzini <pbonzini@redhat.com> wrote: >> Il 17/12/2013 12:54, Peter Crosthwaite ha scritto: >>>> + visit_start_struct(opts_get_visitor(ov), &dummy, NULL, NULL, 0, &err); >>>> + if (error_is_set(&err)) { >>>> + goto out_clean; >>>> + } >>> >>> So I have been thinking about repeated if(error_is_set(&err)) { goto >>> foo; } and how to reduce its verbosity in situations like this. Can it >>> be solved with a simple semantic: >>> >>> "Error ** accepting APIs will perform no action if the Error ** >>> argument is already set." >> >> I think this is a case where verbosity <<< ease of use. >> >> In this case, the caller code is particularly simple, but what if I >> needed to dereference the return value of the first called function, to >> get the argument to the second? You would still need an "if". >> > > Yes thats right. This isn't going to work universally and callers will > always have the responsibility of knowing whether they can continue or > not. But it will help a lot for repetitive collections of similar > independent functions calls. The ultimate example is probably the > device tree API calls in hw/ppc/e500.c. > > I want to patch the device tree API to be nice and Error**ified (for > my own future reasons) but I sure don't want to have to patch e500 to > check every qemu_devtree_foo API call with these 3 LOC. TBH i'll > probably just preserve current behavior using &error_abort in next rev > of that series, but it should be possible to do less verbose > caller-customized collective error handling in some way. error_set() & friends currently have a "errp doesn't contain an error already" precondition: if (errp == NULL) { return; } assert(*errp == NULL); You could change the function contracts to ignore additional errors. Theoretical drawback: in situations where that isn't intended, programming errors no longer get caught. If people actually care for that enough to veto your change, you can try adding new functions for use when it is intended. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v2 4/5] monitor: add object-add (QMP) and object_add (HMP) command 2013-12-17 13:07 ` Markus Armbruster @ 2013-12-17 21:56 ` Peter Crosthwaite 0 siblings, 0 replies; 13+ messages in thread From: Peter Crosthwaite @ 2013-12-17 21:56 UTC (permalink / raw) To: Markus Armbruster Cc: Paolo Bonzini, Igor Mammedov, qemu-devel@nongnu.org Developers, Stefan Hajnoczi, lcapitulino On Tue, Dec 17, 2013 at 11:07 PM, Markus Armbruster <armbru@redhat.com> wrote: > Peter Crosthwaite <peter.crosthwaite@xilinx.com> writes: > >> On Tue, Dec 17, 2013 at 10:24 PM, Paolo Bonzini <pbonzini@redhat.com> wrote: >>> Il 17/12/2013 12:54, Peter Crosthwaite ha scritto: >>>>> + visit_start_struct(opts_get_visitor(ov), &dummy, NULL, NULL, 0, &err); >>>>> + if (error_is_set(&err)) { >>>>> + goto out_clean; >>>>> + } >>>> >>>> So I have been thinking about repeated if(error_is_set(&err)) { goto >>>> foo; } and how to reduce its verbosity in situations like this. Can it >>>> be solved with a simple semantic: >>>> >>>> "Error ** accepting APIs will perform no action if the Error ** >>>> argument is already set." >>> >>> I think this is a case where verbosity <<< ease of use. >>> >>> In this case, the caller code is particularly simple, but what if I >>> needed to dereference the return value of the first called function, to >>> get the argument to the second? You would still need an "if". >>> >> >> Yes thats right. This isn't going to work universally and callers will >> always have the responsibility of knowing whether they can continue or >> not. But it will help a lot for repetitive collections of similar >> independent functions calls. The ultimate example is probably the >> device tree API calls in hw/ppc/e500.c. >> >> I want to patch the device tree API to be nice and Error**ified (for >> my own future reasons) but I sure don't want to have to patch e500 to >> check every qemu_devtree_foo API call with these 3 LOC. TBH i'll >> probably just preserve current behavior using &error_abort in next rev >> of that series, but it should be possible to do less verbose >> caller-customized collective error handling in some way. > > error_set() & friends currently have a "errp doesn't contain an error > already" precondition: > > if (errp == NULL) { > return; > } > assert(*errp == NULL); > > You could change the function contracts to ignore additional errors. > Theoretical drawback: in situations where that isn't intended, > programming errors no longer get caught. If people actually care for > that enough to veto your change, you can try adding new functions for > use when it is intended. > That will work for some cases. But pre-checking in the API call ASAP guards you against the case where subsequent API calls depends upon the first. This is similar to the problem Paolo flagged. What happens if an API returns a ptr but fails, then that ptr is passes to the second API which derefs it? (before any error checks). Regards, Peter ^ permalink raw reply [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH v2 5/5] monitor: add object-del (QMP) and object_del (HMP) command 2013-12-17 11:25 [Qemu-devel] [PATCH v2 0/5] Monitor commands for object-add/del Paolo Bonzini ` (3 preceding siblings ...) 2013-12-17 11:26 ` [Qemu-devel] [PATCH v2 4/5] monitor: add object-add (QMP) and object_add (HMP) command Paolo Bonzini @ 2013-12-17 11:26 ` Paolo Bonzini 2013-12-18 13:00 ` [Qemu-devel] [PATCH v2 0/5] Monitor commands for object-add/del Igor Mammedov 2013-12-18 16:36 ` Luiz Capitulino 6 siblings, 0 replies; 13+ messages in thread From: Paolo Bonzini @ 2013-12-17 11:26 UTC (permalink / raw) To: qemu-devel; +Cc: imammedo, stefanha, lcapitulino These two commands invoke the "unparent" method of Object. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- hmp-commands.hx | 14 ++++++++++++++ hmp.c | 9 +++++++++ hmp.h | 1 + qapi-schema.json | 14 ++++++++++++++ qmp-commands.hx | 24 ++++++++++++++++++++++++ qmp.c | 12 ++++++++++++ 6 files changed, 74 insertions(+) diff --git a/hmp-commands.hx b/hmp-commands.hx index 0563b33..cb5aa87 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1257,6 +1257,20 @@ STEXI Create QOM object. ETEXI + { + .name = "object_del", + .args_type = "id:s", + .params = "id", + .help = "destroy QOM object", + .mhandler.cmd = hmp_object_del, + }, + +STEXI +@item object_del +@findex object_del +Destroy QOM object. +ETEXI + #ifdef CONFIG_SLIRP { .name = "hostfwd_add", diff --git a/hmp.c b/hmp.c index a1669ab..9f4c9b3 100644 --- a/hmp.c +++ b/hmp.c @@ -1622,3 +1622,12 @@ void hmp_qemu_io(Monitor *mon, const QDict *qdict) hmp_handle_error(mon, &err); } + +void hmp_object_del(Monitor *mon, const QDict *qdict) +{ + const char *id = qdict_get_str(qdict, "id"); + Error *err = NULL; + + qmp_object_del(id, &err); + hmp_handle_error(mon, &err); +} diff --git a/hmp.h b/hmp.h index 521449b..94264d6 100644 --- a/hmp.h +++ b/hmp.h @@ -90,5 +90,6 @@ void hmp_chardev_add(Monitor *mon, const QDict *qdict); void hmp_chardev_remove(Monitor *mon, const QDict *qdict); void hmp_qemu_io(Monitor *mon, const QDict *qdict); void hmp_object_add(Monitor *mon, const QDict *qdict); +void hmp_object_del(Monitor *mon, const QDict *qdict); #endif diff --git a/qapi-schema.json b/qapi-schema.json index 111463b..8ca4d0c 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -2779,6 +2779,20 @@ 'gen': 'no' } ## +# @object-del: +# +# Remove a QOM object. +# +# @id: the name of the QOM object to remove +# +# Returns: Nothing on success +# Error if @id is not a valid id for a QOM object +# +# Since: 2.0 +## +{ 'command': 'object-del', 'data': {'id': 'str'} } + +## # @NetdevNoneOptions # # Use it alone to have zero network devices. diff --git a/qmp-commands.hx b/qmp-commands.hx index d09ea53..02cc815 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -904,6 +904,30 @@ Example: EQMP + { + .name = "object-del", + .args_type = "id:s", + .mhandler.cmd_new = qmp_marshal_input_object_del, + }, + +SQMP +object-del +---------- + +Remove QOM object. + +Arguments: + +- "id": the object's ID (json-string) + +Example: + +-> { "execute": "object-del", "arguments": { "id": "rng1" } } +<- { "return": {} } + + +EQMP + { .name = "block_resize", diff --git a/qmp.c b/qmp.c index 255c55f..0d51e44 100644 --- a/qmp.c +++ b/qmp.c @@ -591,3 +591,16 @@ out: return 0; } + +void qmp_object_del(const char *id, Error **errp) +{ + Object *obj; + + obj = object_resolve_path_component(container_get(object_get_root(), "/objects"), + id); + if (!obj) { + error_setg(errp, "object id not found"); + return; + } + object_unparent(obj); +} -- 1.8.4.2 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v2 0/5] Monitor commands for object-add/del 2013-12-17 11:25 [Qemu-devel] [PATCH v2 0/5] Monitor commands for object-add/del Paolo Bonzini ` (4 preceding siblings ...) 2013-12-17 11:26 ` [Qemu-devel] [PATCH v2 5/5] monitor: add object-del (QMP) and object_del " Paolo Bonzini @ 2013-12-18 13:00 ` Igor Mammedov 2013-12-18 16:36 ` Luiz Capitulino 6 siblings, 0 replies; 13+ messages in thread From: Igor Mammedov @ 2013-12-18 13:00 UTC (permalink / raw) To: Paolo Bonzini; +Cc: qemu-devel, stefanha, lcapitulino On Tue, 17 Dec 2013 12:25:59 +0100 Paolo Bonzini <pbonzini@redhat.com> wrote: > These allow hotplugging (and hot-unplugging without leaking an object) > virtio-rng devices. They can also be used for memory hotplug. > > v1->v2: fix mistyped underscores in qapi-schema.json > > Paolo Bonzini (5): > rng: initialize file descriptor to -1 > qom: fix leak for objects created with -object > qom: catch errors in object_property_add_child > monitor: add object-add (QMP) and object_add (HMP) command > monitor: add object-del (QMP) and object_del (HMP) command > > backends/rng-random.c | 4 +-- > hmp-commands.hx | 28 ++++++++++++++++++ > hmp.c | 67 ++++++++++++++++++++++++++++++++++++++++++ > hmp.h | 2 ++ > include/monitor/monitor.h | 3 ++ > include/qapi/visitor.h | 3 +- > include/qemu/typedefs.h | 2 ++ > qapi-schema.json | 34 ++++++++++++++++++++++ > qmp-commands.hx | 51 ++++++++++++++++++++++++++++++++ > qmp.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++ > qom/object.c | 9 ++++-- > vl.c | 3 +- > 12 files changed, 273 insertions(+), 7 deletions(-) > Reviewed-By: Igor Mammedov <imammedo@redhat.com> ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [Qemu-devel] [PATCH v2 0/5] Monitor commands for object-add/del 2013-12-17 11:25 [Qemu-devel] [PATCH v2 0/5] Monitor commands for object-add/del Paolo Bonzini ` (5 preceding siblings ...) 2013-12-18 13:00 ` [Qemu-devel] [PATCH v2 0/5] Monitor commands for object-add/del Igor Mammedov @ 2013-12-18 16:36 ` Luiz Capitulino 6 siblings, 0 replies; 13+ messages in thread From: Luiz Capitulino @ 2013-12-18 16:36 UTC (permalink / raw) To: Paolo Bonzini; +Cc: imammedo, qemu-devel, stefanha On Tue, 17 Dec 2013 12:25:59 +0100 Paolo Bonzini <pbonzini@redhat.com> wrote: > These allow hotplugging (and hot-unplugging without leaking an object) > virtio-rng devices. They can also be used for memory hotplug. > > v1->v2: fix mistyped underscores in qapi-schema.json Applied to the qmp branch, thanks. > > Paolo Bonzini (5): > rng: initialize file descriptor to -1 > qom: fix leak for objects created with -object > qom: catch errors in object_property_add_child > monitor: add object-add (QMP) and object_add (HMP) command > monitor: add object-del (QMP) and object_del (HMP) command > > backends/rng-random.c | 4 +-- > hmp-commands.hx | 28 ++++++++++++++++++ > hmp.c | 67 ++++++++++++++++++++++++++++++++++++++++++ > hmp.h | 2 ++ > include/monitor/monitor.h | 3 ++ > include/qapi/visitor.h | 3 +- > include/qemu/typedefs.h | 2 ++ > qapi-schema.json | 34 ++++++++++++++++++++++ > qmp-commands.hx | 51 ++++++++++++++++++++++++++++++++ > qmp.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++ > qom/object.c | 9 ++++-- > vl.c | 3 +- > 12 files changed, 273 insertions(+), 7 deletions(-) > ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2013-12-18 16:55 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2013-12-17 11:25 [Qemu-devel] [PATCH v2 0/5] Monitor commands for object-add/del Paolo Bonzini 2013-12-17 11:26 ` [Qemu-devel] [PATCH v2 1/5] rng: initialize file descriptor to -1 Paolo Bonzini 2013-12-17 11:26 ` [Qemu-devel] [PATCH v2 2/5] qom: fix leak for objects created with -object Paolo Bonzini 2013-12-17 11:26 ` [Qemu-devel] [PATCH v2 3/5] qom: catch errors in object_property_add_child Paolo Bonzini 2013-12-17 11:26 ` [Qemu-devel] [PATCH v2 4/5] monitor: add object-add (QMP) and object_add (HMP) command Paolo Bonzini 2013-12-17 11:54 ` Peter Crosthwaite 2013-12-17 12:24 ` Paolo Bonzini 2013-12-17 12:38 ` Peter Crosthwaite 2013-12-17 13:07 ` Markus Armbruster 2013-12-17 21:56 ` Peter Crosthwaite 2013-12-17 11:26 ` [Qemu-devel] [PATCH v2 5/5] monitor: add object-del (QMP) and object_del " Paolo Bonzini 2013-12-18 13:00 ` [Qemu-devel] [PATCH v2 0/5] Monitor commands for object-add/del Igor Mammedov 2013-12-18 16:36 ` Luiz Capitulino
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).