The QMP monitor code has two helper methods object_add and qmp_object_del that are called from several places in the code (QMP, HMP and main emulator startup).
We soon need to use this code from qemu-img, qemu-io and qemu-nbd too, but don't want those to depend on the monitor. To avoid this, move object_add to user_creatable_add an qmp_object_del to user_creatable_del, to the object_interfaces.c file where they can be easily shared with all users of QOM Signed-off-by: Daniel P. Berrange <berra...@redhat.com> --- hmp.c | 11 ++++-- include/monitor/monitor.h | 3 -- include/qom/object_interfaces.h | 31 +++++++++++++++++ qmp.c | 75 ++++------------------------------------ qom/object_interfaces.c | 76 +++++++++++++++++++++++++++++++++++++++++ vl.c | 8 +++-- 6 files changed, 127 insertions(+), 77 deletions(-) diff --git a/hmp.c b/hmp.c index c2b2c16..57fa3f5 100644 --- a/hmp.c +++ b/hmp.c @@ -29,6 +29,7 @@ #include "qapi/string-output-visitor.h" #include "qapi/util.h" #include "qapi-visit.h" +#include "qom/object_interfaces.h" #include "ui/console.h" #include "block/qapi.h" #include "qemu-io.h" @@ -1670,6 +1671,7 @@ void hmp_object_add(Monitor *mon, const QDict *qdict) void *dummy = NULL; OptsVisitor *ov; QDict *pdict; + Object *obj = NULL; opts = qemu_opts_from_qdict(qemu_find_opts("object"), qdict, &err); if (err) { @@ -1696,12 +1698,12 @@ void hmp_object_add(Monitor *mon, const QDict *qdict) goto out_end; } - object_add(type, id, pdict, opts_get_visitor(ov), &err); + obj = user_creatable_add(type, id, pdict, opts_get_visitor(ov), &err); out_end: visit_end_struct(opts_get_visitor(ov), &err_end); if (!err && err_end) { - qmp_object_del(id, NULL); + user_creatable_del(id, NULL); } error_propagate(&err, err_end); out_clean: @@ -1712,6 +1714,9 @@ out_clean: g_free(id); g_free(type); g_free(dummy); + if (obj) { + object_unref(obj); + } out: hmp_handle_error(mon, &err); @@ -1944,7 +1949,7 @@ 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); + user_creatable_del(id, &err); hmp_handle_error(mon, &err); } diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h index 91b95ae..aa0f373 100644 --- a/include/monitor/monitor.h +++ b/include/monitor/monitor.h @@ -43,9 +43,6 @@ void monitor_read_command(Monitor *mon, int show_prompt); int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func, void *opaque); -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, Error **errp); diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h index 283ae0d..3e2afeb 100644 --- a/include/qom/object_interfaces.h +++ b/include/qom/object_interfaces.h @@ -2,6 +2,8 @@ #define OBJECT_INTERFACES_H #include "qom/object.h" +#include "qapi/qmp/qdict.h" +#include "qapi/visitor.h" #define TYPE_USER_CREATABLE "user-creatable" @@ -72,4 +74,33 @@ void user_creatable_complete(Object *obj, Error **errp); * from implements USER_CREATABLE interface. */ bool user_creatable_can_be_deleted(UserCreatable *uc, Error **errp); + +/** + * user_creatable_add: + * @type: the object type name + * @id: the unique ID for the object + * @qdict: the object parameters + * @v: the visitor + * @errp: if an error occurs, a pointer to an area to store the error + * + * Create an instance of the user creatable object @type, placing + * it in the object composition tree with name @id, initializing + * it with properties from @qdict + * + * Returns: the newly created object or NULL on error + */ +Object *user_creatable_add(const char *type, const char *id, + const QDict *qdict, + Visitor *v, Error **errp); + +/** + * user_creatable_del: + * @id: the unique ID for the object + * @errp: if an error occurs, a pointer to an area to store the error + * + * Delete an instance of the user creatable object identified + * by @id. + */ +void user_creatable_del(const char *id, Error **errp); + #endif diff --git a/qmp.c b/qmp.c index 0a1fa19..70fdecd 100644 --- a/qmp.c +++ b/qmp.c @@ -622,65 +622,13 @@ void qmp_add_client(const char *protocol, const char *fdname, close(fd); } -void object_add(const char *type, const char *id, const QDict *qdict, - Visitor *v, Error **errp) -{ - Object *obj; - ObjectClass *klass; - const QDictEntry *e; - Error *local_err = NULL; - - klass = object_class_by_name(type); - if (!klass) { - error_setg(errp, "invalid object type: %s", type); - return; - } - - if (!object_class_dynamic_cast(klass, TYPE_USER_CREATABLE)) { - error_setg(errp, "object type '%s' isn't supported by object-add", - type); - return; - } - - if (object_class_is_abstract(klass)) { - error_setg(errp, "object type '%s' is abstract", type); - 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 (local_err) { - goto out; - } - } - } - - object_property_add_child(object_get_objects_root(), - id, obj, &local_err); - if (local_err) { - goto out; - } - - user_creatable_complete(obj, &local_err); - if (local_err) { - object_property_del(object_get_objects_root(), - id, &error_abort); - goto out; - } -out: - if (local_err) { - error_propagate(errp, local_err); - } - object_unref(obj); -} void qmp_object_add(const char *type, const char *id, bool has_props, QObject *props, Error **errp) { const QDict *pdict = NULL; QmpInputVisitor *qiv; + Object *obj; if (props) { pdict = qobject_to_qdict(props); @@ -691,27 +639,16 @@ void qmp_object_add(const char *type, const char *id, } qiv = qmp_input_visitor_new(props); - object_add(type, id, pdict, qmp_input_get_visitor(qiv), errp); + obj = user_creatable_add(type, id, pdict, qmp_input_get_visitor(qiv), errp); qmp_input_visitor_cleanup(qiv); + if (obj) { + object_unref(obj); + } } void qmp_object_del(const char *id, Error **errp) { - Object *container; - Object *obj; - - container = object_get_objects_root(); - obj = object_resolve_path_component(container, id); - if (!obj) { - error_setg(errp, "object id not found"); - return; - } - - if (!user_creatable_can_be_deleted(USER_CREATABLE(obj), errp)) { - error_setg(errp, "%s is in use, can not be deleted", id); - return; - } - object_unparent(obj); + user_creatable_del(id, errp); } MemoryDeviceInfoList *qmp_query_memory_devices(Error **errp) diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c index a66cd60..d94995f 100644 --- a/qom/object_interfaces.c +++ b/qom/object_interfaces.c @@ -30,6 +30,82 @@ bool user_creatable_can_be_deleted(UserCreatable *uc, Error **errp) } } +Object *user_creatable_add(const char *type, const char *id, + const QDict *qdict, + Visitor *v, Error **errp) +{ + Object *obj; + ObjectClass *klass; + const QDictEntry *e; + Error *local_err = NULL; + + klass = object_class_by_name(type); + if (!klass) { + error_setg(errp, "invalid object type: %s", type); + return NULL; + } + + if (!object_class_dynamic_cast(klass, TYPE_USER_CREATABLE)) { + error_setg(errp, "object type '%s' isn't supported by object-add", + type); + return NULL; + } + + if (object_class_is_abstract(klass)) { + error_setg(errp, "object type '%s' is abstract", type); + return NULL; + } + + 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 (local_err) { + goto out; + } + } + } + + object_property_add_child(object_get_objects_root(), + id, obj, &local_err); + if (local_err) { + goto out; + } + + user_creatable_complete(obj, &local_err); + if (local_err) { + object_property_del(object_get_objects_root(), + id, &error_abort); + goto out; + } +out: + if (local_err) { + error_propagate(errp, local_err); + object_unref(obj); + return NULL; + } + return obj; +} + +void user_creatable_del(const char *id, Error **errp) +{ + Object *container; + Object *obj; + + container = object_get_objects_root(); + obj = object_resolve_path_component(container, id); + if (!obj) { + error_setg(errp, "object id not found"); + return; + } + + if (!user_creatable_can_be_deleted(USER_CREATABLE(obj), errp)) { + error_setg(errp, "%s is in use, can not be deleted", id); + return; + } + object_unparent(obj); +} + static void register_types(void) { static const TypeInfo uc_interface_info = { diff --git a/vl.c b/vl.c index 5aaea77..812e039 100644 --- a/vl.c +++ b/vl.c @@ -2834,6 +2834,7 @@ static int object_create(void *opaque, QemuOpts *opts, Error **errp) OptsVisitor *ov; QDict *pdict; bool (*type_predicate)(const char *) = opaque; + Object *obj = NULL; ov = opts_visitor_new(opts); pdict = qemu_opts_to_qdict(opts, NULL); @@ -2858,13 +2859,13 @@ static int object_create(void *opaque, QemuOpts *opts, Error **errp) goto out; } - object_add(type, id, pdict, opts_get_visitor(ov), &err); + obj = user_creatable_add(type, id, pdict, opts_get_visitor(ov), &err); if (err) { goto out; } visit_end_struct(opts_get_visitor(ov), &err); if (err) { - qmp_object_del(id, NULL); + user_creatable_del(id, NULL); } out: @@ -2874,6 +2875,9 @@ out: g_free(id); g_free(type); g_free(dummy); + if (obj) { + object_unref(obj); + } if (err) { error_report_err(err); return -1; -- 2.5.0