Merge remote-tracking branch 'qmp-unstable/queue/qmp' into staging

* qmp-unstable/queue/qmp:
  monitor: Cleanup mon->outbuf on write error
  virtio_rng: replace custom backend API with UserCreatable.complete() callback
  add optional 2nd stage initialization to -object/object-add commands
  vl.c: -object: don't ignore duplicate 'id'
  object_add: consolidate error handling

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2014-02-01 23:32:23 +00:00
commit 2f61120c10
9 changed files with 160 additions and 26 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,
@ -40,9 +41,9 @@ static bool rng_backend_prop_get_opened(Object *obj, Error **errp)
return s->opened;
}
void rng_backend_open(RngBackend *s, Error **errp)
static void rng_backend_complete(UserCreatable *uc, Error **errp)
{
object_property_set_bool(OBJECT(s), true, "opened", errp);
object_property_set_bool(OBJECT(uc), true, "opened", errp);
}
static void rng_backend_prop_set_opened(Object *obj, bool value, Error **errp)
@ -76,13 +77,25 @@ static void rng_backend_init(Object *obj)
NULL);
}
static void rng_backend_class_init(ObjectClass *oc, void *data)
{
UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
ucc->complete = rng_backend_complete;
}
static const TypeInfo rng_backend_info = {
.name = TYPE_RNG_BACKEND,
.parent = TYPE_OBJECT,
.instance_size = sizeof(RngBackend),
.instance_init = rng_backend_init,
.class_size = sizeof(RngBackendClass),
.class_init = rng_backend_class_init,
.abstract = true,
.interfaces = (InterfaceInfo[]) {
{ TYPE_USER_CREATABLE },
{ }
}
};
static void register_types(void)

View File

@ -15,6 +15,7 @@
#include "hw/virtio/virtio.h"
#include "hw/virtio/virtio-rng.h"
#include "sysemu/rng.h"
#include "qom/object_interfaces.h"
static bool is_guest_ready(VirtIORNG *vrng)
{
@ -148,6 +149,14 @@ static void virtio_rng_device_realize(DeviceState *dev, Error **errp)
if (vrng->conf.rng == NULL) {
vrng->conf.default_backend = RNG_RANDOM(object_new(TYPE_RNG_RANDOM));
user_creatable_complete(OBJECT(vrng->conf.default_backend),
&local_err);
if (local_err) {
error_propagate(errp, local_err);
object_unref(OBJECT(vrng->conf.default_backend));
return;
}
object_property_add_child(OBJECT(dev),
"default-backend",
OBJECT(vrng->conf.default_backend),
@ -166,12 +175,6 @@ static void virtio_rng_device_realize(DeviceState *dev, Error **errp)
return;
}
rng_backend_open(vrng->rng, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
vrng->vq = virtio_add_queue(vdev, 8, handle_input);
assert(vrng->conf.max_bytes <= INT64_MAX);

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

View File

@ -79,15 +79,4 @@ void rng_backend_request_entropy(RngBackend *s, size_t size,
* to stop tracking any request.
*/
void rng_backend_cancel_requests(RngBackend *s);
/**
* rng_backend_open:
* @s: the backend to open
* @errp: a pointer to return the #Error object if an error occurs.
*
* This function will open the backend if it is not already open. Calling this
* function on an already opened backend will not result in an error.
*/
void rng_backend_open(RngBackend *s, Error **errp);
#endif

View File

@ -288,8 +288,8 @@ void monitor_flush(Monitor *mon)
if (len && !mon->mux_out) {
rc = qemu_chr_fe_write(mon->chr, (const uint8_t *) buf, len);
if (rc == len) {
/* all flushed */
if ((rc < 0 && errno != EAGAIN) || (rc == len)) {
/* all flushed or error */
QDECREF(mon->outbuf);
mon->outbuf = qstring_new();
return;

22
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)
{
@ -549,15 +550,28 @@ void object_add(const char *type, const char *id, const QDict *qdict,
for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) {
object_property_set(obj, v, e->key, &local_err);
if (local_err) {
error_propagate(errp, local_err);
object_unref(obj);
return;
goto out;
}
}
}
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, errp);
id, obj, &local_err);
out:
if (local_err) {
error_propagate(errp, local_err);
}
object_unref(obj);
}

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)

22
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
@ -2800,6 +2801,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);
Error *local_err = NULL;
Object *obj;
g_assert(type != NULL);
@ -2815,9 +2817,27 @@ 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, NULL);
id, obj, &local_err);
out:
object_unref(obj);
if (local_err) {
qerror_report_err(local_err);
error_free(local_err);
return -1;
}
return 0;
}