3 * Copyright (C) 2005,2006 Jason Pepas
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; only version 2 of the License is applicable.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 * Jason Pepas <cell at ices.utexas.edu>
20 * Florian octo Forster <octo at verplant.org>
26 #include "utils_debug.h"
28 #define MODULE_NAME "nfs"
30 /* #if defined(KERNEL_LINUX) || defined(HAVE_LIBKSTAT) */
32 # define NFS_HAVE_READ 1
34 # define NFS_HAVE_READ 0
39 see http://www.missioncriticallinux.com/orph/NFS-Statistics
42 rpc_stat.netcnt Not used; always zero.
43 rpc_stat.netudpcnt Not used; always zero.
44 rpc_stat.nettcpcnt Not used; always zero.
45 rpc_stat.nettcpconn Not used; always zero.
48 rpc_stat.rpccnt The number of RPC calls.
49 rpc_stat.rpcretrans The number of retransmitted RPC calls.
50 rpc_stat.rpcauthrefresh The number of credential refreshes.
55 Procedure NFS Version NFS Version 3
56 Number Procedures Procedures
82 static data_source_t procedure_dsrc[1] =
84 {"value", DS_TYPE_COUNTER, 0, 4294967295.0}
87 static data_set_t procedure_ds =
89 "nfs_procedure", 1, procedure_dsrc
92 static const char *nfs2_procedures_names[] =
114 static int nfs2_procedures_names_num = 18;
116 static const char *nfs3_procedures_names[] =
142 static int nfs3_procedures_names_num = 22;
144 #if HAVE_LIBKSTAT && 0
145 extern kstat_ctl_t *kc;
146 static kstat_t *nfs2_ksp_client;
147 static kstat_t *nfs2_ksp_server;
148 static kstat_t *nfs3_ksp_client;
149 static kstat_t *nfs3_ksp_server;
150 static kstat_t *nfs4_ksp_client;
151 static kstat_t *nfs4_ksp_server;
154 /* Possibly TODO: NFSv4 statistics */
157 static int nfs_init (void)
159 #if HAVE_LIBKSTAT && 0
162 nfs2_ksp_client = NULL;
163 nfs2_ksp_server = NULL;
164 nfs3_ksp_client = NULL;
165 nfs3_ksp_server = NULL;
166 nfs4_ksp_client = NULL;
167 nfs4_ksp_server = NULL;
172 for (ksp_chain = kc->kc_chain; ksp_chain != NULL;
173 ksp_chain = ksp_chain->ks_next)
175 if (strncmp (ksp_chain->ks_module, "nfs", 3) != 0)
177 else if (strncmp (ksp_chain->ks_name, "rfsproccnt_v2", 13) == 0)
178 nfs2_ksp_server = ksp_chain;
179 else if (strncmp (ksp_chain->ks_name, "rfsproccnt_v3", 13) == 0)
180 nfs3_ksp_server = ksp_chain;
181 else if (strncmp (ksp_chain->ks_name, "rfsproccnt_v4", 13) == 0)
182 nfs4_ksp_server = ksp_chain;
183 else if (strncmp (ksp_chain->ks_name, "rfsreqcnt_v2", 12) == 0)
184 nfs2_ksp_client = ksp_chain;
185 else if (strncmp (ksp_chain->ks_name, "rfsreqcnt_v3", 12) == 0)
186 nfs3_ksp_client = ksp_chain;
187 else if (strncmp (ksp_chain->ks_name, "rfsreqcnt_v4", 12) == 0)
188 nfs4_ksp_client = ksp_chain;
198 static void nfs_procedures_submit (const char *plugin_instance,
199 unsigned long long *val, const char **names, int len)
207 vl.time = time (NULL);
208 /* FIXME: do this globally */
209 if (gethostname (vl.host, sizeof (vl.host)) != 0)
211 syslog (LOG_ERR, "load plugin: gethostname failed: %s",
215 strcpy (vl.plugin, "nfs");
216 strncpy (vl.plugin_instance, plugin_instance,
217 sizeof (vl.plugin_instance));
219 for (i = 0; i < len; i++)
221 values[0].counter = val[i];
222 strncpy (vl.type_instance, names[i],
223 sizeof (vl.type_instance));
224 DBG ("%s-%s/nfs_procedure-%s = %llu",
225 vl.plugin, vl.plugin_instance,
226 vl.type_instance, val[i]);
227 plugin_dispatch_values ("nfs_procedure", &vl);
229 } /* void nfs_procedures_submit */
230 #endif /* NFS_HAVE_READ */
233 static void nfs_read_stats_file (FILE *fh, char *inst)
235 char buffer[BUFSIZE];
237 char plugin_instance[DATA_MAX_NAME_LEN];
245 while (fgets (buffer, BUFSIZE, fh) != NULL)
247 numfields = strsplit (buffer, fields, 48);
249 if (((numfields - 2) != nfs2_procedures_names_num)
251 != nfs3_procedures_names_num))
254 if (strcmp (fields[0], "proc2") == 0)
257 unsigned long long *values;
259 if ((numfields - 2) != nfs2_procedures_names_num)
261 syslog (LOG_WARNING, "nfs plugin: Wrong "
262 "number of fields (= %i) "
263 "for NFSv2 statistics.",
268 snprintf (plugin_instance, sizeof (plugin_instance),
270 plugin_instance[DATA_MAX_NAME_LEN - 1] = '\0';
272 values = (unsigned long long *) malloc (nfs2_procedures_names_num * sizeof (unsigned long long));
275 syslog (LOG_ERR, "nfs plugin: malloc "
281 for (i = 0; i < nfs2_procedures_names_num; i++)
282 values[i] = atoll (fields[i + 2]);
284 nfs_procedures_submit (plugin_instance, values,
285 nfs2_procedures_names,
286 nfs2_procedures_names_num);
290 else if (strncmp (fields[0], "proc3", 5) == 0)
293 unsigned long long *values;
295 if ((numfields - 2) != nfs3_procedures_names_num)
297 syslog (LOG_WARNING, "nfs plugin: Wrong "
298 "number of fields (= %i) "
299 "for NFSv3 statistics.",
304 snprintf (plugin_instance, sizeof (plugin_instance),
306 plugin_instance[DATA_MAX_NAME_LEN - 1] = '\0';
308 values = (unsigned long long *) malloc (nfs3_procedures_names_num * sizeof (unsigned long long));
311 syslog (LOG_ERR, "nfs plugin: malloc "
317 for (i = 0; i < nfs3_procedures_names_num; i++)
318 values[i] = atoll (fields[i + 2]);
320 nfs_procedures_submit (plugin_instance, values,
321 nfs3_procedures_names,
322 nfs3_procedures_names_num);
326 } /* while (fgets (buffer, BUFSIZE, fh) != NULL) */
327 } /* void nfs_read_stats_file */
328 #endif /* defined(KERNEL_LINUX) */
331 #if HAVE_LIBKSTAT && 0
332 static void nfs2_read_kstat (kstat_t *ksp, char *inst)
334 unsigned long long values[18];
336 values[0] = get_kstat_value (ksp, "null");
337 values[1] = get_kstat_value (ksp, "getattr");
338 values[2] = get_kstat_value (ksp, "setattr");
339 values[3] = get_kstat_value (ksp, "root");
340 values[4] = get_kstat_value (ksp, "lookup");
341 values[5] = get_kstat_value (ksp, "readlink");
342 values[6] = get_kstat_value (ksp, "read");
343 values[7] = get_kstat_value (ksp, "wrcache");
344 values[8] = get_kstat_value (ksp, "write");
345 values[9] = get_kstat_value (ksp, "create");
346 values[10] = get_kstat_value (ksp, "remove");
347 values[11] = get_kstat_value (ksp, "rename");
348 values[12] = get_kstat_value (ksp, "link");
349 values[13] = get_kstat_value (ksp, "symlink");
350 values[14] = get_kstat_value (ksp, "mkdir");
351 values[15] = get_kstat_value (ksp, "rmdir");
352 values[16] = get_kstat_value (ksp, "readdir");
353 values[17] = get_kstat_value (ksp, "statfs");
355 nfs2_procedures_submit (values, inst);
360 static int nfs_read (void)
365 if ((fh = fopen ("/proc/net/rpc/nfs", "r")) != NULL)
367 nfs_read_stats_file (fh, "client");
371 if ((fh = fopen ("/proc/net/rpc/nfsd", "r")) != NULL)
373 nfs_read_stats_file (fh, "server");
377 /* #endif defined(KERNEL_LINUX) */
379 #elif HAVE_LIBKSTAT && 0
380 if (nfs2_ksp_client != NULL)
381 nfs2_read_kstat (nfs2_ksp_client, "client");
382 if (nfs2_ksp_server != NULL)
383 nfs2_read_kstat (nfs2_ksp_server, "server");
384 #endif /* defined(HAVE_LIBKSTAT) */
388 #endif /* NFS_HAVE_READ */
390 void module_register (void)
392 plugin_register_data_set (&procedure_ds);
395 plugin_register_read ("nfs", nfs_read);