Related: https://gitlab.com/libvirt/libvirt/-/issues/276 This patch uses qemuMonitorQueryStats to query "halt_poll_success_ns" and "halt_poll_fail_ns" for every vCPU. The respective values for each vCPU are then added together. Signed-off-by: Amneesh Singh <natto@xxxxxxxxxxxxx> --- src/qemu/qemu_driver.c | 48 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 3b5c3db6..0a2be6d3 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -18057,10 +18057,50 @@ qemuDomainGetStatsCpuHaltPollTime(virDomainObj *dom, { unsigned long long haltPollSuccess = 0; unsigned long long haltPollFail = 0; - pid_t pid = dom->pid; + qemuDomainObjPrivate *priv = dom->privateData; + bool canQueryStats = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_QUERY_STATS); - if (virHostCPUGetHaltPollTime(pid, &haltPollSuccess, &haltPollFail) < 0) - return 0; + if (!canQueryStats) { + pid_t pid = dom->pid; + + if (virHostCPUGetHaltPollTime(pid, &haltPollSuccess, &haltPollFail) < 0) + return 0; + } else { + size_t i; + qemuMonitorQueryStatsTargetType target = QEMU_MONITOR_QUERY_STATS_TARGET_VCPU; + qemuMonitorQueryStatsProvider *provider = NULL; + g_autoptr(GPtrArray) providers = NULL; + g_autoptr(GPtrArray) queried_stats = NULL; + const char *success_str = "halt_poll_success_ns"; + const char *fail_str = "halt_poll_fail_ns"; + + provider = qemuMonitorQueryStatsProviderNew(QEMU_MONITOR_QUERY_STATS_PROVIDER_KVM); + provider->names = g_new0(char *, 3); + provider->names[0] = g_strdup(success_str), provider->names[1] = g_strdup(fail_str); + + providers = g_ptr_array_new_full(1, (GDestroyNotify) qemuMonitorQueryStatsProviderFree); + g_ptr_array_add(providers, provider); + + queried_stats = qemuMonitorQueryStats(priv->mon, target, NULL, providers); + + if (!queried_stats) + return 0; + + for (i = 0; i < queried_stats->len; i++) { + unsigned long long curHaltPollSuccess, curHaltPollFail; + GHashTable *cur_table = queried_stats->pdata[i]; + virJSONValue *success, *fail; + + success = g_hash_table_lookup(cur_table, success_str); + fail = g_hash_table_lookup(cur_table, fail_str); + + ignore_value(virJSONValueGetNumberUlong(success, &curHaltPollSuccess)); + ignore_value(virJSONValueGetNumberUlong(fail, &curHaltPollFail)); + + haltPollSuccess += curHaltPollSuccess; + haltPollFail += curHaltPollFail; + } + } if (virTypedParamListAddULLong(params, haltPollSuccess, "cpu.haltpoll.success.time") < 0 || virTypedParamListAddULLong(params, haltPollFail, "cpu.haltpoll.fail.time") < 0) @@ -18915,7 +18955,7 @@ static virQEMUCapsFlags queryDirtyRateRequired[] = { static struct qemuDomainGetStatsWorker qemuDomainGetStatsWorkers[] = { { qemuDomainGetStatsState, VIR_DOMAIN_STATS_STATE, false, NULL }, - { qemuDomainGetStatsCpu, VIR_DOMAIN_STATS_CPU_TOTAL, false, NULL }, + { qemuDomainGetStatsCpu, VIR_DOMAIN_STATS_CPU_TOTAL, true, NULL }, { qemuDomainGetStatsBalloon, VIR_DOMAIN_STATS_BALLOON, true, NULL }, { qemuDomainGetStatsVcpu, VIR_DOMAIN_STATS_VCPU, true, NULL }, { qemuDomainGetStatsInterface, VIR_DOMAIN_STATS_INTERFACE, false, NULL }, -- 2.36.1