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