3 * Copyright (C) 2005,2006 Jason Pepas
4 * Copyright (C) 2012,2013 Florian Forster
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; only version 2 of the License is applicable.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * Jason Pepas <cell at ices.utexas.edu>
21 * Florian octo Forster <octo at collectd.org>
22 * Cosmin Ioiart <cioiart at gmail.com>
35 see http://www.missioncriticallinux.com/orph/NFS-Statistics
38 rpc_stat.netcnt Not used; always zero.
39 rpc_stat.netudpcnt Not used; always zero.
40 rpc_stat.nettcpcnt Not used; always zero.
41 rpc_stat.nettcpconn Not used; always zero.
44 rpc_stat.rpccnt The number of RPC calls.
45 rpc_stat.rpcretrans The number of retransmitted RPC calls.
46 rpc_stat.rpcauthrefresh The number of credential refreshes.
51 Procedure NFS Version NFS Version 3
52 Number Procedures Procedures
78 static const char *nfs2_procedures_names[] =
99 static size_t nfs2_procedures_names_num = STATIC_ARRAY_SIZE (nfs2_procedures_names);
101 static const char *nfs3_procedures_names[] =
126 static size_t nfs3_procedures_names_num = STATIC_ARRAY_SIZE (nfs3_procedures_names);
129 static const char *nfs4_procedures_names[] =
167 "setclientid_confirm",
171 static size_t nfs4_procedures_names_num = STATIC_ARRAY_SIZE (nfs4_procedures_names);
175 extern kstat_ctl_t *kc;
176 static kstat_t *nfs2_ksp_client;
177 static kstat_t *nfs2_ksp_server;
178 static kstat_t *nfs3_ksp_client;
179 static kstat_t *nfs3_ksp_server;
180 static kstat_t *nfs4_ksp_client;
181 static kstat_t *nfs4_ksp_server;
184 /* Possibly TODO: NFSv4 statistics */
187 static int nfs_init (void)
191 /* #endif KERNEL_LINUX */
194 static int nfs_init (void)
196 kstat_t *ksp_chain = NULL;
198 nfs2_ksp_client = NULL;
199 nfs2_ksp_server = NULL;
200 nfs3_ksp_client = NULL;
201 nfs3_ksp_server = NULL;
202 nfs4_ksp_client = NULL;
203 nfs4_ksp_server = NULL;
208 for (ksp_chain = kc->kc_chain; ksp_chain != NULL;
209 ksp_chain = ksp_chain->ks_next)
211 if (strncmp (ksp_chain->ks_module, "nfs", 3) != 0)
213 else if (strncmp (ksp_chain->ks_name, "rfsproccnt_v2", 13) == 0)
214 nfs2_ksp_server = ksp_chain;
215 else if (strncmp (ksp_chain->ks_name, "rfsproccnt_v3", 13) == 0)
216 nfs3_ksp_server = ksp_chain;
217 else if (strncmp (ksp_chain->ks_name, "rfsproccnt_v4", 13) == 0)
218 nfs4_ksp_server = ksp_chain;
219 else if (strncmp (ksp_chain->ks_name, "rfsreqcnt_v2", 12) == 0)
220 nfs2_ksp_client = ksp_chain;
221 else if (strncmp (ksp_chain->ks_name, "rfsreqcnt_v3", 12) == 0)
222 nfs3_ksp_client = ksp_chain;
223 else if (strncmp (ksp_chain->ks_name, "rfsreqcnt_v4", 12) == 0)
224 nfs4_ksp_client = ksp_chain;
231 static void nfs_procedures_submit (const char *plugin_instance,
232 const char **type_instances,
233 value_t *values, size_t values_num)
235 value_list_t vl = VALUE_LIST_INIT;
239 sstrncpy (vl.host, hostname_g, sizeof (vl.host));
240 sstrncpy (vl.plugin, "nfs", sizeof (vl.plugin));
241 sstrncpy (vl.plugin_instance, plugin_instance,
242 sizeof (vl.plugin_instance));
243 sstrncpy (vl.type, "nfs_procedure", sizeof (vl.type));
245 for (i = 0; i < values_num; i++)
247 vl.values = values + i;
248 sstrncpy (vl.type_instance, type_instances[i],
249 sizeof (vl.type_instance));
250 plugin_dispatch_values (&vl);
252 } /* void nfs_procedures_submit */
255 static int nfs_submit_fields (int nfs_version, const char *instance,
256 char **fields, size_t fields_num,
257 const char **proc_names, size_t proc_names_num)
259 char plugin_instance[DATA_MAX_NAME_LEN];
260 value_t values[fields_num];
263 if (fields_num != proc_names_num)
265 WARNING ("nfs plugin: Wrong number of fields for "
266 "NFSv%i %s statistics. Expected %zu, got %zu.",
267 nfs_version, instance,
268 proc_names_num, fields_num);
272 ssnprintf (plugin_instance, sizeof (plugin_instance), "v%i%s",
273 nfs_version, instance);
275 for (i = 0; i < proc_names_num; i++)
276 (void) parse_value (fields[i], &values[i], DS_TYPE_DERIVE);
278 nfs_procedures_submit (plugin_instance, proc_names, values,
284 static void nfs_read_linux (FILE *fh, char *inst)
294 while (fgets (buffer, sizeof (buffer), fh) != NULL)
296 fields_num = strsplit (buffer,
297 fields, STATIC_ARRAY_SIZE (fields));
302 if (strcmp (fields[0], "proc2") == 0)
304 nfs_submit_fields (/* version = */ 2, inst,
305 fields + 2, (size_t) (fields_num - 2),
306 nfs2_procedures_names,
307 nfs2_procedures_names_num);
309 else if (strncmp (fields[0], "proc3", 5) == 0)
311 nfs_submit_fields (/* version = */ 3, inst,
312 fields + 2, (size_t) (fields_num - 2),
313 nfs3_procedures_names,
314 nfs3_procedures_names_num);
316 } /* while (fgets) */
317 } /* void nfs_read_linux */
318 #endif /* KERNEL_LINUX */
321 static int nfs_read_kstat (kstat_t *ksp, int nfs_version, char *inst,
322 char const **proc_names, size_t proc_names_num)
324 char plugin_instance[DATA_MAX_NAME_LEN];
325 value_t values[proc_names_num];
331 ssnprintf (plugin_instance, sizeof (plugin_instance), "v%i%s",
334 kstat_read(kc, ksp, NULL);
335 for (i = 0; i < proc_names_num; i++)
337 /* The name passed to kstat_data_lookup() doesn't have the
338 * "const" modifier, so we need to copy the name here. */
340 sstrncpy (name, proc_names[i], sizeof (name));
342 values[i].counter = (derive_t) get_kstat_value (ksp, name);
345 nfs_procedures_submit (plugin_instance, proc_names, values,
352 static int nfs_read (void)
356 if ((fh = fopen ("/proc/net/rpc/nfs", "r")) != NULL)
358 nfs_read_linux (fh, "client");
362 if ((fh = fopen ("/proc/net/rpc/nfsd", "r")) != NULL)
364 nfs_read_linux (fh, "server");
370 /* #endif KERNEL_LINUX */
373 static int nfs_read (void)
375 nfs_read_kstat (nfs2_ksp_client, /* version = */ 2, "client",
376 nfs2_procedures_names, nfs2_procedures_names_num);
377 nfs_read_kstat (nfs2_ksp_server, /* version = */ 2, "server",
378 nfs2_procedures_names, nfs2_procedures_names_num);
379 nfs_read_kstat (nfs3_ksp_client, /* version = */ 3, "client",
380 nfs3_procedures_names, nfs3_procedures_names_num);
381 nfs_read_kstat (nfs3_ksp_server, /* version = */ 3, "server",
382 nfs3_procedures_names, nfs3_procedures_names_num);
383 nfs_read_kstat (nfs4_ksp_client, /* version = */ 4, "client",
384 nfs4_procedures_names, nfs4_procedures_names_num);
385 nfs_read_kstat (nfs4_ksp_server, /* version = */ 4, "server",
386 nfs4_procedures_names, nfs4_procedures_names_num);
390 #endif /* HAVE_LIBKSTAT */
392 void module_register (void)
394 plugin_register_init ("nfs", nfs_init);
395 plugin_register_read ("nfs", nfs_read);
396 } /* void module_register */