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>
This commit is contained in:
Igor Mammedov 2014-01-16 17:34:38 +01:00 committed by Luiz Capitulino
parent 90e9cf28e5
commit 269e09f3fc
6 changed files with 125 additions and 0 deletions

View file

@ -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)

View file

@ -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

12
qmp.c
View file

@ -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:

View file

@ -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

32
qom/object_interfaces.c Normal file
View file

@ -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)

13
vl.c
View file

@ -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);