[libvirt] [PATCH 6/6] virNodeGetMemoryStats: Implement linux support

Minoru Usui usui at mxm.nes.nec.co.jp
Wed May 25 09:03:57 UTC 2011


virNodeGetMemoryStats: Implement linux support

Signed-off-by: Minoru Usui <usui at mxm.nes.nec.co.jp>
---
 src/libvirt_private.syms |    1 +
 src/lxc/lxc_driver.c     |    1 +
 src/nodeinfo.c           |   97 ++++++++++++++++++++++++++++++++++++++++++++++
 src/nodeinfo.h           |    4 ++
 src/qemu/qemu_driver.c   |    1 +
 src/uml/uml_driver.c     |    1 +
 6 files changed, 105 insertions(+), 0 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 4cb8dda..5e55cf1 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -689,6 +689,7 @@ virNodeDeviceObjUnlock;
 
 # nodeinfo.h
 nodeCapsInitNUMA;
+nodeGetMemoryStats;
 nodeGetCellsFreeMemory;
 nodeGetFreeMemory;
 nodeGetInfo;
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index 9e09c95..41b6260 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -2754,6 +2754,7 @@ static virDriver lxcDriver = {
     .domainGetSchedulerParameters = lxcGetSchedulerParameters, /* 0.5.0 */
     .domainSetSchedulerParameters = lxcSetSchedulerParameters, /* 0.5.0 */
     .domainInterfaceStats = lxcDomainInterfaceStats, /* 0.7.3 */
+    .nodeGetMemoryStats = nodeGetMemoryStats, /* 0.9.2 */
     .nodeGetCellsFreeMemory = nodeGetCellsFreeMemory, /* 0.6.5 */
     .nodeGetFreeMemory = nodeGetFreeMemory, /* 0.6.5 */
     .domainEventRegister = lxcDomainEventRegister, /* 0.7.0 */
diff --git a/src/nodeinfo.c b/src/nodeinfo.c
index f55c83e..63d7822 100644
--- a/src/nodeinfo.c
+++ b/src/nodeinfo.c
@@ -57,11 +57,17 @@
 #ifdef __linux__
 # define CPUINFO_PATH "/proc/cpuinfo"
 # define CPU_SYS_PATH "/sys/devices/system/cpu"
+# define MEMINFO_PATH "/proc/meminfo"
+
+# define LINUX_NB_MEMORY_STATS 4
 
 /* NB, this is not static as we need to call it from the testsuite */
 int linuxNodeInfoCPUPopulate(FILE *cpuinfo,
                              virNodeInfoPtr nodeinfo,
                              bool need_hyperthreads);
+int linuxNodeGetMemoryStats(FILE *meminfo,
+                            virMemoryStatsPtr params,
+                            int *nparams);
 
 /* Return the positive decimal contents of the given
  * CPU_SYS_PATH/cpu%u/FILE, or -1 on error.  If MISSING_OK and the
@@ -378,6 +384,71 @@ int linuxNodeInfoCPUPopulate(FILE *cpuinfo,
     return 0;
 }
 
+int linuxNodeGetMemoryStats(FILE *meminfo,
+                            virMemoryStatsPtr params,
+                            int *nparams)
+{
+    int ret = -1;
+    int i = 0, j = 0;
+    char line[1024];
+    char meminfo_hdr[VIR_MEMORY_STATS_FIELD_LENGTH];
+    unsigned long val;
+    struct field_conv {
+        const char *meminfo_hdr;  // meminfo header
+        const char *field;        // MemoryStats field name
+    } field_conv[] = {
+        {"MemTotal:", VIR_MEMORY_STATS_TOTAL},
+        {"MemFree:",  VIR_MEMORY_STATS_FREE},
+        {"Buffers:",  VIR_MEMORY_STATS_BUFFERS},
+        {"Cached:",   VIR_MEMORY_STATS_CACHED},
+        {NULL,        NULL}
+    };
+
+    if ((*nparams) == 0) {
+        /* Current number of memory stats supported by linux */
+        *nparams = LINUX_NB_MEMORY_STATS;
+        ret = 0;
+        goto cleanup;
+    }
+
+    if ((*nparams) != LINUX_NB_MEMORY_STATS) {
+        nodeReportError(VIR_ERR_INVALID_ARG,
+                        "%s", _("Invalid stats count"));
+        goto cleanup;
+    }
+
+    while (fgets(line, sizeof(line), meminfo) != NULL) {
+        char *buf = line;
+
+        if (sscanf(buf, "%s %lu kB", meminfo_hdr, &val) < 2) {
+                continue;
+        }
+
+        for (j = 0; field_conv[j].meminfo_hdr != NULL; j++) {
+            struct field_conv *convp = &field_conv[j];
+
+            if (STREQ(meminfo_hdr, convp->meminfo_hdr)) {
+                virMemoryStatsPtr param = &params[i++];
+
+                if (virStrcpyStatic(param->field, convp->field) == NULL) {
+                    nodeReportError(VIR_ERR_INTERNAL_ERROR,
+                                    "%s", _("Field kernel memory too long for destination"));
+                    goto cleanup;
+                }
+                param->value = val;
+                break;
+            }
+        }
+    }
+
+    ret = 0;
+    goto cleanup;
+
+    nodeReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no \'cpu \' line found"));
+
+cleanup:
+    return ret;
+}
 #endif
 
 int nodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED, virNodeInfoPtr nodeinfo) {
@@ -416,6 +487,32 @@ int nodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED, virNodeInfoPtr nodeinfo) {
 #endif
 }
 
