Commit 2f61120c authored by Peter Maydell's avatar Peter Maydell

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: default avatarPeter Maydell <peter.maydell@linaro.org>
parents b4a8c9ae 056f49ff
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "sysemu/rng.h" #include "sysemu/rng.h"
#include "qapi/qmp/qerror.h" #include "qapi/qmp/qerror.h"
#include "qom/object_interfaces.h"
void rng_backend_request_entropy(RngBackend *s, size_t size, void rng_backend_request_entropy(RngBackend *s, size_t size,
EntropyReceiveFunc *receive_entropy, EntropyReceiveFunc *receive_entropy,
...@@ -40,9 +41,9 @@ static bool rng_backend_prop_get_opened(Object *obj, Error **errp) ...@@ -40,9 +41,9 @@ static bool rng_backend_prop_get_opened(Object *obj, Error **errp)
return s->opened; 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) static void rng_backend_prop_set_opened(Object *obj, bool value, Error **errp)
...@@ -76,13 +77,25 @@ static void rng_backend_init(Object *obj) ...@@ -76,13 +77,25 @@ static void rng_backend_init(Object *obj)
NULL); 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 = { static const TypeInfo rng_backend_info = {
.name = TYPE_RNG_BACKEND, .name = TYPE_RNG_BACKEND,
.parent = TYPE_OBJECT, .parent = TYPE_OBJECT,
.instance_size = sizeof(RngBackend), .instance_size = sizeof(RngBackend),
.instance_init = rng_backend_init, .instance_init = rng_backend_init,
.class_size = sizeof(RngBackendClass), .class_size = sizeof(RngBackendClass),
.class_init = rng_backend_class_init,
.abstract = true, .abstract = true,
.interfaces = (InterfaceInfo[]) {
{ TYPE_USER_CREATABLE },
{ }
}
}; };
static void register_types(void) static void register_types(void)
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "hw/virtio/virtio.h" #include "hw/virtio/virtio.h"
#include "hw/virtio/virtio-rng.h" #include "hw/virtio/virtio-rng.h"
#include "sysemu/rng.h" #include "sysemu/rng.h"
#include "qom/object_interfaces.h"
static bool is_guest_ready(VirtIORNG *vrng) static bool is_guest_ready(VirtIORNG *vrng)
{ {
...@@ -148,6 +149,14 @@ static void virtio_rng_device_realize(DeviceState *dev, Error **errp) ...@@ -148,6 +149,14 @@ static void virtio_rng_device_realize(DeviceState *dev, Error **errp)
if (vrng->conf.rng == NULL) { if (vrng->conf.rng == NULL) {
vrng->conf.default_backend = RNG_RANDOM(object_new(TYPE_RNG_RANDOM)); 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), object_property_add_child(OBJECT(dev),
"default-backend", "default-backend",
OBJECT(vrng->conf.default_backend), OBJECT(vrng->conf.default_backend),
...@@ -166,12 +175,6 @@ static void virtio_rng_device_realize(DeviceState *dev, Error **errp) ...@@ -166,12 +175,6 @@ static void virtio_rng_device_realize(DeviceState *dev, Error **errp)
return; 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); vrng->vq = virtio_add_queue(vdev, 8, handle_input);
assert(vrng->conf.max_bytes <= INT64_MAX); assert(vrng->conf.max_bytes <= INT64_MAX);
......
#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
...@@ -79,15 +79,4 @@ void rng_backend_request_entropy(RngBackend *s, size_t size, ...@@ -79,15 +79,4 @@ void rng_backend_request_entropy(RngBackend *s, size_t size,
* to stop tracking any request. * to stop tracking any request.
*/ */
void rng_backend_cancel_requests(RngBackend *s); 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 #endif
...@@ -288,8 +288,8 @@ void monitor_flush(Monitor *mon) ...@@ -288,8 +288,8 @@ void monitor_flush(Monitor *mon)
if (len && !mon->mux_out) { if (len && !mon->mux_out) {
rc = qemu_chr_fe_write(mon->chr, (const uint8_t *) buf, len); rc = qemu_chr_fe_write(mon->chr, (const uint8_t *) buf, len);
if (rc == len) { if ((rc < 0 && errno != EAGAIN) || (rc == len)) {
/* all flushed */ /* all flushed or error */
QDECREF(mon->outbuf); QDECREF(mon->outbuf);
mon->outbuf = qstring_new(); mon->outbuf = qstring_new();
return; return;
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "qapi/qmp/qobject.h" #include "qapi/qmp/qobject.h"
#include "qapi/qmp-input-visitor.h" #include "qapi/qmp-input-visitor.h"
#include "hw/boards.h" #include "hw/boards.h"
#include "qom/object_interfaces.h"
NameInfo *qmp_query_name(Error **errp) NameInfo *qmp_query_name(Error **errp)
{ {
...@@ -549,15 +550,28 @@ void object_add(const char *type, const char *id, const QDict *qdict, ...@@ -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)) { for (e = qdict_first(qdict); e; e = qdict_next(qdict, e)) {
object_property_set(obj, v, e->key, &local_err); object_property_set(obj, v, e->key, &local_err);
if (local_err) { if (local_err) {
error_propagate(errp, local_err); goto out;
object_unref(obj);
return;
} }
} }
} }
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"), 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); object_unref(obj);
} }
......
common-obj-y = object.o container.o qom-qobject.o common-obj-y = object.o container.o qom-qobject.o
common-obj-y += cpu.o common-obj-y += cpu.o
common-obj-y += object_interfaces.o
#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) ...@@ -170,6 +170,7 @@ int main(int argc, char **argv)
#include "ui/qemu-spice.h" #include "ui/qemu-spice.h"
#include "qapi/string-input-visitor.h" #include "qapi/string-input-visitor.h"
#include "qom/object_interfaces.h"
//#define DEBUG_NET //#define DEBUG_NET
//#define DEBUG_SLIRP //#define DEBUG_SLIRP
...@@ -2800,6 +2801,7 @@ static int object_create(QemuOpts *opts, void *opaque) ...@@ -2800,6 +2801,7 @@ static int object_create(QemuOpts *opts, void *opaque)
{ {
const char *type = qemu_opt_get(opts, "qom-type"); const char *type = qemu_opt_get(opts, "qom-type");
const char *id = qemu_opts_id(opts); const char *id = qemu_opts_id(opts);
Error *local_err = NULL;
Object *obj; Object *obj;
g_assert(type != NULL); g_assert(type != NULL);
...@@ -2815,9 +2817,27 @@ static int object_create(QemuOpts *opts, void *opaque) ...@@ -2815,9 +2817,27 @@ static int object_create(QemuOpts *opts, void *opaque)
return -1; 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"), object_property_add_child(container_get(object_get_root(), "/objects"),
id, obj, NULL); id, obj, &local_err);
out:
object_unref(obj); object_unref(obj);
if (local_err) {
qerror_report_err(local_err);
error_free(local_err);
return -1;
}
return 0; return 0;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment