mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-22 20:45:18 +00:00
getstats: perform recursion in monitor collection
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>
This commit is contained in:
parent
7b11f5e554
commit
b1802714da
@ -2694,6 +2694,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,
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user