[libvirt] [PATCH 3/6] qemu-driver: Enable domainMemStats in the qemu driver

Adam Litke agl at us.ibm.com
Tue Dec 8 19:57:17 UTC 2009


Support for memory statistics reporting is accepted for qemu inclusion.
Statistics are reported via the monitor command 'info balloon' as a comma
seprated list:

(qemu) info balloon
balloon: actual=1024,mem_swapped_in=0,mem_swapped_out=0,major_page_faults=88,minor_page_faults=105535,free_mem=1017065472,total_mem=1045229568

Libvirt, qemu, and the guest operating system may support a subset of the
statistics defined by the virtio spec.  Thus, only statistics recognized by all
components will be reported.  All others will be returned as -1.

Signed-off-by: Adam Litke <agl at us.ibm.com>
To: libvirt list <libvir-list at redhat.com>
---
 src/qemu/qemu_driver.c       |   40 +++++++++++++++++++++++++++--
 src/qemu/qemu_monitor_text.c |   56 ++++++++++++++++++++++++++++++++++++++++-
 src/qemu/qemu_monitor_text.h |    3 +-
 3 files changed, 93 insertions(+), 6 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 35c397d..60c0da1 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -3077,7 +3077,7 @@ static int qemudDomainGetInfo(virDomainPtr dom,
     info->maxMem = vm->def->maxmem;
 
     if (virDomainIsActive(vm)) {
-        err = qemuMonitorGetBalloonInfo(vm, &balloon);
+        err = qemuMonitorGetBalloonInfo(vm, &balloon, NULL);
         if (err < 0)
             goto cleanup;
 
@@ -3880,7 +3880,7 @@ static char *qemudDomainDumpXML(virDomainPtr dom,
 
     /* Refresh current memory based on balloon info */
     if (virDomainIsActive(vm)) {
-        err = qemuMonitorGetBalloonInfo(vm, &balloon);
+        err = qemuMonitorGetBalloonInfo(vm, &balloon, NULL);
         if (err < 0)
             goto cleanup;
         if (err > 0)
@@ -5563,6 +5563,40 @@ qemudDomainInterfaceStats (virDomainPtr dom,
 #endif
 
 static int
+qemudDomainMemStats (virDomainPtr dom,
+                     struct _virDomainMemStats *stats)
+{
+    struct qemud_driver *driver = dom->conn->privateData;
+    virDomainObjPtr vm;
+    struct _virDomainMemStats stats2 = { -1, -1, -1, -1, -1, -1 };
+    int ret = -1;
+
+    qemuDriverLock(driver);
+    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    qemuDriverUnlock(driver);
+
+    if (!vm) {
+        char uuidstr[VIR_UUID_STRING_BUFLEN];
+        virUUIDFormat(dom->uuid, uuidstr);
+        qemudReportError(dom->conn, dom, NULL, VIR_ERR_NO_DOMAIN,
+                         _("no domain with matching uuid '%s'"), uuidstr);
+        goto cleanup;
+    }
+
+    if (virDomainIsActive(vm)) {
+        memcpy (stats, &stats2, sizeof stats);
+        ret = qemuMonitorGetBalloonInfo(vm, NULL, stats);
+        if (ret > 0)
+            ret = 0;
+    }
+
+cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    return ret;
+}
+
+static int
 qemudDomainBlockPeek (virDomainPtr dom,
                       const char *path,
                       unsigned long long offset, size_t size,
@@ -7124,7 +7158,7 @@ static virDriver qemuDriver = {
     NULL, /* domainMigrateFinish */
     qemudDomainBlockStats, /* domainBlockStats */
     qemudDomainInterfaceStats, /* domainInterfaceStats */
-    NULL, /* domainMemStats */
+    qemudDomainMemStats, /* domainMemStats */
     qemudDomainBlockPeek, /* domainBlockPeek */
     qemudDomainMemoryPeek, /* domainMemoryPeek */
     nodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */
diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c
index 66526dc..f785f7c 100644
--- a/src/qemu/qemu_monitor_text.c
+++ b/src/qemu/qemu_monitor_text.c
@@ -650,6 +650,52 @@ error:
     return 0;
 }
 
+/* The reply from the 'info balloon' command may contain additional memory
+ * statistics in the form: '[,<tag>=<val>]*'
+ */
+static void qemuMonitorParseExtraBalloonInfo(const virDomainObjPtr vm,
+                                             char *text,
+                                             virDomainMemStatsPtr stats)
+{
+    char *dummy, *p = text;
+    while (*p) {
+        if (STRPREFIX (p, ",mem_swapped_in=")) {
+            p += 16;
+            if (virStrToLong_ull (p, &dummy, 10, &stats->swap_in))
+                DEBUG ("%s: error reading mem_swapped_in: %s",
+                       vm->def->name, p);
+        } else if (STRPREFIX (p, ",mem_swapped_out=")) {
+            p += 17;
+            if (virStrToLong_ull (p, &dummy, 10, &stats->swap_out))
+                DEBUG ("%s: error reading mem_swapped_out: %s",
+                       vm->def->name, p);
+        } else if (STRPREFIX (p, ",major_page_faults=")) {
+            p += 19;
+            if (virStrToLong_ull (p, &dummy, 10, &stats->major_fault))
+                DEBUG ("%s: error reading major_page_faults: %s",
+                       vm->def->name, p);
+        } else if (STRPREFIX (p, ",minor_page_faults=")) {
+            p += 19;
+            if (virStrToLong_ull (p, &dummy, 10, &stats->minor_fault))
+                DEBUG ("%s: error reading minor_page_faults: %s",
+                       vm->def->name, p);
+        } else if (STRPREFIX (p, ",free_mem=")) {
+            p += 10;
+            if (virStrToLong_ull (p, &dummy, 10, &stats->mem_free))
+                DEBUG ("%s: error reading free_mem: %s",
+                       vm->def->name, p);
+        } else if (STRPREFIX (p, ",total_mem=")) {
+            p += 11;
+            if (virStrToLong_ull (p, &dummy, 10, &stats->mem_tot))
+                DEBUG ("%s: error reading total_mem: %s",
+                       vm->def->name, p);
+        }
+
+        /* Skip to the next label */
+        p = strchr (p, ',');
+        if (!p) break;
+    }
+}
 
 
 /* The reply from QEMU contains 'ballon: actual=421' where value is in MB */
@@ -660,7 +706,8 @@ error:
  * or -1 on failure
  */
 int qemuMonitorGetBalloonInfo(const virDomainObjPtr vm,
-                              unsigned long *currmem)
+                              unsigned long *currmem,
+                              virDomainMemStatsPtr stats)
 {
     char *reply = NULL;
     int ret = -1;
@@ -683,7 +730,12 @@ int qemuMonitorGetBalloonInfo(const virDomainObjPtr vm,
                              _("could not parse memory balloon allocation from '%s'"), reply);
             goto cleanup;
         }
-        *currmem = memMB * 1024;
+        if (currmem != NULL)
+            *currmem = memMB * 1024;
+        offset = strchr(reply, ',');
+        if (stats != NULL && offset != NULL) {
+            qemuMonitorParseExtraBalloonInfo(vm, offset, stats);
+        }
         ret = 1;
     } else {
         /* We don't raise an error here, since its to be expected that
diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h
index 9175456..4e9b581 100644
--- a/src/qemu/qemu_monitor_text.h
+++ b/src/qemu/qemu_monitor_text.h
@@ -41,7 +41,8 @@ int qemuMonitorSystemPowerdown(const virDomainObjPtr vm);
 int qemuMonitorGetCPUInfo(const virDomainObjPtr vm,
                           int **pids);
 int qemuMonitorGetBalloonInfo(const virDomainObjPtr vm,
-                              unsigned long *currmem);
+                              unsigned long *currmem,
+                              virDomainMemStatsPtr stats);
 int qemuMonitorGetBlockStatsInfo(const virDomainObjPtr vm,
                                  const char *devname,
                                  long long *rd_req,
-- 
1.6.5




More information about the libvir-list mailing list