Child alias properties allow a parent object to expose child object properties. This makes it possible for a parent object to forward all or a subset of a child's properties.
Currently we achieve similar behavior by duplicating property definitions and copying the fields around. It turns out virtio has several double-frees since we didn't get the memory management right. Using child alias properties it will be much easier for a parent object to set a child's properties without fragile memory management issues since the actual field only exists once in the child object. Signed-off-by: Stefan Hajnoczi <stefa...@redhat.com> --- hw/core/qdev-properties.c | 28 ++++++++++++++++++++++++++++ include/hw/qdev-properties.h | 28 ++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c index 77d0c66..e62a4fd 100644 --- a/hw/core/qdev-properties.c +++ b/hw/core/qdev-properties.c @@ -1002,3 +1002,31 @@ PropertyInfo qdev_prop_size = { .get = get_size, .set = set_size, }; + +/* --- alias that forwards to a child object's property --- */ + +static void get_child_alias(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + Object *child = OBJECT(qdev_get_prop_ptr(dev, prop)); + + object_property_get(child, v, name, errp); +} + +static void set_child_alias(Object *obj, Visitor *v, void *opaque, + const char *name, Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + Object *child = OBJECT(qdev_get_prop_ptr(dev, prop)); + + object_property_set(child, v, name, errp); +} + +PropertyInfo qdev_prop_child_alias = { + .name = "ChildAlias", + .get = get_child_alias, + .set = set_child_alias, +}; diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h index 3c000ee..5ab1cac 100644 --- a/include/hw/qdev-properties.h +++ b/include/hw/qdev-properties.h @@ -13,6 +13,7 @@ extern PropertyInfo qdev_prop_uint32; extern PropertyInfo qdev_prop_int32; extern PropertyInfo qdev_prop_uint64; extern PropertyInfo qdev_prop_size; +extern PropertyInfo qdev_prop_child_alias; extern PropertyInfo qdev_prop_string; extern PropertyInfo qdev_prop_chr; extern PropertyInfo qdev_prop_ptr; @@ -61,6 +62,33 @@ extern PropertyInfo qdev_prop_arraylen; .defval = (bool)_defval, \ } +/** + * DEFINE_PROP_CHILD_ALIAS: + * @_name: property name + * @_state: name of the device state structure type + * @_field: name of field in @_state, must be Object subclass + * + * Define device properties that alias a child object's property. For example, + * use the following to forward the 'baz' property where Foo embeds a Bar + * object: + * + * typedef struct { + * Object parent_obj; + * + * Bar bar_obj; + * } Foo; + * + * DEFINE_PROP_CHILD_ALIAS("baz", Foo, bar_obj) + * + * Any access to Foo's 'baz' property actually accesses bar_obj's 'baz' + * property. + */ +#define DEFINE_PROP_CHILD_ALIAS(_name, _state, _field) { \ + .name = (_name), \ + .info = &(qdev_prop_child_alias), \ + .offset = offsetof(_state, _field), \ + } + #define PROP_ARRAY_LEN_PREFIX "len-" /** -- 1.8.5.3