Paolo Bonzini <pbonz...@redhat.com> writes: > Introduce a simple filtering of statistics, that allows to retrieve > statistics for a subset of the guest vCPUs. This will be used for > example by the HMP monitor, in order to retrieve the statistics > for the currently selected CPU. > > Example: > { "execute": "query-stats", > "arguments": { > "target": "vcpu", > "vcpus": [ "/machine/unattached/device[2]", > "/machine/unattached/device[4]" ] } } > > Extracted from a patch by Mark Kanda. > > Signed-off-by: Paolo Bonzini <pbonz...@redhat.com> > --- > accel/kvm/kvm-all.c | 9 +++++++-- > include/monitor/stats.h | 9 ++++++++- > monitor/qmp-cmds.c | 34 +++++++++++++++++++++++++++++++++- > qapi/stats.json | 24 +++++++++++++++++++----- > 4 files changed, 67 insertions(+), 9 deletions(-) > > diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c > index 6a6bbe2994..28f8a45205 100644 > --- a/accel/kvm/kvm-all.c > +++ b/accel/kvm/kvm-all.c > @@ -2311,7 +2311,8 @@ bool kvm_dirty_ring_enabled(void) > return kvm_state->kvm_dirty_ring_size ? true : false; > } > > -static void query_stats_cb(StatsResultList **result, StatsTarget target, > Error **errp); > +static void query_stats_cb(StatsResultList **result, StatsTarget target, > + strList *targets, Error **errp); > static void query_stats_schemas_cb(StatsSchemaList **result, Error **errp); > > static int kvm_init(MachineState *ms) > @@ -4049,7 +4050,8 @@ static void query_stats_schema_vcpu(CPUState *cpu, > run_on_cpu_data data) > close(stats_fd); > } > > -static void query_stats_cb(StatsResultList **result, StatsTarget target, > Error **errp) > +static void query_stats_cb(StatsResultList **result, StatsTarget target, > + strList *targets, Error **errp) > { > KVMState *s = kvm_state; > CPUState *cpu; > @@ -4073,6 +4075,9 @@ static void query_stats_cb(StatsResultList **result, > StatsTarget target, Error * > stats_args.result.stats = result; > stats_args.errp = errp; > CPU_FOREACH(cpu) { > + if (!str_in_list(cpu->parent_obj.canonical_path, targets)) { > + continue; > + } > run_on_cpu(cpu, query_stats_vcpu, > RUN_ON_CPU_HOST_PTR(&stats_args)); > } > break; > diff --git a/include/monitor/stats.h b/include/monitor/stats.h > index 89552ab06f..92a1df3072 100644 > --- a/include/monitor/stats.h > +++ b/include/monitor/stats.h > @@ -10,7 +10,8 @@ > > #include "qapi/qapi-types-stats.h" > > -typedef void StatRetrieveFunc(StatsResultList **result, StatsTarget target, > Error **errp); > +typedef void StatRetrieveFunc(StatsResultList **result, StatsTarget target, > + strList *targets, Error **errp); > typedef void SchemaRetrieveFunc(StatsSchemaList **result, Error **errp); > > /* > @@ -30,4 +31,10 @@ void add_stats_entry(StatsResultList **, StatsProvider, > const char *id, > void add_stats_schema(StatsSchemaList **, StatsProvider, StatsTarget, > StatsSchemaValueList *); > > +/* > + * True if a string matches the filter passed to the stats_fn callabck, > + * false otherwise. > + */ > +bool str_in_list(const char *string, strList *list); > + > #endif /* STATS_H */ > diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c > index d83faeca88..1ec7409bc2 100644 > --- a/monitor/qmp-cmds.c > +++ b/monitor/qmp-cmds.c > @@ -463,13 +463,30 @@ void add_stats_callbacks(StatRetrieveFunc *stats_fn, > QTAILQ_INSERT_TAIL(&stats_callbacks, entry, next); > } > > +static strList *stats_target_filter(StatsFilter *filter) > +{ > + switch (filter->target) { > + case STATS_TARGET_VM: > + return NULL; > + case STATS_TARGET_VCPU: > + if (!filter->u.vcpu.has_vcpus) { > + return NULL; > + } > + return filter->u.vcpu.vcpus; > + break; > + default: > + abort(); > + } > +} > + > StatsResultList *qmp_query_stats(StatsFilter *filter, Error **errp) > { > StatsResultList *stats_results = NULL; > + strList *targets = stats_target_filter(filter); > StatsCallbacks *entry; > > QTAILQ_FOREACH(entry, &stats_callbacks, next) { > - entry->stats_cb(&stats_results, filter->target, errp); > + entry->stats_cb(&stats_results, filter->target, targets, errp); > } > > return stats_results; > @@ -512,3 +529,18 @@ void add_stats_schema(StatsSchemaList **schema_results, > entry->stats = stats_list; > QAPI_LIST_PREPEND(*schema_results, entry); > } > + > +bool str_in_list(const char *string, strList *list) > +{ > + strList *str_list = NULL; > + > + if (!list) { > + return true; > + } > + for (str_list = list; str_list; str_list = str_list->next) { > + if (g_str_equal(string, str_list->value)) { > + return true; > + } > + } > + return false; > +} > diff --git a/qapi/stats.json b/qapi/stats.json > index 06d2296a49..eb13377358 100644 > --- a/qapi/stats.json > +++ b/qapi/stats.json > @@ -69,15 +69,29 @@ > 'data': [ 'vm', 'vcpu' ] } > > ## > -# @StatsFilter: > +# @StatsVCPUFilter: > # > -# The arguments to the query-stats command; specifies a target for which to > -# request statistics. > +# @vcpus: list of qom paths for the desired vCPU objects.
"QOM paths", because that's how we spell it elsewhere. > # > # Since: 7.1 > ## > -{ 'struct': 'StatsFilter', > - 'data': { 'target': 'StatsTarget' } } > +{ 'struct': 'StatsVCPUFilter', > + 'data': { '*vcpus': [ 'str' ] } } > + > +## > +# @StatsFilter: > +# > +# The arguments to the query-stats command; specifies a target for which to > +# request statistics and optionally the required subset of information for > +# that target: > +# - which vCPUs to request statistics for > +# > +# Since: 7.1 > +## > +{ 'union': 'StatsFilter', > + 'base': { 'target': 'StatsTarget' }, > + 'discriminator': 'target', > + 'data': { 'vcpu': 'StatsVCPUFilter' } } > > ## > # @StatsValue: