#include "collectd.h"
-#include "common.h"
#include "plugin.h"
-#include "utils_ignorelist.h"
+#include "utils/common/common.h"
+#include "utils/ignorelist/ignorelist.h"
#if HAVE_MACH_MACH_TYPES_H
#include <mach/mach_types.h>
static mach_port_t io_master_port = MACH_PORT_NULL;
/* This defaults to false for backwards compatibility. Please fix in the next
* major version. */
-static _Bool use_bsd_name = 0;
+static bool use_bsd_name;
/* #endif HAVE_IOKIT_IOKITLIB_H */
#elif KERNEL_LINUX
derive_t avg_read_time;
derive_t avg_write_time;
- _Bool has_merged;
- _Bool has_in_progress;
- _Bool has_io_time;
+ bool has_merged;
+ bool has_in_progress;
+ bool has_io_time;
struct diskstats *next;
} diskstats_t;
/* #endif KERNEL_FREEBSD */
#elif HAVE_LIBKSTAT
+#if HAVE_KSTAT_H
+#include <kstat.h>
+#endif
#define MAX_NUMDISK 1024
extern kstat_ctl_t *kc;
static kstat_t *ksp[MAX_NUMDISK];
-static int numdisk = 0;
+static int numdisk;
/* #endif HAVE_LIBKSTAT */
#elif defined(HAVE_LIBSTATGRAB)
#error "No applicable input method."
#endif
-#if HAVE_LIBUDEV
+#if HAVE_LIBUDEV_H
#include <libudev.h>
-static char *conf_udev_name_attr = NULL;
+static char *conf_udev_name_attr;
static struct udev *handle_udev;
#endif
"UdevNameAttr"};
static int config_keys_num = STATIC_ARRAY_SIZE(config_keys);
-static ignorelist_t *ignorelist = NULL;
+static ignorelist_t *ignorelist;
static int disk_config(const char *key, const char *value) {
if (ignorelist == NULL)
ignorelist = ignorelist_create(/* invert = */ 1);
if (ignorelist == NULL)
- return (1);
+ return 1;
if (strcasecmp("Disk", key) == 0) {
ignorelist_add(ignorelist, value);
ignorelist_set_invert(ignorelist, invert);
} else if (strcasecmp("UseBSDName", key) == 0) {
#if HAVE_IOKIT_IOKITLIB_H
- use_bsd_name = IS_TRUE(value) ? 1 : 0;
+ use_bsd_name = IS_TRUE(value);
#else
WARNING("disk plugin: The \"UseBSDName\" option is only supported "
"on Mach / Mac OS X and will be ignored.");
#endif
} else if (strcasecmp("UdevNameAttr", key) == 0) {
-#if HAVE_LIBUDEV
+#if HAVE_LIBUDEV_H
if (conf_udev_name_attr != NULL) {
free(conf_udev_name_attr);
conf_udev_name_attr = NULL;
}
if ((conf_udev_name_attr = strdup(value)) == NULL)
- return (1);
+ return 1;
#else
WARNING("disk plugin: The \"UdevNameAttr\" option is only supported "
"if collectd is built with libudev support");
#endif
} else {
- return (-1);
+ return -1;
}
- return (0);
+ return 0;
} /* int disk_config */
static int disk_init(void) {
if (status != kIOReturnSuccess) {
ERROR("IOMasterPort failed: %s", mach_error_string(status));
io_master_port = MACH_PORT_NULL;
- return (-1);
+ return -1;
}
/* #endif HAVE_IOKIT_IOKITLIB_H */
#elif KERNEL_LINUX
-#if HAVE_LIBUDEV
+#if HAVE_LIBUDEV_H
if (conf_udev_name_attr != NULL) {
handle_udev = udev_new();
if (handle_udev == NULL) {
ERROR("disk plugin: udev_new() failed!");
- return (-1);
+ return -1;
}
}
-#endif /* HAVE_LIBUDEV */
+#endif /* HAVE_LIBUDEV_H */
/* #endif KERNEL_LINUX */
#elif KERNEL_FREEBSD
rv = geom_gettree(&geom_tree);
if (rv != 0) {
ERROR("geom_gettree() failed, returned %d", rv);
- return (-1);
+ return -1;
}
rv = geom_stats_open();
if (rv != 0) {
ERROR("geom_stats_open() failed, returned %d", rv);
- return (-1);
+ return -1;
}
/* #endif KERNEL_FREEBSD */
numdisk = 0;
if (kc == NULL)
- return (-1);
+ return -1;
for (numdisk = 0, ksp_chain = kc->kc_chain;
(numdisk < MAX_NUMDISK) && (ksp_chain != NULL);
}
#endif /* HAVE_LIBKSTAT */
- return (0);
+ return 0;
} /* int disk_init */
static int disk_shutdown(void) {
#if KERNEL_LINUX
-#if HAVE_LIBUDEV
+#if HAVE_LIBUDEV_H
if (handle_udev != NULL)
udev_unref(handle_udev);
-#endif /* HAVE_LIBUDEV */
+#endif /* HAVE_LIBUDEV_H */
#endif /* KERNEL_LINUX */
- return (0);
+ return 0;
} /* int disk_shutdown */
static void disk_submit(const char *plugin_instance, const char *type,
plugin_dispatch_values(&vl);
} /* void submit_io_time */
-#endif /* KERNEL_FREEBSD || KERNEL_LINUX */
-#if KERNEL_LINUX
static void submit_in_progress(char const *disk_name, gauge_t in_progress) {
value_list_t vl = VALUE_LIST_INIT;
plugin_dispatch_values(&vl);
}
+#endif /* KERNEL_FREEBSD || KERNEL_LINUX */
+#if KERNEL_LINUX
static counter_t disk_calc_time_incr(counter_t delta_time,
counter_t delta_ops) {
double interval = CDTIME_T_TO_DOUBLE(plugin_get_interval());
double avg_time = ((double)delta_time) / ((double)delta_ops);
double avg_time_incr = interval * avg_time;
- return ((counter_t)(avg_time_incr + .5));
+ return (counter_t)(avg_time_incr + .5);
}
#endif
-#if HAVE_LIBUDEV
+#if HAVE_LIBUDEV_H
/**
* Attempt to provide an rename disk instance from an assigned udev attribute.
*
kCFStringEncodingASCII);
if (key_obj == NULL) {
DEBUG("CFStringCreateWithCString (%s) failed.", key);
- return (-1LL);
+ return -1LL;
}
/* get => we don't need to release (== free) the object */
if (val_obj == NULL) {
DEBUG("CFDictionaryGetValue (%s) failed.", key);
- return (-1LL);
+ return -1LL;
}
if (!CFNumberGetValue(val_obj, kCFNumberSInt64Type, &val_int)) {
DEBUG("CFNumberGetValue (%s) failed.", key);
- return (-1LL);
+ return -1LL;
}
- return (val_int);
+ return val_int;
}
#endif /* HAVE_IOKIT_IOKITLIB_H */
io_master_port, IOServiceMatching(kIOBlockStorageDriverClass),
&disk_list) != kIOReturnSuccess) {
ERROR("disk plugin: IOServiceGetMatchingServices failed.");
- return (-1);
+ return -1;
}
while ((disk = IOIteratorNext(disk_list)) != 0) {
sstrncpy(disk_name, props_disk_name_bsd, sizeof(disk_name));
else {
ERROR("disk plugin: can't find bsd disk name.");
- ssnprintf(disk_name, sizeof(disk_name), "%i-%i", disk_major,
- disk_minor);
+ snprintf(disk_name, sizeof(disk_name), "%i-%i", disk_major, disk_minor);
}
} else
- ssnprintf(disk_name, sizeof(disk_name), "%i-%i", disk_major, disk_minor);
+ snprintf(disk_name, sizeof(disk_name), "%i-%i", disk_major, disk_minor);
DEBUG("disk plugin: disk_name = \"%s\"", disk_name);
const char *disk_name;
long double read_time, write_time, busy_time, total_duration;
+ uint64_t queue_length;
for (retry = 0, dirty = 1; retry < 5 && dirty == 1; retry++) {
if (snap != NULL)
snap = geom_stats_snapshot_get();
if (snap == NULL) {
ERROR("disk plugin: geom_stats_snapshot_get() failed.");
- return (-1);
+ return -1;
}
/* Check if we have dirty read from this snapshot */
if (geom_gettree(&geom_tree) != 0) {
ERROR("disk plugin: geom_gettree() failed");
geom_stats_snapshot_free(snap);
- return (-1);
+ return -1;
}
geom_id = geom_lookupid(&geom_tree, snap_iter->id);
}
}
if (devstat_compute_statistics(snap_iter, NULL, 1.0, DSM_TOTAL_BUSY_TIME,
&busy_time, DSM_TOTAL_DURATION,
- &total_duration, DSM_NONE) != 0) {
+ &total_duration, DSM_QUEUE_LENGTH,
+ &queue_length, DSM_NONE) != 0) {
WARNING("%s", devstat_errbuf);
} else {
submit_io_time(disk_name, busy_time, total_duration);
+ submit_in_progress(disk_name, (gauge_t)queue_length);
}
}
geom_stats_snapshot_free(snap);
char buffer[1024];
char *fields[32];
- int numfields;
- int fieldshift = 0;
-
- int minor = 0;
+ static unsigned int poll_count = 0;
derive_t read_sectors = 0;
derive_t write_sectors = 0;
diskstats_t *ds, *pre_ds;
if ((fh = fopen("/proc/diskstats", "r")) == NULL) {
- fh = fopen("/proc/partitions", "r");
- if (fh == NULL) {
- ERROR("disk plugin: fopen (/proc/{diskstats,partitions}) failed.");
- return (-1);
- }
-
- /* Kernel is 2.4.* */
- fieldshift = 1;
+ ERROR("disk plugin: fopen(\"/proc/diskstats\"): %s", STRERRNO);
+ return -1;
}
+ poll_count++;
while (fgets(buffer, sizeof(buffer), fh) != NULL) {
- char *disk_name;
- char *output_name;
+ int numfields = strsplit(buffer, fields, 32);
- numfields = strsplit(buffer, fields, 32);
-
- if ((numfields != (14 + fieldshift)) && (numfields != 7))
+ /* need either 7 fields (partition) or at least 14 fields */
+ if ((numfields != 7) && (numfields < 14))
continue;
- minor = atoll(fields[1]);
-
- disk_name = fields[2 + fieldshift];
+ char *disk_name = fields[2];
for (ds = disklist, pre_ds = disklist; ds != NULL;
pre_ds = ds, ds = ds->next)
break;
if (ds == NULL) {
- if ((ds = (diskstats_t *)calloc(1, sizeof(diskstats_t))) == NULL)
+ if ((ds = calloc(1, sizeof(*ds))) == NULL)
continue;
if ((ds->name = strdup(disk_name)) == NULL) {
read_sectors = atoll(fields[4]);
write_ops = atoll(fields[5]);
write_sectors = atoll(fields[6]);
- } else if (numfields == (14 + fieldshift)) {
- read_ops = atoll(fields[3 + fieldshift]);
- write_ops = atoll(fields[7 + fieldshift]);
+ } else {
+ assert(numfields >= 14);
+ read_ops = atoll(fields[3]);
+ write_ops = atoll(fields[7]);
- read_sectors = atoll(fields[5 + fieldshift]);
- write_sectors = atoll(fields[9 + fieldshift]);
+ read_sectors = atoll(fields[5]);
+ write_sectors = atoll(fields[9]);
- if ((fieldshift == 0) || (minor == 0)) {
- is_disk = 1;
- read_merged = atoll(fields[4 + fieldshift]);
- read_time = atoll(fields[6 + fieldshift]);
- write_merged = atoll(fields[8 + fieldshift]);
- write_time = atoll(fields[10 + fieldshift]);
+ is_disk = 1;
+ read_merged = atoll(fields[4]);
+ read_time = atoll(fields[6]);
+ write_merged = atoll(fields[8]);
+ write_time = atoll(fields[10]);
- in_progress = atof(fields[11 + fieldshift]);
+ in_progress = atof(fields[11]);
- io_time = atof(fields[12 + fieldshift]);
- weighted_time = atof(fields[13 + fieldshift]);
- }
- } else {
- DEBUG("numfields = %i; => unknown file format.", numfields);
- continue;
+ io_time = atof(fields[12]);
+ weighted_time = atof(fields[13]);
}
{
ds->write_time = write_time;
if (read_merged || write_merged)
- ds->has_merged = 1;
+ ds->has_merged = true;
if (in_progress)
- ds->has_in_progress = 1;
+ ds->has_in_progress = true;
if (io_time)
- ds->has_io_time = 1;
+ ds->has_io_time = true;
} /* if (is_disk) */
- /* Don't write to the RRDs if we've just started.. */
- ds->poll_count++;
- if (ds->poll_count <= 2) {
- DEBUG("disk plugin: (ds->poll_count = %i) <= "
- "(min_poll_count = 2); => Not writing.",
- ds->poll_count);
+ /* Skip first cycle for newly-added disk */
+ if (ds->poll_count == 0) {
+ DEBUG("disk plugin: (ds->poll_count = 0) => Skipping.");
+ ds->poll_count = poll_count;
continue;
}
+ ds->poll_count = poll_count;
if ((read_ops == 0) && (write_ops == 0)) {
DEBUG("disk plugin: ((read_ops == 0) && "
continue;
}
- output_name = disk_name;
+ char *output_name = disk_name;
-#if HAVE_LIBUDEV
+#if HAVE_LIBUDEV_H
char *alt_name = NULL;
if (conf_udev_name_attr != NULL) {
alt_name =
#endif
if (ignorelist_match(ignorelist, output_name) != 0) {
-#if HAVE_LIBUDEV
+#if HAVE_LIBUDEV_H
/* release udev-based alternate name, if allocated */
sfree(alt_name);
#endif
submit_io_time(output_name, io_time, weighted_time);
} /* if (is_disk) */
-#if HAVE_LIBUDEV
+#if HAVE_LIBUDEV_H
/* release udev-based alternate name, if allocated */
sfree(alt_name);
#endif
} /* while (fgets (buffer, sizeof (buffer), fh) != NULL) */
+ /* Remove disks that have disappeared from diskstats */
+ for (ds = disklist, pre_ds = disklist; ds != NULL;) {
+ /* Disk exists */
+ if (ds->poll_count == poll_count) {
+ pre_ds = ds;
+ ds = ds->next;
+ continue;
+ }
+
+ /* Disk is missing, remove it */
+ diskstats_t *missing_ds = ds;
+ if (ds == disklist) {
+ pre_ds = disklist = ds->next;
+ } else {
+ pre_ds->next = ds->next;
+ }
+ ds = ds->next;
+
+ DEBUG("disk plugin: Disk %s disappeared.", missing_ds->name);
+ free(missing_ds->name);
+ free(missing_ds);
+ }
fclose(fh);
/* #endif defined(KERNEL_LINUX) */
static kstat_io_t kio;
if (kc == NULL)
- return (-1);
+ return -1;
for (int i = 0; i < numdisk; i++) {
if (kstat_read(kc, ksp[i], &kio) == -1)
char name[DATA_MAX_NAME_LEN];
if ((ds = sg_get_disk_io_stats(&disks)) == NULL)
- return (0);
+ return 0;
for (int counter = 0; counter < disks; counter++) {
strncpy(name, ds->disk_name, sizeof(name));
int rnumdisk;
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);
+ WARNING("disk plugin: perfstat_disk: %s", STRERRNO);
+ 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));
+ free(stat_disk);
+ stat_disk = calloc(numdisk, sizeof(*stat_disk));
}
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);
+ WARNING("disk plugin: perfstat_disk : %s", STRERRNO);
+ return -1;
}
for (int i = 0; i < rnumdisk; i++) {
}
#endif /* defined(HAVE_PERFSTAT) */
- return (0);
+ return 0;
} /* int disk_read */
void module_register(void) {