[libvirt] [PATCH] BSD: implement nodeGetMemoryStats

Roman Bogorodskiy bogorodskiy at gmail.com
Thu Jan 2 15:35:53 UTC 2014


Add a BSD implementation of nodeGetMemoryStats based
on sysctl(3).
---
 src/nodeinfo.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 73 insertions(+)

diff --git a/src/nodeinfo.c b/src/nodeinfo.c
index 1838547..ecacfa4 100644
--- a/src/nodeinfo.c
+++ b/src/nodeinfo.c
@@ -55,6 +55,8 @@
 #define VIR_FROM_THIS VIR_FROM_NONE
 
 #if defined(__FreeBSD__) || defined(__APPLE__)
+# define BSD_MEMORY_STATS_ALL 4
+
 static int
 appleFreebsdNodeGetCPUCount(void)
 {
@@ -96,6 +98,75 @@ appleFreebsdNodeGetMemorySize(unsigned long *memory)
 
     return 0;
 }
+
+static int
+appleFreebsdNodeGetMemoryStats(virNodeMemoryStatsPtr params,
+                               int *nparams)
+{
+    size_t i, j = 0;
+    unsigned long pagesize = getpagesize() >> 10;
+    long bufpages;
+    size_t bufpages_size = sizeof(bufpages);
+    struct field_sysctl_map {
+        const char *field;
+        const char *sysctl_name;
+    } sysctl_map[] = {
+        {VIR_NODE_MEMORY_STATS_TOTAL, "vm.stats.vm.v_page_count"},
+        {VIR_NODE_MEMORY_STATS_FREE, "vm.stats.vm.v_free_count"},
+        {VIR_NODE_MEMORY_STATS_CACHED, "vm.stats.vm.v_cache_count"},
+        {NULL, NULL}
+    };
+
+    if ((*nparams) == 0) {
+        *nparams = BSD_MEMORY_STATS_ALL;
+        return 0;
+    }
+
+    if ((*nparams) != BSD_MEMORY_STATS_ALL) {
+        virReportInvalidArg(nparams,
+                            _("nparams in %s must be %d"),
+                            __FUNCTION__, BSD_MEMORY_STATS_ALL);
+        return -1;
+    }
+
+    for (i = 0; sysctl_map[i].field != NULL; i++) {
+        u_int value;
+        size_t value_size = sizeof(value);
+        virNodeMemoryStatsPtr param;
+
+        if (sysctlbyname(sysctl_map[i].sysctl_name, &value,
+                         &value_size, NULL, 0) < 0) {
+            virReportSystemError(errno, "%s", _("sysctl failed"));
+            return -1;
+        }
+
+        param = &params[j++];
+        if (virStrcpyStatic(param->field, sysctl_map[i].field) == NULL) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Field '%s' too long for destination"),
+                           sysctl_map[i].field);
+            return -1;
+        }
+        param->value = (unsigned long long)value * pagesize;
+    }
+
+    {
+        virNodeMemoryStatsPtr param = &params[j];
+
+        if (sysctlbyname("vfs.bufspace", &bufpages, &bufpages_size, NULL, 0) < 0) {
+            return -1;
+        }
+        if (virStrcpyStatic(param->field, VIR_NODE_MEMORY_STATS_BUFFERS) == NULL) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Field '%s' too long for destination"),
+                           VIR_NODE_MEMORY_STATS_BUFFERS);
+            return -1;
+        }
+        param->value = (unsigned long long)bufpages >> 10;
+    }
+
+    return 0;
+}
 #endif
 
 #ifdef __linux__
@@ -1041,6 +1112,8 @@ int nodeGetMemoryStats(int cellNum ATTRIBUTE_UNUSED,
 
         return ret;
     }
+#elif defined(__FreeBSD__) || defined(__APPLE__)
+    return appleFreebsdNodeGetMemoryStats(params, nparams);
 #else
     virReportError(VIR_ERR_NO_SUPPORT, "%s",
                    _("node memory stats not implemented on this platform"));
-- 
1.8.4.3




More information about the libvir-list mailing list