From: Pierre Lebleu Date: Thu, 4 Jul 2019 13:58:21 +0000 (+0200) Subject: UBI plugin: collect some stats about the UBIFS X-Git-Tag: collectd-5.11.0~34^2~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=71144b36809e5cde5ee86a3b00f3eca5bc3be520;p=thirdparty%2Fcollectd.git UBI plugin: collect some stats about the UBIFS UBIFS is a filesystem for unmanaged flash memory devices. This plugin collects some stats about the UBIFS: * bad physical underlying blocks (bad_peb_count) * max erase counter value (max_ec) --- diff --git a/Makefile.am b/Makefile.am index 9b9698f34..cf3865217 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1904,6 +1904,13 @@ turbostat_la_SOURCES = \ turbostat_la_LDFLAGS = $(PLUGIN_LDFLAGS) endif +if BUILD_PLUGIN_UBI +pkglib_LTLIBRARIES += ubi.la +ubi_la_SOURCES = src/ubi.c +ubi_la_LDFLAGS = $(PLUGIN_LDFLAGS) +ubi_la_LIBADD = libignorelist.la +endif + if BUILD_PLUGIN_UNIXSOCK pkglib_LTLIBRARIES += unixsock.la unixsock_la_SOURCES = src/unixsock.c diff --git a/configure.ac b/configure.ac index 2289aa434..f4e87c83e 100644 --- a/configure.ac +++ b/configure.ac @@ -6420,6 +6420,7 @@ plugin_tcpconns="no" plugin_ted="no" plugin_thermal="no" plugin_turbostat="no" +plugin_ubi="no" plugin_uptime="no" plugin_users="no" plugin_virt="no" @@ -6913,6 +6914,7 @@ AC_PLUGIN([thermal], [$plugin_thermal], [Linux ACPI therma AC_PLUGIN([threshold], [yes], [Threshold checking plugin]) AC_PLUGIN([tokyotyrant], [$with_libtokyotyrant], [TokyoTyrant database statistics]) AC_PLUGIN([turbostat], [$plugin_turbostat], [Advanced statistic on Intel cpu states]) +AC_PLUGIN([ubi], [$plugin_ubi], [UBI statistics]) AC_PLUGIN([unixsock], [yes], [Unixsock communication plugin]) AC_PLUGIN([uptime], [$plugin_uptime], [Uptime statistics]) AC_PLUGIN([users], [$plugin_users], [User statistics]) @@ -7341,6 +7343,7 @@ AC_MSG_RESULT([ thermal . . . . . . . $enable_thermal]) AC_MSG_RESULT([ threshold . . . . . . $enable_threshold]) AC_MSG_RESULT([ tokyotyrant . . . . . $enable_tokyotyrant]) AC_MSG_RESULT([ turbostat . . . . . . $enable_turbostat]) +AC_MSG_RESULT([ ubi . . . . . . . . . $enable_ubi]) AC_MSG_RESULT([ unixsock . . . . . . $enable_unixsock]) AC_MSG_RESULT([ uptime . . . . . . . $enable_uptime]) AC_MSG_RESULT([ users . . . . . . . . $enable_users]) diff --git a/src/types.db b/src/types.db index 69f59b065..82b284d46 100644 --- a/src/types.db +++ b/src/types.db @@ -7,6 +7,7 @@ apache_scoreboard value:GAUGE:0:65535 ath_nodes value:GAUGE:0:65535 ath_stat value:DERIVE:0:U backends value:GAUGE:0:65535 +bad_peb_count value:COUNTER:0:U bitrate value:GAUGE:0:4294967295 blocked_clients value:GAUGE:0:U bucket value:GAUGE:0:U @@ -134,6 +135,7 @@ job_stats value:DERIVE:0:U latency value:GAUGE:0:U links value:GAUGE:0:U load shortterm:GAUGE:0:5000, midterm:GAUGE:0:5000, longterm:GAUGE:0:5000 +max_ec value:COUNTER:0:U memory_bandwidth value:DERIVE:0:U md_disks value:GAUGE:0:U memcached_command value:DERIVE:0:U diff --git a/src/ubi.c b/src/ubi.c new file mode 100644 index 000000000..4dd071630 --- /dev/null +++ b/src/ubi.c @@ -0,0 +1,156 @@ +/** + * collectd - src/ubi.c + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; only version 2 of the License is applicable. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "collectd.h" + +#include "plugin.h" +#include "utils/common/common.h" +#include "utils/ignorelist/ignorelist.h" + +#if !KERNEL_LINUX +#error "No applicable input method." +#endif + +#define PLUGIN_NAME "ubi" + +#define SYS_PATH "/sys/class/ubi/" + +/* + * Device attributes + */ +#define DEV_BAD_COUNT "bad_peb_count" // Count of bad physical eraseblocks on the underlying MTD device. +#define MAXIMUM_ERASE "max_ec" // Current maximum erase counter value + +/* + * The config key strings + */ +#define DEVICE_KEY "Device" +#define IGNORE_KEY "IgnoreSelected" + +static const char *config_keys[] = +{ + DEVICE_KEY, + IGNORE_KEY, +}; +static int config_keys_num = STATIC_ARRAY_SIZE (config_keys); + +static ignorelist_t *ignorelist = NULL; + +/* + * Private functions + */ +static int ubi_config(const char *key, const char *value) +{ + if ( ignorelist == NULL && + (ignorelist = ignorelist_create(/* invert = */ 1)) == NULL ) + return -1; + + if ( strcasecmp(key, DEVICE_KEY) == 0 ) + ignorelist_add(ignorelist, value); + else if ( strcasecmp(key, IGNORE_KEY) == 0 ) + ignorelist_set_invert(ignorelist, IS_TRUE(value) ? 0 : 1); + else + return -1; + + return 0; +} /* int ubi_config */ + +static void ubi_submit(const char *dev_name, const char *type, counter_t value) +{ + value_list_t vl = VALUE_LIST_INIT; + + if (ignorelist_match(ignorelist, dev_name) != 0) + return; + + vl.values = &(value_t){.counter = value}; + vl.values_len = 1; + sstrncpy(vl.plugin, PLUGIN_NAME, sizeof(vl.plugin)); + sstrncpy(vl.type_instance, dev_name, sizeof(vl.type_instance)); + sstrncpy(vl.type, type, sizeof(vl.type)); + + plugin_dispatch_values(&vl); +} /* void ubi_submit */ + +static int ubi_read_dev_attr(const char *dev_name, const char *attr) +{ + FILE *f; + int val; + char str[sizeof(SYS_PATH) + strlen(dev_name) + sizeof("/") + strlen(attr) + 1]; + int n; + + snprintf(str, sizeof(str), SYS_PATH "%s/%s", dev_name, attr); + + if ( (f = fopen(str, "r")) == NULL ) + { + ERROR(PLUGIN_NAME ": cannot open [%s]", str); + return -1; + } + + n = fscanf(f, "%d", &val); + fclose(f); + + if ( n != 1 ) + { + ERROR(PLUGIN_NAME " : did not find an integer in %s", str); + return -1; + } + + ubi_submit(dev_name, attr, (counter_t)val); + + return 0; +} /* int ubi_read_dev_attr */ + +static inline int ubi_read_dev_bad_count(const char *dev_name) +{ + return ubi_read_dev_attr(dev_name, DEV_BAD_COUNT); +} /* int ubi_read_dev_bad_count */ + +static inline int ubi_read_max_ec(const char *dev_name) +{ + return ubi_read_dev_attr(dev_name, MAXIMUM_ERASE); +} /* int ubi_read_max_ec */ + +static int ubi_read(void) +{ + DIR *dir; + struct dirent *dirent; + + if ( (dir = opendir(SYS_PATH)) == NULL ) + { + ERROR(PLUGIN_NAME " : cannot open dir " SYS_PATH); + return -1; + } + + while ( (dirent = readdir(dir)) != NULL ) + { + if ( ignorelist_match(ignorelist, dirent->d_name) ) + continue; + + ubi_read_dev_bad_count(dirent->d_name); + ubi_read_max_ec(dirent->d_name); + } + + closedir(dir); + + return 0; +} /* int ubi_read */ + +void module_register(void) +{ + plugin_register_config(PLUGIN_NAME, ubi_config, config_keys, config_keys_num); + plugin_register_read(PLUGIN_NAME, ubi_read); +} /* void module_register */