Merge branch 'collectd-5.3' into collectd-5.4
[collectd.git] / src / zfs_arc.c
index b8bccde..3a54ad8 100644 (file)
@@ -2,6 +2,7 @@
  * collectd - src/zfs_arc.c
  * Copyright (C) 2009  Anthony Dewhurst
  * Copyright (C) 2012  Aurelien Rougemont
+ * Copyright (C) 2013  Xin Li
  *
  * 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
@@ -19,6 +20,7 @@
  * Authors:
  *   Anthony Dewhurst <dewhurst at gmail>
  *   Aurelien Rougemont <beorn at gandi.net>
+ *   Xin Li <delphij at FreeBSD.org>
  **/
 
 #include "collectd.h"
@@ -47,23 +49,19 @@ const char zfs_arcstat[] = "kstat.zfs.misc.arcstats.";
 typedef void kstat_t;
 #endif
 
-static long long get_zfs_value(void * dummy __unused, const char *kstat_value)
+static long long get_zfs_value(kstat_t *dummy __attribute__((unused)),
+               char const *name)
 {
+       char buffer[256];
        long long value;
        size_t valuelen = sizeof(value);
        int rv;
-       char *key;
-
-       key = ssnprintf_alloc("%s%s", zfs_arcstat, kstat_value);
-       if (key != NULL) {
-               if (strlen(key) > 0) {
-                       rv = sysctlbyname(key, (void *)&value, &valuelen, NULL, (size_t)0);
-                       free(key);
-                       if (rv == 0)
-                               return (value);
-               } else
-                       free(key);
-       }
+
+       ssnprintf (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 (-1);
 }
@@ -101,7 +99,7 @@ static int za_read_derive (kstat_t *ksp, const char *kstat_value,
   tmp = get_zfs_value (ksp, (char *)kstat_value);
   if (tmp == -1LL)
   {
-    ERROR ("zfs_arc plugin: Reading kstat value \"%s\" failed.", kstat_value);
+    WARNING ("zfs_arc plugin: Reading kstat value \"%s\" failed.", kstat_value);
     return (-1);
   }
 
@@ -119,7 +117,7 @@ static int za_read_gauge (kstat_t *ksp, const char *kstat_value,
   tmp = get_zfs_value (ksp, (char *)kstat_value);
   if (tmp == -1LL)
   {
-    ERROR ("zfs_arc plugin: Reading kstat value \"%s\" failed.", kstat_value);
+    WARNING ("zfs_arc plugin: Reading kstat value \"%s\" failed.", kstat_value);
     return (-1);
   }
 
@@ -160,18 +158,27 @@ static int za_read (void)
 
        /* Sizes */
        za_read_gauge (ksp, "size",    "cache_size", "arc");
-       za_read_gauge (ksp, "l2_size", "cache_size", "L2");
 
-        /* Operations */
-       za_read_derive (ksp, "allocated","cache_operation", "allocated");
+       /* The "l2_size" value has disappeared from Solaris some time in
+        * early 2013, and has only reappeared recently in Solaris 11.2.
+        * Stop trying if we ever fail to read it, so we don't spam the log.
+        */
+       static int l2_size_avail = 1;
+       if (l2_size_avail && za_read_gauge (ksp, "l2_size", "cache_size", "L2") != 0)
+               l2_size_avail = 0;
+
+       /* Operations */
        za_read_derive (ksp, "deleted",  "cache_operation", "deleted");
+#if __FreeBSD__
+       za_read_derive (ksp, "allocated","cache_operation", "allocated");
        za_read_derive (ksp, "stolen",   "cache_operation", "stolen");
+#endif
 
-        /* Issue indicators */
-        za_read_derive (ksp, "mutex_miss", "mutex_operations", "miss");
+       /* Issue indicators */
+       za_read_derive (ksp, "mutex_miss", "mutex_operations", "miss");
        za_read_derive (ksp, "hash_collisions", "hash_collisions", "");
        
-        /* Evictions */
+       /* Evictions */
        za_read_derive (ksp, "evict_l2_cached",     "cache_eviction", "cached");
        za_read_derive (ksp, "evict_l2_eligible",   "cache_eviction", "eligible");
        za_read_derive (ksp, "evict_l2_ineligible", "cache_eviction", "ineligible");