X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Fdisk.c;h=255d4db6076d905210e7fd1628217c05bcaf6db1;hb=5eb1fef6de7e0c8fb99e3d85063d96d7cc785f9b;hp=f319c9c6da408808b08c80870c4aad72e712ac7c;hpb=1d7fbcf1832d4a9887a0bc7dca1896564adeca67;p=collectd.git diff --git a/src/disk.c b/src/disk.c index f319c9c6..255d4db6 100644 --- a/src/disk.c +++ b/src/disk.c @@ -106,14 +106,16 @@ typedef struct diskstats derive_t avg_read_time; derive_t avg_write_time; + _Bool has_merged; + _Bool has_in_progress; + _Bool has_io_time; + struct diskstats *next; } diskstats_t; static diskstats_t *disklist; /* #endif KERNEL_LINUX */ #elif KERNEL_FREEBSD -static void *snap_previous; -static struct timespec tsnap_previous; static struct gmesh geom_tree; /* #endif KERNEL_FREEBSD */ @@ -228,7 +230,16 @@ static int disk_init (void) /* #endif HAVE_IOKIT_IOKITLIB_H */ #elif KERNEL_LINUX - /* do nothing */ +#if HAVE_LIBUDEV + if (conf_udev_name_attr != NULL) + { + handle_udev = udev_new(); + if (handle_udev == NULL) { + ERROR ("disk plugin: udev_new() failed!"); + return (-1); + } + } +#endif /* HAVE_LIBUDEV */ /* #endif KERNEL_LINUX */ #elif KERNEL_FREEBSD @@ -244,12 +255,6 @@ static int disk_init (void) ERROR ("geom_stats_open() failed, returned %d", rv); return (-1); } - snap_previous = geom_stats_snapshot_get(); - if (snap_previous == NULL) { - ERROR ("geom_stats_snapshot_get() failed"); - return (-1); - } - geom_stats_snapshot_timestamp(snap_previous, &tsnap_previous); /* #endif KERNEL_FREEBSD */ #elif HAVE_LIBKSTAT @@ -276,6 +281,17 @@ static int disk_init (void) return (0); } /* int disk_init */ +static int disk_shutdown (void) +{ +#if KERNEL_LINUX +#if HAVE_LIBUDEV + if (handle_udev != NULL) + udev_unref(handle_udev); +#endif /* HAVE_LIBUDEV */ +#endif /* KERNEL_LINUX */ + return (0); +} /* int disk_shutdown */ + static void disk_submit (const char *plugin_instance, const char *type, derive_t read, derive_t write) @@ -283,10 +299,6 @@ static void disk_submit (const char *plugin_instance, value_t values[2]; value_list_t vl = VALUE_LIST_INIT; - /* Both `ignorelist' and `plugin_instance' may be NULL. */ - if (ignorelist_match (ignorelist, plugin_instance) != 0) - return; - values[0].derive = read; values[1].derive = write; @@ -301,44 +313,40 @@ static void disk_submit (const char *plugin_instance, plugin_dispatch_values (&vl); } /* void disk_submit */ -#if KERNEL_LINUX -static void submit_in_progress (char const *disk_name, gauge_t in_progress) +#if KERNEL_FREEBSD || KERNEL_LINUX +static void submit_io_time (char const *plugin_instance, derive_t io_time, derive_t weighted_time) { - value_t v; + value_t values[2]; value_list_t vl = VALUE_LIST_INIT; - if (ignorelist_match (ignorelist, disk_name) != 0) - return; - - v.gauge = in_progress; + values[0].derive = io_time; + values[1].derive = weighted_time; - vl.values = &v; - vl.values_len = 1; + 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, disk_name, sizeof (vl.plugin_instance)); - sstrncpy (vl.type, "pending_operations", sizeof (vl.type)); + sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance)); + sstrncpy (vl.type, "disk_io_time", sizeof (vl.type)); plugin_dispatch_values (&vl); -} +} /* void submit_io_time */ +#endif /* KERNEL_FREEBSD || KERNEL_LINUX */ -static void submit_io_time (char const *plugin_instance, derive_t io_time, derive_t weighted_time) +#if KERNEL_LINUX +static void submit_in_progress (char const *disk_name, gauge_t in_progress) { - value_t values[2]; + value_t v; value_list_t vl = VALUE_LIST_INIT; - if (ignorelist_match (ignorelist, plugin_instance) != 0) - return; - - values[0].derive = io_time; - values[1].derive = weighted_time; + v.gauge = in_progress; - vl.values = values; - vl.values_len = 2; + vl.values = &v; + vl.values_len = 1; 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, "disk_io_time", sizeof (vl.type)); + sstrncpy (vl.plugin_instance, disk_name, sizeof (vl.plugin_instance)); + sstrncpy (vl.type, "pending_operations", sizeof (vl.type)); plugin_dispatch_values (&vl); } @@ -397,7 +405,7 @@ static signed long long dict_get_value (CFDictionaryRef dict, const char *key) DEBUG ("CFStringCreateWithCString (%s) failed.", key); return (-1LL); } - + /* get => we don't need to release (== free) the object */ val_obj = (CFNumberRef) CFDictionaryGetValue (dict, key_obj); @@ -512,6 +520,15 @@ static int disk_read (void) else ssnprintf (disk_name, sizeof (disk_name), "%i-%i", disk_major, disk_minor); + DEBUG ("disk plugin: disk_name = \"%s\"", disk_name); + + /* check the name against ignore list */ + if (ignorelist_match (ignorelist, disk_name) != 0) { + CFRelease (props_dict); + IOObjectRelease (disk); + continue; + } + /* extract the stats */ read_ops = dict_get_value (stats_dict, kIOBlockStorageDriverStatisticsReadsKey); read_byt = dict_get_value (stats_dict, kIOBlockStorageDriverStatisticsBytesReadKey); @@ -523,7 +540,6 @@ static int disk_read (void) IOObjectRelease (disk); /* and submit */ - DEBUG ("disk plugin: 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)) @@ -538,47 +554,42 @@ static int disk_read (void) #elif KERNEL_FREEBSD int retry, dirty; - void *snap_present = NULL; - struct devstat *snap_present_iter, *snap_previous_iter; - struct timespec tsnap_present; + void *snap = NULL; + struct devstat *snap_iter; struct gident *geom_id; - double timedelta; - long double ld[11]; const char *disk_name; - derive_t read_bytes, write_bytes; - derive_t read_ops, write_ops; - derive_t read_time, write_time; + long double read_time, write_time, busy_time, total_duration; for (retry = 0, dirty = 1; retry < 5 && dirty == 1; retry++) { - if (snap_present != NULL) - geom_stats_snapshot_free(snap_present); + if (snap != NULL) + geom_stats_snapshot_free(snap); /* Get a fresh copy of stats snapshot */ - snap_present = geom_stats_snapshot_get(); - if (snap_present == NULL) { + snap = geom_stats_snapshot_get(); + if (snap == NULL) { ERROR("disk plugin: geom_stats_snapshot_get() failed."); return (-1); } /* Check if we have dirty read from this snapshot */ dirty = 0; - geom_stats_snapshot_reset(snap_present); - while ((snap_present_iter = geom_stats_snapshot_next(snap_present)) != NULL) { - if (snap_present_iter->id == NULL) + geom_stats_snapshot_reset(snap); + while ((snap_iter = geom_stats_snapshot_next(snap)) != NULL) { + if (snap_iter->id == NULL) continue; - geom_id = geom_lookupid(&geom_tree, snap_present_iter->id); + geom_id = geom_lookupid(&geom_tree, snap_iter->id); /* New device? refresh GEOM tree */ if (geom_id == NULL) { geom_deletetree(&geom_tree); if (geom_gettree(&geom_tree) != 0) { ERROR("disk plugin: geom_gettree() failed"); - geom_stats_snapshot_free(snap_present); + geom_stats_snapshot_free(snap); return (-1); } - geom_id = geom_lookupid(&geom_tree, snap_present_iter->id); + geom_id = geom_lookupid(&geom_tree, snap_iter->id); } /* * This should be rare: the device come right before we take the @@ -597,34 +608,23 @@ static int disk_read (void) continue; /* Check if this is a dirty read quit for another try */ - if (snap_present_iter->sequence0 != snap_present_iter->sequence1) { + if (snap_iter->sequence0 != snap_iter->sequence1) { dirty = 1; break; } } } - /* - * Now we have a snapshot that is either clean, or still dirty after 5 - * reads. - */ - geom_stats_snapshot_timestamp(snap_present, &tsnap_present); - timedelta = tsnap_present.tv_sec - tsnap_previous.tv_sec; - timedelta += (tsnap_present.tv_nsec - tsnap_previous.tv_nsec) * 1e-9; - tsnap_previous = tsnap_present; - - /* Reset iterators for both snapshots */ - geom_stats_snapshot_reset(snap_present); - geom_stats_snapshot_reset(snap_previous); + /* Reset iterator */ + geom_stats_snapshot_reset(snap); for (;;) { - snap_present_iter = geom_stats_snapshot_next(snap_present); - snap_previous_iter = geom_stats_snapshot_next(snap_previous); - if (snap_present_iter == NULL || snap_previous_iter == NULL) + snap_iter = geom_stats_snapshot_next(snap); + if (snap_iter == NULL) break; - if (snap_present_iter->id == NULL) + if (snap_iter->id == NULL) continue; - geom_id = geom_lookupid(&geom_tree, snap_present_iter->id); + geom_id = geom_lookupid(&geom_tree, snap_iter->id); if (geom_id == NULL) continue; if (geom_id->lg_what != ISPROVIDER) @@ -632,58 +632,49 @@ static int disk_read (void) if (((struct gprovider *)(geom_id->lg_ptr))->lg_geom->lg_rank != 1) continue; /* Skip dirty reads, if present */ - if (dirty && (snap_present_iter->sequence0 != snap_present_iter->sequence1)) + if (dirty && (snap_iter->sequence0 != snap_iter->sequence1)) continue; - devstat_compute_statistics(snap_present_iter, snap_previous_iter, timedelta, - DSM_TRANSFERS_PER_SECOND, &ld[0], - - DSM_TRANSFERS_PER_SECOND_READ, &ld[1], - DSM_MB_PER_SECOND_READ, &ld[2], - DSM_MS_PER_TRANSACTION_READ, &ld[3], - - DSM_TRANSFERS_PER_SECOND_WRITE, &ld[4], - DSM_MB_PER_SECOND_WRITE, &ld[5], - DSM_MS_PER_TRANSACTION_WRITE, &ld[6], - - DSM_BUSY_PCT, &ld[7], - - DSM_TRANSFERS_PER_SECOND_FREE, &ld[8], - DSM_MB_PER_SECOND_FREE, &ld[9], - DSM_MS_PER_TRANSACTION_FREE, &ld[10], - DSM_NONE); - *snap_previous_iter = *snap_present_iter; - - /* Derive data to be submitted */ - read_ops = (derive_t)ld[1]; - write_ops = (derive_t)ld[4]; - read_bytes = (derive_t)(ld[2] * 1048576LL); - write_bytes = (derive_t)(ld[5] * 1048576LL); - read_time = (derive_t)ld[3]; - write_time = (derive_t)ld[6]; - disk_name = ((struct gprovider *)geom_id->lg_ptr)->lg_name; - if ((read_bytes != 0) || (write_bytes != 0)) + if (ignorelist_match (ignorelist, disk_name) != 0) + continue; + + if ((snap_iter->bytes[DEVSTAT_READ] != 0) || (snap_iter->bytes[DEVSTAT_WRITE] != 0)) { disk_submit(disk_name, "disk_octets", - read_bytes, write_bytes); + (derive_t)snap_iter->bytes[DEVSTAT_READ], + (derive_t)snap_iter->bytes[DEVSTAT_WRITE]); + } - if ((read_ops != 0) || (write_ops != 0)) + if ((snap_iter->operations[DEVSTAT_READ] != 0) || (snap_iter->operations[DEVSTAT_WRITE] != 0)) { disk_submit(disk_name, "disk_ops", - read_ops, write_ops); + (derive_t)snap_iter->operations[DEVSTAT_READ], + (derive_t)snap_iter->operations[DEVSTAT_WRITE]); + } - if ((read_time != 0) || (write_time != 0)) + read_time = devstat_compute_etime(&snap_iter->duration[DEVSTAT_READ], NULL); + write_time = devstat_compute_etime(&snap_iter->duration[DEVSTAT_WRITE], NULL); + if ((read_time != 0) || (write_time != 0)) { disk_submit (disk_name, "disk_time", - read_time, write_time); - - /* TODO: TRIM statistics collected but not reported. */ + (derive_t)(read_time*1000), (derive_t)(write_time*1000)); + } + if (devstat_compute_statistics(snap_iter, NULL, 1.0, + DSM_TOTAL_BUSY_TIME, &busy_time, + DSM_TOTAL_DURATION, &total_duration, + DSM_NONE) != 0) { + WARNING("%s", devstat_errbuf); + } + else + { + submit_io_time(disk_name, busy_time, total_duration); + } } - geom_stats_snapshot_free(snap_present); + geom_stats_snapshot_free(snap); #elif KERNEL_LINUX FILE *fh; char buffer[1024]; - + char *fields[32]; int numfields; int fieldshift = 0; @@ -719,15 +710,10 @@ static int disk_read (void) fieldshift = 1; } -#if HAVE_LIBUDEV - handle_udev = udev_new(); -#endif - while (fgets (buffer, sizeof (buffer), fh) != NULL) { char *disk_name; char *output_name; - char *alt_name; numfields = strsplit (buffer, fields, 32); @@ -865,6 +851,16 @@ static int disk_read (void) ds->read_time = read_time; ds->write_ops = write_ops; ds->write_time = write_time; + + if (read_merged || write_merged) + ds->has_merged = 1; + + if (in_progress) + ds->has_in_progress = 1; + + if (io_time) + ds->has_io_time = 1; + } /* if (is_disk) */ /* Don't write to the RRDs if we've just started.. */ @@ -887,13 +883,17 @@ static int disk_read (void) output_name = disk_name; #if HAVE_LIBUDEV - alt_name = disk_udev_attr_name (handle_udev, disk_name, - conf_udev_name_attr); -#else - alt_name = NULL; + char *alt_name = NULL; + if (conf_udev_name_attr != NULL) + { + alt_name = disk_udev_attr_name (handle_udev, disk_name, conf_udev_name_attr); + if (alt_name != NULL) + output_name = alt_name; + } #endif - if (alt_name != NULL) - output_name = alt_name; + + if (ignorelist_match (ignorelist, output_name) != 0) + continue; if ((ds->read_bytes != 0) || (ds->write_bytes != 0)) disk_submit (output_name, "disk_octets", @@ -909,19 +909,21 @@ static int disk_read (void) if (is_disk) { - disk_submit (output_name, "disk_merged", + if (ds->has_merged) + disk_submit (output_name, "disk_merged", read_merged, write_merged); - submit_in_progress (output_name, in_progress); - submit_io_time (output_name, io_time, weighted_time); + if (ds->has_in_progress) + submit_in_progress (output_name, in_progress); + if (ds->has_io_time) + submit_io_time (output_name, io_time, weighted_time); } /* if (is_disk) */ +#if HAVE_LIBUDEV /* release udev-based alternate name, if allocated */ - free(alt_name); + sfree (alt_name); +#endif } /* while (fgets (buffer, sizeof (buffer), fh) != NULL) */ -#if HAVE_LIBUDEV - udev_unref(handle_udev); -#endif fclose (fh); /* #endif defined(KERNEL_LINUX) */ @@ -957,6 +959,9 @@ static int disk_read (void) if (strncmp (ksp[i]->ks_class, "disk", 4) == 0) { + if (ignorelist_match (ignorelist, ksp[i]->ks_name) != 0) + continue; + disk_submit (ksp[i]->ks_name, "disk_octets", kio.KIO_ROCTETS, kio.KIO_WOCTETS); disk_submit (ksp[i]->ks_name, "disk_ops", @@ -967,6 +972,9 @@ static int disk_read (void) } else if (strncmp (ksp[i]->ks_class, "partition", 9) == 0) { + if (ignorelist_match (ignorelist, ksp[i]->ks_name) != 0) + continue; + disk_submit (ksp[i]->ks_name, "disk_octets", kio.KIO_ROCTETS, kio.KIO_WOCTETS); disk_submit (ksp[i]->ks_name, "disk_ops", @@ -984,13 +992,19 @@ static int disk_read (void) #endif int 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 */ + + if (ignorelist_match (ignorelist, name) != 0) { + ds++; + continue; + } + disk_submit (name, "disk_octets", ds->read_bytes, ds->write_bytes); ds++; } @@ -1007,7 +1021,7 @@ static int disk_read (void) int rnumdisk; int i; - if ((numdisk = perfstat_disk(NULL, NULL, sizeof(perfstat_disk_t), 0)) < 0) + if ((numdisk = perfstat_disk(NULL, NULL, sizeof(perfstat_disk_t), 0)) < 0) { char errbuf[1024]; WARNING ("disk plugin: perfstat_disk: %s", @@ -1016,14 +1030,14 @@ static int disk_read (void) } if (numdisk != pnumdisk || stat_disk==NULL) { - if (stat_disk!=NULL) + if (stat_disk!=NULL) free(stat_disk); stat_disk = (perfstat_disk_t *)calloc(numdisk, sizeof(perfstat_disk_t)); - } + } pnumdisk = numdisk; firstpath.name[0]='\0'; - if ((rnumdisk = perfstat_disk(&firstpath, stat_disk, sizeof(perfstat_disk_t), numdisk)) < 0) + if ((rnumdisk = perfstat_disk(&firstpath, stat_disk, sizeof(perfstat_disk_t), numdisk)) < 0) { char errbuf[1024]; WARNING ("disk plugin: perfstat_disk : %s", @@ -1031,8 +1045,11 @@ static int disk_read (void) return (-1); } - for (i = 0; i < rnumdisk; i++) + for (i = 0; i < rnumdisk; i++) { + if (ignorelist_match (ignorelist, stat_disk[i].name) != 0) + continue; + read_sectors = stat_disk[i].rblks*stat_disk[i].bsize; write_sectors = stat_disk[i].wblks*stat_disk[i].bsize; disk_submit (stat_disk[i].name, "disk_octets", read_sectors, write_sectors); @@ -1057,5 +1074,6 @@ void module_register (void) plugin_register_config ("disk", disk_config, config_keys, config_keys_num); plugin_register_init ("disk", disk_init); + plugin_register_shutdown ("disk", disk_shutdown); plugin_register_read ("disk", disk_read); } /* void module_register */