+int nodeGetMemoryStats(virConnectPtr conn ATTRIBUTE_UNUSED,
+                       virMemoryStatsPtr params,
+                       int *nparams,
+                       unsigned int flags ATTRIBUTE_UNUSED)
+{
+#ifdef __linux__
+    {
+    int ret;
+    FILE *meminfo = fopen(MEMINFO_PATH, "r");
+    if (!meminfo) {
+        virReportSystemError(errno,
+                             _("cannot open %s"), MEMINFO_PATH);
+        return -1;
+    }
+    ret = linuxNodeGetMemoryStats(meminfo, params, nparams);
+    VIR_FORCE_FCLOSE(meminfo);
+
+    return ret;
+    }
+#else
+    nodeReportError(VIR_ERR_NO_SUPPORT, "%s",
+                    _("node memory stats not implemented on this platform"));
+    return -1;
+#endif
+}
+
 #if HAVE_NUMACTL
 # if LIBNUMA_API_VERSION <= 1
 #  define NUMA_MAX_N_CPUS 4096
diff --git a/src/nodeinfo.h b/src/nodeinfo.h
index 88bac6c..6e69f76 100644
--- a/src/nodeinfo.h
+++ b/src/nodeinfo.h
@@ -28,6 +28,10 @@
 # include "capabilities.h"
 
 int nodeGetInfo(virConnectPtr conn, virNodeInfoPtr nodeinfo);
+int nodeGetMemoryStats(virConnectPtr conn ATTRIBUTE_UNUSED,
+                       virMemoryStatsPtr params,
+                       int *nparams,
+                       unsigned int flags ATTRIBUTE_UNUSED);
 int nodeCapsInitNUMA(virCapsPtr caps);
 
 
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 576393e..cc930c8 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -7734,6 +7734,7 @@ static virDriver qemuDriver = {
     .domainBlockPeek = qemudDomainBlockPeek, /* 0.4.4 */
     .domainMemoryPeek = qemudDomainMemoryPeek, /* 0.4.4 */
     .domainGetBlockInfo = qemuDomainGetBlockInfo, /* 0.8.1 */
+    .nodeGetMemoryStats = nodeGetMemoryStats, /* 0.9.2 */
     .nodeGetCellsFreeMemory = nodeGetCellsFreeMemory, /* 0.4.4 */
     .nodeGetFreeMemory = nodeGetFreeMemory, /* 0.4.4 */
     .domainEventRegister = qemuDomainEventRegister, /* 0.5.0 */
diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c
index 536cd8c..6987d05 100644
--- a/src/uml/uml_driver.c
+++ b/src/uml/uml_driver.c
@@ -2218,6 +2218,7 @@ static virDriver umlDriver = {
     .domainGetAutostart = umlDomainGetAutostart, /* 0.5.0 */
     .domainSetAutostart = umlDomainSetAutostart, /* 0.5.0 */
     .domainBlockPeek = umlDomainBlockPeek, /* 0.5.0 */
+    .nodeGetMemoryStats = nodeGetMemoryStats, /* 0.9.2 */
     .nodeGetCellsFreeMemory = nodeGetCellsFreeMemory, /* 0.5.0 */
     .nodeGetFreeMemory = nodeGetFreeMemory, /* 0.5.0 */
     .isEncrypted = umlIsEncrypted, /* 0.7.3 */
-- 
1.7.1




More information about the libvir-list mailing list