#include "collectd.h"
#include "common.h"
#include "plugin.h"
-#include "utils_debug.h"
#if HAVE_MACH_MACH_TYPES_H
# include <mach/mach_types.h>
# include <IOKit/IOBSD.h>
#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 <limits.h>
+#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 */
{
char *name;
- /* This overflows in roughly 1361 year */
+ /* This overflows in roughly 1361 years */
unsigned int poll_count;
counter_t read_sectors;
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
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)
{
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);
/* #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
vl.values = values;
vl.values_len = 2;
vl.time = time (NULL);
- strcpy (vl.host, hostname);
+ strcpy (vl.host, hostname_g);
strcpy (vl.plugin, "disk");
strncpy (vl.plugin_instance, plugin_instance,
sizeof (vl.plugin_instance));
kCFStringEncodingASCII);
if (key_obj == NULL)
{
- DBG ("CFStringCreateWithCString (%s) failed.", key);
+ DEBUG ("CFStringCreateWithCString (%s) failed.", key);
return (-1LL);
}
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);
}
!= 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;
}
kNilOptions)
!= kIOReturnSuccess)
{
- syslog (LOG_ERR, "disk-plugin: IORegistryEntryCreateCFProperties failed.");
+ ERROR ("disk-plugin: IORegistryEntryCreateCFProperties failed.");
IOObjectRelease (disk_child);
IOObjectRelease (disk);
continue;
if (props_dict == NULL)
{
- DBG ("IORegistryEntryCreateCFProperties (disk) failed.");
+ DEBUG ("IORegistryEntryCreateCFProperties (disk) failed.");
IOObjectRelease (disk_child);
IOObjectRelease (disk);
continue;
if (stats_dict == NULL)
{
- DBG ("CFDictionaryGetValue (%s) failed.",
+ DEBUG ("CFDictionaryGetValue (%s) failed.",
kIOBlockStorageDriverStatisticsKey);
CFRelease (props_dict);
IOObjectRelease (disk_child);
kNilOptions)
!= kIOReturnSuccess)
{
- DBG ("IORegistryEntryCreateCFProperties (disk_child) failed.");
+ DEBUG ("IORegistryEntryCreateCFProperties (disk_child) failed.");
IOObjectRelease (disk_child);
CFRelease (props_dict);
IOObjectRelease (disk);
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);
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;
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]);
}
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;
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 */