X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fdisk.c;h=c809fdb6a33c0762b6b002a6a66367e1a884660c;hb=ec6fec62b15992b22774233c6a915e46673b25af;hp=c63b49db1210b97123072ebad15004e1ad113242;hpb=582ea8b1552ea27f51d7f0face43fcaf303d8056;p=collectd.git diff --git a/src/disk.c b/src/disk.c index c63b49db..c809fdb6 100644 --- a/src/disk.c +++ b/src/disk.c @@ -23,6 +23,7 @@ #include "collectd.h" #include "common.h" #include "plugin.h" +#include "utils_debug.h" #define MODULE_NAME "disk" @@ -47,6 +48,12 @@ #if HAVE_IOKIT_IOTYPES_H # include #endif +#if HAVE_IOKIT_STORAGE_IOBLOCKSTORAGEDRIVER_H +# include +#endif +#if HAVE_IOKIT_IOBSD_H +# include +#endif #if HAVE_IOKIT_IOKITLIB_H || KERNEL_LINUX || HAVE_LIBKSTAT # define DISK_HAVE_READ 1 @@ -94,8 +101,8 @@ typedef struct diskstats /* This overflows in roughly 1361 year */ unsigned int poll_count; - unsigned int read_sectors; - unsigned int write_sectors; + unsigned long long read_sectors; + unsigned long long write_sectors; unsigned long long read_bytes; unsigned long long write_bytes; @@ -104,6 +111,7 @@ typedef struct diskstats } diskstats_t; static diskstats_t *disklist; +static int min_poll_count; /* #endif KERNEL_LINUX */ #elif HAVE_LIBKSTAT @@ -136,7 +144,17 @@ static void disk_init (void) /* #endif HAVE_IOKIT_IOKITLIB_H */ #elif KERNEL_LINUX - /* No init needed */ + 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); /* #endif KERNEL_LINUX */ #elif HAVE_LIBKSTAT @@ -212,9 +230,13 @@ static void disk_submit (char *disk_name, write_time) >= BUFSIZE) return; + DBG ("disk_name = %s; buf = %s;", + disk_name, buf); + plugin_submit (MODULE_NAME, disk_name, buf); } +#if KERNEL_LINUX || HAVE_LIBKSTAT static void partition_submit (char *part_name, unsigned long long read_count, unsigned long long read_bytes, @@ -231,6 +253,7 @@ static void partition_submit (char *part_name, plugin_submit ("partition", part_name, buf); } +#endif /* KERNEL_LINUX || HAVE_LIBKSTAT */ #undef BUFSIZE #if HAVE_IOKIT_IOKITLIB_H @@ -238,17 +261,33 @@ static signed long long dict_get_value (CFDictionaryRef dict, const char *key) { signed long long val_int; CFNumberRef val_obj; + CFStringRef key_obj; + + /* `key_obj' needs to be released. */ + key_obj = CFStringCreateWithCString (kCFAllocatorDefault, key, + kCFStringEncodingASCII); + if (key_obj == NULL) + { + DBG ("CFStringCreateWithCString (%s) failed.", key); + return (-1LL); + } /* get => we don't need to release (== free) the object */ - val_obj = (CFNumberRef) CFDictionaryGetValue (dict, - CFSTR (key)); + val_obj = (CFNumberRef) CFDictionaryGetValue (dict, key_obj); + + CFRelease (key_obj); - if (number == NULL) + if (val_obj == NULL) + { + DBG ("CFDictionaryGetValue (%s) failed.", key); return (-1LL); + } - if (CFNumberGetValue (val_obj, kCFNumberSInt64Type, &val_int) - != kIOReturnSuccess) + if (!CFNumberGetValue (val_obj, kCFNumberSInt64Type, &val_int)) + { + DBG ("CFNumberGetValue (%s) failed.", key); return (-1LL); + } return (val_int); } @@ -257,10 +296,13 @@ static signed long long dict_get_value (CFDictionaryRef dict, const char *key) static void disk_read (void) { #if HAVE_IOKIT_IOKITLIB_H - CFDictionaryRef props_dict; - CFDictionaryRef stats_dict; io_registry_entry_t disk; + io_registry_entry_t disk_child; io_iterator_t disk_list; + CFDictionaryRef props_dict; + CFDictionaryRef stats_dict; + CFDictionaryRef child_dict; + kern_return_t status; signed long long read_ops; signed long long read_byt; @@ -269,19 +311,42 @@ static void disk_read (void) signed long long write_byt; signed long long write_tme; + int disk_major; + 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) { - syslog (LOG_ERR, "disk-plugin: IOServiceGetMatchingServices failed."); + plugin_complain (LOG_ERR, &complain_obj, "disk plugin: " + "IOServiceGetMatchingServices failed."); return; } + else if (complain_obj.interval != 0) + { + plugin_relief (LOG_NOTICE, &complain_obj, "disk plugin: " + "IOServiceGetMatchingServices succeeded."); + } - while ((disk = IOIteratorNext (disk_list)) != NULL) + while ((disk = IOIteratorNext (disk_list)) != 0) { props_dict = NULL; stats_dict = NULL; + child_dict = NULL; + + /* `disk_child' must be released */ + if ((status = IORegistryEntryGetChildEntry (disk, kIOServicePlane, &disk_child)) + != kIOReturnSuccess) + { + /* This fails for example for DVD/CD drives.. */ + DBG ("IORegistryEntryGetChildEntry (disk) failed: 0x%08x", status); + IOObjectRelease (disk); + continue; + } /* We create `props_dict' => we need to release it later */ if (IORegistryEntryCreateCFProperties (disk, @@ -291,21 +356,49 @@ static void disk_read (void) != kIOReturnSuccess) { syslog (LOG_ERR, "disk-plugin: IORegistryEntryCreateCFProperties failed."); + IOObjectRelease (disk_child); + IOObjectRelease (disk); continue; } if (props_dict == NULL) + { + DBG ("IORegistryEntryCreateCFProperties (disk) failed."); + IOObjectRelease (disk_child); + IOObjectRelease (disk); continue; + } stats_dict = (CFDictionaryRef) CFDictionaryGetValue (props_dict, CFSTR (kIOBlockStorageDriverStatisticsKey)); if (stats_dict == NULL) { + DBG ("CFDictionaryGetValue (%s) failed.", + kIOBlockStorageDriverStatisticsKey); + CFRelease (props_dict); + IOObjectRelease (disk_child); + IOObjectRelease (disk); + continue; + } + + if (IORegistryEntryCreateCFProperties (disk_child, + (CFMutableDictionaryRef *) &child_dict, + kCFAllocatorDefault, + kNilOptions) + != kIOReturnSuccess) + { + DBG ("IORegistryEntryCreateCFProperties (disk_child) failed."); + IOObjectRelease (disk_child); CFRelease (props_dict); + IOObjectRelease (disk); continue; } + disk_major = (int) dict_get_value (child_dict, + kIOBSDMajorKey); + disk_minor = (int) dict_get_value (child_dict, + kIOBSDMinorKey); read_ops = dict_get_value (stats_dict, kIOBlockStorageDriverStatisticsReadsKey); read_byt = dict_get_value (stats_dict, @@ -319,16 +412,29 @@ static void disk_read (void) write_tme = dict_get_value (stats_dict, kIOBlockStorageDriverStatisticsTotalWriteTimeKey); + if (snprintf (disk_name, 64, "%i-%i", disk_major, disk_minor) >= 64) + { + DBG ("snprintf (major, minor) failed."); + CFRelease (child_dict); + IOObjectRelease (disk_child); + CFRelease (props_dict); + IOObjectRelease (disk); + continue; + } + DBG ("disk_name = %s", disk_name); + if ((read_ops != -1LL) || (read_byt != -1LL) || (read_tme != -1LL) || (write_ops != -1LL) || (write_byt != -1LL) || (write_tme != -1LL)) - disk_submit (kIOBlockStorageDriverClass, /* FIXME */ + disk_submit (disk_name, read_ops, 0ULL, read_byt, read_tme, write_ops, 0ULL, write_byt, write_tme); + CFRelease (child_dict); + IOObjectRelease (disk_child); CFRelease (props_dict); IOObjectRelease (disk); } @@ -347,30 +453,37 @@ static void disk_read (void) int major = 0; int minor = 0; - unsigned int read_sectors; - unsigned int write_sectors; - - unsigned long long read_count = 0; - unsigned long long read_merged = 0; - unsigned long long read_bytes = 0; - unsigned long long read_time = 0; - unsigned long long write_count = 0; - unsigned long long write_merged = 0; - unsigned long long write_bytes = 0; - unsigned long long write_time = 0; + unsigned long long read_sectors = 0ULL; + unsigned long long write_sectors = 0ULL; + + unsigned long long read_count = 0ULL; + unsigned long long read_merged = 0ULL; + unsigned long long read_bytes = 0ULL; + unsigned long long read_time = 0ULL; + unsigned long long write_count = 0ULL; + unsigned long long write_merged = 0ULL; + unsigned long long write_bytes = 0ULL; + unsigned long long write_time = 0ULL; 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) + { + plugin_complain (LOG_ERR, &complain_obj, "disk plugin: Failed to open /proc/{diskstats,partitions}."); return; + } /* Kernel is 2.4.* */ fieldshift = 1; } + plugin_relief (LOG_NOTICE, &complain_obj, "disk plugin: Succeeded to open /proc/{diskstats,partitions}."); + while (fgets (buffer, 1024, fh) != NULL) { numfields = strsplit (buffer, fields, 32); @@ -411,17 +524,17 @@ static void disk_read (void) { /* Kernel 2.6, Partition */ read_count = atoll (fields[3]); - read_sectors = atoi (fields[4]); + read_sectors = atoll (fields[4]); write_count = atoll (fields[5]); - write_sectors = atoi (fields[6]); + write_sectors = atoll (fields[6]); } else if (numfields == (14 + fieldshift)) { read_count = atoll (fields[3 + fieldshift]); write_count = atoll (fields[7 + fieldshift]); - read_sectors = atoi (fields[5 + fieldshift]); - write_sectors = atoi (fields[9 + fieldshift]); + read_sectors = atoll (fields[5 + fieldshift]); + write_sectors = atoll (fields[9 + fieldshift]); if ((fieldshift == 0) || (minor == 0)) { @@ -434,19 +547,20 @@ static void disk_read (void) } else { + DBG ("numfields = %i; => unknown file format.", numfields); continue; } - - if (read_sectors >= ds->read_sectors) - ds->read_bytes += 512 * (read_sectors - ds->read_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 * ((UINT_MAX - ds->read_sectors) + read_sectors); + ds->read_bytes += 512 * (read_sectors - ds->read_sectors); - if (write_sectors >= ds->write_sectors) - ds->write_bytes += 512 * (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 * ((UINT_MAX - ds->write_sectors) + write_sectors); + ds->write_bytes += 512 * (write_sectors - ds->write_sectors); ds->read_sectors = read_sectors; ds->write_sectors = write_sectors; @@ -455,11 +569,18 @@ static void disk_read (void) /* Don't write to the RRDs if we've just started.. */ ds->poll_count++; - if (ds->poll_count <= 6) + if (ds->poll_count <= min_poll_count) + { + DBG ("(ds->poll_count = %i) <= (min_poll_count = %i); => Not writing.", + ds->poll_count, min_poll_count); continue; + } if ((read_count == 0) && (write_count == 0)) + { + DBG ("((read_count == 0) && (write_count == 0)); => Not writing."); continue; + } if (is_disk) disk_submit (disk_name, read_count, read_merged, read_bytes, read_time,