X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Fzfs_arc.c;h=1a7613c74a53cec15c7750395edd839220f2788c;hb=6a1a62048b6d0d2ddf5c17295609d3ebf010f40b;hp=4190a717e01d264431bbd02412e679f925888adc;hpb=521df2eab8db4c5d370310b9739fbdb6a3e66557;p=collectd.git diff --git a/src/zfs_arc.c b/src/zfs_arc.c index 4190a717..1a7613c7 100644 --- a/src/zfs_arc.c +++ b/src/zfs_arc.c @@ -4,6 +4,7 @@ * Copyright (C) 2012 Aurelien Rougemont * Copyright (C) 2013 Xin Li * Copyright (C) 2014 Marc Fournier + * Copyright (C) 2014 Wilfried Goesgens * * 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 @@ -23,6 +24,7 @@ * Aurelien Rougemont * Xin Li * Marc Fournier + * Wilfried Goesgens **/ #include "collectd.h" @@ -37,24 +39,68 @@ #include "utils_llist.h" #define ZOL_ARCSTATS_FILE "/proc/spl/kstat/zfs/arcstats" -#if !defined(kstat_t) -typedef void kstat_t; -static llist_t *zfs_stats = NULL; -#endif +typedef llist_t kstat_t; -static long long get_zfs_value(kstat_t *dummy __attribute__((unused)), - char *name) +static int put_zfs_value (kstat_t *ksp, char const *k, value_t v) { llentry_t *e; + char *k_copy; + value_t *v_copy; + + k_copy = strdup (k); + if (k_copy == NULL) + return ENOMEM; - e = llist_search (zfs_stats, name); + v_copy = malloc (sizeof (*v_copy)); + if (v_copy == NULL) + { + sfree (k_copy); + return ENOMEM; + } + *v_copy = v; + + e = llentry_create (k_copy, v_copy); if (e == NULL) { - ERROR ("zfs_arc plugin: `llist_search` failed for key: '%s'.", name); + sfree (v_copy); + sfree (k_copy); + return ENOMEM; + } + + llist_append (ksp, e); + return 0; +} + +static long long get_zfs_value(kstat_t *ksp, char *key) +{ + llentry_t *e; + value_t *v; + + e = llist_search (ksp, key); + if (e == NULL) + { + ERROR ("zfs_arc plugin: `llist_search` failed for key: '%s'.", key); return (-1); } - return ((long long int)e->value); + v = e->value; + return ((long long) v->derive); +} + +static void free_zfs_values (kstat_t *ksp) +{ + llentry_t *e; + + if (ksp == NULL) + return; + + for (e = llist_head (ksp); e != NULL; e = e->next) + { + sfree (e->key); + sfree (e->value); + } + + llist_destroy (ksp); } #elif !defined(__FreeBSD__) // Solaris @@ -175,66 +221,43 @@ static int za_read (void) #if KERNEL_LINUX FILE *fh; + char buffer[1024]; - char buf[1024]; - char *fields[3]; - int numfields; - - if ((fh = fopen (ZOL_ARCSTATS_FILE, "r")) == NULL) + fh = fopen (ZOL_ARCSTATS_FILE, "r"); + if (fh == NULL) { char errbuf[1024]; - ERROR ("zfs_arc plugin: `fopen (%s)' failed: %s", - ZOL_ARCSTATS_FILE, - sstrerror (errno, errbuf, sizeof (errbuf))); + ERROR ("zfs_arc plugin: Opening \"%s\" failed: %s", ZOL_ARCSTATS_FILE, + sstrerror (errno, errbuf, sizeof (errbuf))); return (-1); } - zfs_stats = llist_create (); - if (zfs_stats == NULL) + ksp = llist_create (); + if (ksp == NULL) { ERROR ("zfs_arc plugin: `llist_create' failed."); fclose (fh); return (-1); } - while (fgets (buf, 1024, fh) != NULL) + while (fgets (buffer, sizeof (buffer), fh) != NULL) { - numfields = strsplit (buf, fields, 4); - if (numfields != 3) - continue; - - char *llkey; - long long int llvalue; + char *fields[3]; + value_t v; + int status; - llkey = strdup (fields[0]); - if (llkey == NULL) { - char errbuf[1024]; - ERROR ("zfs_arc plugin: `strdup' failed: %s", - sstrerror (errno, errbuf, sizeof (errbuf))); + status = strsplit (buffer, fields, STATIC_ARRAY_SIZE (fields)); + if (status != 3) continue; - } - - llvalue = atoll (fields[2]); - llentry_t *e; - e = llentry_create (llkey, (void *)llvalue); - if (e == NULL) - { - ERROR ("zfs_arc plugin: `llentry_create' failed."); - free (llkey); + status = parse_value (fields[2], &v, DS_TYPE_DERIVE); + if (status != 0) continue; - } - free (llkey); - - llist_append (zfs_stats, e); + put_zfs_value (ksp, fields[0], v); } - if (fclose (fh)) - { - char errbuf[1024]; - WARNING ("zfs_arc: `fclose' failed: %s", sstrerror (errno, errbuf, sizeof (errbuf))); - } + fclose (fh); #elif !defined(__FreeBSD__) // Solaris get_kstat (&ksp, "zfs", 0, "arcstats"); @@ -247,7 +270,17 @@ static int za_read (void) /* Sizes */ za_read_gauge (ksp, "size", "cache_size", "arc"); - za_read_gauge (ksp, "l2_size", "cache_size", "L2"); + za_read_gauge (ksp, "c", "cache_size", "c"); + za_read_gauge (ksp, "c_min", "cache_size", "c_min"); + za_read_gauge (ksp, "c_max", "cache_size", "c_max"); + + /* 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"); @@ -291,10 +324,7 @@ static int za_read (void) za_submit ("io_octets", "L2", l2_io, /* num values = */ 2); #if defined(KERNEL_LINUX) - if (zfs_stats != NULL) - { - llist_destroy (zfs_stats); - } + free_zfs_values (ksp); #endif return (0);