On 09/08/14 15:05, Francesco Romani wrote:
Management software, want to be able to allocate disk space on
demand.
s/, want/ wants/
To support this, they need keep track of the space occupation
s/,//
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, an helper is extracted from
s/,// s/an/a/
qemuMonitorJSONGetBlockExtent in order to get per-device
allocation information.
Signed-off-by: Francesco Romani <fromani(a)redhat.com>
---
src/libvirt.c | 2 ++
src/qemu/qemu_driver.c | 15 +++++++++
src/qemu/qemu_monitor.h | 1 +
src/qemu/qemu_monitor_json.c | 76 ++++++++++++++++++++++++++++++++------------
4 files changed, 73 insertions(+), 21 deletions(-)
diff --git a/src/qemu/qemu_monitor_json.c
b/src/qemu/qemu_monitor_json.c
index aa95e71..bc5616d 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -1776,6 +1776,55 @@ int qemuMonitorJSONGetBlockStatsInfo(qemuMonitorPtr mon,
}
+/* This helper function could be called in the
+ * qemuMonitorJSONGetAllBlockStatsInfo
+ * path - which is used also by the
+ * qemuMonitorJSONGetBlockStatsInfo
+ * path. In this case, we don't know in advance if the wr_highest_offset
+ * field is there, so it is OK to fail silently.
+ * However, we can get here by the
+ * qemuMonitorJSONGetBlockExtent
+ * path, and in that case we _must_ fail loudly.
+ */
+static int
+qemuMonitorJSONDevGetBlockExtent(virJSONValuePtr dev,
+ bool report_error,
+ unsigned long long *extent)
+{
+ virJSONValuePtr stats;
+ virJSONValuePtr parent;
+
+ if ((parent = virJSONValueObjectGet(dev, "parent")) == NULL ||
+ parent->type != VIR_JSON_TYPE_OBJECT) {
+ if (report_error)
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("blockstats parent entry was not in "
+ "expected format"));
+ return -1;
+ }
+
+ if ((stats = virJSONValueObjectGet(parent, "stats")) == NULL ||
+ stats->type != VIR_JSON_TYPE_OBJECT) {
+ if (report_error)
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("blockstats stats entry was not in "
+ "expected format"));
+ return -1;
+ }
+
+ if (virJSONValueObjectGetNumberUlong(stats, "wr_highest_offset",
+ extent) < 0) {
+ if (report_error)
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("cannot read %s statistic"),
+ "wr_highest_offset");
+ return -1;
+ }
+
+ return 0;
+}
+
+
int qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitorPtr mon,
const char *dev_name,
qemuBlockStatsPtr bstats,
@@ -1919,6 +1968,10 @@ int qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitorPtr mon,
goto cleanup;
}
+ /* it's ok to not have this information here. Just skip silently. */
+ qemuMonitorJSONDevGetBlockExtent(dev, false,
+ &bstats->wr_highest_offset);
As you want to ignore errors, it would probably be better just to copy
the extraction code here without error reporting rather than extracting
it to a helper ... this isn't something that would be reused any more.
+
ret++;
bstats++;
}
@@ -2010,6 +2063,7 @@ int qemuMonitorJSONGetBlockStatsParamsNumber(qemuMonitorPtr mon,
return ret;
}
+
int qemuMonitorJSONGetBlockExtent(qemuMonitorPtr mon,
const char *dev_name,
unsigned long long *extent)
@@ -2044,8 +2098,6 @@ int qemuMonitorJSONGetBlockExtent(qemuMonitorPtr mon,
for (i = 0; i < virJSONValueArraySize(devices); i++) {
virJSONValuePtr dev = virJSONValueArrayGet(devices, i);
- virJSONValuePtr stats;
- virJSONValuePtr parent;
const char *thisdev;
if (!dev || dev->type != VIR_JSON_TYPE_OBJECT) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -2070,26 +2122,8 @@ 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"));
+ if (qemuMonitorJSONDevGetBlockExtent(dev, true, extent) < 0)
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");
- goto cleanup;
- }
}
if (!found) {
Peter