X-Git-Url: https://git.octo.it/?p=collectd.git;a=blobdiff_plain;f=src%2Fsmart.c;h=30680be6ed4b5d0565ea27a4a46c453e3f3c1051;hp=285eb860e480d7c5944658e793ca9b0a25088768;hb=1159cb5d383c55a80a0db100b8f7aadcf44740a5;hpb=c442c66d9e98852f1b8eaa1b816d6ee7f84d0342 diff --git a/src/smart.c b/src/smart.c index 285eb860..30680be6 100644 --- a/src/smart.c +++ b/src/smart.c @@ -33,224 +33,181 @@ #include #include -static const char *config_keys[] = -{ - "Disk", - "IgnoreSelected", - "IgnoreSleepMode", - "UseSerial" -}; +#ifdef HAVE_SYS_CAPABILITY_H +#include +#endif -static int config_keys_num = STATIC_ARRAY_SIZE (config_keys); +static const char *config_keys[] = {"Disk", "IgnoreSelected", "IgnoreSleepMode", + "UseSerial"}; + +static int config_keys_num = STATIC_ARRAY_SIZE(config_keys); static ignorelist_t *ignorelist = NULL; static int ignore_sleep_mode = 0; static int use_serial = 0; -static int smart_config (const char *key, const char *value) -{ +static int smart_config(const char *key, const char *value) { if (ignorelist == NULL) - ignorelist = ignorelist_create (/* invert = */ 1); + ignorelist = ignorelist_create(/* invert = */ 1); if (ignorelist == NULL) - return (1); + return 1; - if (strcasecmp ("Disk", key) == 0) - { - ignorelist_add (ignorelist, value); - } - else if (strcasecmp ("IgnoreSelected", key) == 0) - { + if (strcasecmp("Disk", key) == 0) { + ignorelist_add(ignorelist, value); + } else if (strcasecmp("IgnoreSelected", key) == 0) { int invert = 1; - if (IS_TRUE (value)) + if (IS_TRUE(value)) invert = 0; - ignorelist_set_invert (ignorelist, invert); - } - else if (strcasecmp ("IgnoreSleepMode", key) == 0) - { - if (IS_TRUE (value)) + ignorelist_set_invert(ignorelist, invert); + } else if (strcasecmp("IgnoreSleepMode", key) == 0) { + if (IS_TRUE(value)) ignore_sleep_mode = 1; - } - else if (strcasecmp ("UseSerial", key) == 0) - { - if (IS_TRUE (value)) + } else if (strcasecmp("UseSerial", key) == 0) { + if (IS_TRUE(value)) use_serial = 1; - } - else - { - return (-1); + } else { + return -1; } - return (0); + return 0; } /* int smart_config */ -static void smart_submit (const char *dev, const char *type, - const char *type_inst, double value) -{ - value_list_t vl = VALUE_LIST_INIT; +static void smart_submit(const char *dev, const char *type, + const char *type_inst, double value) { + value_list_t vl = VALUE_LIST_INIT; - vl.values = &(value_t) { .gauge = value }; - vl.values_len = 1; - sstrncpy (vl.plugin, "smart", sizeof (vl.plugin)); - sstrncpy (vl.plugin_instance, dev, sizeof (vl.plugin_instance)); - sstrncpy (vl.type, type, sizeof (vl.type)); - sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance)); + vl.values = &(value_t){.gauge = value}; + vl.values_len = 1; + sstrncpy(vl.plugin, "smart", sizeof(vl.plugin)); + sstrncpy(vl.plugin_instance, dev, sizeof(vl.plugin_instance)); + sstrncpy(vl.type, type, sizeof(vl.type)); + sstrncpy(vl.type_instance, type_inst, sizeof(vl.type_instance)); - plugin_dispatch_values (&vl); + plugin_dispatch_values(&vl); } -static void smart_handle_disk_attribute(SkDisk *d, const SkSmartAttributeParsedData *a, - void* userdata) -{ - const char *dev = userdata; +static void handle_attribute(SkDisk *d, const SkSmartAttributeParsedData *a, + void *userdata) { + char const *name = userdata; if (!a->current_value_valid || !a->worst_value_valid) return; value_list_t vl = VALUE_LIST_INIT; value_t values[] = { - { .gauge = a->current_value }, - { .gauge = a->worst_value }, - { .gauge = a->threshold_valid ? a->threshold : 0 }, - { .gauge = a->pretty_value }, + {.gauge = a->current_value}, + {.gauge = a->worst_value}, + {.gauge = a->threshold_valid ? a->threshold : 0}, + {.gauge = a->pretty_value}, }; vl.values = values; - vl.values_len = STATIC_ARRAY_SIZE (values); - sstrncpy (vl.plugin, "smart", sizeof (vl.plugin)); - sstrncpy (vl.plugin_instance, dev, sizeof (vl.plugin_instance)); - sstrncpy (vl.type, "smart_attribute", sizeof (vl.type)); - sstrncpy (vl.type_instance, a->name, sizeof (vl.type_instance)); - - plugin_dispatch_values (&vl); - - if (a->threshold_valid && a->current_value <= a->threshold) - { - notification_t notif = { NOTIF_WARNING, - cdtime (), - "", - "", - "smart", "", - "smart_attribute", - "", - NULL }; - sstrncpy (notif.host, hostname_g, sizeof (notif.host)); - sstrncpy (notif.plugin_instance, dev, sizeof (notif.plugin_instance)); - sstrncpy (notif.type_instance, a->name, sizeof (notif.type_instance)); - ssnprintf (notif.message, sizeof (notif.message), - "attribute %s is below allowed threshold (%d < %d)", - a->name, a->current_value, a->threshold); - plugin_dispatch_notification (¬if); + vl.values_len = STATIC_ARRAY_SIZE(values); + sstrncpy(vl.plugin, "smart", sizeof(vl.plugin)); + sstrncpy(vl.plugin_instance, name, sizeof(vl.plugin_instance)); + sstrncpy(vl.type, "smart_attribute", sizeof(vl.type)); + sstrncpy(vl.type_instance, a->name, sizeof(vl.type_instance)); + + plugin_dispatch_values(&vl); + + if (a->threshold_valid && a->current_value <= a->threshold) { + notification_t notif = {NOTIF_WARNING, cdtime(), "", "", "smart", "", + "smart_attribute", "", NULL}; + sstrncpy(notif.host, hostname_g, sizeof(notif.host)); + sstrncpy(notif.plugin_instance, name, sizeof(notif.plugin_instance)); + sstrncpy(notif.type_instance, a->name, sizeof(notif.type_instance)); + snprintf(notif.message, sizeof(notif.message), + "attribute %s is below allowed threshold (%d < %d)", a->name, + a->current_value, a->threshold); + plugin_dispatch_notification(¬if); } } -static void smart_handle_disk (const char *dev, const char *serial) -{ - SkDisk *d = NULL; - SkBool awake = FALSE; +static void smart_read_disk(SkDisk *d, char const *name) { SkBool available = FALSE; - const char *shortname; - const SkSmartParsedData *spd; - uint64_t poweron, powercycles, badsectors, temperature; - - if (use_serial && serial) - { - shortname = serial; - } - else - { - shortname = strrchr(dev, '/'); - if (!shortname) return; - shortname++; - } - if (ignorelist_match (ignorelist, shortname) != 0) { - DEBUG ("smart plugin: ignoring %s.", dev); + if (sk_disk_identify_is_available(d, &available) < 0 || !available) { + DEBUG("smart plugin: disk %s cannot be identified.", name); return; } - - DEBUG ("smart plugin: checking SMART status of %s.", - dev); - - if (sk_disk_open (dev, &d) < 0) - { - ERROR ("smart plugin: unable to open %s.", dev); + if (sk_disk_smart_is_available(d, &available) < 0 || !available) { + DEBUG("smart plugin: disk %s has no SMART support.", name); return; } - if (sk_disk_identify_is_available (d, &available) < 0 || !available) - { - DEBUG ("smart plugin: disk %s cannot be identified.", dev); - goto end; - } - if (sk_disk_smart_is_available (d, &available) < 0 || !available) - { - DEBUG ("smart plugin: disk %s has no SMART support.", dev); - goto end; - } - if (!ignore_sleep_mode) - { - if (sk_disk_check_sleep_mode (d, &awake) < 0 || !awake) - { - DEBUG ("smart plugin: disk %s is sleeping.", dev); - goto end; + if (!ignore_sleep_mode) { + SkBool awake = FALSE; + if (sk_disk_check_sleep_mode(d, &awake) < 0 || !awake) { + DEBUG("smart plugin: disk %s is sleeping.", name); + return; } } - if (sk_disk_smart_read_data (d) < 0) - { - ERROR ("smart plugin: unable to get SMART data for disk %s.", dev); - goto end; + if (sk_disk_smart_read_data(d) < 0) { + ERROR("smart plugin: unable to get SMART data for disk %s.", name); + return; } - if (sk_disk_smart_parse (d, &spd) < 0) - { - ERROR ("smart plugin: unable to parse SMART data for disk %s.", dev); - goto end; + + if (sk_disk_smart_parse(d, &(SkSmartParsedData const *){NULL}) < 0) { + ERROR("smart plugin: unable to parse SMART data for disk %s.", name); + return; } /* Get some specific values */ - if (sk_disk_smart_get_power_on (d, &poweron) < 0) - { - WARNING ("smart plugin: unable to get milliseconds since power on for %s.", - dev); - } + uint64_t value; + if (sk_disk_smart_get_power_on(d, &value) >= 0) + smart_submit(name, "smart_poweron", "", ((gauge_t)value) / 1000.); else - smart_submit (shortname, "smart_poweron", "", poweron / 1000.); + DEBUG("smart plugin: unable to get milliseconds since power on for %s.", + name); - if (sk_disk_smart_get_power_cycle (d, &powercycles) < 0) - { - WARNING ("smart plugin: unable to get number of power cycles for %s.", - dev); - } + if (sk_disk_smart_get_power_cycle(d, &value) >= 0) + smart_submit(name, "smart_powercycles", "", (gauge_t)value); else - smart_submit (shortname, "smart_powercycles", "", powercycles); + DEBUG("smart plugin: unable to get number of power cycles for %s.", name); - if (sk_disk_smart_get_bad (d, &badsectors) < 0) - { - WARNING ("smart plugin: unable to get number of bad sectors for %s.", - dev); - } + if (sk_disk_smart_get_bad(d, &value) >= 0) + smart_submit(name, "smart_badsectors", "", (gauge_t)value); else - smart_submit (shortname, "smart_badsectors", "", badsectors); + DEBUG("smart plugin: unable to get number of bad sectors for %s.", name); - if (sk_disk_smart_get_temperature (d, &temperature) < 0) - { - WARNING ("smart plugin: unable to get temperature for %s.", - dev); - } + if (sk_disk_smart_get_temperature(d, &value) >= 0) + smart_submit(name, "smart_temperature", "", + ((gauge_t)value) / 1000. - 273.15); else - smart_submit (shortname, "smart_temperature", "", temperature / 1000. - 273.15); + DEBUG("smart plugin: unable to get temperature for %s.", name); /* Grab all attributes */ - if (sk_disk_smart_parse_attributes(d, smart_handle_disk_attribute, - (char *)shortname) < 0) - { - ERROR ("smart plugin: unable to handle SMART attributes for %s.", - dev); + if (sk_disk_smart_parse_attributes(d, handle_attribute, (void *)name) < 0) { + ERROR("smart plugin: unable to handle SMART attributes for %s.", name); + } +} + +static void smart_handle_disk(const char *dev, const char *serial) { + SkDisk *d = NULL; + const char *name; + + if (use_serial && serial) { + name = serial; + } else { + name = strrchr(dev, '/'); + if (!name) + return; + name++; + } + if (ignorelist_match(ignorelist, name) != 0) { + DEBUG("smart plugin: ignoring %s.", dev); + return; } -end: + DEBUG("smart plugin: checking SMART status of %s.", dev); + if (sk_disk_open(dev, &d) < 0) { + ERROR("smart plugin: unable to open %s.", dev); + return; + } + + smart_read_disk(d, name); sk_disk_free(d); } -static int smart_read (void) -{ +static int smart_read(void) { struct udev *handle_udev; struct udev_enumerate *enumerate; struct udev_list_entry *devices, *dev_list_entry; @@ -258,38 +215,52 @@ static int smart_read (void) /* Use udev to get a list of disks */ handle_udev = udev_new(); - if (!handle_udev) - { - ERROR ("smart plugin: unable to initialize udev."); - return (-1); + if (!handle_udev) { + ERROR("smart plugin: unable to initialize udev."); + return -1; } - enumerate = udev_enumerate_new (handle_udev); - udev_enumerate_add_match_subsystem (enumerate, "block"); - udev_enumerate_add_match_property (enumerate, "DEVTYPE", "disk"); - udev_enumerate_scan_devices (enumerate); - devices = udev_enumerate_get_list_entry (enumerate); - udev_list_entry_foreach (dev_list_entry, devices) - { + enumerate = udev_enumerate_new(handle_udev); + udev_enumerate_add_match_subsystem(enumerate, "block"); + udev_enumerate_add_match_property(enumerate, "DEVTYPE", "disk"); + udev_enumerate_scan_devices(enumerate); + devices = udev_enumerate_get_list_entry(enumerate); + udev_list_entry_foreach(dev_list_entry, devices) { const char *path, *devpath, *serial; - path = udev_list_entry_get_name (dev_list_entry); - dev = udev_device_new_from_syspath (handle_udev, path); - devpath = udev_device_get_devnode (dev); - serial = udev_device_get_property_value (dev, "ID_SERIAL"); + path = udev_list_entry_get_name(dev_list_entry); + dev = udev_device_new_from_syspath(handle_udev, path); + devpath = udev_device_get_devnode(dev); + serial = udev_device_get_property_value(dev, "ID_SERIAL"); /* Query status with libatasmart */ - smart_handle_disk (devpath, serial); - udev_device_unref (dev); + smart_handle_disk(devpath, serial); + udev_device_unref(dev); } - udev_enumerate_unref (enumerate); - udev_unref (handle_udev); + udev_enumerate_unref(enumerate); + udev_unref(handle_udev); - return (0); + return 0; } /* int smart_read */ -void module_register (void) -{ - plugin_register_config ("smart", smart_config, - config_keys, config_keys_num); - plugin_register_read ("smart", smart_read); +static int smart_init(void) { +#if defined(HAVE_SYS_CAPABILITY_H) && defined(CAP_SYS_RAWIO) + if (check_capability(CAP_SYS_RAWIO) != 0) { + if (getuid() == 0) + WARNING("smart plugin: Running collectd as root, but the " + "CAP_SYS_RAWIO capability is missing. The plugin's read " + "function will probably fail. Is your init system dropping " + "capabilities?"); + else + WARNING("smart plugin: collectd doesn't have the CAP_SYS_RAWIO " + "capability. If you don't want to run collectd as root, try " + "running \"setcap cap_sys_rawio=ep\" on the collectd binary."); + } +#endif + return 0; +} /* int smart_init */ + +void module_register(void) { + plugin_register_config("smart", smart_config, config_keys, config_keys_num); + plugin_register_init("smart", smart_init); + plugin_register_read("smart", smart_read); } /* void module_register */