Merge branch 'collectd-5.7' into collectd-5.8
[collectd.git] / src / zfs_arc.c
index aff02b6..6c66fb1 100644 (file)
 /*
  * Global variables
  */
+static value_to_rate_state_t arc_hits_state;
+static value_to_rate_state_t arc_misses_state;
+static value_to_rate_state_t l2_hits_state;
+static value_to_rate_state_t l2_misses_state;
 
 #if defined(KERNEL_LINUX)
 #include "utils_llist.h"
@@ -75,11 +79,11 @@ static long long get_zfs_value(kstat_t *ksp, const char *key) {
 
   e = llist_search(ksp, key);
   if (e == NULL) {
-    return (-1);
+    return -1;
   }
 
   v = e->value;
-  return ((long long)v->derive);
+  return (long long)v->derive;
 }
 
 static void free_zfs_values(kstat_t *ksp) {
@@ -95,11 +99,16 @@ static void free_zfs_values(kstat_t *ksp) {
 }
 
 #elif defined(KERNEL_SOLARIS)
+
+#if HAVE_KSTAT_H
+#include <kstat.h>
+#endif
+
 extern kstat_ctl_t *kc;
 
 static long long get_zfs_value(kstat_t *ksp, char *name) {
 
-  return (get_kstat_value(ksp, name));
+  return get_kstat_value(ksp, name);
 }
 #elif defined(KERNEL_FREEBSD)
 #include <sys/sysctl.h>
@@ -118,13 +127,13 @@ static long long get_zfs_value(kstat_t *dummy __attribute__((unused)),
   size_t valuelen = sizeof(value);
   int rv;
 
-  ssnprintf(buffer, sizeof(buffer), "%s%s", zfs_arcstat, name);
+  snprintf(buffer, sizeof(buffer), "%s%s", zfs_arcstat, name);
   rv = sysctlbyname(buffer, (void *)&value, &valuelen,
                     /* new value = */ NULL, /* new length = */ (size_t)0);
   if (rv == 0)
-    return (value);
+    return value;
 
-  return (-1);
+  return -1;
 }
 #endif
 
@@ -152,12 +161,12 @@ static int za_read_derive(kstat_t *ksp, const char *kstat_value,
   long long tmp = get_zfs_value(ksp, (char *)kstat_value);
   if (tmp == -1LL) {
     DEBUG("zfs_arc plugin: Reading kstat value \"%s\" failed.", kstat_value);
-    return (-1);
+    return -1;
   }
 
   za_submit(type, type_instance, &(value_t){.derive = (derive_t)tmp},
             /* values_num = */ 1);
-  return (0);
+  return 0;
 }
 
 static int za_read_gauge(kstat_t *ksp, const char *kstat_value,
@@ -165,12 +174,12 @@ static int za_read_gauge(kstat_t *ksp, const char *kstat_value,
   long long tmp = get_zfs_value(ksp, (char *)kstat_value);
   if (tmp == -1LL) {
     DEBUG("zfs_arc plugin: Reading kstat value \"%s\" failed.", kstat_value);
-    return (-1);
+    return -1;
   }
 
   za_submit(type, type_instance, &(value_t){.gauge = (gauge_t)tmp},
             /* values_num = */ 1);
-  return (0);
+  return 0;
 }
 
 static void za_submit_ratio(const char *type_instance, gauge_t hits,
@@ -201,14 +210,26 @@ static int za_read(void) {
     char errbuf[1024];
     ERROR("zfs_arc plugin: Opening \"%s\" failed: %s", ZOL_ARCSTATS_FILE,
           sstrerror(errno, errbuf, sizeof(errbuf)));
-    return (-1);
+    return -1;
+  }
+
+  /* Ignore the first two lines because they contain information about the rest
+   * of the file.
+   * See kstat_seq_show_headers module/spl/spl-kstat.c of the spl kernel module.
+   */
+  if ((fgets(buffer, sizeof(buffer), fh) == NULL) ||
+      (fgets(buffer, sizeof(buffer), fh) == NULL)) {
+    ERROR("zfs_arc plugin: \"%s\" does not contain at least two lines.",
+          ZOL_ARCSTATS_FILE);
+    fclose(fh);
+    return -1;
   }
 
   ksp = llist_create();
   if (ksp == NULL) {
     ERROR("zfs_arc plugin: `llist_create' failed.");
     fclose(fh);
-    return (-1);
+    return -1;
   }
 
   // Ignore the first two lines because they contain information about
@@ -216,12 +237,14 @@ static int za_read(void) {
   // See kstat_seq_show_headers module/spl/spl-kstat.c of the spl kernel
   // module.
   if (fgets(buffer, sizeof(buffer), fh) == NULL) {
-    ERROR("zfs_arc plugin: \"%s\" does not contain a single line.", ZOL_ARCSTATS_FILE);
+    ERROR("zfs_arc plugin: \"%s\" does not contain a single line.",
+          ZOL_ARCSTATS_FILE);
     fclose(fh);
     return (-1);
   }
   if (fgets(buffer, sizeof(buffer), fh) == NULL) {
-    ERROR("zfs_arc plugin: \"%s\" does not contain at least two lines.", ZOL_ARCSTATS_FILE);
+    ERROR("zfs_arc plugin: \"%s\" does not contain at least two lines.",
+          ZOL_ARCSTATS_FILE);
     fclose(fh);
     return (-1);
   }
@@ -248,7 +271,7 @@ static int za_read(void) {
   get_kstat(&ksp, "zfs", 0, "arcstats");
   if (ksp == NULL) {
     ERROR("zfs_arc plugin: Cannot find zfs:0:arcstats kstat.");
-    return (-1);
+    return -1;
   }
 #endif
 
@@ -311,14 +334,25 @@ static int za_read(void) {
   za_read_derive(ksp, "mru_hits", "cache_result", "mru-hit");
   za_read_derive(ksp, "mru_ghost_hits", "cache_result", "mru_ghost-hit");
 
+  cdtime_t now = cdtime();
+
   /* Ratios */
-  arc_hits = (gauge_t)get_zfs_value(ksp, "hits");
-  arc_misses = (gauge_t)get_zfs_value(ksp, "misses");
-  l2_hits = (gauge_t)get_zfs_value(ksp, "l2_hits");
-  l2_misses = (gauge_t)get_zfs_value(ksp, "l2_misses");
+  if ((value_to_rate(&arc_hits, (value_t){.derive = get_zfs_value(ksp, "hits")},
+                     DS_TYPE_DERIVE, now, &arc_hits_state) == 0) &&
+      (value_to_rate(&arc_misses,
+                     (value_t){.derive = get_zfs_value(ksp, "misses")},
+                     DS_TYPE_DERIVE, now, &arc_misses_state) == 0)) {
+    za_submit_ratio("arc", arc_hits, arc_misses);
+  }
 
-  za_submit_ratio("arc", arc_hits, arc_misses);
-  za_submit_ratio("L2", l2_hits, l2_misses);
+  if ((value_to_rate(&l2_hits,
+                     (value_t){.derive = get_zfs_value(ksp, "l2_hits")},
+                     DS_TYPE_DERIVE, now, &l2_hits_state) == 0) &&
+      (value_to_rate(&l2_misses,
+                     (value_t){.derive = get_zfs_value(ksp, "l2_misses")},
+                     DS_TYPE_DERIVE, now, &l2_misses_state) == 0)) {
+    za_submit_ratio("L2", l2_hits, l2_misses);
+  }
 
   /* I/O */
   value_t l2_io[] = {
@@ -331,7 +365,7 @@ static int za_read(void) {
   free_zfs_values(ksp);
 #endif
 
-  return (0);
+  return 0;
 } /* int za_read */
 
 static int za_init(void) /* {{{ */
@@ -341,11 +375,11 @@ static int za_init(void) /* {{{ */
    * went fine. */
   if (kc == NULL) {
     ERROR("zfs_arc plugin: kstat chain control structure not available.");
-    return (-1);
+    return -1;
   }
 #endif
 
-  return (0);
+  return 0;
 } /* }}} int za_init */
 
 void module_register(void) {