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(a)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 220304f..02887cd 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -2693,6 +2693,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 efabd82..288b601 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -375,6 +375,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 3a13890..e567aa7 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -1696,13 +1696,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;
@@ -1778,12 +1783,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;
}
@@ -1838,10 +1851,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;
@@ -1862,17 +1872,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;
}
@@ -1889,7 +1902,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;
}
@@ -1942,15 +1966,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;
}
--
1.9.3