9119d9
From d86dcee6e419259d365eaaa69a4d71c48491e95f Mon Sep 17 00:00:00 2001
9119d9
Message-Id: <d86dcee6e419259d365eaaa69a4d71c48491e95f@dist-git>
9119d9
From: Eric Blake <eblake@redhat.com>
9119d9
Date: Wed, 17 Dec 2014 03:09:04 -0700
9119d9
Subject: [PATCH] getstats: prepare monitor collection for recursion
9119d9
9119d9
https://bugzilla.redhat.com/show_bug.cgi?id=1041569
9119d9
9119d9
A future patch will allow recursion into backing chains when
9119d9
collecting block stats.  This patch should not change behavior,
9119d9
but merely moves out the common code that will be reused once
9119d9
recursion is enabled, and adds the parameter that will turn on
9119d9
recursion.
9119d9
9119d9
* src/qemu/qemu_monitor.h (qemuMonitorGetAllBlockStatsInfo)
9119d9
(qemuMonitorBlockStatsUpdateCapacity): Add recursion parameter,
9119d9
although it is ignored for now.
9119d9
* src/qemu/qemu_monitor.h (qemuMonitorGetAllBlockStatsInfo)
9119d9
(qemuMonitorBlockStatsUpdateCapacity): Likewise.
9119d9
* src/qemu/qemu_monitor_json.h
9119d9
(qemuMonitorJSONGetAllBlockStatsInfo)
9119d9
(qemuMonitorJSONBlockStatsUpdateCapacity): Likewise.
9119d9
* src/qemu/qemu_monitor_json.c
9119d9
(qemuMonitorJSONGetAllBlockStatsInfo)
9119d9
(qemuMonitorJSONBlockStatsUpdateCapacity): Add parameter, and
9119d9
split...
9119d9
(qemuMonitorJSONGetOneBlockStatsInfo)
9119d9
(qemuMonitorJSONBlockStatsUpdateCapacityOne): ...into helpers.
9119d9
(qemuMonitorJSONGetBlockStatsInfo): Update caller.
9119d9
* src/qemu/qemu_driver.c (qemuDomainGetStatsBlock): Update caller.
9119d9
* src/qemu/qemu_migration.c (qemuMigrationCookieAddNBD): Likewise.
9119d9
9119d9
Signed-off-by: Eric Blake <eblake@redhat.com>
9119d9
(cherry picked from commit 7b11f5e5547ded860692caa2cefae1a856920336)
9119d9
9119d9
Conflicts:
9119d9
	src/qemu/qemu_migration.c - no disk precreation (commit e1466dc)
9119d9
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
9119d9
---
9119d9
 src/qemu/qemu_driver.c       |   5 +-
9119d9
 src/qemu/qemu_monitor.c      |  24 ++--
9119d9
 src/qemu/qemu_monitor.h      |   6 +-
9119d9
 src/qemu/qemu_monitor_json.c | 257 +++++++++++++++++++++++++------------------
9119d9
 src/qemu/qemu_monitor_json.h |   6 +-
9119d9
 5 files changed, 173 insertions(+), 125 deletions(-)
