On 09/25/2014 08:06 AM, Peter Krempa wrote:
From: Francesco Romani <fromani(a)redhat.com>
Management software wants to be able to allocate disk space on demand.
To support this they need keep track of the space occupation of the
block device. This information is reported by qemu as part of block
stats.
This patch extend the block information in the bulk stats with the
allocation information.
To keep the same behaviour a helper is extracted from
qemuMonitorJSONGetBlockExtent in order to get per-device allocation
information.
Signed-off-by: Francesco Romani <fromani(a)redhat.com>
Signed-off-by: Peter Krempa <pkrempa(a)redhat.com>
---
src/libvirt.c | 6 +++
src/qemu/qemu_driver.c | 27 +++++++++++++
src/qemu/qemu_monitor.h | 1 +
src/qemu/qemu_monitor_json.c | 91 ++++++++++++++++++++++++++++++++++----------
4 files changed, 105 insertions(+), 20 deletions(-)
,,,
int qemuMonitorGetAllBlockStatsInfo(qemuMonitorPtr mon,
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index b634121..c41a7fb 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -1782,6 +1782,40 @@ int qemuMonitorJSONGetBlockStatsInfo(qemuMonitorPtr mon,
}
+typedef enum {
+ QEMU_MONITOR_BLOCK_EXTENT_ERROR_OK,
+ QEMU_MONITOR_BLOCK_EXTENT_ERROR_NOPARENT,
+ QEMU_MONITOR_BLOCK_EXTENT_ERROR_NOSTATS,
+ QEMU_MONITOR_BLOCK_EXTENT_ERROR_NOOFFSET
+} qemuMonitorBlockExtentError;
+
+
+static int
+qemuMonitorJSONDevGetBlockExtent(virJSONValuePtr dev,
+ unsigned long long *extent)
+{
+ virJSONValuePtr stats;
+ virJSONValuePtr parent;
+
+ if ((parent = virJSONValueObjectGet(dev, "parent")) == NULL ||
+ parent->type != VIR_JSON_TYPE_OBJECT) {
+ return QEMU_MONITOR_BLOCK_EXTENT_ERROR_NOPARENT;
+ }
+
+ if ((stats = virJSONValueObjectGet(parent, "stats")) == NULL ||
+ stats->type != VIR_JSON_TYPE_OBJECT) {
+ return QEMU_MONITOR_BLOCK_EXTENT_ERROR_NOSTATS;
+ }
+
+ if (virJSONValueObjectGetNumberUlong(stats, "wr_highest_offset",
+ extent) < 0) {
+ return QEMU_MONITOR_BLOCK_EXTENT_ERROR_NOOFFSET;
+ }
+
+ return QEMU_MONITOR_BLOCK_EXTENT_ERROR_OK;
+}
+
+
int qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitorPtr mon,
virHashTablePtr *ret_stats)
{
@@ -1908,6 +1942,9 @@ int qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitorPtr mon,
goto cleanup;
}
+ /* it's ok to not have this information here. Just skip silently. */
+ qemuMonitorJSONDevGetBlockExtent(dev, &bstats->wr_highest_offset);
+
if (virHashAddEntry(hash, devname, bstats) < 0)
goto cleanup;
bstats = NULL;
@@ -2077,6 +2114,36 @@ int qemuMonitorJSONGetBlockStatsParamsNumber(qemuMonitorPtr mon,
return ret;
}
+
+static int
+qemuMonitorJSONReportBlockExtentError(qemuMonitorBlockExtentError error)
+{
+ switch (error) {
+ case QEMU_MONITOR_BLOCK_EXTENT_ERROR_NOPARENT:
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("blockstats parent entry was not in "
+ "expected format"));
+ break;
+
+ case QEMU_MONITOR_BLOCK_EXTENT_ERROR_NOSTATS:
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("blockstats stats entry was not in "
+ "expected format"));
+
Missing a break;
(found by my monrning Coverity run)
John
+ case QEMU_MONITOR_BLOCK_EXTENT_ERROR_NOOFFSET:
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot read %s statistic"),
+ "wr_highest_offset");
+ break;
+
+ case QEMU_MONITOR_BLOCK_EXTENT_ERROR_OK:
+ return 0;
+ }
+
+ return -1;
+}
+
+
int qemuMonitorJSONGetBlockExtent(qemuMonitorPtr mon,
const char *dev_name,
unsigned long long *extent)
@@ -2111,9 +2178,8 @@ int qemuMonitorJSONGetBlockExtent(qemuMonitorPtr mon,
for (i = 0; i < virJSONValueArraySize(devices); i++) {
virJSONValuePtr dev = virJSONValueArrayGet(devices, i);
- virJSONValuePtr stats;
- virJSONValuePtr parent;
const char *thisdev;
+ int err;
if (!dev || dev->type != VIR_JSON_TYPE_OBJECT) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("blockstats device entry was not in expected
format"));
@@ -2137,24 +2203,9 @@ int qemuMonitorJSONGetBlockExtent(qemuMonitorPtr mon,
continue;
found = true;
- if ((parent = virJSONValueObjectGet(dev, "parent")) == NULL ||
- parent->type != VIR_JSON_TYPE_OBJECT) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("blockstats parent entry was not in expected
format"));
- goto cleanup;
- }
-
- if ((stats = virJSONValueObjectGet(parent, "stats")) == NULL ||
- stats->type != VIR_JSON_TYPE_OBJECT) {
- virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("blockstats stats entry was not in expected
format"));
- goto cleanup;
- }
-
- if (virJSONValueObjectGetNumberUlong(stats, "wr_highest_offset",
extent) < 0) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("cannot read %s statistic"),
- "wr_highest_offset");
+ if ((err = qemuMonitorJSONDevGetBlockExtent(dev, extent)) !=
+ QEMU_MONITOR_BLOCK_EXTENT_ERROR_OK) {
+ qemuMonitorJSONReportBlockExtentError(err);
goto cleanup;
}
}