[libvirt] [PATCH v2] BSD: implement nodeGetMemoryStats

Add a BSD implementation of nodeGetMemoryStats based on sysctl(3). --- src/nodeinfo.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) diff --git a/src/nodeinfo.c b/src/nodeinfo.c index 1838547..5e84e78 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,7 +98,81 @@ appleFreebsdNodeGetMemorySize(unsigned long *memory) return 0; } -#endif + +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, + _("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 /* defined(__FreeBSD__) || defined(__APPLE__) */ #ifdef __linux__ # define CPUINFO_PATH "/proc/cpuinfo" @@ -1041,6 +1117,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

Hi Roman, Unfortunately Mac OS X doesn't has the sysctl MIBs. So ifdef __APPLE__ should be dropped. I still don't know the correct API for that purpose though, host_statistics seems to be used according to http://stackoverflow.com/questions/6094444 . ozaki-r On Sat, Jan 4, 2014 at 12:13 AM, Roman Bogorodskiy <bogorodskiy@gmail.com> wrote:
Add a BSD implementation of nodeGetMemoryStats based on sysctl(3). --- src/nodeinfo.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-)
diff --git a/src/nodeinfo.c b/src/nodeinfo.c index 1838547..5e84e78 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,7 +98,81 @@ appleFreebsdNodeGetMemorySize(unsigned long *memory)
return 0; } -#endif + +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, + _("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 /* defined(__FreeBSD__) || defined(__APPLE__) */
#ifdef __linux__ # define CPUINFO_PATH "/proc/cpuinfo" @@ -1041,6 +1117,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
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list

Ryota Ozaki wrote:
Hi Roman,
Unfortunately Mac OS X doesn't has the sysctl MIBs. So ifdef __APPLE__ should be dropped.
I still don't know the correct API for that purpose though, host_statistics seems to be used according to http://stackoverflow.com/questions/6094444 .
Hi, Thanks for checking that. I'll re-roll the patch then. Roman Bogorodskiy
participants (2)
-
Roman Bogorodskiy
-
Ryota Ozaki