From 7245a00d5adcdd74eb8a5051de2a1d52a4107ae8 Mon Sep 17 00:00:00 2001
Message-Id: <7245a00d5adcdd74eb8a5051de2a1d52a4107ae8@dist-git>
From: Eric Blake <eblake@redhat.com>
Date: Wed, 17 Dec 2014 03:09:05 -0700
Subject: [PATCH] getstats: perform recursion in monitor collection
https://bugzilla.redhat.com/show_bug.cgi?id=1041569
When requested in a later patch, the QMP command results are now
examined recursively. As qemu_driver will eventually have to
read items out of the hash table as stored by this patch, the
computation of backing alias string is done in a shared location.
* src/qemu/qemu_domain.h (qemuDomainStorageAlias): New prototype.
* src/qemu/qemu_domain.c (qemuDomainStorageAlias): Implement it.
* src/qemu/qemu_monitor_json.c
(qemuMonitorJSONGetOneBlockStatsInfo)
(qemuMonitorJSONBlockStatsUpdateCapacityOne): Perform recursion.
(qemuMonitorJSONGetAllBlockStatsInfo)
(qemuMonitorJSONBlockStatsUpdateCapacity): Update callers.
Signed-off-by: Eric Blake <eblake@redhat.com>
(cherry picked from commit b1802714dab51bd5f0214a4d93a2c0b635bc5f14)
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
src/qemu/qemu_domain.c | 16 +++++++++++++++
src/qemu/qemu_domain.h | 1 +
src/qemu/qemu_monitor_json.c | 48 ++++++++++++++++++++++++++++++++------------
3 files changed, 52 insertions(+), 13 deletions(-)
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 01fa3ac..58fcd75 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -2707,6 +2707,22 @@ qemuDomainStorageFileInit(virQEMUDriverPtr driver,
}
+char *
+qemuDomainStorageAlias(const char *device, int depth)
+{
+ char *alias;
+
+ if (STRPREFIX(device, QEMU_DRIVE_HOST_PREFIX))
+ device += strlen(QEMU_DRIVE_HOST_PREFIX);
+
+ if (!depth)
+ ignore_value(VIR_STRDUP(alias, device));
+ else
+ ignore_value(virAsprintf(&alias, "%s.%d", device, depth));
+ return alias;
+}
+
+
int
qemuDomainDetermineDiskChain(virQEMUDriverPtr driver,
virDomainObjPtr vm,
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index ebb282a..9c94a65 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -376,6 +376,7 @@ int qemuDomainDetermineDiskChain(virQEMUDriverPtr driver,
int qemuDomainStorageFileInit(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virStorageSourcePtr src);
+char *qemuDomainStorageAlias(const char *device, int depth);
int qemuDomainCleanupAdd(virDomainObjPtr vm,
qemuDomainCleanupCallback cb);
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 7088409..97151dc 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -1839,13 +1839,18 @@ qemuMonitorJSONDevGetBlockExtent(virJSONValuePtr dev,
static int
qemuMonitorJSONGetOneBlockStatsInfo(virJSONValuePtr dev,
const char *dev_name,
+ int depth,
virHashTablePtr hash,
- bool backingChain ATTRIBUTE_UNUSED)
+ bool backingChain)
{
qemuBlockStatsPtr bstats = NULL;
virJSONValuePtr stats;
int ret = -1;
+ char *entry_name = qemuDomainStorageAlias(dev_name, depth);
+ virJSONValuePtr backing;
+ if (!entry_name)
+ goto cleanup;
if (VIR_ALLOC(bstats) < 0)
goto cleanup;
@@ -1921,12 +1926,20 @@ qemuMonitorJSONGetOneBlockStatsInfo(virJSONValuePtr dev,
/* it's ok to not have this information here. Just skip silently. */
qemuMonitorJSONDevGetBlockExtent(dev, &bstats->wr_highest_offset);
- if (virHashAddEntry(hash, dev_name, bstats) < 0)
+ if (virHashAddEntry(hash, entry_name, bstats) < 0)
goto cleanup;
bstats = NULL;
+
+ if (backingChain &&
+ (backing = virJSONValueObjectGet(dev, "backing")) &&
+ qemuMonitorJSONGetOneBlockStatsInfo(backing, dev_name, depth + 1,
+ hash, true) < 0)
+ goto cleanup;
+
ret = 0;
cleanup:
VIR_FREE(bstats);
+ VIR_FREE(entry_name);
return ret;
}
@@ -1981,10 +1994,7 @@ qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitorPtr mon,
goto cleanup;
}
- if (STRPREFIX(dev_name, QEMU_DRIVE_HOST_PREFIX))
- dev_name += strlen(QEMU_DRIVE_HOST_PREFIX);
-
- if (qemuMonitorJSONGetOneBlockStatsInfo(dev, dev_name, hash,
+ if (qemuMonitorJSONGetOneBlockStatsInfo(dev, dev_name, 0, hash,
backingChain) < 0)
goto cleanup;
@@ -2005,17 +2015,20 @@ qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitorPtr mon,
static int
qemuMonitorJSONBlockStatsUpdateCapacityOne(virJSONValuePtr image,
const char *dev_name,
+ int depth,
virHashTablePtr stats,
- bool backingChain ATTRIBUTE_UNUSED)
+ bool backingChain)
{
qemuBlockStatsPtr bstats;
int ret = -1;
+ char *entry_name = qemuDomainStorageAlias(dev_name, depth);
+ virJSONValuePtr backing;
- if (!(bstats = virHashLookup(stats, dev_name))) {
+ if (!(bstats = virHashLookup(stats, entry_name))) {
if (VIR_ALLOC(bstats) < 0)
goto cleanup;
- if (virHashAddEntry(stats, dev_name, bstats) < 0) {
+ if (virHashAddEntry(stats, entry_name, bstats) < 0) {
VIR_FREE(bstats);
goto cleanup;
}
@@ -2032,7 +2045,18 @@ qemuMonitorJSONBlockStatsUpdateCapacityOne(virJSONValuePtr image,
if (virJSONValueObjectGetNumberUlong(image, "actual-size",
&bstats->physical) < 0)
bstats->physical = bstats->capacity;
+
+ if (backingChain &&
+ (backing = virJSONValueObjectGet(image, "backing-image"))) {
+ ret = qemuMonitorJSONBlockStatsUpdateCapacityOne(backing,
+ dev_name,
+ depth + 1,
+ stats,
+ true);
+ }
+
cleanup:
+ VIR_FREE(entry_name);
return ret;
}
@@ -2085,15 +2109,13 @@ qemuMonitorJSONBlockStatsUpdateCapacity(qemuMonitorPtr mon,
goto cleanup;
}
- if (STRPREFIX(dev_name, QEMU_DRIVE_HOST_PREFIX))
- dev_name += strlen(QEMU_DRIVE_HOST_PREFIX);
-
/* drive may be empty */
if (!(inserted = virJSONValueObjectGet(dev, "inserted")) ||
!(image = virJSONValueObjectGet(inserted, "image")))
continue;
- if (qemuMonitorJSONBlockStatsUpdateCapacityOne(image, dev_name, stats,
+ if (qemuMonitorJSONBlockStatsUpdateCapacityOne(image, dev_name, 0,
+ stats,
backingChain) < 0)
goto cleanup;
}
--
2.2.0