From: Patrick Mooney Date: Mon, 10 Feb 2014 16:00:15 +0000 (-0600) Subject: disk: Add udev-based device renaming on Linux X-Git-Tag: collectd-5.5.0~293^2~1 X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=c8e864195fea2abc7cd35c03dd7796003cdf9b2f;p=collectd.git disk: Add udev-based device renaming on Linux On systems with large collections of allocated disk resources, the kernel provided names can be difficult to use to logically group or compare collected values. To grant users the ability to assign custom instance names for disk devices, collectd can query for a specified udev attribute. If the attribute is present, its value is subsituted for the kernel name when submitting the data points. --- diff --git a/configure.ac b/configure.ac index 3b9b8eb7..74dbb223 100644 --- a/configure.ac +++ b/configure.ac @@ -4030,6 +4030,67 @@ fi AM_CONDITIONAL(BUILD_WITH_LIBTOKYOTYRANT, test "x$with_libtokyotyrant" = "xyes") # }}} +# --with-libudev {{{ +with_libudev_cflags="" +with_libudev_ldflags="" +AC_ARG_WITH(libudev, [AS_HELP_STRING([--with-libudev@<:@=PREFIX@:>@], [Path to libudev.])], +[ + if test "x$withval" = "xno" + then + with_libudev="no" + else + with_libudev="yes" + if test "x$withval" != "xyes" + then + with_libudev_cflags="-I$withval/include" + with_libudev_ldflags="-L$withval/lib" + with_libudev="yes" + fi + fi +], +[ + if test "x$ac_system" = "xLinux" + then + with_libudev="yes" + else + with_libudev="no (Linux only library)" + fi +]) +if test "x$with_libudev" = "xyes" +then + SAVE_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $with_libudev_cflags" + + AC_CHECK_HEADERS(libudev.h, [], [with_libudev="no (libudev.h not found)"]) + + CPPFLAGS="$SAVE_CPPFLAGS" +fi +if test "x$with_libudev" = "xyes" +then + SAVE_CPPFLAGS="$CPPFLAGS" + SAVE_LDFLAGS="$LDFLAGS" + CPPFLAGS="$CPPFLAGS $with_libudev_cflags" + LDFLAGS="$LDFLAGS $with_libudev_ldflags" + + AC_CHECK_LIB(udev, udev_new, + [ + AC_DEFINE(HAVE_LIBUDEV, 1, [Define to 1 if you have the udev library (-ludev).]) + ], + [with_libudev="no (libudev not found)"]) + + CPPFLAGS="$SAVE_CPPFLAGS" + LDFLAGS="$SAVE_LDFLAGS" +fi +if test "x$with_libudev" = "xyes" +then + BUILD_WITH_LIBUDEV_CFLAGS="$with_libudev_cflags" + BUILD_WITH_LIBUDEV_LDFLAGS="$with_libudev_ldflags" + AC_SUBST(BUILD_WITH_LIBUDEV_CFLAGS) + AC_SUBST(BUILD_WITH_LIBUDEV_LDFLAGS) +fi +AM_CONDITIONAL(BUILD_WITH_LIBUDEV, test "x$with_libudev" = "xyes") +# }}} + # --with-libupsclient {{{ with_libupsclient_config="" with_libupsclient_cflags="" @@ -5413,6 +5474,7 @@ Configuration: libsigrok . . . . . $with_libsigrok libstatgrab . . . . . $with_libstatgrab libtokyotyrant . . . $with_libtokyotyrant + libudev . . . . . . . $with_libudev libupsclient . . . . $with_libupsclient libvarnish . . . . . $with_libvarnish libvirt . . . . . . . $with_libvirt diff --git a/src/Makefile.am b/src/Makefile.am index a9d85823..8720adfd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -385,6 +385,9 @@ if BUILD_WITH_LIBSTATGRAB disk_la_CFLAGS += $(BUILD_WITH_LIBSTATGRAB_CFLAGS) disk_la_LIBADD += $(BUILD_WITH_LIBSTATGRAB_LDFLAGS) endif +if BUILD_WITH_LIBUDEV +disk_la_LIBADD += -ludev +endif if BUILD_WITH_PERFSTAT disk_la_LIBADD += -lperfstat endif diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod index f597c490..201b5c9d 100644 --- a/src/collectd.conf.pod +++ b/src/collectd.conf.pod @@ -1649,6 +1649,12 @@ collected. If at least one B option is given and no B or set to B, B matching disks will be collected. If B is set to B, all disks are collected B the ones matched. +=item B I + +Attempt to override disk instance name with the value of a specified udev +attribute When built with B. If the attribute is not defined for the +given device, the default name is used. + =back =head2 Plugin C diff --git a/src/disk.c b/src/disk.c index 36d0a0c3..cdf2816d 100644 --- a/src/disk.c +++ b/src/disk.c @@ -128,11 +128,19 @@ static int pnumdisk; # error "No applicable input method." #endif +#if HAVE_LIBUDEV +#include + +static char *conf_udev_name_attr = NULL; +static struct udev *handle_udev; +#endif + static const char *config_keys[] = { "Disk", "UseBSDName", - "IgnoreSelected" + "IgnoreSelected", + "UdevNameAttr" }; static int config_keys_num = STATIC_ARRAY_SIZE (config_keys); @@ -163,6 +171,21 @@ static int disk_config (const char *key, const char *value) #else WARNING ("disk plugin: The \"UseBSDName\" option is only supported " "on Mach / Mac OS X and will be ignored."); +#endif + } + else if (strcasecmp ("UdevNameAttr", key) == 0) + { +#if HAVE_LIBUDEV + if (conf_udev_name_attr != NULL) + { + free (conf_udev_name_attr); + conf_udev_name_attr = NULL; + } + if ((conf_udev_name_attr = strdup (value)) == NULL) + return (1); +#else + WARNING ("disk plugin: The \"UdevNameAttr\" option is only supported " + "if collectd is built with libudev support"); #endif } else @@ -259,6 +282,34 @@ static counter_t disk_calc_time_incr (counter_t delta_time, counter_t delta_ops) } #endif +#if HAVE_LIBUDEV +/** + * Attempt to provide an rename disk instance from an assigned udev attribute. + * + * On success, it returns a strduped char* to the desired attribute value. + * Otherwise it returns NULL. + */ + +static char *disk_udev_attr_name (struct udev *udev, char *disk_name, const char *attr) +{ + struct udev_device *dev; + const char *prop; + char *output = NULL; + + dev = udev_device_new_from_subsystem_sysname (udev, "block", disk_name); + if (dev != NULL) + { + prop = udev_device_get_property_value (dev, attr); + if (prop) { + output = strdup (prop); + DEBUG ("disk plugin: renaming %s => %s", disk_name, output); + } + udev_device_unref (dev); + } + return output; +} +#endif + #if HAVE_IOKIT_IOKITLIB_H static signed long long dict_get_value (CFDictionaryRef dict, const char *key) { @@ -505,9 +556,15 @@ static int disk_read (void) fieldshift = 1; } +#if HAVE_LIBUDEV + handle_udev = udev_new(); +#endif + while (fgets (buffer, sizeof (buffer), fh) != NULL) { char *disk_name; + char *output_name; + char *alt_name; numfields = strsplit (buffer, fields, 32); @@ -659,25 +716,43 @@ static int disk_read (void) continue; } + output_name = disk_name; + +#if HAVE_LIBUDEV + alt_name = disk_udev_attr_name (handle_udev, disk_name, + conf_udev_name_attr); +#else + alt_name = NULL; +#endif + if (alt_name != NULL) + output_name = alt_name; + if ((ds->read_bytes != 0) || (ds->write_bytes != 0)) - disk_submit (disk_name, "disk_octets", + disk_submit (output_name, "disk_octets", ds->read_bytes, ds->write_bytes); if ((ds->read_ops != 0) || (ds->write_ops != 0)) - disk_submit (disk_name, "disk_ops", + disk_submit (output_name, "disk_ops", read_ops, write_ops); if ((ds->avg_read_time != 0) || (ds->avg_write_time != 0)) - disk_submit (disk_name, "disk_time", + disk_submit (output_name, "disk_time", ds->avg_read_time, ds->avg_write_time); if (is_disk) { - disk_submit (disk_name, "disk_merged", + disk_submit (output_name, "disk_merged", read_merged, write_merged); } /* if (is_disk) */ + + /* release udev-based alternate name, if allocated */ + free(alt_name); } /* while (fgets (buffer, sizeof (buffer), fh) != NULL) */ +#if HAVE_LIBUDEV + udev_unref(handle_udev); +#endif + fclose (fh); /* #endif defined(KERNEL_LINUX) */