X-Git-Url: https://git.octo.it/?p=collectd.git;a=blobdiff_plain;f=src%2Fsmart.c;h=30680be6ed4b5d0565ea27a4a46c453e3f3c1051;hp=373839e13fb7ea565cdcf68685c7b0b5d985cc0a;hb=1159cb5d383c55a80a0db100b8f7aadcf44740a5;hpb=facbb03bdd0c591344b1a81dd0437064cfcc24e5 diff --git a/src/smart.c b/src/smart.c index 373839e1..30680be6 100644 --- a/src/smart.c +++ b/src/smart.c @@ -33,6 +33,10 @@ #include #include +#ifdef HAVE_SYS_CAPABILITY_H +#include +#endif + static const char *config_keys[] = {"Disk", "IgnoreSelected", "IgnoreSleepMode", "UseSerial"}; @@ -46,7 +50,7 @@ static int smart_config(const char *key, const char *value) { if (ignorelist == NULL) ignorelist = ignorelist_create(/* invert = */ 1); if (ignorelist == NULL) - return (1); + return 1; if (strcasecmp("Disk", key) == 0) { ignorelist_add(ignorelist, value); @@ -62,10 +66,10 @@ static int smart_config(const char *key, const char *value) { if (IS_TRUE(value)) use_serial = 1; } else { - return (-1); + return -1; } - return (0); + return 0; } /* int smart_config */ static void smart_submit(const char *dev, const char *type, @@ -82,10 +86,9 @@ static void smart_submit(const char *dev, const char *type, 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; @@ -101,7 +104,7 @@ static void smart_handle_disk_attribute(SkDisk *d, 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.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)); @@ -111,95 +114,96 @@ static void smart_handle_disk_attribute(SkDisk *d, 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.plugin_instance, name, 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); + 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); - 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); - return; - } if (sk_disk_identify_is_available(d, &available) < 0 || !available) { - DEBUG("smart plugin: disk %s cannot be identified.", dev); - goto end; + DEBUG("smart plugin: disk %s cannot be identified.", name); + return; } if (sk_disk_smart_is_available(d, &available) < 0 || !available) { - DEBUG("smart plugin: disk %s has no SMART support.", dev); - goto end; + DEBUG("smart plugin: disk %s has no SMART support.", name); + return; } if (!ignore_sleep_mode) { + SkBool awake = FALSE; if (sk_disk_check_sleep_mode(d, &awake) < 0 || !awake) { - DEBUG("smart plugin: disk %s is sleeping.", dev); - goto end; + 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; + 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); - } else - smart_submit(shortname, "smart_poweron", "", poweron / 1000.); - - if (sk_disk_smart_get_power_cycle(d, &powercycles) < 0) { - WARNING("smart plugin: unable to get number of power cycles for %s.", dev); - } else - smart_submit(shortname, "smart_powercycles", "", powercycles); - - if (sk_disk_smart_get_bad(d, &badsectors) < 0) { - WARNING("smart plugin: unable to get number of bad sectors for %s.", dev); - } else - smart_submit(shortname, "smart_badsectors", "", badsectors); - - if (sk_disk_smart_get_temperature(d, &temperature) < 0) { - WARNING("smart plugin: unable to get temperature for %s.", dev); - } else - smart_submit(shortname, "smart_temperature", "", - temperature / 1000. - 273.15); + uint64_t value; + if (sk_disk_smart_get_power_on(d, &value) >= 0) + smart_submit(name, "smart_poweron", "", ((gauge_t)value) / 1000.); + else + DEBUG("smart plugin: unable to get milliseconds since power on for %s.", + name); + + if (sk_disk_smart_get_power_cycle(d, &value) >= 0) + smart_submit(name, "smart_powercycles", "", (gauge_t)value); + else + DEBUG("smart plugin: unable to get number of power cycles for %s.", name); + + if (sk_disk_smart_get_bad(d, &value) >= 0) + smart_submit(name, "smart_badsectors", "", (gauge_t)value); + else + DEBUG("smart plugin: unable to get number of bad sectors for %s.", name); + + if (sk_disk_smart_get_temperature(d, &value) >= 0) + smart_submit(name, "smart_temperature", "", + ((gauge_t)value) / 1000. - 273.15); + else + 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); } @@ -213,7 +217,7 @@ static int smart_read(void) { handle_udev = udev_new(); if (!handle_udev) { ERROR("smart plugin: unable to initialize udev."); - return (-1); + return -1; } enumerate = udev_enumerate_new(handle_udev); udev_enumerate_add_match_subsystem(enumerate, "block"); @@ -235,10 +239,28 @@ static int smart_read(void) { udev_enumerate_unref(enumerate); udev_unref(handle_udev); - return (0); + return 0; } /* int 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 */