Add a optional OBJECT_PATH_INTERFACE, that will allow to set custom container path if object's type implements this interface.
Signed-off-by: Igor Mammedov <imamm...@redhat.com> --- it will be used for memdev backend to so that -object membackendX,id=memdevY could create object with path /backends/memdev/memdevY, grouping similar objects in one place and not clattering "/objects" container. it also could be used for iothread backend, which could use -object instead of custom -iothread option. --- include/qom/object_interfaces.h | 43 +++++++++++++++++++++++++++++++++++++++ qmp.c | 14 ++++++++++-- qom/object_interfaces.c | 24 +++++++++++++++++++++ vl.c | 5 +++- 4 files changed, 82 insertions(+), 4 deletions(-) diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h index 8a42d46..9c4b4b3 100644 --- a/include/qom/object_interfaces.h +++ b/include/qom/object_interfaces.h @@ -50,4 +50,47 @@ typedef struct ObjectRealizeInterfaceClass { * implements OBJECT_REALIZE_INTERFACE, otherwise the call does nothing. */ void call_object_realize_interface(Object *obj, Error **errp); + + +#define TYPE_OBJECT_PATH_INTERFACE "object-path-interface" + +#define OBJECT_PATH_INTERFACE_CLASS(klass) \ + OBJECT_CLASS_CHECK(ObjectPathInterfaceClass, (klass), \ + TYPE_OBJECT_PATH_INTERFACE) +#define OBJECT_PATH_INTERFACE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(ObjectPathInterfaceClass, (obj), \ + TYPE_OBJECT_PATH_INTERFACE) +#define OBJECT_PATH_INTERFACE(obj) \ + INTERFACE_CHECK(ObjectPathInterface, (obj), \ + TYPE_OBJECT_PATH_INTERFACE) + +typedef struct ObjectPathInterface { + /* <private> */ + Object Parent; +} ObjectPathInterface; + +/** + * ObjectPathInterfaceClass: + * @parent_class: the base class + * @default_parent: returns default parent path + * + * Interface is designed to work with -object/object-add/object_add + * commands and provides an optional ability for object to + * provide its default location in QOM tree. + */ +typedef struct ObjectPathInterfaceClass { + /* <private> */ + InterfaceClass parent_class; + + const char *(*default_parent)(ObjectPathInterface *obj); +} ObjectPathInterfaceClass; + +/** + * object_default_parent_path: + * @obj: the object default_parent() method is called + * + * Wrapper to call default_parent() method if type implements + * OBJECT_PATH_INTERFACE, returns default parent path. + */ +const char *object_default_parent_path(Object *obj); #endif diff --git a/qmp.c b/qmp.c index 3ed78cd..53ee026 100644 --- a/qmp.c +++ b/qmp.c @@ -539,6 +539,7 @@ void object_add(const char *type, const char *id, const QDict *qdict, Object *obj; const QDictEntry *e; Error *local_err = NULL; + const char *default_path; if (!object_class_by_name(type)) { error_setg(errp, "invalid class name"); @@ -560,7 +561,9 @@ void object_add(const char *type, const char *id, const QDict *qdict, goto out; } - object_property_add_child(container_get(object_get_root(), "/objects"), + default_path = object_default_parent_path(obj); + default_path = default_path ? default_path : "/objects"; + object_property_add_child(container_get(object_get_root(), default_path), id, obj, &local_err); out: if (local_err) { @@ -603,13 +606,18 @@ out: void qmp_object_del(const char *id, Error **errp) { Object *container; + bool ambiguous; Object *obj; - container = container_get(object_get_root(), "/objects"); - obj = object_resolve_path_component(container, id); + obj = object_resolve_path(id, &ambiguous); if (!obj) { error_setg(errp, "object id not found"); return; } + if (ambiguous) { + error_setg(errp, "object id is ambiguous, use absolute" + " QOM path to specify the object"); + return; + } object_unparent(obj); } diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c index d2aa722..66eb052 100644 --- a/qom/object_interfaces.c +++ b/qom/object_interfaces.c @@ -18,6 +18,23 @@ void call_object_realize_interface(Object *obj, Error **errp) } } +const char *object_default_parent_path(Object *obj) +{ + ObjectPathInterface *opi; + ObjectPathInterfaceClass *opic; + + opi = (ObjectPathInterface *) + object_dynamic_cast(obj, TYPE_OBJECT_PATH_INTERFACE); + if (!opi) { + return NULL; + } + + opic = OBJECT_PATH_INTERFACE_GET_CLASS(opi); + if (opic->default_parent) { + return opic->default_parent(opi); + } + return NULL; +} static void register_types(void) { @@ -27,7 +44,14 @@ static void register_types(void) .class_size = sizeof(ObjectRealizeInterfaceClass), }; + static const TypeInfo path_interface_info = { + .name = TYPE_OBJECT_PATH_INTERFACE, + .parent = TYPE_INTERFACE, + .class_size = sizeof(ObjectPathInterfaceClass), + }; + type_register_static(&realize_interface_info); + type_register_static(&path_interface_info); } type_init(register_types) diff --git a/vl.c b/vl.c index 84cb7a8..fc2a2ca 100644 --- a/vl.c +++ b/vl.c @@ -2799,6 +2799,7 @@ static int object_create(QemuOpts *opts, void *opaque) { const char *type = qemu_opt_get(opts, "qom-type"); const char *id = qemu_opts_id(opts); + const char *default_path; Error *local_err = NULL; Object *obj; @@ -2820,7 +2821,9 @@ static int object_create(QemuOpts *opts, void *opaque) goto out; } - object_property_add_child(container_get(object_get_root(), "/objects"), + default_path = object_default_parent_path(obj); + default_path = default_path ? default_path : "/objects"; + object_property_add_child(container_get(object_get_root(), default_path), id, obj, &local_err); out: -- 1.7.1