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