summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPeter Schiffer <pschiffe@redhat.com>2013-04-30 15:09:33 +0200
committerPeter Schiffer <pschiffe@redhat.com>2013-04-30 16:58:58 +0200
commitb2d1d95ef4b0812aca631d11c2b08946c73203c8 (patch)
treed4943199a06715e1c8119c77ec71b265968eaf58 /src
parent9d055e9cec6a305d553fd88e74345d75f10fab1e (diff)
downloadopenlmi-providers-b2d1d95ef4b0812aca631d11c2b08946c73203c8.tar.gz
openlmi-providers-b2d1d95ef4b0812aca631d11c2b08946c73203c8.tar.xz
openlmi-providers-b2d1d95ef4b0812aca631d11c2b08946c73203c8.zip
Hardware: Added additional information to the Memory provider
Added information: * detect NUMA layout * standard memory page size * all supported sizes of huge memory pages * current state of transparent huge pages
Diffstat (limited to 'src')
-rw-r--r--src/hardware/LMI_MemoryProvider.c25
-rw-r--r--src/hardware/dmidecode.c4
-rw-r--r--src/hardware/sysfs.c107
-rw-r--r--src/hardware/sysfs.h36
4 files changed, 168 insertions, 4 deletions
diff --git a/src/hardware/LMI_MemoryProvider.c b/src/hardware/LMI_MemoryProvider.c
index 0d77c17..4f2ab7f 100644
--- a/src/hardware/LMI_MemoryProvider.c
+++ b/src/hardware/LMI_MemoryProvider.c
@@ -19,11 +19,15 @@
*/
#include <konkret/konkret.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <limits.h>
#include "LMI_Memory.h"
#include "LMI_Hardware.h"
#include "globals.h"
#include "dmidecode.h"
#include "procfs.h"
+#include "sysfs.h"
static const CMPIBroker* _cb = NULL;
@@ -59,8 +63,10 @@ static CMPIStatus LMI_MemoryEnumInstances(
LMI_Memory lmi_mem;
const char *ns = KNameSpace(cop), *name = "System Memory";
char *error_msg = NULL;
+ long page_size;
unsigned long fallback_memory_size = 0;
DmiMemory dmi_memory;
+ unsigned i, *huge_page_sizes = NULL, huge_page_sizes_nb;
if (dmi_get_memory(&dmi_memory) != 0) {
fallback_memory_size = meminfo_get_memory_size();
@@ -70,6 +76,9 @@ static CMPIStatus LMI_MemoryEnumInstances(
}
}
+ page_size = sysconf(_SC_PAGESIZE);
+ sysfs_get_sizes_of_hugepages(&huge_page_sizes, &huge_page_sizes_nb);
+
LMI_Memory_Init(&lmi_mem, _cb, ns);
LMI_Memory_Set_SystemCreationClassName(&lmi_mem,
@@ -107,10 +116,26 @@ static CMPIStatus LMI_MemoryEnumInstances(
LMI_Memory_Set_NumberOfBlocks(&lmi_mem, fallback_memory_size);
}
+ LMI_Memory_Set_HasNUMA(&lmi_mem, sysfs_has_numa());
+ if (page_size > 0) {
+ LMI_Memory_Set_StandardMemoryPageSize(&lmi_mem, page_size / 1024);
+ }
+ if (huge_page_sizes_nb > 0) {
+ LMI_Memory_Init_SupportedHugeMemoryPageSizes(&lmi_mem,
+ huge_page_sizes_nb);
+ for (i = 0; i < huge_page_sizes_nb; i++) {
+ LMI_Memory_Set_SupportedHugeMemoryPageSizes(&lmi_mem, i,
+ huge_page_sizes[i]);
+ }
+ }
+ LMI_Memory_Set_TransparentHugeMemoryPageStatus(&lmi_mem,
+ sysfs_get_transparent_hugepages_status());
+
KReturnInstance(cr, lmi_mem);
done:
dmi_free_memory(&dmi_memory);
+ free(huge_page_sizes);
if (error_msg) {
KReturn2(_cb, ERR_FAILED, error_msg);
diff --git a/src/hardware/dmidecode.c b/src/hardware/dmidecode.c
index f034b56..dfff7e3 100644
--- a/src/hardware/dmidecode.c
+++ b/src/hardware/dmidecode.c
@@ -439,7 +439,7 @@ void dmi_free_processors(DmiProcessor **cpus, unsigned *cpus_nb)
free((*cpus)[i].part_number);
(*cpus)[i].part_number = NULL;
}
- free (*cpus);
+ free(*cpus);
}
*cpus_nb = 0;
@@ -686,7 +686,7 @@ void dmi_free_cpu_caches(DmiCpuCache **caches, unsigned *caches_nb)
free((*caches)[i].associativity);
(*caches)[i].associativity = NULL;
}
- free (*caches);
+ free(*caches);
}
*caches_nb = 0;
diff --git a/src/hardware/sysfs.c b/src/hardware/sysfs.c
index d07df71..80d360e 100644
--- a/src/hardware/sysfs.c
+++ b/src/hardware/sysfs.c
@@ -149,11 +149,11 @@ short sysfs_get_cpu_caches(SysfsCpuCache **caches, unsigned *caches_nb)
short ret = -1;
unsigned i, level;
char *buf = NULL, *format_str, path[PATH_MAX];
- DIR *dir;
*caches_nb = 0;
/* count caches */
+ DIR *dir;
char *cache_dir = SYSFS_CPU_PATH "/cpu0/cache";
dir = opendir(cache_dir);
if (!dir) {
@@ -285,3 +285,108 @@ void sysfs_free_cpu_caches(SysfsCpuCache **caches, unsigned *caches_nb)
*caches_nb = 0;
*caches = NULL;
}
+
+short sysfs_has_numa()
+{
+ struct stat st;
+
+ if (stat(SYSFS_PATH "/node/node0", &st) == 0) {
+ return 1;
+ }
+
+ return 0;
+}
+
+short sysfs_get_sizes_of_hugepages(unsigned **sizes, unsigned *sizes_nb)
+{
+ short ret = -1;
+ DIR *dir;
+
+ *sizes_nb = 0;
+ *sizes = NULL;
+
+ /* count all sizes */
+ char *sizes_dir = SYSFS_KERNEL_MM "/hugepages";
+ dir = opendir(sizes_dir);
+ if (!dir) {
+ warn("Failed to read directory: \"%s\"; Error: %s",
+ sizes_dir, strerror(errno));
+ ret = -2;
+ goto done;
+ }
+ while (readdir(dir)) {
+ (*sizes_nb)++;
+ }
+
+ /* do not count . and .. */
+ *sizes_nb -= 2;
+
+ /* if no size was found */
+ if (*sizes_nb < 1) {
+ warn("Looks like kernel doesn't support huge memory pages.");
+ ret = -3;
+ goto done;
+ }
+
+ /* allocate memory for sizes */
+ *sizes = (unsigned *)calloc(*sizes_nb, sizeof(unsigned));
+ if (!(*sizes)) {
+ warn("Failed to allocate memory.");
+ ret = -4;
+ goto done;
+ }
+
+ /* get sizes */
+ struct dirent *d;
+ unsigned i = 0;
+ rewinddir(dir);
+ while ((d = readdir(dir)) && i < *sizes_nb) {
+ if (strcmp(d->d_name, ".") == 0 || strcmp(d->d_name, "..") == 0) {
+ continue;
+ }
+ if (strlen(d->d_name) > 11) {
+ /* read page size from the dirname, which looks like: hugepages-2048kB */
+ if (sscanf(d->d_name + 10, "%u", &(*sizes)[i]) == 1) {
+ i++;
+ }
+ }
+ }
+
+ ret = 0;
+
+done:
+ if (dir) {
+ closedir(dir);
+ }
+
+ if (ret != 0) {
+ *sizes_nb = 0;
+ free(*sizes);
+ *sizes = NULL;
+ }
+
+ return ret;
+}
+
+ThpStatus sysfs_get_transparent_hugepages_status()
+{
+ ThpStatus ret = thp_unsupported;
+ char *val = NULL;
+
+ if (path_get_string(SYSFS_KERNEL_MM "/transparent_hugepage/enabled", &val) != 0) {
+ goto done;
+ }
+
+ if (strstr(val, "[always]")) {
+ ret = thp_always;
+ } else if (strstr(val, "[madvise]")) {
+ ret = thp_madvise;
+ } else if (strstr(val, "[never]")) {
+ ret = thp_never;
+ }
+
+done:
+ free(val);
+
+ return ret;
+}
diff --git a/src/hardware/sysfs.h b/src/hardware/sysfs.h
index 028b559..297a1a7 100644
--- a/src/hardware/sysfs.h
+++ b/src/hardware/sysfs.h
@@ -27,9 +27,23 @@
#include <dirent.h>
#include <errno.h>
#include <limits.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include "utils.h"
-#define SYSFS_CPU_PATH "/sys/devices/system/cpu"
+#define SYSFS_PATH "/sys/devices/system"
+#define SYSFS_CPU_PATH SYSFS_PATH "/cpu"
+#define SYSFS_KERNEL_MM "/sys/kernel/mm"
+
+
+/* Transparent memory huge pages statuses. */
+typedef enum _ThpStatus {
+ thp_unsupported = 0,
+ thp_never,
+ thp_madvise,
+ thp_always
+} ThpStatus;
+
/* Processor cache from sysfs. */
typedef struct _SysfsCpuCache {
@@ -59,5 +73,25 @@ short sysfs_get_cpu_caches(SysfsCpuCache **caches, unsigned *caches_nb);
*/
void sysfs_free_cpu_caches(SysfsCpuCache **caches, unsigned *caches_nb);
+/*
+ * Detects whether system has NUMA memory layout.
+ * @return 0 if no, 1 if yes
+ */
+short sysfs_has_numa();
+
+/*
+ * Get all supported sizes of memory huge pages in kB
+ * @param sizes array of all supported sizes if huge pages
+ * @param sizes_nb number of items in array
+ * @return 0 if success, negative value otherwise
+ */
+short sysfs_get_sizes_of_hugepages(unsigned **sizes, unsigned *sizes_nb);
+
+/*
+ * Get current status of transparent memory huge pages.
+ * @return ThpStatus
+ */
+ThpStatus sysfs_get_transparent_hugepages_status();
+
#endif /* SYSFS_H_ */