xref: /qemu/stats/stats-qmp-cmds.c (revision f2b90109)
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;
67f2b90109Szhenwei pi     case STATS_TARGET_CRYPTODEV:
68f2b90109Szhenwei 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