]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
getstats: perform recursion in monitor collection
authorEric Blake <eblake@redhat.com>
Fri, 12 Dec 2014 16:53:33 +0000 (09:53 -0700)
committerEric Blake <eblake@redhat.com>
Tue, 16 Dec 2014 23:14:55 +0000 (16:14 -0700)
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@redhat.com>
src/qemu/qemu_domain.c
src/qemu/qemu_domain.h
src/qemu/qemu_monitor_json.c

index 8dd427ad016310541501d6d9d779c3288295ba8a..ee3b52067f334e4ecbb69e15571df00c6194a2a3 100644 (file)
@@ -2694,6 +2694,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,
index ce5eba3feee2bf85a3c3686fa3affc8a473750ca..d77d486ef7c2f2892496a4416119ef3963d3717a 100644 (file)
@@ -376,6 +376,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);
index 3a13890828dbb058b18ebd33da63c15520439316..e567aa772fa728a4a561d31cd4072f5eb86acdc0 100644 (file)
@@ -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;
     }