diff options
author | Igor Mammedov <imammedo@redhat.com> | 2014-01-16 17:34:38 +0100 |
---|---|---|
committer | Luiz Capitulino <lcapitulino@redhat.com> | 2014-01-28 12:47:02 -0500 |
commit | 269e09f3fc922b800d118d9c8a721be46b5462a3 (patch) | |
tree | 45a18489d3fa4c2bb54e96f7f26ca9f7f6a0af81 | |
parent | 90e9cf28e57a3e1d6caa0a28b0a332ff982ccb0b (diff) |
add optional 2nd stage initialization to -object/object-add commands
Introduces USER_CREATABLE interface that must be implemented by
objects which are designed to created with -object CLI option or
object-add QMP command.
Interface provides an ability to do an optional second stage
initialization of the object created with -object/object-add
commands. By providing complete() callback, which is called
after the object properties were set.
It allows to:
* prevents misusing of -object/object-add by filtering out
objects that are not designed for it.
* generalize second stage backend initialization instead of
adding custom APIs to perform it
* early error detection of backend initialization at -object/
object-add time rather than through a proxy DEVICE object
that tries to use backend.
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
-rw-r--r-- | backends/rng.c | 5 | ||||
-rw-r--r-- | include/qom/object_interfaces.h | 62 | ||||
-rw-r--r-- | qmp.c | 12 | ||||
-rw-r--r-- | qom/Makefile.objs | 1 | ||||
-rw-r--r-- | qom/object_interfaces.c | 32 | ||||
-rw-r--r-- | vl.c | 13 |
6 files changed, 125 insertions, 0 deletions
diff --git a/backends/rng.c b/backends/rng.c index 85cb83f5e1..7bab806ee1 100644 --- a/backends/rng.c +++ b/backends/rng.c @@ -12,6 +12,7 @@ #include "sysemu/rng.h" #include "qapi/qmp/qerror.h" +#include "qom/object_interfaces.h" void rng_backend_request_entropy(RngBackend *s, size_t size, EntropyReceiveFunc *receive_entropy, @@ -83,6 +84,10 @@ static const TypeInfo rng_backend_info = { .instance_init = rng_backend_init, .class_size = sizeof(RngBackendClass), .abstract = true, + .interfaces = (InterfaceInfo[]) { + { TYPE_USER_CREATABLE }, + { } + } }; static void register_types(void) diff --git a/include/qom/object_interfaces.h b/include/qom/object_interfaces.h new file mode 100644 index 0000000000..b7922833e1 --- /dev/null +++ b/include/qom/object_interfaces.h @@ -0,0 +1,62 @@ +#ifndef OBJECT_INTERFACES_H +#define OBJECT_INTERFACES_H + +#include "qom/object.h" + +#define TYPE_USER_CREATABLE "user-creatable" + +#define USER_CREATABLE_CLASS(klass) \ + OBJECT_CLASS_CHECK(UserCreatableClass, (klass), \ + TYPE_USER_CREATABLE) +#define USER_CREATABLE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(UserCreatableClass, (obj), \ + TYPE_USER_CREATABLE) +#define USER_CREATABLE(obj) \ + INTERFACE_CHECK(UserCreatable, (obj), \ + TYPE_USER_CREATABLE) + + +typedef struct UserCreatable { + /* <private> */ + Object Parent; +} UserCreatable; + +/** + * UserCreatableClass: + * @parent_class: the base class + * @complete: callback to be called after @obj's properties are set. + * + * Interface is designed to work with -object/object-add/object_add + * commands. + * Interface is mandatory for objects that are designed to be user + * creatable (i.e. -object/object-add/object_add, will accept only + * objects that inherit this interface). + * + * Interface also provides an optional ability to do the second + * stage * initialization of the object after its properties were + * set. + * + * For objects created without using -object/object-add/object_add, + * @user_creatable_complete() wrapper should be called manually if + * object's type implements USER_CREATABLE interface and needs + * complete() callback to be called. + */ +typedef struct UserCreatableClass { + /* <private> */ + InterfaceClass parent_class; + + /* <public> */ + void (*complete)(UserCreatable *uc, Error **errp); +} UserCreatableClass; + +/** + * user_creatable_complete: + * @obj: the object whose complete() method is called if defined + * @errp: if an error occurs, a pointer to an area to store the error + * + * Wrapper to call complete() method if one of types it's inherited + * from implements USER_CREATABLE interface, otherwise the call does + * nothing. + */ +void user_creatable_complete(Object *obj, Error **errp); +#endif @@ -27,6 +27,7 @@ #include "qapi/qmp/qobject.h" #include "qapi/qmp-input-visitor.h" #include "hw/boards.h" +#include "qom/object_interfaces.h" NameInfo *qmp_query_name(Error **errp) { @@ -554,6 +555,17 @@ void object_add(const char *type, const char *id, const QDict *qdict, } } + if (!object_dynamic_cast(obj, TYPE_USER_CREATABLE)) { + error_setg(&local_err, "object '%s' isn't supported by object-add", + id); + goto out; + } + + user_creatable_complete(obj, &local_err); + if (local_err) { + goto out; + } + object_property_add_child(container_get(object_get_root(), "/objects"), id, obj, &local_err); out: diff --git a/qom/Makefile.objs b/qom/Makefile.objs index 6a93ac7398..985003bd03 100644 --- a/qom/Makefile.objs +++ b/qom/Makefile.objs @@ -1,2 +1,3 @@ common-obj-y = object.o container.o qom-qobject.o common-obj-y += cpu.o +common-obj-y += object_interfaces.o diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c new file mode 100644 index 0000000000..6360818397 --- /dev/null +++ b/qom/object_interfaces.c @@ -0,0 +1,32 @@ +#include "qom/object_interfaces.h" +#include "qemu/module.h" + +void user_creatable_complete(Object *obj, Error **errp) +{ + + UserCreatableClass *ucc; + UserCreatable *uc = + (UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE); + + if (!uc) { + return; + } + + ucc = USER_CREATABLE_GET_CLASS(uc); + if (ucc->complete) { + ucc->complete(uc, errp); + } +} + +static void register_types(void) +{ + static const TypeInfo uc_interface_info = { + .name = TYPE_USER_CREATABLE, + .parent = TYPE_INTERFACE, + .class_size = sizeof(UserCreatableClass), + }; + + type_register_static(&uc_interface_info); +} + +type_init(register_types) @@ -170,6 +170,7 @@ int main(int argc, char **argv) #include "ui/qemu-spice.h" #include "qapi/string-input-visitor.h" +#include "qom/object_interfaces.h" //#define DEBUG_NET //#define DEBUG_SLIRP @@ -2816,9 +2817,21 @@ static int object_create(QemuOpts *opts, void *opaque) return -1; } + if (!object_dynamic_cast(obj, TYPE_USER_CREATABLE)) { + error_setg(&local_err, "object '%s' isn't supported by -object", + id); + goto out; + } + + user_creatable_complete(obj, &local_err); + if (local_err) { + goto out; + } + object_property_add_child(container_get(object_get_root(), "/objects"), id, obj, &local_err); +out: object_unref(obj); if (local_err) { qerror_report_err(local_err); |