Only implemented for linux platform. * src/nodeinfo.h: (Declare node{Get,Set}SharedMemoryParameters) * src/nodeinfo.c: (Implement node{Get,Set}SharedMemoryParameters) * src/libvirt_private.syms: (Export those two new internal APIs to private symbols) --- src/libvirt_private.syms | 2 + src/nodeinfo.c | 344 ++++++++++++++++++++++++++++++++++++++++++++++ src/nodeinfo.h | 10 ++ 3 files changed, 356 insertions(+), 0 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 10af063..b6f3d84 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -878,6 +878,8 @@ nodeGetCellsFreeMemory; nodeGetFreeMemory; nodeGetInfo; nodeGetMemoryStats; +nodeGetSharedMemoryParameters; +nodeSetSharedMemoryParameters; # nwfilter_conf.h diff --git a/src/nodeinfo.c b/src/nodeinfo.c index e3d4a24..b7560b0 100644 --- a/src/nodeinfo.c +++ b/src/nodeinfo.c @@ -48,6 +48,7 @@ #include "count-one-bits.h" #include "intprops.h" #include "virfile.h" +#include "virtypedparam.h" #define VIR_FROM_THIS VIR_FROM_NONE @@ -57,6 +58,7 @@ # define SYSFS_SYSTEM_PATH "/sys/devices/system" # define PROCSTAT_PATH "/proc/stat" # define MEMINFO_PATH "/proc/meminfo" +# define SYSFS_SHARED_MEMORY_PATH "/sys/kernel/mm/ksm" # define LINUX_NB_CPU_STATS 4 # define LINUX_NB_MEMORY_STATS_ALL 4 @@ -933,6 +935,348 @@ nodeGetCPUmap(virConnectPtr conn ATTRIBUTE_UNUSED, #endif } +int +nodeSetSharedMemoryParameters(virConnectPtr conn ATTRIBUTE_UNUSED, + virTypedParameterPtr params, + int nparams, + unsigned int flags) +{ + virCheckFlags(0, -1); + +#ifdef __linux__ + { + int ret = 0; + int rc; + int i; + + if (virTypedParameterArrayValidate(params, nparams, + VIR_NODE_SHARED_MEMORY_PAGES_TO_SCAN, + VIR_TYPED_PARAM_UINT, + VIR_NODE_SHARED_MEMORY_SLEEP_MILLISECS, + VIR_TYPED_PARAM_UINT, + NULL) < 0) + return -1; + + if (!virFileExists(SYSFS_SHARED_MEMORY_PATH)) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("shared memory is not enabled on this host")); + return -1; + } + + for (i = 0; i < nparams; i++) { + virTypedParameterPtr param = ¶ms[i]; + + if (STREQ(param->field, + VIR_NODE_SHARED_MEMORY_PAGES_TO_SCAN)) { + char *pages_to_scan = NULL; + char *strval = NULL; + + if (virAsprintf(&pages_to_scan, "%s/%s", + SYSFS_SHARED_MEMORY_PATH, + VIR_NODE_SHARED_MEMORY_PAGES_TO_SCAN) < 0) { + virReportOOMError(); + return -1; + } + + if (virAsprintf(&strval, "%u", param->value.ui) == -1) { + virReportOOMError(); + VIR_FREE(pages_to_scan); + return -1; + } + + if ((rc = virFileWriteStr(pages_to_scan, strval, 0)) < 0) { + virReportSystemError(-rc, "%s", + _("failed to set pages_to_scan")); + ret = -1; + } + VIR_FREE(pages_to_scan); + VIR_FREE(strval); + } else if (STREQ(param->field, + VIR_NODE_SHARED_MEMORY_SLEEP_MILLISECS)) { + char *sleep_millisecs = NULL; + char *strval = NULL; + + if (virAsprintf(&sleep_millisecs, "%s/%s", + SYSFS_SHARED_MEMORY_PATH, + VIR_NODE_SHARED_MEMORY_SLEEP_MILLISECS) < 0) { + virReportOOMError(); + return -1; + } + + if (virAsprintf(&strval, "%u", param->value.ui) == -1) { + virReportOOMError(); + VIR_FREE(sleep_millisecs); + return -1; + } + + if ((rc = virFileWriteStr(sleep_millisecs, strval, 0)) < 0) { + virReportSystemError(-rc, "%s", + _("failed to set pages_to_scan")); + ret = -1; + } + VIR_FREE(sleep_millisecs); + VIR_FREE(strval); + } + } + + return ret; + } +#else + virReportError(VIR_ERR_NO_SUPPORT, "%s", + _("node set shared memory parameters not implemented" + " on this platform")); + return -1; +#endif +} + +#define NODE_SHARED_MEMORY_PARAMETERS_NUM 7 +int +nodeGetSharedMemoryParameters(virConnectPtr conn ATTRIBUTE_UNUSED, + virTypedParameterPtr params, + int *nparams, + unsigned int flags) +{ + virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1); + +#ifdef __linux__ + { + char *path = NULL; + char *buf = NULL; + unsigned int pages_to_scan; + unsigned int sleep_millisecs; + unsigned long long pages_shared; + unsigned long long pages_sharing; + unsigned long long pages_unshared; + unsigned long long pages_volatile; + unsigned long long full_scans = 0; + int ret = -1; + int i; + + if (!virFileExists(SYSFS_SHARED_MEMORY_PATH)) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("shared memory is not enabled on this host")); + return -1; + } + + if ((*nparams) == 0) { + *nparams = NODE_SHARED_MEMORY_PARAMETERS_NUM; + return 0; + } + + for (i = 0; i < *nparams && i < NODE_SHARED_MEMORY_PARAMETERS_NUM; i++) { + virTypedParameterPtr param = ¶ms[i]; + char *tmp = NULL; + + switch(i) { + case 0: + if (virAsprintf(&path, "%s/%s", SYSFS_SHARED_MEMORY_PATH, + VIR_NODE_SHARED_MEMORY_PAGES_TO_SCAN) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (virFileReadAll(path, 1024, &buf) < 0) + goto cleanup; + + if ((tmp = strchr(buf, '\n'))) + *tmp = '\0'; + + if (virStrToLong_ui(buf, NULL, 10, &pages_to_scan) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to parse pages_to_scan")); + goto cleanup; + } + + if (virTypedParameterAssign(param, VIR_NODE_SHARED_MEMORY_PAGES_TO_SCAN, + VIR_TYPED_PARAM_UINT, pages_to_scan) < 0) + goto cleanup; + + VIR_FREE(path); + VIR_FREE(buf); + break; + + case 1: + if (virAsprintf(&path, "%s/%s", SYSFS_SHARED_MEMORY_PATH, + VIR_NODE_SHARED_MEMORY_SLEEP_MILLISECS) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (virFileReadAll(path, 1024, &buf) < 0) + goto cleanup; + + if ((tmp = strchr(buf, '\n'))) + *tmp = '\0'; + + if (virStrToLong_ui(buf, NULL, 10, &sleep_millisecs) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to parse sleep_millisecs")); + goto cleanup; + } + + if (virTypedParameterAssign(param, VIR_NODE_SHARED_MEMORY_SLEEP_MILLISECS, + VIR_TYPED_PARAM_UINT, sleep_millisecs) < 0) + goto cleanup; + + VIR_FREE(path); + VIR_FREE(buf); + break; + + case 2: + if (virAsprintf(&path, "%s/%s", SYSFS_SHARED_MEMORY_PATH, + VIR_NODE_SHARED_MEMORY_PAGES_SHARED) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (virFileReadAll(path, 1024, &buf) < 0) + goto cleanup; + + if ((tmp = strchr(buf, '\n'))) + *tmp = '\0'; + + if (virStrToLong_ull(buf, NULL, 10, &pages_shared) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to parse pages_shared")); + goto cleanup; + } + + if (virTypedParameterAssign(param, VIR_NODE_SHARED_MEMORY_PAGES_SHARED, + VIR_TYPED_PARAM_ULLONG, pages_shared) < 0) + goto cleanup; + + VIR_FREE(path); + VIR_FREE(buf); + break; + + case 3: + if (virAsprintf(&path, "%s/%s", SYSFS_SHARED_MEMORY_PATH, + VIR_NODE_SHARED_MEMORY_PAGES_SHARING) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (virFileReadAll(path, 1024, &buf) < 0) + goto cleanup; + + if ((tmp = strchr(buf, '\n'))) + *tmp = '\0'; + + if (virStrToLong_ull(buf, NULL, 10, &pages_sharing) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to parse pages_sharing")); + goto cleanup; + } + + if (virTypedParameterAssign(param, VIR_NODE_SHARED_MEMORY_PAGES_SHARING, + VIR_TYPED_PARAM_ULLONG, pages_sharing) < 0) + goto cleanup; + + VIR_FREE(path); + VIR_FREE(buf); + break; + + case 4: + if (virAsprintf(&path, "%s/%s", SYSFS_SHARED_MEMORY_PATH, + VIR_NODE_SHARED_MEMORY_PAGES_UNSHARED) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (virFileReadAll(path, 1024, &buf) < 0) + goto cleanup; + + if ((tmp = strchr(buf, '\n'))) + *tmp = '\0'; + + if (virStrToLong_ull(buf, NULL, 10, &pages_unshared) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to parse pages_unshared")); + goto cleanup; + } + + if (virTypedParameterAssign(param, VIR_NODE_SHARED_MEMORY_PAGES_UNSHARED, + VIR_TYPED_PARAM_ULLONG, pages_unshared) < 0) + goto cleanup; + + VIR_FREE(path); + VIR_FREE(buf); + break; + + case 5: + if (virAsprintf(&path, "%s/%s", SYSFS_SHARED_MEMORY_PATH, + VIR_NODE_SHARED_MEMORY_PAGES_VOLATILE) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (virFileReadAll(path, 1024, &buf) < 0) + goto cleanup; + + if ((tmp = strchr(buf, '\n'))) + *tmp = '\0'; + + if (virStrToLong_ull(buf, NULL, 10, &pages_volatile) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to parse pages_volatile")); + goto cleanup; + } + + if (virTypedParameterAssign(param, VIR_NODE_SHARED_MEMORY_PAGES_VOLATILE, + VIR_TYPED_PARAM_ULLONG, pages_volatile) < 0) + goto cleanup; + + VIR_FREE(path); + VIR_FREE(buf); + break; + + case 6: + if (virAsprintf(&path, "%s/%s", SYSFS_SHARED_MEMORY_PATH, + VIR_NODE_SHARED_MEMORY_FULL_SCANS) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (virFileReadAll(path, 1024, &buf) < 0) + goto cleanup; + + if ((tmp = strchr(buf, '\n'))) + *tmp = '\0'; + + if (virStrToLong_ull(buf, NULL, 10, &full_scans) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to parse full_scans")); + goto cleanup; + } + + if (virTypedParameterAssign(param, VIR_NODE_SHARED_MEMORY_FULL_SCANS, + VIR_TYPED_PARAM_ULLONG, full_scans) < 0) + goto cleanup; + + VIR_FREE(path); + VIR_FREE(buf); + break; + + default: + break; + } + } + + ret = 0; + + cleanup: + VIR_FREE(path); + VIR_FREE(buf); + return ret; + } +#else + virReportError(VIR_ERR_NO_SUPPORT, "%s", + _("node get shared memory parameters 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 12090e2..fa9e49f 100644 --- a/src/nodeinfo.h +++ b/src/nodeinfo.h @@ -49,4 +49,14 @@ unsigned long long nodeGetFreeMemory(virConnectPtr conn); char *nodeGetCPUmap(virConnectPtr conn, int *max_id, const char *mapname); + +int nodeGetSharedMemoryParameters(virConnectPtr conn, + virTypedParameterPtr params, + int *nparams, + unsigned int flags); + +int nodeSetSharedMemoryParameters(virConnectPtr conn, + virTypedParameterPtr params, + int nparams, + unsigned int flags); #endif /* __VIR_NODEINFO_H__*/ -- 1.7.7.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list