2 * collectd - src/hugepages.c
5 * Copyright(c) 2016 Intel Corporation. All rights reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a copy of
8 * this software and associated documentation files (the "Software"), to deal in
9 * the Software without restriction, including without limitation the rights to
10 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
11 * of the Software, and to permit persons to whom the Software is furnished to do
12 * so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in all
15 * copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 * Jaroslav Safka <jaroslavx.safka@intel.com>
30 #include "common.h" /* auxiliary functions */
31 #include "plugin.h" /* plugin_register_*, plugin_dispatch_values */
37 static int huge_read (void);
38 static int huge_config_callback (const char *key, const char *val);
40 static const char PLUGIN_NAME[] = "hugepages";
41 static const char SYS_NODE[] = "/sys/devices/system/node";
42 static const char NODE[] = "node";
43 static const char HUGEPAGES_DIR[] = "hugepages";
44 static const char SYS_NODE_HUGEPAGES[] = "/sys/devices/system/node/%s/hugepages";
45 static const char SYS_MM_HUGEPAGES[] = "/sys/kernel/mm/hugepages";
46 static const char CONFIG_NAME[] = "hugepages";
47 static const char CFG_ENA_NUMA[] = "EnableNuma";
48 static const char CFG_ENA_MM[] = "EnableMM";
50 static const char *CONFIG_KEYS[] = {
54 static const size_t CONFIG_KEYS_NUM = sizeof(CONFIG_KEYS)/sizeof(*CONFIG_NAME);
55 static int g_config_ena_numa = 1;
56 static int g_config_ena_mm = 1;
58 static int huge_config_callback (const char *key, const char *val)
60 INFO("HugePages config key='%s', val='%s'", key, val);
62 if (0 == strcasecmp(key, CFG_ENA_NUMA)) {
63 g_config_ena_numa = IS_TRUE(val);
66 if (0 == strcasecmp(key, CFG_ENA_MM)) {
67 g_config_ena_mm = IS_TRUE(val);
74 static void submit_one (const char *plug_inst, const char *type,
75 const char *type_instance, derive_t value)
78 value_list_t vl = VALUE_LIST_INIT;
80 values[0].derive = value;
84 sstrncpy (vl.host, hostname_g, sizeof (vl.host));
85 sstrncpy (vl.plugin, PLUGIN_NAME, sizeof (vl.plugin));
86 sstrncpy (vl.plugin_instance, plug_inst, sizeof (vl.plugin_instance));
87 sstrncpy (vl.type, type, sizeof (vl.type));
89 if (type_instance != NULL) {
90 sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
93 DEBUG("submit_one pl_inst:%s, inst_type %s, type %s, val=%lu",
94 plug_inst, type_instance, type, value);
96 plugin_dispatch_values (&vl);
99 static int read_hugepage_entry(const char *path, const char* entry,
100 const char* plinst, const char* hpsize)
104 snprintf(path2, sizeof(path2), "%s/%s", path, entry);
106 FILE *fh = fopen(path2, "rt");
108 ERROR("Cannot open %s", path2);
112 if (fscanf(fh, "%ld", &value) !=1) {
113 ERROR("Cannot parse file %s", path2);
118 submit_one (plinst, entry, hpsize, value);
124 static int read_syshugepage_dir(const char* path, const char* dirhpsize,
128 struct dirent *entry = NULL;
129 struct dirent *result = NULL;
135 ERROR("Cannot open directory %s", path);
139 name_max = pathconf(path, _PC_NAME_MAX);
140 if (name_max == -1) { /* Limit not defined, or error */
141 name_max = 255; /* Take a guess */
144 len = offsetof(struct dirent, d_name) + name_max + 1;
147 ERROR("Malloc returned NULL");
151 while (0 == readdir_r(dir, entry, &result)) {
152 if (NULL == result) {
156 if (result->d_name[0] == '.') {
157 /* not interesting "." and ".." */
161 read_hugepage_entry(path, result->d_name, node, dirhpsize);
171 static int read_syshugepages(const char* path, const char* node)
174 struct dirent *entry = NULL;
175 struct dirent *result = NULL;
182 ERROR("Cannot open directory %s", path);
186 name_max = pathconf(path, _PC_NAME_MAX);
187 if (name_max == -1) { /* Limit not defined, or error */
188 name_max = 255; /* Take a guess */
190 len = offsetof(struct dirent, d_name) + name_max + 1;
193 ERROR("Malloc returned NULL");
197 while (0 == readdir_r(dir, entry, &result)) {
198 /* read "hugepages-XXXXXkB" entries */
199 if (NULL == result) {
204 if (strncmp(result->d_name, HUGEPAGES_DIR, sizeof(HUGEPAGES_DIR)-1)) {
209 /* /sys/devices/system/node/node?/hugepages/ */
210 snprintf(path2, sizeof(path2), "%s/%s", path, result->d_name);
211 read_syshugepage_dir(path2, result->d_name, node);
220 static int read_nodes(void)
223 struct dirent *entry = NULL;
224 struct dirent *result = NULL;
229 dir = opendir(SYS_NODE);
231 ERROR("Cannot open directory %s", SYS_NODE);
235 name_max = pathconf(SYS_NODE, _PC_NAME_MAX);
236 if (name_max == -1) { /* Limit not defined, or error */
237 name_max = 255; /* Take a guess */
239 len = offsetof(struct dirent, d_name) + name_max + 1;
242 ERROR("Malloc returned NULL");
246 while (0 == readdir_r(dir, entry, &result)) {
247 if (NULL == result) {
252 if (strncmp(result->d_name, NODE, sizeof(NODE)-1)) {
257 snprintf(path, sizeof(path), SYS_NODE_HUGEPAGES, result->d_name);
258 read_syshugepages(path, result->d_name);
268 static int huge_read (void)
270 if (g_config_ena_mm) {
271 read_syshugepages(SYS_MM_HUGEPAGES, "mm");
273 if (g_config_ena_numa) {
280 void module_register (void)
282 plugin_register_config(CONFIG_NAME, huge_config_callback, CONFIG_KEYS,
284 plugin_register_read (PLUGIN_NAME, huge_read);