2011-12-03 23:10:08 +00:00
|
|
|
/*
|
|
|
|
* QEMU Object Model
|
|
|
|
*
|
|
|
|
* Copyright IBM, Corp. 2011
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Anthony Liguori <aliguori@us.ibm.com>
|
|
|
|
*
|
|
|
|
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
|
|
|
* See the COPYING file in the top-level directory.
|
|
|
|
*/
|
|
|
|
|
2016-01-29 17:50:02 +00:00
|
|
|
#include "qemu/osdep.h"
|
2019-08-12 05:23:37 +00:00
|
|
|
#include "hw/qdev-core.h"
|
include/qemu/osdep.h: Don't include qapi/error.h
Commit 57cb38b included qapi/error.h into qemu/osdep.h to get the
Error typedef. Since then, we've moved to include qemu/osdep.h
everywhere. Its file comment explains: "To avoid getting into
possible circular include dependencies, this file should not include
any other QEMU headers, with the exceptions of config-host.h,
compiler.h, os-posix.h and os-win32.h, all of which are doing a
similar job to this file and are under similar constraints."
qapi/error.h doesn't do a similar job, and it doesn't adhere to
similar constraints: it includes qapi-types.h. That's in excess of
100KiB of crap most .c files don't actually need.
Add the typedef to qemu/typedefs.h, and include that instead of
qapi/error.h. Include qapi/error.h in .c files that need it and don't
get it now. Include qapi-types.h in qom/object.h for uint16List.
Update scripts/clean-includes accordingly. Update it further to match
reality: replace config.h by config-target.h, add sysemu/os-posix.h,
sysemu/os-win32.h. Update the list of includes in the qemu/osdep.h
comment quoted above similarly.
This reduces the number of objects depending on qapi/error.h from "all
of them" to less than a third. Unfortunately, the number depending on
qapi-types.h shrinks only a little. More work is needed for that one.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
[Fix compilation without the spice devel packages. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2016-03-14 08:01:28 +00:00
|
|
|
#include "qapi/error.h"
|
2012-12-17 17:19:50 +00:00
|
|
|
#include "qom/object.h"
|
qom: Add object_new_with_props() / object_new_withpropv() helpers
It is reasonably common to want to create an object, set a
number of properties, register it in the hierarchy and then
mark it as complete (if a user creatable type). This requires
quite a lot of error prone, verbose, boilerplate code to achieve.
First a pair of functions object_set_props() / object_set_propv()
are added which allow for a list of objects to be set in
one single API call.
Then object_new_with_props() / object_new_with_propv() constructors
are added which simplify the sequence of calls to create an
object, populate properties, register in the object composition
tree and mark the object complete, into a single method call.
Usage would be:
Error *err = NULL;
Object *obj;
obj = object_new_with_propv(TYPE_MEMORY_BACKEND_FILE,
object_get_objects_root(),
"hostmem0",
&err,
"share", "yes",
"mem-path", "/dev/shm/somefile",
"prealloc", "yes",
"size", "1048576",
NULL);
Note all property values are passed in string form and will
be parsed into their required data types, using normal QOM
semantics for parsing from string format.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 16:14:06 +00:00
|
|
|
#include "qom/object_interfaces.h"
|
2016-03-20 17:16:19 +00:00
|
|
|
#include "qemu/cutils.h"
|
2012-12-17 17:19:43 +00:00
|
|
|
#include "qapi/visitor.h"
|
2012-02-09 08:52:59 +00:00
|
|
|
#include "qapi/string-input-visitor.h"
|
|
|
|
#include "qapi/string-output-visitor.h"
|
2020-01-10 15:30:23 +00:00
|
|
|
#include "qapi/qobject-input-visitor.h"
|
2018-02-11 09:36:05 +00:00
|
|
|
#include "qapi/qapi-builtin-visit.h"
|
2012-12-17 17:19:43 +00:00
|
|
|
#include "qapi/qmp/qerror.h"
|
2020-01-10 15:30:23 +00:00
|
|
|
#include "qapi/qmp/qjson.h"
|
2013-05-10 12:16:39 +00:00
|
|
|
#include "trace.h"
|
2011-12-03 23:10:08 +00:00
|
|
|
|
2012-02-01 16:16:22 +00:00
|
|
|
/* TODO: replace QObject with a simpler visitor to avoid a dependency
|
|
|
|
* of the QOM core on QObject? */
|
2012-12-17 17:19:50 +00:00
|
|
|
#include "qom/qom-qobject.h"
|
2012-12-17 17:19:43 +00:00
|
|
|
#include "qapi/qmp/qbool.h"
|
2018-02-01 11:18:36 +00:00
|
|
|
#include "qapi/qmp/qnum.h"
|
2012-12-17 17:19:43 +00:00
|
|
|
#include "qapi/qmp/qstring.h"
|
qom/object: Display more helpful message when an object type is missing
When writing a new board, adding device which uses other devices
(container) or simply refactoring, one can discover the hard way
his machine misses some devices. In the case of containers, the
error is not obvious:
$ qemu-system-microblaze -M xlnx-zynqmp-pmu
**
ERROR:/source/qemu/qom/object.c:454:object_initialize_with_type: assertion failed: (type != NULL)
Aborted (core dumped)
And we have to look at the coredump to figure the error:
(gdb) bt
#1 0x00007f84773cf895 in abort () at /lib64/libc.so.6
#2 0x00007f847961fb53 in () at /lib64/libglib-2.0.so.0
#3 0x00007f847967a4de in g_assertion_message_expr () at /lib64/libglib-2.0.so.0
#4 0x000055c4bcac6c11 in object_initialize_with_type (data=data@entry=0x55c4bdf239e0, size=size@entry=2464, type=<optimized out>) at /source/qemu/qom/object.c:454
#5 0x000055c4bcac6e6d in object_initialize (data=data@entry=0x55c4bdf239e0, size=size@entry=2464, typename=typename@entry=0x55c4bcc7c643 "xlnx.zynqmp_ipi") at /source/qemu/qom/object.c:474
#6 0x000055c4bc9ea474 in xlnx_zynqmp_pmu_init (machine=0x55c4bdd46000) at /source/qemu/hw/microblaze/xlnx-zynqmp-pmu.c:176
#7 0x000055c4bca3b6cb in machine_run_board_init (machine=0x55c4bdd46000) at /source/qemu/hw/core/machine.c:1030
#8 0x000055c4bc95f6d2 in main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>) at /source/qemu/vl.c:4479
Since the caller knows the type name requested, we can simply display it
to ease development.
With this patch applied we get:
$ qemu-system-microblaze -M xlnx-zynqmp-pmu
qemu-system-microblaze: missing object type 'xlnx.zynqmp_ipi'
Aborted (core dumped)
Since the assert(type) check in object_initialize_with_type() is
now impossible, remove it.
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-Id: <20190427135642.16464-1-philmd@redhat.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2019-04-27 13:56:42 +00:00
|
|
|
#include "qemu/error-report.h"
|
2012-02-01 16:16:22 +00:00
|
|
|
|
2011-12-03 23:10:08 +00:00
|
|
|
#define MAX_INTERFACES 32
|
|
|
|
|
|
|
|
typedef struct InterfaceImpl InterfaceImpl;
|
|
|
|
typedef struct TypeImpl TypeImpl;
|
|
|
|
|
|
|
|
struct InterfaceImpl
|
|
|
|
{
|
2012-08-10 03:16:10 +00:00
|
|
|
const char *typename;
|
2011-12-03 23:10:08 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct TypeImpl
|
|
|
|
{
|
|
|
|
const char *name;
|
|
|
|
|
|
|
|
size_t class_size;
|
|
|
|
|
|
|
|
size_t instance_size;
|
2020-09-16 00:46:34 +00:00
|
|
|
size_t instance_align;
|
2011-12-03 23:10:08 +00:00
|
|
|
|
|
|
|
void (*class_init)(ObjectClass *klass, void *data);
|
2012-05-02 11:30:55 +00:00
|
|
|
void (*class_base_init)(ObjectClass *klass, void *data);
|
2011-12-03 23:10:08 +00:00
|
|
|
|
|
|
|
void *class_data;
|
|
|
|
|
|
|
|
void (*instance_init)(Object *obj);
|
2013-07-10 20:08:41 +00:00
|
|
|
void (*instance_post_init)(Object *obj);
|
2011-12-03 23:10:08 +00:00
|
|
|
void (*instance_finalize)(Object *obj);
|
|
|
|
|
|
|
|
bool abstract;
|
|
|
|
|
|
|
|
const char *parent;
|
|
|
|
TypeImpl *parent_type;
|
|
|
|
|
|
|
|
ObjectClass *class;
|
|
|
|
|
|
|
|
int num_interfaces;
|
|
|
|
InterfaceImpl interfaces[MAX_INTERFACES];
|
|
|
|
};
|
|
|
|
|
2012-02-03 10:51:39 +00:00
|
|
|
static Type type_interface;
|
|
|
|
|
2011-12-03 23:10:08 +00:00
|
|
|
static GHashTable *type_table_get(void)
|
|
|
|
{
|
|
|
|
static GHashTable *type_table;
|
|
|
|
|
|
|
|
if (type_table == NULL) {
|
|
|
|
type_table = g_hash_table_new(g_str_hash, g_str_equal);
|
|
|
|
}
|
|
|
|
|
|
|
|
return type_table;
|
|
|
|
}
|
|
|
|
|
2013-12-03 15:42:00 +00:00
|
|
|
static bool enumerating_types;
|
|
|
|
|
2011-12-03 23:10:08 +00:00
|
|
|
static void type_table_add(TypeImpl *ti)
|
|
|
|
{
|
2013-12-03 15:42:00 +00:00
|
|
|
assert(!enumerating_types);
|
2011-12-03 23:10:08 +00:00
|
|
|
g_hash_table_insert(type_table_get(), (void *)ti->name, ti);
|
|
|
|
}
|
|
|
|
|
|
|
|
static TypeImpl *type_table_lookup(const char *name)
|
|
|
|
{
|
|
|
|
return g_hash_table_lookup(type_table_get(), name);
|
|
|
|
}
|
|
|
|
|
2013-12-03 15:41:59 +00:00
|
|
|
static TypeImpl *type_new(const TypeInfo *info)
|
2011-12-03 23:10:08 +00:00
|
|
|
{
|
|
|
|
TypeImpl *ti = g_malloc0(sizeof(*ti));
|
2012-08-10 03:16:10 +00:00
|
|
|
int i;
|
2011-12-03 23:10:08 +00:00
|
|
|
|
|
|
|
g_assert(info->name != NULL);
|
|
|
|
|
2012-01-25 19:37:36 +00:00
|
|
|
if (type_table_lookup(info->name) != NULL) {
|
|
|
|
fprintf(stderr, "Registering `%s' which already exists\n", info->name);
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
2011-12-03 23:10:08 +00:00
|
|
|
ti->name = g_strdup(info->name);
|
|
|
|
ti->parent = g_strdup(info->parent);
|
|
|
|
|
|
|
|
ti->class_size = info->class_size;
|
|
|
|
ti->instance_size = info->instance_size;
|
2020-09-16 00:46:34 +00:00
|
|
|
ti->instance_align = info->instance_align;
|
2011-12-03 23:10:08 +00:00
|
|
|
|
|
|
|
ti->class_init = info->class_init;
|
2012-05-02 11:30:55 +00:00
|
|
|
ti->class_base_init = info->class_base_init;
|
2011-12-03 23:10:08 +00:00
|
|
|
ti->class_data = info->class_data;
|
|
|
|
|
|
|
|
ti->instance_init = info->instance_init;
|
2013-07-10 20:08:41 +00:00
|
|
|
ti->instance_post_init = info->instance_post_init;
|
2011-12-03 23:10:08 +00:00
|
|
|
ti->instance_finalize = info->instance_finalize;
|
|
|
|
|
|
|
|
ti->abstract = info->abstract;
|
|
|
|
|
2012-08-10 03:16:10 +00:00
|
|
|
for (i = 0; info->interfaces && info->interfaces[i].type; i++) {
|
|
|
|
ti->interfaces[i].typename = g_strdup(info->interfaces[i].type);
|
2011-12-03 23:10:08 +00:00
|
|
|
}
|
2012-08-10 03:16:10 +00:00
|
|
|
ti->num_interfaces = i;
|
2011-12-03 23:10:08 +00:00
|
|
|
|
2013-12-03 15:41:59 +00:00
|
|
|
return ti;
|
|
|
|
}
|
2011-12-03 23:10:08 +00:00
|
|
|
|
2013-12-03 15:41:59 +00:00
|
|
|
static TypeImpl *type_register_internal(const TypeInfo *info)
|
|
|
|
{
|
|
|
|
TypeImpl *ti;
|
|
|
|
ti = type_new(info);
|
|
|
|
|
|
|
|
type_table_add(ti);
|
2011-12-03 23:10:08 +00:00
|
|
|
return ti;
|
|
|
|
}
|
|
|
|
|
2012-04-04 13:58:40 +00:00
|
|
|
TypeImpl *type_register(const TypeInfo *info)
|
|
|
|
{
|
|
|
|
assert(info->parent);
|
|
|
|
return type_register_internal(info);
|
|
|
|
}
|
|
|
|
|
2011-12-03 23:10:08 +00:00
|
|
|
TypeImpl *type_register_static(const TypeInfo *info)
|
|
|
|
{
|
|
|
|
return type_register(info);
|
|
|
|
}
|
|
|
|
|
2017-10-09 19:50:49 +00:00
|
|
|
void type_register_static_array(const TypeInfo *infos, int nr_infos)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < nr_infos; i++) {
|
|
|
|
type_register_static(&infos[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-03 23:10:08 +00:00
|
|
|
static TypeImpl *type_get_by_name(const char *name)
|
|
|
|
{
|
|
|
|
if (name == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return type_table_lookup(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
static TypeImpl *type_get_parent(TypeImpl *type)
|
|
|
|
{
|
|
|
|
if (!type->parent_type && type->parent) {
|
|
|
|
type->parent_type = type_get_by_name(type->parent);
|
2020-01-21 11:03:45 +00:00
|
|
|
if (!type->parent_type) {
|
|
|
|
fprintf(stderr, "Type '%s' is missing its parent '%s'\n",
|
|
|
|
type->name, type->parent);
|
|
|
|
abort();
|
|
|
|
}
|
2011-12-03 23:10:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return type->parent_type;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool type_has_parent(TypeImpl *type)
|
|
|
|
{
|
|
|
|
return (type->parent != NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static size_t type_class_get_size(TypeImpl *ti)
|
|
|
|
{
|
|
|
|
if (ti->class_size) {
|
|
|
|
return ti->class_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (type_has_parent(ti)) {
|
|
|
|
return type_class_get_size(type_get_parent(ti));
|
|
|
|
}
|
|
|
|
|
|
|
|
return sizeof(ObjectClass);
|
|
|
|
}
|
|
|
|
|
2012-02-28 11:57:10 +00:00
|
|
|
static size_t type_object_get_size(TypeImpl *ti)
|
|
|
|
{
|
|
|
|
if (ti->instance_size) {
|
|
|
|
return ti->instance_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (type_has_parent(ti)) {
|
|
|
|
return type_object_get_size(type_get_parent(ti));
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-06-10 00:59:00 +00:00
|
|
|
size_t object_type_get_instance_size(const char *typename)
|
|
|
|
{
|
|
|
|
TypeImpl *type = type_get_by_name(typename);
|
|
|
|
|
|
|
|
g_assert(type != NULL);
|
|
|
|
return type_object_get_size(type);
|
|
|
|
}
|
|
|
|
|
2012-08-10 03:16:10 +00:00
|
|
|
static bool type_is_ancestor(TypeImpl *type, TypeImpl *target_type)
|
2011-12-03 23:10:08 +00:00
|
|
|
{
|
2012-08-10 03:16:10 +00:00
|
|
|
assert(target_type);
|
|
|
|
|
2015-11-03 02:36:42 +00:00
|
|
|
/* Check if target_type is a direct ancestor of type */
|
2012-08-10 03:16:10 +00:00
|
|
|
while (type) {
|
|
|
|
if (type == target_type) {
|
|
|
|
return true;
|
|
|
|
}
|
2011-12-03 23:10:08 +00:00
|
|
|
|
2012-08-10 03:16:10 +00:00
|
|
|
type = type_get_parent(type);
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void type_initialize(TypeImpl *ti);
|
|
|
|
|
2013-12-03 15:41:59 +00:00
|
|
|
static void type_initialize_interface(TypeImpl *ti, TypeImpl *interface_type,
|
|
|
|
TypeImpl *parent_type)
|
2012-08-10 03:16:10 +00:00
|
|
|
{
|
|
|
|
InterfaceClass *new_iface;
|
|
|
|
TypeInfo info = { };
|
|
|
|
TypeImpl *iface_impl;
|
|
|
|
|
2013-12-03 15:41:59 +00:00
|
|
|
info.parent = parent_type->name;
|
|
|
|
info.name = g_strdup_printf("%s::%s", ti->name, interface_type->name);
|
2012-08-10 03:16:10 +00:00
|
|
|
info.abstract = true;
|
|
|
|
|
2013-12-03 15:41:59 +00:00
|
|
|
iface_impl = type_new(&info);
|
|
|
|
iface_impl->parent_type = parent_type;
|
2012-08-10 03:16:10 +00:00
|
|
|
type_initialize(iface_impl);
|
|
|
|
g_free((char *)info.name);
|
|
|
|
|
|
|
|
new_iface = (InterfaceClass *)iface_impl->class;
|
|
|
|
new_iface->concrete_class = ti->class;
|
2013-12-03 15:41:59 +00:00
|
|
|
new_iface->interface_type = interface_type;
|
2012-08-10 03:16:10 +00:00
|
|
|
|
2020-05-12 18:25:01 +00:00
|
|
|
ti->class->interfaces = g_slist_append(ti->class->interfaces, new_iface);
|
2011-12-03 23:10:08 +00:00
|
|
|
}
|
|
|
|
|
2015-10-13 12:37:46 +00:00
|
|
|
static void object_property_free(gpointer data)
|
|
|
|
{
|
|
|
|
ObjectProperty *prop = data;
|
|
|
|
|
2020-01-10 15:30:23 +00:00
|
|
|
if (prop->defval) {
|
|
|
|
qobject_unref(prop->defval);
|
|
|
|
prop->defval = NULL;
|
|
|
|
}
|
2015-10-13 12:37:46 +00:00
|
|
|
g_free(prop->name);
|
|
|
|
g_free(prop->type);
|
|
|
|
g_free(prop->description);
|
|
|
|
g_free(prop);
|
|
|
|
}
|
|
|
|
|
2012-02-28 11:57:11 +00:00
|
|
|
static void type_initialize(TypeImpl *ti)
|
2011-12-03 23:10:08 +00:00
|
|
|
{
|
2012-03-31 14:45:54 +00:00
|
|
|
TypeImpl *parent;
|
2011-12-03 23:10:08 +00:00
|
|
|
|
|
|
|
if (ti->class) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ti->class_size = type_class_get_size(ti);
|
2012-02-28 11:57:10 +00:00
|
|
|
ti->instance_size = type_object_get_size(ti);
|
2016-12-12 18:31:01 +00:00
|
|
|
/* Any type with zero instance_size is implicitly abstract.
|
|
|
|
* This means interface types are all abstract.
|
|
|
|
*/
|
|
|
|
if (ti->instance_size == 0) {
|
|
|
|
ti->abstract = true;
|
|
|
|
}
|
2018-09-12 12:53:03 +00:00
|
|
|
if (type_is_ancestor(ti, type_interface)) {
|
|
|
|
assert(ti->instance_size == 0);
|
|
|
|
assert(ti->abstract);
|
|
|
|
assert(!ti->instance_init);
|
|
|
|
assert(!ti->instance_post_init);
|
|
|
|
assert(!ti->instance_finalize);
|
|
|
|
assert(!ti->num_interfaces);
|
|
|
|
}
|
2011-12-03 23:10:08 +00:00
|
|
|
ti->class = g_malloc0(ti->class_size);
|
|
|
|
|
2012-03-31 14:45:54 +00:00
|
|
|
parent = type_get_parent(ti);
|
|
|
|
if (parent) {
|
2012-02-28 11:57:11 +00:00
|
|
|
type_initialize(parent);
|
2012-08-10 03:16:10 +00:00
|
|
|
GSList *e;
|
|
|
|
int i;
|
2011-12-03 23:10:08 +00:00
|
|
|
|
2018-06-08 17:02:31 +00:00
|
|
|
g_assert(parent->class_size <= ti->class_size);
|
2020-01-10 15:30:14 +00:00
|
|
|
g_assert(parent->instance_size <= ti->instance_size);
|
2012-03-31 14:45:54 +00:00
|
|
|
memcpy(ti->class, parent->class, parent->class_size);
|
2013-02-19 04:02:09 +00:00
|
|
|
ti->class->interfaces = NULL;
|
2012-08-10 03:16:10 +00:00
|
|
|
|
|
|
|
for (e = parent->class->interfaces; e; e = e->next) {
|
2013-12-03 15:41:59 +00:00
|
|
|
InterfaceClass *iface = e->data;
|
|
|
|
ObjectClass *klass = OBJECT_CLASS(iface);
|
|
|
|
|
|
|
|
type_initialize_interface(ti, iface->interface_type, klass->type);
|
2012-08-10 03:16:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < ti->num_interfaces; i++) {
|
|
|
|
TypeImpl *t = type_get_by_name(ti->interfaces[i].typename);
|
2020-01-18 16:23:48 +00:00
|
|
|
if (!t) {
|
|
|
|
error_report("missing interface '%s' for object '%s'",
|
|
|
|
ti->interfaces[i].typename, parent->name);
|
|
|
|
abort();
|
|
|
|
}
|
2012-08-10 03:16:10 +00:00
|
|
|
for (e = ti->class->interfaces; e; e = e->next) {
|
|
|
|
TypeImpl *target_type = OBJECT_CLASS(e->data)->type;
|
|
|
|
|
|
|
|
if (type_is_ancestor(target_type, t)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (e) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2013-12-03 15:41:59 +00:00
|
|
|
type_initialize_interface(ti, t, t);
|
2012-08-10 03:16:10 +00:00
|
|
|
}
|
2012-03-31 14:45:54 +00:00
|
|
|
}
|
2011-12-03 23:10:08 +00:00
|
|
|
|
2020-05-12 17:26:15 +00:00
|
|
|
ti->class->properties = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
|
|
|
|
object_property_free);
|
|
|
|
|
2012-03-31 14:45:54 +00:00
|
|
|
ti->class->type = ti;
|
2012-05-02 11:30:55 +00:00
|
|
|
|
2012-03-31 14:45:54 +00:00
|
|
|
while (parent) {
|
|
|
|
if (parent->class_base_init) {
|
|
|
|
parent->class_base_init(ti->class, ti->class_data);
|
2012-05-02 11:30:55 +00:00
|
|
|
}
|
2012-03-31 14:45:54 +00:00
|
|
|
parent = type_get_parent(parent);
|
2011-12-03 23:10:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (ti->class_init) {
|
|
|
|
ti->class_init(ti->class, ti->class_data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void object_init_with_type(Object *obj, TypeImpl *ti)
|
|
|
|
{
|
|
|
|
if (type_has_parent(ti)) {
|
|
|
|
object_init_with_type(obj, type_get_parent(ti));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ti->instance_init) {
|
|
|
|
ti->instance_init(obj);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-10 20:08:41 +00:00
|
|
|
static void object_post_init_with_type(Object *obj, TypeImpl *ti)
|
|
|
|
{
|
|
|
|
if (ti->instance_post_init) {
|
|
|
|
ti->instance_post_init(obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (type_has_parent(ti)) {
|
|
|
|
object_post_init_with_type(obj, type_get_parent(ti));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-07 16:05:55 +00:00
|
|
|
bool object_apply_global_props(Object *obj, const GPtrArray *props,
|
|
|
|
Error **errp)
|
2018-11-26 18:04:32 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!props) {
|
2020-07-07 16:05:55 +00:00
|
|
|
return true;
|
2018-11-26 18:04:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < props->len; i++) {
|
|
|
|
GlobalProperty *p = g_ptr_array_index(props, i);
|
2019-01-10 02:02:57 +00:00
|
|
|
Error *err = NULL;
|
2018-11-26 18:04:32 +00:00
|
|
|
|
|
|
|
if (object_dynamic_cast(obj, p->driver) == NULL) {
|
|
|
|
continue;
|
|
|
|
}
|
2020-09-14 13:56:17 +00:00
|
|
|
if (p->optional && !object_property_find(obj, p->property)) {
|
2019-07-29 16:29:02 +00:00
|
|
|
continue;
|
|
|
|
}
|
2018-11-26 18:04:32 +00:00
|
|
|
p->used = true;
|
qom: Use returned bool to check for failure, Coccinelle part
The previous commit enables conversion of
foo(..., &err);
if (err) {
...
}
to
if (!foo(..., errp)) {
...
}
for QOM functions that now return true / false on success / error.
Coccinelle script:
@@
identifier fun = {
object_apply_global_props, object_initialize_child_with_props,
object_initialize_child_with_propsv, object_property_get,
object_property_get_bool, object_property_parse, object_property_set,
object_property_set_bool, object_property_set_int,
object_property_set_link, object_property_set_qobject,
object_property_set_str, object_property_set_uint, object_set_props,
object_set_propv, user_creatable_add_dict,
user_creatable_complete, user_creatable_del
};
expression list args, args2;
typedef Error;
Error *err;
@@
- fun(args, &err, args2);
- if (err)
+ if (!fun(args, &err, args2))
{
...
}
Fails to convert hw/arm/armsse.c, because Coccinelle gets confused by
ARMSSE being used both as typedef and function-like macro there.
Convert manually.
Line breaks tidied up manually.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-Id: <20200707160613.848843-29-armbru@redhat.com>
2020-07-07 16:05:56 +00:00
|
|
|
if (!object_property_parse(obj, p->property, p->value, &err)) {
|
2018-11-26 18:04:32 +00:00
|
|
|
error_prepend(&err, "can't apply global %s.%s=%s: ",
|
|
|
|
p->driver, p->property, p->value);
|
2018-11-07 11:35:34 +00:00
|
|
|
/*
|
|
|
|
* If errp != NULL, propagate error and return.
|
|
|
|
* If errp == NULL, report a warning, but keep going
|
|
|
|
* with the remaining globals.
|
|
|
|
*/
|
|
|
|
if (errp) {
|
|
|
|
error_propagate(errp, err);
|
2020-07-07 16:05:55 +00:00
|
|
|
return false;
|
2018-11-07 11:35:34 +00:00
|
|
|
} else {
|
|
|
|
warn_report_err(err);
|
|
|
|
}
|
2018-11-26 18:04:32 +00:00
|
|
|
}
|
|
|
|
}
|
2020-07-07 16:05:55 +00:00
|
|
|
|
|
|
|
return true;
|
2018-11-26 18:04:32 +00:00
|
|
|
}
|
|
|
|
|
2019-03-08 13:14:35 +00:00
|
|
|
/*
|
|
|
|
* Global property defaults
|
|
|
|
* Slot 0: accelerator's global property defaults
|
|
|
|
* Slot 1: machine's global property defaults
|
2019-11-13 12:33:44 +00:00
|
|
|
* Slot 2: global properties from legacy command line option
|
2019-03-08 13:14:35 +00:00
|
|
|
* Each is a GPtrArray of of GlobalProperty.
|
|
|
|
* Applied in order, later entries override earlier ones.
|
|
|
|
*/
|
2019-11-13 12:33:44 +00:00
|
|
|
static GPtrArray *object_compat_props[3];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Retrieve @GPtrArray for global property defined with options
|
|
|
|
* other than "-global". These are generally used for syntactic
|
|
|
|
* sugar and legacy command line options.
|
|
|
|
*/
|
2020-08-14 07:24:50 +00:00
|
|
|
void object_register_sugar_prop(const char *driver, const char *prop,
|
|
|
|
const char *value, bool optional)
|
2019-11-13 12:33:44 +00:00
|
|
|
{
|
|
|
|
GlobalProperty *g;
|
|
|
|
if (!object_compat_props[2]) {
|
|
|
|
object_compat_props[2] = g_ptr_array_new();
|
|
|
|
}
|
|
|
|
g = g_new0(GlobalProperty, 1);
|
|
|
|
g->driver = g_strdup(driver);
|
|
|
|
g->property = g_strdup(prop);
|
|
|
|
g->value = g_strdup(value);
|
2020-08-14 07:24:50 +00:00
|
|
|
g->optional = optional;
|
2019-11-13 12:33:44 +00:00
|
|
|
g_ptr_array_add(object_compat_props[2], g);
|
|
|
|
}
|
2019-03-08 13:14:35 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Set machine's global property defaults to @compat_props.
|
|
|
|
* May be called at most once.
|
|
|
|
*/
|
|
|
|
void object_set_machine_compat_props(GPtrArray *compat_props)
|
|
|
|
{
|
|
|
|
assert(!object_compat_props[1]);
|
|
|
|
object_compat_props[1] = compat_props;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set accelerator's global property defaults to @compat_props.
|
|
|
|
* May be called at most once.
|
|
|
|
*/
|
|
|
|
void object_set_accelerator_compat_props(GPtrArray *compat_props)
|
|
|
|
{
|
|
|
|
assert(!object_compat_props[0]);
|
|
|
|
object_compat_props[0] = compat_props;
|
|
|
|
}
|
|
|
|
|
|
|
|
void object_apply_compat_props(Object *obj)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(object_compat_props); i++) {
|
|
|
|
object_apply_global_props(obj, object_compat_props[i],
|
2019-11-13 12:33:44 +00:00
|
|
|
i == 2 ? &error_fatal : &error_abort);
|
2019-03-08 13:14:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-10 15:30:19 +00:00
|
|
|
static void object_class_property_init_all(Object *obj)
|
|
|
|
{
|
|
|
|
ObjectPropertyIterator iter;
|
|
|
|
ObjectProperty *prop;
|
|
|
|
|
|
|
|
object_class_property_iter_init(&iter, object_get_class(obj));
|
|
|
|
while ((prop = object_property_iter_next(&iter))) {
|
|
|
|
if (prop->init) {
|
|
|
|
prop->init(obj, prop);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-12 17:31:04 +00:00
|
|
|
static void object_initialize_with_type(Object *obj, size_t size, TypeImpl *type)
|
2011-12-03 23:10:08 +00:00
|
|
|
{
|
2012-02-28 11:57:11 +00:00
|
|
|
type_initialize(type);
|
2012-02-28 11:57:10 +00:00
|
|
|
|
2018-06-08 17:02:31 +00:00
|
|
|
g_assert(type->instance_size >= sizeof(Object));
|
2011-12-03 23:10:08 +00:00
|
|
|
g_assert(type->abstract == false);
|
2018-06-08 17:02:31 +00:00
|
|
|
g_assert(size >= type->instance_size);
|
2011-12-03 23:10:08 +00:00
|
|
|
|
|
|
|
memset(obj, 0, type->instance_size);
|
|
|
|
obj->class = type->class;
|
2012-11-23 08:47:12 +00:00
|
|
|
object_ref(obj);
|
2020-01-10 15:30:19 +00:00
|
|
|
object_class_property_init_all(obj);
|
2015-10-13 12:37:45 +00:00
|
|
|
obj->properties = g_hash_table_new_full(g_str_hash, g_str_equal,
|
|
|
|
NULL, object_property_free);
|
2011-12-03 23:10:08 +00:00
|
|
|
object_init_with_type(obj, type);
|
2013-07-10 20:08:41 +00:00
|
|
|
object_post_init_with_type(obj, type);
|
2011-12-03 23:10:08 +00:00
|
|
|
}
|
|
|
|
|
2013-08-23 17:37:12 +00:00
|
|
|
void object_initialize(void *data, size_t size, const char *typename)
|
2011-12-03 23:10:08 +00:00
|
|
|
{
|
|
|
|
TypeImpl *type = type_get_by_name(typename);
|
|
|
|
|
2020-09-14 13:42:22 +00:00
|
|
|
#ifdef CONFIG_MODULES
|
|
|
|
if (!type) {
|
|
|
|
module_load_qom_one(typename);
|
|
|
|
type = type_get_by_name(typename);
|
|
|
|
}
|
|
|
|
#endif
|
qom/object: Display more helpful message when an object type is missing
When writing a new board, adding device which uses other devices
(container) or simply refactoring, one can discover the hard way
his machine misses some devices. In the case of containers, the
error is not obvious:
$ qemu-system-microblaze -M xlnx-zynqmp-pmu
**
ERROR:/source/qemu/qom/object.c:454:object_initialize_with_type: assertion failed: (type != NULL)
Aborted (core dumped)
And we have to look at the coredump to figure the error:
(gdb) bt
#1 0x00007f84773cf895 in abort () at /lib64/libc.so.6
#2 0x00007f847961fb53 in () at /lib64/libglib-2.0.so.0
#3 0x00007f847967a4de in g_assertion_message_expr () at /lib64/libglib-2.0.so.0
#4 0x000055c4bcac6c11 in object_initialize_with_type (data=data@entry=0x55c4bdf239e0, size=size@entry=2464, type=<optimized out>) at /source/qemu/qom/object.c:454
#5 0x000055c4bcac6e6d in object_initialize (data=data@entry=0x55c4bdf239e0, size=size@entry=2464, typename=typename@entry=0x55c4bcc7c643 "xlnx.zynqmp_ipi") at /source/qemu/qom/object.c:474
#6 0x000055c4bc9ea474 in xlnx_zynqmp_pmu_init (machine=0x55c4bdd46000) at /source/qemu/hw/microblaze/xlnx-zynqmp-pmu.c:176
#7 0x000055c4bca3b6cb in machine_run_board_init (machine=0x55c4bdd46000) at /source/qemu/hw/core/machine.c:1030
#8 0x000055c4bc95f6d2 in main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>) at /source/qemu/vl.c:4479
Since the caller knows the type name requested, we can simply display it
to ease development.
With this patch applied we get:
$ qemu-system-microblaze -M xlnx-zynqmp-pmu
qemu-system-microblaze: missing object type 'xlnx.zynqmp_ipi'
Aborted (core dumped)
Since the assert(type) check in object_initialize_with_type() is
now impossible, remove it.
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Message-Id: <20190427135642.16464-1-philmd@redhat.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2019-04-27 13:56:42 +00:00
|
|
|
if (!type) {
|
|
|
|
error_report("missing object type '%s'", typename);
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
2013-08-30 16:28:37 +00:00
|
|
|
object_initialize_with_type(data, size, type);
|
2011-12-03 23:10:08 +00:00
|
|
|
}
|
|
|
|
|
2020-07-07 16:05:55 +00:00
|
|
|
bool object_initialize_child_with_props(Object *parentobj,
|
|
|
|
const char *propname,
|
|
|
|
void *childobj, size_t size,
|
|
|
|
const char *type,
|
|
|
|
Error **errp, ...)
|
2018-07-16 12:59:18 +00:00
|
|
|
{
|
|
|
|
va_list vargs;
|
2020-07-07 16:05:55 +00:00
|
|
|
bool ok;
|
2018-07-16 12:59:18 +00:00
|
|
|
|
|
|
|
va_start(vargs, errp);
|
2020-07-07 16:05:55 +00:00
|
|
|
ok = object_initialize_child_with_propsv(parentobj, propname,
|
|
|
|
childobj, size, type, errp,
|
|
|
|
vargs);
|
2018-07-16 12:59:18 +00:00
|
|
|
va_end(vargs);
|
2020-07-07 16:05:55 +00:00
|
|
|
return ok;
|
2018-07-16 12:59:18 +00:00
|
|
|
}
|
|
|
|
|
2020-07-07 16:05:55 +00:00
|
|
|
bool object_initialize_child_with_propsv(Object *parentobj,
|
|
|
|
const char *propname,
|
|
|
|
void *childobj, size_t size,
|
|
|
|
const char *type,
|
|
|
|
Error **errp, va_list vargs)
|
2018-07-16 12:59:18 +00:00
|
|
|
{
|
2020-07-07 16:05:55 +00:00
|
|
|
bool ok = false;
|
2018-07-16 12:59:18 +00:00
|
|
|
Object *obj;
|
2018-12-04 14:20:07 +00:00
|
|
|
UserCreatable *uc;
|
2018-07-16 12:59:18 +00:00
|
|
|
|
|
|
|
object_initialize(childobj, size, type);
|
|
|
|
obj = OBJECT(childobj);
|
|
|
|
|
2020-07-07 16:05:58 +00:00
|
|
|
if (!object_set_propv(obj, errp, vargs)) {
|
2018-07-16 12:59:18 +00:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
object_property_add_child(parentobj, propname, obj);
|
2018-07-16 12:59:18 +00:00
|
|
|
|
2018-12-04 14:20:07 +00:00
|
|
|
uc = (UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE);
|
|
|
|
if (uc) {
|
2020-07-07 16:06:04 +00:00
|
|
|
if (!user_creatable_complete(uc, errp)) {
|
2018-07-16 12:59:18 +00:00
|
|
|
object_unparent(obj);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-07 16:05:55 +00:00
|
|
|
ok = true;
|
|
|
|
|
2020-05-05 15:29:09 +00:00
|
|
|
out:
|
2018-07-16 12:59:18 +00:00
|
|
|
/*
|
2020-05-05 15:29:09 +00:00
|
|
|
* We want @obj's reference to be 1 on success, 0 on failure.
|
|
|
|
* On success, it's 2: one taken by object_initialize(), and one
|
|
|
|
* by object_property_add_child().
|
|
|
|
* On failure in object_initialize() or earlier, it's 1.
|
|
|
|
* On failure afterwards, it's also 1: object_unparent() releases
|
|
|
|
* the reference taken by object_property_add_child().
|
2018-07-16 12:59:18 +00:00
|
|
|
*/
|
|
|
|
object_unref(obj);
|
2020-07-07 16:05:55 +00:00
|
|
|
return ok;
|
2018-07-16 12:59:18 +00:00
|
|
|
}
|
|
|
|
|
qom: Less verbose object_initialize_child()
All users of object_initialize_child() pass the obvious child size
argument. Almost all pass &error_abort and no properties. Tiresome.
Rename object_initialize_child() to
object_initialize_child_with_props() to free the name. New
convenience wrapper object_initialize_child() automates the size
argument, and passes &error_abort and no properties.
Rename object_initialize_childv() to
object_initialize_child_with_propsv() for consistency.
Convert callers with this Coccinelle script:
@@
expression parent, propname, type;
expression child, size;
symbol error_abort;
@@
- object_initialize_child(parent, propname, OBJECT(child), size, type, &error_abort, NULL)
+ object_initialize_child(parent, propname, child, size, type, &error_abort, NULL)
@@
expression parent, propname, type;
expression child;
symbol error_abort;
@@
- object_initialize_child(parent, propname, child, sizeof(*child), type, &error_abort, NULL)
+ object_initialize_child(parent, propname, child, type)
@@
expression parent, propname, type;
expression child;
symbol error_abort;
@@
- object_initialize_child(parent, propname, &child, sizeof(child), type, &error_abort, NULL)
+ object_initialize_child(parent, propname, &child, type)
@@
expression parent, propname, type;
expression child, size, err;
expression list props;
@@
- object_initialize_child(parent, propname, child, size, type, err, props)
+ object_initialize_child_with_props(parent, propname, child, size, type, err, props)
Note that Coccinelle chokes on ARMSSE typedef vs. macro in
hw/arm/armsse.c. Worked around by temporarily renaming the macro for
the spatch run.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
[Rebased: machine opentitan is new (commit fe0fe4735e7)]
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200610053247.1583243-37-armbru@redhat.com>
2020-06-10 05:32:25 +00:00
|
|
|
void object_initialize_child_internal(Object *parent,
|
|
|
|
const char *propname,
|
|
|
|
void *child, size_t size,
|
|
|
|
const char *type)
|
|
|
|
{
|
|
|
|
object_initialize_child_with_props(parent, propname, child, size, type,
|
|
|
|
&error_abort, NULL);
|
|
|
|
}
|
|
|
|
|
2012-05-26 22:32:40 +00:00
|
|
|
static inline bool object_property_is_child(ObjectProperty *prop)
|
|
|
|
{
|
|
|
|
return strstart(prop->type, "child<", NULL);
|
|
|
|
}
|
|
|
|
|
2012-01-30 14:55:55 +00:00
|
|
|
static void object_property_del_all(Object *obj)
|
|
|
|
{
|
2020-01-10 15:30:30 +00:00
|
|
|
g_autoptr(GHashTable) done = g_hash_table_new(NULL, NULL);
|
2015-10-13 12:37:45 +00:00
|
|
|
ObjectProperty *prop;
|
2020-01-10 15:30:30 +00:00
|
|
|
ObjectPropertyIterator iter;
|
2015-10-13 12:37:45 +00:00
|
|
|
bool released;
|
|
|
|
|
|
|
|
do {
|
|
|
|
released = false;
|
2020-01-10 15:30:30 +00:00
|
|
|
object_property_iter_init(&iter, obj);
|
|
|
|
while ((prop = object_property_iter_next(&iter)) != NULL) {
|
|
|
|
if (g_hash_table_add(done, prop)) {
|
|
|
|
if (prop->release) {
|
|
|
|
prop->release(obj, prop->name, prop->opaque);
|
|
|
|
released = true;
|
|
|
|
break;
|
|
|
|
}
|
2015-10-13 12:37:45 +00:00
|
|
|
}
|
2012-01-30 14:55:55 +00:00
|
|
|
}
|
2015-10-13 12:37:45 +00:00
|
|
|
} while (released);
|
2012-01-30 14:55:55 +00:00
|
|
|
|
2015-10-13 12:37:45 +00:00
|
|
|
g_hash_table_unref(obj->properties);
|
2012-01-30 14:55:55 +00:00
|
|
|
}
|
|
|
|
|
2020-05-05 15:29:11 +00:00
|
|
|
static void object_property_del_child(Object *obj, Object *child)
|
2012-01-30 14:55:55 +00:00
|
|
|
{
|
|
|
|
ObjectProperty *prop;
|
2015-10-13 12:37:45 +00:00
|
|
|
GHashTableIter iter;
|
|
|
|
gpointer key, value;
|
2012-01-30 14:55:55 +00:00
|
|
|
|
2015-10-13 12:37:45 +00:00
|
|
|
g_hash_table_iter_init(&iter, obj->properties);
|
|
|
|
while (g_hash_table_iter_next(&iter, &key, &value)) {
|
|
|
|
prop = value;
|
|
|
|
if (object_property_is_child(prop) && prop->opaque == child) {
|
|
|
|
if (prop->release) {
|
|
|
|
prop->release(obj, prop->name, prop->opaque);
|
|
|
|
prop->release = NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
g_hash_table_iter_init(&iter, obj->properties);
|
|
|
|
while (g_hash_table_iter_next(&iter, &key, &value)) {
|
|
|
|
prop = value;
|
2012-05-26 22:32:40 +00:00
|
|
|
if (object_property_is_child(prop) && prop->opaque == child) {
|
2015-10-13 12:37:45 +00:00
|
|
|
g_hash_table_iter_remove(&iter);
|
2012-02-28 08:54:15 +00:00
|
|
|
break;
|
2012-01-30 14:55:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void object_unparent(Object *obj)
|
|
|
|
{
|
2013-03-18 19:01:37 +00:00
|
|
|
if (obj->parent) {
|
2020-05-05 15:29:11 +00:00
|
|
|
object_property_del_child(obj->parent, obj);
|
2013-03-18 19:01:37 +00:00
|
|
|
}
|
2012-01-30 14:55:55 +00:00
|
|
|
}
|
|
|
|
|
2011-12-03 23:10:08 +00:00
|
|
|
static void object_deinit(Object *obj, TypeImpl *type)
|
|
|
|
{
|
|
|
|
if (type->instance_finalize) {
|
|
|
|
type->instance_finalize(obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (type_has_parent(type)) {
|
|
|
|
object_deinit(obj, type_get_parent(type));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-23 08:47:16 +00:00
|
|
|
static void object_finalize(void *data)
|
2011-12-03 23:10:08 +00:00
|
|
|
{
|
|
|
|
Object *obj = data;
|
|
|
|
TypeImpl *ti = obj->class->type;
|
|
|
|
|
2012-01-30 14:55:55 +00:00
|
|
|
object_property_del_all(obj);
|
2014-06-11 09:58:30 +00:00
|
|
|
object_deinit(obj, ti);
|
2011-12-23 14:47:39 +00:00
|
|
|
|
2018-06-08 17:02:31 +00:00
|
|
|
g_assert(obj->ref == 0);
|
2020-12-15 22:41:33 +00:00
|
|
|
g_assert(obj->parent == NULL);
|
2012-11-23 08:47:14 +00:00
|
|
|
if (obj->free) {
|
|
|
|
obj->free(obj);
|
|
|
|
}
|
2011-12-03 23:10:08 +00:00
|
|
|
}
|
|
|
|
|
2020-09-16 00:46:34 +00:00
|
|
|
/* Find the minimum alignment guaranteed by the system malloc. */
|
|
|
|
#if __STDC_VERSION__ >= 201112L
|
|
|
|
typddef max_align_t qemu_max_align_t;
|
|
|
|
#else
|
|
|
|
typedef union {
|
|
|
|
long l;
|
|
|
|
void *p;
|
|
|
|
double d;
|
|
|
|
long double ld;
|
|
|
|
} qemu_max_align_t;
|
|
|
|
#endif
|
|
|
|
|
2016-12-12 17:31:51 +00:00
|
|
|
static Object *object_new_with_type(Type type)
|
2011-12-03 23:10:08 +00:00
|
|
|
{
|
|
|
|
Object *obj;
|
2020-09-16 00:46:34 +00:00
|
|
|
size_t size, align;
|
|
|
|
void (*obj_free)(void *);
|
2011-12-03 23:10:08 +00:00
|
|
|
|
|
|
|
g_assert(type != NULL);
|
2012-02-28 11:57:11 +00:00
|
|
|
type_initialize(type);
|
2011-12-03 23:10:08 +00:00
|
|
|
|
2020-09-16 00:46:34 +00:00
|
|
|
size = type->instance_size;
|
|
|
|
align = type->instance_align;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Do not use qemu_memalign unless required. Depending on the
|
|
|
|
* implementation, extra alignment implies extra overhead.
|
|
|
|
*/
|
|
|
|
if (likely(align <= __alignof__(qemu_max_align_t))) {
|
|
|
|
obj = g_malloc(size);
|
|
|
|
obj_free = g_free;
|
|
|
|
} else {
|
|
|
|
obj = qemu_memalign(align, size);
|
|
|
|
obj_free = qemu_vfree;
|
|
|
|
}
|
|
|
|
|
|
|
|
object_initialize_with_type(obj, size, type);
|
|
|
|
obj->free = obj_free;
|
2011-12-03 23:10:08 +00:00
|
|
|
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
2019-11-13 12:57:55 +00:00
|
|
|
Object *object_new_with_class(ObjectClass *klass)
|
|
|
|
{
|
|
|
|
return object_new_with_type(klass->type);
|
|
|
|
}
|
|
|
|
|
2011-12-03 23:10:08 +00:00
|
|
|
Object *object_new(const char *typename)
|
|
|
|
{
|
|
|
|
TypeImpl *ti = type_get_by_name(typename);
|
|
|
|
|
|
|
|
return object_new_with_type(ti);
|
|
|
|
}
|
|
|
|
|
qom: Add object_new_with_props() / object_new_withpropv() helpers
It is reasonably common to want to create an object, set a
number of properties, register it in the hierarchy and then
mark it as complete (if a user creatable type). This requires
quite a lot of error prone, verbose, boilerplate code to achieve.
First a pair of functions object_set_props() / object_set_propv()
are added which allow for a list of objects to be set in
one single API call.
Then object_new_with_props() / object_new_with_propv() constructors
are added which simplify the sequence of calls to create an
object, populate properties, register in the object composition
tree and mark the object complete, into a single method call.
Usage would be:
Error *err = NULL;
Object *obj;
obj = object_new_with_propv(TYPE_MEMORY_BACKEND_FILE,
object_get_objects_root(),
"hostmem0",
&err,
"share", "yes",
"mem-path", "/dev/shm/somefile",
"prealloc", "yes",
"size", "1048576",
NULL);
Note all property values are passed in string form and will
be parsed into their required data types, using normal QOM
semantics for parsing from string format.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 16:14:06 +00:00
|
|
|
|
|
|
|
Object *object_new_with_props(const char *typename,
|
|
|
|
Object *parent,
|
|
|
|
const char *id,
|
|
|
|
Error **errp,
|
|
|
|
...)
|
|
|
|
{
|
|
|
|
va_list vargs;
|
|
|
|
Object *obj;
|
|
|
|
|
|
|
|
va_start(vargs, errp);
|
|
|
|
obj = object_new_with_propv(typename, parent, id, errp, vargs);
|
|
|
|
va_end(vargs);
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Object *object_new_with_propv(const char *typename,
|
|
|
|
Object *parent,
|
|
|
|
const char *id,
|
|
|
|
Error **errp,
|
|
|
|
va_list vargs)
|
|
|
|
{
|
|
|
|
Object *obj;
|
|
|
|
ObjectClass *klass;
|
2018-12-04 14:20:07 +00:00
|
|
|
UserCreatable *uc;
|
qom: Add object_new_with_props() / object_new_withpropv() helpers
It is reasonably common to want to create an object, set a
number of properties, register it in the hierarchy and then
mark it as complete (if a user creatable type). This requires
quite a lot of error prone, verbose, boilerplate code to achieve.
First a pair of functions object_set_props() / object_set_propv()
are added which allow for a list of objects to be set in
one single API call.
Then object_new_with_props() / object_new_with_propv() constructors
are added which simplify the sequence of calls to create an
object, populate properties, register in the object composition
tree and mark the object complete, into a single method call.
Usage would be:
Error *err = NULL;
Object *obj;
obj = object_new_with_propv(TYPE_MEMORY_BACKEND_FILE,
object_get_objects_root(),
"hostmem0",
&err,
"share", "yes",
"mem-path", "/dev/shm/somefile",
"prealloc", "yes",
"size", "1048576",
NULL);
Note all property values are passed in string form and will
be parsed into their required data types, using normal QOM
semantics for parsing from string format.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 16:14:06 +00:00
|
|
|
|
|
|
|
klass = object_class_by_name(typename);
|
|
|
|
if (!klass) {
|
|
|
|
error_setg(errp, "invalid object type: %s", typename);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (object_class_is_abstract(klass)) {
|
|
|
|
error_setg(errp, "object type '%s' is abstract", typename);
|
|
|
|
return NULL;
|
|
|
|
}
|
2019-03-11 08:32:34 +00:00
|
|
|
obj = object_new_with_type(klass->type);
|
qom: Add object_new_with_props() / object_new_withpropv() helpers
It is reasonably common to want to create an object, set a
number of properties, register it in the hierarchy and then
mark it as complete (if a user creatable type). This requires
quite a lot of error prone, verbose, boilerplate code to achieve.
First a pair of functions object_set_props() / object_set_propv()
are added which allow for a list of objects to be set in
one single API call.
Then object_new_with_props() / object_new_with_propv() constructors
are added which simplify the sequence of calls to create an
object, populate properties, register in the object composition
tree and mark the object complete, into a single method call.
Usage would be:
Error *err = NULL;
Object *obj;
obj = object_new_with_propv(TYPE_MEMORY_BACKEND_FILE,
object_get_objects_root(),
"hostmem0",
&err,
"share", "yes",
"mem-path", "/dev/shm/somefile",
"prealloc", "yes",
"size", "1048576",
NULL);
Note all property values are passed in string form and will
be parsed into their required data types, using normal QOM
semantics for parsing from string format.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 16:14:06 +00:00
|
|
|
|
2020-07-07 16:05:58 +00:00
|
|
|
if (!object_set_propv(obj, errp, vargs)) {
|
qom: Add object_new_with_props() / object_new_withpropv() helpers
It is reasonably common to want to create an object, set a
number of properties, register it in the hierarchy and then
mark it as complete (if a user creatable type). This requires
quite a lot of error prone, verbose, boilerplate code to achieve.
First a pair of functions object_set_props() / object_set_propv()
are added which allow for a list of objects to be set in
one single API call.
Then object_new_with_props() / object_new_with_propv() constructors
are added which simplify the sequence of calls to create an
object, populate properties, register in the object composition
tree and mark the object complete, into a single method call.
Usage would be:
Error *err = NULL;
Object *obj;
obj = object_new_with_propv(TYPE_MEMORY_BACKEND_FILE,
object_get_objects_root(),
"hostmem0",
&err,
"share", "yes",
"mem-path", "/dev/shm/somefile",
"prealloc", "yes",
"size", "1048576",
NULL);
Note all property values are passed in string form and will
be parsed into their required data types, using normal QOM
semantics for parsing from string format.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 16:14:06 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2018-06-15 15:39:35 +00:00
|
|
|
if (id != NULL) {
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
object_property_add_child(parent, id, obj);
|
qom: Add object_new_with_props() / object_new_withpropv() helpers
It is reasonably common to want to create an object, set a
number of properties, register it in the hierarchy and then
mark it as complete (if a user creatable type). This requires
quite a lot of error prone, verbose, boilerplate code to achieve.
First a pair of functions object_set_props() / object_set_propv()
are added which allow for a list of objects to be set in
one single API call.
Then object_new_with_props() / object_new_with_propv() constructors
are added which simplify the sequence of calls to create an
object, populate properties, register in the object composition
tree and mark the object complete, into a single method call.
Usage would be:
Error *err = NULL;
Object *obj;
obj = object_new_with_propv(TYPE_MEMORY_BACKEND_FILE,
object_get_objects_root(),
"hostmem0",
&err,
"share", "yes",
"mem-path", "/dev/shm/somefile",
"prealloc", "yes",
"size", "1048576",
NULL);
Note all property values are passed in string form and will
be parsed into their required data types, using normal QOM
semantics for parsing from string format.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 16:14:06 +00:00
|
|
|
}
|
|
|
|
|
2018-12-04 14:20:07 +00:00
|
|
|
uc = (UserCreatable *)object_dynamic_cast(obj, TYPE_USER_CREATABLE);
|
|
|
|
if (uc) {
|
2020-07-07 16:06:04 +00:00
|
|
|
if (!user_creatable_complete(uc, errp)) {
|
2018-06-15 15:39:35 +00:00
|
|
|
if (id != NULL) {
|
|
|
|
object_unparent(obj);
|
|
|
|
}
|
qom: Add object_new_with_props() / object_new_withpropv() helpers
It is reasonably common to want to create an object, set a
number of properties, register it in the hierarchy and then
mark it as complete (if a user creatable type). This requires
quite a lot of error prone, verbose, boilerplate code to achieve.
First a pair of functions object_set_props() / object_set_propv()
are added which allow for a list of objects to be set in
one single API call.
Then object_new_with_props() / object_new_with_propv() constructors
are added which simplify the sequence of calls to create an
object, populate properties, register in the object composition
tree and mark the object complete, into a single method call.
Usage would be:
Error *err = NULL;
Object *obj;
obj = object_new_with_propv(TYPE_MEMORY_BACKEND_FILE,
object_get_objects_root(),
"hostmem0",
&err,
"share", "yes",
"mem-path", "/dev/shm/somefile",
"prealloc", "yes",
"size", "1048576",
NULL);
Note all property values are passed in string form and will
be parsed into their required data types, using normal QOM
semantics for parsing from string format.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 16:14:06 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-12 07:00:19 +00:00
|
|
|
object_unref(obj);
|
qom: Add object_new_with_props() / object_new_withpropv() helpers
It is reasonably common to want to create an object, set a
number of properties, register it in the hierarchy and then
mark it as complete (if a user creatable type). This requires
quite a lot of error prone, verbose, boilerplate code to achieve.
First a pair of functions object_set_props() / object_set_propv()
are added which allow for a list of objects to be set in
one single API call.
Then object_new_with_props() / object_new_with_propv() constructors
are added which simplify the sequence of calls to create an
object, populate properties, register in the object composition
tree and mark the object complete, into a single method call.
Usage would be:
Error *err = NULL;
Object *obj;
obj = object_new_with_propv(TYPE_MEMORY_BACKEND_FILE,
object_get_objects_root(),
"hostmem0",
&err,
"share", "yes",
"mem-path", "/dev/shm/somefile",
"prealloc", "yes",
"size", "1048576",
NULL);
Note all property values are passed in string form and will
be parsed into their required data types, using normal QOM
semantics for parsing from string format.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 16:14:06 +00:00
|
|
|
return obj;
|
|
|
|
|
|
|
|
error:
|
|
|
|
object_unref(obj);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-07-07 16:05:58 +00:00
|
|
|
bool object_set_props(Object *obj,
|
qom: Add object_new_with_props() / object_new_withpropv() helpers
It is reasonably common to want to create an object, set a
number of properties, register it in the hierarchy and then
mark it as complete (if a user creatable type). This requires
quite a lot of error prone, verbose, boilerplate code to achieve.
First a pair of functions object_set_props() / object_set_propv()
are added which allow for a list of objects to be set in
one single API call.
Then object_new_with_props() / object_new_with_propv() constructors
are added which simplify the sequence of calls to create an
object, populate properties, register in the object composition
tree and mark the object complete, into a single method call.
Usage would be:
Error *err = NULL;
Object *obj;
obj = object_new_with_propv(TYPE_MEMORY_BACKEND_FILE,
object_get_objects_root(),
"hostmem0",
&err,
"share", "yes",
"mem-path", "/dev/shm/somefile",
"prealloc", "yes",
"size", "1048576",
NULL);
Note all property values are passed in string form and will
be parsed into their required data types, using normal QOM
semantics for parsing from string format.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 16:14:06 +00:00
|
|
|
Error **errp,
|
|
|
|
...)
|
|
|
|
{
|
|
|
|
va_list vargs;
|
2020-07-07 16:05:58 +00:00
|
|
|
bool ret;
|
qom: Add object_new_with_props() / object_new_withpropv() helpers
It is reasonably common to want to create an object, set a
number of properties, register it in the hierarchy and then
mark it as complete (if a user creatable type). This requires
quite a lot of error prone, verbose, boilerplate code to achieve.
First a pair of functions object_set_props() / object_set_propv()
are added which allow for a list of objects to be set in
one single API call.
Then object_new_with_props() / object_new_with_propv() constructors
are added which simplify the sequence of calls to create an
object, populate properties, register in the object composition
tree and mark the object complete, into a single method call.
Usage would be:
Error *err = NULL;
Object *obj;
obj = object_new_with_propv(TYPE_MEMORY_BACKEND_FILE,
object_get_objects_root(),
"hostmem0",
&err,
"share", "yes",
"mem-path", "/dev/shm/somefile",
"prealloc", "yes",
"size", "1048576",
NULL);
Note all property values are passed in string form and will
be parsed into their required data types, using normal QOM
semantics for parsing from string format.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 16:14:06 +00:00
|
|
|
|
|
|
|
va_start(vargs, errp);
|
|
|
|
ret = object_set_propv(obj, errp, vargs);
|
|
|
|
va_end(vargs);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-07-07 16:05:58 +00:00
|
|
|
bool object_set_propv(Object *obj,
|
qom: Add object_new_with_props() / object_new_withpropv() helpers
It is reasonably common to want to create an object, set a
number of properties, register it in the hierarchy and then
mark it as complete (if a user creatable type). This requires
quite a lot of error prone, verbose, boilerplate code to achieve.
First a pair of functions object_set_props() / object_set_propv()
are added which allow for a list of objects to be set in
one single API call.
Then object_new_with_props() / object_new_with_propv() constructors
are added which simplify the sequence of calls to create an
object, populate properties, register in the object composition
tree and mark the object complete, into a single method call.
Usage would be:
Error *err = NULL;
Object *obj;
obj = object_new_with_propv(TYPE_MEMORY_BACKEND_FILE,
object_get_objects_root(),
"hostmem0",
&err,
"share", "yes",
"mem-path", "/dev/shm/somefile",
"prealloc", "yes",
"size", "1048576",
NULL);
Note all property values are passed in string form and will
be parsed into their required data types, using normal QOM
semantics for parsing from string format.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 16:14:06 +00:00
|
|
|
Error **errp,
|
|
|
|
va_list vargs)
|
|
|
|
{
|
|
|
|
const char *propname;
|
|
|
|
|
|
|
|
propname = va_arg(vargs, char *);
|
|
|
|
while (propname != NULL) {
|
|
|
|
const char *value = va_arg(vargs, char *);
|
|
|
|
|
|
|
|
g_assert(value != NULL);
|
error: Eliminate error_propagate() with Coccinelle, part 1
When all we do with an Error we receive into a local variable is
propagating to somewhere else, we can just as well receive it there
right away. Convert
if (!foo(..., &err)) {
...
error_propagate(errp, err);
...
return ...
}
to
if (!foo(..., errp)) {
...
...
return ...
}
where nothing else needs @err. Coccinelle script:
@rule1 forall@
identifier fun, err, errp, lbl;
expression list args, args2;
binary operator op;
constant c1, c2;
symbol false;
@@
if (
(
- fun(args, &err, args2)
+ fun(args, errp, args2)
|
- !fun(args, &err, args2)
+ !fun(args, errp, args2)
|
- fun(args, &err, args2) op c1
+ fun(args, errp, args2) op c1
)
)
{
... when != err
when != lbl:
when strict
- error_propagate(errp, err);
... when != err
(
return;
|
return c2;
|
return false;
)
}
@rule2 forall@
identifier fun, err, errp, lbl;
expression list args, args2;
expression var;
binary operator op;
constant c1, c2;
symbol false;
@@
- var = fun(args, &err, args2);
+ var = fun(args, errp, args2);
... when != err
if (
(
var
|
!var
|
var op c1
)
)
{
... when != err
when != lbl:
when strict
- error_propagate(errp, err);
... when != err
(
return;
|
return c2;
|
return false;
|
return var;
)
}
@depends on rule1 || rule2@
identifier err;
@@
- Error *err = NULL;
... when != err
Not exactly elegant, I'm afraid.
The "when != lbl:" is necessary to avoid transforming
if (fun(args, &err)) {
goto out
}
...
out:
error_propagate(errp, err);
even though other paths to label out still need the error_propagate().
For an actual example, see sclp_realize().
Without the "when strict", Coccinelle transforms vfio_msix_setup(),
incorrectly. I don't know what exactly "when strict" does, only that
it helps here.
The match of return is narrower than what I want, but I can't figure
out how to express "return where the operand doesn't use @err". For
an example where it's too narrow, see vfio_intx_enable().
Silently fails to convert hw/arm/armsse.c, because Coccinelle gets
confused by ARMSSE being used both as typedef and function-like macro
there. Converted manually.
Line breaks tidied up manually. One nested declaration of @local_err
deleted manually. Preexisting unwanted blank line dropped in
hw/riscv/sifive_e.c.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20200707160613.848843-35-armbru@redhat.com>
2020-07-07 16:06:02 +00:00
|
|
|
if (!object_property_parse(obj, propname, value, errp)) {
|
2020-07-07 16:05:58 +00:00
|
|
|
return false;
|
qom: Add object_new_with_props() / object_new_withpropv() helpers
It is reasonably common to want to create an object, set a
number of properties, register it in the hierarchy and then
mark it as complete (if a user creatable type). This requires
quite a lot of error prone, verbose, boilerplate code to achieve.
First a pair of functions object_set_props() / object_set_propv()
are added which allow for a list of objects to be set in
one single API call.
Then object_new_with_props() / object_new_with_propv() constructors
are added which simplify the sequence of calls to create an
object, populate properties, register in the object composition
tree and mark the object complete, into a single method call.
Usage would be:
Error *err = NULL;
Object *obj;
obj = object_new_with_propv(TYPE_MEMORY_BACKEND_FILE,
object_get_objects_root(),
"hostmem0",
&err,
"share", "yes",
"mem-path", "/dev/shm/somefile",
"prealloc", "yes",
"size", "1048576",
NULL);
Note all property values are passed in string form and will
be parsed into their required data types, using normal QOM
semantics for parsing from string format.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 16:14:06 +00:00
|
|
|
}
|
|
|
|
propname = va_arg(vargs, char *);
|
|
|
|
}
|
|
|
|
|
2020-07-07 16:05:58 +00:00
|
|
|
return true;
|
qom: Add object_new_with_props() / object_new_withpropv() helpers
It is reasonably common to want to create an object, set a
number of properties, register it in the hierarchy and then
mark it as complete (if a user creatable type). This requires
quite a lot of error prone, verbose, boilerplate code to achieve.
First a pair of functions object_set_props() / object_set_propv()
are added which allow for a list of objects to be set in
one single API call.
Then object_new_with_props() / object_new_with_propv() constructors
are added which simplify the sequence of calls to create an
object, populate properties, register in the object composition
tree and mark the object complete, into a single method call.
Usage would be:
Error *err = NULL;
Object *obj;
obj = object_new_with_propv(TYPE_MEMORY_BACKEND_FILE,
object_get_objects_root(),
"hostmem0",
&err,
"share", "yes",
"mem-path", "/dev/shm/somefile",
"prealloc", "yes",
"size", "1048576",
NULL);
Note all property values are passed in string form and will
be parsed into their required data types, using normal QOM
semantics for parsing from string format.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 16:14:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-12-03 23:10:08 +00:00
|
|
|
Object *object_dynamic_cast(Object *obj, const char *typename)
|
|
|
|
{
|
2012-11-23 15:56:17 +00:00
|
|
|
if (obj && object_class_dynamic_cast(object_get_class(obj), typename)) {
|
2012-02-03 10:57:23 +00:00
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
2011-12-03 23:10:08 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-05-10 12:16:38 +00:00
|
|
|
Object *object_dynamic_cast_assert(Object *obj, const char *typename,
|
|
|
|
const char *file, int line, const char *func)
|
2011-12-03 23:10:08 +00:00
|
|
|
{
|
2013-05-10 12:16:39 +00:00
|
|
|
trace_object_dynamic_cast_assert(obj ? obj->class->type->name : "(null)",
|
|
|
|
typename, file, line, func);
|
|
|
|
|
2013-05-10 12:16:40 +00:00
|
|
|
#ifdef CONFIG_QOM_CAST_DEBUG
|
2013-05-13 20:22:24 +00:00
|
|
|
int i;
|
|
|
|
Object *inst;
|
|
|
|
|
2013-05-22 01:19:16 +00:00
|
|
|
for (i = 0; obj && i < OBJECT_CLASS_CAST_CACHE; i++) {
|
2020-09-23 10:56:46 +00:00
|
|
|
if (qatomic_read(&obj->class->object_cast_cache[i]) == typename) {
|
2013-05-13 20:22:24 +00:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inst = object_dynamic_cast(obj, typename);
|
2011-12-03 23:10:08 +00:00
|
|
|
|
2012-11-23 15:56:17 +00:00
|
|
|
if (!inst && obj) {
|
2013-05-10 12:16:38 +00:00
|
|
|
fprintf(stderr, "%s:%d:%s: Object %p is not an instance of type %s\n",
|
|
|
|
file, line, func, obj, typename);
|
2011-12-03 23:10:08 +00:00
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
2013-05-10 12:16:40 +00:00
|
|
|
assert(obj == inst);
|
2013-05-13 20:22:24 +00:00
|
|
|
|
2013-05-22 01:19:16 +00:00
|
|
|
if (obj && obj == inst) {
|
2013-05-13 20:22:24 +00:00
|
|
|
for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) {
|
2020-09-23 10:56:46 +00:00
|
|
|
qatomic_set(&obj->class->object_cast_cache[i - 1],
|
|
|
|
qatomic_read(&obj->class->object_cast_cache[i]));
|
2013-05-13 20:22:24 +00:00
|
|
|
}
|
2020-09-23 10:56:46 +00:00
|
|
|
qatomic_set(&obj->class->object_cast_cache[i - 1], typename);
|
2013-05-13 20:22:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
2013-05-10 12:16:40 +00:00
|
|
|
#endif
|
|
|
|
return obj;
|
2011-12-03 23:10:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ObjectClass *object_class_dynamic_cast(ObjectClass *class,
|
|
|
|
const char *typename)
|
|
|
|
{
|
2012-08-10 03:16:10 +00:00
|
|
|
ObjectClass *ret = NULL;
|
2013-05-10 12:16:36 +00:00
|
|
|
TypeImpl *target_type;
|
|
|
|
TypeImpl *type;
|
2011-12-03 23:10:08 +00:00
|
|
|
|
2013-05-10 12:16:36 +00:00
|
|
|
if (!class) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-05-10 12:16:37 +00:00
|
|
|
/* A simple fast path that can trigger a lot for leaf classes. */
|
2013-05-10 12:16:36 +00:00
|
|
|
type = class->type;
|
2013-05-10 12:16:37 +00:00
|
|
|
if (type->name == typename) {
|
|
|
|
return class;
|
|
|
|
}
|
|
|
|
|
2013-05-10 12:16:36 +00:00
|
|
|
target_type = type_get_by_name(typename);
|
2013-04-30 13:02:16 +00:00
|
|
|
if (!target_type) {
|
|
|
|
/* target class type unknown, so fail the cast */
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-02-19 04:02:10 +00:00
|
|
|
if (type->class->interfaces &&
|
|
|
|
type_is_ancestor(target_type, type_interface)) {
|
2012-08-10 03:16:10 +00:00
|
|
|
int found = 0;
|
|
|
|
GSList *i;
|
2011-12-03 23:10:08 +00:00
|
|
|
|
2012-08-10 03:16:10 +00:00
|
|
|
for (i = class->interfaces; i; i = i->next) {
|
|
|
|
ObjectClass *target_class = i->data;
|
|
|
|
|
|
|
|
if (type_is_ancestor(target_class->type, target_type)) {
|
|
|
|
ret = target_class;
|
|
|
|
found++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The match was ambiguous, don't allow a cast */
|
|
|
|
if (found > 1) {
|
|
|
|
ret = NULL;
|
|
|
|
}
|
|
|
|
} else if (type_is_ancestor(type, target_type)) {
|
|
|
|
ret = class;
|
2011-12-03 23:10:08 +00:00
|
|
|
}
|
|
|
|
|
2012-08-10 03:16:10 +00:00
|
|
|
return ret;
|
2011-12-03 23:10:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class,
|
2013-05-10 12:16:38 +00:00
|
|
|
const char *typename,
|
|
|
|
const char *file, int line,
|
|
|
|
const char *func)
|
2011-12-03 23:10:08 +00:00
|
|
|
{
|
2013-05-10 12:16:39 +00:00
|
|
|
ObjectClass *ret;
|
|
|
|
|
|
|
|
trace_object_class_dynamic_cast_assert(class ? class->type->name : "(null)",
|
|
|
|
typename, file, line, func);
|
2011-12-03 23:10:08 +00:00
|
|
|
|
2013-05-13 20:22:24 +00:00
|
|
|
#ifdef CONFIG_QOM_CAST_DEBUG
|
|
|
|
int i;
|
|
|
|
|
2013-06-18 09:18:59 +00:00
|
|
|
for (i = 0; class && i < OBJECT_CLASS_CAST_CACHE; i++) {
|
2020-09-23 10:56:46 +00:00
|
|
|
if (qatomic_read(&class->class_cast_cache[i]) == typename) {
|
2013-05-13 20:22:24 +00:00
|
|
|
ret = class;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
2013-06-18 09:18:59 +00:00
|
|
|
if (!class || !class->interfaces) {
|
2013-05-10 12:16:40 +00:00
|
|
|
return class;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-05-10 12:16:39 +00:00
|
|
|
ret = object_class_dynamic_cast(class, typename);
|
2013-05-10 12:16:36 +00:00
|
|
|
if (!ret && class) {
|
2013-05-10 12:16:38 +00:00
|
|
|
fprintf(stderr, "%s:%d:%s: Object %p is not an instance of type %s\n",
|
|
|
|
file, line, func, class, typename);
|
2011-12-03 23:10:08 +00:00
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
2013-05-13 20:22:24 +00:00
|
|
|
#ifdef CONFIG_QOM_CAST_DEBUG
|
2013-06-18 09:18:59 +00:00
|
|
|
if (class && ret == class) {
|
2013-05-13 20:22:24 +00:00
|
|
|
for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) {
|
2020-09-23 10:56:46 +00:00
|
|
|
qatomic_set(&class->class_cast_cache[i - 1],
|
|
|
|
qatomic_read(&class->class_cast_cache[i]));
|
2013-05-13 20:22:24 +00:00
|
|
|
}
|
2020-09-23 10:56:46 +00:00
|
|
|
qatomic_set(&class->class_cast_cache[i - 1], typename);
|
2013-05-13 20:22:24 +00:00
|
|
|
}
|
|
|
|
out:
|
|
|
|
#endif
|
2011-12-03 23:10:08 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-07-14 02:14:50 +00:00
|
|
|
const char *object_get_typename(const Object *obj)
|
2011-12-03 23:10:08 +00:00
|
|
|
{
|
|
|
|
return obj->class->type->name;
|
|
|
|
}
|
|
|
|
|
|
|
|
ObjectClass *object_get_class(Object *obj)
|
|
|
|
{
|
|
|
|
return obj->class;
|
|
|
|
}
|
|
|
|
|
2013-01-23 11:20:18 +00:00
|
|
|
bool object_class_is_abstract(ObjectClass *klass)
|
|
|
|
{
|
|
|
|
return klass->type->abstract;
|
|
|
|
}
|
|
|
|
|
2011-12-03 23:10:08 +00:00
|
|
|
const char *object_class_get_name(ObjectClass *klass)
|
|
|
|
{
|
|
|
|
return klass->type->name;
|
|
|
|
}
|
|
|
|
|
|
|
|
ObjectClass *object_class_by_name(const char *typename)
|
|
|
|
{
|
|
|
|
TypeImpl *type = type_get_by_name(typename);
|
|
|
|
|
|
|
|
if (!type) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-02-28 11:57:11 +00:00
|
|
|
type_initialize(type);
|
2011-12-03 23:10:08 +00:00
|
|
|
|
|
|
|
return type->class;
|
|
|
|
}
|
|
|
|
|
2020-06-24 13:10:37 +00:00
|
|
|
ObjectClass *module_object_class_by_name(const char *typename)
|
|
|
|
{
|
|
|
|
ObjectClass *oc;
|
|
|
|
|
|
|
|
oc = object_class_by_name(typename);
|
|
|
|
#ifdef CONFIG_MODULES
|
|
|
|
if (!oc) {
|
|
|
|
module_load_qom_one(typename);
|
|
|
|
oc = object_class_by_name(typename);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return oc;
|
|
|
|
}
|
|
|
|
|
2012-05-02 11:30:54 +00:00
|
|
|
ObjectClass *object_class_get_parent(ObjectClass *class)
|
|
|
|
{
|
|
|
|
TypeImpl *type = type_get_parent(class->type);
|
|
|
|
|
|
|
|
if (!type) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
type_initialize(type);
|
|
|
|
|
|
|
|
return type->class;
|
|
|
|
}
|
|
|
|
|
2011-12-03 23:10:08 +00:00
|
|
|
typedef struct OCFData
|
|
|
|
{
|
|
|
|
void (*fn)(ObjectClass *klass, void *opaque);
|
2011-12-22 20:11:53 +00:00
|
|
|
const char *implements_type;
|
|
|
|
bool include_abstract;
|
2011-12-03 23:10:08 +00:00
|
|
|
void *opaque;
|
|
|
|
} OCFData;
|
|
|
|
|
|
|
|
static void object_class_foreach_tramp(gpointer key, gpointer value,
|
|
|
|
gpointer opaque)
|
|
|
|
{
|
|
|
|
OCFData *data = opaque;
|
|
|
|
TypeImpl *type = value;
|
2011-12-22 20:11:53 +00:00
|
|
|
ObjectClass *k;
|
2011-12-03 23:10:08 +00:00
|
|
|
|
2012-02-28 11:57:11 +00:00
|
|
|
type_initialize(type);
|
2011-12-22 20:11:53 +00:00
|
|
|
k = type->class;
|
2011-12-03 23:10:08 +00:00
|
|
|
|
2011-12-22 20:11:53 +00:00
|
|
|
if (!data->include_abstract && type->abstract) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (data->implements_type &&
|
|
|
|
!object_class_dynamic_cast(k, data->implements_type)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
data->fn(k, data->opaque);
|
2011-12-03 23:10:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void object_class_foreach(void (*fn)(ObjectClass *klass, void *opaque),
|
2011-12-22 20:11:53 +00:00
|
|
|
const char *implements_type, bool include_abstract,
|
2011-12-03 23:10:08 +00:00
|
|
|
void *opaque)
|
|
|
|
{
|
2011-12-22 20:11:53 +00:00
|
|
|
OCFData data = { fn, implements_type, include_abstract, opaque };
|
2011-12-03 23:10:08 +00:00
|
|
|
|
2013-12-03 15:42:00 +00:00
|
|
|
enumerating_types = true;
|
2011-12-03 23:10:08 +00:00
|
|
|
g_hash_table_foreach(type_table_get(), object_class_foreach_tramp, &data);
|
2013-12-03 15:42:00 +00:00
|
|
|
enumerating_types = false;
|
2011-12-03 23:10:08 +00:00
|
|
|
}
|
2012-01-30 14:55:55 +00:00
|
|
|
|
2015-09-08 16:38:43 +00:00
|
|
|
static int do_object_child_foreach(Object *obj,
|
|
|
|
int (*fn)(Object *child, void *opaque),
|
|
|
|
void *opaque, bool recurse)
|
2012-04-11 21:30:20 +00:00
|
|
|
{
|
2015-10-13 12:37:45 +00:00
|
|
|
GHashTableIter iter;
|
|
|
|
ObjectProperty *prop;
|
2012-04-11 21:30:20 +00:00
|
|
|
int ret = 0;
|
|
|
|
|
2015-10-13 12:37:45 +00:00
|
|
|
g_hash_table_iter_init(&iter, obj->properties);
|
|
|
|
while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) {
|
2012-04-11 21:30:20 +00:00
|
|
|
if (object_property_is_child(prop)) {
|
2015-09-08 16:38:43 +00:00
|
|
|
Object *child = prop->opaque;
|
|
|
|
|
|
|
|
ret = fn(child, opaque);
|
2012-04-11 21:30:20 +00:00
|
|
|
if (ret != 0) {
|
|
|
|
break;
|
|
|
|
}
|
2015-09-08 16:38:43 +00:00
|
|
|
if (recurse) {
|
2020-04-04 15:33:40 +00:00
|
|
|
ret = do_object_child_foreach(child, fn, opaque, true);
|
|
|
|
if (ret != 0) {
|
|
|
|
break;
|
|
|
|
}
|
2015-09-08 16:38:43 +00:00
|
|
|
}
|
2012-04-11 21:30:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-09-08 16:38:43 +00:00
|
|
|
int object_child_foreach(Object *obj, int (*fn)(Object *child, void *opaque),
|
|
|
|
void *opaque)
|
|
|
|
{
|
|
|
|
return do_object_child_foreach(obj, fn, opaque, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
int object_child_foreach_recursive(Object *obj,
|
|
|
|
int (*fn)(Object *child, void *opaque),
|
|
|
|
void *opaque)
|
|
|
|
{
|
|
|
|
return do_object_child_foreach(obj, fn, opaque, true);
|
|
|
|
}
|
|
|
|
|
2012-02-25 22:07:34 +00:00
|
|
|
static void object_class_get_list_tramp(ObjectClass *klass, void *opaque)
|
|
|
|
{
|
|
|
|
GSList **list = opaque;
|
|
|
|
|
|
|
|
*list = g_slist_prepend(*list, klass);
|
|
|
|
}
|
|
|
|
|
|
|
|
GSList *object_class_get_list(const char *implements_type,
|
|
|
|
bool include_abstract)
|
|
|
|
{
|
|
|
|
GSList *list = NULL;
|
|
|
|
|
|
|
|
object_class_foreach(object_class_get_list_tramp,
|
|
|
|
implements_type, include_abstract, &list);
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2018-03-03 07:33:10 +00:00
|
|
|
static gint object_class_cmp(gconstpointer a, gconstpointer b)
|
|
|
|
{
|
|
|
|
return strcasecmp(object_class_get_name((ObjectClass *)a),
|
|
|
|
object_class_get_name((ObjectClass *)b));
|
|
|
|
}
|
|
|
|
|
|
|
|
GSList *object_class_get_list_sorted(const char *implements_type,
|
|
|
|
bool include_abstract)
|
|
|
|
{
|
|
|
|
return g_slist_sort(object_class_get_list(implements_type, include_abstract),
|
|
|
|
object_class_cmp);
|
|
|
|
}
|
|
|
|
|
2020-08-31 21:07:23 +00:00
|
|
|
Object *object_ref(void *objptr)
|
2012-01-30 14:55:55 +00:00
|
|
|
{
|
2020-08-31 21:07:23 +00:00
|
|
|
Object *obj = OBJECT(objptr);
|
2014-06-06 06:13:36 +00:00
|
|
|
if (!obj) {
|
2020-01-10 15:30:31 +00:00
|
|
|
return NULL;
|
2014-06-06 06:13:36 +00:00
|
|
|
}
|
2020-09-23 10:56:46 +00:00
|
|
|
qatomic_inc(&obj->ref);
|
2020-01-10 15:30:31 +00:00
|
|
|
return obj;
|
2012-01-30 14:55:55 +00:00
|
|
|
}
|
|
|
|
|
2020-08-31 21:07:23 +00:00
|
|
|
void object_unref(void *objptr)
|
2012-01-30 14:55:55 +00:00
|
|
|
{
|
2020-08-31 21:07:23 +00:00
|
|
|
Object *obj = OBJECT(objptr);
|
2014-06-06 06:13:36 +00:00
|
|
|
if (!obj) {
|
|
|
|
return;
|
|
|
|
}
|
2018-06-08 17:02:31 +00:00
|
|
|
g_assert(obj->ref > 0);
|
2012-01-30 14:55:55 +00:00
|
|
|
|
|
|
|
/* parent always holds a reference to its children */
|
2020-09-23 10:56:46 +00:00
|
|
|
if (qatomic_fetch_dec(&obj->ref) == 1) {
|
2012-01-30 14:55:55 +00:00
|
|
|
object_finalize(obj);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-29 19:34:22 +00:00
|
|
|
ObjectProperty *
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
object_property_try_add(Object *obj, const char *name, const char *type,
|
|
|
|
ObjectPropertyAccessor *get,
|
|
|
|
ObjectPropertyAccessor *set,
|
|
|
|
ObjectPropertyRelease *release,
|
|
|
|
void *opaque, Error **errp)
|
2012-01-30 14:55:55 +00:00
|
|
|
{
|
2013-03-25 13:15:13 +00:00
|
|
|
ObjectProperty *prop;
|
2014-08-20 06:55:52 +00:00
|
|
|
size_t name_len = strlen(name);
|
|
|
|
|
|
|
|
if (name_len >= 3 && !memcmp(name + name_len - 3, "[*]", 4)) {
|
|
|
|
int i;
|
2020-09-21 09:33:25 +00:00
|
|
|
ObjectProperty *ret = NULL;
|
2014-08-20 06:55:52 +00:00
|
|
|
char *name_no_array = g_strdup(name);
|
|
|
|
|
|
|
|
name_no_array[name_len - 3] = '\0';
|
2020-09-21 09:33:25 +00:00
|
|
|
for (i = 0; i < INT16_MAX; ++i) {
|
2014-08-20 06:55:52 +00:00
|
|
|
char *full_name = g_strdup_printf("%s[%d]", name_no_array, i);
|
|
|
|
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
ret = object_property_try_add(obj, full_name, type, get, set,
|
|
|
|
release, opaque, NULL);
|
2014-08-20 06:55:52 +00:00
|
|
|
g_free(full_name);
|
|
|
|
if (ret) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
g_free(name_no_array);
|
2020-09-21 09:33:25 +00:00
|
|
|
assert(ret);
|
2014-08-20 06:55:52 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2013-03-25 13:15:13 +00:00
|
|
|
|
2020-09-14 13:56:17 +00:00
|
|
|
if (object_property_find(obj, name) != NULL) {
|
2019-11-04 13:23:55 +00:00
|
|
|
error_setg(errp, "attempt to add duplicate property '%s' to object (type '%s')",
|
|
|
|
name, object_get_typename(obj));
|
2015-10-13 12:37:45 +00:00
|
|
|
return NULL;
|
2013-03-25 13:15:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
prop = g_malloc0(sizeof(*prop));
|
2012-01-30 14:55:55 +00:00
|
|
|
|
|
|
|
prop->name = g_strdup(name);
|
|
|
|
prop->type = g_strdup(type);
|
|
|
|
|
|
|
|
prop->get = get;
|
|
|
|
prop->set = set;
|
|
|
|
prop->release = release;
|
|
|
|
prop->opaque = opaque;
|
|
|
|
|
2015-10-13 12:37:45 +00:00
|
|
|
g_hash_table_insert(obj->properties, prop->name, prop);
|
2014-06-05 11:11:51 +00:00
|
|
|
return prop;
|
2012-01-30 14:55:55 +00:00
|
|
|
}
|
|
|
|
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
ObjectProperty *
|
|
|
|
object_property_add(Object *obj, const char *name, const char *type,
|
|
|
|
ObjectPropertyAccessor *get,
|
|
|
|
ObjectPropertyAccessor *set,
|
|
|
|
ObjectPropertyRelease *release,
|
|
|
|
void *opaque)
|
|
|
|
{
|
|
|
|
return object_property_try_add(obj, name, type, get, set, release,
|
|
|
|
opaque, &error_abort);
|
|
|
|
}
|
|
|
|
|
2015-10-13 12:37:46 +00:00
|
|
|
ObjectProperty *
|
|
|
|
object_class_property_add(ObjectClass *klass,
|
|
|
|
const char *name,
|
|
|
|
const char *type,
|
|
|
|
ObjectPropertyAccessor *get,
|
|
|
|
ObjectPropertyAccessor *set,
|
|
|
|
ObjectPropertyRelease *release,
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
void *opaque)
|
2015-10-13 12:37:46 +00:00
|
|
|
{
|
|
|
|
ObjectProperty *prop;
|
|
|
|
|
2020-09-14 13:56:17 +00:00
|
|
|
assert(!object_class_property_find(klass, name));
|
2015-10-13 12:37:46 +00:00
|
|
|
|
|
|
|
prop = g_malloc0(sizeof(*prop));
|
|
|
|
|
|
|
|
prop->name = g_strdup(name);
|
|
|
|
prop->type = g_strdup(type);
|
|
|
|
|
|
|
|
prop->get = get;
|
|
|
|
prop->set = set;
|
|
|
|
prop->release = release;
|
|
|
|
prop->opaque = opaque;
|
|
|
|
|
2020-01-10 15:30:18 +00:00
|
|
|
g_hash_table_insert(klass->properties, prop->name, prop);
|
2015-10-13 12:37:46 +00:00
|
|
|
|
|
|
|
return prop;
|
|
|
|
}
|
|
|
|
|
2020-09-14 13:56:17 +00:00
|
|
|
ObjectProperty *object_property_find(Object *obj, const char *name)
|
2012-01-30 14:55:55 +00:00
|
|
|
{
|
|
|
|
ObjectProperty *prop;
|
2015-10-13 12:37:46 +00:00
|
|
|
ObjectClass *klass = object_get_class(obj);
|
|
|
|
|
2020-09-14 13:56:17 +00:00
|
|
|
prop = object_class_property_find(klass, name);
|
2015-10-13 12:37:46 +00:00
|
|
|
if (prop) {
|
|
|
|
return prop;
|
|
|
|
}
|
2012-01-30 14:55:55 +00:00
|
|
|
|
2020-09-14 13:56:17 +00:00
|
|
|
return g_hash_table_lookup(obj->properties, name);
|
|
|
|
}
|
2012-01-30 14:55:55 +00:00
|
|
|
|
2020-09-14 13:56:17 +00:00
|
|
|
ObjectProperty *object_property_find_err(Object *obj, const char *name,
|
|
|
|
Error **errp)
|
|
|
|
{
|
|
|
|
ObjectProperty *prop = object_property_find(obj, name);
|
|
|
|
if (!prop) {
|
2020-09-20 15:53:40 +00:00
|
|
|
error_setg(errp, "Property '%s.%s' not found",
|
|
|
|
object_get_typename(obj), name);
|
2020-09-14 13:56:17 +00:00
|
|
|
}
|
|
|
|
return prop;
|
2012-01-30 14:55:55 +00:00
|
|
|
}
|
|
|
|
|
2015-12-09 12:34:02 +00:00
|
|
|
void object_property_iter_init(ObjectPropertyIterator *iter,
|
|
|
|
Object *obj)
|
2015-10-13 12:37:40 +00:00
|
|
|
{
|
2015-12-09 12:34:02 +00:00
|
|
|
g_hash_table_iter_init(&iter->iter, obj->properties);
|
|
|
|
iter->nextclass = object_get_class(obj);
|
2015-10-13 12:37:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ObjectProperty *object_property_iter_next(ObjectPropertyIterator *iter)
|
|
|
|
{
|
2015-10-13 12:37:45 +00:00
|
|
|
gpointer key, val;
|
2015-10-13 12:37:46 +00:00
|
|
|
while (!g_hash_table_iter_next(&iter->iter, &key, &val)) {
|
|
|
|
if (!iter->nextclass) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
g_hash_table_iter_init(&iter->iter, iter->nextclass->properties);
|
|
|
|
iter->nextclass = object_class_get_parent(iter->nextclass);
|
2015-10-13 12:37:40 +00:00
|
|
|
}
|
2015-10-13 12:37:45 +00:00
|
|
|
return val;
|
2015-10-13 12:37:40 +00:00
|
|
|
}
|
|
|
|
|
2018-03-01 13:09:39 +00:00
|
|
|
void object_class_property_iter_init(ObjectPropertyIterator *iter,
|
|
|
|
ObjectClass *klass)
|
|
|
|
{
|
|
|
|
g_hash_table_iter_init(&iter->iter, klass->properties);
|
2018-09-06 13:37:36 +00:00
|
|
|
iter->nextclass = object_class_get_parent(klass);
|
2018-03-01 13:09:39 +00:00
|
|
|
}
|
|
|
|
|
2020-09-14 13:56:17 +00:00
|
|
|
ObjectProperty *object_class_property_find(ObjectClass *klass, const char *name)
|
2015-10-13 12:37:46 +00:00
|
|
|
{
|
|
|
|
ObjectClass *parent_klass;
|
|
|
|
|
|
|
|
parent_klass = object_class_get_parent(klass);
|
|
|
|
if (parent_klass) {
|
2020-09-14 13:56:17 +00:00
|
|
|
ObjectProperty *prop =
|
|
|
|
object_class_property_find(parent_klass, name);
|
2015-10-13 12:37:46 +00:00
|
|
|
if (prop) {
|
|
|
|
return prop;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-14 13:56:17 +00:00
|
|
|
return g_hash_table_lookup(klass->properties, name);
|
|
|
|
}
|
|
|
|
|
|
|
|
ObjectProperty *object_class_property_find_err(ObjectClass *klass,
|
|
|
|
const char *name,
|
|
|
|
Error **errp)
|
|
|
|
{
|
|
|
|
ObjectProperty *prop = object_class_property_find(klass, name);
|
2015-10-13 12:37:46 +00:00
|
|
|
if (!prop) {
|
|
|
|
error_setg(errp, "Property '.%s' not found", name);
|
|
|
|
}
|
|
|
|
return prop;
|
|
|
|
}
|
|
|
|
|
2020-09-14 13:56:17 +00:00
|
|
|
|
2020-05-05 15:29:26 +00:00
|
|
|
void object_property_del(Object *obj, const char *name)
|
2012-01-30 14:55:55 +00:00
|
|
|
{
|
2015-10-13 12:37:45 +00:00
|
|
|
ObjectProperty *prop = g_hash_table_lookup(obj->properties, name);
|
|
|
|
|
2011-12-23 21:34:39 +00:00
|
|
|
if (prop->release) {
|
|
|
|
prop->release(obj, name, prop->opaque);
|
|
|
|
}
|
2015-10-13 12:37:45 +00:00
|
|
|
g_hash_table_remove(obj->properties, name);
|
2012-01-30 14:55:55 +00:00
|
|
|
}
|
|
|
|
|
2020-07-07 16:05:55 +00:00
|
|
|
bool object_property_get(Object *obj, const char *name, Visitor *v,
|
2012-01-30 14:55:55 +00:00
|
|
|
Error **errp)
|
|
|
|
{
|
2020-07-07 16:05:55 +00:00
|
|
|
Error *err = NULL;
|
2020-09-14 13:56:17 +00:00
|
|
|
ObjectProperty *prop = object_property_find_err(obj, name, errp);
|
2020-07-07 16:05:55 +00:00
|
|
|
|
2012-01-30 14:55:55 +00:00
|
|
|
if (prop == NULL) {
|
2020-07-07 16:05:55 +00:00
|
|
|
return false;
|
2012-01-30 14:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!prop->get) {
|
2015-03-17 10:54:50 +00:00
|
|
|
error_setg(errp, QERR_PERMISSION_DENIED);
|
2020-07-07 16:05:55 +00:00
|
|
|
return false;
|
2012-01-30 14:55:55 +00:00
|
|
|
}
|
2020-07-07 16:05:55 +00:00
|
|
|
prop->get(obj, v, name, prop->opaque, &err);
|
|
|
|
error_propagate(errp, err);
|
|
|
|
return !err;
|
2012-01-30 14:55:55 +00:00
|
|
|
}
|
|
|
|
|
2020-07-07 16:05:55 +00:00
|
|
|
bool object_property_set(Object *obj, const char *name, Visitor *v,
|
2012-01-30 14:55:55 +00:00
|
|
|
Error **errp)
|
|
|
|
{
|
2020-07-07 16:05:55 +00:00
|
|
|
Error *err = NULL;
|
2020-09-14 13:56:17 +00:00
|
|
|
ObjectProperty *prop = object_property_find_err(obj, name, errp);
|
2020-07-07 16:05:55 +00:00
|
|
|
|
2012-01-30 14:55:55 +00:00
|
|
|
if (prop == NULL) {
|
2020-07-07 16:05:55 +00:00
|
|
|
return false;
|
2012-01-30 14:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!prop->set) {
|
2015-03-17 10:54:50 +00:00
|
|
|
error_setg(errp, QERR_PERMISSION_DENIED);
|
2020-07-07 16:05:55 +00:00
|
|
|
return false;
|
2012-01-30 14:55:55 +00:00
|
|
|
}
|
2020-07-07 16:05:55 +00:00
|
|
|
prop->set(obj, v, name, prop->opaque, &err);
|
|
|
|
error_propagate(errp, err);
|
|
|
|
return !err;
|
2012-01-30 14:55:55 +00:00
|
|
|
}
|
|
|
|
|
2020-07-07 16:05:55 +00:00
|
|
|
bool object_property_set_str(Object *obj, const char *name,
|
qom: Put name parameter before value / visitor parameter
The object_property_set_FOO() setters take property name and value in
an unusual order:
void object_property_set_FOO(Object *obj, FOO_TYPE value,
const char *name, Error **errp)
Having to pass value before name feels grating. Swap them.
Same for object_property_set(), object_property_get(), and
object_property_parse().
Convert callers with this Coccinelle script:
@@
identifier fun = {
object_property_get, object_property_parse, object_property_set_str,
object_property_set_link, object_property_set_bool,
object_property_set_int, object_property_set_uint, object_property_set,
object_property_set_qobject
};
expression obj, v, name, errp;
@@
- fun(obj, v, name, errp)
+ fun(obj, name, v, errp)
Chokes on hw/arm/musicpal.c's lcd_refresh() with the unhelpful error
message "no position information". Convert that one manually.
Fails to convert hw/arm/armsse.c, because Coccinelle gets confused by
ARMSSE being used both as typedef and function-like macro there.
Convert manually.
Fails to convert hw/rx/rx-gdbsim.c, because Coccinelle gets confused
by RXCPU being used both as typedef and function-like macro there.
Convert manually. The other files using RXCPU that way don't need
conversion.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-Id: <20200707160613.848843-27-armbru@redhat.com>
[Straightforwad conflict with commit 2336172d9b "audio: set default
value for pcspk.iobase property" resolved]
2020-07-07 16:05:54 +00:00
|
|
|
const char *value, Error **errp)
|
2012-02-01 16:16:22 +00:00
|
|
|
{
|
|
|
|
QString *qstr = qstring_from_str(value);
|
2020-07-07 16:05:55 +00:00
|
|
|
bool ok = object_property_set_qobject(obj, name, QOBJECT(qstr), errp);
|
2012-02-01 16:16:22 +00:00
|
|
|
|
2018-04-19 15:01:43 +00:00
|
|
|
qobject_unref(qstr);
|
2020-07-07 16:05:55 +00:00
|
|
|
return ok;
|
2012-02-01 16:16:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
char *object_property_get_str(Object *obj, const char *name,
|
|
|
|
Error **errp)
|
|
|
|
{
|
|
|
|
QObject *ret = object_property_get_qobject(obj, name, errp);
|
2020-12-11 17:11:43 +00:00
|
|
|
QString *qstring;
|
2012-02-01 16:16:22 +00:00
|
|
|
char *retval;
|
|
|
|
|
|
|
|
if (!ret) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2020-12-11 17:11:43 +00:00
|
|
|
qstring = qobject_to(QString, ret);
|
|
|
|
if (!qstring) {
|
2015-03-17 10:54:50 +00:00
|
|
|
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "string");
|
2020-12-11 17:11:43 +00:00
|
|
|
retval = NULL;
|
|
|
|
} else {
|
|
|
|
retval = g_strdup(qstring_get_str(qstring));
|
2012-02-01 16:16:22 +00:00
|
|
|
}
|
|
|
|
|
2018-04-19 15:01:43 +00:00
|
|
|
qobject_unref(ret);
|
2012-02-01 16:16:22 +00:00
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2020-07-07 16:05:55 +00:00
|
|
|
bool object_property_set_link(Object *obj, const char *name,
|
qom: Put name parameter before value / visitor parameter
The object_property_set_FOO() setters take property name and value in
an unusual order:
void object_property_set_FOO(Object *obj, FOO_TYPE value,
const char *name, Error **errp)
Having to pass value before name feels grating. Swap them.
Same for object_property_set(), object_property_get(), and
object_property_parse().
Convert callers with this Coccinelle script:
@@
identifier fun = {
object_property_get, object_property_parse, object_property_set_str,
object_property_set_link, object_property_set_bool,
object_property_set_int, object_property_set_uint, object_property_set,
object_property_set_qobject
};
expression obj, v, name, errp;
@@
- fun(obj, v, name, errp)
+ fun(obj, name, v, errp)
Chokes on hw/arm/musicpal.c's lcd_refresh() with the unhelpful error
message "no position information". Convert that one manually.
Fails to convert hw/arm/armsse.c, because Coccinelle gets confused by
ARMSSE being used both as typedef and function-like macro there.
Convert manually.
Fails to convert hw/rx/rx-gdbsim.c, because Coccinelle gets confused
by RXCPU being used both as typedef and function-like macro there.
Convert manually. The other files using RXCPU that way don't need
conversion.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-Id: <20200707160613.848843-27-armbru@redhat.com>
[Straightforwad conflict with commit 2336172d9b "audio: set default
value for pcspk.iobase property" resolved]
2020-07-07 16:05:54 +00:00
|
|
|
Object *value, Error **errp)
|
2012-02-02 09:51:57 +00:00
|
|
|
{
|
2020-07-07 16:05:55 +00:00
|
|
|
g_autofree char *path = NULL;
|
|
|
|
|
2014-09-26 05:19:19 +00:00
|
|
|
if (value) {
|
2020-07-07 16:05:55 +00:00
|
|
|
path = object_get_canonical_path(value);
|
2014-09-26 05:19:19 +00:00
|
|
|
}
|
2020-07-07 16:05:55 +00:00
|
|
|
return object_property_set_str(obj, name, path ?: "", errp);
|
2012-02-02 09:51:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Object *object_property_get_link(Object *obj, const char *name,
|
|
|
|
Error **errp)
|
|
|
|
{
|
|
|
|
char *str = object_property_get_str(obj, name, errp);
|
|
|
|
Object *target = NULL;
|
|
|
|
|
|
|
|
if (str && *str) {
|
|
|
|
target = object_resolve_path(str, NULL);
|
|
|
|
if (!target) {
|
2015-03-16 07:57:47 +00:00
|
|
|
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
|
|
|
|
"Device '%s' not found", str);
|
2012-02-02 09:51:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free(str);
|
|
|
|
return target;
|
|
|
|
}
|
|
|
|
|
2020-07-07 16:05:55 +00:00
|
|
|
bool object_property_set_bool(Object *obj, const char *name,
|
qom: Put name parameter before value / visitor parameter
The object_property_set_FOO() setters take property name and value in
an unusual order:
void object_property_set_FOO(Object *obj, FOO_TYPE value,
const char *name, Error **errp)
Having to pass value before name feels grating. Swap them.
Same for object_property_set(), object_property_get(), and
object_property_parse().
Convert callers with this Coccinelle script:
@@
identifier fun = {
object_property_get, object_property_parse, object_property_set_str,
object_property_set_link, object_property_set_bool,
object_property_set_int, object_property_set_uint, object_property_set,
object_property_set_qobject
};
expression obj, v, name, errp;
@@
- fun(obj, v, name, errp)
+ fun(obj, name, v, errp)
Chokes on hw/arm/musicpal.c's lcd_refresh() with the unhelpful error
message "no position information". Convert that one manually.
Fails to convert hw/arm/armsse.c, because Coccinelle gets confused by
ARMSSE being used both as typedef and function-like macro there.
Convert manually.
Fails to convert hw/rx/rx-gdbsim.c, because Coccinelle gets confused
by RXCPU being used both as typedef and function-like macro there.
Convert manually. The other files using RXCPU that way don't need
conversion.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-Id: <20200707160613.848843-27-armbru@redhat.com>
[Straightforwad conflict with commit 2336172d9b "audio: set default
value for pcspk.iobase property" resolved]
2020-07-07 16:05:54 +00:00
|
|
|
bool value, Error **errp)
|
2012-02-01 16:16:22 +00:00
|
|
|
{
|
2015-05-15 22:24:59 +00:00
|
|
|
QBool *qbool = qbool_from_bool(value);
|
2020-07-07 16:05:55 +00:00
|
|
|
bool ok = object_property_set_qobject(obj, name, QOBJECT(qbool), errp);
|
2012-02-01 16:16:22 +00:00
|
|
|
|
2018-04-19 15:01:43 +00:00
|
|
|
qobject_unref(qbool);
|
2020-07-07 16:05:55 +00:00
|
|
|
return ok;
|
2012-02-01 16:16:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool object_property_get_bool(Object *obj, const char *name,
|
|
|
|
Error **errp)
|
|
|
|
{
|
|
|
|
QObject *ret = object_property_get_qobject(obj, name, errp);
|
|
|
|
QBool *qbool;
|
|
|
|
bool retval;
|
|
|
|
|
|
|
|
if (!ret) {
|
|
|
|
return false;
|
|
|
|
}
|
2018-02-24 15:40:29 +00:00
|
|
|
qbool = qobject_to(QBool, ret);
|
2012-02-01 16:16:22 +00:00
|
|
|
if (!qbool) {
|
2015-03-17 10:54:50 +00:00
|
|
|
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "boolean");
|
2012-02-01 16:16:22 +00:00
|
|
|
retval = false;
|
|
|
|
} else {
|
2015-05-15 22:24:59 +00:00
|
|
|
retval = qbool_get_bool(qbool);
|
2012-02-01 16:16:22 +00:00
|
|
|
}
|
|
|
|
|
2018-04-19 15:01:43 +00:00
|
|
|
qobject_unref(ret);
|
2012-02-01 16:16:22 +00:00
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2020-07-07 16:05:55 +00:00
|
|
|
bool object_property_set_int(Object *obj, const char *name,
|
qom: Put name parameter before value / visitor parameter
The object_property_set_FOO() setters take property name and value in
an unusual order:
void object_property_set_FOO(Object *obj, FOO_TYPE value,
const char *name, Error **errp)
Having to pass value before name feels grating. Swap them.
Same for object_property_set(), object_property_get(), and
object_property_parse().
Convert callers with this Coccinelle script:
@@
identifier fun = {
object_property_get, object_property_parse, object_property_set_str,
object_property_set_link, object_property_set_bool,
object_property_set_int, object_property_set_uint, object_property_set,
object_property_set_qobject
};
expression obj, v, name, errp;
@@
- fun(obj, v, name, errp)
+ fun(obj, name, v, errp)
Chokes on hw/arm/musicpal.c's lcd_refresh() with the unhelpful error
message "no position information". Convert that one manually.
Fails to convert hw/arm/armsse.c, because Coccinelle gets confused by
ARMSSE being used both as typedef and function-like macro there.
Convert manually.
Fails to convert hw/rx/rx-gdbsim.c, because Coccinelle gets confused
by RXCPU being used both as typedef and function-like macro there.
Convert manually. The other files using RXCPU that way don't need
conversion.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-Id: <20200707160613.848843-27-armbru@redhat.com>
[Straightforwad conflict with commit 2336172d9b "audio: set default
value for pcspk.iobase property" resolved]
2020-07-07 16:05:54 +00:00
|
|
|
int64_t value, Error **errp)
|
2012-02-01 16:16:22 +00:00
|
|
|
{
|
2017-06-07 16:35:58 +00:00
|
|
|
QNum *qnum = qnum_from_int(value);
|
2020-07-07 16:05:55 +00:00
|
|
|
bool ok = object_property_set_qobject(obj, name, QOBJECT(qnum), errp);
|
2012-02-01 16:16:22 +00:00
|
|
|
|
2018-04-19 15:01:43 +00:00
|
|
|
qobject_unref(qnum);
|
2020-07-07 16:05:55 +00:00
|
|
|
return ok;
|
2012-02-01 16:16:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int64_t object_property_get_int(Object *obj, const char *name,
|
|
|
|
Error **errp)
|
|
|
|
{
|
|
|
|
QObject *ret = object_property_get_qobject(obj, name, errp);
|
2017-06-07 16:35:58 +00:00
|
|
|
QNum *qnum;
|
2012-02-01 16:16:22 +00:00
|
|
|
int64_t retval;
|
|
|
|
|
|
|
|
if (!ret) {
|
|
|
|
return -1;
|
|
|
|
}
|
2017-06-07 16:35:58 +00:00
|
|
|
|
2018-02-24 15:40:29 +00:00
|
|
|
qnum = qobject_to(QNum, ret);
|
2017-06-07 16:35:58 +00:00
|
|
|
if (!qnum || !qnum_get_try_int(qnum, &retval)) {
|
2015-03-17 10:54:50 +00:00
|
|
|
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "int");
|
2012-02-01 16:16:22 +00:00
|
|
|
retval = -1;
|
|
|
|
}
|
|
|
|
|
2018-04-19 15:01:43 +00:00
|
|
|
qobject_unref(ret);
|
2012-02-01 16:16:22 +00:00
|
|
|
return retval;
|
2012-02-09 08:52:59 +00:00
|
|
|
}
|
|
|
|
|
2020-01-10 15:30:23 +00:00
|
|
|
static void object_property_init_defval(Object *obj, ObjectProperty *prop)
|
|
|
|
{
|
|
|
|
Visitor *v = qobject_input_visitor_new(prop->defval);
|
|
|
|
|
|
|
|
assert(prop->set != NULL);
|
|
|
|
prop->set(obj, v, prop->name, prop->opaque, &error_abort);
|
|
|
|
|
|
|
|
visit_free(v);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void object_property_set_default(ObjectProperty *prop, QObject *defval)
|
|
|
|
{
|
|
|
|
assert(!prop->defval);
|
|
|
|
assert(!prop->init);
|
|
|
|
|
|
|
|
prop->defval = defval;
|
|
|
|
prop->init = object_property_init_defval;
|
|
|
|
}
|
|
|
|
|
|
|
|
void object_property_set_default_bool(ObjectProperty *prop, bool value)
|
|
|
|
{
|
|
|
|
object_property_set_default(prop, QOBJECT(qbool_from_bool(value)));
|
|
|
|
}
|
|
|
|
|
|
|
|
void object_property_set_default_str(ObjectProperty *prop, const char *value)
|
|
|
|
{
|
|
|
|
object_property_set_default(prop, QOBJECT(qstring_from_str(value)));
|
|
|
|
}
|
|
|
|
|
|
|
|
void object_property_set_default_int(ObjectProperty *prop, int64_t value)
|
|
|
|
{
|
|
|
|
object_property_set_default(prop, QOBJECT(qnum_from_int(value)));
|
|
|
|
}
|
|
|
|
|
|
|
|
void object_property_set_default_uint(ObjectProperty *prop, uint64_t value)
|
|
|
|
{
|
|
|
|
object_property_set_default(prop, QOBJECT(qnum_from_uint(value)));
|
|
|
|
}
|
|
|
|
|
2020-07-07 16:05:55 +00:00
|
|
|
bool object_property_set_uint(Object *obj, const char *name,
|
qom: Put name parameter before value / visitor parameter
The object_property_set_FOO() setters take property name and value in
an unusual order:
void object_property_set_FOO(Object *obj, FOO_TYPE value,
const char *name, Error **errp)
Having to pass value before name feels grating. Swap them.
Same for object_property_set(), object_property_get(), and
object_property_parse().
Convert callers with this Coccinelle script:
@@
identifier fun = {
object_property_get, object_property_parse, object_property_set_str,
object_property_set_link, object_property_set_bool,
object_property_set_int, object_property_set_uint, object_property_set,
object_property_set_qobject
};
expression obj, v, name, errp;
@@
- fun(obj, v, name, errp)
+ fun(obj, name, v, errp)
Chokes on hw/arm/musicpal.c's lcd_refresh() with the unhelpful error
message "no position information". Convert that one manually.
Fails to convert hw/arm/armsse.c, because Coccinelle gets confused by
ARMSSE being used both as typedef and function-like macro there.
Convert manually.
Fails to convert hw/rx/rx-gdbsim.c, because Coccinelle gets confused
by RXCPU being used both as typedef and function-like macro there.
Convert manually. The other files using RXCPU that way don't need
conversion.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-Id: <20200707160613.848843-27-armbru@redhat.com>
[Straightforwad conflict with commit 2336172d9b "audio: set default
value for pcspk.iobase property" resolved]
2020-07-07 16:05:54 +00:00
|
|
|
uint64_t value, Error **errp)
|
2017-06-07 16:36:04 +00:00
|
|
|
{
|
|
|
|
QNum *qnum = qnum_from_uint(value);
|
2020-07-07 16:05:55 +00:00
|
|
|
bool ok = object_property_set_qobject(obj, name, QOBJECT(qnum), errp);
|
2017-06-07 16:36:04 +00:00
|
|
|
|
2018-04-19 15:01:43 +00:00
|
|
|
qobject_unref(qnum);
|
2020-07-07 16:05:55 +00:00
|
|
|
return ok;
|
2017-06-07 16:36:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t object_property_get_uint(Object *obj, const char *name,
|
|
|
|
Error **errp)
|
|
|
|
{
|
|
|
|
QObject *ret = object_property_get_qobject(obj, name, errp);
|
|
|
|
QNum *qnum;
|
|
|
|
uint64_t retval;
|
|
|
|
|
|
|
|
if (!ret) {
|
|
|
|
return 0;
|
|
|
|
}
|
2018-02-24 15:40:29 +00:00
|
|
|
qnum = qobject_to(QNum, ret);
|
2017-06-07 16:36:04 +00:00
|
|
|
if (!qnum || !qnum_get_try_uint(qnum, &retval)) {
|
|
|
|
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, "uint");
|
|
|
|
retval = 0;
|
|
|
|
}
|
|
|
|
|
2018-04-19 15:01:43 +00:00
|
|
|
qobject_unref(ret);
|
2017-06-07 16:36:04 +00:00
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
qom: Add an object_property_add_enum() helper function
A QOM property can be parsed as enum using the visit_type_enum()
helper function, but this forces callers to use the more complex
generic object_property_add() method when registering it. It
also requires that users of that object have access to the
string map when they want to read the property value.
This patch introduces a specialized object_property_add_enum()
method which simplifies the use of enum properties, so the
setters/getters directly get passed the int value.
typedef enum {
MYDEV_TYPE_FROG,
MYDEV_TYPE_ALLIGATOR,
MYDEV_TYPE_PLATYPUS,
MYDEV_TYPE_LAST
} MyDevType;
Then provide a table of enum <-> string mappings
static const char *const mydevtypemap[MYDEV_TYPE_LAST + 1] = {
[MYDEV_TYPE_FROG] = "frog",
[MYDEV_TYPE_ALLIGATOR] = "alligator",
[MYDEV_TYPE_PLATYPUS] = "platypus",
[MYDEV_TYPE_LAST] = NULL,
};
Assuming an object struct of
typedef struct {
Object parent_obj;
MyDevType devtype;
...other fields...
} MyDev;
The property can then be registered as follows:
static int mydev_prop_get_devtype(Object *obj,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
return dev->devtype;
}
static void mydev_prop_set_devtype(Object *obj,
int value,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
dev->devtype = value;
}
object_property_add_enum(obj, "devtype",
mydevtypemap, "MyDevType",
mydev_prop_get_devtype,
mydev_prop_set_devtype,
NULL);
Note there is no need to check the range of 'value' in
the setter, because the string->enum conversion code will
have already done that and reported an error as required.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 16:14:08 +00:00
|
|
|
typedef struct EnumProperty {
|
2017-08-24 08:46:10 +00:00
|
|
|
const QEnumLookup *lookup;
|
qom: Add an object_property_add_enum() helper function
A QOM property can be parsed as enum using the visit_type_enum()
helper function, but this forces callers to use the more complex
generic object_property_add() method when registering it. It
also requires that users of that object have access to the
string map when they want to read the property value.
This patch introduces a specialized object_property_add_enum()
method which simplifies the use of enum properties, so the
setters/getters directly get passed the int value.
typedef enum {
MYDEV_TYPE_FROG,
MYDEV_TYPE_ALLIGATOR,
MYDEV_TYPE_PLATYPUS,
MYDEV_TYPE_LAST
} MyDevType;
Then provide a table of enum <-> string mappings
static const char *const mydevtypemap[MYDEV_TYPE_LAST + 1] = {
[MYDEV_TYPE_FROG] = "frog",
[MYDEV_TYPE_ALLIGATOR] = "alligator",
[MYDEV_TYPE_PLATYPUS] = "platypus",
[MYDEV_TYPE_LAST] = NULL,
};
Assuming an object struct of
typedef struct {
Object parent_obj;
MyDevType devtype;
...other fields...
} MyDev;
The property can then be registered as follows:
static int mydev_prop_get_devtype(Object *obj,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
return dev->devtype;
}
static void mydev_prop_set_devtype(Object *obj,
int value,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
dev->devtype = value;
}
object_property_add_enum(obj, "devtype",
mydevtypemap, "MyDevType",
mydev_prop_get_devtype,
mydev_prop_set_devtype,
NULL);
Note there is no need to check the range of 'value' in
the setter, because the string->enum conversion code will
have already done that and reported an error as required.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 16:14:08 +00:00
|
|
|
int (*get)(Object *, Error **);
|
|
|
|
void (*set)(Object *, int, Error **);
|
|
|
|
} EnumProperty;
|
|
|
|
|
2014-05-14 09:43:33 +00:00
|
|
|
int object_property_get_enum(Object *obj, const char *name,
|
2015-05-27 15:07:56 +00:00
|
|
|
const char *typename, Error **errp)
|
2014-05-14 09:43:33 +00:00
|
|
|
{
|
2014-08-18 06:46:34 +00:00
|
|
|
char *str;
|
2014-05-14 09:43:33 +00:00
|
|
|
int ret;
|
2020-09-14 13:56:17 +00:00
|
|
|
ObjectProperty *prop = object_property_find_err(obj, name, errp);
|
2015-05-27 15:07:56 +00:00
|
|
|
EnumProperty *enumprop;
|
|
|
|
|
|
|
|
if (prop == NULL) {
|
2020-09-17 12:55:39 +00:00
|
|
|
return -1;
|
2015-05-27 15:07:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!g_str_equal(prop->type, typename)) {
|
|
|
|
error_setg(errp, "Property %s on %s is not '%s' enum type",
|
|
|
|
name, object_class_get_name(
|
|
|
|
object_get_class(obj)), typename);
|
2020-09-17 12:55:39 +00:00
|
|
|
return -1;
|
2015-05-27 15:07:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
enumprop = prop->opaque;
|
2014-05-14 09:43:33 +00:00
|
|
|
|
2020-05-05 15:29:12 +00:00
|
|
|
str = object_property_get_str(obj, name, errp);
|
|
|
|
if (!str) {
|
2020-09-17 12:55:39 +00:00
|
|
|
return -1;
|
2015-08-25 18:00:45 +00:00
|
|
|
}
|
2014-08-18 06:46:34 +00:00
|
|
|
|
2020-04-24 08:43:36 +00:00
|
|
|
ret = qapi_enum_parse(enumprop->lookup, str, -1, errp);
|
2014-08-18 06:46:34 +00:00
|
|
|
g_free(str);
|
2014-05-14 09:43:33 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2020-07-07 16:05:55 +00:00
|
|
|
bool object_property_parse(Object *obj, const char *name,
|
qom: Put name parameter before value / visitor parameter
The object_property_set_FOO() setters take property name and value in
an unusual order:
void object_property_set_FOO(Object *obj, FOO_TYPE value,
const char *name, Error **errp)
Having to pass value before name feels grating. Swap them.
Same for object_property_set(), object_property_get(), and
object_property_parse().
Convert callers with this Coccinelle script:
@@
identifier fun = {
object_property_get, object_property_parse, object_property_set_str,
object_property_set_link, object_property_set_bool,
object_property_set_int, object_property_set_uint, object_property_set,
object_property_set_qobject
};
expression obj, v, name, errp;
@@
- fun(obj, v, name, errp)
+ fun(obj, name, v, errp)
Chokes on hw/arm/musicpal.c's lcd_refresh() with the unhelpful error
message "no position information". Convert that one manually.
Fails to convert hw/arm/armsse.c, because Coccinelle gets confused by
ARMSSE being used both as typedef and function-like macro there.
Convert manually.
Fails to convert hw/rx/rx-gdbsim.c, because Coccinelle gets confused
by RXCPU being used both as typedef and function-like macro there.
Convert manually. The other files using RXCPU that way don't need
conversion.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-Id: <20200707160613.848843-27-armbru@redhat.com>
[Straightforwad conflict with commit 2336172d9b "audio: set default
value for pcspk.iobase property" resolved]
2020-07-07 16:05:54 +00:00
|
|
|
const char *string, Error **errp)
|
2012-02-09 08:52:59 +00:00
|
|
|
{
|
2016-06-09 16:48:37 +00:00
|
|
|
Visitor *v = string_input_visitor_new(string);
|
2020-07-07 16:05:55 +00:00
|
|
|
bool ok = object_property_set(obj, name, v, errp);
|
|
|
|
|
2016-06-09 16:48:37 +00:00
|
|
|
visit_free(v);
|
2020-07-07 16:05:55 +00:00
|
|
|
return ok;
|
2012-02-09 08:52:59 +00:00
|
|
|
}
|
|
|
|
|
2014-02-08 10:01:50 +00:00
|
|
|
char *object_property_print(Object *obj, const char *name, bool human,
|
2012-02-09 08:52:59 +00:00
|
|
|
Error **errp)
|
|
|
|
{
|
qapi: Add new visit_complete() function
Making each output visitor provide its own output collection
function was the only remaining reason for exposing visitor
sub-types to the rest of the code base. Add a polymorphic
visit_complete() function which is a no-op for input visitors,
and which populates an opaque pointer for output visitors. For
maximum type-safety, also add a parameter to the output visitor
constructors with a type-correct version of the output pointer,
and assert that the two uses match.
This approach was considered superior to either passing the
output parameter only during construction (action at a distance
during visit_free() feels awkward) or only during visit_complete()
(defeating type safety makes it easier to use incorrectly).
Most callers were function-local, and therefore a mechanical
conversion; the testsuite was a bit trickier, but the previous
cleanup patch minimized the churn here.
The visit_complete() function may be called at most once; doing
so lets us use transfer semantics rather than duplication or
ref-count semantics to get the just-built output back to the
caller, even though it means our behavior is not idempotent.
Generated code is simplified as follows for events:
|@@ -26,7 +26,7 @@ void qapi_event_send_acpi_device_ost(ACP
| QDict *qmp;
| Error *err = NULL;
| QMPEventFuncEmit emit;
|- QmpOutputVisitor *qov;
|+ QObject *obj;
| Visitor *v;
| q_obj_ACPI_DEVICE_OST_arg param = {
| info
|@@ -39,8 +39,7 @@ void qapi_event_send_acpi_device_ost(ACP
|
| qmp = qmp_event_build_dict("ACPI_DEVICE_OST");
|
|- qov = qmp_output_visitor_new();
|- v = qmp_output_get_visitor(qov);
|+ v = qmp_output_visitor_new(&obj);
|
| visit_start_struct(v, "ACPI_DEVICE_OST", NULL, 0, &err);
| if (err) {
|@@ -55,7 +54,8 @@ void qapi_event_send_acpi_device_ost(ACP
| goto out;
| }
|
|- qdict_put_obj(qmp, "data", qmp_output_get_qobject(qov));
|+ visit_complete(v, &obj);
|+ qdict_put_obj(qmp, "data", obj);
| emit(QAPI_EVENT_ACPI_DEVICE_OST, qmp, &err);
and for commands:
| {
| Error *err = NULL;
|- QmpOutputVisitor *qov = qmp_output_visitor_new();
| Visitor *v;
|
|- v = qmp_output_get_visitor(qov);
|+ v = qmp_output_visitor_new(ret_out);
| visit_type_AddfdInfo(v, "unused", &ret_in, &err);
|- if (err) {
|- goto out;
|+ if (!err) {
|+ visit_complete(v, ret_out);
| }
|- *ret_out = qmp_output_get_qobject(qov);
|-
|-out:
| error_propagate(errp, err);
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1465490926-28625-13-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-06-09 16:48:43 +00:00
|
|
|
Visitor *v;
|
2014-09-27 05:13:55 +00:00
|
|
|
char *string = NULL;
|
2012-02-09 08:52:59 +00:00
|
|
|
|
qapi: Add new visit_complete() function
Making each output visitor provide its own output collection
function was the only remaining reason for exposing visitor
sub-types to the rest of the code base. Add a polymorphic
visit_complete() function which is a no-op for input visitors,
and which populates an opaque pointer for output visitors. For
maximum type-safety, also add a parameter to the output visitor
constructors with a type-correct version of the output pointer,
and assert that the two uses match.
This approach was considered superior to either passing the
output parameter only during construction (action at a distance
during visit_free() feels awkward) or only during visit_complete()
(defeating type safety makes it easier to use incorrectly).
Most callers were function-local, and therefore a mechanical
conversion; the testsuite was a bit trickier, but the previous
cleanup patch minimized the churn here.
The visit_complete() function may be called at most once; doing
so lets us use transfer semantics rather than duplication or
ref-count semantics to get the just-built output back to the
caller, even though it means our behavior is not idempotent.
Generated code is simplified as follows for events:
|@@ -26,7 +26,7 @@ void qapi_event_send_acpi_device_ost(ACP
| QDict *qmp;
| Error *err = NULL;
| QMPEventFuncEmit emit;
|- QmpOutputVisitor *qov;
|+ QObject *obj;
| Visitor *v;
| q_obj_ACPI_DEVICE_OST_arg param = {
| info
|@@ -39,8 +39,7 @@ void qapi_event_send_acpi_device_ost(ACP
|
| qmp = qmp_event_build_dict("ACPI_DEVICE_OST");
|
|- qov = qmp_output_visitor_new();
|- v = qmp_output_get_visitor(qov);
|+ v = qmp_output_visitor_new(&obj);
|
| visit_start_struct(v, "ACPI_DEVICE_OST", NULL, 0, &err);
| if (err) {
|@@ -55,7 +54,8 @@ void qapi_event_send_acpi_device_ost(ACP
| goto out;
| }
|
|- qdict_put_obj(qmp, "data", qmp_output_get_qobject(qov));
|+ visit_complete(v, &obj);
|+ qdict_put_obj(qmp, "data", obj);
| emit(QAPI_EVENT_ACPI_DEVICE_OST, qmp, &err);
and for commands:
| {
| Error *err = NULL;
|- QmpOutputVisitor *qov = qmp_output_visitor_new();
| Visitor *v;
|
|- v = qmp_output_get_visitor(qov);
|+ v = qmp_output_visitor_new(ret_out);
| visit_type_AddfdInfo(v, "unused", &ret_in, &err);
|- if (err) {
|- goto out;
|+ if (!err) {
|+ visit_complete(v, ret_out);
| }
|- *ret_out = qmp_output_get_qobject(qov);
|-
|-out:
| error_propagate(errp, err);
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1465490926-28625-13-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-06-09 16:48:43 +00:00
|
|
|
v = string_output_visitor_new(human, &string);
|
2020-07-07 16:06:03 +00:00
|
|
|
if (!object_property_get(obj, name, v, errp)) {
|
2014-09-27 05:13:55 +00:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
qapi: Add new visit_complete() function
Making each output visitor provide its own output collection
function was the only remaining reason for exposing visitor
sub-types to the rest of the code base. Add a polymorphic
visit_complete() function which is a no-op for input visitors,
and which populates an opaque pointer for output visitors. For
maximum type-safety, also add a parameter to the output visitor
constructors with a type-correct version of the output pointer,
and assert that the two uses match.
This approach was considered superior to either passing the
output parameter only during construction (action at a distance
during visit_free() feels awkward) or only during visit_complete()
(defeating type safety makes it easier to use incorrectly).
Most callers were function-local, and therefore a mechanical
conversion; the testsuite was a bit trickier, but the previous
cleanup patch minimized the churn here.
The visit_complete() function may be called at most once; doing
so lets us use transfer semantics rather than duplication or
ref-count semantics to get the just-built output back to the
caller, even though it means our behavior is not idempotent.
Generated code is simplified as follows for events:
|@@ -26,7 +26,7 @@ void qapi_event_send_acpi_device_ost(ACP
| QDict *qmp;
| Error *err = NULL;
| QMPEventFuncEmit emit;
|- QmpOutputVisitor *qov;
|+ QObject *obj;
| Visitor *v;
| q_obj_ACPI_DEVICE_OST_arg param = {
| info
|@@ -39,8 +39,7 @@ void qapi_event_send_acpi_device_ost(ACP
|
| qmp = qmp_event_build_dict("ACPI_DEVICE_OST");
|
|- qov = qmp_output_visitor_new();
|- v = qmp_output_get_visitor(qov);
|+ v = qmp_output_visitor_new(&obj);
|
| visit_start_struct(v, "ACPI_DEVICE_OST", NULL, 0, &err);
| if (err) {
|@@ -55,7 +54,8 @@ void qapi_event_send_acpi_device_ost(ACP
| goto out;
| }
|
|- qdict_put_obj(qmp, "data", qmp_output_get_qobject(qov));
|+ visit_complete(v, &obj);
|+ qdict_put_obj(qmp, "data", obj);
| emit(QAPI_EVENT_ACPI_DEVICE_OST, qmp, &err);
and for commands:
| {
| Error *err = NULL;
|- QmpOutputVisitor *qov = qmp_output_visitor_new();
| Visitor *v;
|
|- v = qmp_output_get_visitor(qov);
|+ v = qmp_output_visitor_new(ret_out);
| visit_type_AddfdInfo(v, "unused", &ret_in, &err);
|- if (err) {
|- goto out;
|+ if (!err) {
|+ visit_complete(v, ret_out);
| }
|- *ret_out = qmp_output_get_qobject(qov);
|-
|-out:
| error_propagate(errp, err);
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1465490926-28625-13-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-06-09 16:48:43 +00:00
|
|
|
visit_complete(v, &string);
|
2014-09-27 05:13:55 +00:00
|
|
|
|
|
|
|
out:
|
qapi: Add new visit_complete() function
Making each output visitor provide its own output collection
function was the only remaining reason for exposing visitor
sub-types to the rest of the code base. Add a polymorphic
visit_complete() function which is a no-op for input visitors,
and which populates an opaque pointer for output visitors. For
maximum type-safety, also add a parameter to the output visitor
constructors with a type-correct version of the output pointer,
and assert that the two uses match.
This approach was considered superior to either passing the
output parameter only during construction (action at a distance
during visit_free() feels awkward) or only during visit_complete()
(defeating type safety makes it easier to use incorrectly).
Most callers were function-local, and therefore a mechanical
conversion; the testsuite was a bit trickier, but the previous
cleanup patch minimized the churn here.
The visit_complete() function may be called at most once; doing
so lets us use transfer semantics rather than duplication or
ref-count semantics to get the just-built output back to the
caller, even though it means our behavior is not idempotent.
Generated code is simplified as follows for events:
|@@ -26,7 +26,7 @@ void qapi_event_send_acpi_device_ost(ACP
| QDict *qmp;
| Error *err = NULL;
| QMPEventFuncEmit emit;
|- QmpOutputVisitor *qov;
|+ QObject *obj;
| Visitor *v;
| q_obj_ACPI_DEVICE_OST_arg param = {
| info
|@@ -39,8 +39,7 @@ void qapi_event_send_acpi_device_ost(ACP
|
| qmp = qmp_event_build_dict("ACPI_DEVICE_OST");
|
|- qov = qmp_output_visitor_new();
|- v = qmp_output_get_visitor(qov);
|+ v = qmp_output_visitor_new(&obj);
|
| visit_start_struct(v, "ACPI_DEVICE_OST", NULL, 0, &err);
| if (err) {
|@@ -55,7 +54,8 @@ void qapi_event_send_acpi_device_ost(ACP
| goto out;
| }
|
|- qdict_put_obj(qmp, "data", qmp_output_get_qobject(qov));
|+ visit_complete(v, &obj);
|+ qdict_put_obj(qmp, "data", obj);
| emit(QAPI_EVENT_ACPI_DEVICE_OST, qmp, &err);
and for commands:
| {
| Error *err = NULL;
|- QmpOutputVisitor *qov = qmp_output_visitor_new();
| Visitor *v;
|
|- v = qmp_output_get_visitor(qov);
|+ v = qmp_output_visitor_new(ret_out);
| visit_type_AddfdInfo(v, "unused", &ret_in, &err);
|- if (err) {
|- goto out;
|+ if (!err) {
|+ visit_complete(v, ret_out);
| }
|- *ret_out = qmp_output_get_qobject(qov);
|-
|-out:
| error_propagate(errp, err);
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1465490926-28625-13-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-06-09 16:48:43 +00:00
|
|
|
visit_free(v);
|
2012-02-09 08:52:59 +00:00
|
|
|
return string;
|
2012-02-01 16:16:22 +00:00
|
|
|
}
|
|
|
|
|
2012-01-30 14:55:55 +00:00
|
|
|
const char *object_property_get_type(Object *obj, const char *name, Error **errp)
|
|
|
|
{
|
2020-09-14 13:56:17 +00:00
|
|
|
ObjectProperty *prop = object_property_find_err(obj, name, errp);
|
2012-01-30 14:55:55 +00:00
|
|
|
if (prop == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return prop->type;
|
|
|
|
}
|
|
|
|
|
|
|
|
Object *object_get_root(void)
|
|
|
|
{
|
2011-12-23 15:08:05 +00:00
|
|
|
static Object *root;
|
2012-01-30 14:55:55 +00:00
|
|
|
|
2011-12-23 15:08:05 +00:00
|
|
|
if (!root) {
|
|
|
|
root = object_new("container");
|
2012-01-30 14:55:55 +00:00
|
|
|
}
|
|
|
|
|
2011-12-23 15:08:05 +00:00
|
|
|
return root;
|
2012-01-30 14:55:55 +00:00
|
|
|
}
|
|
|
|
|
2015-05-13 16:14:05 +00:00
|
|
|
Object *object_get_objects_root(void)
|
|
|
|
{
|
|
|
|
return container_get(object_get_root(), "/objects");
|
|
|
|
}
|
|
|
|
|
2017-09-28 02:59:54 +00:00
|
|
|
Object *object_get_internal_root(void)
|
|
|
|
{
|
|
|
|
static Object *internal_root;
|
|
|
|
|
|
|
|
if (!internal_root) {
|
|
|
|
internal_root = object_new("container");
|
|
|
|
}
|
|
|
|
|
|
|
|
return internal_root;
|
|
|
|
}
|
|
|
|
|
qom: Swap 'name' next to visitor in ObjectPropertyAccessor
Similar to the previous patch, it's nice to have all functions
in the tree that involve a visitor and a name for conversion to
or from QAPI to consistently stick the 'name' parameter next
to the Visitor parameter.
Done by manually changing include/qom/object.h and qom/object.c,
then running this Coccinelle script and touching up the fallout
(Coccinelle insisted on adding some trailing whitespace).
@ rule1 @
identifier fn;
typedef Object, Visitor, Error;
identifier obj, v, opaque, name, errp;
@@
void fn
- (Object *obj, Visitor *v, void *opaque, const char *name,
+ (Object *obj, Visitor *v, const char *name, void *opaque,
Error **errp) { ... }
@@
identifier rule1.fn;
expression obj, v, opaque, name, errp;
@@
fn(obj, v,
- opaque, name,
+ name, opaque,
errp)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-20-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 13:48:55 +00:00
|
|
|
static void object_get_child_property(Object *obj, Visitor *v,
|
|
|
|
const char *name, void *opaque,
|
|
|
|
Error **errp)
|
2012-01-30 14:55:55 +00:00
|
|
|
{
|
|
|
|
Object *child = opaque;
|
2020-05-05 15:29:10 +00:00
|
|
|
char *path;
|
2012-01-30 14:55:55 +00:00
|
|
|
|
|
|
|
path = object_get_canonical_path(child);
|
qapi: Swap visit_* arguments for consistent 'name' placement
JSON uses "name":value, but many of our visitor interfaces were
called with visit_type_FOO(v, &value, name, errp). This can be
a bit confusing to have to mentally swap the parameter order to
match JSON order. It's particularly bad for visit_start_struct(),
where the 'name' parameter is smack in the middle of the
otherwise-related group of 'obj, kind, size' parameters! It's
time to do a global swap of the parameter ordering, so that the
'name' parameter is always immediately after the Visitor argument.
Additional reason in favor of the swap: the existing include/qjson.h
prefers listing 'name' first in json_prop_*(), and I have plans to
unify that file with the qapi visitors; listing 'name' first in
qapi will minimize churn to the (admittedly few) qjson.h clients.
Later patches will then fix docs, object.h, visitor-impl.h, and
those clients to match.
Done by first patching scripts/qapi*.py by hand to make generated
files do what I want, then by running the following Coccinelle
script to affect the rest of the code base:
$ spatch --sp-file script `git grep -l '\bvisit_' -- '**/*.[ch]'`
I then had to apply some touchups (Coccinelle insisted on TAB
indentation in visitor.h, and botched the signature of
visit_type_enum() by rewriting 'const char *const strings[]' to
the syntactically invalid 'const char*const[] strings'). The
movement of parameters is sufficient to provoke compiler errors
if any callers were missed.
// Part 1: Swap declaration order
@@
type TV, TErr, TObj, T1, T2;
identifier OBJ, ARG1, ARG2;
@@
void visit_start_struct
-(TV v, TObj OBJ, T1 ARG1, const char *name, T2 ARG2, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp)
{ ... }
@@
type bool, TV, T1;
identifier ARG1;
@@
bool visit_optional
-(TV v, T1 ARG1, const char *name)
+(TV v, const char *name, T1 ARG1)
{ ... }
@@
type TV, TErr, TObj, T1;
identifier OBJ, ARG1;
@@
void visit_get_next_type
-(TV v, TObj OBJ, T1 ARG1, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, TErr errp)
{ ... }
@@
type TV, TErr, TObj, T1, T2;
identifier OBJ, ARG1, ARG2;
@@
void visit_type_enum
-(TV v, TObj OBJ, T1 ARG1, T2 ARG2, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp)
{ ... }
@@
type TV, TErr, TObj;
identifier OBJ;
identifier VISIT_TYPE =~ "^visit_type_";
@@
void VISIT_TYPE
-(TV v, TObj OBJ, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, TErr errp)
{ ... }
// Part 2: swap caller order
@@
expression V, NAME, OBJ, ARG1, ARG2, ERR;
identifier VISIT_TYPE =~ "^visit_type_";
@@
(
-visit_start_struct(V, OBJ, ARG1, NAME, ARG2, ERR)
+visit_start_struct(V, NAME, OBJ, ARG1, ARG2, ERR)
|
-visit_optional(V, ARG1, NAME)
+visit_optional(V, NAME, ARG1)
|
-visit_get_next_type(V, OBJ, ARG1, NAME, ERR)
+visit_get_next_type(V, NAME, OBJ, ARG1, ERR)
|
-visit_type_enum(V, OBJ, ARG1, ARG2, NAME, ERR)
+visit_type_enum(V, NAME, OBJ, ARG1, ARG2, ERR)
|
-VISIT_TYPE(V, OBJ, NAME, ERR)
+VISIT_TYPE(V, NAME, OBJ, ERR)
)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-19-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 13:48:54 +00:00
|
|
|
visit_type_str(v, name, &path, errp);
|
2012-01-30 14:55:55 +00:00
|
|
|
g_free(path);
|
|
|
|
}
|
|
|
|
|
2020-05-05 15:29:10 +00:00
|
|
|
static Object *object_resolve_child_property(Object *parent, void *opaque,
|
|
|
|
const char *part)
|
2014-06-05 11:11:51 +00:00
|
|
|
{
|
|
|
|
return opaque;
|
|
|
|
}
|
|
|
|
|
2011-12-23 14:47:39 +00:00
|
|
|
static void object_finalize_child_property(Object *obj, const char *name,
|
|
|
|
void *opaque)
|
|
|
|
{
|
|
|
|
Object *child = opaque;
|
|
|
|
|
2014-06-11 09:57:38 +00:00
|
|
|
if (child->class->unparent) {
|
|
|
|
(child->class->unparent)(child);
|
|
|
|
}
|
|
|
|
child->parent = NULL;
|
2011-12-23 14:47:39 +00:00
|
|
|
object_unref(child);
|
|
|
|
}
|
|
|
|
|
2020-05-05 15:29:14 +00:00
|
|
|
ObjectProperty *
|
2020-06-29 19:34:22 +00:00
|
|
|
object_property_try_add_child(Object *obj, const char *name,
|
|
|
|
Object *child, Error **errp)
|
2012-01-30 14:55:55 +00:00
|
|
|
{
|
2020-05-05 15:29:14 +00:00
|
|
|
g_autofree char *type = NULL;
|
2014-06-05 11:11:51 +00:00
|
|
|
ObjectProperty *op;
|
2012-01-30 14:55:55 +00:00
|
|
|
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
assert(!child->parent);
|
2014-09-26 05:19:52 +00:00
|
|
|
|
2020-05-12 07:00:19 +00:00
|
|
|
type = g_strdup_printf("child<%s>", object_get_typename(child));
|
2012-01-30 14:55:55 +00:00
|
|
|
|
2020-06-29 19:34:22 +00:00
|
|
|
op = object_property_try_add(obj, name, type, object_get_child_property,
|
|
|
|
NULL, object_finalize_child_property,
|
|
|
|
child, errp);
|
|
|
|
if (!op) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2014-06-05 11:11:51 +00:00
|
|
|
op->resolve = object_resolve_child_property;
|
2012-01-30 14:55:55 +00:00
|
|
|
object_ref(child);
|
|
|
|
child->parent = obj;
|
2020-05-05 15:29:14 +00:00
|
|
|
return op;
|
2012-01-30 14:55:55 +00:00
|
|
|
}
|
|
|
|
|
2020-06-29 19:34:22 +00:00
|
|
|
ObjectProperty *
|
|
|
|
object_property_add_child(Object *obj, const char *name,
|
|
|
|
Object *child)
|
|
|
|
{
|
|
|
|
return object_property_try_add_child(obj, name, child, &error_abort);
|
|
|
|
}
|
|
|
|
|
2017-07-14 02:14:50 +00:00
|
|
|
void object_property_allow_set_link(const Object *obj, const char *name,
|
2014-03-19 07:58:56 +00:00
|
|
|
Object *val, Error **errp)
|
|
|
|
{
|
|
|
|
/* Allow the link to be set, always */
|
|
|
|
}
|
|
|
|
|
qom: Make QOM link property unref optional
Some object_property_add_link() callers expect property deletion to
unref the link property object. Other callers expect to manage the
refcount themselves. The former are currently broken and therefore leak
the link property object.
This patch adds a flags argument to object_property_add_link() so the
caller can specify which refcount behavior they require. The new
OBJ_PROP_LINK_UNREF_ON_RELEASE flag causes the link pointer to be
unreferenced when the property is deleted.
This fixes refcount leaks in qdev.c, xilinx_axidma.c, xilinx_axienet.c,
s390-virtio-bus.c, virtio-pci.c, virtio-rng.c, and ui/console.c.
Rationale for refcount behavior:
* hw/core/qdev.c
- bus children are explicitly unreferenced, don't interfere
- parent_bus is essentially a read-only property that doesn't hold a
refcount, don't unref
- hotplug_handler is leaked, do unref
* hw/dma/xilinx_axidma.c
- rx stream "dma" links are set using set_link, therefore they
need unref
- tx streams are set using set_link, therefore they need unref
* hw/net/xilinx_axienet.c
- same reasoning as hw/dma/xilinx_axidma.c
* hw/pcmcia/pxa2xx.c
- pxa2xx bypasses set_link and therefore does not use refcounts
* hw/s390x/s390-virtio-bus.c
* hw/virtio/virtio-pci.c
* hw/virtio/virtio-rng.c
* ui/console.c
- set_link is used and there is no explicit unref, do unref
Cc: Peter Crosthwaite <peter.crosthwaite@petalogix.com>
Cc: Alexander Graf <agraf@suse.de>
Cc: Anthony Liguori <aliguori@amazon.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2014-03-19 07:58:55 +00:00
|
|
|
typedef struct {
|
2020-01-10 15:30:27 +00:00
|
|
|
union {
|
|
|
|
Object **targetp;
|
|
|
|
Object *target; /* if OBJ_PROP_LINK_DIRECT, when holding the pointer */
|
2020-01-10 15:30:29 +00:00
|
|
|
ptrdiff_t offset; /* if OBJ_PROP_LINK_CLASS */
|
2020-01-10 15:30:27 +00:00
|
|
|
};
|
2017-07-14 02:14:50 +00:00
|
|
|
void (*check)(const Object *, const char *, Object *, Error **);
|
qom: Make QOM link property unref optional
Some object_property_add_link() callers expect property deletion to
unref the link property object. Other callers expect to manage the
refcount themselves. The former are currently broken and therefore leak
the link property object.
This patch adds a flags argument to object_property_add_link() so the
caller can specify which refcount behavior they require. The new
OBJ_PROP_LINK_UNREF_ON_RELEASE flag causes the link pointer to be
unreferenced when the property is deleted.
This fixes refcount leaks in qdev.c, xilinx_axidma.c, xilinx_axienet.c,
s390-virtio-bus.c, virtio-pci.c, virtio-rng.c, and ui/console.c.
Rationale for refcount behavior:
* hw/core/qdev.c
- bus children are explicitly unreferenced, don't interfere
- parent_bus is essentially a read-only property that doesn't hold a
refcount, don't unref
- hotplug_handler is leaked, do unref
* hw/dma/xilinx_axidma.c
- rx stream "dma" links are set using set_link, therefore they
need unref
- tx streams are set using set_link, therefore they need unref
* hw/net/xilinx_axienet.c
- same reasoning as hw/dma/xilinx_axidma.c
* hw/pcmcia/pxa2xx.c
- pxa2xx bypasses set_link and therefore does not use refcounts
* hw/s390x/s390-virtio-bus.c
* hw/virtio/virtio-pci.c
* hw/virtio/virtio-rng.c
* ui/console.c
- set_link is used and there is no explicit unref, do unref
Cc: Peter Crosthwaite <peter.crosthwaite@petalogix.com>
Cc: Alexander Graf <agraf@suse.de>
Cc: Anthony Liguori <aliguori@amazon.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2014-03-19 07:58:55 +00:00
|
|
|
ObjectPropertyLinkFlags flags;
|
|
|
|
} LinkProperty;
|
|
|
|
|
2020-01-10 15:30:27 +00:00
|
|
|
static Object **
|
|
|
|
object_link_get_targetp(Object *obj, LinkProperty *lprop)
|
|
|
|
{
|
|
|
|
if (lprop->flags & OBJ_PROP_LINK_DIRECT) {
|
|
|
|
return &lprop->target;
|
2020-01-10 15:30:29 +00:00
|
|
|
} else if (lprop->flags & OBJ_PROP_LINK_CLASS) {
|
|
|
|
return (void *)obj + lprop->offset;
|
2020-01-10 15:30:27 +00:00
|
|
|
} else {
|
|
|
|
return lprop->targetp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
qom: Swap 'name' next to visitor in ObjectPropertyAccessor
Similar to the previous patch, it's nice to have all functions
in the tree that involve a visitor and a name for conversion to
or from QAPI to consistently stick the 'name' parameter next
to the Visitor parameter.
Done by manually changing include/qom/object.h and qom/object.c,
then running this Coccinelle script and touching up the fallout
(Coccinelle insisted on adding some trailing whitespace).
@ rule1 @
identifier fn;
typedef Object, Visitor, Error;
identifier obj, v, opaque, name, errp;
@@
void fn
- (Object *obj, Visitor *v, void *opaque, const char *name,
+ (Object *obj, Visitor *v, const char *name, void *opaque,
Error **errp) { ... }
@@
identifier rule1.fn;
expression obj, v, opaque, name, errp;
@@
fn(obj, v,
- opaque, name,
+ name, opaque,
errp)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-20-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 13:48:55 +00:00
|
|
|
static void object_get_link_property(Object *obj, Visitor *v,
|
|
|
|
const char *name, void *opaque,
|
|
|
|
Error **errp)
|
2012-01-30 14:55:55 +00:00
|
|
|
{
|
qom: Make QOM link property unref optional
Some object_property_add_link() callers expect property deletion to
unref the link property object. Other callers expect to manage the
refcount themselves. The former are currently broken and therefore leak
the link property object.
This patch adds a flags argument to object_property_add_link() so the
caller can specify which refcount behavior they require. The new
OBJ_PROP_LINK_UNREF_ON_RELEASE flag causes the link pointer to be
unreferenced when the property is deleted.
This fixes refcount leaks in qdev.c, xilinx_axidma.c, xilinx_axienet.c,
s390-virtio-bus.c, virtio-pci.c, virtio-rng.c, and ui/console.c.
Rationale for refcount behavior:
* hw/core/qdev.c
- bus children are explicitly unreferenced, don't interfere
- parent_bus is essentially a read-only property that doesn't hold a
refcount, don't unref
- hotplug_handler is leaked, do unref
* hw/dma/xilinx_axidma.c
- rx stream "dma" links are set using set_link, therefore they
need unref
- tx streams are set using set_link, therefore they need unref
* hw/net/xilinx_axienet.c
- same reasoning as hw/dma/xilinx_axidma.c
* hw/pcmcia/pxa2xx.c
- pxa2xx bypasses set_link and therefore does not use refcounts
* hw/s390x/s390-virtio-bus.c
* hw/virtio/virtio-pci.c
* hw/virtio/virtio-rng.c
* ui/console.c
- set_link is used and there is no explicit unref, do unref
Cc: Peter Crosthwaite <peter.crosthwaite@petalogix.com>
Cc: Alexander Graf <agraf@suse.de>
Cc: Anthony Liguori <aliguori@amazon.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2014-03-19 07:58:55 +00:00
|
|
|
LinkProperty *lprop = opaque;
|
2020-01-10 15:30:27 +00:00
|
|
|
Object **targetp = object_link_get_targetp(obj, lprop);
|
2020-05-05 15:29:10 +00:00
|
|
|
char *path;
|
2012-01-30 14:55:55 +00:00
|
|
|
|
2020-01-10 15:30:26 +00:00
|
|
|
if (*targetp) {
|
|
|
|
path = object_get_canonical_path(*targetp);
|
qapi: Swap visit_* arguments for consistent 'name' placement
JSON uses "name":value, but many of our visitor interfaces were
called with visit_type_FOO(v, &value, name, errp). This can be
a bit confusing to have to mentally swap the parameter order to
match JSON order. It's particularly bad for visit_start_struct(),
where the 'name' parameter is smack in the middle of the
otherwise-related group of 'obj, kind, size' parameters! It's
time to do a global swap of the parameter ordering, so that the
'name' parameter is always immediately after the Visitor argument.
Additional reason in favor of the swap: the existing include/qjson.h
prefers listing 'name' first in json_prop_*(), and I have plans to
unify that file with the qapi visitors; listing 'name' first in
qapi will minimize churn to the (admittedly few) qjson.h clients.
Later patches will then fix docs, object.h, visitor-impl.h, and
those clients to match.
Done by first patching scripts/qapi*.py by hand to make generated
files do what I want, then by running the following Coccinelle
script to affect the rest of the code base:
$ spatch --sp-file script `git grep -l '\bvisit_' -- '**/*.[ch]'`
I then had to apply some touchups (Coccinelle insisted on TAB
indentation in visitor.h, and botched the signature of
visit_type_enum() by rewriting 'const char *const strings[]' to
the syntactically invalid 'const char*const[] strings'). The
movement of parameters is sufficient to provoke compiler errors
if any callers were missed.
// Part 1: Swap declaration order
@@
type TV, TErr, TObj, T1, T2;
identifier OBJ, ARG1, ARG2;
@@
void visit_start_struct
-(TV v, TObj OBJ, T1 ARG1, const char *name, T2 ARG2, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp)
{ ... }
@@
type bool, TV, T1;
identifier ARG1;
@@
bool visit_optional
-(TV v, T1 ARG1, const char *name)
+(TV v, const char *name, T1 ARG1)
{ ... }
@@
type TV, TErr, TObj, T1;
identifier OBJ, ARG1;
@@
void visit_get_next_type
-(TV v, TObj OBJ, T1 ARG1, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, TErr errp)
{ ... }
@@
type TV, TErr, TObj, T1, T2;
identifier OBJ, ARG1, ARG2;
@@
void visit_type_enum
-(TV v, TObj OBJ, T1 ARG1, T2 ARG2, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp)
{ ... }
@@
type TV, TErr, TObj;
identifier OBJ;
identifier VISIT_TYPE =~ "^visit_type_";
@@
void VISIT_TYPE
-(TV v, TObj OBJ, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, TErr errp)
{ ... }
// Part 2: swap caller order
@@
expression V, NAME, OBJ, ARG1, ARG2, ERR;
identifier VISIT_TYPE =~ "^visit_type_";
@@
(
-visit_start_struct(V, OBJ, ARG1, NAME, ARG2, ERR)
+visit_start_struct(V, NAME, OBJ, ARG1, ARG2, ERR)
|
-visit_optional(V, ARG1, NAME)
+visit_optional(V, NAME, ARG1)
|
-visit_get_next_type(V, OBJ, ARG1, NAME, ERR)
+visit_get_next_type(V, NAME, OBJ, ARG1, ERR)
|
-visit_type_enum(V, OBJ, ARG1, ARG2, NAME, ERR)
+visit_type_enum(V, NAME, OBJ, ARG1, ARG2, ERR)
|
-VISIT_TYPE(V, OBJ, NAME, ERR)
+VISIT_TYPE(V, NAME, OBJ, ERR)
)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-19-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 13:48:54 +00:00
|
|
|
visit_type_str(v, name, &path, errp);
|
2012-01-30 14:55:55 +00:00
|
|
|
g_free(path);
|
|
|
|
} else {
|
2020-05-05 15:29:10 +00:00
|
|
|
path = (char *)"";
|
qapi: Swap visit_* arguments for consistent 'name' placement
JSON uses "name":value, but many of our visitor interfaces were
called with visit_type_FOO(v, &value, name, errp). This can be
a bit confusing to have to mentally swap the parameter order to
match JSON order. It's particularly bad for visit_start_struct(),
where the 'name' parameter is smack in the middle of the
otherwise-related group of 'obj, kind, size' parameters! It's
time to do a global swap of the parameter ordering, so that the
'name' parameter is always immediately after the Visitor argument.
Additional reason in favor of the swap: the existing include/qjson.h
prefers listing 'name' first in json_prop_*(), and I have plans to
unify that file with the qapi visitors; listing 'name' first in
qapi will minimize churn to the (admittedly few) qjson.h clients.
Later patches will then fix docs, object.h, visitor-impl.h, and
those clients to match.
Done by first patching scripts/qapi*.py by hand to make generated
files do what I want, then by running the following Coccinelle
script to affect the rest of the code base:
$ spatch --sp-file script `git grep -l '\bvisit_' -- '**/*.[ch]'`
I then had to apply some touchups (Coccinelle insisted on TAB
indentation in visitor.h, and botched the signature of
visit_type_enum() by rewriting 'const char *const strings[]' to
the syntactically invalid 'const char*const[] strings'). The
movement of parameters is sufficient to provoke compiler errors
if any callers were missed.
// Part 1: Swap declaration order
@@
type TV, TErr, TObj, T1, T2;
identifier OBJ, ARG1, ARG2;
@@
void visit_start_struct
-(TV v, TObj OBJ, T1 ARG1, const char *name, T2 ARG2, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp)
{ ... }
@@
type bool, TV, T1;
identifier ARG1;
@@
bool visit_optional
-(TV v, T1 ARG1, const char *name)
+(TV v, const char *name, T1 ARG1)
{ ... }
@@
type TV, TErr, TObj, T1;
identifier OBJ, ARG1;
@@
void visit_get_next_type
-(TV v, TObj OBJ, T1 ARG1, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, TErr errp)
{ ... }
@@
type TV, TErr, TObj, T1, T2;
identifier OBJ, ARG1, ARG2;
@@
void visit_type_enum
-(TV v, TObj OBJ, T1 ARG1, T2 ARG2, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp)
{ ... }
@@
type TV, TErr, TObj;
identifier OBJ;
identifier VISIT_TYPE =~ "^visit_type_";
@@
void VISIT_TYPE
-(TV v, TObj OBJ, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, TErr errp)
{ ... }
// Part 2: swap caller order
@@
expression V, NAME, OBJ, ARG1, ARG2, ERR;
identifier VISIT_TYPE =~ "^visit_type_";
@@
(
-visit_start_struct(V, OBJ, ARG1, NAME, ARG2, ERR)
+visit_start_struct(V, NAME, OBJ, ARG1, ARG2, ERR)
|
-visit_optional(V, ARG1, NAME)
+visit_optional(V, NAME, ARG1)
|
-visit_get_next_type(V, OBJ, ARG1, NAME, ERR)
+visit_get_next_type(V, NAME, OBJ, ARG1, ERR)
|
-visit_type_enum(V, OBJ, ARG1, ARG2, NAME, ERR)
+visit_type_enum(V, NAME, OBJ, ARG1, ARG2, ERR)
|
-VISIT_TYPE(V, OBJ, NAME, ERR)
+VISIT_TYPE(V, NAME, OBJ, ERR)
)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-19-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 13:48:54 +00:00
|
|
|
visit_type_str(v, name, &path, errp);
|
2012-01-30 14:55:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-19 07:58:53 +00:00
|
|
|
/*
|
|
|
|
* object_resolve_link:
|
|
|
|
*
|
|
|
|
* Lookup an object and ensure its type matches the link property type. This
|
|
|
|
* is similar to object_resolve_path() except type verification against the
|
|
|
|
* link property is performed.
|
|
|
|
*
|
|
|
|
* Returns: The matched object or NULL on path lookup failures.
|
|
|
|
*/
|
|
|
|
static Object *object_resolve_link(Object *obj, const char *name,
|
|
|
|
const char *path, Error **errp)
|
|
|
|
{
|
|
|
|
const char *type;
|
2020-05-05 15:29:10 +00:00
|
|
|
char *target_type;
|
2014-03-19 07:58:53 +00:00
|
|
|
bool ambiguous = false;
|
|
|
|
Object *target;
|
|
|
|
|
|
|
|
/* Go from link<FOO> to FOO. */
|
|
|
|
type = object_property_get_type(obj, name, NULL);
|
|
|
|
target_type = g_strndup(&type[5], strlen(type) - 6);
|
|
|
|
target = object_resolve_path_type(path, target_type, &ambiguous);
|
|
|
|
|
|
|
|
if (ambiguous) {
|
2015-11-11 06:51:20 +00:00
|
|
|
error_setg(errp, "Path '%s' does not uniquely identify an object",
|
|
|
|
path);
|
2014-03-19 07:58:53 +00:00
|
|
|
} else if (!target) {
|
|
|
|
target = object_resolve_path(path, &ambiguous);
|
|
|
|
if (target || ambiguous) {
|
2015-03-17 10:54:50 +00:00
|
|
|
error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name, target_type);
|
2014-03-19 07:58:53 +00:00
|
|
|
} else {
|
2015-03-16 07:57:47 +00:00
|
|
|
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
|
|
|
|
"Device '%s' not found", path);
|
2014-03-19 07:58:53 +00:00
|
|
|
}
|
|
|
|
target = NULL;
|
|
|
|
}
|
|
|
|
g_free(target_type);
|
|
|
|
|
|
|
|
return target;
|
|
|
|
}
|
|
|
|
|
qom: Swap 'name' next to visitor in ObjectPropertyAccessor
Similar to the previous patch, it's nice to have all functions
in the tree that involve a visitor and a name for conversion to
or from QAPI to consistently stick the 'name' parameter next
to the Visitor parameter.
Done by manually changing include/qom/object.h and qom/object.c,
then running this Coccinelle script and touching up the fallout
(Coccinelle insisted on adding some trailing whitespace).
@ rule1 @
identifier fn;
typedef Object, Visitor, Error;
identifier obj, v, opaque, name, errp;
@@
void fn
- (Object *obj, Visitor *v, void *opaque, const char *name,
+ (Object *obj, Visitor *v, const char *name, void *opaque,
Error **errp) { ... }
@@
identifier rule1.fn;
expression obj, v, opaque, name, errp;
@@
fn(obj, v,
- opaque, name,
+ name, opaque,
errp)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-20-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 13:48:55 +00:00
|
|
|
static void object_set_link_property(Object *obj, Visitor *v,
|
|
|
|
const char *name, void *opaque,
|
|
|
|
Error **errp)
|
2012-01-30 14:55:55 +00:00
|
|
|
{
|
2014-03-19 07:58:54 +00:00
|
|
|
Error *local_err = NULL;
|
qom: Make QOM link property unref optional
Some object_property_add_link() callers expect property deletion to
unref the link property object. Other callers expect to manage the
refcount themselves. The former are currently broken and therefore leak
the link property object.
This patch adds a flags argument to object_property_add_link() so the
caller can specify which refcount behavior they require. The new
OBJ_PROP_LINK_UNREF_ON_RELEASE flag causes the link pointer to be
unreferenced when the property is deleted.
This fixes refcount leaks in qdev.c, xilinx_axidma.c, xilinx_axienet.c,
s390-virtio-bus.c, virtio-pci.c, virtio-rng.c, and ui/console.c.
Rationale for refcount behavior:
* hw/core/qdev.c
- bus children are explicitly unreferenced, don't interfere
- parent_bus is essentially a read-only property that doesn't hold a
refcount, don't unref
- hotplug_handler is leaked, do unref
* hw/dma/xilinx_axidma.c
- rx stream "dma" links are set using set_link, therefore they
need unref
- tx streams are set using set_link, therefore they need unref
* hw/net/xilinx_axienet.c
- same reasoning as hw/dma/xilinx_axidma.c
* hw/pcmcia/pxa2xx.c
- pxa2xx bypasses set_link and therefore does not use refcounts
* hw/s390x/s390-virtio-bus.c
* hw/virtio/virtio-pci.c
* hw/virtio/virtio-rng.c
* ui/console.c
- set_link is used and there is no explicit unref, do unref
Cc: Peter Crosthwaite <peter.crosthwaite@petalogix.com>
Cc: Alexander Graf <agraf@suse.de>
Cc: Anthony Liguori <aliguori@amazon.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2014-03-19 07:58:55 +00:00
|
|
|
LinkProperty *prop = opaque;
|
2020-01-10 15:30:27 +00:00
|
|
|
Object **targetp = object_link_get_targetp(obj, prop);
|
2020-01-10 15:30:26 +00:00
|
|
|
Object *old_target = *targetp;
|
2020-07-07 16:05:53 +00:00
|
|
|
Object *new_target;
|
2014-03-19 07:58:54 +00:00
|
|
|
char *path = NULL;
|
2012-01-30 14:55:55 +00:00
|
|
|
|
2020-07-07 16:05:53 +00:00
|
|
|
if (!visit_type_str(v, name, &path, errp)) {
|
|
|
|
return;
|
|
|
|
}
|
2012-01-30 14:55:55 +00:00
|
|
|
|
2020-07-07 16:05:53 +00:00
|
|
|
if (*path) {
|
|
|
|
new_target = object_resolve_link(obj, name, path, errp);
|
|
|
|
if (!new_target) {
|
|
|
|
g_free(path);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
new_target = NULL;
|
2012-01-30 14:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
g_free(path);
|
2012-02-22 17:22:26 +00:00
|
|
|
|
2014-03-19 07:58:56 +00:00
|
|
|
prop->check(obj, name, new_target, &local_err);
|
|
|
|
if (local_err) {
|
|
|
|
error_propagate(errp, local_err);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-01-10 15:30:26 +00:00
|
|
|
*targetp = new_target;
|
2020-01-10 15:30:25 +00:00
|
|
|
if (prop->flags & OBJ_PROP_LINK_STRONG) {
|
2018-05-31 19:51:17 +00:00
|
|
|
object_ref(new_target);
|
|
|
|
object_unref(old_target);
|
|
|
|
}
|
2012-01-30 14:55:55 +00:00
|
|
|
}
|
|
|
|
|
2020-05-05 15:29:10 +00:00
|
|
|
static Object *object_resolve_link_property(Object *parent, void *opaque,
|
|
|
|
const char *part)
|
2014-06-05 11:11:51 +00:00
|
|
|
{
|
|
|
|
LinkProperty *lprop = opaque;
|
|
|
|
|
2020-01-10 15:30:27 +00:00
|
|
|
return *object_link_get_targetp(parent, lprop);
|
2014-06-05 11:11:51 +00:00
|
|
|
}
|
|
|
|
|
qom: Make QOM link property unref optional
Some object_property_add_link() callers expect property deletion to
unref the link property object. Other callers expect to manage the
refcount themselves. The former are currently broken and therefore leak
the link property object.
This patch adds a flags argument to object_property_add_link() so the
caller can specify which refcount behavior they require. The new
OBJ_PROP_LINK_UNREF_ON_RELEASE flag causes the link pointer to be
unreferenced when the property is deleted.
This fixes refcount leaks in qdev.c, xilinx_axidma.c, xilinx_axienet.c,
s390-virtio-bus.c, virtio-pci.c, virtio-rng.c, and ui/console.c.
Rationale for refcount behavior:
* hw/core/qdev.c
- bus children are explicitly unreferenced, don't interfere
- parent_bus is essentially a read-only property that doesn't hold a
refcount, don't unref
- hotplug_handler is leaked, do unref
* hw/dma/xilinx_axidma.c
- rx stream "dma" links are set using set_link, therefore they
need unref
- tx streams are set using set_link, therefore they need unref
* hw/net/xilinx_axienet.c
- same reasoning as hw/dma/xilinx_axidma.c
* hw/pcmcia/pxa2xx.c
- pxa2xx bypasses set_link and therefore does not use refcounts
* hw/s390x/s390-virtio-bus.c
* hw/virtio/virtio-pci.c
* hw/virtio/virtio-rng.c
* ui/console.c
- set_link is used and there is no explicit unref, do unref
Cc: Peter Crosthwaite <peter.crosthwaite@petalogix.com>
Cc: Alexander Graf <agraf@suse.de>
Cc: Anthony Liguori <aliguori@amazon.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2014-03-19 07:58:55 +00:00
|
|
|
static void object_release_link_property(Object *obj, const char *name,
|
|
|
|
void *opaque)
|
|
|
|
{
|
|
|
|
LinkProperty *prop = opaque;
|
2020-01-10 15:30:27 +00:00
|
|
|
Object **targetp = object_link_get_targetp(obj, prop);
|
qom: Make QOM link property unref optional
Some object_property_add_link() callers expect property deletion to
unref the link property object. Other callers expect to manage the
refcount themselves. The former are currently broken and therefore leak
the link property object.
This patch adds a flags argument to object_property_add_link() so the
caller can specify which refcount behavior they require. The new
OBJ_PROP_LINK_UNREF_ON_RELEASE flag causes the link pointer to be
unreferenced when the property is deleted.
This fixes refcount leaks in qdev.c, xilinx_axidma.c, xilinx_axienet.c,
s390-virtio-bus.c, virtio-pci.c, virtio-rng.c, and ui/console.c.
Rationale for refcount behavior:
* hw/core/qdev.c
- bus children are explicitly unreferenced, don't interfere
- parent_bus is essentially a read-only property that doesn't hold a
refcount, don't unref
- hotplug_handler is leaked, do unref
* hw/dma/xilinx_axidma.c
- rx stream "dma" links are set using set_link, therefore they
need unref
- tx streams are set using set_link, therefore they need unref
* hw/net/xilinx_axienet.c
- same reasoning as hw/dma/xilinx_axidma.c
* hw/pcmcia/pxa2xx.c
- pxa2xx bypasses set_link and therefore does not use refcounts
* hw/s390x/s390-virtio-bus.c
* hw/virtio/virtio-pci.c
* hw/virtio/virtio-rng.c
* ui/console.c
- set_link is used and there is no explicit unref, do unref
Cc: Peter Crosthwaite <peter.crosthwaite@petalogix.com>
Cc: Alexander Graf <agraf@suse.de>
Cc: Anthony Liguori <aliguori@amazon.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2014-03-19 07:58:55 +00:00
|
|
|
|
2020-01-10 15:30:27 +00:00
|
|
|
if ((prop->flags & OBJ_PROP_LINK_STRONG) && *targetp) {
|
|
|
|
object_unref(*targetp);
|
qom: Make QOM link property unref optional
Some object_property_add_link() callers expect property deletion to
unref the link property object. Other callers expect to manage the
refcount themselves. The former are currently broken and therefore leak
the link property object.
This patch adds a flags argument to object_property_add_link() so the
caller can specify which refcount behavior they require. The new
OBJ_PROP_LINK_UNREF_ON_RELEASE flag causes the link pointer to be
unreferenced when the property is deleted.
This fixes refcount leaks in qdev.c, xilinx_axidma.c, xilinx_axienet.c,
s390-virtio-bus.c, virtio-pci.c, virtio-rng.c, and ui/console.c.
Rationale for refcount behavior:
* hw/core/qdev.c
- bus children are explicitly unreferenced, don't interfere
- parent_bus is essentially a read-only property that doesn't hold a
refcount, don't unref
- hotplug_handler is leaked, do unref
* hw/dma/xilinx_axidma.c
- rx stream "dma" links are set using set_link, therefore they
need unref
- tx streams are set using set_link, therefore they need unref
* hw/net/xilinx_axienet.c
- same reasoning as hw/dma/xilinx_axidma.c
* hw/pcmcia/pxa2xx.c
- pxa2xx bypasses set_link and therefore does not use refcounts
* hw/s390x/s390-virtio-bus.c
* hw/virtio/virtio-pci.c
* hw/virtio/virtio-rng.c
* ui/console.c
- set_link is used and there is no explicit unref, do unref
Cc: Peter Crosthwaite <peter.crosthwaite@petalogix.com>
Cc: Alexander Graf <agraf@suse.de>
Cc: Anthony Liguori <aliguori@amazon.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2014-03-19 07:58:55 +00:00
|
|
|
}
|
2020-01-10 15:30:29 +00:00
|
|
|
if (!(prop->flags & OBJ_PROP_LINK_CLASS)) {
|
|
|
|
g_free(prop);
|
|
|
|
}
|
qom: Make QOM link property unref optional
Some object_property_add_link() callers expect property deletion to
unref the link property object. Other callers expect to manage the
refcount themselves. The former are currently broken and therefore leak
the link property object.
This patch adds a flags argument to object_property_add_link() so the
caller can specify which refcount behavior they require. The new
OBJ_PROP_LINK_UNREF_ON_RELEASE flag causes the link pointer to be
unreferenced when the property is deleted.
This fixes refcount leaks in qdev.c, xilinx_axidma.c, xilinx_axienet.c,
s390-virtio-bus.c, virtio-pci.c, virtio-rng.c, and ui/console.c.
Rationale for refcount behavior:
* hw/core/qdev.c
- bus children are explicitly unreferenced, don't interfere
- parent_bus is essentially a read-only property that doesn't hold a
refcount, don't unref
- hotplug_handler is leaked, do unref
* hw/dma/xilinx_axidma.c
- rx stream "dma" links are set using set_link, therefore they
need unref
- tx streams are set using set_link, therefore they need unref
* hw/net/xilinx_axienet.c
- same reasoning as hw/dma/xilinx_axidma.c
* hw/pcmcia/pxa2xx.c
- pxa2xx bypasses set_link and therefore does not use refcounts
* hw/s390x/s390-virtio-bus.c
* hw/virtio/virtio-pci.c
* hw/virtio/virtio-rng.c
* ui/console.c
- set_link is used and there is no explicit unref, do unref
Cc: Peter Crosthwaite <peter.crosthwaite@petalogix.com>
Cc: Alexander Graf <agraf@suse.de>
Cc: Anthony Liguori <aliguori@amazon.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2014-03-19 07:58:55 +00:00
|
|
|
}
|
|
|
|
|
2020-05-05 15:29:14 +00:00
|
|
|
static ObjectProperty *
|
|
|
|
object_add_link_prop(Object *obj, const char *name,
|
|
|
|
const char *type, void *ptr,
|
|
|
|
void (*check)(const Object *, const char *,
|
|
|
|
Object *, Error **),
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
ObjectPropertyLinkFlags flags)
|
2012-01-30 14:55:55 +00:00
|
|
|
{
|
qom: Make QOM link property unref optional
Some object_property_add_link() callers expect property deletion to
unref the link property object. Other callers expect to manage the
refcount themselves. The former are currently broken and therefore leak
the link property object.
This patch adds a flags argument to object_property_add_link() so the
caller can specify which refcount behavior they require. The new
OBJ_PROP_LINK_UNREF_ON_RELEASE flag causes the link pointer to be
unreferenced when the property is deleted.
This fixes refcount leaks in qdev.c, xilinx_axidma.c, xilinx_axienet.c,
s390-virtio-bus.c, virtio-pci.c, virtio-rng.c, and ui/console.c.
Rationale for refcount behavior:
* hw/core/qdev.c
- bus children are explicitly unreferenced, don't interfere
- parent_bus is essentially a read-only property that doesn't hold a
refcount, don't unref
- hotplug_handler is leaked, do unref
* hw/dma/xilinx_axidma.c
- rx stream "dma" links are set using set_link, therefore they
need unref
- tx streams are set using set_link, therefore they need unref
* hw/net/xilinx_axienet.c
- same reasoning as hw/dma/xilinx_axidma.c
* hw/pcmcia/pxa2xx.c
- pxa2xx bypasses set_link and therefore does not use refcounts
* hw/s390x/s390-virtio-bus.c
* hw/virtio/virtio-pci.c
* hw/virtio/virtio-rng.c
* ui/console.c
- set_link is used and there is no explicit unref, do unref
Cc: Peter Crosthwaite <peter.crosthwaite@petalogix.com>
Cc: Alexander Graf <agraf@suse.de>
Cc: Anthony Liguori <aliguori@amazon.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2014-03-19 07:58:55 +00:00
|
|
|
LinkProperty *prop = g_malloc(sizeof(*prop));
|
2020-05-05 15:29:14 +00:00
|
|
|
g_autofree char *full_type = NULL;
|
2014-06-05 11:11:51 +00:00
|
|
|
ObjectProperty *op;
|
2012-01-30 14:55:55 +00:00
|
|
|
|
2020-01-10 15:30:28 +00:00
|
|
|
if (flags & OBJ_PROP_LINK_DIRECT) {
|
|
|
|
prop->target = ptr;
|
|
|
|
} else {
|
|
|
|
prop->targetp = ptr;
|
|
|
|
}
|
2014-03-19 07:58:56 +00:00
|
|
|
prop->check = check;
|
qom: Make QOM link property unref optional
Some object_property_add_link() callers expect property deletion to
unref the link property object. Other callers expect to manage the
refcount themselves. The former are currently broken and therefore leak
the link property object.
This patch adds a flags argument to object_property_add_link() so the
caller can specify which refcount behavior they require. The new
OBJ_PROP_LINK_UNREF_ON_RELEASE flag causes the link pointer to be
unreferenced when the property is deleted.
This fixes refcount leaks in qdev.c, xilinx_axidma.c, xilinx_axienet.c,
s390-virtio-bus.c, virtio-pci.c, virtio-rng.c, and ui/console.c.
Rationale for refcount behavior:
* hw/core/qdev.c
- bus children are explicitly unreferenced, don't interfere
- parent_bus is essentially a read-only property that doesn't hold a
refcount, don't unref
- hotplug_handler is leaked, do unref
* hw/dma/xilinx_axidma.c
- rx stream "dma" links are set using set_link, therefore they
need unref
- tx streams are set using set_link, therefore they need unref
* hw/net/xilinx_axienet.c
- same reasoning as hw/dma/xilinx_axidma.c
* hw/pcmcia/pxa2xx.c
- pxa2xx bypasses set_link and therefore does not use refcounts
* hw/s390x/s390-virtio-bus.c
* hw/virtio/virtio-pci.c
* hw/virtio/virtio-rng.c
* ui/console.c
- set_link is used and there is no explicit unref, do unref
Cc: Peter Crosthwaite <peter.crosthwaite@petalogix.com>
Cc: Alexander Graf <agraf@suse.de>
Cc: Anthony Liguori <aliguori@amazon.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2014-03-19 07:58:55 +00:00
|
|
|
prop->flags = flags;
|
|
|
|
|
2012-01-30 14:55:55 +00:00
|
|
|
full_type = g_strdup_printf("link<%s>", type);
|
|
|
|
|
2014-06-05 11:11:51 +00:00
|
|
|
op = object_property_add(obj, name, full_type,
|
|
|
|
object_get_link_property,
|
|
|
|
check ? object_set_link_property : NULL,
|
|
|
|
object_release_link_property,
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
prop);
|
2014-06-05 11:11:51 +00:00
|
|
|
op->resolve = object_resolve_link_property;
|
2020-05-05 15:29:14 +00:00
|
|
|
return op;
|
2012-01-30 14:55:55 +00:00
|
|
|
}
|
|
|
|
|
2020-05-05 15:29:14 +00:00
|
|
|
ObjectProperty *
|
|
|
|
object_property_add_link(Object *obj, const char *name,
|
|
|
|
const char *type, Object **targetp,
|
|
|
|
void (*check)(const Object *, const char *,
|
|
|
|
Object *, Error **),
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
ObjectPropertyLinkFlags flags)
|
2020-01-10 15:30:28 +00:00
|
|
|
{
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
return object_add_link_prop(obj, name, type, targetp, check, flags);
|
2020-01-10 15:30:28 +00:00
|
|
|
}
|
|
|
|
|
2020-01-10 15:30:29 +00:00
|
|
|
ObjectProperty *
|
|
|
|
object_class_property_add_link(ObjectClass *oc,
|
|
|
|
const char *name,
|
|
|
|
const char *type, ptrdiff_t offset,
|
|
|
|
void (*check)(const Object *obj, const char *name,
|
|
|
|
Object *val, Error **errp),
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
ObjectPropertyLinkFlags flags)
|
2020-01-10 15:30:29 +00:00
|
|
|
{
|
|
|
|
LinkProperty *prop = g_new0(LinkProperty, 1);
|
2020-05-05 15:29:10 +00:00
|
|
|
char *full_type;
|
2020-01-10 15:30:29 +00:00
|
|
|
ObjectProperty *op;
|
|
|
|
|
|
|
|
prop->offset = offset;
|
|
|
|
prop->check = check;
|
|
|
|
prop->flags = flags | OBJ_PROP_LINK_CLASS;
|
|
|
|
|
|
|
|
full_type = g_strdup_printf("link<%s>", type);
|
|
|
|
|
|
|
|
op = object_class_property_add(oc, name, full_type,
|
|
|
|
object_get_link_property,
|
|
|
|
check ? object_set_link_property : NULL,
|
|
|
|
object_release_link_property,
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
prop);
|
2020-01-10 15:30:29 +00:00
|
|
|
|
|
|
|
op->resolve = object_resolve_link_property;
|
|
|
|
|
|
|
|
g_free(full_type);
|
|
|
|
return op;
|
|
|
|
}
|
|
|
|
|
2020-05-05 15:29:14 +00:00
|
|
|
ObjectProperty *
|
|
|
|
object_property_add_const_link(Object *obj, const char *name,
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
Object *target)
|
2015-05-05 16:29:00 +00:00
|
|
|
{
|
2020-05-05 15:29:14 +00:00
|
|
|
return object_add_link_prop(obj, name,
|
|
|
|
object_get_typename(target), target,
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
NULL, OBJ_PROP_LINK_DIRECT);
|
2015-05-05 16:29:00 +00:00
|
|
|
}
|
|
|
|
|
2020-07-14 16:02:00 +00:00
|
|
|
const char *object_get_canonical_path_component(const Object *obj)
|
2014-03-03 10:30:02 +00:00
|
|
|
{
|
|
|
|
ObjectProperty *prop = NULL;
|
2015-10-13 12:37:45 +00:00
|
|
|
GHashTableIter iter;
|
2014-03-03 10:30:02 +00:00
|
|
|
|
2018-04-30 09:44:17 +00:00
|
|
|
if (obj->parent == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2014-03-03 10:30:02 +00:00
|
|
|
|
2015-10-13 12:37:45 +00:00
|
|
|
g_hash_table_iter_init(&iter, obj->parent->properties);
|
|
|
|
while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) {
|
2014-03-03 10:30:02 +00:00
|
|
|
if (!object_property_is_child(prop)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (prop->opaque == obj) {
|
2020-07-14 16:02:00 +00:00
|
|
|
return prop->name;
|
2014-03-03 10:30:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* obj had a parent but was not a child, should never happen */
|
|
|
|
g_assert_not_reached();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-05-27 08:47:53 +00:00
|
|
|
char *object_get_canonical_path(const Object *obj)
|
2012-01-30 14:55:55 +00:00
|
|
|
{
|
|
|
|
Object *root = object_get_root();
|
2014-03-03 10:30:02 +00:00
|
|
|
char *newpath, *path = NULL;
|
2012-01-30 14:55:55 +00:00
|
|
|
|
2018-05-30 16:16:04 +00:00
|
|
|
if (obj == root) {
|
|
|
|
return g_strdup("/");
|
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
2020-07-14 16:02:00 +00:00
|
|
|
const char *component = object_get_canonical_path_component(obj);
|
2012-01-30 14:55:55 +00:00
|
|
|
|
2018-05-30 16:16:04 +00:00
|
|
|
if (!component) {
|
|
|
|
/* A canonical path must be complete, so discard what was
|
|
|
|
* collected so far.
|
|
|
|
*/
|
2014-03-03 10:30:02 +00:00
|
|
|
g_free(path);
|
2018-05-30 16:16:04 +00:00
|
|
|
return NULL;
|
2012-01-30 14:55:55 +00:00
|
|
|
}
|
|
|
|
|
2018-05-30 16:16:04 +00:00
|
|
|
newpath = g_strdup_printf("/%s%s", component, path ? path : "");
|
|
|
|
g_free(path);
|
|
|
|
path = newpath;
|
2012-01-30 14:55:55 +00:00
|
|
|
obj = obj->parent;
|
2018-05-30 16:16:04 +00:00
|
|
|
} while (obj != root);
|
2012-01-30 14:55:55 +00:00
|
|
|
|
2018-05-30 16:16:04 +00:00
|
|
|
return path;
|
2012-01-30 14:55:55 +00:00
|
|
|
}
|
|
|
|
|
2020-05-05 15:29:10 +00:00
|
|
|
Object *object_resolve_path_component(Object *parent, const char *part)
|
2012-03-27 16:38:45 +00:00
|
|
|
{
|
2020-09-14 13:56:17 +00:00
|
|
|
ObjectProperty *prop = object_property_find(parent, part);
|
2012-03-27 16:38:45 +00:00
|
|
|
if (prop == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2014-06-05 11:11:51 +00:00
|
|
|
if (prop->resolve) {
|
|
|
|
return prop->resolve(parent, prop->opaque, part);
|
2012-03-27 16:38:45 +00:00
|
|
|
} else {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-30 14:55:55 +00:00
|
|
|
static Object *object_resolve_abs_path(Object *parent,
|
2020-05-10 01:32:35 +00:00
|
|
|
char **parts,
|
|
|
|
const char *typename)
|
2012-01-30 14:55:55 +00:00
|
|
|
{
|
|
|
|
Object *child;
|
|
|
|
|
2020-05-10 01:32:35 +00:00
|
|
|
if (*parts == NULL) {
|
2012-02-03 10:21:01 +00:00
|
|
|
return object_dynamic_cast(parent, typename);
|
2012-01-30 14:55:55 +00:00
|
|
|
}
|
|
|
|
|
2020-05-10 01:32:35 +00:00
|
|
|
if (strcmp(*parts, "") == 0) {
|
|
|
|
return object_resolve_abs_path(parent, parts + 1, typename);
|
2012-01-30 14:55:55 +00:00
|
|
|
}
|
|
|
|
|
2020-05-10 01:32:35 +00:00
|
|
|
child = object_resolve_path_component(parent, *parts);
|
2012-01-30 14:55:55 +00:00
|
|
|
if (!child) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-05-10 01:32:35 +00:00
|
|
|
return object_resolve_abs_path(child, parts + 1, typename);
|
2012-01-30 14:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static Object *object_resolve_partial_path(Object *parent,
|
2020-05-05 15:29:10 +00:00
|
|
|
char **parts,
|
|
|
|
const char *typename,
|
|
|
|
bool *ambiguous)
|
2012-01-30 14:55:55 +00:00
|
|
|
{
|
|
|
|
Object *obj;
|
2015-10-13 12:37:45 +00:00
|
|
|
GHashTableIter iter;
|
2012-01-30 14:55:55 +00:00
|
|
|
ObjectProperty *prop;
|
|
|
|
|
2020-05-10 01:32:35 +00:00
|
|
|
obj = object_resolve_abs_path(parent, parts, typename);
|
2012-01-30 14:55:55 +00:00
|
|
|
|
2015-10-13 12:37:45 +00:00
|
|
|
g_hash_table_iter_init(&iter, parent->properties);
|
|
|
|
while (g_hash_table_iter_next(&iter, NULL, (gpointer *)&prop)) {
|
2012-01-30 14:55:55 +00:00
|
|
|
Object *found;
|
|
|
|
|
2012-05-26 22:32:40 +00:00
|
|
|
if (!object_property_is_child(prop)) {
|
2012-01-30 14:55:55 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2012-02-03 10:21:01 +00:00
|
|
|
found = object_resolve_partial_path(prop->opaque, parts,
|
|
|
|
typename, ambiguous);
|
2012-01-30 14:55:55 +00:00
|
|
|
if (found) {
|
|
|
|
if (obj) {
|
2017-07-07 21:30:52 +00:00
|
|
|
*ambiguous = true;
|
2012-01-30 14:55:55 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
obj = found;
|
|
|
|
}
|
|
|
|
|
2017-07-07 21:30:52 +00:00
|
|
|
if (*ambiguous) {
|
2012-01-30 14:55:55 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
2012-02-03 10:21:01 +00:00
|
|
|
Object *object_resolve_path_type(const char *path, const char *typename,
|
2017-07-07 21:30:52 +00:00
|
|
|
bool *ambiguousp)
|
2012-01-30 14:55:55 +00:00
|
|
|
{
|
|
|
|
Object *obj;
|
2020-05-05 15:29:10 +00:00
|
|
|
char **parts;
|
2012-01-30 14:55:55 +00:00
|
|
|
|
|
|
|
parts = g_strsplit(path, "/", 0);
|
2013-04-18 16:44:02 +00:00
|
|
|
assert(parts);
|
2012-01-30 14:55:55 +00:00
|
|
|
|
2013-04-18 16:44:02 +00:00
|
|
|
if (parts[0] == NULL || strcmp(parts[0], "") != 0) {
|
2017-07-07 21:30:52 +00:00
|
|
|
bool ambiguous = false;
|
2012-02-03 10:21:01 +00:00
|
|
|
obj = object_resolve_partial_path(object_get_root(), parts,
|
2017-07-07 21:30:52 +00:00
|
|
|
typename, &ambiguous);
|
|
|
|
if (ambiguousp) {
|
|
|
|
*ambiguousp = ambiguous;
|
|
|
|
}
|
2012-01-30 14:55:55 +00:00
|
|
|
} else {
|
2020-05-10 01:32:35 +00:00
|
|
|
obj = object_resolve_abs_path(object_get_root(), parts + 1, typename);
|
2012-01-30 14:55:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
g_strfreev(parts);
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
2012-02-03 10:21:01 +00:00
|
|
|
Object *object_resolve_path(const char *path, bool *ambiguous)
|
|
|
|
{
|
|
|
|
return object_resolve_path_type(path, TYPE_OBJECT, ambiguous);
|
|
|
|
}
|
|
|
|
|
2012-01-30 14:55:55 +00:00
|
|
|
typedef struct StringProperty
|
|
|
|
{
|
|
|
|
char *(*get)(Object *, Error **);
|
|
|
|
void (*set)(Object *, const char *, Error **);
|
|
|
|
} StringProperty;
|
|
|
|
|
qom: Swap 'name' next to visitor in ObjectPropertyAccessor
Similar to the previous patch, it's nice to have all functions
in the tree that involve a visitor and a name for conversion to
or from QAPI to consistently stick the 'name' parameter next
to the Visitor parameter.
Done by manually changing include/qom/object.h and qom/object.c,
then running this Coccinelle script and touching up the fallout
(Coccinelle insisted on adding some trailing whitespace).
@ rule1 @
identifier fn;
typedef Object, Visitor, Error;
identifier obj, v, opaque, name, errp;
@@
void fn
- (Object *obj, Visitor *v, void *opaque, const char *name,
+ (Object *obj, Visitor *v, const char *name, void *opaque,
Error **errp) { ... }
@@
identifier rule1.fn;
expression obj, v, opaque, name, errp;
@@
fn(obj, v,
- opaque, name,
+ name, opaque,
errp)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-20-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 13:48:55 +00:00
|
|
|
static void property_get_str(Object *obj, Visitor *v, const char *name,
|
|
|
|
void *opaque, Error **errp)
|
2012-01-30 14:55:55 +00:00
|
|
|
{
|
|
|
|
StringProperty *prop = opaque;
|
|
|
|
char *value;
|
2015-08-25 18:00:46 +00:00
|
|
|
Error *err = NULL;
|
2012-01-30 14:55:55 +00:00
|
|
|
|
2015-08-25 18:00:46 +00:00
|
|
|
value = prop->get(obj, &err);
|
|
|
|
if (err) {
|
|
|
|
error_propagate(errp, err);
|
|
|
|
return;
|
2012-01-30 14:55:55 +00:00
|
|
|
}
|
2015-08-25 18:00:46 +00:00
|
|
|
|
qapi: Swap visit_* arguments for consistent 'name' placement
JSON uses "name":value, but many of our visitor interfaces were
called with visit_type_FOO(v, &value, name, errp). This can be
a bit confusing to have to mentally swap the parameter order to
match JSON order. It's particularly bad for visit_start_struct(),
where the 'name' parameter is smack in the middle of the
otherwise-related group of 'obj, kind, size' parameters! It's
time to do a global swap of the parameter ordering, so that the
'name' parameter is always immediately after the Visitor argument.
Additional reason in favor of the swap: the existing include/qjson.h
prefers listing 'name' first in json_prop_*(), and I have plans to
unify that file with the qapi visitors; listing 'name' first in
qapi will minimize churn to the (admittedly few) qjson.h clients.
Later patches will then fix docs, object.h, visitor-impl.h, and
those clients to match.
Done by first patching scripts/qapi*.py by hand to make generated
files do what I want, then by running the following Coccinelle
script to affect the rest of the code base:
$ spatch --sp-file script `git grep -l '\bvisit_' -- '**/*.[ch]'`
I then had to apply some touchups (Coccinelle insisted on TAB
indentation in visitor.h, and botched the signature of
visit_type_enum() by rewriting 'const char *const strings[]' to
the syntactically invalid 'const char*const[] strings'). The
movement of parameters is sufficient to provoke compiler errors
if any callers were missed.
// Part 1: Swap declaration order
@@
type TV, TErr, TObj, T1, T2;
identifier OBJ, ARG1, ARG2;
@@
void visit_start_struct
-(TV v, TObj OBJ, T1 ARG1, const char *name, T2 ARG2, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp)
{ ... }
@@
type bool, TV, T1;
identifier ARG1;
@@
bool visit_optional
-(TV v, T1 ARG1, const char *name)
+(TV v, const char *name, T1 ARG1)
{ ... }
@@
type TV, TErr, TObj, T1;
identifier OBJ, ARG1;
@@
void visit_get_next_type
-(TV v, TObj OBJ, T1 ARG1, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, TErr errp)
{ ... }
@@
type TV, TErr, TObj, T1, T2;
identifier OBJ, ARG1, ARG2;
@@
void visit_type_enum
-(TV v, TObj OBJ, T1 ARG1, T2 ARG2, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp)
{ ... }
@@
type TV, TErr, TObj;
identifier OBJ;
identifier VISIT_TYPE =~ "^visit_type_";
@@
void VISIT_TYPE
-(TV v, TObj OBJ, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, TErr errp)
{ ... }
// Part 2: swap caller order
@@
expression V, NAME, OBJ, ARG1, ARG2, ERR;
identifier VISIT_TYPE =~ "^visit_type_";
@@
(
-visit_start_struct(V, OBJ, ARG1, NAME, ARG2, ERR)
+visit_start_struct(V, NAME, OBJ, ARG1, ARG2, ERR)
|
-visit_optional(V, ARG1, NAME)
+visit_optional(V, NAME, ARG1)
|
-visit_get_next_type(V, OBJ, ARG1, NAME, ERR)
+visit_get_next_type(V, NAME, OBJ, ARG1, ERR)
|
-visit_type_enum(V, OBJ, ARG1, ARG2, NAME, ERR)
+visit_type_enum(V, NAME, OBJ, ARG1, ARG2, ERR)
|
-VISIT_TYPE(V, OBJ, NAME, ERR)
+VISIT_TYPE(V, NAME, OBJ, ERR)
)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-19-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 13:48:54 +00:00
|
|
|
visit_type_str(v, name, &value, errp);
|
2015-08-25 18:00:46 +00:00
|
|
|
g_free(value);
|
2012-01-30 14:55:55 +00:00
|
|
|
}
|
|
|
|
|
qom: Swap 'name' next to visitor in ObjectPropertyAccessor
Similar to the previous patch, it's nice to have all functions
in the tree that involve a visitor and a name for conversion to
or from QAPI to consistently stick the 'name' parameter next
to the Visitor parameter.
Done by manually changing include/qom/object.h and qom/object.c,
then running this Coccinelle script and touching up the fallout
(Coccinelle insisted on adding some trailing whitespace).
@ rule1 @
identifier fn;
typedef Object, Visitor, Error;
identifier obj, v, opaque, name, errp;
@@
void fn
- (Object *obj, Visitor *v, void *opaque, const char *name,
+ (Object *obj, Visitor *v, const char *name, void *opaque,
Error **errp) { ... }
@@
identifier rule1.fn;
expression obj, v, opaque, name, errp;
@@
fn(obj, v,
- opaque, name,
+ name, opaque,
errp)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-20-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 13:48:55 +00:00
|
|
|
static void property_set_str(Object *obj, Visitor *v, const char *name,
|
|
|
|
void *opaque, Error **errp)
|
2012-01-30 14:55:55 +00:00
|
|
|
{
|
|
|
|
StringProperty *prop = opaque;
|
|
|
|
char *value;
|
|
|
|
|
error: Eliminate error_propagate() with Coccinelle, part 1
When all we do with an Error we receive into a local variable is
propagating to somewhere else, we can just as well receive it there
right away. Convert
if (!foo(..., &err)) {
...
error_propagate(errp, err);
...
return ...
}
to
if (!foo(..., errp)) {
...
...
return ...
}
where nothing else needs @err. Coccinelle script:
@rule1 forall@
identifier fun, err, errp, lbl;
expression list args, args2;
binary operator op;
constant c1, c2;
symbol false;
@@
if (
(
- fun(args, &err, args2)
+ fun(args, errp, args2)
|
- !fun(args, &err, args2)
+ !fun(args, errp, args2)
|
- fun(args, &err, args2) op c1
+ fun(args, errp, args2) op c1
)
)
{
... when != err
when != lbl:
when strict
- error_propagate(errp, err);
... when != err
(
return;
|
return c2;
|
return false;
)
}
@rule2 forall@
identifier fun, err, errp, lbl;
expression list args, args2;
expression var;
binary operator op;
constant c1, c2;
symbol false;
@@
- var = fun(args, &err, args2);
+ var = fun(args, errp, args2);
... when != err
if (
(
var
|
!var
|
var op c1
)
)
{
... when != err
when != lbl:
when strict
- error_propagate(errp, err);
... when != err
(
return;
|
return c2;
|
return false;
|
return var;
)
}
@depends on rule1 || rule2@
identifier err;
@@
- Error *err = NULL;
... when != err
Not exactly elegant, I'm afraid.
The "when != lbl:" is necessary to avoid transforming
if (fun(args, &err)) {
goto out
}
...
out:
error_propagate(errp, err);
even though other paths to label out still need the error_propagate().
For an actual example, see sclp_realize().
Without the "when strict", Coccinelle transforms vfio_msix_setup(),
incorrectly. I don't know what exactly "when strict" does, only that
it helps here.
The match of return is narrower than what I want, but I can't figure
out how to express "return where the operand doesn't use @err". For
an example where it's too narrow, see vfio_intx_enable().
Silently fails to convert hw/arm/armsse.c, because Coccinelle gets
confused by ARMSSE being used both as typedef and function-like macro
there. Converted manually.
Line breaks tidied up manually. One nested declaration of @local_err
deleted manually. Preexisting unwanted blank line dropped in
hw/riscv/sifive_e.c.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20200707160613.848843-35-armbru@redhat.com>
2020-07-07 16:06:02 +00:00
|
|
|
if (!visit_type_str(v, name, &value, errp)) {
|
2012-01-30 14:55:55 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
prop->set(obj, value, errp);
|
|
|
|
g_free(value);
|
|
|
|
}
|
|
|
|
|
2020-10-27 16:12:57 +00:00
|
|
|
static void property_release_data(Object *obj, const char *name,
|
|
|
|
void *opaque)
|
2012-01-30 14:55:55 +00:00
|
|
|
{
|
2020-10-27 16:12:57 +00:00
|
|
|
g_free(opaque);
|
2012-01-30 14:55:55 +00:00
|
|
|
}
|
|
|
|
|
2020-05-05 15:29:14 +00:00
|
|
|
ObjectProperty *
|
|
|
|
object_property_add_str(Object *obj, const char *name,
|
|
|
|
char *(*get)(Object *, Error **),
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
void (*set)(Object *, const char *, Error **))
|
2012-01-30 14:55:55 +00:00
|
|
|
{
|
|
|
|
StringProperty *prop = g_malloc0(sizeof(*prop));
|
|
|
|
|
|
|
|
prop->get = get;
|
|
|
|
prop->set = set;
|
|
|
|
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
return object_property_add(obj, name, "string",
|
|
|
|
get ? property_get_str : NULL,
|
|
|
|
set ? property_set_str : NULL,
|
2020-10-27 16:12:57 +00:00
|
|
|
property_release_data,
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
prop);
|
2012-01-30 14:55:55 +00:00
|
|
|
}
|
2012-03-31 14:45:54 +00:00
|
|
|
|
2020-01-10 15:30:21 +00:00
|
|
|
ObjectProperty *
|
|
|
|
object_class_property_add_str(ObjectClass *klass, const char *name,
|
2015-10-13 12:37:46 +00:00
|
|
|
char *(*get)(Object *, Error **),
|
|
|
|
void (*set)(Object *, const char *,
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
Error **))
|
2015-10-13 12:37:46 +00:00
|
|
|
{
|
|
|
|
StringProperty *prop = g_malloc0(sizeof(*prop));
|
|
|
|
|
|
|
|
prop->get = get;
|
|
|
|
prop->set = set;
|
|
|
|
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
return object_class_property_add(klass, name, "string",
|
|
|
|
get ? property_get_str : NULL,
|
|
|
|
set ? property_set_str : NULL,
|
|
|
|
NULL,
|
|
|
|
prop);
|
2015-10-13 12:37:46 +00:00
|
|
|
}
|
|
|
|
|
2012-06-25 15:32:46 +00:00
|
|
|
typedef struct BoolProperty
|
|
|
|
{
|
|
|
|
bool (*get)(Object *, Error **);
|
|
|
|
void (*set)(Object *, bool, Error **);
|
|
|
|
} BoolProperty;
|
|
|
|
|
qom: Swap 'name' next to visitor in ObjectPropertyAccessor
Similar to the previous patch, it's nice to have all functions
in the tree that involve a visitor and a name for conversion to
or from QAPI to consistently stick the 'name' parameter next
to the Visitor parameter.
Done by manually changing include/qom/object.h and qom/object.c,
then running this Coccinelle script and touching up the fallout
(Coccinelle insisted on adding some trailing whitespace).
@ rule1 @
identifier fn;
typedef Object, Visitor, Error;
identifier obj, v, opaque, name, errp;
@@
void fn
- (Object *obj, Visitor *v, void *opaque, const char *name,
+ (Object *obj, Visitor *v, const char *name, void *opaque,
Error **errp) { ... }
@@
identifier rule1.fn;
expression obj, v, opaque, name, errp;
@@
fn(obj, v,
- opaque, name,
+ name, opaque,
errp)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-20-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 13:48:55 +00:00
|
|
|
static void property_get_bool(Object *obj, Visitor *v, const char *name,
|
|
|
|
void *opaque, Error **errp)
|
2012-06-25 15:32:46 +00:00
|
|
|
{
|
|
|
|
BoolProperty *prop = opaque;
|
|
|
|
bool value;
|
2015-08-25 18:00:45 +00:00
|
|
|
Error *err = NULL;
|
|
|
|
|
|
|
|
value = prop->get(obj, &err);
|
|
|
|
if (err) {
|
|
|
|
error_propagate(errp, err);
|
|
|
|
return;
|
|
|
|
}
|
2012-06-25 15:32:46 +00:00
|
|
|
|
qapi: Swap visit_* arguments for consistent 'name' placement
JSON uses "name":value, but many of our visitor interfaces were
called with visit_type_FOO(v, &value, name, errp). This can be
a bit confusing to have to mentally swap the parameter order to
match JSON order. It's particularly bad for visit_start_struct(),
where the 'name' parameter is smack in the middle of the
otherwise-related group of 'obj, kind, size' parameters! It's
time to do a global swap of the parameter ordering, so that the
'name' parameter is always immediately after the Visitor argument.
Additional reason in favor of the swap: the existing include/qjson.h
prefers listing 'name' first in json_prop_*(), and I have plans to
unify that file with the qapi visitors; listing 'name' first in
qapi will minimize churn to the (admittedly few) qjson.h clients.
Later patches will then fix docs, object.h, visitor-impl.h, and
those clients to match.
Done by first patching scripts/qapi*.py by hand to make generated
files do what I want, then by running the following Coccinelle
script to affect the rest of the code base:
$ spatch --sp-file script `git grep -l '\bvisit_' -- '**/*.[ch]'`
I then had to apply some touchups (Coccinelle insisted on TAB
indentation in visitor.h, and botched the signature of
visit_type_enum() by rewriting 'const char *const strings[]' to
the syntactically invalid 'const char*const[] strings'). The
movement of parameters is sufficient to provoke compiler errors
if any callers were missed.
// Part 1: Swap declaration order
@@
type TV, TErr, TObj, T1, T2;
identifier OBJ, ARG1, ARG2;
@@
void visit_start_struct
-(TV v, TObj OBJ, T1 ARG1, const char *name, T2 ARG2, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp)
{ ... }
@@
type bool, TV, T1;
identifier ARG1;
@@
bool visit_optional
-(TV v, T1 ARG1, const char *name)
+(TV v, const char *name, T1 ARG1)
{ ... }
@@
type TV, TErr, TObj, T1;
identifier OBJ, ARG1;
@@
void visit_get_next_type
-(TV v, TObj OBJ, T1 ARG1, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, TErr errp)
{ ... }
@@
type TV, TErr, TObj, T1, T2;
identifier OBJ, ARG1, ARG2;
@@
void visit_type_enum
-(TV v, TObj OBJ, T1 ARG1, T2 ARG2, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp)
{ ... }
@@
type TV, TErr, TObj;
identifier OBJ;
identifier VISIT_TYPE =~ "^visit_type_";
@@
void VISIT_TYPE
-(TV v, TObj OBJ, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, TErr errp)
{ ... }
// Part 2: swap caller order
@@
expression V, NAME, OBJ, ARG1, ARG2, ERR;
identifier VISIT_TYPE =~ "^visit_type_";
@@
(
-visit_start_struct(V, OBJ, ARG1, NAME, ARG2, ERR)
+visit_start_struct(V, NAME, OBJ, ARG1, ARG2, ERR)
|
-visit_optional(V, ARG1, NAME)
+visit_optional(V, NAME, ARG1)
|
-visit_get_next_type(V, OBJ, ARG1, NAME, ERR)
+visit_get_next_type(V, NAME, OBJ, ARG1, ERR)
|
-visit_type_enum(V, OBJ, ARG1, ARG2, NAME, ERR)
+visit_type_enum(V, NAME, OBJ, ARG1, ARG2, ERR)
|
-VISIT_TYPE(V, OBJ, NAME, ERR)
+VISIT_TYPE(V, NAME, OBJ, ERR)
)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-19-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 13:48:54 +00:00
|
|
|
visit_type_bool(v, name, &value, errp);
|
2012-06-25 15:32:46 +00:00
|
|
|
}
|
|
|
|
|
qom: Swap 'name' next to visitor in ObjectPropertyAccessor
Similar to the previous patch, it's nice to have all functions
in the tree that involve a visitor and a name for conversion to
or from QAPI to consistently stick the 'name' parameter next
to the Visitor parameter.
Done by manually changing include/qom/object.h and qom/object.c,
then running this Coccinelle script and touching up the fallout
(Coccinelle insisted on adding some trailing whitespace).
@ rule1 @
identifier fn;
typedef Object, Visitor, Error;
identifier obj, v, opaque, name, errp;
@@
void fn
- (Object *obj, Visitor *v, void *opaque, const char *name,
+ (Object *obj, Visitor *v, const char *name, void *opaque,
Error **errp) { ... }
@@
identifier rule1.fn;
expression obj, v, opaque, name, errp;
@@
fn(obj, v,
- opaque, name,
+ name, opaque,
errp)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-20-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 13:48:55 +00:00
|
|
|
static void property_set_bool(Object *obj, Visitor *v, const char *name,
|
|
|
|
void *opaque, Error **errp)
|
2012-06-25 15:32:46 +00:00
|
|
|
{
|
|
|
|
BoolProperty *prop = opaque;
|
|
|
|
bool value;
|
|
|
|
|
error: Eliminate error_propagate() with Coccinelle, part 1
When all we do with an Error we receive into a local variable is
propagating to somewhere else, we can just as well receive it there
right away. Convert
if (!foo(..., &err)) {
...
error_propagate(errp, err);
...
return ...
}
to
if (!foo(..., errp)) {
...
...
return ...
}
where nothing else needs @err. Coccinelle script:
@rule1 forall@
identifier fun, err, errp, lbl;
expression list args, args2;
binary operator op;
constant c1, c2;
symbol false;
@@
if (
(
- fun(args, &err, args2)
+ fun(args, errp, args2)
|
- !fun(args, &err, args2)
+ !fun(args, errp, args2)
|
- fun(args, &err, args2) op c1
+ fun(args, errp, args2) op c1
)
)
{
... when != err
when != lbl:
when strict
- error_propagate(errp, err);
... when != err
(
return;
|
return c2;
|
return false;
)
}
@rule2 forall@
identifier fun, err, errp, lbl;
expression list args, args2;
expression var;
binary operator op;
constant c1, c2;
symbol false;
@@
- var = fun(args, &err, args2);
+ var = fun(args, errp, args2);
... when != err
if (
(
var
|
!var
|
var op c1
)
)
{
... when != err
when != lbl:
when strict
- error_propagate(errp, err);
... when != err
(
return;
|
return c2;
|
return false;
|
return var;
)
}
@depends on rule1 || rule2@
identifier err;
@@
- Error *err = NULL;
... when != err
Not exactly elegant, I'm afraid.
The "when != lbl:" is necessary to avoid transforming
if (fun(args, &err)) {
goto out
}
...
out:
error_propagate(errp, err);
even though other paths to label out still need the error_propagate().
For an actual example, see sclp_realize().
Without the "when strict", Coccinelle transforms vfio_msix_setup(),
incorrectly. I don't know what exactly "when strict" does, only that
it helps here.
The match of return is narrower than what I want, but I can't figure
out how to express "return where the operand doesn't use @err". For
an example where it's too narrow, see vfio_intx_enable().
Silently fails to convert hw/arm/armsse.c, because Coccinelle gets
confused by ARMSSE being used both as typedef and function-like macro
there. Converted manually.
Line breaks tidied up manually. One nested declaration of @local_err
deleted manually. Preexisting unwanted blank line dropped in
hw/riscv/sifive_e.c.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20200707160613.848843-35-armbru@redhat.com>
2020-07-07 16:06:02 +00:00
|
|
|
if (!visit_type_bool(v, name, &value, errp)) {
|
2012-06-25 15:32:46 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
prop->set(obj, value, errp);
|
|
|
|
}
|
|
|
|
|
2020-05-05 15:29:14 +00:00
|
|
|
ObjectProperty *
|
|
|
|
object_property_add_bool(Object *obj, const char *name,
|
|
|
|
bool (*get)(Object *, Error **),
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
void (*set)(Object *, bool, Error **))
|
2012-06-25 15:32:46 +00:00
|
|
|
{
|
|
|
|
BoolProperty *prop = g_malloc0(sizeof(*prop));
|
|
|
|
|
|
|
|
prop->get = get;
|
|
|
|
prop->set = set;
|
|
|
|
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
return object_property_add(obj, name, "bool",
|
|
|
|
get ? property_get_bool : NULL,
|
|
|
|
set ? property_set_bool : NULL,
|
2020-10-27 16:12:57 +00:00
|
|
|
property_release_data,
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
prop);
|
2012-06-25 15:32:46 +00:00
|
|
|
}
|
|
|
|
|
2020-01-10 15:30:21 +00:00
|
|
|
ObjectProperty *
|
|
|
|
object_class_property_add_bool(ObjectClass *klass, const char *name,
|
2015-10-13 12:37:46 +00:00
|
|
|
bool (*get)(Object *, Error **),
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
void (*set)(Object *, bool, Error **))
|
2015-10-13 12:37:46 +00:00
|
|
|
{
|
|
|
|
BoolProperty *prop = g_malloc0(sizeof(*prop));
|
|
|
|
|
|
|
|
prop->get = get;
|
|
|
|
prop->set = set;
|
|
|
|
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
return object_class_property_add(klass, name, "bool",
|
|
|
|
get ? property_get_bool : NULL,
|
|
|
|
set ? property_set_bool : NULL,
|
|
|
|
NULL,
|
|
|
|
prop);
|
2015-10-13 12:37:46 +00:00
|
|
|
}
|
|
|
|
|
qom: Swap 'name' next to visitor in ObjectPropertyAccessor
Similar to the previous patch, it's nice to have all functions
in the tree that involve a visitor and a name for conversion to
or from QAPI to consistently stick the 'name' parameter next
to the Visitor parameter.
Done by manually changing include/qom/object.h and qom/object.c,
then running this Coccinelle script and touching up the fallout
(Coccinelle insisted on adding some trailing whitespace).
@ rule1 @
identifier fn;
typedef Object, Visitor, Error;
identifier obj, v, opaque, name, errp;
@@
void fn
- (Object *obj, Visitor *v, void *opaque, const char *name,
+ (Object *obj, Visitor *v, const char *name, void *opaque,
Error **errp) { ... }
@@
identifier rule1.fn;
expression obj, v, opaque, name, errp;
@@
fn(obj, v,
- opaque, name,
+ name, opaque,
errp)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-20-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 13:48:55 +00:00
|
|
|
static void property_get_enum(Object *obj, Visitor *v, const char *name,
|
|
|
|
void *opaque, Error **errp)
|
qom: Add an object_property_add_enum() helper function
A QOM property can be parsed as enum using the visit_type_enum()
helper function, but this forces callers to use the more complex
generic object_property_add() method when registering it. It
also requires that users of that object have access to the
string map when they want to read the property value.
This patch introduces a specialized object_property_add_enum()
method which simplifies the use of enum properties, so the
setters/getters directly get passed the int value.
typedef enum {
MYDEV_TYPE_FROG,
MYDEV_TYPE_ALLIGATOR,
MYDEV_TYPE_PLATYPUS,
MYDEV_TYPE_LAST
} MyDevType;
Then provide a table of enum <-> string mappings
static const char *const mydevtypemap[MYDEV_TYPE_LAST + 1] = {
[MYDEV_TYPE_FROG] = "frog",
[MYDEV_TYPE_ALLIGATOR] = "alligator",
[MYDEV_TYPE_PLATYPUS] = "platypus",
[MYDEV_TYPE_LAST] = NULL,
};
Assuming an object struct of
typedef struct {
Object parent_obj;
MyDevType devtype;
...other fields...
} MyDev;
The property can then be registered as follows:
static int mydev_prop_get_devtype(Object *obj,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
return dev->devtype;
}
static void mydev_prop_set_devtype(Object *obj,
int value,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
dev->devtype = value;
}
object_property_add_enum(obj, "devtype",
mydevtypemap, "MyDevType",
mydev_prop_get_devtype,
mydev_prop_set_devtype,
NULL);
Note there is no need to check the range of 'value' in
the setter, because the string->enum conversion code will
have already done that and reported an error as required.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 16:14:08 +00:00
|
|
|
{
|
|
|
|
EnumProperty *prop = opaque;
|
|
|
|
int value;
|
2015-08-25 18:00:45 +00:00
|
|
|
Error *err = NULL;
|
|
|
|
|
|
|
|
value = prop->get(obj, &err);
|
|
|
|
if (err) {
|
|
|
|
error_propagate(errp, err);
|
|
|
|
return;
|
|
|
|
}
|
qom: Add an object_property_add_enum() helper function
A QOM property can be parsed as enum using the visit_type_enum()
helper function, but this forces callers to use the more complex
generic object_property_add() method when registering it. It
also requires that users of that object have access to the
string map when they want to read the property value.
This patch introduces a specialized object_property_add_enum()
method which simplifies the use of enum properties, so the
setters/getters directly get passed the int value.
typedef enum {
MYDEV_TYPE_FROG,
MYDEV_TYPE_ALLIGATOR,
MYDEV_TYPE_PLATYPUS,
MYDEV_TYPE_LAST
} MyDevType;
Then provide a table of enum <-> string mappings
static const char *const mydevtypemap[MYDEV_TYPE_LAST + 1] = {
[MYDEV_TYPE_FROG] = "frog",
[MYDEV_TYPE_ALLIGATOR] = "alligator",
[MYDEV_TYPE_PLATYPUS] = "platypus",
[MYDEV_TYPE_LAST] = NULL,
};
Assuming an object struct of
typedef struct {
Object parent_obj;
MyDevType devtype;
...other fields...
} MyDev;
The property can then be registered as follows:
static int mydev_prop_get_devtype(Object *obj,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
return dev->devtype;
}
static void mydev_prop_set_devtype(Object *obj,
int value,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
dev->devtype = value;
}
object_property_add_enum(obj, "devtype",
mydevtypemap, "MyDevType",
mydev_prop_get_devtype,
mydev_prop_set_devtype,
NULL);
Note there is no need to check the range of 'value' in
the setter, because the string->enum conversion code will
have already done that and reported an error as required.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 16:14:08 +00:00
|
|
|
|
2017-08-24 08:46:10 +00:00
|
|
|
visit_type_enum(v, name, &value, prop->lookup, errp);
|
qom: Add an object_property_add_enum() helper function
A QOM property can be parsed as enum using the visit_type_enum()
helper function, but this forces callers to use the more complex
generic object_property_add() method when registering it. It
also requires that users of that object have access to the
string map when they want to read the property value.
This patch introduces a specialized object_property_add_enum()
method which simplifies the use of enum properties, so the
setters/getters directly get passed the int value.
typedef enum {
MYDEV_TYPE_FROG,
MYDEV_TYPE_ALLIGATOR,
MYDEV_TYPE_PLATYPUS,
MYDEV_TYPE_LAST
} MyDevType;
Then provide a table of enum <-> string mappings
static const char *const mydevtypemap[MYDEV_TYPE_LAST + 1] = {
[MYDEV_TYPE_FROG] = "frog",
[MYDEV_TYPE_ALLIGATOR] = "alligator",
[MYDEV_TYPE_PLATYPUS] = "platypus",
[MYDEV_TYPE_LAST] = NULL,
};
Assuming an object struct of
typedef struct {
Object parent_obj;
MyDevType devtype;
...other fields...
} MyDev;
The property can then be registered as follows:
static int mydev_prop_get_devtype(Object *obj,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
return dev->devtype;
}
static void mydev_prop_set_devtype(Object *obj,
int value,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
dev->devtype = value;
}
object_property_add_enum(obj, "devtype",
mydevtypemap, "MyDevType",
mydev_prop_get_devtype,
mydev_prop_set_devtype,
NULL);
Note there is no need to check the range of 'value' in
the setter, because the string->enum conversion code will
have already done that and reported an error as required.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 16:14:08 +00:00
|
|
|
}
|
|
|
|
|
qom: Swap 'name' next to visitor in ObjectPropertyAccessor
Similar to the previous patch, it's nice to have all functions
in the tree that involve a visitor and a name for conversion to
or from QAPI to consistently stick the 'name' parameter next
to the Visitor parameter.
Done by manually changing include/qom/object.h and qom/object.c,
then running this Coccinelle script and touching up the fallout
(Coccinelle insisted on adding some trailing whitespace).
@ rule1 @
identifier fn;
typedef Object, Visitor, Error;
identifier obj, v, opaque, name, errp;
@@
void fn
- (Object *obj, Visitor *v, void *opaque, const char *name,
+ (Object *obj, Visitor *v, const char *name, void *opaque,
Error **errp) { ... }
@@
identifier rule1.fn;
expression obj, v, opaque, name, errp;
@@
fn(obj, v,
- opaque, name,
+ name, opaque,
errp)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-20-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 13:48:55 +00:00
|
|
|
static void property_set_enum(Object *obj, Visitor *v, const char *name,
|
|
|
|
void *opaque, Error **errp)
|
qom: Add an object_property_add_enum() helper function
A QOM property can be parsed as enum using the visit_type_enum()
helper function, but this forces callers to use the more complex
generic object_property_add() method when registering it. It
also requires that users of that object have access to the
string map when they want to read the property value.
This patch introduces a specialized object_property_add_enum()
method which simplifies the use of enum properties, so the
setters/getters directly get passed the int value.
typedef enum {
MYDEV_TYPE_FROG,
MYDEV_TYPE_ALLIGATOR,
MYDEV_TYPE_PLATYPUS,
MYDEV_TYPE_LAST
} MyDevType;
Then provide a table of enum <-> string mappings
static const char *const mydevtypemap[MYDEV_TYPE_LAST + 1] = {
[MYDEV_TYPE_FROG] = "frog",
[MYDEV_TYPE_ALLIGATOR] = "alligator",
[MYDEV_TYPE_PLATYPUS] = "platypus",
[MYDEV_TYPE_LAST] = NULL,
};
Assuming an object struct of
typedef struct {
Object parent_obj;
MyDevType devtype;
...other fields...
} MyDev;
The property can then be registered as follows:
static int mydev_prop_get_devtype(Object *obj,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
return dev->devtype;
}
static void mydev_prop_set_devtype(Object *obj,
int value,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
dev->devtype = value;
}
object_property_add_enum(obj, "devtype",
mydevtypemap, "MyDevType",
mydev_prop_get_devtype,
mydev_prop_set_devtype,
NULL);
Note there is no need to check the range of 'value' in
the setter, because the string->enum conversion code will
have already done that and reported an error as required.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 16:14:08 +00:00
|
|
|
{
|
|
|
|
EnumProperty *prop = opaque;
|
|
|
|
int value;
|
|
|
|
|
error: Eliminate error_propagate() with Coccinelle, part 1
When all we do with an Error we receive into a local variable is
propagating to somewhere else, we can just as well receive it there
right away. Convert
if (!foo(..., &err)) {
...
error_propagate(errp, err);
...
return ...
}
to
if (!foo(..., errp)) {
...
...
return ...
}
where nothing else needs @err. Coccinelle script:
@rule1 forall@
identifier fun, err, errp, lbl;
expression list args, args2;
binary operator op;
constant c1, c2;
symbol false;
@@
if (
(
- fun(args, &err, args2)
+ fun(args, errp, args2)
|
- !fun(args, &err, args2)
+ !fun(args, errp, args2)
|
- fun(args, &err, args2) op c1
+ fun(args, errp, args2) op c1
)
)
{
... when != err
when != lbl:
when strict
- error_propagate(errp, err);
... when != err
(
return;
|
return c2;
|
return false;
)
}
@rule2 forall@
identifier fun, err, errp, lbl;
expression list args, args2;
expression var;
binary operator op;
constant c1, c2;
symbol false;
@@
- var = fun(args, &err, args2);
+ var = fun(args, errp, args2);
... when != err
if (
(
var
|
!var
|
var op c1
)
)
{
... when != err
when != lbl:
when strict
- error_propagate(errp, err);
... when != err
(
return;
|
return c2;
|
return false;
|
return var;
)
}
@depends on rule1 || rule2@
identifier err;
@@
- Error *err = NULL;
... when != err
Not exactly elegant, I'm afraid.
The "when != lbl:" is necessary to avoid transforming
if (fun(args, &err)) {
goto out
}
...
out:
error_propagate(errp, err);
even though other paths to label out still need the error_propagate().
For an actual example, see sclp_realize().
Without the "when strict", Coccinelle transforms vfio_msix_setup(),
incorrectly. I don't know what exactly "when strict" does, only that
it helps here.
The match of return is narrower than what I want, but I can't figure
out how to express "return where the operand doesn't use @err". For
an example where it's too narrow, see vfio_intx_enable().
Silently fails to convert hw/arm/armsse.c, because Coccinelle gets
confused by ARMSSE being used both as typedef and function-like macro
there. Converted manually.
Line breaks tidied up manually. One nested declaration of @local_err
deleted manually. Preexisting unwanted blank line dropped in
hw/riscv/sifive_e.c.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20200707160613.848843-35-armbru@redhat.com>
2020-07-07 16:06:02 +00:00
|
|
|
if (!visit_type_enum(v, name, &value, prop->lookup, errp)) {
|
2015-08-25 18:00:45 +00:00
|
|
|
return;
|
|
|
|
}
|
qom: Add an object_property_add_enum() helper function
A QOM property can be parsed as enum using the visit_type_enum()
helper function, but this forces callers to use the more complex
generic object_property_add() method when registering it. It
also requires that users of that object have access to the
string map when they want to read the property value.
This patch introduces a specialized object_property_add_enum()
method which simplifies the use of enum properties, so the
setters/getters directly get passed the int value.
typedef enum {
MYDEV_TYPE_FROG,
MYDEV_TYPE_ALLIGATOR,
MYDEV_TYPE_PLATYPUS,
MYDEV_TYPE_LAST
} MyDevType;
Then provide a table of enum <-> string mappings
static const char *const mydevtypemap[MYDEV_TYPE_LAST + 1] = {
[MYDEV_TYPE_FROG] = "frog",
[MYDEV_TYPE_ALLIGATOR] = "alligator",
[MYDEV_TYPE_PLATYPUS] = "platypus",
[MYDEV_TYPE_LAST] = NULL,
};
Assuming an object struct of
typedef struct {
Object parent_obj;
MyDevType devtype;
...other fields...
} MyDev;
The property can then be registered as follows:
static int mydev_prop_get_devtype(Object *obj,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
return dev->devtype;
}
static void mydev_prop_set_devtype(Object *obj,
int value,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
dev->devtype = value;
}
object_property_add_enum(obj, "devtype",
mydevtypemap, "MyDevType",
mydev_prop_get_devtype,
mydev_prop_set_devtype,
NULL);
Note there is no need to check the range of 'value' in
the setter, because the string->enum conversion code will
have already done that and reported an error as required.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 16:14:08 +00:00
|
|
|
prop->set(obj, value, errp);
|
|
|
|
}
|
|
|
|
|
2020-05-05 15:29:14 +00:00
|
|
|
ObjectProperty *
|
|
|
|
object_property_add_enum(Object *obj, const char *name,
|
|
|
|
const char *typename,
|
|
|
|
const QEnumLookup *lookup,
|
|
|
|
int (*get)(Object *, Error **),
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
void (*set)(Object *, int, Error **))
|
qom: Add an object_property_add_enum() helper function
A QOM property can be parsed as enum using the visit_type_enum()
helper function, but this forces callers to use the more complex
generic object_property_add() method when registering it. It
also requires that users of that object have access to the
string map when they want to read the property value.
This patch introduces a specialized object_property_add_enum()
method which simplifies the use of enum properties, so the
setters/getters directly get passed the int value.
typedef enum {
MYDEV_TYPE_FROG,
MYDEV_TYPE_ALLIGATOR,
MYDEV_TYPE_PLATYPUS,
MYDEV_TYPE_LAST
} MyDevType;
Then provide a table of enum <-> string mappings
static const char *const mydevtypemap[MYDEV_TYPE_LAST + 1] = {
[MYDEV_TYPE_FROG] = "frog",
[MYDEV_TYPE_ALLIGATOR] = "alligator",
[MYDEV_TYPE_PLATYPUS] = "platypus",
[MYDEV_TYPE_LAST] = NULL,
};
Assuming an object struct of
typedef struct {
Object parent_obj;
MyDevType devtype;
...other fields...
} MyDev;
The property can then be registered as follows:
static int mydev_prop_get_devtype(Object *obj,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
return dev->devtype;
}
static void mydev_prop_set_devtype(Object *obj,
int value,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
dev->devtype = value;
}
object_property_add_enum(obj, "devtype",
mydevtypemap, "MyDevType",
mydev_prop_get_devtype,
mydev_prop_set_devtype,
NULL);
Note there is no need to check the range of 'value' in
the setter, because the string->enum conversion code will
have already done that and reported an error as required.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 16:14:08 +00:00
|
|
|
{
|
|
|
|
EnumProperty *prop = g_malloc(sizeof(*prop));
|
|
|
|
|
2017-08-24 08:46:10 +00:00
|
|
|
prop->lookup = lookup;
|
qom: Add an object_property_add_enum() helper function
A QOM property can be parsed as enum using the visit_type_enum()
helper function, but this forces callers to use the more complex
generic object_property_add() method when registering it. It
also requires that users of that object have access to the
string map when they want to read the property value.
This patch introduces a specialized object_property_add_enum()
method which simplifies the use of enum properties, so the
setters/getters directly get passed the int value.
typedef enum {
MYDEV_TYPE_FROG,
MYDEV_TYPE_ALLIGATOR,
MYDEV_TYPE_PLATYPUS,
MYDEV_TYPE_LAST
} MyDevType;
Then provide a table of enum <-> string mappings
static const char *const mydevtypemap[MYDEV_TYPE_LAST + 1] = {
[MYDEV_TYPE_FROG] = "frog",
[MYDEV_TYPE_ALLIGATOR] = "alligator",
[MYDEV_TYPE_PLATYPUS] = "platypus",
[MYDEV_TYPE_LAST] = NULL,
};
Assuming an object struct of
typedef struct {
Object parent_obj;
MyDevType devtype;
...other fields...
} MyDev;
The property can then be registered as follows:
static int mydev_prop_get_devtype(Object *obj,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
return dev->devtype;
}
static void mydev_prop_set_devtype(Object *obj,
int value,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
dev->devtype = value;
}
object_property_add_enum(obj, "devtype",
mydevtypemap, "MyDevType",
mydev_prop_get_devtype,
mydev_prop_set_devtype,
NULL);
Note there is no need to check the range of 'value' in
the setter, because the string->enum conversion code will
have already done that and reported an error as required.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 16:14:08 +00:00
|
|
|
prop->get = get;
|
|
|
|
prop->set = set;
|
|
|
|
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
return object_property_add(obj, name, typename,
|
|
|
|
get ? property_get_enum : NULL,
|
|
|
|
set ? property_set_enum : NULL,
|
2020-10-27 16:12:57 +00:00
|
|
|
property_release_data,
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
prop);
|
qom: Add an object_property_add_enum() helper function
A QOM property can be parsed as enum using the visit_type_enum()
helper function, but this forces callers to use the more complex
generic object_property_add() method when registering it. It
also requires that users of that object have access to the
string map when they want to read the property value.
This patch introduces a specialized object_property_add_enum()
method which simplifies the use of enum properties, so the
setters/getters directly get passed the int value.
typedef enum {
MYDEV_TYPE_FROG,
MYDEV_TYPE_ALLIGATOR,
MYDEV_TYPE_PLATYPUS,
MYDEV_TYPE_LAST
} MyDevType;
Then provide a table of enum <-> string mappings
static const char *const mydevtypemap[MYDEV_TYPE_LAST + 1] = {
[MYDEV_TYPE_FROG] = "frog",
[MYDEV_TYPE_ALLIGATOR] = "alligator",
[MYDEV_TYPE_PLATYPUS] = "platypus",
[MYDEV_TYPE_LAST] = NULL,
};
Assuming an object struct of
typedef struct {
Object parent_obj;
MyDevType devtype;
...other fields...
} MyDev;
The property can then be registered as follows:
static int mydev_prop_get_devtype(Object *obj,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
return dev->devtype;
}
static void mydev_prop_set_devtype(Object *obj,
int value,
Error **errp G_GNUC_UNUSED)
{
MyDev *dev = MYDEV(obj);
dev->devtype = value;
}
object_property_add_enum(obj, "devtype",
mydevtypemap, "MyDevType",
mydev_prop_get_devtype,
mydev_prop_set_devtype,
NULL);
Note there is no need to check the range of 'value' in
the setter, because the string->enum conversion code will
have already done that and reported an error as required.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Andreas Färber <afaerber@suse.de>
2015-05-13 16:14:08 +00:00
|
|
|
}
|
|
|
|
|
2020-01-10 15:30:21 +00:00
|
|
|
ObjectProperty *
|
|
|
|
object_class_property_add_enum(ObjectClass *klass, const char *name,
|
2015-10-13 12:37:46 +00:00
|
|
|
const char *typename,
|
2017-08-24 08:46:10 +00:00
|
|
|
const QEnumLookup *lookup,
|
2015-10-13 12:37:46 +00:00
|
|
|
int (*get)(Object *, Error **),
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
void (*set)(Object *, int, Error **))
|
2015-10-13 12:37:46 +00:00
|
|
|
{
|
|
|
|
EnumProperty *prop = g_malloc(sizeof(*prop));
|
|
|
|
|
2017-08-24 08:46:10 +00:00
|
|
|
prop->lookup = lookup;
|
2015-10-13 12:37:46 +00:00
|
|
|
prop->get = get;
|
|
|
|
prop->set = set;
|
|
|
|
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
return object_class_property_add(klass, name, typename,
|
|
|
|
get ? property_get_enum : NULL,
|
|
|
|
set ? property_set_enum : NULL,
|
|
|
|
NULL,
|
|
|
|
prop);
|
2015-10-13 12:37:46 +00:00
|
|
|
}
|
|
|
|
|
2015-02-06 03:55:45 +00:00
|
|
|
typedef struct TMProperty {
|
|
|
|
void (*get)(Object *, struct tm *, Error **);
|
|
|
|
} TMProperty;
|
|
|
|
|
qom: Swap 'name' next to visitor in ObjectPropertyAccessor
Similar to the previous patch, it's nice to have all functions
in the tree that involve a visitor and a name for conversion to
or from QAPI to consistently stick the 'name' parameter next
to the Visitor parameter.
Done by manually changing include/qom/object.h and qom/object.c,
then running this Coccinelle script and touching up the fallout
(Coccinelle insisted on adding some trailing whitespace).
@ rule1 @
identifier fn;
typedef Object, Visitor, Error;
identifier obj, v, opaque, name, errp;
@@
void fn
- (Object *obj, Visitor *v, void *opaque, const char *name,
+ (Object *obj, Visitor *v, const char *name, void *opaque,
Error **errp) { ... }
@@
identifier rule1.fn;
expression obj, v, opaque, name, errp;
@@
fn(obj, v,
- opaque, name,
+ name, opaque,
errp)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-20-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 13:48:55 +00:00
|
|
|
static void property_get_tm(Object *obj, Visitor *v, const char *name,
|
|
|
|
void *opaque, Error **errp)
|
2015-02-06 03:55:45 +00:00
|
|
|
{
|
|
|
|
TMProperty *prop = opaque;
|
|
|
|
Error *err = NULL;
|
|
|
|
struct tm value;
|
|
|
|
|
|
|
|
prop->get(obj, &value, &err);
|
|
|
|
if (err) {
|
2020-07-07 16:06:04 +00:00
|
|
|
error_propagate(errp, err);
|
|
|
|
return;
|
2015-02-06 03:55:45 +00:00
|
|
|
}
|
|
|
|
|
2020-07-07 16:06:04 +00:00
|
|
|
if (!visit_start_struct(v, name, NULL, 0, errp)) {
|
|
|
|
return;
|
2015-02-06 03:55:45 +00:00
|
|
|
}
|
2020-07-07 16:06:04 +00:00
|
|
|
if (!visit_type_int32(v, "tm_year", &value.tm_year, errp)) {
|
2015-02-06 03:55:45 +00:00
|
|
|
goto out_end;
|
|
|
|
}
|
2020-07-07 16:06:04 +00:00
|
|
|
if (!visit_type_int32(v, "tm_mon", &value.tm_mon, errp)) {
|
2015-02-06 03:55:45 +00:00
|
|
|
goto out_end;
|
|
|
|
}
|
2020-07-07 16:06:04 +00:00
|
|
|
if (!visit_type_int32(v, "tm_mday", &value.tm_mday, errp)) {
|
2015-02-06 03:55:45 +00:00
|
|
|
goto out_end;
|
|
|
|
}
|
2020-07-07 16:06:04 +00:00
|
|
|
if (!visit_type_int32(v, "tm_hour", &value.tm_hour, errp)) {
|
2015-02-06 03:55:45 +00:00
|
|
|
goto out_end;
|
|
|
|
}
|
2020-07-07 16:06:04 +00:00
|
|
|
if (!visit_type_int32(v, "tm_min", &value.tm_min, errp)) {
|
2015-02-06 03:55:45 +00:00
|
|
|
goto out_end;
|
|
|
|
}
|
2020-07-07 16:06:04 +00:00
|
|
|
if (!visit_type_int32(v, "tm_sec", &value.tm_sec, errp)) {
|
2015-02-06 03:55:45 +00:00
|
|
|
goto out_end;
|
|
|
|
}
|
2020-07-07 16:06:04 +00:00
|
|
|
visit_check_struct(v, errp);
|
2015-02-06 03:55:45 +00:00
|
|
|
out_end:
|
qapi: Add parameter to visit_end_*
Rather than making the dealloc visitor track of stack of pointers
remembered during visit_start_* in order to free them during
visit_end_*, it's a lot easier to just make all callers pass the
same pointer to visit_end_*. The generated code has access to the
same pointer, while all other users are doing virtual walks and
can pass NULL. The dealloc visitor is then greatly simplified.
All three visit_end_*() functions intentionally take a void**,
even though the visit_start_*() functions differ between void**,
GenericList**, and GenericAlternate**. This is done for several
reasons: when doing a virtual walk, passing NULL doesn't care
what the type is, but when doing a generated walk, we already
have to cast the caller's specific FOO* to call visit_start,
while using void** lets us use visit_end without a cast. Also,
an upcoming patch will add a clone visitor that wants to use
the same implementation for all three visit_end callbacks,
which is made easier if all three share the same signature.
For visitors with already track per-object state (the QMP visitors
via a stack, and the string visitors which do not allow nesting),
add an assertion that the caller is indeed passing the same
pointer to paired calls.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1465490926-28625-4-git-send-email-eblake@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-06-09 16:48:34 +00:00
|
|
|
visit_end_struct(v, NULL);
|
2015-02-06 03:55:45 +00:00
|
|
|
}
|
|
|
|
|
2020-05-05 15:29:14 +00:00
|
|
|
ObjectProperty *
|
|
|
|
object_property_add_tm(Object *obj, const char *name,
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
void (*get)(Object *, struct tm *, Error **))
|
2015-02-06 03:55:45 +00:00
|
|
|
{
|
|
|
|
TMProperty *prop = g_malloc0(sizeof(*prop));
|
|
|
|
|
|
|
|
prop->get = get;
|
|
|
|
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
return object_property_add(obj, name, "struct tm",
|
|
|
|
get ? property_get_tm : NULL, NULL,
|
2020-10-27 16:12:57 +00:00
|
|
|
property_release_data,
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
prop);
|
2015-02-06 03:55:45 +00:00
|
|
|
}
|
|
|
|
|
2020-01-10 15:30:21 +00:00
|
|
|
ObjectProperty *
|
|
|
|
object_class_property_add_tm(ObjectClass *klass, const char *name,
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
void (*get)(Object *, struct tm *, Error **))
|
2015-10-13 12:37:46 +00:00
|
|
|
{
|
|
|
|
TMProperty *prop = g_malloc0(sizeof(*prop));
|
|
|
|
|
|
|
|
prop->get = get;
|
|
|
|
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
return object_class_property_add(klass, name, "struct tm",
|
|
|
|
get ? property_get_tm : NULL,
|
|
|
|
NULL, NULL, prop);
|
2015-10-13 12:37:46 +00:00
|
|
|
}
|
|
|
|
|
2020-07-07 16:05:50 +00:00
|
|
|
static char *object_get_type(Object *obj, Error **errp)
|
2012-04-02 15:33:51 +00:00
|
|
|
{
|
|
|
|
return g_strdup(object_get_typename(obj));
|
|
|
|
}
|
|
|
|
|
qom: Swap 'name' next to visitor in ObjectPropertyAccessor
Similar to the previous patch, it's nice to have all functions
in the tree that involve a visitor and a name for conversion to
or from QAPI to consistently stick the 'name' parameter next
to the Visitor parameter.
Done by manually changing include/qom/object.h and qom/object.c,
then running this Coccinelle script and touching up the fallout
(Coccinelle insisted on adding some trailing whitespace).
@ rule1 @
identifier fn;
typedef Object, Visitor, Error;
identifier obj, v, opaque, name, errp;
@@
void fn
- (Object *obj, Visitor *v, void *opaque, const char *name,
+ (Object *obj, Visitor *v, const char *name, void *opaque,
Error **errp) { ... }
@@
identifier rule1.fn;
expression obj, v, opaque, name, errp;
@@
fn(obj, v,
- opaque, name,
+ name, opaque,
errp)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-20-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 13:48:55 +00:00
|
|
|
static void property_get_uint8_ptr(Object *obj, Visitor *v, const char *name,
|
|
|
|
void *opaque, Error **errp)
|
2013-09-22 07:10:17 +00:00
|
|
|
{
|
|
|
|
uint8_t value = *(uint8_t *)opaque;
|
qapi: Swap visit_* arguments for consistent 'name' placement
JSON uses "name":value, but many of our visitor interfaces were
called with visit_type_FOO(v, &value, name, errp). This can be
a bit confusing to have to mentally swap the parameter order to
match JSON order. It's particularly bad for visit_start_struct(),
where the 'name' parameter is smack in the middle of the
otherwise-related group of 'obj, kind, size' parameters! It's
time to do a global swap of the parameter ordering, so that the
'name' parameter is always immediately after the Visitor argument.
Additional reason in favor of the swap: the existing include/qjson.h
prefers listing 'name' first in json_prop_*(), and I have plans to
unify that file with the qapi visitors; listing 'name' first in
qapi will minimize churn to the (admittedly few) qjson.h clients.
Later patches will then fix docs, object.h, visitor-impl.h, and
those clients to match.
Done by first patching scripts/qapi*.py by hand to make generated
files do what I want, then by running the following Coccinelle
script to affect the rest of the code base:
$ spatch --sp-file script `git grep -l '\bvisit_' -- '**/*.[ch]'`
I then had to apply some touchups (Coccinelle insisted on TAB
indentation in visitor.h, and botched the signature of
visit_type_enum() by rewriting 'const char *const strings[]' to
the syntactically invalid 'const char*const[] strings'). The
movement of parameters is sufficient to provoke compiler errors
if any callers were missed.
// Part 1: Swap declaration order
@@
type TV, TErr, TObj, T1, T2;
identifier OBJ, ARG1, ARG2;
@@
void visit_start_struct
-(TV v, TObj OBJ, T1 ARG1, const char *name, T2 ARG2, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp)
{ ... }
@@
type bool, TV, T1;
identifier ARG1;
@@
bool visit_optional
-(TV v, T1 ARG1, const char *name)
+(TV v, const char *name, T1 ARG1)
{ ... }
@@
type TV, TErr, TObj, T1;
identifier OBJ, ARG1;
@@
void visit_get_next_type
-(TV v, TObj OBJ, T1 ARG1, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, TErr errp)
{ ... }
@@
type TV, TErr, TObj, T1, T2;
identifier OBJ, ARG1, ARG2;
@@
void visit_type_enum
-(TV v, TObj OBJ, T1 ARG1, T2 ARG2, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp)
{ ... }
@@
type TV, TErr, TObj;
identifier OBJ;
identifier VISIT_TYPE =~ "^visit_type_";
@@
void VISIT_TYPE
-(TV v, TObj OBJ, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, TErr errp)
{ ... }
// Part 2: swap caller order
@@
expression V, NAME, OBJ, ARG1, ARG2, ERR;
identifier VISIT_TYPE =~ "^visit_type_";
@@
(
-visit_start_struct(V, OBJ, ARG1, NAME, ARG2, ERR)
+visit_start_struct(V, NAME, OBJ, ARG1, ARG2, ERR)
|
-visit_optional(V, ARG1, NAME)
+visit_optional(V, NAME, ARG1)
|
-visit_get_next_type(V, OBJ, ARG1, NAME, ERR)
+visit_get_next_type(V, NAME, OBJ, ARG1, ERR)
|
-visit_type_enum(V, OBJ, ARG1, ARG2, NAME, ERR)
+visit_type_enum(V, NAME, OBJ, ARG1, ARG2, ERR)
|
-VISIT_TYPE(V, OBJ, NAME, ERR)
+VISIT_TYPE(V, NAME, OBJ, ERR)
)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-19-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 13:48:54 +00:00
|
|
|
visit_type_uint8(v, name, &value, errp);
|
2013-09-22 07:10:17 +00:00
|
|
|
}
|
|
|
|
|
2020-02-04 13:15:58 +00:00
|
|
|
static void property_set_uint8_ptr(Object *obj, Visitor *v, const char *name,
|
|
|
|
void *opaque, Error **errp)
|
|
|
|
{
|
|
|
|
uint8_t *field = opaque;
|
|
|
|
uint8_t value;
|
|
|
|
|
error: Eliminate error_propagate() with Coccinelle, part 1
When all we do with an Error we receive into a local variable is
propagating to somewhere else, we can just as well receive it there
right away. Convert
if (!foo(..., &err)) {
...
error_propagate(errp, err);
...
return ...
}
to
if (!foo(..., errp)) {
...
...
return ...
}
where nothing else needs @err. Coccinelle script:
@rule1 forall@
identifier fun, err, errp, lbl;
expression list args, args2;
binary operator op;
constant c1, c2;
symbol false;
@@
if (
(
- fun(args, &err, args2)
+ fun(args, errp, args2)
|
- !fun(args, &err, args2)
+ !fun(args, errp, args2)
|
- fun(args, &err, args2) op c1
+ fun(args, errp, args2) op c1
)
)
{
... when != err
when != lbl:
when strict
- error_propagate(errp, err);
... when != err
(
return;
|
return c2;
|
return false;
)
}
@rule2 forall@
identifier fun, err, errp, lbl;
expression list args, args2;
expression var;
binary operator op;
constant c1, c2;
symbol false;
@@
- var = fun(args, &err, args2);
+ var = fun(args, errp, args2);
... when != err
if (
(
var
|
!var
|
var op c1
)
)
{
... when != err
when != lbl:
when strict
- error_propagate(errp, err);
... when != err
(
return;
|
return c2;
|
return false;
|
return var;
)
}
@depends on rule1 || rule2@
identifier err;
@@
- Error *err = NULL;
... when != err
Not exactly elegant, I'm afraid.
The "when != lbl:" is necessary to avoid transforming
if (fun(args, &err)) {
goto out
}
...
out:
error_propagate(errp, err);
even though other paths to label out still need the error_propagate().
For an actual example, see sclp_realize().
Without the "when strict", Coccinelle transforms vfio_msix_setup(),
incorrectly. I don't know what exactly "when strict" does, only that
it helps here.
The match of return is narrower than what I want, but I can't figure
out how to express "return where the operand doesn't use @err". For
an example where it's too narrow, see vfio_intx_enable().
Silently fails to convert hw/arm/armsse.c, because Coccinelle gets
confused by ARMSSE being used both as typedef and function-like macro
there. Converted manually.
Line breaks tidied up manually. One nested declaration of @local_err
deleted manually. Preexisting unwanted blank line dropped in
hw/riscv/sifive_e.c.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20200707160613.848843-35-armbru@redhat.com>
2020-07-07 16:06:02 +00:00
|
|
|
if (!visit_type_uint8(v, name, &value, errp)) {
|
2020-02-04 13:15:58 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
*field = value;
|
|
|
|
}
|
|
|
|
|
qom: Swap 'name' next to visitor in ObjectPropertyAccessor
Similar to the previous patch, it's nice to have all functions
in the tree that involve a visitor and a name for conversion to
or from QAPI to consistently stick the 'name' parameter next
to the Visitor parameter.
Done by manually changing include/qom/object.h and qom/object.c,
then running this Coccinelle script and touching up the fallout
(Coccinelle insisted on adding some trailing whitespace).
@ rule1 @
identifier fn;
typedef Object, Visitor, Error;
identifier obj, v, opaque, name, errp;
@@
void fn
- (Object *obj, Visitor *v, void *opaque, const char *name,
+ (Object *obj, Visitor *v, const char *name, void *opaque,
Error **errp) { ... }
@@
identifier rule1.fn;
expression obj, v, opaque, name, errp;
@@
fn(obj, v,
- opaque, name,
+ name, opaque,
errp)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-20-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 13:48:55 +00:00
|
|
|
static void property_get_uint16_ptr(Object *obj, Visitor *v, const char *name,
|
|
|
|
void *opaque, Error **errp)
|
2013-09-22 07:10:17 +00:00
|
|
|
{
|
|
|
|
uint16_t value = *(uint16_t *)opaque;
|
qapi: Swap visit_* arguments for consistent 'name' placement
JSON uses "name":value, but many of our visitor interfaces were
called with visit_type_FOO(v, &value, name, errp). This can be
a bit confusing to have to mentally swap the parameter order to
match JSON order. It's particularly bad for visit_start_struct(),
where the 'name' parameter is smack in the middle of the
otherwise-related group of 'obj, kind, size' parameters! It's
time to do a global swap of the parameter ordering, so that the
'name' parameter is always immediately after the Visitor argument.
Additional reason in favor of the swap: the existing include/qjson.h
prefers listing 'name' first in json_prop_*(), and I have plans to
unify that file with the qapi visitors; listing 'name' first in
qapi will minimize churn to the (admittedly few) qjson.h clients.
Later patches will then fix docs, object.h, visitor-impl.h, and
those clients to match.
Done by first patching scripts/qapi*.py by hand to make generated
files do what I want, then by running the following Coccinelle
script to affect the rest of the code base:
$ spatch --sp-file script `git grep -l '\bvisit_' -- '**/*.[ch]'`
I then had to apply some touchups (Coccinelle insisted on TAB
indentation in visitor.h, and botched the signature of
visit_type_enum() by rewriting 'const char *const strings[]' to
the syntactically invalid 'const char*const[] strings'). The
movement of parameters is sufficient to provoke compiler errors
if any callers were missed.
// Part 1: Swap declaration order
@@
type TV, TErr, TObj, T1, T2;
identifier OBJ, ARG1, ARG2;
@@
void visit_start_struct
-(TV v, TObj OBJ, T1 ARG1, const char *name, T2 ARG2, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp)
{ ... }
@@
type bool, TV, T1;
identifier ARG1;
@@
bool visit_optional
-(TV v, T1 ARG1, const char *name)
+(TV v, const char *name, T1 ARG1)
{ ... }
@@
type TV, TErr, TObj, T1;
identifier OBJ, ARG1;
@@
void visit_get_next_type
-(TV v, TObj OBJ, T1 ARG1, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, TErr errp)
{ ... }
@@
type TV, TErr, TObj, T1, T2;
identifier OBJ, ARG1, ARG2;
@@
void visit_type_enum
-(TV v, TObj OBJ, T1 ARG1, T2 ARG2, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp)
{ ... }
@@
type TV, TErr, TObj;
identifier OBJ;
identifier VISIT_TYPE =~ "^visit_type_";
@@
void VISIT_TYPE
-(TV v, TObj OBJ, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, TErr errp)
{ ... }
// Part 2: swap caller order
@@
expression V, NAME, OBJ, ARG1, ARG2, ERR;
identifier VISIT_TYPE =~ "^visit_type_";
@@
(
-visit_start_struct(V, OBJ, ARG1, NAME, ARG2, ERR)
+visit_start_struct(V, NAME, OBJ, ARG1, ARG2, ERR)
|
-visit_optional(V, ARG1, NAME)
+visit_optional(V, NAME, ARG1)
|
-visit_get_next_type(V, OBJ, ARG1, NAME, ERR)
+visit_get_next_type(V, NAME, OBJ, ARG1, ERR)
|
-visit_type_enum(V, OBJ, ARG1, ARG2, NAME, ERR)
+visit_type_enum(V, NAME, OBJ, ARG1, ARG2, ERR)
|
-VISIT_TYPE(V, OBJ, NAME, ERR)
+VISIT_TYPE(V, NAME, OBJ, ERR)
)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-19-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 13:48:54 +00:00
|
|
|
visit_type_uint16(v, name, &value, errp);
|
2013-09-22 07:10:17 +00:00
|
|
|
}
|
|
|
|
|
2020-02-04 13:15:58 +00:00
|
|
|
static void property_set_uint16_ptr(Object *obj, Visitor *v, const char *name,
|
|
|
|
void *opaque, Error **errp)
|
|
|
|
{
|
|
|
|
uint16_t *field = opaque;
|
|
|
|
uint16_t value;
|
|
|
|
|
error: Eliminate error_propagate() with Coccinelle, part 1
When all we do with an Error we receive into a local variable is
propagating to somewhere else, we can just as well receive it there
right away. Convert
if (!foo(..., &err)) {
...
error_propagate(errp, err);
...
return ...
}
to
if (!foo(..., errp)) {
...
...
return ...
}
where nothing else needs @err. Coccinelle script:
@rule1 forall@
identifier fun, err, errp, lbl;
expression list args, args2;
binary operator op;
constant c1, c2;
symbol false;
@@
if (
(
- fun(args, &err, args2)
+ fun(args, errp, args2)
|
- !fun(args, &err, args2)
+ !fun(args, errp, args2)
|
- fun(args, &err, args2) op c1
+ fun(args, errp, args2) op c1
)
)
{
... when != err
when != lbl:
when strict
- error_propagate(errp, err);
... when != err
(
return;
|
return c2;
|
return false;
)
}
@rule2 forall@
identifier fun, err, errp, lbl;
expression list args, args2;
expression var;
binary operator op;
constant c1, c2;
symbol false;
@@
- var = fun(args, &err, args2);
+ var = fun(args, errp, args2);
... when != err
if (
(
var
|
!var
|
var op c1
)
)
{
... when != err
when != lbl:
when strict
- error_propagate(errp, err);
... when != err
(
return;
|
return c2;
|
return false;
|
return var;
)
}
@depends on rule1 || rule2@
identifier err;
@@
- Error *err = NULL;
... when != err
Not exactly elegant, I'm afraid.
The "when != lbl:" is necessary to avoid transforming
if (fun(args, &err)) {
goto out
}
...
out:
error_propagate(errp, err);
even though other paths to label out still need the error_propagate().
For an actual example, see sclp_realize().
Without the "when strict", Coccinelle transforms vfio_msix_setup(),
incorrectly. I don't know what exactly "when strict" does, only that
it helps here.
The match of return is narrower than what I want, but I can't figure
out how to express "return where the operand doesn't use @err". For
an example where it's too narrow, see vfio_intx_enable().
Silently fails to convert hw/arm/armsse.c, because Coccinelle gets
confused by ARMSSE being used both as typedef and function-like macro
there. Converted manually.
Line breaks tidied up manually. One nested declaration of @local_err
deleted manually. Preexisting unwanted blank line dropped in
hw/riscv/sifive_e.c.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20200707160613.848843-35-armbru@redhat.com>
2020-07-07 16:06:02 +00:00
|
|
|
if (!visit_type_uint16(v, name, &value, errp)) {
|
2020-02-04 13:15:58 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
*field = value;
|
|
|
|
}
|
|
|
|
|
qom: Swap 'name' next to visitor in ObjectPropertyAccessor
Similar to the previous patch, it's nice to have all functions
in the tree that involve a visitor and a name for conversion to
or from QAPI to consistently stick the 'name' parameter next
to the Visitor parameter.
Done by manually changing include/qom/object.h and qom/object.c,
then running this Coccinelle script and touching up the fallout
(Coccinelle insisted on adding some trailing whitespace).
@ rule1 @
identifier fn;
typedef Object, Visitor, Error;
identifier obj, v, opaque, name, errp;
@@
void fn
- (Object *obj, Visitor *v, void *opaque, const char *name,
+ (Object *obj, Visitor *v, const char *name, void *opaque,
Error **errp) { ... }
@@
identifier rule1.fn;
expression obj, v, opaque, name, errp;
@@
fn(obj, v,
- opaque, name,
+ name, opaque,
errp)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-20-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 13:48:55 +00:00
|
|
|
static void property_get_uint32_ptr(Object *obj, Visitor *v, const char *name,
|
|
|
|
void *opaque, Error **errp)
|
2013-09-22 07:10:17 +00:00
|
|
|
{
|
|
|
|
uint32_t value = *(uint32_t *)opaque;
|
qapi: Swap visit_* arguments for consistent 'name' placement
JSON uses "name":value, but many of our visitor interfaces were
called with visit_type_FOO(v, &value, name, errp). This can be
a bit confusing to have to mentally swap the parameter order to
match JSON order. It's particularly bad for visit_start_struct(),
where the 'name' parameter is smack in the middle of the
otherwise-related group of 'obj, kind, size' parameters! It's
time to do a global swap of the parameter ordering, so that the
'name' parameter is always immediately after the Visitor argument.
Additional reason in favor of the swap: the existing include/qjson.h
prefers listing 'name' first in json_prop_*(), and I have plans to
unify that file with the qapi visitors; listing 'name' first in
qapi will minimize churn to the (admittedly few) qjson.h clients.
Later patches will then fix docs, object.h, visitor-impl.h, and
those clients to match.
Done by first patching scripts/qapi*.py by hand to make generated
files do what I want, then by running the following Coccinelle
script to affect the rest of the code base:
$ spatch --sp-file script `git grep -l '\bvisit_' -- '**/*.[ch]'`
I then had to apply some touchups (Coccinelle insisted on TAB
indentation in visitor.h, and botched the signature of
visit_type_enum() by rewriting 'const char *const strings[]' to
the syntactically invalid 'const char*const[] strings'). The
movement of parameters is sufficient to provoke compiler errors
if any callers were missed.
// Part 1: Swap declaration order
@@
type TV, TErr, TObj, T1, T2;
identifier OBJ, ARG1, ARG2;
@@
void visit_start_struct
-(TV v, TObj OBJ, T1 ARG1, const char *name, T2 ARG2, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp)
{ ... }
@@
type bool, TV, T1;
identifier ARG1;
@@
bool visit_optional
-(TV v, T1 ARG1, const char *name)
+(TV v, const char *name, T1 ARG1)
{ ... }
@@
type TV, TErr, TObj, T1;
identifier OBJ, ARG1;
@@
void visit_get_next_type
-(TV v, TObj OBJ, T1 ARG1, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, TErr errp)
{ ... }
@@
type TV, TErr, TObj, T1, T2;
identifier OBJ, ARG1, ARG2;
@@
void visit_type_enum
-(TV v, TObj OBJ, T1 ARG1, T2 ARG2, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp)
{ ... }
@@
type TV, TErr, TObj;
identifier OBJ;
identifier VISIT_TYPE =~ "^visit_type_";
@@
void VISIT_TYPE
-(TV v, TObj OBJ, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, TErr errp)
{ ... }
// Part 2: swap caller order
@@
expression V, NAME, OBJ, ARG1, ARG2, ERR;
identifier VISIT_TYPE =~ "^visit_type_";
@@
(
-visit_start_struct(V, OBJ, ARG1, NAME, ARG2, ERR)
+visit_start_struct(V, NAME, OBJ, ARG1, ARG2, ERR)
|
-visit_optional(V, ARG1, NAME)
+visit_optional(V, NAME, ARG1)
|
-visit_get_next_type(V, OBJ, ARG1, NAME, ERR)
+visit_get_next_type(V, NAME, OBJ, ARG1, ERR)
|
-visit_type_enum(V, OBJ, ARG1, ARG2, NAME, ERR)
+visit_type_enum(V, NAME, OBJ, ARG1, ARG2, ERR)
|
-VISIT_TYPE(V, OBJ, NAME, ERR)
+VISIT_TYPE(V, NAME, OBJ, ERR)
)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-19-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 13:48:54 +00:00
|
|
|
visit_type_uint32(v, name, &value, errp);
|
2013-09-22 07:10:17 +00:00
|
|
|
}
|
|
|
|
|
2020-02-04 13:15:58 +00:00
|
|
|
static void property_set_uint32_ptr(Object *obj, Visitor *v, const char *name,
|
|
|
|
void *opaque, Error **errp)
|
|
|
|
{
|
|
|
|
uint32_t *field = opaque;
|
|
|
|
uint32_t value;
|
|
|
|
|
error: Eliminate error_propagate() with Coccinelle, part 1
When all we do with an Error we receive into a local variable is
propagating to somewhere else, we can just as well receive it there
right away. Convert
if (!foo(..., &err)) {
...
error_propagate(errp, err);
...
return ...
}
to
if (!foo(..., errp)) {
...
...
return ...
}
where nothing else needs @err. Coccinelle script:
@rule1 forall@
identifier fun, err, errp, lbl;
expression list args, args2;
binary operator op;
constant c1, c2;
symbol false;
@@
if (
(
- fun(args, &err, args2)
+ fun(args, errp, args2)
|
- !fun(args, &err, args2)
+ !fun(args, errp, args2)
|
- fun(args, &err, args2) op c1
+ fun(args, errp, args2) op c1
)
)
{
... when != err
when != lbl:
when strict
- error_propagate(errp, err);
... when != err
(
return;
|
return c2;
|
return false;
)
}
@rule2 forall@
identifier fun, err, errp, lbl;
expression list args, args2;
expression var;
binary operator op;
constant c1, c2;
symbol false;
@@
- var = fun(args, &err, args2);
+ var = fun(args, errp, args2);
... when != err
if (
(
var
|
!var
|
var op c1
)
)
{
... when != err
when != lbl:
when strict
- error_propagate(errp, err);
... when != err
(
return;
|
return c2;
|
return false;
|
return var;
)
}
@depends on rule1 || rule2@
identifier err;
@@
- Error *err = NULL;
... when != err
Not exactly elegant, I'm afraid.
The "when != lbl:" is necessary to avoid transforming
if (fun(args, &err)) {
goto out
}
...
out:
error_propagate(errp, err);
even though other paths to label out still need the error_propagate().
For an actual example, see sclp_realize().
Without the "when strict", Coccinelle transforms vfio_msix_setup(),
incorrectly. I don't know what exactly "when strict" does, only that
it helps here.
The match of return is narrower than what I want, but I can't figure
out how to express "return where the operand doesn't use @err". For
an example where it's too narrow, see vfio_intx_enable().
Silently fails to convert hw/arm/armsse.c, because Coccinelle gets
confused by ARMSSE being used both as typedef and function-like macro
there. Converted manually.
Line breaks tidied up manually. One nested declaration of @local_err
deleted manually. Preexisting unwanted blank line dropped in
hw/riscv/sifive_e.c.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20200707160613.848843-35-armbru@redhat.com>
2020-07-07 16:06:02 +00:00
|
|
|
if (!visit_type_uint32(v, name, &value, errp)) {
|
2020-02-04 13:15:58 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
*field = value;
|
|
|
|
}
|
|
|
|
|
qom: Swap 'name' next to visitor in ObjectPropertyAccessor
Similar to the previous patch, it's nice to have all functions
in the tree that involve a visitor and a name for conversion to
or from QAPI to consistently stick the 'name' parameter next
to the Visitor parameter.
Done by manually changing include/qom/object.h and qom/object.c,
then running this Coccinelle script and touching up the fallout
(Coccinelle insisted on adding some trailing whitespace).
@ rule1 @
identifier fn;
typedef Object, Visitor, Error;
identifier obj, v, opaque, name, errp;
@@
void fn
- (Object *obj, Visitor *v, void *opaque, const char *name,
+ (Object *obj, Visitor *v, const char *name, void *opaque,
Error **errp) { ... }
@@
identifier rule1.fn;
expression obj, v, opaque, name, errp;
@@
fn(obj, v,
- opaque, name,
+ name, opaque,
errp)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-20-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 13:48:55 +00:00
|
|
|
static void property_get_uint64_ptr(Object *obj, Visitor *v, const char *name,
|
|
|
|
void *opaque, Error **errp)
|
2013-09-22 07:10:17 +00:00
|
|
|
{
|
|
|
|
uint64_t value = *(uint64_t *)opaque;
|
qapi: Swap visit_* arguments for consistent 'name' placement
JSON uses "name":value, but many of our visitor interfaces were
called with visit_type_FOO(v, &value, name, errp). This can be
a bit confusing to have to mentally swap the parameter order to
match JSON order. It's particularly bad for visit_start_struct(),
where the 'name' parameter is smack in the middle of the
otherwise-related group of 'obj, kind, size' parameters! It's
time to do a global swap of the parameter ordering, so that the
'name' parameter is always immediately after the Visitor argument.
Additional reason in favor of the swap: the existing include/qjson.h
prefers listing 'name' first in json_prop_*(), and I have plans to
unify that file with the qapi visitors; listing 'name' first in
qapi will minimize churn to the (admittedly few) qjson.h clients.
Later patches will then fix docs, object.h, visitor-impl.h, and
those clients to match.
Done by first patching scripts/qapi*.py by hand to make generated
files do what I want, then by running the following Coccinelle
script to affect the rest of the code base:
$ spatch --sp-file script `git grep -l '\bvisit_' -- '**/*.[ch]'`
I then had to apply some touchups (Coccinelle insisted on TAB
indentation in visitor.h, and botched the signature of
visit_type_enum() by rewriting 'const char *const strings[]' to
the syntactically invalid 'const char*const[] strings'). The
movement of parameters is sufficient to provoke compiler errors
if any callers were missed.
// Part 1: Swap declaration order
@@
type TV, TErr, TObj, T1, T2;
identifier OBJ, ARG1, ARG2;
@@
void visit_start_struct
-(TV v, TObj OBJ, T1 ARG1, const char *name, T2 ARG2, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp)
{ ... }
@@
type bool, TV, T1;
identifier ARG1;
@@
bool visit_optional
-(TV v, T1 ARG1, const char *name)
+(TV v, const char *name, T1 ARG1)
{ ... }
@@
type TV, TErr, TObj, T1;
identifier OBJ, ARG1;
@@
void visit_get_next_type
-(TV v, TObj OBJ, T1 ARG1, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, TErr errp)
{ ... }
@@
type TV, TErr, TObj, T1, T2;
identifier OBJ, ARG1, ARG2;
@@
void visit_type_enum
-(TV v, TObj OBJ, T1 ARG1, T2 ARG2, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, T1 ARG1, T2 ARG2, TErr errp)
{ ... }
@@
type TV, TErr, TObj;
identifier OBJ;
identifier VISIT_TYPE =~ "^visit_type_";
@@
void VISIT_TYPE
-(TV v, TObj OBJ, const char *name, TErr errp)
+(TV v, const char *name, TObj OBJ, TErr errp)
{ ... }
// Part 2: swap caller order
@@
expression V, NAME, OBJ, ARG1, ARG2, ERR;
identifier VISIT_TYPE =~ "^visit_type_";
@@
(
-visit_start_struct(V, OBJ, ARG1, NAME, ARG2, ERR)
+visit_start_struct(V, NAME, OBJ, ARG1, ARG2, ERR)
|
-visit_optional(V, ARG1, NAME)
+visit_optional(V, NAME, ARG1)
|
-visit_get_next_type(V, OBJ, ARG1, NAME, ERR)
+visit_get_next_type(V, NAME, OBJ, ARG1, ERR)
|
-visit_type_enum(V, OBJ, ARG1, ARG2, NAME, ERR)
+visit_type_enum(V, NAME, OBJ, ARG1, ARG2, ERR)
|
-VISIT_TYPE(V, OBJ, NAME, ERR)
+VISIT_TYPE(V, NAME, OBJ, ERR)
)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-19-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 13:48:54 +00:00
|
|
|
visit_type_uint64(v, name, &value, errp);
|
2013-09-22 07:10:17 +00:00
|
|
|
}
|
|
|
|
|
2020-02-04 13:15:58 +00:00
|
|
|
static void property_set_uint64_ptr(Object *obj, Visitor *v, const char *name,
|
|
|
|
void *opaque, Error **errp)
|
|
|
|
{
|
|
|
|
uint64_t *field = opaque;
|
|
|
|
uint64_t value;
|
|
|
|
|
error: Eliminate error_propagate() with Coccinelle, part 1
When all we do with an Error we receive into a local variable is
propagating to somewhere else, we can just as well receive it there
right away. Convert
if (!foo(..., &err)) {
...
error_propagate(errp, err);
...
return ...
}
to
if (!foo(..., errp)) {
...
...
return ...
}
where nothing else needs @err. Coccinelle script:
@rule1 forall@
identifier fun, err, errp, lbl;
expression list args, args2;
binary operator op;
constant c1, c2;
symbol false;
@@
if (
(
- fun(args, &err, args2)
+ fun(args, errp, args2)
|
- !fun(args, &err, args2)
+ !fun(args, errp, args2)
|
- fun(args, &err, args2) op c1
+ fun(args, errp, args2) op c1
)
)
{
... when != err
when != lbl:
when strict
- error_propagate(errp, err);
... when != err
(
return;
|
return c2;
|
return false;
)
}
@rule2 forall@
identifier fun, err, errp, lbl;
expression list args, args2;
expression var;
binary operator op;
constant c1, c2;
symbol false;
@@
- var = fun(args, &err, args2);
+ var = fun(args, errp, args2);
... when != err
if (
(
var
|
!var
|
var op c1
)
)
{
... when != err
when != lbl:
when strict
- error_propagate(errp, err);
... when != err
(
return;
|
return c2;
|
return false;
|
return var;
)
}
@depends on rule1 || rule2@
identifier err;
@@
- Error *err = NULL;
... when != err
Not exactly elegant, I'm afraid.
The "when != lbl:" is necessary to avoid transforming
if (fun(args, &err)) {
goto out
}
...
out:
error_propagate(errp, err);
even though other paths to label out still need the error_propagate().
For an actual example, see sclp_realize().
Without the "when strict", Coccinelle transforms vfio_msix_setup(),
incorrectly. I don't know what exactly "when strict" does, only that
it helps here.
The match of return is narrower than what I want, but I can't figure
out how to express "return where the operand doesn't use @err". For
an example where it's too narrow, see vfio_intx_enable().
Silently fails to convert hw/arm/armsse.c, because Coccinelle gets
confused by ARMSSE being used both as typedef and function-like macro
there. Converted manually.
Line breaks tidied up manually. One nested declaration of @local_err
deleted manually. Preexisting unwanted blank line dropped in
hw/riscv/sifive_e.c.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20200707160613.848843-35-armbru@redhat.com>
2020-07-07 16:06:02 +00:00
|
|
|
if (!visit_type_uint64(v, name, &value, errp)) {
|
2020-02-04 13:15:58 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
*field = value;
|
|
|
|
}
|
|
|
|
|
2020-05-05 15:29:14 +00:00
|
|
|
ObjectProperty *
|
|
|
|
object_property_add_uint8_ptr(Object *obj, const char *name,
|
|
|
|
const uint8_t *v,
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
ObjectPropertyFlags flags)
|
2013-09-22 07:10:17 +00:00
|
|
|
{
|
2020-02-04 13:15:58 +00:00
|
|
|
ObjectPropertyAccessor *getter = NULL;
|
|
|
|
ObjectPropertyAccessor *setter = NULL;
|
|
|
|
|
|
|
|
if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
|
|
|
|
getter = property_get_uint8_ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
|
|
|
|
setter = property_set_uint8_ptr;
|
|
|
|
}
|
|
|
|
|
2020-05-05 15:29:14 +00:00
|
|
|
return object_property_add(obj, name, "uint8",
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
getter, setter, NULL, (void *)v);
|
2013-09-22 07:10:17 +00:00
|
|
|
}
|
|
|
|
|
2020-01-10 15:30:21 +00:00
|
|
|
ObjectProperty *
|
|
|
|
object_class_property_add_uint8_ptr(ObjectClass *klass, const char *name,
|
2020-02-04 13:15:58 +00:00
|
|
|
const uint8_t *v,
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
ObjectPropertyFlags flags)
|
2015-10-13 12:37:46 +00:00
|
|
|
{
|
2020-02-04 13:15:58 +00:00
|
|
|
ObjectPropertyAccessor *getter = NULL;
|
|
|
|
ObjectPropertyAccessor *setter = NULL;
|
|
|
|
|
|
|
|
if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
|
|
|
|
getter = property_get_uint8_ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
|
|
|
|
setter = property_set_uint8_ptr;
|
|
|
|
}
|
|
|
|
|
2020-01-10 15:30:21 +00:00
|
|
|
return object_class_property_add(klass, name, "uint8",
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
getter, setter, NULL, (void *)v);
|
2015-10-13 12:37:46 +00:00
|
|
|
}
|
|
|
|
|
2020-05-05 15:29:14 +00:00
|
|
|
ObjectProperty *
|
|
|
|
object_property_add_uint16_ptr(Object *obj, const char *name,
|
|
|
|
const uint16_t *v,
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
ObjectPropertyFlags flags)
|
2013-09-22 07:10:17 +00:00
|
|
|
{
|
2020-02-04 13:15:58 +00:00
|
|
|
ObjectPropertyAccessor *getter = NULL;
|
|
|
|
ObjectPropertyAccessor *setter = NULL;
|
|
|
|
|
|
|
|
if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
|
|
|
|
getter = property_get_uint16_ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
|
|
|
|
setter = property_set_uint16_ptr;
|
|
|
|
}
|
|
|
|
|
2020-05-05 15:29:14 +00:00
|
|
|
return object_property_add(obj, name, "uint16",
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
getter, setter, NULL, (void *)v);
|
2013-09-22 07:10:17 +00:00
|
|
|
}
|
|
|
|
|
2020-01-10 15:30:21 +00:00
|
|
|
ObjectProperty *
|
|
|
|
object_class_property_add_uint16_ptr(ObjectClass *klass, const char *name,
|
2020-02-04 13:15:58 +00:00
|
|
|
const uint16_t *v,
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
ObjectPropertyFlags flags)
|
2015-10-13 12:37:46 +00:00
|
|
|
{
|
2020-02-04 13:15:58 +00:00
|
|
|
ObjectPropertyAccessor *getter = NULL;
|
|
|
|
ObjectPropertyAccessor *setter = NULL;
|
|
|
|
|
|
|
|
if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
|
|
|
|
getter = property_get_uint16_ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
|
|
|
|
setter = property_set_uint16_ptr;
|
|
|
|
}
|
|
|
|
|
2020-01-10 15:30:21 +00:00
|
|
|
return object_class_property_add(klass, name, "uint16",
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
getter, setter, NULL, (void *)v);
|
2015-10-13 12:37:46 +00:00
|
|
|
}
|
|
|
|
|
2020-05-05 15:29:14 +00:00
|
|
|
ObjectProperty *
|
|
|
|
object_property_add_uint32_ptr(Object *obj, const char *name,
|
|
|
|
const uint32_t *v,
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
ObjectPropertyFlags flags)
|
2013-09-22 07:10:17 +00:00
|
|
|
{
|
2020-02-04 13:15:58 +00:00
|
|
|
ObjectPropertyAccessor *getter = NULL;
|
|
|
|
ObjectPropertyAccessor *setter = NULL;
|
|
|
|
|
|
|
|
if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
|
|
|
|
getter = property_get_uint32_ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
|
|
|
|
setter = property_set_uint32_ptr;
|
|
|
|
}
|
|
|
|
|
2020-05-05 15:29:14 +00:00
|
|
|
return object_property_add(obj, name, "uint32",
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
getter, setter, NULL, (void *)v);
|
2013-09-22 07:10:17 +00:00
|
|
|
}
|
|
|
|
|
2020-01-10 15:30:21 +00:00
|
|
|
ObjectProperty *
|
|
|
|
object_class_property_add_uint32_ptr(ObjectClass *klass, const char *name,
|
2020-02-04 13:15:58 +00:00
|
|
|
const uint32_t *v,
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
ObjectPropertyFlags flags)
|
2015-10-13 12:37:46 +00:00
|
|
|
{
|
2020-02-04 13:15:58 +00:00
|
|
|
ObjectPropertyAccessor *getter = NULL;
|
|
|
|
ObjectPropertyAccessor *setter = NULL;
|
|
|
|
|
|
|
|
if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
|
|
|
|
getter = property_get_uint32_ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
|
|
|
|
setter = property_set_uint32_ptr;
|
|
|
|
}
|
|
|
|
|
2020-01-10 15:30:21 +00:00
|
|
|
return object_class_property_add(klass, name, "uint32",
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
getter, setter, NULL, (void *)v);
|
2015-10-13 12:37:46 +00:00
|
|
|
}
|
|
|
|
|
2020-05-05 15:29:14 +00:00
|
|
|
ObjectProperty *
|
|
|
|
object_property_add_uint64_ptr(Object *obj, const char *name,
|
|
|
|
const uint64_t *v,
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
ObjectPropertyFlags flags)
|
2013-09-22 07:10:17 +00:00
|
|
|
{
|
2020-02-04 13:15:58 +00:00
|
|
|
ObjectPropertyAccessor *getter = NULL;
|
|
|
|
ObjectPropertyAccessor *setter = NULL;
|
|
|
|
|
|
|
|
if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
|
|
|
|
getter = property_get_uint64_ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
|
|
|
|
setter = property_set_uint64_ptr;
|
|
|
|
}
|
|
|
|
|
2020-05-05 15:29:14 +00:00
|
|
|
return object_property_add(obj, name, "uint64",
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
getter, setter, NULL, (void *)v);
|
2013-09-22 07:10:17 +00:00
|
|
|
}
|
|
|
|
|
2020-01-10 15:30:21 +00:00
|
|
|
ObjectProperty *
|
|
|
|
object_class_property_add_uint64_ptr(ObjectClass *klass, const char *name,
|
2020-02-04 13:15:58 +00:00
|
|
|
const uint64_t *v,
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
ObjectPropertyFlags flags)
|
2015-10-13 12:37:46 +00:00
|
|
|
{
|
2020-02-04 13:15:58 +00:00
|
|
|
ObjectPropertyAccessor *getter = NULL;
|
|
|
|
ObjectPropertyAccessor *setter = NULL;
|
|
|
|
|
|
|
|
if ((flags & OBJ_PROP_FLAG_READ) == OBJ_PROP_FLAG_READ) {
|
|
|
|
getter = property_get_uint64_ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((flags & OBJ_PROP_FLAG_WRITE) == OBJ_PROP_FLAG_WRITE) {
|
|
|
|
setter = property_set_uint64_ptr;
|
|
|
|
}
|
|
|
|
|
2020-01-10 15:30:21 +00:00
|
|
|
return object_class_property_add(klass, name, "uint64",
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
getter, setter, NULL, (void *)v);
|
2015-10-13 12:37:46 +00:00
|
|
|
}
|
|
|
|
|
2014-06-18 09:58:28 +00:00
|
|
|
typedef struct {
|
|
|
|
Object *target_obj;
|
2015-04-09 19:57:29 +00:00
|
|
|
char *target_name;
|
2014-06-18 09:58:28 +00:00
|
|
|
} AliasProperty;
|
|
|
|
|
qom: Swap 'name' next to visitor in ObjectPropertyAccessor
Similar to the previous patch, it's nice to have all functions
in the tree that involve a visitor and a name for conversion to
or from QAPI to consistently stick the 'name' parameter next
to the Visitor parameter.
Done by manually changing include/qom/object.h and qom/object.c,
then running this Coccinelle script and touching up the fallout
(Coccinelle insisted on adding some trailing whitespace).
@ rule1 @
identifier fn;
typedef Object, Visitor, Error;
identifier obj, v, opaque, name, errp;
@@
void fn
- (Object *obj, Visitor *v, void *opaque, const char *name,
+ (Object *obj, Visitor *v, const char *name, void *opaque,
Error **errp) { ... }
@@
identifier rule1.fn;
expression obj, v, opaque, name, errp;
@@
fn(obj, v,
- opaque, name,
+ name, opaque,
errp)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-20-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 13:48:55 +00:00
|
|
|
static void property_get_alias(Object *obj, Visitor *v, const char *name,
|
|
|
|
void *opaque, Error **errp)
|
2014-06-18 09:58:28 +00:00
|
|
|
{
|
|
|
|
AliasProperty *prop = opaque;
|
|
|
|
|
qom: Put name parameter before value / visitor parameter
The object_property_set_FOO() setters take property name and value in
an unusual order:
void object_property_set_FOO(Object *obj, FOO_TYPE value,
const char *name, Error **errp)
Having to pass value before name feels grating. Swap them.
Same for object_property_set(), object_property_get(), and
object_property_parse().
Convert callers with this Coccinelle script:
@@
identifier fun = {
object_property_get, object_property_parse, object_property_set_str,
object_property_set_link, object_property_set_bool,
object_property_set_int, object_property_set_uint, object_property_set,
object_property_set_qobject
};
expression obj, v, name, errp;
@@
- fun(obj, v, name, errp)
+ fun(obj, name, v, errp)
Chokes on hw/arm/musicpal.c's lcd_refresh() with the unhelpful error
message "no position information". Convert that one manually.
Fails to convert hw/arm/armsse.c, because Coccinelle gets confused by
ARMSSE being used both as typedef and function-like macro there.
Convert manually.
Fails to convert hw/rx/rx-gdbsim.c, because Coccinelle gets confused
by RXCPU being used both as typedef and function-like macro there.
Convert manually. The other files using RXCPU that way don't need
conversion.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-Id: <20200707160613.848843-27-armbru@redhat.com>
[Straightforwad conflict with commit 2336172d9b "audio: set default
value for pcspk.iobase property" resolved]
2020-07-07 16:05:54 +00:00
|
|
|
object_property_get(prop->target_obj, prop->target_name, v, errp);
|
2014-06-18 09:58:28 +00:00
|
|
|
}
|
|
|
|
|
qom: Swap 'name' next to visitor in ObjectPropertyAccessor
Similar to the previous patch, it's nice to have all functions
in the tree that involve a visitor and a name for conversion to
or from QAPI to consistently stick the 'name' parameter next
to the Visitor parameter.
Done by manually changing include/qom/object.h and qom/object.c,
then running this Coccinelle script and touching up the fallout
(Coccinelle insisted on adding some trailing whitespace).
@ rule1 @
identifier fn;
typedef Object, Visitor, Error;
identifier obj, v, opaque, name, errp;
@@
void fn
- (Object *obj, Visitor *v, void *opaque, const char *name,
+ (Object *obj, Visitor *v, const char *name, void *opaque,
Error **errp) { ... }
@@
identifier rule1.fn;
expression obj, v, opaque, name, errp;
@@
fn(obj, v,
- opaque, name,
+ name, opaque,
errp)
Signed-off-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <1454075341-13658-20-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 13:48:55 +00:00
|
|
|
static void property_set_alias(Object *obj, Visitor *v, const char *name,
|
|
|
|
void *opaque, Error **errp)
|
2014-06-18 09:58:28 +00:00
|
|
|
{
|
|
|
|
AliasProperty *prop = opaque;
|
|
|
|
|
qom: Put name parameter before value / visitor parameter
The object_property_set_FOO() setters take property name and value in
an unusual order:
void object_property_set_FOO(Object *obj, FOO_TYPE value,
const char *name, Error **errp)
Having to pass value before name feels grating. Swap them.
Same for object_property_set(), object_property_get(), and
object_property_parse().
Convert callers with this Coccinelle script:
@@
identifier fun = {
object_property_get, object_property_parse, object_property_set_str,
object_property_set_link, object_property_set_bool,
object_property_set_int, object_property_set_uint, object_property_set,
object_property_set_qobject
};
expression obj, v, name, errp;
@@
- fun(obj, v, name, errp)
+ fun(obj, name, v, errp)
Chokes on hw/arm/musicpal.c's lcd_refresh() with the unhelpful error
message "no position information". Convert that one manually.
Fails to convert hw/arm/armsse.c, because Coccinelle gets confused by
ARMSSE being used both as typedef and function-like macro there.
Convert manually.
Fails to convert hw/rx/rx-gdbsim.c, because Coccinelle gets confused
by RXCPU being used both as typedef and function-like macro there.
Convert manually. The other files using RXCPU that way don't need
conversion.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-Id: <20200707160613.848843-27-armbru@redhat.com>
[Straightforwad conflict with commit 2336172d9b "audio: set default
value for pcspk.iobase property" resolved]
2020-07-07 16:05:54 +00:00
|
|
|
object_property_set(prop->target_obj, prop->target_name, v, errp);
|
2014-06-18 09:58:28 +00:00
|
|
|
}
|
|
|
|
|
2014-06-05 11:11:51 +00:00
|
|
|
static Object *property_resolve_alias(Object *obj, void *opaque,
|
2020-05-05 15:29:10 +00:00
|
|
|
const char *part)
|
2014-06-05 11:11:51 +00:00
|
|
|
{
|
|
|
|
AliasProperty *prop = opaque;
|
|
|
|
|
|
|
|
return object_resolve_path_component(prop->target_obj, prop->target_name);
|
|
|
|
}
|
|
|
|
|
2014-06-18 09:58:28 +00:00
|
|
|
static void property_release_alias(Object *obj, const char *name, void *opaque)
|
|
|
|
{
|
|
|
|
AliasProperty *prop = opaque;
|
|
|
|
|
2015-04-09 19:57:29 +00:00
|
|
|
g_free(prop->target_name);
|
2014-06-18 09:58:28 +00:00
|
|
|
g_free(prop);
|
|
|
|
}
|
|
|
|
|
2020-05-05 15:29:14 +00:00
|
|
|
ObjectProperty *
|
|
|
|
object_property_add_alias(Object *obj, const char *name,
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
Object *target_obj, const char *target_name)
|
2014-06-18 09:58:28 +00:00
|
|
|
{
|
|
|
|
AliasProperty *prop;
|
2014-06-05 11:11:51 +00:00
|
|
|
ObjectProperty *op;
|
2014-06-18 09:58:28 +00:00
|
|
|
ObjectProperty *target_prop;
|
2020-05-05 15:29:14 +00:00
|
|
|
g_autofree char *prop_type = NULL;
|
2014-06-18 09:58:28 +00:00
|
|
|
|
2020-09-14 13:56:17 +00:00
|
|
|
target_prop = object_property_find_err(target_obj, target_name,
|
|
|
|
&error_abort);
|
2014-06-18 09:58:28 +00:00
|
|
|
|
2014-06-10 09:17:35 +00:00
|
|
|
if (object_property_is_child(target_prop)) {
|
|
|
|
prop_type = g_strdup_printf("link%s",
|
|
|
|
target_prop->type + strlen("child"));
|
|
|
|
} else {
|
|
|
|
prop_type = g_strdup(target_prop->type);
|
|
|
|
}
|
|
|
|
|
2014-06-18 09:58:28 +00:00
|
|
|
prop = g_malloc(sizeof(*prop));
|
|
|
|
prop->target_obj = target_obj;
|
2015-04-09 19:57:29 +00:00
|
|
|
prop->target_name = g_strdup(target_name);
|
2014-06-18 09:58:28 +00:00
|
|
|
|
2014-06-10 09:17:35 +00:00
|
|
|
op = object_property_add(obj, name, prop_type,
|
2014-06-05 11:11:51 +00:00
|
|
|
property_get_alias,
|
|
|
|
property_set_alias,
|
|
|
|
property_release_alias,
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
prop);
|
2014-06-05 11:11:51 +00:00
|
|
|
op->resolve = property_resolve_alias;
|
2020-01-10 15:30:23 +00:00
|
|
|
if (target_prop->defval) {
|
|
|
|
op->defval = qobject_ref(target_prop->defval);
|
|
|
|
}
|
2014-06-10 09:17:35 +00:00
|
|
|
|
2015-03-27 16:34:10 +00:00
|
|
|
object_property_set_description(obj, op->name,
|
2020-05-05 15:29:15 +00:00
|
|
|
target_prop->description);
|
2020-05-05 15:29:14 +00:00
|
|
|
return op;
|
2014-06-18 09:58:28 +00:00
|
|
|
}
|
|
|
|
|
2014-10-07 06:33:21 +00:00
|
|
|
void object_property_set_description(Object *obj, const char *name,
|
2020-05-05 15:29:15 +00:00
|
|
|
const char *description)
|
2014-10-07 06:33:21 +00:00
|
|
|
{
|
|
|
|
ObjectProperty *op;
|
|
|
|
|
2020-09-14 13:56:17 +00:00
|
|
|
op = object_property_find_err(obj, name, &error_abort);
|
2014-10-07 06:33:21 +00:00
|
|
|
g_free(op->description);
|
|
|
|
op->description = g_strdup(description);
|
|
|
|
}
|
|
|
|
|
2015-10-13 12:37:46 +00:00
|
|
|
void object_class_property_set_description(ObjectClass *klass,
|
|
|
|
const char *name,
|
2020-05-05 15:29:15 +00:00
|
|
|
const char *description)
|
2015-10-13 12:37:46 +00:00
|
|
|
{
|
|
|
|
ObjectProperty *op;
|
|
|
|
|
|
|
|
op = g_hash_table_lookup(klass->properties, name);
|
|
|
|
g_free(op->description);
|
|
|
|
op->description = g_strdup(description);
|
|
|
|
}
|
|
|
|
|
2018-09-06 14:09:32 +00:00
|
|
|
static void object_class_init(ObjectClass *klass, void *data)
|
2012-04-02 15:33:51 +00:00
|
|
|
{
|
2020-07-07 16:05:50 +00:00
|
|
|
object_class_property_add_str(klass, "type", object_get_type,
|
qom: Drop parameter @errp of object_property_add() & friends
The only way object_property_add() can fail is when a property with
the same name already exists. Since our property names are all
hardcoded, failure is a programming error, and the appropriate way to
handle it is passing &error_abort.
Same for its variants, except for object_property_add_child(), which
additionally fails when the child already has a parent. Parentage is
also under program control, so this is a programming error, too.
We have a bit over 500 callers. Almost half of them pass
&error_abort, slightly fewer ignore errors, one test case handles
errors, and the remaining few callers pass them to their own callers.
The previous few commits demonstrated once again that ignoring
programming errors is a bad idea.
Of the few ones that pass on errors, several violate the Error API.
The Error ** argument must be NULL, &error_abort, &error_fatal, or a
pointer to a variable containing NULL. Passing an argument of the
latter kind twice without clearing it in between is wrong: if the
first call sets an error, it no longer points to NULL for the second
call. ich9_pm_add_properties(), sparc32_ledma_realize(),
sparc32_dma_realize(), xilinx_axidma_realize(), xilinx_enet_realize()
are wrong that way.
When the one appropriate choice of argument is &error_abort, letting
users pick the argument is a bad idea.
Drop parameter @errp and assert the preconditions instead.
There's one exception to "duplicate property name is a programming
error": the way object_property_add() implements the magic (and
undocumented) "automatic arrayification". Don't drop @errp there.
Instead, rename object_property_add() to object_property_try_add(),
and add the obvious wrapper object_property_add().
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200505152926.18877-15-armbru@redhat.com>
[Two semantic rebase conflicts resolved]
2020-05-05 15:29:22 +00:00
|
|
|
NULL);
|
2012-04-02 15:33:51 +00:00
|
|
|
}
|
|
|
|
|
2012-03-31 14:45:54 +00:00
|
|
|
static void register_types(void)
|
|
|
|
{
|
|
|
|
static TypeInfo interface_info = {
|
|
|
|
.name = TYPE_INTERFACE,
|
2012-08-10 03:16:10 +00:00
|
|
|
.class_size = sizeof(InterfaceClass),
|
2012-03-31 14:45:54 +00:00
|
|
|
.abstract = true,
|
|
|
|
};
|
|
|
|
|
|
|
|
static TypeInfo object_info = {
|
|
|
|
.name = TYPE_OBJECT,
|
|
|
|
.instance_size = sizeof(Object),
|
2018-09-06 14:09:32 +00:00
|
|
|
.class_init = object_class_init,
|
2012-03-31 14:45:54 +00:00
|
|
|
.abstract = true,
|
|
|
|
};
|
|
|
|
|
2012-04-04 13:58:40 +00:00
|
|
|
type_interface = type_register_internal(&interface_info);
|
|
|
|
type_register_internal(&object_info);
|
2012-03-31 14:45:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type_init(register_types)
|