Merge branch 'collectd-5.5' into collectd-5.6
[collectd.git] / src / disk.c
index 05a863f..d7eb0a5 100644 (file)
@@ -22,6 +22,7 @@
  **/
 
 #include "collectd.h"
+
 #include "common.h"
 #include "plugin.h"
 #include "utils_ignorelist.h"
@@ -106,6 +107,10 @@ 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;
 
@@ -226,7 +231,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
@@ -268,6 +282,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)
@@ -275,10 +300,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;
 
@@ -293,14 +314,12 @@ static void disk_submit (const char *plugin_instance,
        plugin_dispatch_values (&vl);
 } /* void disk_submit */
 
+#if KERNEL_FREEBSD || KERNEL_LINUX
 static void submit_io_time (char const *plugin_instance, derive_t io_time, derive_t weighted_time)
 {
        value_t values[2];
        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;
 
@@ -313,6 +332,7 @@ static void submit_io_time (char const *plugin_instance, derive_t io_time, deriv
 
        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)
@@ -320,9 +340,6 @@ static void submit_in_progress (char const *disk_name, gauge_t in_progress)
        value_t v;
        value_list_t vl = VALUE_LIST_INIT;
 
-       if (ignorelist_match (ignorelist, disk_name) != 0)
-         return;
-
        v.gauge = in_progress;
 
        vl.values = &v;
@@ -504,6 +521,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);
@@ -515,7 +541,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))
@@ -536,7 +561,7 @@ static int disk_read (void)
        struct gident *geom_id;
 
        const char *disk_name;
-       long double 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 != NULL)
@@ -613,6 +638,9 @@ static int disk_read (void)
 
                disk_name = ((struct gprovider *)geom_id->lg_ptr)->lg_name;
 
+               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",
                                        (derive_t)snap_iter->bytes[DEVSTAT_READ],
@@ -631,6 +659,16 @@ static int disk_read (void)
                        disk_submit (disk_name, "disk_time",
                                        (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);
 
@@ -673,10 +711,6 @@ 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;
@@ -818,6 +852,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.. */
@@ -840,11 +884,24 @@ static int disk_read (void)
                output_name = disk_name;
 
 #if HAVE_LIBUDEV
-               char *alt_name = disk_udev_attr_name (handle_udev, disk_name, conf_udev_name_attr);
-               if (alt_name != NULL)
-                       output_name = alt_name;
+               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 (ignorelist_match (ignorelist, output_name) != 0)
+               {
+#if HAVE_LIBUDEV
+                       /* release udev-based alternate name, if allocated */
+                       sfree (alt_name);
+#endif
+                       continue;
+               }
+
                if ((ds->read_bytes != 0) || (ds->write_bytes != 0))
                        disk_submit (output_name, "disk_octets",
                                        ds->read_bytes, ds->write_bytes);
@@ -859,10 +916,13 @@ 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
@@ -871,9 +931,6 @@ static int disk_read (void)
 #endif
        } /* while (fgets (buffer, sizeof (buffer), fh) != NULL) */
 
-#if HAVE_LIBUDEV
-       udev_unref(handle_udev);
-#endif
 
        fclose (fh);
 /* #endif defined(KERNEL_LINUX) */
@@ -897,18 +954,20 @@ static int disk_read (void)
 #  error "kstat_io_t does not have the required members"
 # endif
        static kstat_io_t kio;
-       int i;
 
        if (kc == NULL)
                return (-1);
 
-       for (i = 0; i < numdisk; i++)
+       for (int i = 0; i < numdisk; i++)
        {
                if (kstat_read (kc, ksp[i], &kio) == -1)
                        continue;
 
                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",
@@ -919,6 +978,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",
@@ -934,15 +996,20 @@ static int disk_read (void)
 # else
        int disks;
 #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++) {
+       for (int 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++;
        }
@@ -957,7 +1024,6 @@ static int disk_read (void)
        derive_t write_ops;
        perfstat_id_t firstpath;
        int rnumdisk;
-       int i;
 
        if ((numdisk = perfstat_disk(NULL, NULL, sizeof(perfstat_disk_t), 0)) < 0)
        {
@@ -983,8 +1049,11 @@ static int disk_read (void)
                return (-1);
        }
 
-       for (i = 0; i < rnumdisk; i++)
+       for (int 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);
@@ -1009,5 +1078,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 */