X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fhugepages.c;h=ee43237032955608270bb662c7f39737cddc4afd;hb=f91506bb8f91ca3725fd3081deba4e1829186aaa;hp=fb736a6a991758554af96e211d70b55059e83804;hpb=fa49565fa7ef682ce61bc446fb0d2469eedddc66;p=collectd.git diff --git a/src/hugepages.c b/src/hugepages.c index fb736a6a..ee432370 100644 --- a/src/hugepages.c +++ b/src/hugepages.c @@ -24,65 +24,59 @@ * * Authors: * Jaroslav Safka + * Kim-Marie Jones */ #include "collectd.h" #include "common.h" /* auxiliary functions */ #include "plugin.h" /* plugin_register_*, plugin_dispatch_values */ -#include -#include -#include - -static int huge_read (void); -static int huge_config_callback (const char *key, const char *val); - -static const char PLUGIN_NAME[] = "hugepages"; -static const char SYS_NODE[] = "/sys/devices/system/node"; -static const char NODE[] = "node"; -static const char HUGEPAGES_DIR[] = "hugepages"; -static const char SYS_NODE_HUGEPAGES[] = "/sys/devices/system/node/%s/hugepages"; -static const char SYS_MM_HUGEPAGES[] = "/sys/kernel/mm/hugepages"; -static const char CONFIG_NAME[] = "hugepages"; -static const char CFG_ENA_NUMA[] = "EnableNuma"; -static const char CFG_ENA_MM[] = "EnableMM"; - -static const char *CONFIG_KEYS[] = { - CFG_ENA_NUMA, - CFG_ENA_MM, +static const char g_plugin_name[] = "hugepages"; +static const char g_cfg_rpt_numa[] = "ReportPerNodeHP"; +static const char g_cfg_rpt_mm[] = "ReportRootHP"; + +static const char *g_config_keys[] = { + g_cfg_rpt_numa, + g_cfg_rpt_mm, +}; +static size_t g_config_keys_num = STATIC_ARRAY_SIZE(g_config_keys); +static int g_flag_rpt_numa = 1; +static int g_flag_rpt_mm = 1; + +struct entry_info { + char *d_name; + char *node; }; -static const size_t CONFIG_KEYS_NUM = sizeof(CONFIG_KEYS)/sizeof(*CONFIG_NAME); -static int g_config_ena_numa = 1; -static int g_config_ena_mm = 1; -static int huge_config_callback (const char *key, const char *val) +static int huge_config_callback(const char *key, const char *val) { - INFO("HugePages config key='%s', val='%s'", key, val); + INFO("%s: HugePages config key='%s', val='%s'", g_plugin_name, key, val); - if (0 == strcasecmp(key, CFG_ENA_NUMA)) { - g_config_ena_numa = IS_TRUE(val); + if (strcasecmp(key, g_cfg_rpt_numa) == 0) { + g_flag_rpt_numa = IS_TRUE(val); return 0; } - if (0 == strcasecmp(key, CFG_ENA_MM)) { - g_config_ena_mm = IS_TRUE(val); + if (strcasecmp(key, g_cfg_rpt_mm) == 0) { + g_flag_rpt_mm = IS_TRUE(val); return 0; } return -1; } -static void submit_one (const char *plug_inst, const char *type, - const char *type_instance, derive_t value) +static void submit_hp(const char *plug_inst, const char *type, + const char *type_instance, gauge_t free_value, gauge_t used_value) { - value_t values[1]; + value_t values[2]; value_list_t vl = VALUE_LIST_INIT; - values[0].derive = value; + values[0].gauge = free_value; + values[1].gauge = used_value; vl.values = values; - vl.values_len = 1; + vl.values_len = 2; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); - sstrncpy (vl.plugin, PLUGIN_NAME, sizeof (vl.plugin)); + sstrncpy (vl.plugin, g_plugin_name, sizeof (vl.plugin)); sstrncpy (vl.plugin_instance, plug_inst, sizeof (vl.plugin_instance)); sstrncpy (vl.type, type, sizeof (vl.type)); @@ -90,128 +84,114 @@ static void submit_one (const char *plug_inst, const char *type, sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance)); } - DEBUG("submit_one pl_inst:%s, inst_type %s, type %s, val=%"PRIu64"", - plug_inst, type_instance, type, value); + DEBUG("submit_hp pl_inst:%s, inst_type %s, type %s, free=%lf, used=%lf", + plug_inst, type_instance, type, free_value, used_value); plugin_dispatch_values (&vl); } -static int read_hugepage_entry(const char *path, const char* entry, - const char* plinst, const char* hpsize) +static int read_hugepage_entry(const char *path, const char *entry, + void *e_info) { - char path2[512]; - long value = 0; - snprintf(path2, sizeof(path2), "%s/%s", path, entry); + char path2[PATH_MAX]; + char *type = "hugepages"; + char *partial_type_inst = "free_used"; + char type_instance[PATH_MAX]; + char *strin = NULL; + struct entry_info *hpsize_plinst = (struct entry_info *) e_info; + static int flag = 0; + static double used_hp = 0; + static double free_hp = 0; + double value; + + ssnprintf(path2, sizeof(path2), "%s/%s", path, entry); FILE *fh = fopen(path2, "rt"); - if (NULL == fh) { - ERROR("Cannot open %s", path2); + if (fh == NULL) { + ERROR("%s: cannot open %s", g_plugin_name, path2); return -1; } - if (fscanf(fh, "%ld", &value) !=1) { - ERROR("Cannot parse file %s", path2); + if (fscanf(fh, "%lf", &value) !=1) { + ERROR("%s: cannot parse file %s", g_plugin_name, path2); fclose(fh); return -1; } - submit_one (plinst, entry, hpsize, value); - - fclose(fh); - return 0; -} - -static int read_syshugepage_dir(const char* path, const char* dirhpsize, - const char* node) -{ - DIR *dir = NULL; - struct dirent *entry = NULL; - struct dirent *result = NULL; - size_t name_max = 0; - size_t len = 0; - - dir = opendir(path); - if (NULL == dir) { - ERROR("Cannot open directory %s", path); - return -1; - } - - name_max = pathconf(path, _PC_NAME_MAX); - if (name_max == -1) { /* Limit not defined, or error */ - name_max = 255; /* Take a guess */ - } - - len = offsetof(struct dirent, d_name) + name_max + 1; - entry = malloc(len); - if (entry == NULL) { - ERROR("Malloc returned NULL"); - return -1; + if (strcmp(entry, "nr_hugepages") == 0) { + used_hp += value; + flag++; + } else if (strcmp(entry, "surplus_hugepages") == 0) { + used_hp += value; + flag++; + } else if (strcmp(entry, "free_hugepages") == 0) { + used_hp -= value; + free_hp = value; + flag++; } - while (0 == readdir_r(dir, entry, &result)) { - if (NULL == result) { - /* end of dir */ - break; - } - if (result->d_name[0] == '.') { - /* not interesting "." and ".." */ - continue; + if (flag == 3) { + /* Can now submit "used" and "free" values. + * 0x2D is the ASCII "-" character, after which the string + * contains "kB" + * The string passed as param 3 to submit_hp is of the format: + * --kB + */ + strin = strchr(hpsize_plinst->d_name, 0x2D); + if (strin != NULL) { + ssnprintf(type_instance, sizeof(type_instance), "%s%s", partial_type_inst, strin); + } else { + ssnprintf(type_instance, sizeof(type_instance), "%s%s", partial_type_inst, + hpsize_plinst->d_name); } + submit_hp(hpsize_plinst->node, type, type_instance, free_hp, used_hp); - read_hugepage_entry(path, result->d_name, node, dirhpsize); + /* Reset for next time */ + flag = 0; + used_hp = 0; + free_hp = 0; } - free(entry); - closedir(dir); - - + fclose(fh); return 0; } static int read_syshugepages(const char* path, const char* node) { - DIR *dir = NULL; - struct dirent *entry = NULL; + const char hugepages_dir[] = "hugepages"; + DIR *dir = NULL; struct dirent *result = NULL; - size_t name_max = 0; - size_t len = 0; - char path2[255]; + char path2[PATH_MAX]; + struct entry_info e_info; dir = opendir(path); - if (NULL == dir) { - ERROR("Cannot open directory %s", path); + if (dir == NULL) { + ERROR("%s: cannot open directory %s", g_plugin_name, path); return -1; } - name_max = pathconf(path, _PC_NAME_MAX); - if (name_max == -1) { /* Limit not defined, or error */ - name_max = 255; /* Take a guess */ - } - len = offsetof(struct dirent, d_name) + name_max + 1; - entry = malloc(len); - if (entry == NULL) { - ERROR("Malloc returned NULL"); + if (pathconf(path, _PC_NAME_MAX) == -1) { + /* Limit not defined, or error */ + ERROR("%s: pathconf failed", g_plugin_name); + closedir(dir); return -1; } - while (0 == readdir_r(dir, entry, &result)) { - /* read "hugepages-XXXXXkB" entries */ - if (NULL == result) { - /* end of dir */ - break; - } - - if (strncmp(result->d_name, HUGEPAGES_DIR, sizeof(HUGEPAGES_DIR)-1)) { + /* read "hugepages-XXXXXkB" entries */ + while ((result = readdir(dir)) != NULL) { + if (strncmp(result->d_name, hugepages_dir, sizeof(hugepages_dir)-1)) { /* not node dir */ continue; } /* /sys/devices/system/node/node?/hugepages/ */ - snprintf(path2, sizeof(path2), "%s/%s", path, result->d_name); - read_syshugepage_dir(path2, result->d_name, node); + ssnprintf(path2, sizeof(path2), "%s/%s", path, result->d_name); + + e_info.d_name = result->d_name; + e_info.node = (char *) node; + walk_directory(path2, read_hugepage_entry, (void *) &e_info, 0); } - free(entry); closedir(dir); return 0; @@ -219,68 +199,60 @@ static int read_syshugepages(const char* path, const char* node) static int read_nodes(void) { - DIR *dir = NULL; - struct dirent *entry = NULL; + const char sys_node[] = "/sys/devices/system/node"; + const char node_string[] = "node"; + const char sys_node_hugepages[] = "/sys/devices/system/node/%s/hugepages"; + DIR *dir = NULL; struct dirent *result = NULL; - size_t name_max = 0; - size_t len = 0; - char path[255]; + char path[PATH_MAX]; - dir = opendir(SYS_NODE); - if (NULL == dir) { - ERROR("Cannot open directory %s", SYS_NODE); + dir = opendir(sys_node); + if (dir == NULL) { + ERROR("%s: cannot open directory %s", g_plugin_name, sys_node); return -1; } - name_max = pathconf(SYS_NODE, _PC_NAME_MAX); - if (name_max == -1) { /* Limit not defined, or error */ - name_max = 255; /* Take a guess */ - } - len = offsetof(struct dirent, d_name) + name_max + 1; - entry = malloc(len); - if (entry == NULL) { - ERROR("Malloc returned NULL"); + if (pathconf(sys_node, _PC_NAME_MAX) == -1) { + /* Limit not defined, or error */ + ERROR("%s: pathconf failed", g_plugin_name); + closedir(dir); return -1; } - while (0 == readdir_r(dir, entry, &result)) { - if (NULL == result) { - /* end of dir */ - break; - } - - if (strncmp(result->d_name, NODE, sizeof(NODE)-1)) { + while ((result = readdir(dir)) != NULL) { + if (strncmp(result->d_name, node_string, sizeof(node_string)-1)) { /* not node dir */ continue; } - snprintf(path, sizeof(path), SYS_NODE_HUGEPAGES, result->d_name); + ssnprintf(path, sizeof(path), sys_node_hugepages, result->d_name); read_syshugepages(path, result->d_name); } - free(entry); closedir(dir); return 0; } -static int huge_read (void) +static int huge_read(void) { - if (g_config_ena_mm) { - read_syshugepages(SYS_MM_HUGEPAGES, "mm"); + const char sys_mm_hugepages[] = "/sys/kernel/mm/hugepages"; + + if (g_flag_rpt_mm) { + read_syshugepages(sys_mm_hugepages, "mm"); } - if (g_config_ena_numa) { + if (g_flag_rpt_numa) { read_nodes(); } return 0; } -void module_register (void) +void module_register(void) { - plugin_register_config(CONFIG_NAME, huge_config_callback, CONFIG_KEYS, - CONFIG_KEYS_NUM); - plugin_register_read (PLUGIN_NAME, huge_read); + plugin_register_config(g_plugin_name, huge_config_callback, g_config_keys, + g_config_keys_num); + plugin_register_read(g_plugin_name, huge_read); }