X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fzfs_arc.c;h=f0d23239a82ab158c03c669f9a96cf2fc7f8dd24;hb=880246ed45437c4d1f52600ac14b18cb9f78d746;hp=96ffc54957aae84a8fb548e3df352307a9a9d168;hpb=1894607dc4c03ce20db7c5256c97890aa70bcaa5;p=collectd.git diff --git a/src/zfs_arc.c b/src/zfs_arc.c index 96ffc549..f0d23239 100644 --- a/src/zfs_arc.c +++ b/src/zfs_arc.c @@ -3,6 +3,8 @@ * Copyright (C) 2009 Anthony Dewhurst * 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 @@ -21,6 +23,8 @@ * Anthony Dewhurst * Aurelien Rougemont * Xin Li + * Marc Fournier + * Wilfried Goesgens **/ #include "collectd.h" @@ -31,7 +35,28 @@ * Global variables */ -#if !defined(__FreeBSD__) +#if defined(KERNEL_LINUX) +#include "utils_llist.h" +#define ZOL_ARCSTATS_FILE "/proc/spl/kstat/zfs/arcstats" + +typedef llist_t kstat_t; + +static long long get_zfs_value(kstat_t *zfs_stats __attribute__((unused)), + char *name) +{ + llentry_t *e; + + e = llist_search (zfs_stats, name); + if (e == NULL) + { + ERROR ("zfs_arc plugin: `llist_search` failed for key: '%s'.", name); + return (-1); + } + + return (*(long long int*)e->value); +} + +#elif !defined(__FreeBSD__) // Solaris extern kstat_ctl_t *kc; static long long get_zfs_value(kstat_t *ksp, char *name) @@ -39,7 +64,7 @@ static long long get_zfs_value(kstat_t *ksp, char *name) return (get_kstat_value(ksp, name)); } -#else +#else // FreeBSD #include #include @@ -147,7 +172,75 @@ static int za_read (void) value_t l2_io[2]; kstat_t *ksp = NULL; -#if !defined(__FreeBSD__) +#if KERNEL_LINUX + long long int *llvalues = NULL; + char file_contents[1024 * 10]; + char *fields[3]; + int numfields; + ssize_t len; + + ksp = llist_create (); + if (ksp == NULL) + { + ERROR ("zfs_arc plugin: `llist_create' failed."); + return (-1); + } + + len = read_file_contents (ZOL_ARCSTATS_FILE, file_contents, sizeof(file_contents)); + if (len > 1) + { + + int i=0; + char *pnl = file_contents; + char *pnnl; + + file_contents[len] = '\0'; + + while (pnl != NULL) + { + pnl = strchr(pnl, '\n'); + i++; + if (pnl && (*pnl != '\0')) + pnl++; + } + + 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 get_kstat (&ksp, "zfs", 0, "arcstats"); if (ksp == NULL) { @@ -158,7 +251,14 @@ static int za_read (void) /* Sizes */ za_read_gauge (ksp, "size", "cache_size", "arc"); - za_read_gauge (ksp, "l2_size", "cache_size", "L2"); + + /* 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"); @@ -170,7 +270,7 @@ static int za_read (void) /* Issue indicators */ za_read_derive (ksp, "mutex_miss", "mutex_operations", "miss"); za_read_derive (ksp, "hash_collisions", "hash_collisions", ""); - + /* Evictions */ za_read_derive (ksp, "evict_l2_cached", "cache_eviction", "cached"); za_read_derive (ksp, "evict_l2_eligible", "cache_eviction", "eligible"); @@ -201,12 +301,23 @@ static int za_read (void) za_submit ("io_octets", "L2", l2_io, /* num values = */ 2); +#if defined(KERNEL_LINUX) + if (llvalues != NULL) + { + free(llvalues); + } + if (ksp != NULL) + { + llist_destroy (ksp); + } +#endif + return (0); } /* int za_read */ static int za_init (void) /* {{{ */ { -#if !defined(__FreeBSD__) +#if !defined(__FreeBSD__) && !defined(KERNEL_LINUX) // Solaris /* kstats chain already opened by update_kstat (using *kc), verify everything went fine. */ if (kc == NULL) {