X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fdisk.c;h=490da07ae56098e2e438a835e8e4a72b1c9c110d;hb=0f0dd3b00845209b865862c073813caf44d01ae8;hp=af7c01a60e39da34d92635d9c0b9a0c5b1276621;hpb=2d897a731bd23f7a33b89e7b7e3004b6b26b5a94;p=collectd.git diff --git a/src/disk.c b/src/disk.c index af7c01a6..490da07a 100644 --- a/src/disk.c +++ b/src/disk.c @@ -22,7 +22,6 @@ #include "collectd.h" #include "common.h" #include "plugin.h" -#include "utils_debug.h" #if HAVE_MACH_MACH_TYPES_H # include @@ -52,59 +51,13 @@ # 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 -/* 2^34 = 17179869184 = ~17.2GByte/s */ -static data_source_t octets_dsrc[2] = -{ - {"read", DS_TYPE_COUNTER, 0, 17179869183.0}, - {"write", DS_TYPE_COUNTER, 0, 17179869183.0} -}; - -static data_set_t octets_ds = -{ - "disk_octets", 2, octets_dsrc -}; - -static data_source_t operations_dsrc[2] = -{ - {"read", DS_TYPE_COUNTER, 0, 4294967295.0}, - {"write", DS_TYPE_COUNTER, 0, 4294967295.0} -}; - -static data_set_t operations_ds = -{ - "disk_ops", 2, operations_dsrc -}; - -static data_source_t merged_dsrc[2] = -{ - {"read", DS_TYPE_COUNTER, 0, 4294967295.0}, - {"write", DS_TYPE_COUNTER, 0, 4294967295.0} -}; - -static data_set_t merged_ds = -{ - "disk_merged", 2, merged_dsrc -}; - -/* max is 1000000us per second. */ -static data_source_t time_dsrc[2] = -{ - {"read", DS_TYPE_COUNTER, 0, 1000000.0}, - {"write", DS_TYPE_COUNTER, 0, 1000000.0} -}; - -static data_set_t time_ds = -{ - "disk_time", 2, time_dsrc -}; - -#if DISK_HAVE_READ #if HAVE_IOKIT_IOKITLIB_H static mach_port_t io_master_port = MACH_PORT_NULL; /* #endif HAVE_IOKIT_IOKITLIB_H */ @@ -114,7 +67,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; @@ -123,11 +76,18 @@ 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; static diskstats_t *disklist; -static int min_poll_count; /* #endif KERNEL_LINUX */ #elif HAVE_LIBKSTAT @@ -135,7 +95,11 @@ static int min_poll_count; extern kstat_ctl_t *kc; static kstat_t *ksp[MAX_NUMDISK]; static int numdisk = 0; -#endif /* HAVE_LIBKSTAT */ +/* #endif HAVE_LIBKSTAT */ + +#else +# error "No applicable input method." +#endif static int disk_init (void) { @@ -152,7 +116,7 @@ static int disk_init (void) status = IOMasterPort (MACH_PORT_NULL, &io_master_port); if (status != kIOReturnSuccess) { - syslog (LOG_ERR, "IOMasterPort failed: %s", + ERROR ("IOMasterPort failed: %s", mach_error_string (status)); io_master_port = MACH_PORT_NULL; return (-1); @@ -160,17 +124,7 @@ static int disk_init (void) /* #endif HAVE_IOKIT_IOKITLIB_H */ #elif KERNEL_LINUX - int step; - int heartbeat; - - step = atoi (COLLECTD_STEP); - heartbeat = atoi (COLLECTD_HEARTBEAT); - - assert (step > 0); - assert (heartbeat >= step); - - min_poll_count = 1 + (heartbeat / step); - DBG ("min_poll_count = %i;", min_poll_count); + /* do nothing */ /* #endif KERNEL_LINUX */ #elif HAVE_LIBKSTAT @@ -230,7 +184,7 @@ static signed long long dict_get_value (CFDictionaryRef dict, const char *key) kCFStringEncodingASCII); if (key_obj == NULL) { - DBG ("CFStringCreateWithCString (%s) failed.", key); + DEBUG ("CFStringCreateWithCString (%s) failed.", key); return (-1LL); } @@ -241,13 +195,13 @@ static signed long long dict_get_value (CFDictionaryRef dict, const char *key) if (val_obj == NULL) { - DBG ("CFDictionaryGetValue (%s) failed.", key); + DEBUG ("CFDictionaryGetValue (%s) failed.", key); return (-1LL); } if (!CFNumberGetValue (val_obj, kCFNumberSInt64Type, &val_int)) { - DBG ("CFNumberGetValue (%s) failed.", key); + DEBUG ("CFNumberGetValue (%s) failed.", key); return (-1LL); } @@ -305,7 +259,7 @@ static int disk_read (void) != kIOReturnSuccess) { /* This fails for example for DVD/CD drives.. */ - DBG ("IORegistryEntryGetChildEntry (disk) failed: 0x%08x", status); + DEBUG ("IORegistryEntryGetChildEntry (disk) failed: 0x%08x", status); IOObjectRelease (disk); continue; } @@ -317,7 +271,7 @@ static int disk_read (void) kNilOptions) != kIOReturnSuccess) { - syslog (LOG_ERR, "disk-plugin: IORegistryEntryCreateCFProperties failed."); + ERROR ("disk-plugin: IORegistryEntryCreateCFProperties failed."); IOObjectRelease (disk_child); IOObjectRelease (disk); continue; @@ -325,7 +279,7 @@ static int disk_read (void) if (props_dict == NULL) { - DBG ("IORegistryEntryCreateCFProperties (disk) failed."); + DEBUG ("IORegistryEntryCreateCFProperties (disk) failed."); IOObjectRelease (disk_child); IOObjectRelease (disk); continue; @@ -336,7 +290,7 @@ static int disk_read (void) if (stats_dict == NULL) { - DBG ("CFDictionaryGetValue (%s) failed.", + DEBUG ("CFDictionaryGetValue (%s) failed.", kIOBlockStorageDriverStatisticsKey); CFRelease (props_dict); IOObjectRelease (disk_child); @@ -350,7 +304,7 @@ static int disk_read (void) kNilOptions) != kIOReturnSuccess) { - DBG ("IORegistryEntryCreateCFProperties (disk_child) failed."); + DEBUG ("IORegistryEntryCreateCFProperties (disk_child) failed."); IOObjectRelease (disk_child); CFRelease (props_dict); IOObjectRelease (disk); @@ -382,14 +336,14 @@ static int disk_read (void) if (snprintf (disk_name, 64, "%i-%i", disk_major, disk_minor) >= 64) { - DBG ("snprintf (major, minor) failed."); + DEBUG ("snprintf (major, minor) failed."); CFRelease (child_dict); IOObjectRelease (disk_child); CFRelease (props_dict); IOObjectRelease (disk); continue; } - DBG ("disk_name = %s", disk_name); + DEBUG ("disk_name = %s", disk_name); if ((read_byt != -1LL) || (write_byt != -1LL)) disk_submit (disk_name, "disk_octets", read_byt, write_byt); @@ -422,13 +376,11 @@ static int disk_read (void) 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; @@ -492,15 +444,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]); @@ -516,61 +468,141 @@ static int disk_read (void) } else { - DBG ("numfields = %i; => unknown file format.", numfields); + DEBUG ("numfields = %i; => unknown file format.", numfields); 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; + } + + /* 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; - ds->read_sectors = read_sectors; - ds->write_sectors = write_sectors; - read_bytes = ds->read_bytes; - write_bytes = ds->write_bytes; + 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 <= min_poll_count) + if (ds->poll_count <= 2) { - DBG ("(ds->poll_count = %i) <= (min_poll_count = %i); => Not writing.", - ds->poll_count, min_poll_count); + 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)) { - DBG ("((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); - } + } /* if (is_disk) */ } /* while (fgets (buffer, sizeof (buffer), fh) != NULL) */ fclose (fh); /* #endif defined(KERNEL_LINUX) */ #elif HAVE_LIBKSTAT +# if HAVE_KSTAT_IO_T_WRITES && HAVE_KSTAT_IO_T_NWRITES && HAVE_KSTAT_IO_T_WTIME +# define KIO_ROCTETS reads +# define KIO_WOCTETS writes +# define KIO_ROPS nreads +# define KIO_WOPS nwrites +# define KIO_RTIME rtime +# define KIO_WTIME wtime +# elif HAVE_KSTAT_IO_T_NWRITTEN && HAVE_KSTAT_IO_T_WRITES && HAVE_KSTAT_IO_T_WTIME +# define KIO_ROCTETS nread +# define KIO_WOCTETS nwritten +# define KIO_ROPS reads +# define KIO_WOPS writes +# define KIO_RTIME rtime +# define KIO_WTIME wtime +# else +# error "kstat_io_t does not have the required members" +# endif static kstat_io_t kio; int i; @@ -584,32 +616,29 @@ static int disk_read (void) if (strncmp (ksp[i]->ks_class, "disk", 4) == 0) { - disk_submit (ksp[i]->ks_name, "disk_octets", kio.reads, kio.writes); - disk_submit (ksp[i]->ks_name, "disk_ops", kio.nreads, kio.nwrites); + disk_submit (ksp[i]->ks_name, "disk_octets", + kio.KIO_ROCTETS, kio.KIO_WOCTETS); + disk_submit (ksp[i]->ks_name, "disk_ops", + kio.KIO_ROPS, kio.KIO_WOPS); /* FIXME: Convert this to microseconds if necessary */ - disk_submit (ksp[i]->ks_name, "disk_time", kio.rtime, kio.wtime); + disk_submit (ksp[i]->ks_name, "disk_time", + kio.KIO_RTIME, kio.KIO_WTIME); } else if (strncmp (ksp[i]->ks_class, "partition", 9) == 0) { - disk_submit (ksp[i]->ks_name, "disk_octets", kio.reads, kio.writes); - disk_submit (ksp[i]->ks_name, "disk_ops", kio.nreads, kio.nwrites); + disk_submit (ksp[i]->ks_name, "disk_octets", + kio.KIO_ROCTETS, kio.KIO_WOCTETS); + disk_submit (ksp[i]->ks_name, "disk_ops", + kio.KIO_ROPS, kio.KIO_WOPS); } } #endif /* defined(HAVE_LIBKSTAT) */ return (0); } /* int disk_read */ -#endif /* DISK_HAVE_READ */ void module_register (void) { - plugin_register_data_set (&octets_ds); - plugin_register_data_set (&operations_ds); - plugin_register_data_set (&merged_ds); - plugin_register_data_set (&time_ds); - -#if DISK_HAVE_READ plugin_register_init ("disk", disk_init); plugin_register_read ("disk", disk_read); -#endif /* DISK_HAVE_READ */ -} +} /* void module_register */