From e7a65dc77c360820cf5a0d0f4ca7921d326c3c1f Mon Sep 17 00:00:00 2001 From: Roman Bogorodskiy Date: Fri, 3 Jan 2014 22:35:50 +0400 Subject: [PATCH] BSD: implement nodeGetMemoryStats Add a BSD implementation of nodeGetMemoryStats based on sysctl(3). --- src/nodeinfo.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-) diff --git a/src/nodeinfo.c b/src/nodeinfo.c index 1838547417..05bc038134 100644 --- a/src/nodeinfo.c +++ b/src/nodeinfo.c @@ -96,7 +96,85 @@ appleFreebsdNodeGetMemorySize(unsigned long *memory) return 0; } -#endif +#endif /* defined(__FreeBSD__) || defined(__APPLE__) */ + +#ifdef __FreeBSD__ +# define BSD_MEMORY_STATS_ALL 4 + +static int +freebsdNodeGetMemoryStats(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, + _("sysctl failed for '%s'"), + sysctl_map[i].sysctl_name); + return -1; + } + + param = ¶ms[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 = ¶ms[j++]; + + if (sysctlbyname("vfs.bufspace", &bufpages, &bufpages_size, NULL, 0) < 0) { + virReportSystemError(errno, + _("sysctl failed for '%s'"), + "vfs.bufspace"); + 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 /* __FreeBSD__ */ #ifdef __linux__ # define CPUINFO_PATH "/proc/cpuinfo" @@ -1041,6 +1119,8 @@ int nodeGetMemoryStats(int cellNum ATTRIBUTE_UNUSED, return ret; } +#elif defined(__FreeBSD__) + return freebsdNodeGetMemoryStats(params, nparams); #else virReportError(VIR_ERR_NO_SUPPORT, "%s", _("node memory stats not implemented on this platform"));