[libvirt] [PATCH 6/8] Add capability to fetch balloon stats

John Ferlan jferlan at redhat.com
Tue Jul 2 13:39:24 UTC 2013


This patch will add the QEMU_MONITOR_OBJECT_PROPERTY_BALLOON_STATS type and
a mechanism in the qemuMonitorObjectProperty to fetch and store an opaque
data array assuming that we are provided a count of current elements,
a count of maximum elements, and the address of the array store the data.
Use the mechanism to fetch balloon driver statistics.
---
 src/qemu/qemu_monitor.h      |  4 +++
 src/qemu/qemu_monitor_json.c | 76 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 80 insertions(+)

diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index b822b97..4199160 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -703,6 +703,7 @@ typedef enum {
     QEMU_MONITOR_OBJECT_PROPERTY_ULONG,
     QEMU_MONITOR_OBJECT_PROPERTY_DOUBLE,
     QEMU_MONITOR_OBJECT_PROPERTY_STRING,
+    QEMU_MONITOR_OBJECT_PROPERTY_BALLOON_STATS,
 
     QEMU_MONITOR_OBJECT_PROPERTY_LAST
 } qemuMonitorObjectPropertyType;
@@ -711,6 +712,8 @@ typedef struct _qemuMonitorObjectProperty qemuMonitorObjectProperty;
 typedef qemuMonitorObjectProperty *qemuMonitorObjectPropertyPtr;
 struct _qemuMonitorObjectProperty {
     int type;    /* qemuMonitorObjectPropertyType */
+    int curelems;   /* Current number elements in **ptr array */
+    int maxelems;   /* Maximum number elements allowed in any **ptr array */
     union {
         bool b;
         int i;
@@ -719,6 +722,7 @@ struct _qemuMonitorObjectProperty {
         unsigned long long ul;
         double d;
         char *str;
+        void **ptr;
     } val;
 };
 
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index c599626..49001a8 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -4627,6 +4627,78 @@ cleanup:
 }
 
 
+/* Process the balloon driver statistics.  The request and data returned
+ * will be as follows (although the 'child[#]' entry will differ based on
+ * where it's run).
+ *
+ * { "execute": "qom-get","arguments": \
+ *    { "path": "/machine/i440fx/pci.0/child[7]","property": "guest-stats"} }
+ *
+ * {"return": {"stats": \
+ *               {"stat-swap-out": 0,
+ *                "stat-free-memory": 686350336,
+ *                "stat-minor-faults": 697283,
+ *                "stat-major-faults": 951,
+ *                "stat-total-memory": 1019924480,
+ *                "stat-swap-in": 0},
+ *            "last-update": 1371221540}}
+ *
+ * A value in "stats" can be -1 indicating it's never been collected/stored.
+ * The 'last-update' value could be used in the future in order to determine
+ * rates and/or whether data has been collected since a previous cycle.
+ * It's currently unused.
+ */
+#define GET_BALLOON_STATS(FIELD, TAG, DIVISOR)                                \
+    if (virJSONValueObjectHasKey(statsdata, FIELD) &&                         \
+       (prop->curelems < prop->maxelems)) {                                   \
+        if (virJSONValueObjectGetNumberUlong(statsdata, FIELD, &mem) < 0) {   \
+            VIR_DEBUG("Failed to get '%s' value", FIELD);                     \
+        } else {                                                              \
+            /* Not being collected? No point in providing bad data */         \
+            if (mem != -1UL) {                                                \
+                stat[prop->curelems].tag = TAG;                               \
+                stat[prop->curelems].val = mem / DIVISOR;                     \
+                prop->curelems++;                                             \
+            }                                                                 \
+        }                                                                     \
+    }
+
+static int
+qemuMonitorJSONGetBalloonStats(virJSONValuePtr data,
+                               qemuMonitorObjectPropertyPtr prop)
+{
+    int ret = -1;
+    unsigned long long mem;
+    virJSONValuePtr statsdata;
+    virDomainMemoryStatPtr stat = (virDomainMemoryStatPtr)prop->val.ptr;
+
+    VIR_DEBUG("Address of found stat = %p", stat);
+
+    if (!(statsdata = virJSONValueObjectGet(data, "stats"))) {
+        VIR_DEBUG("data does not include 'stats'");
+        goto cleanup;
+    }
+
+    GET_BALLOON_STATS("stat-swap-in",
+                      VIR_DOMAIN_MEMORY_STAT_SWAP_IN, 1024);
+    GET_BALLOON_STATS("stat-swap-out",
+                      VIR_DOMAIN_MEMORY_STAT_SWAP_OUT, 1024);
+    GET_BALLOON_STATS("stat-major-faults",
+                      VIR_DOMAIN_MEMORY_STAT_MAJOR_FAULT, 1);
+    GET_BALLOON_STATS("stat-minor-faults",
+                      VIR_DOMAIN_MEMORY_STAT_MINOR_FAULT, 1);
+    GET_BALLOON_STATS("stat-free-memory",
+                      VIR_DOMAIN_MEMORY_STAT_UNUSED, 1024);
+    GET_BALLOON_STATS("stat-total-memory",
+                      VIR_DOMAIN_MEMORY_STAT_AVAILABLE, 1024);
+
+    ret = 0;
+
+cleanup:
+    virJSONValueFree(statsdata);
+    return ret;
+}
+
 int qemuMonitorJSONGetObjectProperty(qemuMonitorPtr mon,
                                      const char *path,
                                      const char *property,
@@ -4689,6 +4761,9 @@ int qemuMonitorJSONGetObjectProperty(qemuMonitorPtr mon,
         if (tmp)
             ret = 0;
         break;
+    case QEMU_MONITOR_OBJECT_PROPERTY_BALLOON_STATS:
+        ret = qemuMonitorJSONGetBalloonStats(data, prop);
+        break;
     case QEMU_MONITOR_OBJECT_PROPERTY_LAST:
     default:
         virReportError(VIR_ERR_INTERNAL_ERROR,
@@ -4752,6 +4827,7 @@ int qemuMonitorJSONSetObjectProperty(qemuMonitorPtr mon,
     case QEMU_MONITOR_OBJECT_PROPERTY_STRING:
         MAKE_SET_CMD("s:value", prop->val.str);
         break;
+    case QEMU_MONITOR_OBJECT_PROPERTY_BALLOON_STATS:
     case QEMU_MONITOR_OBJECT_PROPERTY_LAST:
     default:
         virReportError(VIR_ERR_INTERNAL_ERROR,
-- 
1.8.1.4




More information about the libvir-list mailing list