X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Fzfs_arc.c;h=dd633d5f2287352969f1619f553c105eccd7eade;hb=155102256542b6dab3261cd2d6dfb000354de425;hp=4190a717e01d264431bbd02412e679f925888adc;hpb=521df2eab8db4c5d370310b9739fbdb6a3e66557;p=collectd.git diff --git a/src/zfs_arc.c b/src/zfs_arc.c index 4190a717..dd633d5f 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,12 +39,9 @@ #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)), +static long long get_zfs_value(kstat_t *zfs_stats __attribute__((unused)), char *name) { llentry_t *e; @@ -54,7 +53,7 @@ static long long get_zfs_value(kstat_t *dummy __attribute__((unused)), return (-1); } - return ((long long int)e->value); + return (*(long long int*)e->value); } #elif !defined(__FreeBSD__) // Solaris @@ -174,66 +173,71 @@ static int za_read (void) kstat_t *ksp = NULL; #if KERNEL_LINUX - FILE *fh; - - char buf[1024]; + long long int *llvalues = NULL; + char file_contents[1024 * 10]; char *fields[3]; int numfields; + ssize_t len; - if ((fh = fopen (ZOL_ARCSTATS_FILE, "r")) == NULL) - { - char errbuf[1024]; - ERROR ("zfs_arc plugin: `fopen (%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) + len = read_file_contents (ZOL_ARCSTATS_FILE, file_contents, sizeof(file_contents)); + if (len > 1) { - numfields = strsplit (buf, fields, 4); - if (numfields != 3) - continue; - - char *llkey; - long long int llvalue; - - llkey = strdup (fields[0]); - if (llkey == NULL) { - char errbuf[1024]; - ERROR ("zfs_arc plugin: `strdup' failed: %s", - sstrerror (errno, errbuf, sizeof (errbuf))); - continue; - } - llvalue = atoll (fields[2]); + int i=0; + char *pnl = file_contents; + char *pnnl; + + file_contents[len] = '\0'; - llentry_t *e; - e = llentry_create (llkey, (void *)llvalue); - if (e == NULL) + while (pnl != NULL) { - ERROR ("zfs_arc plugin: `llentry_create' failed."); - free (llkey); - continue; + pnl = strchr(pnl, '\n'); + i++; + if (pnl && (*pnl != '\0')) + pnl++; } - free (llkey); - - llist_append (zfs_stats, e); - } - - if (fclose (fh)) - { - char errbuf[1024]; - WARNING ("zfs_arc: `fclose' failed: %s", sstrerror (errno, errbuf, sizeof (errbuf))); + if (i > 0) + { + llentry_t *e; + llvalues = malloc(sizeof(long long int) * i); + int j = 0; + + pnl = file_contents; + while (pnl != NULL) + { + pnnl = strchr(pnl, '\n'); + if (pnnl != NULL) + *pnnl = '\0'; + + numfields = strsplit (pnl, fields, 4); + if (numfields == 3) + { + llvalues[j] = atoll (fields[2]); + + e = llentry_create (fields[0], &llvalues[j]); + if (e == NULL) + { + ERROR ("zfs_arc plugin: `llentry_create' failed."); + } + else + { + llist_append (ksp, e); + } + j++; + } + pnl = pnnl; + if (pnl != NULL) + pnl ++; + } + } } #elif !defined(__FreeBSD__) // Solaris @@ -247,7 +251,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,9 +305,13 @@ static int za_read (void) za_submit ("io_octets", "L2", l2_io, /* num values = */ 2); #if defined(KERNEL_LINUX) - if (zfs_stats != NULL) + if (llvalues != NULL) + { + free(llvalues); + } + if (ksp != NULL) { - llist_destroy (zfs_stats); + llist_destroy (ksp); } #endif