[libvirt] [PATCH v2 04/12] getstats: perform recursion in monitor collection

Eric Blake eblake at redhat.com
Tue Dec 16 08:04:10 UTC 2014


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 at redhat.com>
---
 src/qemu/qemu_domain.c       | 16 +++++++++++++++
 src/qemu/qemu_domain.h       |  1 +
 src/qemu/qemu_monitor_json.c | 48 ++++++++++++++++++++++++++++++++------------
 3 files changed, 52 insertions(+), 13 deletions(-)

diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 220304f..02887cd 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -2693,6 +2693,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,
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index efabd82..288b601 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -375,6 +375,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);
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 3a13890..e567aa7 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -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;
     }
-- 
1.9.3




More information about the libvir-list mailing list