X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fdisk.c;h=8feaa8dff6fe77d8127c20c9afdaa9fd2530d14d;hb=108068f268cad453e5d3b54e288917409db1e467;hp=ded2080626f1a12dfba17f776909127153ce945d;hpb=3c0f5d53afde12740b34a35b2127f9c664342c8f;p=collectd.git diff --git a/src/disk.c b/src/disk.c index ded20806..489770c7 100644 --- a/src/disk.c +++ b/src/disk.c @@ -1,11 +1,10 @@ /** * collectd - src/disk.c - * Copyright (C) 2005,2006 Florian octo Forster + * Copyright (C) 2005-2008 Florian octo Forster * * 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 - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. + * Free Software Foundation; only version 2 of the License is applicable. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of @@ -23,79 +22,163 @@ #include "collectd.h" #include "common.h" #include "plugin.h" +#include "utils_ignorelist.h" -#define MODULE_NAME "disk" +#if HAVE_MACH_MACH_TYPES_H +# include +#endif +#if HAVE_MACH_MACH_INIT_H +# include +#endif +#if HAVE_MACH_MACH_ERROR_H +# include +#endif +#if HAVE_MACH_MACH_PORT_H +# include +#endif +#if HAVE_COREFOUNDATION_COREFOUNDATION_H +# include +#endif +#if HAVE_IOKIT_IOKITLIB_H +# include +#endif +#if HAVE_IOKIT_IOTYPES_H +# include +#endif +#if HAVE_IOKIT_STORAGE_IOBLOCKSTORAGEDRIVER_H +# include +#endif +#if HAVE_IOKIT_IOBSD_H +# include +#endif -#if defined(KERNEL_LINUX) || defined(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 -static char *disk_filename_template = "disk-%s.rrd"; -static char *part_filename_template = "partition-%s.rrd"; +#if HAVE_STATGRAB_H +# include +#endif -/* 104857600 == 100 MB */ -static char *disk_ds_def[] = -{ - "DS:rcount:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:rmerged:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:rbytes:COUNTER:"COLLECTD_HEARTBEAT":0:104857600", - "DS:rtime:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:wcount:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:wmerged:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:wbytes:COUNTER:"COLLECTD_HEARTBEAT":0:104857600", - "DS:wtime:COUNTER:"COLLECTD_HEARTBEAT":0:U", - NULL -}; -static int disk_ds_num = 8; +#if HAVE_IOKIT_IOKITLIB_H +static mach_port_t io_master_port = MACH_PORT_NULL; +/* #endif HAVE_IOKIT_IOKITLIB_H */ -static char *part_ds_def[] = -{ - "DS:rcount:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:rbytes:COUNTER:"COLLECTD_HEARTBEAT":0:104857600", - "DS:wcount:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:wbytes:COUNTER:"COLLECTD_HEARTBEAT":0:104857600", - NULL -}; -static int part_ds_num = 4; - -#ifdef KERNEL_LINUX +#elif KERNEL_LINUX typedef struct diskstats { char *name; - /* This overflows in roughly 1361 year */ + /* This overflows in roughly 1361 years */ unsigned int poll_count; - unsigned int read_sectors; - unsigned int write_sectors; + counter_t read_sectors; + counter_t write_sectors; + + counter_t read_bytes; + counter_t write_bytes; - unsigned long long read_bytes; - unsigned long long 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; -/* #endif defined(KERNEL_LINUX) */ +/* #endif KERNEL_LINUX */ -#elif defined(HAVE_LIBKSTAT) +#elif HAVE_LIBKSTAT #define MAX_NUMDISK 256 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 */ -static void disk_init (void) +#else +# error "No applicable input method." +#endif + +static const char *config_keys[] = { -#ifdef HAVE_LIBKSTAT + "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 ((strcasecmp ("True", value) == 0) + || (strcasecmp ("Yes", value) == 0) + || (strcasecmp ("On", value) == 0)) + 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 (), + io_master_port); + io_master_port = MACH_PORT_NULL; + } + + status = IOMasterPort (MACH_PORT_NULL, &io_master_port); + if (status != kIOReturnSuccess) + { + ERROR ("IOMasterPort failed: %s", + mach_error_string (status)); + io_master_port = MACH_PORT_NULL; + return (-1); + } +/* #endif HAVE_IOKIT_IOKITLIB_H */ + +#elif KERNEL_LINUX + /* do nothing */ +/* #endif KERNEL_LINUX */ + +#elif HAVE_LIBKSTAT kstat_t *ksp_chain; numdisk = 0; if (kc == NULL) - return; + return (-1); for (numdisk = 0, ksp_chain = kc->kc_chain; (numdisk < MAX_NUMDISK) && (ksp_chain != NULL); @@ -108,87 +191,222 @@ static void disk_init (void) continue; ksp[numdisk++] = ksp_chain; } -#endif +#endif /* HAVE_LIBKSTAT */ - return; -} + return (0); +} /* int disk_init */ -static void disk_write (char *host, char *inst, char *val) +static void disk_submit (const char *plugin_instance, + const char *type, + counter_t read, counter_t write) { - char file[512]; - int status; + value_t values[2]; + value_list_t vl = VALUE_LIST_INIT; - status = snprintf (file, 512, disk_filename_template, inst); - if (status < 1) - return; - else if (status >= 512) - return; + /* Both `ignorelist' and `plugin_instance' may be NULL. */ + if (ignorelist_match (ignorelist, plugin_instance) != 0) + return; - rrd_update_file (host, file, val, disk_ds_def, disk_ds_num); -} + values[0].counter = read; + values[1].counter = write; + + 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, type, sizeof (vl.type)); -static void partition_write (char *host, char *inst, char *val) + plugin_dispatch_values (&vl); +} /* void disk_submit */ + +#if HAVE_IOKIT_IOKITLIB_H +static signed long long dict_get_value (CFDictionaryRef dict, const char *key) { - char file[512]; - int status; + 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) + { + DEBUG ("CFStringCreateWithCString (%s) failed.", key); + return (-1LL); + } + + /* get => we don't need to release (== free) the object */ + val_obj = (CFNumberRef) CFDictionaryGetValue (dict, key_obj); + + CFRelease (key_obj); + + if (val_obj == NULL) + { + DEBUG ("CFDictionaryGetValue (%s) failed.", key); + return (-1LL); + } - status = snprintf (file, 512, part_filename_template, inst); - if (status < 1) - return; - else if (status >= 512) - return; + if (!CFNumberGetValue (val_obj, kCFNumberSInt64Type, &val_int)) + { + DEBUG ("CFNumberGetValue (%s) failed.", key); + return (-1LL); + } - rrd_update_file (host, file, val, part_ds_def, part_ds_num); + return (val_int); } +#endif /* HAVE_IOKIT_IOKITLIB_H */ -#if DISK_HAVE_READ -#define BUFSIZE 512 -static void disk_submit (char *disk_name, - unsigned long long read_count, - unsigned long long read_merged, - unsigned long long read_bytes, - unsigned long long read_time, - unsigned long long write_count, - unsigned long long write_merged, - unsigned long long write_bytes, - unsigned long long write_time) +static int disk_read (void) { - char buf[BUFSIZE]; +#if HAVE_IOKIT_IOKITLIB_H + 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; + signed long long read_tme; + signed long long write_ops; + signed long long write_byt; + signed long long write_tme; + + int disk_major; + int disk_minor; + char disk_name[64]; + + /* Get the list of all disk objects. */ + if (IOServiceGetMatchingServices (io_master_port, + IOServiceMatching (kIOBlockStorageDriverClass), + &disk_list) != kIOReturnSuccess) + { + ERROR ("disk plugin: IOServiceGetMatchingServices failed."); + return (-1); + } - if (snprintf (buf, BUFSIZE, "%u:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu", - (unsigned int) curtime, - read_count, read_merged, read_bytes, read_time, - write_count, write_merged, write_bytes, - write_time) >= BUFSIZE) - return; + while ((disk = IOIteratorNext (disk_list)) != 0) + { + props_dict = NULL; + stats_dict = NULL; + child_dict = NULL; - plugin_submit (MODULE_NAME, disk_name, buf); -} + /* `disk_child' must be released */ + if ((status = IORegistryEntryGetChildEntry (disk, kIOServicePlane, &disk_child)) + != kIOReturnSuccess) + { + /* This fails for example for DVD/CD drives.. */ + DEBUG ("IORegistryEntryGetChildEntry (disk) failed: 0x%08x", status); + IOObjectRelease (disk); + continue; + } -static void partition_submit (char *part_name, - unsigned long long read_count, - unsigned long long read_bytes, - unsigned long long write_count, - unsigned long long write_bytes) -{ - char buf[BUFSIZE]; + /* We create `props_dict' => we need to release it later */ + if (IORegistryEntryCreateCFProperties (disk, + (CFMutableDictionaryRef *) &props_dict, + kCFAllocatorDefault, + kNilOptions) + != kIOReturnSuccess) + { + ERROR ("disk-plugin: IORegistryEntryCreateCFProperties failed."); + IOObjectRelease (disk_child); + IOObjectRelease (disk); + continue; + } - if (snprintf (buf, BUFSIZE, "%u:%llu:%llu:%llu:%llu", - (unsigned int) curtime, - read_count, read_bytes, write_count, - write_bytes) >= BUFSIZE) - return; + if (props_dict == NULL) + { + DEBUG ("IORegistryEntryCreateCFProperties (disk) failed."); + IOObjectRelease (disk_child); + IOObjectRelease (disk); + continue; + } - plugin_submit ("partition", part_name, buf); -} -#undef BUFSIZE + stats_dict = (CFDictionaryRef) CFDictionaryGetValue (props_dict, + CFSTR (kIOBlockStorageDriverStatisticsKey)); -static void disk_read (void) -{ -#ifdef KERNEL_LINUX + if (stats_dict == NULL) + { + DEBUG ("CFDictionaryGetValue (%s) failed.", + kIOBlockStorageDriverStatisticsKey); + CFRelease (props_dict); + IOObjectRelease (disk_child); + IOObjectRelease (disk); + continue; + } + + if (IORegistryEntryCreateCFProperties (disk_child, + (CFMutableDictionaryRef *) &child_dict, + kCFAllocatorDefault, + kNilOptions) + != kIOReturnSuccess) + { + DEBUG ("IORegistryEntryCreateCFProperties (disk_child) failed."); + IOObjectRelease (disk_child); + CFRelease (props_dict); + IOObjectRelease (disk); + continue; + } + + /* kIOBSDNameKey */ + 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, + kIOBlockStorageDriverStatisticsBytesReadKey); + read_tme = dict_get_value (stats_dict, + kIOBlockStorageDriverStatisticsTotalReadTimeKey); + write_ops = dict_get_value (stats_dict, + kIOBlockStorageDriverStatisticsWritesKey); + write_byt = dict_get_value (stats_dict, + kIOBlockStorageDriverStatisticsBytesWrittenKey); + /* This property describes the number of nanoseconds spent + * performing writes since the block storage driver was + * instantiated. It is one of the statistic entries listed + * under the top-level kIOBlockStorageDriverStatisticsKey + * property table. It has an OSNumber value. */ + 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 ((read_byt != -1LL) || (write_byt != -1LL)) + disk_submit (disk_name, "disk_octets", read_byt, write_byt); + if ((read_ops != -1LL) || (write_ops != -1LL)) + disk_submit (disk_name, "disk_ops", read_ops, write_ops); + if ((read_tme != -1LL) || (write_tme != -1LL)) + disk_submit (disk_name, "disk_time", + read_tme / 1000, + write_tme / 1000); + + CFRelease (child_dict); + IOObjectRelease (disk_child); + CFRelease (props_dict); + IOObjectRelease (disk); + } + IOObjectRelease (disk_list); +/* #endif HAVE_IOKIT_IOKITLIB_H */ + +#elif KERNEL_LINUX FILE *fh; char buffer[1024]; - char disk_name[128]; char *fields[32]; int numfields; @@ -197,32 +415,36 @@ 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; + 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; int is_disk = 0; diskstats_t *ds, *pre_ds; if ((fh = fopen ("/proc/diskstats", "r")) == NULL) { - if ((fh = fopen ("/proc/partitions", "r")) == NULL) - return; + fh = fopen ("/proc/partitions", "r"); + if (fh == NULL) + { + ERROR ("disk plugin: fopen (/proc/{diskstats,partitions}) failed."); + return (-1); + } /* Kernel is 2.4.* */ fieldshift = 1; } - while (fgets (buffer, 1024, fh) != NULL) + while (fgets (buffer, sizeof (buffer), fh) != NULL) { + char *disk_name; + numfields = strsplit (buffer, fields, 32); if ((numfields != (14 + fieldshift)) && (numfields != 7)) @@ -231,9 +453,7 @@ static void disk_read (void) major = atoll (fields[0]); minor = atoll (fields[1]); - if (snprintf (disk_name, 128, "%i-%i", major, minor) < 1) - continue; - disk_name[127] = '\0'; + 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) @@ -260,18 +480,18 @@ static void disk_read (void) if (numfields == 7) { /* Kernel 2.6, Partition */ - read_count = atoll (fields[3]); - read_sectors = atoi (fields[4]); - write_count = atoll (fields[5]); - write_sectors = atoi (fields[6]); + read_ops = atoll (fields[3]); + read_sectors = atoll (fields[4]); + 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 = 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)) { @@ -284,49 +504,145 @@ static void disk_read (void) } else { + DEBUG ("numfields = %i; => unknown file format.", numfields); continue; } + { + counter_t diff_read_sectors; + counter_t diff_write_sectors; - if (read_sectors >= ds->read_sectors) - ds->read_bytes += 512 * (read_sectors - ds->read_sectors); - else - ds->read_bytes += 512 * ((UINT_MAX - ds->read_sectors) + read_sectors); + /* If the counter wraps around, it's only 32 bits.. */ + 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 * (write_sectors - ds->write_sectors); - else - ds->write_bytes += 512 * ((UINT_MAX - ds->write_sectors) + 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; - ds->read_sectors = read_sectors; - ds->write_sectors = write_sectors; - read_bytes = ds->read_bytes; - write_bytes = ds->write_bytes; + 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 <= 6) + if (ds->poll_count <= 2) + { + 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 ("disk plugin: ((read_ops == 0) && " + "(write_ops == 0)); => Not writing."); continue; + } + + 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) - disk_submit (disk_name, read_count, read_merged, read_bytes, read_time, - write_count, write_merged, write_bytes, write_time); - else - partition_submit (disk_name, read_count, read_bytes, write_count, write_bytes); - } + { + disk_submit (disk_name, "disk_merged", + read_merged, write_merged); + } /* if (is_disk) */ + } /* while (fgets (buffer, sizeof (buffer), fh) != NULL) */ fclose (fh); /* #endif defined(KERNEL_LINUX) */ -#elif defined(HAVE_LIBKSTAT) +#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; if (kc == NULL) - return; + return (-1); for (i = 0; i < numdisk; i++) { @@ -334,24 +650,48 @@ static void disk_read (void) continue; if (strncmp (ksp[i]->ks_class, "disk", 4) == 0) - disk_submit (ksp[i]->ks_name, - kio.reads, 0LL, kio.nread, kio.rtime, - kio.writes, 0LL, kio.nwritten, kio.wtime); + { + 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.KIO_RTIME, kio.KIO_WTIME); + } else if (strncmp (ksp[i]->ks_class, "partition", 9) == 0) - partition_submit (ksp[i]->ks_name, - kio.reads, kio.nread, - kio.writes,kio.nwritten); + { + 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) */ -} /* static void disk_read (void) */ -#else -# define disk_read NULL -#endif /* DISK_HAVE_READ */ +/* #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) */ + + return (0); +} /* int disk_read */ void module_register (void) { - plugin_register ("partition", NULL, NULL, partition_write); - plugin_register (MODULE_NAME, disk_init, disk_read, disk_write); -} - -#undef MODULE_NAME + 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 */