1aa09b3d5SMarkus Armbruster /*
2aa09b3d5SMarkus Armbruster * QMP commands related to stats
3aa09b3d5SMarkus Armbruster *
4aa09b3d5SMarkus Armbruster * This work is licensed under the terms of the GNU GPL, version 2 or
5aa09b3d5SMarkus Armbruster * (at your option) any later version.
6aa09b3d5SMarkus Armbruster */
7aa09b3d5SMarkus Armbruster
8aa09b3d5SMarkus Armbruster #include "qemu/osdep.h"
9aa09b3d5SMarkus Armbruster #include "sysemu/stats.h"
10aa09b3d5SMarkus Armbruster #include "qapi/qapi-commands-stats.h"
11aa09b3d5SMarkus Armbruster #include "qemu/queue.h"
12aa09b3d5SMarkus Armbruster #include "qapi/error.h"
13aa09b3d5SMarkus Armbruster
14aa09b3d5SMarkus Armbruster typedef struct StatsCallbacks {
15aa09b3d5SMarkus Armbruster StatsProvider provider;
16aa09b3d5SMarkus Armbruster StatRetrieveFunc *stats_cb;
17aa09b3d5SMarkus Armbruster SchemaRetrieveFunc *schemas_cb;
18aa09b3d5SMarkus Armbruster QTAILQ_ENTRY(StatsCallbacks) next;
19aa09b3d5SMarkus Armbruster } StatsCallbacks;
20aa09b3d5SMarkus Armbruster
21aa09b3d5SMarkus Armbruster static QTAILQ_HEAD(, StatsCallbacks) stats_callbacks =
22aa09b3d5SMarkus Armbruster QTAILQ_HEAD_INITIALIZER(stats_callbacks);
23aa09b3d5SMarkus Armbruster
add_stats_callbacks(StatsProvider provider,StatRetrieveFunc * stats_fn,SchemaRetrieveFunc * schemas_fn)24aa09b3d5SMarkus Armbruster void add_stats_callbacks(StatsProvider provider,
25aa09b3d5SMarkus Armbruster StatRetrieveFunc *stats_fn,
26aa09b3d5SMarkus Armbruster SchemaRetrieveFunc *schemas_fn)
27aa09b3d5SMarkus Armbruster {
28aa09b3d5SMarkus Armbruster StatsCallbacks *entry = g_new(StatsCallbacks, 1);
29aa09b3d5SMarkus Armbruster entry->provider = provider;
30aa09b3d5SMarkus Armbruster entry->stats_cb = stats_fn;
31aa09b3d5SMarkus Armbruster entry->schemas_cb = schemas_fn;
32aa09b3d5SMarkus Armbruster
33aa09b3d5SMarkus Armbruster QTAILQ_INSERT_TAIL(&stats_callbacks, entry, next);
34aa09b3d5SMarkus Armbruster }
35aa09b3d5SMarkus Armbruster
invoke_stats_cb(StatsCallbacks * entry,StatsResultList ** stats_results,StatsFilter * filter,StatsRequest * request,Error ** errp)36aa09b3d5SMarkus Armbruster static bool invoke_stats_cb(StatsCallbacks *entry,
37aa09b3d5SMarkus Armbruster StatsResultList **stats_results,
38aa09b3d5SMarkus Armbruster StatsFilter *filter, StatsRequest *request,
39aa09b3d5SMarkus Armbruster Error **errp)
40aa09b3d5SMarkus Armbruster {
41aa09b3d5SMarkus Armbruster ERRP_GUARD();
42aa09b3d5SMarkus Armbruster strList *targets = NULL;
43aa09b3d5SMarkus Armbruster strList *names = NULL;
44aa09b3d5SMarkus Armbruster
45aa09b3d5SMarkus Armbruster if (request) {
46aa09b3d5SMarkus Armbruster if (request->provider != entry->provider) {
47aa09b3d5SMarkus Armbruster return true;
48aa09b3d5SMarkus Armbruster }
49aa09b3d5SMarkus Armbruster if (request->has_names && !request->names) {
50aa09b3d5SMarkus Armbruster return true;
51aa09b3d5SMarkus Armbruster }
52aa09b3d5SMarkus Armbruster names = request->has_names ? request->names : NULL;
53aa09b3d5SMarkus Armbruster }
54aa09b3d5SMarkus Armbruster
55aa09b3d5SMarkus Armbruster switch (filter->target) {
56aa09b3d5SMarkus Armbruster case STATS_TARGET_VM:
57aa09b3d5SMarkus Armbruster break;
58aa09b3d5SMarkus Armbruster case STATS_TARGET_VCPU:
59aa09b3d5SMarkus Armbruster if (filter->u.vcpu.has_vcpus) {
60aa09b3d5SMarkus Armbruster if (!filter->u.vcpu.vcpus) {
61aa09b3d5SMarkus Armbruster /* No targets allowed? Return no statistics. */
62aa09b3d5SMarkus Armbruster return true;
63aa09b3d5SMarkus Armbruster }
64aa09b3d5SMarkus Armbruster targets = filter->u.vcpu.vcpus;
65aa09b3d5SMarkus Armbruster }
66aa09b3d5SMarkus Armbruster break;
67*f2b90109Szhenwei pi case STATS_TARGET_CRYPTODEV:
68*f2b90109Szhenwei pi break;
69aa09b3d5SMarkus Armbruster default:
70aa09b3d5SMarkus Armbruster abort();
71aa09b3d5SMarkus Armbruster }
72aa09b3d5SMarkus Armbruster
73aa09b3d5SMarkus Armbruster entry->stats_cb(stats_results, filter->target, names, targets, errp);
74aa09b3d5SMarkus Armbruster if (*errp) {
75aa09b3d5SMarkus Armbruster qapi_free_StatsResultList(*stats_results);
76aa09b3d5SMarkus Armbruster *stats_results = NULL;
77aa09b3d5SMarkus Armbruster return false;
78aa09b3d5SMarkus Armbruster }
79aa09b3d5SMarkus Armbruster return true;
80aa09b3d5SMarkus Armbruster }
81aa09b3d5SMarkus Armbruster
qmp_query_stats(StatsFilter * filter,Error ** errp)82aa09b3d5SMarkus Armbruster StatsResultList *qmp_query_stats(StatsFilter *filter, Error **errp)
83aa09b3d5SMarkus Armbruster {
84aa09b3d5SMarkus Armbruster StatsResultList *stats_results = NULL;
85aa09b3d5SMarkus Armbruster StatsCallbacks *entry;
86aa09b3d5SMarkus Armbruster StatsRequestList *request;
87aa09b3d5SMarkus Armbruster
88aa09b3d5SMarkus Armbruster QTAILQ_FOREACH(entry, &stats_callbacks, next) {
89aa09b3d5SMarkus Armbruster if (filter->has_providers) {
90aa09b3d5SMarkus Armbruster for (request = filter->providers; request; request = request->next) {
91aa09b3d5SMarkus Armbruster if (!invoke_stats_cb(entry, &stats_results, filter,
92aa09b3d5SMarkus Armbruster request->value, errp)) {
93aa09b3d5SMarkus Armbruster break;
94aa09b3d5SMarkus Armbruster }
95aa09b3d5SMarkus Armbruster }
96aa09b3d5SMarkus Armbruster } else {
97aa09b3d5SMarkus Armbruster if (!invoke_stats_cb(entry, &stats_results, filter, NULL, errp)) {
98aa09b3d5SMarkus Armbruster break;
99aa09b3d5SMarkus Armbruster }
100aa09b3d5SMarkus Armbruster }
101aa09b3d5SMarkus Armbruster }
102aa09b3d5SMarkus Armbruster
103aa09b3d5SMarkus Armbruster return stats_results;
104aa09b3d5SMarkus Armbruster }
105aa09b3d5SMarkus Armbruster
qmp_query_stats_schemas(bool has_provider,StatsProvider provider,Error ** errp)106aa09b3d5SMarkus Armbruster StatsSchemaList *qmp_query_stats_schemas(bool has_provider,
107aa09b3d5SMarkus Armbruster StatsProvider provider,
108aa09b3d5SMarkus Armbruster Error **errp)
109aa09b3d5SMarkus Armbruster {
110aa09b3d5SMarkus Armbruster ERRP_GUARD();
111aa09b3d5SMarkus Armbruster StatsSchemaList *stats_results = NULL;
112aa09b3d5SMarkus Armbruster StatsCallbacks *entry;
113aa09b3d5SMarkus Armbruster
114aa09b3d5SMarkus Armbruster QTAILQ_FOREACH(entry, &stats_callbacks, next) {
115aa09b3d5SMarkus Armbruster if (!has_provider || provider == entry->provider) {
116aa09b3d5SMarkus Armbruster entry->schemas_cb(&stats_results, errp);
117aa09b3d5SMarkus Armbruster if (*errp) {
118aa09b3d5SMarkus Armbruster qapi_free_StatsSchemaList(stats_results);
119aa09b3d5SMarkus Armbruster return NULL;
120aa09b3d5SMarkus Armbruster }
121aa09b3d5SMarkus Armbruster }
122aa09b3d5SMarkus Armbruster }
123aa09b3d5SMarkus Armbruster
124aa09b3d5SMarkus Armbruster return stats_results;
125aa09b3d5SMarkus Armbruster }
126aa09b3d5SMarkus Armbruster
add_stats_entry(StatsResultList ** stats_results,StatsProvider provider,const char * qom_path,StatsList * stats_list)127aa09b3d5SMarkus Armbruster void add_stats_entry(StatsResultList **stats_results, StatsProvider provider,
128aa09b3d5SMarkus Armbruster const char *qom_path, StatsList *stats_list)
129aa09b3d5SMarkus Armbruster {
130aa09b3d5SMarkus Armbruster StatsResult *entry = g_new0(StatsResult, 1);
131aa09b3d5SMarkus Armbruster
132aa09b3d5SMarkus Armbruster entry->provider = provider;
133aa09b3d5SMarkus Armbruster entry->qom_path = g_strdup(qom_path);
134aa09b3d5SMarkus Armbruster entry->stats = stats_list;
135aa09b3d5SMarkus Armbruster
136aa09b3d5SMarkus Armbruster QAPI_LIST_PREPEND(*stats_results, entry);
137aa09b3d5SMarkus Armbruster }
138aa09b3d5SMarkus Armbruster
add_stats_schema(StatsSchemaList ** schema_results,StatsProvider provider,StatsTarget target,StatsSchemaValueList * stats_list)139aa09b3d5SMarkus Armbruster void add_stats_schema(StatsSchemaList **schema_results,
140aa09b3d5SMarkus Armbruster StatsProvider provider, StatsTarget target,
141aa09b3d5SMarkus Armbruster StatsSchemaValueList *stats_list)
142aa09b3d5SMarkus Armbruster {
143aa09b3d5SMarkus Armbruster StatsSchema *entry = g_new0(StatsSchema, 1);
144aa09b3d5SMarkus Armbruster
145aa09b3d5SMarkus Armbruster entry->provider = provider;
146aa09b3d5SMarkus Armbruster entry->target = target;
147aa09b3d5SMarkus Armbruster entry->stats = stats_list;
148aa09b3d5SMarkus Armbruster QAPI_LIST_PREPEND(*schema_results, entry);
149aa09b3d5SMarkus Armbruster }
150aa09b3d5SMarkus Armbruster
apply_str_list_filter(const char * string,strList * list)151aa09b3d5SMarkus Armbruster bool apply_str_list_filter(const char *string, strList *list)
152aa09b3d5SMarkus Armbruster {
153aa09b3d5SMarkus Armbruster strList *str_list = NULL;
154aa09b3d5SMarkus Armbruster
155aa09b3d5SMarkus Armbruster if (!list) {
156aa09b3d5SMarkus Armbruster return true;
157aa09b3d5SMarkus Armbruster }
158aa09b3d5SMarkus Armbruster for (str_list = list; str_list; str_list = str_list->next) {
159aa09b3d5SMarkus Armbruster if (g_str_equal(string, str_list->value)) {
160aa09b3d5SMarkus Armbruster return true;
161aa09b3d5SMarkus Armbruster }
162aa09b3d5SMarkus Armbruster }
163aa09b3d5SMarkus Armbruster return false;
164aa09b3d5SMarkus Armbruster }
165