X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fnfs.c;h=f2db895a00d484bf647e1c2a9a7688dd106ca31e;hb=c1318b06b424523d3704fcdfd16d3adb25d17d18;hp=d0f33c5238269638d00ae52b8bb462b3489ddb0f;hpb=8822d7c9d8e86358cc4bb86e306ff90e40a15401;p=collectd.git diff --git a/src/nfs.c b/src/nfs.c index d0f33c52..f5b579e1 100644 --- a/src/nfs.c +++ b/src/nfs.c @@ -1,11 +1,11 @@ /** * collectd - src/nfs.c * Copyright (C) 2005,2006 Jason Pepas + * Copyright (C) 2012,2013 Florian Forster * * 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 - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. + * Free Software Foundation; only version 2 of the License is applicable. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of @@ -18,25 +18,18 @@ * * Authors: * Jason Pepas - * Florian octo Forster + * Florian octo Forster + * Cosmin Ioiart **/ #include "collectd.h" #include "common.h" #include "plugin.h" -#define MODULE_NAME "nfs" - -/* #if defined(KERNEL_LINUX) || defined(HAVE_LIBKSTAT) */ -#if KERNEL_LINUX -# define NFS_HAVE_READ 1 -#else -# define NFS_HAVE_READ 0 +#if HAVE_KSTAT_H +#include #endif -static char *nfs2_procedures_file = "nfs2_procedures-%s.rrd"; -static char *nfs3_procedures_file = "nfs3_procedures-%s.rrd"; - /* see /proc/net/rpc/nfs see http://www.missioncriticallinux.com/orph/NFS-Statistics @@ -82,59 +75,103 @@ Number Procedures Procedures 21 commit */ -static char *nfs2_procedures_ds_def[] = +static const char *nfs2_procedures_names[] = { - "DS:null:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:getattr:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:setattr:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:root:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:lookup:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:readlink:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:read:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:wrcache:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:write:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:create:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:remove:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:rename:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:link:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:symlink:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:mkdir:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:rmdir:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:readdir:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:fsstat:COUNTER:"COLLECTD_HEARTBEAT":0:U", - NULL + "null", + "getattr", + "setattr", + "root", + "lookup", + "readlink", + "read", + "wrcache", + "write", + "create", + "remove", + "rename", + "link", + "symlink", + "mkdir", + "rmdir", + "readdir", + "fsstat" }; -static int nfs2_procedures_ds_num = 18; +static size_t nfs2_procedures_names_num = STATIC_ARRAY_SIZE (nfs2_procedures_names); -static char *nfs3_procedures_ds_def[] = +static const char *nfs3_procedures_names[] = { - "DS:null:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:getattr:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:setattr:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:lookup:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:access:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:readlink:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:read:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:write:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:create:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:mkdir:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:symlink:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:mknod:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:remove:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:rmdir:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:rename:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:link:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:readdir:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:readdirplus:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:fsstat:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:fsinfo:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:pathconf:COUNTER:"COLLECTD_HEARTBEAT":0:U", - "DS:commit:COUNTER:"COLLECTD_HEARTBEAT":0:U", - NULL + "null", + "getattr", + "setattr", + "lookup", + "access", + "readlink", + "read", + "write", + "create", + "mkdir", + "symlink", + "mknod", + "remove", + "rmdir", + "rename", + "link", + "readdir", + "readdirplus", + "fsstat", + "fsinfo", + "pathconf", + "commit" }; -static int nfs3_procedures_ds_num = 22; +static size_t nfs3_procedures_names_num = STATIC_ARRAY_SIZE (nfs3_procedures_names); + +#if HAVE_LIBKSTAT +static const char *nfs4_procedures_names[] = +{ + "null", + "compound", + "reserved", + "access", + "close", + "commit", + "create", + "delegpurge", + "delegreturn", + "getattr", + "getfh", + "link", + "lock", + "lockt", + "locku", + "lookup", + "lookupp", + "nverify", + "open", + "openattr", + "open_confirm", + "open_downgrade", + "putfh", + "putpubfh", + "putrootfh", + "read", + "readdir", + "readlink", + "remove", + "rename", + "renew", + "restorefh", + "savefh", + "secinfo", + "setattr", + "setclientid", + "setclientid_confirm", + "verify", + "write" +}; +static size_t nfs4_procedures_names_num = STATIC_ARRAY_SIZE (nfs4_procedures_names); +#endif -#if HAVE_LIBKSTAT && 0 +#if HAVE_LIBKSTAT extern kstat_ctl_t *kc; static kstat_t *nfs2_ksp_client; static kstat_t *nfs2_ksp_server; @@ -146,10 +183,17 @@ static kstat_t *nfs4_ksp_server; /* Possibly TODO: NFSv4 statistics */ -static void nfs_init (void) +#if KERNEL_LINUX +static int nfs_init (void) +{ + return (0); +} +/* #endif KERNEL_LINUX */ + +#elif HAVE_LIBKSTAT +static int nfs_init (void) { -#if HAVE_LIBKSTAT && 0 - kstat_t *ksp_chain; + kstat_t *ksp_chain = NULL; nfs2_ksp_client = NULL; nfs2_ksp_server = NULL; @@ -157,9 +201,9 @@ static void nfs_init (void) nfs3_ksp_server = NULL; nfs4_ksp_client = NULL; nfs4_ksp_server = NULL; - + if (kc == NULL) - return; + return (-1); for (ksp_chain = kc->kc_chain; ksp_chain != NULL; ksp_chain = ksp_chain->ks_next) @@ -179,221 +223,174 @@ static void nfs_init (void) else if (strncmp (ksp_chain->ks_name, "rfsreqcnt_v4", 12) == 0) nfs4_ksp_client = ksp_chain; } -#endif - return; -} - -#define BUFSIZE 1024 -static void nfs2_procedures_write (char *host, char *inst, char *val) -{ - char filename[BUFSIZE]; - - if (snprintf (filename, BUFSIZE, nfs2_procedures_file, inst) > BUFSIZE) - return; - - rrd_update_file (host, filename, val, nfs2_procedures_ds_def, - nfs2_procedures_ds_num); -} + return (0); +} /* int nfs_init */ +#endif -static void nfs3_procedures_write (char *host, char *inst, char *val) +static void nfs_procedures_submit (const char *plugin_instance, + const char **type_instances, + value_t *values, size_t values_num) { - char filename[BUFSIZE]; + value_list_t vl = VALUE_LIST_INIT; + size_t i; - if (snprintf (filename, BUFSIZE, nfs3_procedures_file, inst) > BUFSIZE) - return; + vl.values_len = 1; + sstrncpy (vl.host, hostname_g, sizeof (vl.host)); + sstrncpy (vl.plugin, "nfs", sizeof (vl.plugin)); + sstrncpy (vl.plugin_instance, plugin_instance, + sizeof (vl.plugin_instance)); + sstrncpy (vl.type, "nfs_procedure", sizeof (vl.type)); - rrd_update_file (host, filename, val, nfs3_procedures_ds_def, - nfs3_procedures_ds_num); -} + for (i = 0; i < values_num; i++) + { + vl.values = values + i; + sstrncpy (vl.type_instance, type_instances[i], + sizeof (vl.type_instance)); + plugin_dispatch_values (&vl); + } +} /* void nfs_procedures_submit */ -#if NFS_HAVE_READ -static void nfs2_procedures_submit (unsigned long long *val, char *inst) +#if KERNEL_LINUX +static int nfs_submit_fields (int nfs_version, const char *instance, + char **fields, size_t fields_num, + const char **proc_names, size_t proc_names_num) { - char buf[BUFSIZE]; - int retval = 0; - - retval = snprintf (buf, BUFSIZE, "%u:%llu:%llu:%llu:%llu:%llu:%llu:" - "%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:" - "%llu:%llu:%llu", /* 18x %llu */ - (unsigned int) curtime, - val[0], val[1], val[2], val[3], val[4], val[5], val[6], - val[7], val[8], val[9], val[10], val[11], val[12], - val[13], val[14], val[15], val[16], val[17]); + char plugin_instance[DATA_MAX_NAME_LEN]; + value_t values[fields_num]; + size_t i; - - if (retval >= BUFSIZE) - return; - else if (retval < 0) + if (fields_num != proc_names_num) { - syslog (LOG_ERR, "nfs: snprintf's format failed: %s", strerror (errno)); - return; + WARNING ("nfs plugin: Wrong number of fields for " + "NFSv%i %s statistics. Expected %zu, got %zu.", + nfs_version, instance, + proc_names_num, fields_num); + return (EINVAL); } - plugin_submit ("nfs2_procedures", inst, buf); -} + ssnprintf (plugin_instance, sizeof (plugin_instance), "v%i%s", + nfs_version, instance); -static void nfs3_procedures_submit (unsigned long long *val, char *inst) -{ - char buf[BUFSIZE]; - int retval = 0; - - retval = snprintf(buf, BUFSIZE, "%u:%llu:%llu:%llu:%llu:%llu:%llu:" - "%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:" - "%llu:%llu:%llu:%llu:%llu:%llu:%llu", /* 22x %llu */ - (unsigned int) curtime, - val[0], val[1], val[2], val[3], val[4], val[5], val[6], - val[7], val[8], val[9], val[10], val[11], val[12], - val[13], val[14], val[15], val[16], val[17], val[18], - val[19], val[20], val[21]); - - if (retval >= BUFSIZE) - return; - else if (retval < 0) - { - syslog (LOG_ERR, "nfs: snprintf's format failed: %s", strerror (errno)); - return; - } + for (i = 0; i < proc_names_num; i++) + (void) parse_value (fields[i], &values[i], DS_TYPE_DERIVE); - plugin_submit("nfs3_procedures", inst, buf); + nfs_procedures_submit (plugin_instance, proc_names, values, + proc_names_num); + + return (0); } -#endif /* NFS_HAVE_READ */ -#if KERNEL_LINUX -static void nfs_read_stats_file (FILE *fh, char *inst) +static void nfs_read_linux (FILE *fh, char *inst) { - char buffer[BUFSIZE]; + char buffer[1024]; char *fields[48]; - int numfields = 0; + int fields_num = 0; if (fh == NULL) return; - while (fgets (buffer, BUFSIZE, fh) != NULL) + while (fgets (buffer, sizeof (buffer), fh) != NULL) { - numfields = strsplit (buffer, fields, 48); + fields_num = strsplit (buffer, + fields, STATIC_ARRAY_SIZE (fields)); - if (numfields < 2) + if (fields_num < 3) continue; - if (strncmp (fields[0], "proc2", 5) == 0) + if (strcmp (fields[0], "proc2") == 0) { - int i; - unsigned long long *values; - - if (numfields - 2 != nfs2_procedures_ds_num) - { - syslog (LOG_WARNING, "nfs: Wrong number of fields (= %i) for NFS2 statistics.", numfields - 2); - continue; - } - - if ((values = (unsigned long long *) malloc (nfs2_procedures_ds_num * sizeof (unsigned long long))) == NULL) - { - syslog (LOG_ERR, "nfs: malloc: %s", strerror (errno)); - continue; - } - - for (i = 0; i < nfs2_procedures_ds_num; i++) - values[i] = atoll (fields[i + 2]); - - nfs2_procedures_submit (values, inst); - - free (values); + nfs_submit_fields (/* version = */ 2, inst, + fields + 2, (size_t) (fields_num - 2), + nfs2_procedures_names, + nfs2_procedures_names_num); } else if (strncmp (fields[0], "proc3", 5) == 0) { - int i; - unsigned long long *values; + nfs_submit_fields (/* version = */ 3, inst, + fields + 2, (size_t) (fields_num - 2), + nfs3_procedures_names, + nfs3_procedures_names_num); + } + } /* while (fgets) */ +} /* void nfs_read_linux */ +#endif /* KERNEL_LINUX */ - if (numfields - 2 != nfs3_procedures_ds_num) - { - syslog (LOG_WARNING, "nfs: Wrong number of fields (= %i) for NFS3 statistics.", numfields - 2); - continue; - } +#if HAVE_LIBKSTAT +static int nfs_read_kstat (kstat_t *ksp, int nfs_version, char *inst, + char const **proc_names, size_t proc_names_num) +{ + char plugin_instance[DATA_MAX_NAME_LEN]; + value_t values[proc_names_num]; + size_t i; - if ((values = (unsigned long long *) malloc (nfs3_procedures_ds_num * sizeof (unsigned long long))) == NULL) - { - syslog (LOG_ERR, "nfs: malloc: %s", strerror (errno)); - continue; - } + if (ksp == NULL) + return (EINVAL); - for (i = 0; i < nfs3_procedures_ds_num; i++) - values[i] = atoll (fields[i + 2]); + ssnprintf (plugin_instance, sizeof (plugin_instance), "v%i%s", + nfs_version, inst); - nfs3_procedures_submit (values, inst); + kstat_read(kc, ksp, NULL); + for (i = 0; i < proc_names_num; i++) + { + /* The name passed to kstat_data_lookup() doesn't have the + * "const" modifier, so we need to copy the name here. */ + char name[32]; + sstrncpy (name, proc_names[i], sizeof (name)); - free (values); - } + values[i].counter = (derive_t) get_kstat_value (ksp, name); } -} -#endif /* defined(KERNEL_LINUX) */ -#undef BUFSIZE -#if HAVE_LIBKSTAT && 0 -static void nfs2_read_kstat (kstat_t *ksp, char *inst) -{ - unsigned long long values[18]; - - values[0] = get_kstat_value (ksp, "null"); - values[1] = get_kstat_value (ksp, "getattr"); - values[2] = get_kstat_value (ksp, "setattr"); - values[3] = get_kstat_value (ksp, "root"); - values[4] = get_kstat_value (ksp, "lookup"); - values[5] = get_kstat_value (ksp, "readlink"); - values[6] = get_kstat_value (ksp, "read"); - values[7] = get_kstat_value (ksp, "wrcache"); - values[8] = get_kstat_value (ksp, "write"); - values[9] = get_kstat_value (ksp, "create"); - values[10] = get_kstat_value (ksp, "remove"); - values[11] = get_kstat_value (ksp, "rename"); - values[12] = get_kstat_value (ksp, "link"); - values[13] = get_kstat_value (ksp, "symlink"); - values[14] = get_kstat_value (ksp, "mkdir"); - values[15] = get_kstat_value (ksp, "rmdir"); - values[16] = get_kstat_value (ksp, "readdir"); - values[17] = get_kstat_value (ksp, "statfs"); - - nfs2_procedures_submit (values, inst); + nfs_procedures_submit (plugin_instance, proc_names, values, + proc_names_num); + return (0); } #endif -#if NFS_HAVE_READ -static void nfs_read (void) -{ #if KERNEL_LINUX +static int nfs_read (void) +{ FILE *fh; if ((fh = fopen ("/proc/net/rpc/nfs", "r")) != NULL) { - nfs_read_stats_file (fh, "client"); + nfs_read_linux (fh, "client"); fclose (fh); } if ((fh = fopen ("/proc/net/rpc/nfsd", "r")) != NULL) { - nfs_read_stats_file (fh, "server"); + nfs_read_linux (fh, "server"); fclose (fh); } -/* #endif defined(KERNEL_LINUX) */ - -#elif HAVE_LIBKSTAT && 0 - if (nfs2_ksp_client != NULL) - nfs2_read_kstat (nfs2_ksp_client, "client"); - if (nfs2_ksp_server != NULL) - nfs2_read_kstat (nfs2_ksp_server, "server"); -#endif /* defined(HAVE_LIBKSTAT) */ + return (0); } -#else -# define nfs_read NULL -#endif /* NFS_HAVE_READ */ +/* #endif KERNEL_LINUX */ -void module_register (void) +#elif HAVE_LIBKSTAT +static int nfs_read (void) { - plugin_register (MODULE_NAME, nfs_init, nfs_read, NULL); - plugin_register ("nfs2_procedures", NULL, NULL, nfs2_procedures_write); - plugin_register ("nfs3_procedures", NULL, NULL, nfs3_procedures_write); + nfs_read_kstat (nfs2_ksp_client, /* version = */ 2, "client", + nfs2_procedures_names, nfs2_procedures_names_num); + nfs_read_kstat (nfs2_ksp_server, /* version = */ 2, "server", + nfs2_procedures_names, nfs2_procedures_names_num); + nfs_read_kstat (nfs3_ksp_client, /* version = */ 3, "client", + nfs3_procedures_names, nfs3_procedures_names_num); + nfs_read_kstat (nfs3_ksp_server, /* version = */ 3, "server", + nfs3_procedures_names, nfs3_procedures_names_num); + nfs_read_kstat (nfs4_ksp_client, /* version = */ 4, "client", + nfs4_procedures_names, nfs4_procedures_names_num); + nfs_read_kstat (nfs4_ksp_server, /* version = */ 4, "server", + nfs4_procedures_names, nfs4_procedures_names_num); + + return (0); } +#endif /* HAVE_LIBKSTAT */ -#undef MODULE_NAME +void module_register (void) +{ + plugin_register_init ("nfs", nfs_init); + plugin_register_read ("nfs", nfs_read); +} /* void module_register */