9119d9
9119d9
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
9119d9
index 03b62d8..8376486 100644
9119d9
--- a/src/qemu/qemu_driver.c
9119d9
+++ b/src/qemu/qemu_driver.c
9119d9
@@ -18025,8 +18025,9 @@ qemuDomainGetStatsBlock(virQEMUDriverPtr driver,
9119d9
         abbreviated = true; /* it's ok, just go ahead silently */
9119d9
     } else {
9119d9
         qemuDomainObjEnterMonitor(driver, dom);
9119d9
-        rc = qemuMonitorGetAllBlockStatsInfo(priv->mon, &stats);
9119d9
-        ignore_value(qemuMonitorBlockStatsUpdateCapacity(priv->mon, stats));
9119d9
+        rc = qemuMonitorGetAllBlockStatsInfo(priv->mon, &stats, false);
9119d9
+        ignore_value(qemuMonitorBlockStatsUpdateCapacity(priv->mon, stats,
9119d9
+                                                         false));
9119d9
         qemuDomainObjExitMonitor(driver, dom);
9119d9
 
9119d9
         if (rc < 0) {
9119d9
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
9119d9
index 38399ba..f797f4f 100644
9119d9
--- a/src/qemu/qemu_monitor.c
9119d9
+++ b/src/qemu/qemu_monitor.c
9119d9
@@ -1787,16 +1787,16 @@ int qemuMonitorGetBlockStatsInfo(qemuMonitorPtr mon,
9119d9
     return ret;
9119d9
 }
9119d9
 
9119d9
-/* Fills the first 'nstats' block stats. 'stats' must be an array.
9119d9
- * Returns <0 on error, otherwise the number of block stats retrieved.
9119d9
- * if 'dev_name' is != NULL, look for this device only and skip
9119d9
- * any other. In that case return value cannot be greater than 1.
9119d9
+
9119d9
+/* Creates a hash table in 'ret_stats' with all block stats.
9119d9
+ * Returns <0 on error, 0 on success.
9119d9
  */
9119d9
 int
9119d9
 qemuMonitorGetAllBlockStatsInfo(qemuMonitorPtr mon,
9119d9
-                                virHashTablePtr *ret_stats)
9119d9
+                                virHashTablePtr *ret_stats,
9119d9
+                                bool backingChain)
9119d9
 {
9119d9
-    VIR_DEBUG("mon=%p ret_stats=%p", mon, ret_stats);
9119d9
+    VIR_DEBUG("mon=%p ret_stats=%p, backing=%d", mon, ret_stats, backingChain);
9119d9
 
9119d9
     if (!mon->json) {
9119d9
         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
9119d9
@@ -1804,15 +1804,17 @@ qemuMonitorGetAllBlockStatsInfo(qemuMonitorPtr mon,
9119d9
         return -1;
9119d9
     }
9119d9
 
9119d9
-    return qemuMonitorJSONGetAllBlockStatsInfo(mon, ret_stats);
9119d9
+    return qemuMonitorJSONGetAllBlockStatsInfo(mon, ret_stats, backingChain);
9119d9
 }
9119d9
 
9119d9
 
9119d9
 /* Updates "stats" to fill virtual and physical size of the image */
9119d9
-int qemuMonitorBlockStatsUpdateCapacity(qemuMonitorPtr mon,
9119d9
-                                        virHashTablePtr stats)
9119d9
+int
9119d9
+qemuMonitorBlockStatsUpdateCapacity(qemuMonitorPtr mon,
9119d9
+                                    virHashTablePtr stats,
9119d9
+                                    bool backingChain)
9119d9
 {
9119d9
-    VIR_DEBUG("mon=%p, stats=%p", mon, stats);
9119d9
+    VIR_DEBUG("mon=%p, stats=%p, backing=%d", mon, stats, backingChain);
9119d9
 
9119d9
     if (!mon->json) {
9119d9
         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
9119d9
@@ -1820,7 +1822,7 @@ int qemuMonitorBlockStatsUpdateCapacity(qemuMonitorPtr mon,
9119d9
         return -1;
9119d9
     }
9119d9
 
9119d9
-    return qemuMonitorJSONBlockStatsUpdateCapacity(mon, stats);
9119d9
+    return qemuMonitorJSONBlockStatsUpdateCapacity(mon, stats, backingChain);
9119d9
 }
9119d9
 
9119d9
 
9119d9
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
9119d9
index d1dc242..b08d74d 100644
9119d9
--- a/src/qemu/qemu_monitor.h
9119d9
+++ b/src/qemu/qemu_monitor.h
9119d9
@@ -382,11 +382,13 @@ struct _qemuBlockStats {
9119d9
 };
9119d9
 
9119d9
 int qemuMonitorGetAllBlockStatsInfo(qemuMonitorPtr mon,
9119d9
-                                    virHashTablePtr *ret_stats)
9119d9
+                                    virHashTablePtr *ret_stats,
9119d9
+                                    bool backingChain)
9119d9
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
9119d9
 
9119d9
 int qemuMonitorBlockStatsUpdateCapacity(qemuMonitorPtr mon,
9119d9
-                                        virHashTablePtr stats)
9119d9
+                                        virHashTablePtr stats,
9119d9
+                                        bool backingChain)
9119d9
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
9119d9
 
9119d9
 int qemuMonitorGetBlockStatsParamsNumber(qemuMonitorPtr mon,
9119d9
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
9119d9
index 3cf67aa..7088409 100644
9119d9
--- a/src/qemu/qemu_monitor_json.c
9119d9
+++ b/src/qemu/qemu_monitor_json.c
9119d9
@@ -1770,7 +1770,7 @@ int qemuMonitorJSONGetBlockStatsInfo(qemuMonitorPtr mon,
9119d9
     if (flush_total_times)
9119d9
         *flush_total_times = -1;
9119d9
 
9119d9
-    if (qemuMonitorJSONGetAllBlockStatsInfo(mon, &blockstats) < 0)
9119d9
+    if (qemuMonitorJSONGetAllBlockStatsInfo(mon, &blockstats, false) < 0)
9119d9
         goto cleanup;
9119d9
 
9119d9
     if (!(stats = virHashLookup(blockstats, dev_name))) {
9119d9
@@ -1836,16 +1836,112 @@ qemuMonitorJSONDevGetBlockExtent(virJSONValuePtr dev,
9119d9
 }
9119d9
 
9119d9
 
9119d9
-int qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitorPtr mon,
9119d9
-                                        virHashTablePtr *ret_stats)
9119d9
+static int
9119d9
+qemuMonitorJSONGetOneBlockStatsInfo(virJSONValuePtr dev,
9119d9
+                                    const char *dev_name,
9119d9
+                                    virHashTablePtr hash,
9119d9
+                                    bool backingChain ATTRIBUTE_UNUSED)
9119d9
 {
9119d9
-    int ret = -1;
9119d9
-    int rc;
9119d9
-    size_t i;
9119d9
-    virJSONValuePtr cmd;
9119d9
-    virJSONValuePtr reply = NULL;
9119d9
-    virJSONValuePtr devices;
9119d9
     qemuBlockStatsPtr bstats = NULL;
9119d9
+    virJSONValuePtr stats;
9119d9
+    int ret = -1;
9119d9
+
9119d9
+    if (VIR_ALLOC(bstats) < 0)
9119d9
+        goto cleanup;
9119d9
+
9119d9
+    if ((stats = virJSONValueObjectGet(dev, "stats")) == NULL ||
9119d9
+        stats->type != VIR_JSON_TYPE_OBJECT) {
9119d9
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
9119d9
+                       _("blockstats stats entry was not "
9119d9
+                         "in expected format"));
9119d9
+        goto cleanup;
9119d9
+    }
9119d9
+
9119d9
+    if (virJSONValueObjectGetNumberLong(stats, "rd_bytes",
9119d9
+                                        &bstats->rd_bytes) < 0) {
9119d9
+        virReportError(VIR_ERR_INTERNAL_ERROR,
9119d9
+                       _("cannot read %s statistic"),
9119d9
+                       "rd_bytes");
9119d9
+        goto cleanup;
9119d9
+    }
9119d9
+    if (virJSONValueObjectGetNumberLong(stats, "rd_operations",
9119d9
+                                        &bstats->rd_req) < 0) {
9119d9
+        virReportError(VIR_ERR_INTERNAL_ERROR,
9119d9
+                       _("cannot read %s statistic"),
9119d9
+                       "rd_operations");
9119d9
+        goto cleanup;
9119d9
+    }
9119d9
+    if (virJSONValueObjectHasKey(stats, "rd_total_time_ns") &&
9119d9
+        (virJSONValueObjectGetNumberLong(stats, "rd_total_time_ns",
9119d9
+                                         &bstats->rd_total_times) < 0)) {
9119d9
+        virReportError(VIR_ERR_INTERNAL_ERROR,
9119d9
+                       _("cannot read %s statistic"),
9119d9
+                       "rd_total_time_ns");
9119d9
+        goto cleanup;
9119d9
+    }
9119d9
+    if (virJSONValueObjectGetNumberLong(stats, "wr_bytes",
9119d9
+                                        &bstats->wr_bytes) < 0) {
9119d9
+        virReportError(VIR_ERR_INTERNAL_ERROR,
9119d9
+                       _("cannot read %s statistic"),
9119d9
+                       "wr_bytes");
9119d9
+        goto cleanup;
9119d9
+    }
9119d9
+    if (virJSONValueObjectGetNumberLong(stats, "wr_operations",
9119d9
+                                        &bstats->wr_req) < 0) {
9119d9
+        virReportError(VIR_ERR_INTERNAL_ERROR,
9119d9
+                       _("cannot read %s statistic"),
9119d9
+                       "wr_operations");
9119d9
+        goto cleanup;
9119d9
+    }
9119d9
+    if (virJSONValueObjectHasKey(stats, "wr_total_time_ns") &&
9119d9
+        (virJSONValueObjectGetNumberLong(stats, "wr_total_time_ns",
9119d9
+                                         &bstats->wr_total_times) < 0)) {
9119d9
+        virReportError(VIR_ERR_INTERNAL_ERROR,
9119d9
+                       _("cannot read %s statistic"),
9119d9
+                       "wr_total_time_ns");
9119d9
+        goto cleanup;
9119d9
+    }
9119d9
+    if (virJSONValueObjectHasKey(stats, "flush_operations") &&
9119d9
+        (virJSONValueObjectGetNumberLong(stats, "flush_operations",
9119d9
+                                         &bstats->flush_req) < 0)) {
9119d9
+        virReportError(VIR_ERR_INTERNAL_ERROR,
9119d9
+                       _("cannot read %s statistic"),
9119d9
+                       "flush_operations");
9119d9
+        goto cleanup;
9119d9
+    }
9119d9
+    if (virJSONValueObjectHasKey(stats, "flush_total_time_ns") &&
9119d9
+        (virJSONValueObjectGetNumberLong(stats, "flush_total_time_ns",
9119d9
+                                         &bstats->flush_total_times) < 0)) {
9119d9
+        virReportError(VIR_ERR_INTERNAL_ERROR,
9119d9
+                       _("cannot read %s statistic"),
9119d9
+                       "flush_total_time_ns");
9119d9
+        goto cleanup;
9119d9
+    }
9119d9
+
9119d9
+    /* it's ok to not have this information here. Just skip silently. */
9119d9
+    qemuMonitorJSONDevGetBlockExtent(dev, &bstats->wr_highest_offset);
9119d9
+
9119d9
+    if (virHashAddEntry(hash, dev_name, bstats) < 0)
9119d9
+        goto cleanup;
9119d9
+    bstats = NULL;
9119d9
+    ret = 0;
9119d9
+ cleanup:
9119d9
+    VIR_FREE(bstats);
9119d9
+    return ret;
9119d9
+}
9119d9
+
9119d9
+
9119d9
+int
9119d9
+qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitorPtr mon,
9119d9
+                                    virHashTablePtr *ret_stats,
9119d9
+                                    bool backingChain)
9119d9
+{
9119d9
+    int ret = -1;
9119d9
+    int rc;
9119d9
+    size_t i;
9119d9
+    virJSONValuePtr cmd;
9119d9
+    virJSONValuePtr reply = NULL;
9119d9
+    virJSONValuePtr devices;
9119d9
     virHashTablePtr hash = NULL;
9119d9
 
9119d9
     if (!(cmd = qemuMonitorJSONMakeCommand("query-blockstats", NULL)))
9119d9
@@ -1869,12 +1965,8 @@ int qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitorPtr mon,
9119d9
 
9119d9
     for (i = 0; i < virJSONValueArraySize(devices); i++) {
9119d9
         virJSONValuePtr dev = virJSONValueArrayGet(devices, i);
9119d9
-        virJSONValuePtr stats;
9119d9
         const char *dev_name;
9119d9
 
9119d9
-        if (VIR_ALLOC(bstats) < 0)
9119d9
-            goto cleanup;
9119d9
-
9119d9
         if (!dev || dev->type != VIR_JSON_TYPE_OBJECT) {
9119d9
             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
9119d9
                            _("blockstats device entry was not "
9119d9
@@ -1892,81 +1984,10 @@ int qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitorPtr mon,
9119d9
         if (STRPREFIX(dev_name, QEMU_DRIVE_HOST_PREFIX))
9119d9
             dev_name += strlen(QEMU_DRIVE_HOST_PREFIX);
9119d9
 
9119d9
-        if ((stats = virJSONValueObjectGet(dev, "stats")) == NULL ||
9119d9
-            stats->type != VIR_JSON_TYPE_OBJECT) {
9119d9
-            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
9119d9
-                           _("blockstats stats entry was not "
9119d9
-                             "in expected format"));
9119d9
+        if (qemuMonitorJSONGetOneBlockStatsInfo(dev, dev_name, hash,
9119d9
+                                                backingChain) < 0)
9119d9
             goto cleanup;
9119d9
-        }
9119d9
 
9119d9
-        if (virJSONValueObjectGetNumberLong(stats, "rd_bytes",
9119d9
-                                            &bstats->rd_bytes) < 0) {
9119d9
-            virReportError(VIR_ERR_INTERNAL_ERROR,
9119d9
-                           _("cannot read %s statistic"),
9119d9
-                           "rd_bytes");
9119d9
-            goto cleanup;
9119d9
-        }
9119d9
-        if (virJSONValueObjectGetNumberLong(stats, "rd_operations",
9119d9
-                                            &bstats->rd_req) < 0) {
9119d9
-            virReportError(VIR_ERR_INTERNAL_ERROR,
9119d9
-                           _("cannot read %s statistic"),
9119d9
-                            "rd_operations");
9119d9
-            goto cleanup;
9119d9
-        }
9119d9
-        if (virJSONValueObjectHasKey(stats, "rd_total_time_ns") &&
9119d9
-            (virJSONValueObjectGetNumberLong(stats, "rd_total_time_ns",
9119d9
-                                             &bstats->rd_total_times) < 0)) {
9119d9
-            virReportError(VIR_ERR_INTERNAL_ERROR,
9119d9
-                           _("cannot read %s statistic"),
9119d9
-                           "rd_total_time_ns");
9119d9
-            goto cleanup;
9119d9
-        }
9119d9
-        if (virJSONValueObjectGetNumberLong(stats, "wr_bytes",
9119d9
-                                            &bstats->wr_bytes) < 0) {
9119d9
-            virReportError(VIR_ERR_INTERNAL_ERROR,
9119d9
-                           _("cannot read %s statistic"),
9119d9
-                           "wr_bytes");
9119d9
-            goto cleanup;
9119d9
-        }
9119d9
-        if (virJSONValueObjectGetNumberLong(stats, "wr_operations",
9119d9
-                                            &bstats->wr_req) < 0) {
9119d9
-            virReportError(VIR_ERR_INTERNAL_ERROR,
9119d9
-                           _("cannot read %s statistic"),
9119d9
-                           "wr_operations");
9119d9
-            goto cleanup;
9119d9
-        }
9119d9
-        if (virJSONValueObjectHasKey(stats, "wr_total_time_ns") &&
9119d9
-            (virJSONValueObjectGetNumberLong(stats, "wr_total_time_ns",
9119d9
-                                             &bstats->wr_total_times) < 0)) {
9119d9
-            virReportError(VIR_ERR_INTERNAL_ERROR,
9119d9
-                           _("cannot read %s statistic"),
9119d9
-                           "wr_total_time_ns");
9119d9
-            goto cleanup;
9119d9
-        }
9119d9
-        if (virJSONValueObjectHasKey(stats, "flush_operations") &&
9119d9
-            (virJSONValueObjectGetNumberLong(stats, "flush_operations",
9119d9
-                                             &bstats->flush_req) < 0)) {
9119d9
-            virReportError(VIR_ERR_INTERNAL_ERROR,
9119d9
-                           _("cannot read %s statistic"),
9119d9
-                           "flush_operations");
9119d9
-            goto cleanup;
9119d9
-        }
9119d9
-        if (virJSONValueObjectHasKey(stats, "flush_total_time_ns") &&
9119d9
-            (virJSONValueObjectGetNumberLong(stats, "flush_total_time_ns",
9119d9
-                                             &bstats->flush_total_times) < 0)) {
9119d9
-            virReportError(VIR_ERR_INTERNAL_ERROR,
9119d9
-                           _("cannot read %s statistic"),
9119d9
-                           "flush_total_time_ns");
9119d9
-            goto cleanup;
9119d9
-        }
9119d9
-
9119d9
-        /* it's ok to not have this information here. Just skip silently. */
9119d9
-        qemuMonitorJSONDevGetBlockExtent(dev, &bstats->wr_highest_offset);
9119d9
-
9119d9
-        if (virHashAddEntry(hash, dev_name, bstats) < 0)
9119d9
-            goto cleanup;
9119d9
-        bstats = NULL;
9119d9
     }
9119d9
 
9119d9
     *ret_stats = hash;
9119d9
@@ -1974,7 +1995,6 @@ int qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitorPtr mon,
9119d9
     ret = 0;
9119d9
 
9119d9
  cleanup:
9119d9
-    VIR_FREE(bstats);
9119d9
     virHashFree(hash);
9119d9
     virJSONValueFree(cmd);
9119d9
     virJSONValueFree(reply);
9119d9
@@ -1982,8 +2002,45 @@ int qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitorPtr mon,
9119d9
 }
9119d9
 
9119d9
 
9119d9
-int qemuMonitorJSONBlockStatsUpdateCapacity(qemuMonitorPtr mon,
9119d9
-                                            virHashTablePtr stats)
9119d9
+static int
9119d9
+qemuMonitorJSONBlockStatsUpdateCapacityOne(virJSONValuePtr image,
9119d9
+                                           const char *dev_name,
9119d9
+                                           virHashTablePtr stats,
9119d9
+                                           bool backingChain ATTRIBUTE_UNUSED)
9119d9
+{
9119d9
+    qemuBlockStatsPtr bstats;
9119d9
+    int ret = -1;
9119d9
+
9119d9
+    if (!(bstats = virHashLookup(stats, dev_name))) {
9119d9
+        if (VIR_ALLOC(bstats) < 0)
9119d9
+            goto cleanup;
9119d9
+
9119d9
+        if (virHashAddEntry(stats, dev_name, bstats) < 0) {
9119d9
+            VIR_FREE(bstats);
9119d9
+            goto cleanup;
9119d9
+        }
9119d9
+    }
9119d9
+
9119d9
+    /* After this point, we ignore failures; the stats were
9119d9
+     * zero-initialized when created which is a sane fallback.  */
9119d9
+    ret = 0;
9119d9
+    if (virJSONValueObjectGetNumberUlong(image, "virtual-size",
9119d9
+                                         &bstats->capacity) < 0)
9119d9
+        goto cleanup;
9119d9
+
9119d9
+    /* if actual-size is missing, image is not thin provisioned */
9119d9
+    if (virJSONValueObjectGetNumberUlong(image, "actual-size",
9119d9
+                                         &bstats->physical) < 0)
9119d9
+        bstats->physical = bstats->capacity;
9119d9
+ cleanup:
9119d9
+    return ret;
9119d9
+}
9119d9
+
9119d9
+
9119d9
+int
9119d9
+qemuMonitorJSONBlockStatsUpdateCapacity(qemuMonitorPtr mon,
9119d9
+                                        virHashTablePtr stats,
9119d9
+                                        bool backingChain)
9119d9
 {
9119d9
     int ret = -1;
9119d9
     int rc;
9119d9
@@ -2012,7 +2069,6 @@ int qemuMonitorJSONBlockStatsUpdateCapacity(qemuMonitorPtr mon,
9119d9
         virJSONValuePtr dev = virJSONValueArrayGet(devices, i);
9119d9
         virJSONValuePtr inserted;
9119d9
         virJSONValuePtr image;
9119d9
-        qemuBlockStatsPtr bstats;
9119d9
         const char *dev_name;
9119d9
 
9119d9
         if (!dev || dev->type != VIR_JSON_TYPE_OBJECT) {
9119d9
@@ -2037,24 +2093,9 @@ int qemuMonitorJSONBlockStatsUpdateCapacity(qemuMonitorPtr mon,
9119d9
             !(image = virJSONValueObjectGet(inserted, "image")))
9119d9
             continue;
9119d9
 
9119d9
-        if (!(bstats = virHashLookup(stats, dev_name))) {
9119d9
-            if (VIR_ALLOC(bstats) < 0)
9119d9
-                goto cleanup;
9119d9
-
9119d9
-            if (virHashAddEntry(stats, dev_name, bstats) < 0) {
9119d9
-                VIR_FREE(bstats);
9119d9
-                goto cleanup;
9119d9
-            }
9119d9
-        }
9119d9
-
9119d9
-        if (virJSONValueObjectGetNumberUlong(image, "virtual-size",
9119d9
-                                             &bstats->capacity) < 0)
9119d9
-            continue;
9119d9
-
9119d9
-        /* if actual-size is missing, image is not thin provisioned */
9119d9
-        if (virJSONValueObjectGetNumberUlong(image, "actual-size",
9119d9
-                                             &bstats->physical) < 0)
9119d9
-            bstats->physical = bstats->capacity;
9119d9
+        if (qemuMonitorJSONBlockStatsUpdateCapacityOne(image, dev_name, stats,
9119d9
+                                                       backingChain) < 0)
9119d9
+            goto cleanup;
9119d9
     }
9119d9
 
9119d9
     ret = 0;
9119d9
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
9119d9
index 17f9718..d039991 100644
9119d9
--- a/src/qemu/qemu_monitor_json.h
9119d9
+++ b/src/qemu/qemu_monitor_json.h
9119d9
@@ -80,9 +80,11 @@ int qemuMonitorJSONGetBlockStatsInfo(qemuMonitorPtr mon,
9119d9
                                      long long *flush_total_times,
9119d9
                                      long long *errs);
9119d9
 int qemuMonitorJSONGetAllBlockStatsInfo(qemuMonitorPtr mon,
9119d9
-                                        virHashTablePtr *ret_stats);
9119d9
+                                        virHashTablePtr *ret_stats,
9119d9
+                                        bool backingChain);
9119d9
 int qemuMonitorJSONBlockStatsUpdateCapacity(qemuMonitorPtr mon,
9119d9
-                                            virHashTablePtr stats);
9119d9
+                                            virHashTablePtr stats,
9119d9
+                                            bool backingChain);
9119d9
 int qemuMonitorJSONGetBlockStatsParamsNumber(qemuMonitorPtr mon,
9119d9
                                              int *nparams);
9119d9
 int qemuMonitorJSONGetBlockExtent(qemuMonitorPtr mon,
9119d9
-- 
9119d9
2.2.0
9119d9