diff mbox series

[08/12] qom: allow for properties to become "fixed"

Message ID 20230414160433.2096866-9-alex.bennee@linaro.org
State New
Headers show
Series virtio: add vhost-user-generic and reduce copy and paste | expand

Commit Message

Alex Bennée April 14, 2023, 4:04 p.m. UTC
When specialising general purpose objects it is sometimes useful to
"fix" some of the properties that were configurable by the base
classes. We will use this facility when specialising
vhost-user-device.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 qapi/qom.json           |  2 ++
 include/qom/object.h    | 16 +++++++++++++++-
 qom/object.c            | 14 ++++++++++++++
 qom/object_interfaces.c |  9 ++++++---
 qom/qom-qmp-cmds.c      |  1 +
 softmmu/qdev-monitor.c  |  1 +
 6 files changed, 39 insertions(+), 4 deletions(-)

Comments

Markus Armbruster April 17, 2023, 10:02 a.m. UTC | #1
Alex Bennée <alex.bennee@linaro.org> writes:

> When specialising general purpose objects it is sometimes useful to
> "fix" some of the properties that were configurable by the base
> classes. We will use this facility when specialising
> vhost-user-device.
>
> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
> ---
>  qapi/qom.json           |  2 ++
>  include/qom/object.h    | 16 +++++++++++++++-
>  qom/object.c            | 14 ++++++++++++++
>  qom/object_interfaces.c |  9 ++++++---
>  qom/qom-qmp-cmds.c      |  1 +
>  softmmu/qdev-monitor.c  |  1 +
>  6 files changed, 39 insertions(+), 4 deletions(-)
>
> diff --git a/qapi/qom.json b/qapi/qom.json
> index a877b879b9..4cda191f00 100644
> --- a/qapi/qom.json
> +++ b/qapi/qom.json
> @@ -33,12 +33,14 @@
>  # @description: if specified, the description of the property.
>  #
>  # @default-value: the default value, if any (since 5.0)
> +# @fixed: if specified if value has been fixed (since 8.1)

Wat?

>  #
>  # Since: 1.2
>  ##
>  { 'struct': 'ObjectPropertyInfo',
>    'data': { 'name': 'str',
>              'type': 'str',
> +            'fixed': 'bool',
>              '*description': 'str',
>              '*default-value': 'any' } }
>  

qom-list and qom-list-properties return a list of this.  Use cases for
the new member?

[...]
Alex Bennée April 17, 2023, 11:26 a.m. UTC | #2
Markus Armbruster <armbru@redhat.com> writes:

> Alex Bennée <alex.bennee@linaro.org> writes:
>
>> When specialising general purpose objects it is sometimes useful to
>> "fix" some of the properties that were configurable by the base
>> classes. We will use this facility when specialising
>> vhost-user-device.
>>
>> Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
>> ---
>>  qapi/qom.json           |  2 ++
>>  include/qom/object.h    | 16 +++++++++++++++-
>>  qom/object.c            | 14 ++++++++++++++
>>  qom/object_interfaces.c |  9 ++++++---
>>  qom/qom-qmp-cmds.c      |  1 +
>>  softmmu/qdev-monitor.c  |  1 +
>>  6 files changed, 39 insertions(+), 4 deletions(-)
>>
>> diff --git a/qapi/qom.json b/qapi/qom.json
>> index a877b879b9..4cda191f00 100644
>> --- a/qapi/qom.json
>> +++ b/qapi/qom.json
>> @@ -33,12 +33,14 @@
>>  # @description: if specified, the description of the property.
>>  #
>>  # @default-value: the default value, if any (since 5.0)
>> +# @fixed: if specified if value has been fixed (since 8.1)
>
> Wat?
>
>>  #
>>  # Since: 1.2
>>  ##
>>  { 'struct': 'ObjectPropertyInfo',
>>    'data': { 'name': 'str',
>>              'type': 'str',
>> +            'fixed': 'bool',
>>              '*description': 'str',
>>              '*default-value': 'any' } }
>>  
>
> qom-list and qom-list-properties return a list of this.  Use cases for
> the new member?

The use-case is this whole series. Basically I want to have a generic
device (vhost-user-device) which has a bunch of control knobs the user
can fiddle with (e.g. virtio id, num_vqs and the like). However for the
specialised versions of this device (e.g. vhost-user-gpio) some of these
values (e.g. virtio id) need to be fixed.

Mark suggested maybe just duplicating the properties in a similar way to
DEFINE_AUDIO_PROPERTIES but that doesn't really address the problem
wanting to "fix" some of the values for the subclasses and preventing
the user from changing things.

I appreciate this is possibly a horrible hack so I'm open to the QOM
experts showing me the correct way to model this sort of behaviour.
Peter Maydell April 17, 2023, 12:04 p.m. UTC | #3
On Mon, 17 Apr 2023 at 12:33, Alex Bennée <alex.bennee@linaro.org> wrote:
> The use-case is this whole series. Basically I want to have a generic
> device (vhost-user-device) which has a bunch of control knobs the user
> can fiddle with (e.g. virtio id, num_vqs and the like). However for the
> specialised versions of this device (e.g. vhost-user-gpio) some of these
> values (e.g. virtio id) need to be fixed.

> Mark suggested maybe just duplicating the properties in a similar way to
> DEFINE_AUDIO_PROPERTIES but that doesn't really address the problem
> wanting to "fix" some of the values for the subclasses and preventing
> the user from changing things.

This shouldn't be something visible to the user of the object,
though, surely? An object which doesn't have a configurable
virtio-id property because the specific subclass has a fixed
value should look exactly like an object which doesn't have
a configurable virtio-id property because that property just
doesn't exist.

If we add a facility for "constant properties" (which is pretty
much what this would be) then we should do it because it's
useful for users of QOM objects (and especially for users of
QOM objects via the QMP interface) to be able to introspect
them and say "ah, this is a property of the object but it's
a constant value".

thanks
-- PMM
diff mbox series

Patch

diff --git a/qapi/qom.json b/qapi/qom.json
index a877b879b9..4cda191f00 100644
--- a/qapi/qom.json
+++ b/qapi/qom.json
@@ -33,12 +33,14 @@ 
 # @description: if specified, the description of the property.
 #
 # @default-value: the default value, if any (since 5.0)
+# @fixed: if specified if value has been fixed (since 8.1)
 #
 # Since: 1.2
 ##
 { 'struct': 'ObjectPropertyInfo',
   'data': { 'name': 'str',
             'type': 'str',
+            'fixed': 'bool',
             '*description': 'str',
             '*default-value': 'any' } }
 
diff --git a/include/qom/object.h b/include/qom/object.h
index ef7258a5e1..f18d1a8254 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -97,6 +97,8 @@  struct ObjectProperty
     ObjectPropertyInit *init;
     void *opaque;
     QObject *defval;
+    /** @fixed: if the property has been fixed at its default */
+    bool fixed;
 };
 
 /**
@@ -1111,6 +1113,17 @@  void object_property_set_default_int(ObjectProperty *prop, int64_t value);
  */
 void object_property_set_default_uint(ObjectProperty *prop, uint64_t value);
 
+/**
+ * object_property_fix_default_uint:
+ * @prop: the property to be fixed
+ * @value: the fixed value to be written to the property
+ *
+ * When specialising an object it may make send to fix some values and
+ * not allow them to be changed. This can only be applied to
+ * properties that previously had a default and now cannot be changed.
+ */
+void object_property_fix_default_uint(ObjectProperty *prop, uint64_t value);
+
 /**
  * object_property_find:
  * @obj: the object
@@ -1961,13 +1974,14 @@  size_t object_type_get_instance_size(const char *typename);
  * object_property_help:
  * @name: the name of the property
  * @type: the type of the property
+ * @fixed: has the value been fixed
  * @defval: the default value
  * @description: description of the property
  *
  * Returns: a user-friendly formatted string describing the property
  * for help purposes.
  */
-char *object_property_help(const char *name, const char *type,
+char *object_property_help(const char *name, const char *type, bool fixed,
                            QObject *defval, const char *description);
 
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(Object, object_unref)
diff --git a/qom/object.c b/qom/object.c
index e25f1e96db..b5aba3ffc8 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -1584,6 +1584,20 @@  void object_property_set_default_uint(ObjectProperty *prop, uint64_t value)
     object_property_set_default(prop, QOBJECT(qnum_from_uint(value)));
 }
 
+static void object_property_fix_default(ObjectProperty *prop, QObject *defval)
+{
+    g_assert(prop->init == object_property_init_defval);
+    g_assert(!prop->fixed);
+
+    prop->defval = defval;
+    prop->fixed = true;
+}
+
+void object_property_fix_default_uint(ObjectProperty *prop, uint64_t value)
+{
+    object_property_fix_default(prop, QOBJECT(qnum_from_uint(value)));
+}
+
 bool object_property_set_uint(Object *obj, const char *name,
                               uint64_t value, Error **errp)
 {
diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
index 7d31589b04..e351938f8f 100644
--- a/qom/object_interfaces.c
+++ b/qom/object_interfaces.c
@@ -161,7 +161,7 @@  void user_creatable_add_qapi(ObjectOptions *options, Error **errp)
     visit_free(v);
 }
 
-char *object_property_help(const char *name, const char *type,
+char *object_property_help(const char *name, const char *type, bool fixed,
                            QObject *defval, const char *description)
 {
     GString *str = g_string_new(NULL);
@@ -179,7 +179,9 @@  char *object_property_help(const char *name, const char *type,
     if (defval) {
         g_autofree char *def_json = g_string_free(qobject_to_json(defval),
                                                   false);
-        g_string_append_printf(str, " (default: %s)", def_json);
+        g_string_append_printf(str, " (%s: %s)",
+                               fixed ? "fixed" : "default",
+                               def_json);
     }
 
     return g_string_free(str, false);
@@ -220,7 +222,8 @@  bool type_print_class_properties(const char *type)
 
         g_ptr_array_add(array,
                         object_property_help(prop->name, prop->type,
-                                             prop->defval, prop->description));
+                                             prop->fixed, prop->defval,
+                                             prop->description));
     }
     g_ptr_array_sort(array, (GCompareFunc)qemu_pstrcmp0);
     if (array->len > 0) {
diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c
index 7c087299de..f4cdf4ddde 100644
--- a/qom/qom-qmp-cmds.c
+++ b/qom/qom-qmp-cmds.c
@@ -55,6 +55,7 @@  ObjectPropertyInfoList *qmp_qom_list(const char *path, Error **errp)
 
         value->name = g_strdup(prop->name);
         value->type = g_strdup(prop->type);
+        value->fixed = prop->fixed;
     }
 
     return props;
diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c
index b8d2c4dadd..b56b2af2f2 100644
--- a/softmmu/qdev-monitor.c
+++ b/softmmu/qdev-monitor.c
@@ -315,6 +315,7 @@  int qdev_device_help(QemuOpts *opts)
         g_ptr_array_add(array,
                         object_property_help(prop->value->name,
                                              prop->value->type,
+                                             prop->value->fixed,
                                              prop->value->default_value,
                                              prop->value->description));
     }