qmp: add filtering of statistics by target vCPU

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.

Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini 2022-04-26 14:59:44 +02:00
parent cc01a3f4ca
commit 467ef823d8
4 changed files with 69 additions and 9 deletions

View file

@ -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)
@ -4038,7 +4039,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;
@ -4062,6 +4064,9 @@ static void query_stats_cb(StatsResultList **result, StatsTarget target, Error *
stats_args.result.stats = result;
stats_args.errp = errp;
CPU_FOREACH(cpu) {
if (!apply_str_list_filter(cpu->parent_obj.canonical_path, targets)) {
continue;
}
run_on_cpu(cpu, query_stats_vcpu, RUN_ON_CPU_HOST_PTR(&stats_args));
}
break;

View file

@ -11,7 +11,7 @@
#include "qapi/qapi-types-stats.h"
typedef void StatRetrieveFunc(StatsResultList **result, StatsTarget target,
Error **errp);
strList *targets, Error **errp);
typedef void SchemaRetrieveFunc(StatsSchemaList **result, Error **errp);
/*
@ -31,4 +31,13 @@ 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.
*
* Note that an empty list means no filtering, i.e. all strings will
* return true.
*/
bool apply_str_list_filter(const char *string, strList *list);
#endif /* STATS_H */

View file

@ -468,9 +468,26 @@ static bool invoke_stats_cb(StatsCallbacks *entry,
StatsFilter *filter,
Error **errp)
{
strList *targets = NULL;
ERRP_GUARD();
entry->stats_cb(stats_results, filter->target, errp);
switch (filter->target) {
case STATS_TARGET_VM:
break;
case STATS_TARGET_VCPU:
if (filter->u.vcpu.has_vcpus) {
if (!filter->u.vcpu.vcpus) {
/* No targets allowed? Return no statistics. */
return true;
}
targets = filter->u.vcpu.vcpus;
}
break;
default:
abort();
}
entry->stats_cb(stats_results, filter->target, targets, errp);
if (*errp) {
qapi_free_StatsResultList(*stats_results);
*stats_results = NULL;
@ -536,3 +553,18 @@ void add_stats_schema(StatsSchemaList **schema_results,
entry->stats = stats_list;
QAPI_LIST_PREPEND(*schema_results, entry);
}
bool apply_str_list_filter(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;
}

View file

@ -70,15 +70,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.
#
# 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: