X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fdisk.c;h=6187459f8e93fd0088d6b5646f19b204e1e1827e;hb=61a1fa91ba73e4fe3a34949f77c5f017056f2b7a;hp=31c3ec2eba01fb008b33d47f17deac86825f47ab;hpb=e1b0c447f57338706d45a485b40da7325faa4f34;p=collectd.git diff --git a/src/disk.c b/src/disk.c index 31c3ec2e..6187459f 100644 --- a/src/disk.c +++ b/src/disk.c @@ -1,6 +1,7 @@ /** * collectd - src/disk.c - * Copyright (C) 2005-2007 Florian octo Forster + * Copyright (C) 2005-2008 Florian octo Forster + * Copyright (C) 2009 Manuel Sanmartin * * 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 @@ -17,11 +18,13 @@ * * Authors: * Florian octo Forster + * Manuel Sanmartin **/ #include "collectd.h" #include "common.h" #include "plugin.h" +#include "utils_ignorelist.h" #if HAVE_MACH_MACH_TYPES_H # include @@ -51,13 +54,25 @@ # include #endif -#if HAVE_IOKIT_IOKITLIB_H || KERNEL_LINUX || HAVE_LIBKSTAT -# define DISK_HAVE_READ 1 -#else -# define DISK_HAVE_READ 0 +#if HAVE_LIMITS_H +# include +#endif +#ifndef UINT_MAX +# define UINT_MAX 4294967295U +#endif + +#if HAVE_STATGRAB_H +# include +#endif + +#if HAVE_PERFSTAT +# ifndef _AIXVERSION_610 +# include +# endif +# include +# include #endif -#if DISK_HAVE_READ #if HAVE_IOKIT_IOKITLIB_H static mach_port_t io_master_port = MACH_PORT_NULL; /* #endif HAVE_IOKIT_IOKITLIB_H */ @@ -67,7 +82,7 @@ typedef struct diskstats { char *name; - /* This overflows in roughly 1361 year */ + /* This overflows in roughly 1361 years */ unsigned int poll_count; counter_t read_sectors; @@ -76,6 +91,14 @@ typedef struct diskstats counter_t read_bytes; counter_t write_bytes; + counter_t read_ops; + counter_t write_ops; + counter_t read_time; + counter_t write_time; + + counter_t avg_read_time; + counter_t avg_write_time; + struct diskstats *next; } diskstats_t; @@ -87,13 +110,61 @@ static diskstats_t *disklist; extern kstat_ctl_t *kc; static kstat_t *ksp[MAX_NUMDISK]; static int numdisk = 0; -#endif /* HAVE_LIBKSTAT */ +/* #endif HAVE_LIBKSTAT */ + +#elif defined(HAVE_LIBSTATGRAB) +/* #endif HAVE_LIBKSTATGRAB */ + +#elif HAVE_PERFSTAT +static perfstat_disk_t * stat_disk; +static int numdisk; +static int pnumdisk; +/* #endif HAVE_PERFSTAT */ + +#else +# error "No applicable input method." +#endif + +static const char *config_keys[] = +{ + "Disk", + "IgnoreSelected" +}; +static int config_keys_num = STATIC_ARRAY_SIZE (config_keys); + +static ignorelist_t *ignorelist = NULL; + +static int disk_config (const char *key, const char *value) +{ + if (ignorelist == NULL) + ignorelist = ignorelist_create (/* invert = */ 1); + if (ignorelist == NULL) + return (1); + + if (strcasecmp ("Disk", key) == 0) + { + ignorelist_add (ignorelist, value); + } + else if (strcasecmp ("IgnoreSelected", key) == 0) + { + int invert = 1; + if (IS_TRUE (value)) + invert = 0; + ignorelist_set_invert (ignorelist, invert); + } + else + { + return (-1); + } + + return (0); +} /* int disk_config */ static int disk_init (void) { #if HAVE_IOKIT_IOKITLIB_H kern_return_t status; - + if (io_master_port != MACH_PORT_NULL) { mach_port_deallocate (mach_task_self (), @@ -146,18 +217,22 @@ static void disk_submit (const char *plugin_instance, value_t values[2]; value_list_t vl = VALUE_LIST_INIT; + /* Both `ignorelist' and `plugin_instance' may be NULL. */ + if (ignorelist_match (ignorelist, plugin_instance) != 0) + return; + values[0].counter = read; values[1].counter = write; vl.values = values; vl.values_len = 2; - vl.time = time (NULL); - strcpy (vl.host, hostname_g); - strcpy (vl.plugin, "disk"); - strncpy (vl.plugin_instance, plugin_instance, + 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, type, sizeof (vl.type)); - plugin_dispatch_values (type, &vl); + plugin_dispatch_values (&vl); } /* void disk_submit */ #if HAVE_IOKIT_IOKITLIB_H @@ -219,22 +294,14 @@ static int disk_read (void) int disk_minor; char disk_name[64]; - static complain_t complain_obj; - /* Get the list of all disk objects. */ if (IOServiceGetMatchingServices (io_master_port, IOServiceMatching (kIOBlockStorageDriverClass), &disk_list) != kIOReturnSuccess) { - plugin_complain (LOG_ERR, &complain_obj, "disk plugin: " - "IOServiceGetMatchingServices failed."); + ERROR ("disk plugin: IOServiceGetMatchingServices failed."); return (-1); } - else if (complain_obj.interval != 0) - { - plugin_relief (LOG_NOTICE, &complain_obj, "disk plugin: " - "IOServiceGetMatchingServices succeeded."); - } while ((disk = IOIteratorNext (disk_list)) != 0) { @@ -322,7 +389,8 @@ static int disk_read (void) write_tme = dict_get_value (stats_dict, kIOBlockStorageDriverStatisticsTotalWriteTimeKey); - if (snprintf (disk_name, 64, "%i-%i", disk_major, disk_minor) >= 64) + if (ssnprintf (disk_name, sizeof (disk_name), + "%i-%i", disk_major, disk_minor) >= sizeof (disk_name)) { DEBUG ("snprintf (major, minor) failed."); CFRelease (child_dict); @@ -358,33 +426,27 @@ static int disk_read (void) int numfields; int fieldshift = 0; - int major = 0; int minor = 0; counter_t read_sectors = 0; counter_t write_sectors = 0; - counter_t read_count = 0; + counter_t read_ops = 0; counter_t read_merged = 0; - counter_t read_bytes = 0; counter_t read_time = 0; - counter_t write_count = 0; + counter_t write_ops = 0; counter_t write_merged = 0; - counter_t write_bytes = 0; counter_t write_time = 0; int is_disk = 0; diskstats_t *ds, *pre_ds; - static complain_t complain_obj; - if ((fh = fopen ("/proc/diskstats", "r")) == NULL) { - if ((fh = fopen ("/proc/partitions", "r")) == NULL) + fh = fopen ("/proc/partitions", "r"); + if (fh == NULL) { - plugin_complain (LOG_ERR, &complain_obj, - "disk plugin: Failed to open /proc/" - "{diskstats,partitions}."); + ERROR ("disk plugin: fopen (/proc/{diskstats,partitions}) failed."); return (-1); } @@ -392,9 +454,6 @@ static int disk_read (void) fieldshift = 1; } - plugin_relief (LOG_NOTICE, &complain_obj, "disk plugin: " - "Succeeded to open /proc/{diskstats,partitions}."); - while (fgets (buffer, sizeof (buffer), fh) != NULL) { char *disk_name; @@ -404,10 +463,9 @@ static int disk_read (void) if ((numfields != (14 + fieldshift)) && (numfields != 7)) continue; - major = atoll (fields[0]); minor = atoll (fields[1]); - disk_name = fields[2]; + disk_name = fields[2 + fieldshift]; for (ds = disklist, pre_ds = disklist; ds != NULL; pre_ds = ds, ds = ds->next) if (strcmp (disk_name, ds->name) == 0) @@ -434,15 +492,15 @@ static int disk_read (void) if (numfields == 7) { /* Kernel 2.6, Partition */ - read_count = atoll (fields[3]); + read_ops = atoll (fields[3]); read_sectors = atoll (fields[4]); - write_count = atoll (fields[5]); + write_ops = atoll (fields[5]); write_sectors = atoll (fields[6]); } else if (numfields == (14 + fieldshift)) { - read_count = atoll (fields[3 + fieldshift]); - write_count = atoll (fields[7 + fieldshift]); + read_ops = atoll (fields[3 + fieldshift]); + write_ops = atoll (fields[7 + fieldshift]); read_sectors = atoll (fields[5 + fieldshift]); write_sectors = atoll (fields[9 + fieldshift]); @@ -462,51 +520,113 @@ static int disk_read (void) continue; } + { + counter_t diff_read_sectors; + counter_t diff_write_sectors; + /* If the counter wraps around, it's only 32 bits.. */ - if (read_sectors < ds->read_sectors) - ds->read_bytes += 512 * ((0xFFFFFFFF - ds->read_sectors) + read_sectors); - else - ds->read_bytes += 512 * (read_sectors - ds->read_sectors); + if (read_sectors < ds->read_sectors) + diff_read_sectors = 1 + read_sectors + + (UINT_MAX - ds->read_sectors); + else + diff_read_sectors = read_sectors - ds->read_sectors; + if (write_sectors < ds->write_sectors) + diff_write_sectors = 1 + write_sectors + + (UINT_MAX - ds->write_sectors); + else + diff_write_sectors = write_sectors - ds->write_sectors; - if (write_sectors < ds->write_sectors) - ds->write_bytes += 512 * ((0xFFFFFFFF - ds->write_sectors) + write_sectors); - else - ds->write_bytes += 512 * (write_sectors - ds->write_sectors); + ds->read_bytes += 512 * diff_read_sectors; + ds->write_bytes += 512 * diff_write_sectors; + ds->read_sectors = read_sectors; + ds->write_sectors = write_sectors; + } - ds->read_sectors = read_sectors; - ds->write_sectors = write_sectors; - read_bytes = ds->read_bytes; - write_bytes = ds->write_bytes; + /* 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; + + 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;", + disk_name, + read_ops, ds->read_ops, diff_read_ops); + + if (write_ops < ds->write_ops) + diff_write_ops = 1 + write_ops + + (UINT_MAX - ds->write_ops); + else + diff_write_ops = write_ops - ds->write_ops; + + if (read_time < ds->read_time) + diff_read_time = 1 + read_time + + (UINT_MAX - ds->read_time); + else + diff_read_time = read_time - ds->read_time; + + if (write_time < ds->write_time) + diff_write_time = 1 + write_time + + (UINT_MAX - ds->write_time); + else + diff_write_time = write_time - ds->write_time; + + if (diff_read_ops != 0) + ds->avg_read_time += (diff_read_time + + (diff_read_ops / 2)) + / diff_read_ops; + if (diff_write_ops != 0) + ds->avg_write_time += (diff_write_time + + (diff_write_ops / 2)) + / diff_write_ops; + + ds->read_ops = read_ops; + ds->read_time = read_time; + ds->write_ops = write_ops; + ds->write_time = write_time; + } /* if (is_disk) */ /* Don't write to the RRDs if we've just started.. */ ds->poll_count++; if (ds->poll_count <= 2) { - DEBUG ("(ds->poll_count = %i) <= (min_poll_count = 2); => Not writing.", + DEBUG ("disk plugin: (ds->poll_count = %i) <= " + "(min_poll_count = 2); => Not writing.", ds->poll_count); continue; } - if ((read_count == 0) && (write_count == 0)) + if ((read_ops == 0) && (write_ops == 0)) { - DEBUG ("((read_count == 0) && (write_count == 0)); => Not writing."); + DEBUG ("disk plugin: ((read_ops == 0) && " + "(write_ops == 0)); => Not writing."); continue; } - if ((read_bytes != -1LL) || (write_bytes != -1LL)) - disk_submit (disk_name, "disk_octets", read_bytes, write_bytes); - if ((read_count != -1LL) || (write_count != -1LL)) - disk_submit (disk_name, "disk_ops", read_count, write_count); + if ((ds->read_bytes != 0) || (ds->write_bytes != 0)) + disk_submit (disk_name, "disk_octets", + ds->read_bytes, ds->write_bytes); + + if ((ds->read_ops != 0) || (ds->write_ops != 0)) + disk_submit (disk_name, "disk_ops", + read_ops, write_ops); + + if ((ds->avg_read_time != 0) || (ds->avg_write_time != 0)) + disk_submit (disk_name, "disk_time", + ds->avg_read_time, ds->avg_write_time); + if (is_disk) { - if ((read_merged != -1LL) || (write_merged != -1LL)) - disk_submit (disk_name, "disk_merged", - read_merged, write_merged); - if ((read_time != -1LL) || (write_time != -1LL)) - disk_submit (disk_name, "disk_time", - read_time * 1000, - write_time * 1000); - } + disk_submit (disk_name, "disk_merged", + read_merged, write_merged); + } /* if (is_disk) */ } /* while (fgets (buffer, sizeof (buffer), fh) != NULL) */ fclose (fh); @@ -559,16 +679,84 @@ static int disk_read (void) kio.KIO_ROPS, kio.KIO_WOPS); } } -#endif /* defined(HAVE_LIBKSTAT) */ +/* #endif defined(HAVE_LIBKSTAT) */ + +#elif defined(HAVE_LIBSTATGRAB) + sg_disk_io_stats *ds; + int disks, counter; + char name[DATA_MAX_NAME_LEN]; + + if ((ds = sg_get_disk_io_stats(&disks)) == NULL) + return (0); + + for (counter=0; counter < disks; counter++) { + strncpy(name, ds->disk_name, sizeof(name)); + name[sizeof(name)-1] = '\0'; /* strncpy doesn't terminate longer strings */ + disk_submit (name, "disk_octets", ds->read_bytes, ds->write_bytes); + ds++; + } +/* #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; + perfstat_id_t firstpath; + int rnumdisk; + int i; + + if ((numdisk = perfstat_disk(NULL, NULL, sizeof(perfstat_disk_t), 0)) < 0) + { + char errbuf[1024]; + WARNING ("disk plugin: perfstat_disk: %s", + sstrerror (errno, errbuf, sizeof (errbuf))); + return (-1); + } + + if (numdisk != pnumdisk || stat_disk==NULL) { + if (stat_disk!=NULL) + free(stat_disk); + stat_disk = (perfstat_disk_t *)calloc(numdisk, sizeof(perfstat_disk_t)); + } + pnumdisk = numdisk; + + firstpath.name[0]='\0'; + if ((rnumdisk = perfstat_disk(&firstpath, stat_disk, sizeof(perfstat_disk_t), numdisk)) < 0) + { + char errbuf[1024]; + WARNING ("disk plugin: perfstat_disk : %s", + sstrerror (errno, errbuf, sizeof (errbuf))); + return (-1); + } + + for (i = 0; i < rnumdisk; i++) + { + read_sectors = stat_disk[i].rblks*stat_disk[i].bsize; + write_sectors = stat_disk[i].wblks*stat_disk[i].bsize; + disk_submit (stat_disk[i].name, "disk_octets", read_sectors, write_sectors); + + read_ops = stat_disk[i].xrate; + write_ops = stat_disk[i].xfers - stat_disk[i].xrate; + disk_submit (stat_disk[i].name, "disk_ops", read_ops, write_ops); + + read_time = stat_disk[i].rserv; + read_time *= ((double)(_system_configuration.Xint)/(double)(_system_configuration.Xfrac)) / 1000000.0; + write_time = stat_disk[i].wserv; + write_time *= ((double)(_system_configuration.Xint)/(double)(_system_configuration.Xfrac)) / 1000000.0; + disk_submit (stat_disk[i].name, "disk_time", read_time, write_time); + } +#endif /* defined(HAVE_PERFSTAT) */ return (0); } /* int disk_read */ -#endif /* DISK_HAVE_READ */ void module_register (void) { -#if DISK_HAVE_READ - plugin_register_init ("disk", disk_init); - plugin_register_read ("disk", disk_read); -#endif /* DISK_HAVE_READ */ + plugin_register_config ("disk", disk_config, + config_keys, config_keys_num); + plugin_register_init ("disk", disk_init); + plugin_register_read ("disk", disk_read); } /* void module_register */