From: Peter Krempa <pkrempa@redhat.com> The 'timed_stats' block is a set of statistics gathered in configurable time intervals. The stats include latency timings of reads/writes as well as the depth of the request queues. Signed-off-by: Peter Krempa <pkrempa@redhat.com> --- src/qemu/qemu_monitor.c | 1 + src/qemu/qemu_monitor.h | 29 ++++++++++++++++++++++++ src/qemu/qemu_monitor_json.c | 44 ++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 554898b93f..fb01335f89 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -1984,6 +1984,7 @@ qemuBlockStatsFinalize(GObject *object) return; g_free(stats->limits); + g_free(stats->timed_stats); G_OBJECT_CLASS(qemu_block_stats_parent_class)->finalize(object); } diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 9b9292e48d..a93d722418 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -806,6 +806,31 @@ struct qemuBlockStatsLimits { }; +struct qemuBlockStatsTimed { + unsigned long long interval_length; + + /* latencies are in nanoseconds */ + unsigned long long rd_latency_min; + unsigned long long rd_latency_max; + unsigned long long rd_latency_avg; + + unsigned long long wr_latency_min; + unsigned long long wr_latency_max; + unsigned long long wr_latency_avg; + + unsigned long long zone_append_latency_min; + unsigned long long zone_append_latency_max; + unsigned long long zone_append_latency_avg; + + unsigned long long flush_latency_min; + unsigned long long flush_latency_max; + unsigned long long flush_latency_avg; + + double rd_queue_depth_avg; + double wr_queue_depth_avg; + double zone_append_queue_depth_avg; +}; + struct _qemuBlockStats { GObject parent; @@ -829,6 +854,10 @@ struct _qemuBlockStats { unsigned long long write_threshold; struct qemuBlockStatsLimits *limits; + + /* block accounting/timed stats from qemu - one entry per interval configured */ + size_t n_timed_stats; + struct qemuBlockStatsTimed *timed_stats; }; G_DECLARE_FINAL_TYPE(qemuBlockStats, qemu_block_stats, QEMU, BLOCK_STATS, GObject); diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index cf63f43318..0cb20d4387 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -2386,6 +2386,45 @@ qemuMonitorJSONGetBlockInfo(qemuMonitor *mon, } +static void +qemuMonitorJSONBlockStatsCollectDataTimedOne(virJSONValue *j, + struct qemuBlockStatsTimed *s) +{ + virJSONValueObjectGetNumberUlong(j, "interval_length", &s->interval_length); + + virJSONValueObjectGetNumberUlong(j, "min_rd_latency_ns", &s->rd_latency_min); + virJSONValueObjectGetNumberUlong(j, "max_rd_latency_ns", &s->rd_latency_max); + virJSONValueObjectGetNumberUlong(j, "avg_rd_latency_ns", &s->rd_latency_avg); + + virJSONValueObjectGetNumberUlong(j, "min_wr_latency_ns", &s->wr_latency_min); + virJSONValueObjectGetNumberUlong(j, "max_wr_latency_ns", &s->wr_latency_max); + virJSONValueObjectGetNumberUlong(j, "avg_wr_latency_ns", &s->wr_latency_avg); + + virJSONValueObjectGetNumberUlong(j, "min_zone_append_latency_ns", &s->zone_append_latency_min); + virJSONValueObjectGetNumberUlong(j, "max_zone_append_latency_ns", &s->zone_append_latency_max); + virJSONValueObjectGetNumberUlong(j, "avg_zone_append_latency_ns", &s->zone_append_latency_avg); + + virJSONValueObjectGetNumberDouble(j, "avg_rd_queue_depth", &s->rd_queue_depth_avg); + virJSONValueObjectGetNumberDouble(j, "avg_wr_queue_depth", &s->wr_queue_depth_avg); + virJSONValueObjectGetNumberDouble(j, "avg_zone_append_queue_depth", &s->zone_append_queue_depth_avg); +} + + +static void +qemuMonitorJSONBlockStatsCollectDataTimed(virJSONValue *timed_stats, + qemuBlockStats *bstats) +{ + size_t i; + + bstats->n_timed_stats = virJSONValueArraySize(timed_stats); + bstats->timed_stats = g_new0(struct qemuBlockStatsTimed, bstats->n_timed_stats); + + for (i = 0; i < bstats->n_timed_stats; i++) + qemuMonitorJSONBlockStatsCollectDataTimedOne(virJSONValueArrayGet(timed_stats, i), + bstats->timed_stats + i); +} + + static qemuBlockStats * qemuMonitorJSONBlockStatsCollectData(virJSONValue *dev, int *nstats) @@ -2394,6 +2433,7 @@ qemuMonitorJSONBlockStatsCollectData(virJSONValue *dev, virJSONValue *parent; virJSONValue *parentstats; virJSONValue *stats; + virJSONValue *timed_stats; if ((stats = virJSONValueObjectGetObject(dev, "stats")) == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", @@ -2429,6 +2469,10 @@ qemuMonitorJSONBlockStatsCollectData(virJSONValue *dev, bstats->wr_highest_offset_valid = true; } + if ((timed_stats = virJSONValueObjectGetArray(stats, "timed_stats")) && + virJSONValueArraySize(timed_stats) > 0) + qemuMonitorJSONBlockStatsCollectDataTimed(timed_stats, bstats); + return g_steal_pointer(&bstats); } -- 2.51.0