aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Sistare <steven.sistare@oracle.com>2025-07-11 08:45:01 -0700
committerMarkus Armbruster <armbru@redhat.com>2025-07-16 16:51:21 +0200
commit8eb6d39e22a2f9ea1a415d95d3c3ac5d5752b6d7 (patch)
treebf99db25dbcaf941266f7fd1e2dee8ef3304bdaf
parentf96b157ebb93f94cd56ebbc99bc20982b8fd86ef (diff)
downloadqemu-8eb6d39e22a2f9ea1a415d95d3c3ac5d5752b6d7.zip
qemu-8eb6d39e22a2f9ea1a415d95d3c3ac5d5752b6d7.tar.gz
qemu-8eb6d39e22a2f9ea1a415d95d3c3ac5d5752b6d7.tar.bz2
qom: qom-list-get
Using qom-list and qom-get to get all the nodes and property values in a QOM tree can take multiple seconds because it requires 1000's of individual QOM requests. Some managers fetch the entire tree or a large subset of it when starting a new VM, and this cost is a substantial fraction of start up time. Define the qom-list-get command, which fetches all the properties and values for a list of paths. This can be much faster than qom-list plus qom-get. When getting an entire QOM tree, I measured a 10x speedup in elapsed time. Signed-off-by: Steve Sistare <steven.sistare@oracle.com> Tested-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Markus Armbruster <armbru@redhat.com> Message-ID: <1752248703-217318-2-git-send-email-steven.sistare@oracle.com> Signed-off-by: Markus Armbruster <armbru@redhat.com>
-rw-r--r--qapi/qom.json50
-rw-r--r--qom/qom-qmp-cmds.c53
2 files changed, 103 insertions, 0 deletions
diff --git a/qapi/qom.json b/qapi/qom.json
index 96d56df..830cb2f 100644
--- a/qapi/qom.json
+++ b/qapi/qom.json
@@ -48,6 +48,34 @@
'*default-value': 'any' } }
##
+# @ObjectPropertyValue:
+#
+# @name: the name of the property.
+#
+# @type: the type of the property, as described in `ObjectPropertyInfo`.
+#
+# @value: the value of the property. Absent when the property cannot
+# be read.
+#
+# Since 10.1
+##
+{ 'struct': 'ObjectPropertyValue',
+ 'data': { 'name': 'str',
+ 'type': 'str',
+ '*value': 'any' } }
+
+##
+# @ObjectPropertiesValues:
+#
+# @properties: a list of properties.
+#
+# Since 10.1
+##
+{ 'struct': 'ObjectPropertiesValues',
+ 'data': { 'properties': [ 'ObjectPropertyValue' ] }}
+
+
+##
# @qom-list:
#
# List properties of a object given a path in the object model.
@@ -125,6 +153,28 @@
'allow-preconfig': true }
##
+# @qom-list-get:
+#
+# List properties and their values for each object path in the input
+# list.
+#
+# @paths: The absolute or partial path for each object, as described
+# in `qom-get`.
+#
+# Errors:
+# - If any path is not valid or is ambiguous
+#
+# Returns: A list where each element is the result for the
+# corresponding element of @paths.
+#
+# Since 10.1
+##
+{ 'command': 'qom-list-get',
+ 'data': { 'paths': [ 'str' ] },
+ 'returns': [ 'ObjectPropertiesValues' ],
+ 'allow-preconfig': true }
+
+##
# @qom-set:
#
# Set a property value.
diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c
index 293755f..57f1898 100644
--- a/qom/qom-qmp-cmds.c
+++ b/qom/qom-qmp-cmds.c
@@ -69,6 +69,59 @@ ObjectPropertyInfoList *qmp_qom_list(const char *path, Error **errp)
return props;
}
+static void qom_list_add_property_value(Object *obj, ObjectProperty *prop,
+ ObjectPropertyValueList **props)
+{
+ ObjectPropertyValue *item = g_new0(ObjectPropertyValue, 1);
+
+ QAPI_LIST_PREPEND(*props, item);
+
+ item->name = g_strdup(prop->name);
+ item->type = g_strdup(prop->type);
+ item->value = object_property_get_qobject(obj, prop->name, NULL);
+}
+
+static ObjectPropertyValueList *qom_get_property_value_list(const char *path,
+ Error **errp)
+{
+ Object *obj;
+ ObjectProperty *prop;
+ ObjectPropertyIterator iter;
+ ObjectPropertyValueList *props = NULL;
+
+ obj = qom_resolve_path(path, errp);
+ if (obj == NULL) {
+ return NULL;
+ }
+
+ object_property_iter_init(&iter, obj);
+ while ((prop = object_property_iter_next(&iter))) {
+ qom_list_add_property_value(obj, prop, &props);
+ }
+
+ return props;
+}
+
+ObjectPropertiesValuesList *qmp_qom_list_get(strList *paths, Error **errp)
+{
+ ObjectPropertiesValuesList *head = NULL, **tail = &head;
+ strList *path;
+
+ for (path = paths; path; path = path->next) {
+ ObjectPropertiesValues *item = g_new0(ObjectPropertiesValues, 1);
+
+ QAPI_LIST_APPEND(tail, item);
+
+ item->properties = qom_get_property_value_list(path->value, errp);
+ if (!item->properties) {
+ qapi_free_ObjectPropertiesValuesList(head);
+ return NULL;
+ }
+ }
+
+ return head;
+}
+
void qmp_qom_set(const char *path, const char *property, QObject *value,
Error **errp)
{