In cases when -blockdev is used we need to use 'query-named-block-nodes'
instead of 'query-block'. This means that we can extract the
write-threshold variable right away.
To keep compatibility with old VMs modify the code which was extracting
the value previously so that it updates the stats structure and a single
code path then can be used to extract the data.
Signed-off-by: Peter Krempa <pkrempa(a)redhat.com>
---
src/qemu/qemu_driver.c | 57 ++++++++++++++++++++++++++------------------
src/qemu/qemu_monitor.h | 3 +++
src/qemu/qemu_monitor_json.c | 16 ++++++++++---
3 files changed, 50 insertions(+), 26 deletions(-)
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index ed0c563c85..b0ac5e536b 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -20043,29 +20043,39 @@ qemuDomainGetStatsOneBlockFallback(virQEMUDriverPtr driver,
}
-static int
-qemuDomainGetStatsOneBlockNode(virDomainStatsRecordPtr record,
- int *maxparams,
- virStorageSourcePtr src,
- size_t block_idx,
- virHashTablePtr nodedata)
+/**
+ * qemuDomainGetStatsOneBlockRefreshNamed:
+ * @src: disk source structure
+ * @alias: disk alias
+ * @stats: hash table containing stats for all disks
+ * @nodedata: reply containin 'query-named-block-nodes' data
+ *
+ * Refresh disk block stats data (qemuBlockStatsPtr) which are present only
+ * in the reply of 'query-named-block-nodes' in cases when the data was gathered
+ * by using qem-block originally.
+ */
+static void
+qemuDomainGetStatsOneBlockRefreshNamed(virStorageSourcePtr src,
+ const char *alias,
+ virHashTablePtr stats,
+ virHashTablePtr nodedata)
{
+ qemuBlockStatsPtr entry;
+
virJSONValuePtr data;
unsigned long long tmp;
- int ret = -1;
- if (src->nodestorage &&
- (data = virHashLookup(nodedata, src->nodestorage))) {
- if (virJSONValueObjectGetNumberUlong(data, "write_threshold", &tmp)
== 0 &&
- tmp > 0)
- QEMU_ADD_BLOCK_PARAM_ULL(record, maxparams, block_idx,
- "threshold", tmp);
- }
+ if (!nodedata || !src->nodestorage)
+ return;
- ret = 0;
+ if (!(entry = virHashLookup(stats, alias)))
+ return;
- cleanup:
- return ret;
+ if (!(data = virHashLookup(nodedata, src->nodestorage)))
+ return;
+
+ if (virJSONValueObjectGetNumberUlong(data, "write_threshold", &tmp) ==
0)
+ entry->write_threshold = tmp;
}
@@ -20079,8 +20089,7 @@ qemuDomainGetStatsOneBlock(virQEMUDriverPtr driver,
const char *entryname,
virStorageSourcePtr src,
size_t block_idx,
- virHashTablePtr stats,
- virHashTablePtr nodedata)
+ virHashTablePtr stats)
{
qemuBlockStats *entry;
int ret = -1;
@@ -20145,9 +20154,9 @@ qemuDomainGetStatsOneBlock(virQEMUDriverPtr driver,
}
}
- if (qemuDomainGetStatsOneBlockNode(record, maxparams, src, block_idx,
- nodedata) < 0)
- goto cleanup;
+ if (entry->write_threshold)
+ QEMU_ADD_BLOCK_PARAM_ULL(record, maxparams, block_idx, "threshold",
+ entry->write_threshold);
ret = 0;
cleanup:
@@ -20218,9 +20227,11 @@ qemuDomainGetStatsBlock(virQEMUDriverPtr driver,
!(alias = qemuDomainStorageAlias(disk->info.alias, src->id)))
goto cleanup;
+ qemuDomainGetStatsOneBlockRefreshNamed(src, alias, stats, nodestats);
+
if (qemuDomainGetStatsOneBlock(driver, cfg, dom, record, maxparams,
disk->dst, alias, src, visited,
- stats, nodestats) < 0)
+ stats) < 0)
goto cleanup;
VIR_FREE(alias);
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 3e4822c6ec..431848856a 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -583,6 +583,9 @@ struct _qemuBlockStats {
* if wr_highest_offset_valid is true */
unsigned long long wr_highest_offset;
bool wr_highest_offset_valid;
+
+ /* write_threshold is valid only if it's non-zero, conforming to qemu semantics
*/
+ unsigned long long write_threshold;
};
int qemuMonitorGetAllBlockStatsInfo(qemuMonitorPtr mon,
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 51d6ee2917..75f40716ea 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -2484,7 +2484,8 @@ qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitorPtr mon,
static int
qemuMonitorJSONBlockStatsUpdateCapacityData(virJSONValuePtr image,
const char *name,
- virHashTablePtr stats)
+ virHashTablePtr stats,
+ qemuBlockStatsPtr *entry)
{
qemuBlockStatsPtr bstats;
@@ -2498,6 +2499,9 @@ qemuMonitorJSONBlockStatsUpdateCapacityData(virJSONValuePtr image,
}
}
+ if (entry)
+ *entry = bstats;
+
/* failures can be ignored after this point */
if (virJSONValueObjectGetNumberUlong(image, "virtual-size",
&bstats->capacity) < 0)
@@ -2523,7 +2527,8 @@ qemuMonitorJSONBlockStatsUpdateCapacityOne(virJSONValuePtr image,
char *entry_name = qemuDomainStorageAlias(dev_name, depth);
virJSONValuePtr backing;
- if (qemuMonitorJSONBlockStatsUpdateCapacityData(image, entry_name, stats) < 0)
+ if (qemuMonitorJSONBlockStatsUpdateCapacityData(image, entry_name,
+ stats, NULL) < 0)
goto cleanup;
if (backingChain &&
@@ -2593,6 +2598,7 @@ qemuMonitorJSONBlockStatsUpdateCapacityBlockdevWorker(size_t pos
ATTRIBUTE_UNUSE
virHashTablePtr stats = opaque;
virJSONValuePtr image;
const char *nodename;
+ qemuBlockStatsPtr entry;
if (!(nodename = virJSONValueObjectGetString(val, "node-name")) ||
!(image = virJSONValueObjectGetObject(val, "image"))) {
@@ -2601,9 +2607,13 @@ qemuMonitorJSONBlockStatsUpdateCapacityBlockdevWorker(size_t pos
ATTRIBUTE_UNUSE
return -1;
}
- if (qemuMonitorJSONBlockStatsUpdateCapacityData(image, nodename, stats) < 0)
+ if (qemuMonitorJSONBlockStatsUpdateCapacityData(image, nodename, stats, &entry)
< 0)
return -1;
+ if (entry)
+ ignore_value(virJSONValueObjectGetNumberUlong(val, "write_threshold",
+ &entry->write_threshold));
+
return 1; /* we don't want to steal the value from the JSON array */
}
--
2.16.2