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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list