|
|
9119d9 |
From 59a6145c0f1fe4e7ef35970578b8eb9837145bc0 Mon Sep 17 00:00:00 2001
|
|
|
9119d9 |
Message-Id: <59a6145c0f1fe4e7ef35970578b8eb9837145bc0@dist-git>
|
|
|
9119d9 |
From: Francesco Romani <fromani@redhat.com>
|
|
|
9119d9 |
Date: Wed, 1 Oct 2014 11:20:16 +0200
|
|
|
9119d9 |
Subject: [PATCH] qemu: bulk stats: implement block group
|
|
|
9119d9 |
|
|
|
9119d9 |
https://bugzilla.redhat.com/show_bug.cgi?id=1113116
|
|
|
9119d9 |
|
|
|
9119d9 |
This patch implements the VIR_DOMAIN_STATS_BLOCK group of statistics.
|
|
|
9119d9 |
|
|
|
9119d9 |
To do so, a helper function to get the block stats of all the disks of
|
|
|
9119d9 |
a domain is added.
|
|
|
9119d9 |
|
|
|
9119d9 |
Signed-off-by: Francesco Romani <fromani@redhat.com>
|
|
|
9119d9 |
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
|
|
|
9119d9 |
(cherry picked from commit 290e3c6b07a273444f681de198d2416ccd2d4702)
|
|
|
9119d9 |
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
9119d9 |
---
|
|
|
9119d9 |
include/libvirt/libvirt.h.in | 1 +
|
|
|
9119d9 |
src/libvirt.c | 21 +++++++
|
|
|
9119d9 |
src/qemu/qemu_driver.c | 81 ++++++++++++++++++++++++++
|
|
|
9119d9 |
src/qemu/qemu_monitor.c | 26 +++++++++
|
|
|
9119d9 |
src/qemu/qemu_monitor.h | 20 +++++++
|
|
|
9119d9 |
src/qemu/qemu_monitor_json.c | 136 +++++++++++++++++++++++++++++--------------
|
|
|
9119d9 |
src/qemu/qemu_monitor_json.h | 4 ++
|
|
|
9119d9 |
7 files changed, 246 insertions(+), 43 deletions(-)
|
|
|
9119d9 |
|
|
|
9119d9 |
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
|
|
|
9119d9 |
index 72aa47d..60b3e0b 100644
|
|
|
9119d9 |
--- a/include/libvirt/libvirt.h.in
|
|
|
9119d9 |
+++ b/include/libvirt/libvirt.h.in
|
|
|
9119d9 |
@@ -2518,6 +2518,7 @@ typedef enum {
|
|
|
9119d9 |
VIR_DOMAIN_STATS_BALLOON = (1 << 2), /* return domain balloon info */
|
|
|
9119d9 |
VIR_DOMAIN_STATS_VCPU = (1 << 3), /* return domain virtual CPU info */
|
|
|
9119d9 |
VIR_DOMAIN_STATS_INTERFACE = (1 << 4), /* return domain interfaces info */
|
|
|
9119d9 |
+ VIR_DOMAIN_STATS_BLOCK = (1 << 5), /* return domain block info */
|
|
|
9119d9 |
} virDomainStatsTypes;
|
|
|
9119d9 |
|
|
|
9119d9 |
typedef enum {
|
|
|
9119d9 |
diff --git a/src/libvirt.c b/src/libvirt.c
|
|
|
9119d9 |
index 46d3e22..f62ecf7 100644
|
|
|
9119d9 |
--- a/src/libvirt.c
|
|
|
9119d9 |
+++ b/src/libvirt.c
|
|
|
9119d9 |
@@ -21595,6 +21595,27 @@ virConnectGetDomainCapabilities(virConnectPtr conn,
|
|
|
9119d9 |
* "net.<num>.tx.errs" - transmission errors as unsigned long long.
|
|
|
9119d9 |
* "net.<num>.tx.drop" - transmit packets dropped as unsigned long long.
|
|
|
9119d9 |
*
|
|
|
9119d9 |
+ * VIR_DOMAIN_STATS_BLOCK: Return block devices statistics.
|
|
|
9119d9 |
+ * The typed parameter keys are in this format:
|
|
|
9119d9 |
+ * "block.count" - number of block devices on this domain
|
|
|
9119d9 |
+ * as unsigned int.
|
|
|
9119d9 |
+ * "block.<num>.name" - name of the block device <num> as string.
|
|
|
9119d9 |
+ * matches the target name (vda/sda/hda) of the
|
|
|
9119d9 |
+ * block device.
|
|
|
9119d9 |
+ * "block.<num>.rd.reqs" - number of read requests as unsigned long long.
|
|
|
9119d9 |
+ * "block.<num>.rd.bytes" - number of read bytes as unsigned long long.
|
|
|
9119d9 |
+ * "block.<num>.rd.times" - total time (ns) spent on reads as
|
|
|
9119d9 |
+ * unsigned long long.
|
|
|
9119d9 |
+ * "block.<num>.wr.reqs" - number of write requests as unsigned long long.
|
|
|
9119d9 |
+ * "block.<num>.wr.bytes" - number of written bytes as unsigned long long.
|
|
|
9119d9 |
+ * "block.<num>.wr.times" - total time (ns) spent on writes as
|
|
|
9119d9 |
+ * unsigned long long.
|
|
|
9119d9 |
+ * "block.<num>.fl.reqs" - total flush requests as unsigned long long.
|
|
|
9119d9 |
+ * "block.<num>.fl.times" - total time (ns) spent on cache flushing as
|
|
|
9119d9 |
+ * unsigned long long.
|
|
|
9119d9 |
+ * "block.<num>.errors" - Xen only: the 'oo_req' value as
|
|
|
9119d9 |
+ * unsigned long long.
|
|
|
9119d9 |
+ *
|
|
|
9119d9 |
* Using 0 for @stats returns all stats groups supported by the given
|
|
|
9119d9 |
* hypervisor.
|
|
|
9119d9 |
*
|
|
|
9119d9 |
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
|
|
|
9119d9 |
index 3a46c6d..8e90cc6 100644
|
|
|
9119d9 |
--- a/src/qemu/qemu_driver.c
|
|
|
9119d9 |
+++ b/src/qemu/qemu_driver.c
|
|
|
9119d9 |
@@ -9866,6 +9866,7 @@ qemuDomainBlockStats(virDomainPtr dom,
|
|
|
9119d9 |
return ret;
|
|
|
9119d9 |
}
|
|
|
9119d9 |
|
|
|
9119d9 |
+
|
|
|
9119d9 |
static int
|
|
|
9119d9 |
qemuDomainBlockStatsFlags(virDomainPtr dom,
|
|
|
9119d9 |
const char *path,
|
|
|
9119d9 |
@@ -17690,6 +17691,85 @@ qemuDomainGetStatsInterface(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
|
|
|
9119d9 |
|
|
|
9119d9 |
#undef QEMU_ADD_NET_PARAM
|
|
|
9119d9 |
|
|
|
9119d9 |
+/* expects a LL, but typed parameter must be ULL */
|
|
|
9119d9 |
+#define QEMU_ADD_BLOCK_PARAM_LL(record, maxparams, num, name, value) \
|
|
|
9119d9 |
+do { \
|
|
|
9119d9 |
+ char param_name[VIR_TYPED_PARAM_FIELD_LENGTH]; \
|
|
|
9119d9 |
+ snprintf(param_name, VIR_TYPED_PARAM_FIELD_LENGTH, \
|
|
|
9119d9 |
+ "block.%zu.%s", num, name); \
|
|
|
9119d9 |
+ if (value >= 0 && virTypedParamsAddULLong(&(record)->params, \
|
|
|
9119d9 |
+ &(record)->nparams, \
|
|
|
9119d9 |
+ maxparams, \
|
|
|
9119d9 |
+ param_name, \
|
|
|
9119d9 |
+ value) < 0) \
|
|
|
9119d9 |
+ goto cleanup; \
|
|
|
9119d9 |
+} while (0)
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+static int
|
|
|
9119d9 |
+qemuDomainGetStatsBlock(virQEMUDriverPtr driver,
|
|
|
9119d9 |
+ virDomainObjPtr dom,
|
|
|
9119d9 |
+ virDomainStatsRecordPtr record,
|
|
|
9119d9 |
+ int *maxparams,
|
|
|
9119d9 |
+ unsigned int privflags)
|
|
|
9119d9 |
+{
|
|
|
9119d9 |
+ size_t i;
|
|
|
9119d9 |
+ int ret = -1;
|
|
|
9119d9 |
+ int nstats = dom->def->ndisks;
|
|
|
9119d9 |
+ qemuBlockStatsPtr stats = NULL;
|
|
|
9119d9 |
+ qemuDomainObjPrivatePtr priv = dom->privateData;
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ if (!HAVE_JOB(privflags) || !virDomainObjIsActive(dom))
|
|
|
9119d9 |
+ return 0; /* it's ok, just go ahead silently */
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ if (VIR_ALLOC_N(stats, nstats) < 0)
|
|
|
9119d9 |
+ return -1;
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ qemuDomainObjEnterMonitor(driver, dom);
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ nstats = qemuMonitorGetAllBlockStatsInfo(priv->mon, NULL,
|
|
|
9119d9 |
+ stats, nstats);
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ qemuDomainObjExitMonitor(driver, dom);
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ if (nstats < 0) {
|
|
|
9119d9 |
+ virResetLastError();
|
|
|
9119d9 |
+ ret = 0; /* still ok, again go ahead silently */
|
|
|
9119d9 |
+ goto cleanup;
|
|
|
9119d9 |
+ }
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ QEMU_ADD_COUNT_PARAM(record, maxparams, "block", dom->def->ndisks);
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ for (i = 0; i < nstats; i++) {
|
|
|
9119d9 |
+ QEMU_ADD_NAME_PARAM(record, maxparams,
|
|
|
9119d9 |
+ "block", i, dom->def->disks[i]->dst);
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ QEMU_ADD_BLOCK_PARAM_LL(record, maxparams, i,
|
|
|
9119d9 |
+ "rd.reqs", stats[i].rd_req);
|
|
|
9119d9 |
+ QEMU_ADD_BLOCK_PARAM_LL(record, maxparams, i,
|
|
|
9119d9 |
+ "rd.bytes", stats[i].rd_bytes);
|
|
|
9119d9 |
+ QEMU_ADD_BLOCK_PARAM_LL(record, maxparams, i,
|
|
|
9119d9 |
+ "rd.times", stats[i].rd_total_times);
|
|
|
9119d9 |
+ QEMU_ADD_BLOCK_PARAM_LL(record, maxparams, i,
|
|
|
9119d9 |
+ "wr.reqs", stats[i].wr_req);
|
|
|
9119d9 |
+ QEMU_ADD_BLOCK_PARAM_LL(record, maxparams, i,
|
|
|
9119d9 |
+ "wr.bytes", stats[i].wr_bytes);
|
|
|
9119d9 |
+ QEMU_ADD_BLOCK_PARAM_LL(record, maxparams, i,
|
|
|
9119d9 |
+ "wr.times", stats[i].wr_total_times);
|
|
|
9119d9 |
+ QEMU_ADD_BLOCK_PARAM_LL(record, maxparams, i,
|
|
|
9119d9 |
+ "fl.reqs", stats[i].flush_req);
|
|
|
9119d9 |
+ QEMU_ADD_BLOCK_PARAM_LL(record, maxparams, i,
|
|
|
9119d9 |
+ "fl.times", stats[i].flush_total_times);
|
|
|
9119d9 |
+ }
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ ret = 0;
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ cleanup:
|
|
|
9119d9 |
+ VIR_FREE(stats);
|
|
|
9119d9 |
+ return ret;
|
|
|
9119d9 |
+}
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+#undef QEMU_ADD_BLOCK_PARAM_LL
|
|
|
9119d9 |
+
|
|
|
9119d9 |
#undef QEMU_ADD_NAME_PARAM
|
|
|
9119d9 |
|
|
|
9119d9 |
#undef QEMU_ADD_COUNT_PARAM
|
|
|
9119d9 |
@@ -17713,6 +17793,7 @@ static struct qemuDomainGetStatsWorker qemuDomainGetStatsWorkers[] = {
|
|
|
9119d9 |
{ qemuDomainGetStatsBalloon, VIR_DOMAIN_STATS_BALLOON, true },
|
|
|
9119d9 |
{ qemuDomainGetStatsVcpu, VIR_DOMAIN_STATS_VCPU, false },
|
|
|
9119d9 |
{ qemuDomainGetStatsInterface, VIR_DOMAIN_STATS_INTERFACE, false },
|
|
|
9119d9 |
+ { qemuDomainGetStatsBlock, VIR_DOMAIN_STATS_BLOCK, true },
|
|
|
9119d9 |
{ NULL, 0, false }
|
|
|
9119d9 |
};
|
|
|
9119d9 |
|
|
|
9119d9 |
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
|
|
|
9119d9 |
index fea551d..afe7959 100644
|
|
|
9119d9 |
--- a/src/qemu/qemu_monitor.c
|
|
|
9119d9 |
+++ b/src/qemu/qemu_monitor.c
|
|
|
9119d9 |
@@ -1760,6 +1760,32 @@ int qemuMonitorGetBlockStatsInfo(qemuMonitorPtr mon,
|
|
|
9119d9 |
return ret;
|
|
|
9119d9 |
}
|
|
|
9119d9 |
|
|
|
9119d9 |
+/* Fills the first 'nstats' block stats. 'stats' must be an array.
|
|
|
9119d9 |
+ * Returns <0 on error, otherwise the number of block stats retrieved.
|
|
|
9119d9 |
+ * if 'dev_name' is != NULL, look for this device only and skip
|
|
|
9119d9 |
+ * any other. In that case return value cannot be greater than 1.
|
|
|
9119d9 |
+ */
|
|
|
9119d9 |
+int
|
|
|
9119d9 |
+qemuMonitorGetAllBlockStatsInfo(qemuMonitorPtr mon,
|
|
|
9119d9 |
+ const char *dev_name,
|
|
|
9119d9 |
+ qemuBlockStatsPtr stats,
|
|
|
9119d9 |
+ int nstats)
|
|
|
9119d9 |
+{
|
|
|
9119d9 |
+ int ret;
|
|
|
9119d9 |
+ VIR_DEBUG("mon=%p dev=%s", mon, dev_name);
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ if (mon->json) {
|
|
|
9119d9 |
+ ret = qemuMonitorJSONGetAllBlockStatsInfo(mon, dev_name,
|
|
|
9119d9 |
+ stats, nstats);
|
|
|
9119d9 |
+ } else {
|
|
|
9119d9 |
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
9119d9 |
+ _("unable to query all block stats with this QEMU"));
|
|
|
9119d9 |
+ return -1;
|
|
|
9119d9 |
+ }
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ return ret;
|
|
|
9119d9 |
+}
|
|
|
9119d9 |
+
|
|
|
9119d9 |
/* Return 0 and update @nparams with the number of block stats
|
|
|
9119d9 |
* QEMU supports if success. Return -1 if failure.
|
|
|
9119d9 |
*/
|
|
|
9119d9 |
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
|
|
|
9119d9 |
index 62c9f2e..b7f9fd1 100644
|
|
|
9119d9 |
--- a/src/qemu/qemu_monitor.h
|
|
|
9119d9 |
+++ b/src/qemu/qemu_monitor.h
|
|
|
9119d9 |
@@ -346,6 +346,26 @@ int qemuMonitorGetBlockStatsInfo(qemuMonitorPtr mon,
|
|
|
9119d9 |
long long *flush_req,
|
|
|
9119d9 |
long long *flush_total_times,
|
|
|
9119d9 |
long long *errs);
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+typedef struct _qemuBlockStats qemuBlockStats;
|
|
|
9119d9 |
+typedef qemuBlockStats *qemuBlockStatsPtr;
|
|
|
9119d9 |
+struct _qemuBlockStats {
|
|
|
9119d9 |
+ long long rd_req;
|
|
|
9119d9 |
+ long long rd_bytes;
|
|
|
9119d9 |
+ long long wr_req;
|
|
|
9119d9 |
+ long long wr_bytes;
|
|
|
9119d9 |
+ long long rd_total_times;
|
|
|
9119d9 |
+ long long wr_total_times;
|
|
|
9119d9 |
+ long long flush_req;
|
|
|
9119d9 |
+ long long flush_total_times;
|
|
|
9119d9 |
+};
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+int qemuMonitorGetAllBlockStatsInfo(qemuMonitorPtr mon,
|
|
|
9119d9 |
+ const char *dev_name,
|
|
|
9119d9 |
+ qemuBlockStatsPtr stats,
|
|
|
9119d9 |
+ int nstats)
|
|
|
9119d9 |
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3);
|
|
|
9119d9 |
+
|
|
|
9119d9 |
int qemuMonitorGetBlockStatsParamsNumber(qemuMonitorPtr mon,
|
|
|
9119d9 |
int *nparams);
|
|
|
9119d9 |
|
|
|
9119d9 |
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
|
|
|
9119d9 |
index 17b082c..c013d49 100644
|
|
|
9119d9 |
--- a/src/qemu/qemu_monitor_json.c
|
|
|
9119d9 |
+++ b/src/qemu/qemu_monitor_json.c
|
|
|
9119d9 |
@@ -1708,13 +1708,8 @@ int qemuMonitorJSONGetBlockStatsInfo(qemuMonitorPtr mon,
|
|
|
9119d9 |
long long *flush_total_times,
|
|
|
9119d9 |
long long *errs)
|
|
|
9119d9 |
{
|
|
|
9119d9 |
- int ret;
|
|
|
9119d9 |
- size_t i;
|
|
|
9119d9 |
- bool found = false;
|
|
|
9119d9 |
- virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-blockstats",
|
|
|
9119d9 |
- NULL);
|
|
|
9119d9 |
- virJSONValuePtr reply = NULL;
|
|
|
9119d9 |
- virJSONValuePtr devices;
|
|
|
9119d9 |
+ qemuBlockStats stats;
|
|
|
9119d9 |
+ int ret = -1;
|
|
|
9119d9 |
|
|
|
9119d9 |
*rd_req = *rd_bytes = -1;
|
|
|
9119d9 |
*wr_req = *wr_bytes = *errs = -1;
|
|
|
9119d9 |
@@ -1728,9 +1723,49 @@ int qemuMonitorJSONGetBlockStatsInfo(qemuMonitorPtr mon,
|
|
|
9119d9 |
if (flush_total_times)
|
|
|
9119d9 |
*flush_total_times = -1;
|
|
|
9119d9 |
|
|
|
9119d9 |
+ if (qemuMonitorJSONGetAllBlockStatsInfo(mon, dev_name, &stats, 1) != 1)
|
|
|
9119d9 |
+ goto cleanup;
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ *rd_req = stats.rd_req;
|
|
|
9119d9 |
+ *rd_bytes = stats.rd_bytes;
|
|
|
9119d9 |
+ *wr_req = stats.wr_req;
|
|
|
9119d9 |
+ *wr_bytes = stats.wr_bytes;
|
|
|
9119d9 |
+ *errs = -1; /* QEMU does not have this */
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ if (rd_total_times)
|
|
|
9119d9 |
+ *rd_total_times = stats.rd_total_times;
|
|
|
9119d9 |
+ if (wr_total_times)
|
|
|
9119d9 |
+ *wr_total_times = stats.wr_total_times;
|
|
|
9119d9 |
+ if (flush_req)
|
|
|
9119d9 |
+ *flush_req = stats.flush_req;
|
|
|
9119d9 |
+ if (flush_total_times)
|
|
|
9119d9 |
+ *flush_total_times = stats.flush_total_times;
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ ret = 0;
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ cleanup:
|
|
|
9119d9 |
+ return ret;
|
|
|
9119d9 |
+}
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+int qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitorPtr mon,
|
|
|
9119d9 |
+ const char *dev_name,
|
|
|
9119d9 |
+ qemuBlockStatsPtr bstats,
|
|
|
9119d9 |
+ int nstats)
|
|
|
9119d9 |
+{
|
|
|
9119d9 |
+ int ret, count;
|
|
|
9119d9 |
+ size_t i;
|
|
|
9119d9 |
+ virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-blockstats",
|
|
|
9119d9 |
+ NULL);
|
|
|
9119d9 |
+ virJSONValuePtr reply = NULL;
|
|
|
9119d9 |
+ virJSONValuePtr devices;
|
|
|
9119d9 |
+
|
|
|
9119d9 |
if (!cmd)
|
|
|
9119d9 |
return -1;
|
|
|
9119d9 |
|
|
|
9119d9 |
+ if (!bstats || nstats <= 0)
|
|
|
9119d9 |
+ return -1;
|
|
|
9119d9 |
+
|
|
|
9119d9 |
ret = qemuMonitorJSONCommand(mon, cmd, &reply);
|
|
|
9119d9 |
|
|
|
9119d9 |
if (ret == 0)
|
|
|
9119d9 |
@@ -1746,108 +1781,123 @@ int qemuMonitorJSONGetBlockStatsInfo(qemuMonitorPtr mon,
|
|
|
9119d9 |
goto cleanup;
|
|
|
9119d9 |
}
|
|
|
9119d9 |
|
|
|
9119d9 |
- for (i = 0; i < virJSONValueArraySize(devices); i++) {
|
|
|
9119d9 |
+ count = 0;
|
|
|
9119d9 |
+ for (i = 0; i < virJSONValueArraySize(devices) && count < nstats; i++) {
|
|
|
9119d9 |
virJSONValuePtr dev = virJSONValueArrayGet(devices, i);
|
|
|
9119d9 |
virJSONValuePtr stats;
|
|
|
9119d9 |
- const char *thisdev;
|
|
|
9119d9 |
if (!dev || dev->type != VIR_JSON_TYPE_OBJECT) {
|
|
|
9119d9 |
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
9119d9 |
- _("blockstats device entry was not in expected format"));
|
|
|
9119d9 |
+ _("blockstats device entry was not "
|
|
|
9119d9 |
+ "in expected format"));
|
|
|
9119d9 |
goto cleanup;
|
|
|
9119d9 |
}
|
|
|
9119d9 |
|
|
|
9119d9 |
- if ((thisdev = virJSONValueObjectGetString(dev, "device")) == NULL) {
|
|
|
9119d9 |
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
9119d9 |
- _("blockstats device entry was not in expected format"));
|
|
|
9119d9 |
- goto cleanup;
|
|
|
9119d9 |
- }
|
|
|
9119d9 |
-
|
|
|
9119d9 |
- /* New QEMU has separate names for host & guest side of the disk
|
|
|
9119d9 |
- * and libvirt gives the host side a 'drive-' prefix. The passed
|
|
|
9119d9 |
- * in dev_name is the guest side though
|
|
|
9119d9 |
+ /* If dev_name is specified, we are looking for a specific device,
|
|
|
9119d9 |
+ * so we must be stricter.
|
|
|
9119d9 |
*/
|
|
|
9119d9 |
- if (STRPREFIX(thisdev, QEMU_DRIVE_HOST_PREFIX))
|
|
|
9119d9 |
- thisdev += strlen(QEMU_DRIVE_HOST_PREFIX);
|
|
|
9119d9 |
+ if (dev_name) {
|
|
|
9119d9 |
+ const char *thisdev = virJSONValueObjectGetString(dev, "device");
|
|
|
9119d9 |
+ if (!thisdev) {
|
|
|
9119d9 |
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
9119d9 |
+ _("blockstats device entry was not "
|
|
|
9119d9 |
+ "in expected format"));
|
|
|
9119d9 |
+ goto cleanup;
|
|
|
9119d9 |
+ }
|
|
|
9119d9 |
|
|
|
9119d9 |
- if (STRNEQ(thisdev, dev_name))
|
|
|
9119d9 |
- continue;
|
|
|
9119d9 |
+ /* New QEMU has separate names for host & guest side of the disk
|
|
|
9119d9 |
+ * and libvirt gives the host side a 'drive-' prefix. The passed
|
|
|
9119d9 |
+ * in dev_name is the guest side though
|
|
|
9119d9 |
+ */
|
|
|
9119d9 |
+ if (STRPREFIX(thisdev, QEMU_DRIVE_HOST_PREFIX))
|
|
|
9119d9 |
+ thisdev += strlen(QEMU_DRIVE_HOST_PREFIX);
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ if (STRNEQ(thisdev, dev_name))
|
|
|
9119d9 |
+ continue;
|
|
|
9119d9 |
+ }
|
|
|
9119d9 |
|
|
|
9119d9 |
- found = true;
|
|
|
9119d9 |
if ((stats = virJSONValueObjectGet(dev, "stats")) == NULL ||
|
|
|
9119d9 |
stats->type != VIR_JSON_TYPE_OBJECT) {
|
|
|
9119d9 |
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
9119d9 |
- _("blockstats stats entry was not in expected format"));
|
|
|
9119d9 |
+ _("blockstats stats entry was not "
|
|
|
9119d9 |
+ "in expected format"));
|
|
|
9119d9 |
goto cleanup;
|
|
|
9119d9 |
}
|
|
|
9119d9 |
|
|
|
9119d9 |
- if (virJSONValueObjectGetNumberLong(stats, "rd_bytes", rd_bytes) < 0) {
|
|
|
9119d9 |
+ if (virJSONValueObjectGetNumberLong(stats, "rd_bytes",
|
|
|
9119d9 |
+ &bstats->rd_bytes) < 0) {
|
|
|
9119d9 |
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
9119d9 |
_("cannot read %s statistic"),
|
|
|
9119d9 |
"rd_bytes");
|
|
|
9119d9 |
goto cleanup;
|
|
|
9119d9 |
}
|
|
|
9119d9 |
- if (virJSONValueObjectGetNumberLong(stats, "rd_operations", rd_req) < 0) {
|
|
|
9119d9 |
+ if (virJSONValueObjectGetNumberLong(stats, "rd_operations",
|
|
|
9119d9 |
+ &bstats->rd_req) < 0) {
|
|
|
9119d9 |
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
9119d9 |
_("cannot read %s statistic"),
|
|
|
9119d9 |
"rd_operations");
|
|
|
9119d9 |
goto cleanup;
|
|
|
9119d9 |
}
|
|
|
9119d9 |
- if (rd_total_times &&
|
|
|
9119d9 |
- virJSONValueObjectHasKey(stats, "rd_total_time_ns") &&
|
|
|
9119d9 |
+ if (virJSONValueObjectHasKey(stats, "rd_total_time_ns") &&
|
|
|
9119d9 |
(virJSONValueObjectGetNumberLong(stats, "rd_total_time_ns",
|
|
|
9119d9 |
- rd_total_times) < 0)) {
|
|
|
9119d9 |
+ &bstats->rd_total_times) < 0)) {
|
|
|
9119d9 |
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
9119d9 |
_("cannot read %s statistic"),
|
|
|
9119d9 |
"rd_total_time_ns");
|
|
|
9119d9 |
goto cleanup;
|
|
|
9119d9 |
}
|
|
|
9119d9 |
- if (virJSONValueObjectGetNumberLong(stats, "wr_bytes", wr_bytes) < 0) {
|
|
|
9119d9 |
+ if (virJSONValueObjectGetNumberLong(stats, "wr_bytes",
|
|
|
9119d9 |
+ &bstats->wr_bytes) < 0) {
|
|
|
9119d9 |
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
9119d9 |
_("cannot read %s statistic"),
|
|
|
9119d9 |
"wr_bytes");
|
|
|
9119d9 |
goto cleanup;
|
|
|
9119d9 |
}
|
|
|
9119d9 |
- if (virJSONValueObjectGetNumberLong(stats, "wr_operations", wr_req) < 0) {
|
|
|
9119d9 |
+ if (virJSONValueObjectGetNumberLong(stats, "wr_operations",
|
|
|
9119d9 |
+ &bstats->wr_req) < 0) {
|
|
|
9119d9 |
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
9119d9 |
_("cannot read %s statistic"),
|
|
|
9119d9 |
"wr_operations");
|
|
|
9119d9 |
goto cleanup;
|
|
|
9119d9 |
}
|
|
|
9119d9 |
- if (wr_total_times &&
|
|
|
9119d9 |
- virJSONValueObjectHasKey(stats, "wr_total_time_ns") &&
|
|
|
9119d9 |
+ if (virJSONValueObjectHasKey(stats, "wr_total_time_ns") &&
|
|
|
9119d9 |
(virJSONValueObjectGetNumberLong(stats, "wr_total_time_ns",
|
|
|
9119d9 |
- wr_total_times) < 0)) {
|
|
|
9119d9 |
+ &bstats->wr_total_times) < 0)) {
|
|
|
9119d9 |
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
9119d9 |
_("cannot read %s statistic"),
|
|
|
9119d9 |
"wr_total_time_ns");
|
|
|
9119d9 |
goto cleanup;
|
|
|
9119d9 |
}
|
|
|
9119d9 |
- if (flush_req &&
|
|
|
9119d9 |
- virJSONValueObjectHasKey(stats, "flush_operations") &&
|
|
|
9119d9 |
+ if (virJSONValueObjectHasKey(stats, "flush_operations") &&
|
|
|
9119d9 |
(virJSONValueObjectGetNumberLong(stats, "flush_operations",
|
|
|
9119d9 |
- flush_req) < 0)) {
|
|
|
9119d9 |
+ &bstats->flush_req) < 0)) {
|
|
|
9119d9 |
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
9119d9 |
_("cannot read %s statistic"),
|
|
|
9119d9 |
"flush_operations");
|
|
|
9119d9 |
goto cleanup;
|
|
|
9119d9 |
}
|
|
|
9119d9 |
- if (flush_total_times &&
|
|
|
9119d9 |
- virJSONValueObjectHasKey(stats, "flush_total_time_ns") &&
|
|
|
9119d9 |
+ if (virJSONValueObjectHasKey(stats, "flush_total_time_ns") &&
|
|
|
9119d9 |
(virJSONValueObjectGetNumberLong(stats, "flush_total_time_ns",
|
|
|
9119d9 |
- flush_total_times) < 0)) {
|
|
|
9119d9 |
+ &bstats->flush_total_times) < 0)) {
|
|
|
9119d9 |
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
9119d9 |
_("cannot read %s statistic"),
|
|
|
9119d9 |
"flush_total_time_ns");
|
|
|
9119d9 |
goto cleanup;
|
|
|
9119d9 |
}
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ count++;
|
|
|
9119d9 |
+ bstats++;
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ if (dev_name && count)
|
|
|
9119d9 |
+ break;
|
|
|
9119d9 |
}
|
|
|
9119d9 |
|
|
|
9119d9 |
- if (!found) {
|
|
|
9119d9 |
+ if (dev_name && !count) {
|
|
|
9119d9 |
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
9119d9 |
_("cannot find statistics for device '%s'"), dev_name);
|
|
|
9119d9 |
goto cleanup;
|
|
|
9119d9 |
}
|
|
|
9119d9 |
- ret = 0;
|
|
|
9119d9 |
+
|
|
|
9119d9 |
+ ret = count;
|
|
|
9119d9 |
|
|
|
9119d9 |
cleanup:
|
|
|
9119d9 |
virJSONValueFree(cmd);
|
|
|
9119d9 |
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
|
|
|
9119d9 |
index c4e795c..2402b5a 100644
|
|
|
9119d9 |
--- a/src/qemu/qemu_monitor_json.h
|
|
|
9119d9 |
+++ b/src/qemu/qemu_monitor_json.h
|
|
|
9119d9 |
@@ -79,6 +79,10 @@ int qemuMonitorJSONGetBlockStatsInfo(qemuMonitorPtr mon,
|
|
|
9119d9 |
long long *flush_req,
|
|
|
9119d9 |
long long *flush_total_times,
|
|
|
9119d9 |
long long *errs);
|
|
|
9119d9 |
+int qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitorPtr mon,
|
|
|
9119d9 |
+ const char *dev_name,
|
|
|
9119d9 |
+ qemuBlockStatsPtr stats,
|
|
|
9119d9 |
+ int nstats);
|
|
|
9119d9 |
int qemuMonitorJSONGetBlockStatsParamsNumber(qemuMonitorPtr mon,
|
|
|
9119d9 |
int *nparams);
|
|
|
9119d9 |
int qemuMonitorJSONGetBlockExtent(qemuMonitorPtr mon,
|
|
|
9119d9 |
--
|
|
|
9119d9 |
2.1.2
|
|
|
9119d9 |
|