qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v1 8/9] qom: add command to print initial properties


From: Vladimir Sementsov-Ogievskiy
Subject: Re: [PATCH v1 8/9] qom: add command to print initial properties
Date: Wed, 30 Mar 2022 18:17:41 +0300
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.5.0

29.03.2022 00:15, Maxim Davydov wrote:
The command "query-init-properties" is needed to get values of properties
after initialization (not only default value). It makes sense, for example,
when working with x86_64-cpu.
All machine types (and x-remote-object, because its init uses machime
type's infrastructure) should be skipped, because only the one instance can
be correctly initialized.

Signed-off-by: Maxim Davydov <maxim.davydov@openvz.org>
---
  qapi/qom.json      |  69 ++++++++++++++++++++++++++
  qom/qom-qmp-cmds.c | 121 +++++++++++++++++++++++++++++++++++++++++++++
  2 files changed, 190 insertions(+)

diff --git a/qapi/qom.json b/qapi/qom.json
index eeb5395ff3..1eedc441eb 100644
--- a/qapi/qom.json
+++ b/qapi/qom.json
@@ -949,3 +949,72 @@
  ##
  { 'command': 'object-del', 'data': {'id': 'str'},
    'allow-preconfig': true }
+
+##
+# @InitValue:
+#
+# Not all objects have default values but they have "initial" values.
+#
+# @name: property name
+#
+# @value: Current value (default or after initialization. It makes sence,
+#         for example, for x86-cpus)
+#
+# Since: 7.0

7.1 (here and below)

+#
+##
+{ 'struct': 'InitValue',
+  'data': { 'name': 'str',
+            '*value': 'any' } }
+

[..]

diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c
index 2d6f41ecc7..c1bb3f1f8b 100644
--- a/qom/qom-qmp-cmds.c
+++ b/qom/qom-qmp-cmds.c
@@ -27,6 +27,7 @@
  #include "qemu/cutils.h"
  #include "qom/object_interfaces.h"
  #include "qom/qom-qobject.h"
+#include "hw/boards.h"
ObjectPropertyInfoList *qmp_qom_list(const char *path, Error **errp)
  {
@@ -235,3 +236,123 @@ void qmp_object_del(const char *id, Error **errp)
  {
      user_creatable_del(id, errp);
  }
+
+static void query_object_prop(InitValueList **props_list, ObjectProperty *prop,
+                              Object *obj, Error **errp)
+{
+    InitValue *prop_info = NULL;
+
+    /* Skip inconsiderable properties */
+    if (strcmp(prop->name, "type") == 0 ||
+        strcmp(prop->name, "realized") == 0 ||
+        strcmp(prop->name, "hotpluggable") == 0 ||
+        strcmp(prop->name, "hotplugged") == 0 ||
+        strcmp(prop->name, "parent_bus") == 0) {
+        return;
+    }
+
+    prop_info = g_malloc0(sizeof(*prop_info));
+    prop_info->name = g_strdup(prop->name);
+    prop_info->value = NULL;
+    if (prop->defval) {
+        prop_info->value = qobject_ref(prop->defval);
+    } else if (prop->get) {
+        /*
+         * crash-information in x86-cpu uses errp to return current state.
+         * So, after requesting this property it returns  GenericError:
+         * "No crash occured"
+         */
+        if (strcmp(prop->name, "crash-information") != 0) {
+            prop_info->value = object_property_get_qobject(obj, prop->name,
+                                                           errp);
+        }
+    }

Hmmm. Should we instead call prop->get() when is is available, and only if not use 
prep->defval?

+    prop_info->has_value = !!prop_info->value;
+
+    QAPI_LIST_PREPEND(*props_list, prop_info);
+}
+
+typedef struct QIPData {
+    InitPropsList **dev_list;
+    Error **errp;
+} QIPData;
+
+static void query_init_properties_tramp(gpointer list_data, gpointer opaque)
+{
+    ObjectClass *k = list_data;
+    Object *obj;
+    ObjectClass *parent;
+    GHashTableIter iter;
+
+    QIPData *data = opaque;
+    ClassPropertiesList *class_props_list = NULL;
+    InitProps *dev_info;
+
+    /* Only one machine can be initialized correctly (it's already happened) */
+    if (object_class_dynamic_cast(k, TYPE_MACHINE)) {
+        return;
+    }
+
+    const char *klass_name = object_class_get_name(k);
+    /*
+     * Uses machine type infrastructure with notifiers. It causes immediate
+     * notify and SEGSEGV during remote_object_machine_done
+     */
+    if (strcmp(klass_name, "x-remote-object") == 0) {
+        return;
+    }
+
+    dev_info = g_malloc0(sizeof(*dev_info));
+    dev_info->name = g_strdup(klass_name);
+
+    obj = object_new_with_class(k);
+
+    /*
+     * Part of ObjectPropertyIterator infrastructure, but we need more precise
+     * control of current class to dump appropriate features
+     * This part was taken out from loop because first initialization differ
+     * from other reinitializations
+     */
+    parent = object_get_class(obj);

hmm.. obj = object_new_with_class(k); parent = object_get_class(obj);.. Looks 
for me like parent should be equal to k. Or object_ API is rather unobvious.

+    g_hash_table_iter_init(&iter, obj->properties);
+    const char *prop_owner_name = object_get_typename(obj);
+    do {
+        InitValueList *prop_list = NULL;
+        ClassProperties *class_data;
+
+        gpointer key, val;
+        while (g_hash_table_iter_next(&iter, &key, &val)) {
+            query_object_prop(&prop_list, (ObjectProperty *)val, obj,
+                              data->errp);
+        }
+        class_data = g_malloc0(sizeof(*class_data));
+        class_data->classname = g_strdup(prop_owner_name);
+        class_data->classprops = prop_list;
+        class_data->has_classprops = !!prop_list;
+
+        QAPI_LIST_PREPEND(class_props_list, class_data);
+
+        if (!parent) {
+            break;
+        }
+        g_hash_table_iter_init(&iter, parent->properties);
+        prop_owner_name = object_class_get_name(parent);
+        parent = object_class_get_parent(parent);
+    } while (true);
+    dev_info->props = class_props_list;
+    object_unref(OBJECT(obj));
+
+    QAPI_LIST_PREPEND(*(data->dev_list), dev_info);
+}
+
+InitPropsList *qmp_query_init_properties(Error **errp)
+{
+    GSList *typename_list = object_class_get_list(TYPE_OBJECT, false);
+
+    InitPropsList *dev_list = NULL;
+    QIPData data = { &dev_list, errp };
+    g_slist_foreach(typename_list, query_init_properties_tramp, &data);
+    g_slist_free(typename_list);
+
+    return dev_list;
+}


--
Best regards,
Vladimir



reply via email to

[Prev in Thread] Current Thread [Next in Thread]