X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fdisk.c;h=6aefbc7dfb15a65313b9eb580b90abc73a3f930a;hb=1f8b06df4f907658bea49c47dd4e8329fdbc8099;hp=dc0232d4e8af39ba132ce0ed26c9faba74a2caca;hpb=a82ff6683f0011a498b4fc0947833d2e28925b76;p=collectd.git diff --git a/src/disk.c b/src/disk.c index dc0232d4..6aefbc7d 100644 --- a/src/disk.c +++ b/src/disk.c @@ -1,6 +1,6 @@ /** * collectd - src/disk.c - * Copyright (C) 2005 Florian octo Forster + * Copyright (C) 2005,2006 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 @@ -20,19 +20,87 @@ * Florian octo Forster **/ -#include "disk.h" +#include "collectd.h" +#include "common.h" +#include "plugin.h" +#include "utils_debug.h" -#if COLLECT_DISK #define MODULE_NAME "disk" -#include "plugin.h" -#include "common.h" +#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 HAVE_IOKIT_IOKITLIB_H || KERNEL_LINUX || HAVE_LIBKSTAT +# define DISK_HAVE_READ 1 +#else +# define DISK_HAVE_READ 0 +#endif + +static char *disk_filename_template = "disk-%s.rrd"; +static char *part_filename_template = "partition-%s.rrd"; + +/* 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; + +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; + +#if HAVE_IOKIT_IOKITLIB_H +static mach_port_t io_master_port = MACH_PORT_NULL; +/* #endif HAVE_IOKIT_IOKITLIB_H */ -#ifdef KERNEL_LINUX +#elif KERNEL_LINUX typedef struct diskstats { char *name; + /* This overflows in roughly 1361 year */ + unsigned int poll_count; + unsigned int read_sectors; unsigned int write_sectors; @@ -43,46 +111,42 @@ typedef struct diskstats } diskstats_t; static diskstats_t *disklist; -/* 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 */ -static char *disk_filename_template = "disk-%s.rrd"; -static char *part_filename_template = "partition-%s.rrd"; - -/* 104857600 == 100 MB */ -static char *disk_ds_def[] = +static void disk_init (void) { - "DS:rcount:COUNTER:25:0:U", - "DS:rmerged:COUNTER:25:0:U", - "DS:rbytes:COUNTER:25:0:104857600", - "DS:rtime:COUNTER:25:0:U", - "DS:wcount:COUNTER:25:0:U", - "DS:wmerged:COUNTER:25:0:U", - "DS:wbytes:COUNTER:25:0:104857600", - "DS:wtime:COUNTER:25:0:U", - NULL -}; -static int disk_ds_num = 8; +#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; + } -static char *part_ds_def[] = -{ - "DS:rcount:COUNTER:25:0:U", - "DS:rbytes:COUNTER:25:0:104857600", - "DS:wcount:COUNTER:25:0:U", - "DS:wbytes:COUNTER:25:0:104857600", - NULL -}; -static int part_ds_num = 4; + status = IOMasterPort (MACH_PORT_NULL, &io_master_port); + if (status != kIOReturnSuccess) + { + syslog (LOG_ERR, "IOMasterPort failed: %s", + mach_error_string (status)); + io_master_port = MACH_PORT_NULL; + return; + } +/* #endif HAVE_IOKIT_IOKITLIB_H */ -void disk_init (void) -{ -#ifdef HAVE_LIBKSTAT +#elif KERNEL_LINUX + /* No init needed */ +/* #endif KERNEL_LINUX */ + +#elif HAVE_LIBKSTAT kstat_t *ksp_chain; numdisk = 0; @@ -101,12 +165,12 @@ void disk_init (void) continue; ksp[numdisk++] = ksp_chain; } -#endif +#endif /* HAVE_LIBKSTAT */ return; } -void disk_write (char *host, char *inst, char *val) +static void disk_write (char *host, char *inst, char *val) { char file[512]; int status; @@ -120,7 +184,7 @@ void disk_write (char *host, char *inst, char *val) rrd_update_file (host, file, val, disk_ds_def, disk_ds_num); } -void partition_write (char *host, char *inst, char *val) +static void partition_write (char *host, char *inst, char *val) { char file[512]; int status; @@ -134,8 +198,9 @@ void partition_write (char *host, char *inst, char *val) rrd_update_file (host, file, val, part_ds_def, part_ds_num); } +#if DISK_HAVE_READ #define BUFSIZE 512 -void disk_submit (char *disk_name, +static void disk_submit (char *disk_name, unsigned long long read_count, unsigned long long read_merged, unsigned long long read_bytes, @@ -157,7 +222,8 @@ void disk_submit (char *disk_name, plugin_submit (MODULE_NAME, disk_name, buf); } -void partition_submit (char *part_name, +#if KERNEL_LINUX || HAVE_LIBKSTAT +static void partition_submit (char *part_name, unsigned long long read_count, unsigned long long read_bytes, unsigned long long write_count, @@ -173,11 +239,187 @@ void partition_submit (char *part_name, plugin_submit ("partition", part_name, buf); } +#endif /* KERNEL_LINUX || HAVE_LIBKSTAT */ #undef BUFSIZE -void disk_read (void) +#if HAVE_IOKIT_IOKITLIB_H +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, key_obj); + + CFRelease (key_obj); + + if (val_obj == NULL) + { + DBG ("CFDictionaryGetValue (%s) failed.", key); + return (-1LL); + } + + if (!CFNumberGetValue (val_obj, kCFNumberSInt64Type, &val_int)) + { + DBG ("CFNumberGetValue (%s) failed.", key); + return (-1LL); + } + + return (val_int); +} +#endif /* HAVE_IOKIT_IOKITLIB_H */ + +static void disk_read (void) { -#ifdef KERNEL_LINUX +#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) + { + syslog (LOG_ERR, "disk-plugin: IOServiceGetMatchingServices failed."); + return; + } + + 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, + (CFMutableDictionaryRef *) &props_dict, + kCFAllocatorDefault, + kNilOptions) + != 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, + 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); + 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 (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); + } + IOObjectRelease (disk_list); +/* #endif HAVE_IOKIT_IOKITLIB_H */ + +#elif KERNEL_LINUX FILE *fh; char buffer[1024]; char disk_name[128]; @@ -295,6 +537,10 @@ void disk_read (void) read_bytes = ds->read_bytes; write_bytes = ds->write_bytes; + /* Don't write to the RRDs if we've just started.. */ + ds->poll_count++; + if (ds->poll_count <= 6) + continue; if ((read_count == 0) && (write_count == 0)) continue; @@ -309,7 +555,7 @@ void disk_read (void) fclose (fh); /* #endif defined(KERNEL_LINUX) */ -#elif defined(HAVE_LIBKSTAT) +#elif HAVE_LIBKSTAT static kstat_io_t kio; int i; @@ -331,7 +577,10 @@ void disk_read (void) kio.writes,kio.nwritten); } #endif /* defined(HAVE_LIBKSTAT) */ -} +} /* static void disk_read (void) */ +#else +# define disk_read NULL +#endif /* DISK_HAVE_READ */ void module_register (void) { @@ -340,4 +589,3 @@ void module_register (void) } #undef MODULE_NAME -#endif /* COLLECT_DISK */