X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fdisk.c;h=8830403ea60b8533211e7f2c2475d4967f20e362;hb=8aad55ab7d737a97d5927458b2b00885e27cae4d;hp=4a78f1bdbfb060ad1c57109dbe6acaf8c9c4dd2a;hpb=e1cbbf3d7bce76be363f28f83ac87c59156ef2a2;p=collectd.git diff --git a/src/disk.c b/src/disk.c index 4a78f1bd..8830403e 100644 --- a/src/disk.c +++ b/src/disk.c @@ -1,6 +1,6 @@ /** * collectd - src/disk.c - * Copyright (C) 2005-2008 Florian octo Forster + * Copyright (C) 2005-2012 Florian octo Forster * Copyright (C) 2009 Manuel Sanmartin * * This program is free software; you can redistribute it and/or modify it @@ -17,7 +17,7 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: - * Florian octo Forster + * Florian octo Forster * Manuel Sanmartin **/ @@ -75,6 +75,9 @@ #if HAVE_IOKIT_IOKITLIB_H static mach_port_t io_master_port = MACH_PORT_NULL; +/* This defaults to false for backwards compatibility. Please fix in the next + * major version. */ +static _Bool use_bsd_name = 0; /* #endif HAVE_IOKIT_IOKITLIB_H */ #elif KERNEL_LINUX @@ -85,19 +88,19 @@ typedef struct diskstats /* This overflows in roughly 1361 years */ unsigned int poll_count; - counter_t read_sectors; - counter_t write_sectors; + derive_t read_sectors; + derive_t write_sectors; - counter_t read_bytes; - counter_t write_bytes; + derive_t read_bytes; + derive_t write_bytes; - counter_t read_ops; - counter_t write_ops; - counter_t read_time; - counter_t write_time; + derive_t read_ops; + derive_t write_ops; + derive_t read_time; + derive_t write_time; - counter_t avg_read_time; - counter_t avg_write_time; + derive_t avg_read_time; + derive_t avg_write_time; struct diskstats *next; } diskstats_t; @@ -106,7 +109,7 @@ static diskstats_t *disklist; /* #endif KERNEL_LINUX */ #elif HAVE_LIBKSTAT -#define MAX_NUMDISK 256 +#define MAX_NUMDISK 1024 extern kstat_ctl_t *kc; static kstat_t *ksp[MAX_NUMDISK]; static int numdisk = 0; @@ -125,10 +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", - "IgnoreSelected" + "UseBSDName", + "IgnoreSelected", + "UdevNameAttr" }; static int config_keys_num = STATIC_ARRAY_SIZE (config_keys); @@ -152,6 +164,30 @@ static int disk_config (const char *key, const char *value) invert = 0; ignorelist_set_invert (ignorelist, invert); } + else if (strcasecmp ("UseBSDName", key) == 0) + { +#if HAVE_IOKIT_IOKITLIB_H + use_bsd_name = IS_TRUE (value) ? 1 : 0; +#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 { return (-1); @@ -212,7 +248,7 @@ static int disk_init (void) static void disk_submit (const char *plugin_instance, const char *type, - counter_t read, counter_t write) + derive_t read, derive_t write) { value_t values[2]; value_list_t vl = VALUE_LIST_INIT; @@ -221,8 +257,8 @@ static void disk_submit (const char *plugin_instance, if (ignorelist_match (ignorelist, plugin_instance) != 0) return; - values[0].counter = read; - values[1].counter = write; + values[0].derive = read; + values[1].derive = write; vl.values = values; vl.values_len = 2; @@ -236,15 +272,86 @@ static void disk_submit (const char *plugin_instance, } /* void disk_submit */ #if KERNEL_LINUX +static void submit_in_progress (char const *disk_name, gauge_t in_progress) +{ + value_t v; + value_list_t vl = VALUE_LIST_INIT; + + if (ignorelist_match (ignorelist, disk_name) != 0) + return; + + v.gauge = in_progress; + + vl.values = &v; + vl.values_len = 1; + sstrncpy (vl.host, hostname_g, sizeof (vl.host)); + sstrncpy (vl.plugin, "disk", sizeof (vl.plugin)); + sstrncpy (vl.plugin_instance, disk_name, sizeof (vl.plugin_instance)); + sstrncpy (vl.type, "pending_operations", sizeof (vl.type)); + + plugin_dispatch_values (&vl); +} + +static void submit_io_time (char const *plugin_instance, derive_t io_time, derive_t weighted_time) +{ + value_t values[2]; + value_list_t vl = VALUE_LIST_INIT; + + if (ignorelist_match (ignorelist, plugin_instance) != 0) + return; + + values[0].derive = io_time; + values[1].derive = weighted_time; + + vl.values = values; + vl.values_len = 2; + sstrncpy (vl.host, hostname_g, sizeof (vl.host)); + sstrncpy (vl.plugin, "disk", sizeof (vl.plugin)); + sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance)); + sstrncpy (vl.type, "disk_io_time", sizeof (vl.type)); + + plugin_dispatch_values (&vl); +} + + static counter_t disk_calc_time_incr (counter_t delta_time, counter_t delta_ops) { + double interval = CDTIME_T_TO_DOUBLE (plugin_get_interval ()); double avg_time = ((double) delta_time) / ((double) delta_ops); - double avg_time_incr = ((double) interval_g) * avg_time; + double avg_time_incr = interval * avg_time; return ((counter_t) (avg_time_incr + .5)); } #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) { @@ -291,7 +398,8 @@ static int disk_read (void) CFDictionaryRef props_dict; CFDictionaryRef stats_dict; CFDictionaryRef child_dict; - kern_return_t status; + CFStringRef tmp_cf_string_ref; + kern_return_t status; signed long long read_ops; signed long long read_byt; @@ -302,7 +410,8 @@ static int disk_read (void) int disk_major; int disk_minor; - char disk_name[64]; + char disk_name[DATA_MAX_NAME_LEN]; + char disk_name_bsd[DATA_MAX_NAME_LEN]; /* Get the list of all disk objects. */ if (IOServiceGetMatchingServices (io_master_port, @@ -350,12 +459,41 @@ static int disk_read (void) continue; } + /* tmp_cf_string_ref doesn't need to be released. */ + tmp_cf_string_ref = (CFStringRef) CFDictionaryGetValue (props_dict, + CFSTR(kIOBSDNameKey)); + if (!tmp_cf_string_ref) + { + DEBUG ("disk plugin: CFDictionaryGetValue(" + "kIOBSDNameKey) failed."); + CFRelease (props_dict); + IOObjectRelease (disk_child); + IOObjectRelease (disk); + continue; + } + assert (CFGetTypeID (tmp_cf_string_ref) == CFStringGetTypeID ()); + + memset (disk_name_bsd, 0, sizeof (disk_name_bsd)); + CFStringGetCString (tmp_cf_string_ref, + disk_name_bsd, sizeof (disk_name_bsd), + kCFStringEncodingUTF8); + if (disk_name_bsd[0] == 0) + { + ERROR ("disk plugin: CFStringGetCString() failed."); + CFRelease (props_dict); + IOObjectRelease (disk_child); + IOObjectRelease (disk); + continue; + } + DEBUG ("disk plugin: disk_name_bsd = \"%s\"", disk_name_bsd); + stats_dict = (CFDictionaryRef) CFDictionaryGetValue (props_dict, CFSTR (kIOBlockStorageDriverStatisticsKey)); if (stats_dict == NULL) { - DEBUG ("CFDictionaryGetValue (%s) failed.", + DEBUG ("disk plugin: CFDictionaryGetValue (" + "%s) failed.", kIOBlockStorageDriverStatisticsKey); CFRelease (props_dict); IOObjectRelease (disk_child); @@ -369,7 +507,8 @@ static int disk_read (void) kNilOptions) != kIOReturnSuccess) { - DEBUG ("IORegistryEntryCreateCFProperties (disk_child) failed."); + DEBUG ("disk plugin: IORegistryEntryCreateCFProperties (" + "disk_child) failed."); IOObjectRelease (disk_child); CFRelease (props_dict); IOObjectRelease (disk); @@ -399,17 +538,12 @@ static int disk_read (void) write_tme = dict_get_value (stats_dict, kIOBlockStorageDriverStatisticsTotalWriteTimeKey); - if (ssnprintf (disk_name, sizeof (disk_name), - "%i-%i", disk_major, disk_minor) >= sizeof (disk_name)) - { - DEBUG ("snprintf (major, minor) failed."); - CFRelease (child_dict); - IOObjectRelease (disk_child); - CFRelease (props_dict); - IOObjectRelease (disk); - continue; - } - DEBUG ("disk_name = %s", disk_name); + if (use_bsd_name) + sstrncpy (disk_name, disk_name_bsd, sizeof (disk_name)); + else + ssnprintf (disk_name, sizeof (disk_name), "%i-%i", + disk_major, disk_minor); + DEBUG ("disk plugin: disk_name = \"%s\"", disk_name); if ((read_byt != -1LL) || (write_byt != -1LL)) disk_submit (disk_name, "disk_octets", read_byt, write_byt); @@ -438,15 +572,18 @@ static int disk_read (void) int minor = 0; - counter_t read_sectors = 0; - counter_t write_sectors = 0; - - counter_t read_ops = 0; - counter_t read_merged = 0; - counter_t read_time = 0; - counter_t write_ops = 0; - counter_t write_merged = 0; - counter_t write_time = 0; + derive_t read_sectors = 0; + derive_t write_sectors = 0; + + derive_t read_ops = 0; + derive_t read_merged = 0; + derive_t read_time = 0; + derive_t write_ops = 0; + derive_t write_merged = 0; + derive_t write_time = 0; + gauge_t in_progress = NAN; + derive_t io_time = 0; + derive_t weighted_time = 0; int is_disk = 0; diskstats_t *ds, *pre_ds; @@ -464,9 +601,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); @@ -522,6 +665,11 @@ static int disk_read (void) read_time = atoll (fields[6 + fieldshift]); write_merged = atoll (fields[8 + fieldshift]); write_time = atoll (fields[10+ fieldshift]); + + in_progress = atof (fields[11 + fieldshift]); + + io_time = atof (fields[12 + fieldshift]); + weighted_time = atof (fields[13 + fieldshift]); } } else @@ -531,8 +679,8 @@ static int disk_read (void) } { - counter_t diff_read_sectors; - counter_t diff_write_sectors; + derive_t diff_read_sectors; + derive_t diff_write_sectors; /* If the counter wraps around, it's only 32 bits.. */ if (read_sectors < ds->read_sectors) @@ -555,18 +703,18 @@ static int disk_read (void) /* Calculate the average time an io-op needs to complete */ if (is_disk) { - counter_t diff_read_ops; - counter_t diff_write_ops; - counter_t diff_read_time; - counter_t diff_write_time; + derive_t diff_read_ops; + derive_t diff_write_ops; + derive_t diff_read_time; + derive_t diff_write_time; if (read_ops < ds->read_ops) diff_read_ops = 1 + read_ops + (UINT_MAX - ds->read_ops); else diff_read_ops = read_ops - ds->read_ops; - DEBUG ("disk plugin: disk_name = %s; read_ops = %llu; " - "ds->read_ops = %llu; diff_read_ops = %llu;", + DEBUG ("disk plugin: disk_name = %s; read_ops = %"PRIi64"; " + "ds->read_ops = %"PRIi64"; diff_read_ops = %"PRIi64";", disk_name, read_ops, ds->read_ops, diff_read_ops); @@ -618,25 +766,45 @@ 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); + submit_in_progress (output_name, in_progress); + submit_io_time (output_name, io_time, weighted_time); } /* 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) */ @@ -691,7 +859,12 @@ static int disk_read (void) #elif defined(HAVE_LIBSTATGRAB) sg_disk_io_stats *ds; - int disks, counter; +# if HAVE_LIBSTATGRAB_0_90 + size_t disks; +# else + int disks; +#endif + int counter; char name[DATA_MAX_NAME_LEN]; if ((ds = sg_get_disk_io_stats(&disks)) == NULL) @@ -706,12 +879,12 @@ static int disk_read (void) /* #endif defined(HAVE_LIBSTATGRAB) */ #elif defined(HAVE_PERFSTAT) - counter_t read_sectors; - counter_t write_sectors; - counter_t read_time; - counter_t write_time; - counter_t read_ops; - counter_t write_ops; + derive_t read_sectors; + derive_t write_sectors; + derive_t read_time; + derive_t write_time; + derive_t read_ops; + derive_t write_ops; perfstat_id_t firstpath; int rnumdisk; int i;