3 * Copyright (C) 2005 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; either version 2 of the License, or (at your
8 * option) any later version.
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 verplant.org>
27 #define MODULE_NAME "nfs"
32 static char *nfs2_procedures_file = "nfs2_procedures-%s.rrd";
33 static char *nfs3_procedures_file = "nfs3_procedures-%s.rrd";
37 see http://www.missioncriticallinux.com/orph/NFS-Statistics
40 rpc_stat.netcnt Not used; always zero.
41 rpc_stat.netudpcnt Not used; always zero.
42 rpc_stat.nettcpcnt Not used; always zero.
43 rpc_stat.nettcpconn Not used; always zero.
46 rpc_stat.rpccnt The number of RPC calls.
47 rpc_stat.rpcretrans The number of retransmitted RPC calls.
48 rpc_stat.rpcauthrefresh The number of credential refreshes.
53 Procedure NFS Version NFS Version 3
54 Number Procedures Procedures
80 static char *nfs2_procedures_ds_def[] =
82 "DS:null:COUNTER:25:0:U",
83 "DS:getattr:COUNTER:25:0:U",
84 "DS:setattr:COUNTER:25:0:U",
85 "DS:root:COUNTER:25:0:U",
86 "DS:lookup:COUNTER:25:0:U",
87 "DS:readlink:COUNTER:25:0:U",
88 "DS:read:COUNTER:25:0:U",
89 "DS:wrcache:COUNTER:25:0:U",
90 "DS:write:COUNTER:25:0:U",
91 "DS:create:COUNTER:25:0:U",
92 "DS:remove:COUNTER:25:0:U",
93 "DS:rename:COUNTER:25:0:U",
94 "DS:link:COUNTER:25:0:U",
95 "DS:symlink:COUNTER:25:0:U",
96 "DS:mkdir:COUNTER:25:0:U",
97 "DS:rmdir:COUNTER:25:0:U",
98 "DS:readdir:COUNTER:25:0:U",
99 "DS:fsstat:COUNTER:25:0:U",
102 static int nfs2_procedures_ds_num = 18;
104 static char *nfs3_procedures_ds_def[] =
106 "DS:null:COUNTER:25:0:U",
107 "DS:getattr:COUNTER:25:0:U",
108 "DS:setattr:COUNTER:25:0:U",
109 "DS:lookup:COUNTER:25:0:U",
110 "DS:access:COUNTER:25:0:U",
111 "DS:readlink:COUNTER:25:0:U",
112 "DS:read:COUNTER:25:0:U",
113 "DS:write:COUNTER:25:0:U",
114 "DS:create:COUNTER:25:0:U",
115 "DS:mkdir:COUNTER:25:0:U",
116 "DS:symlink:COUNTER:25:0:U",
117 "DS:mknod:COUNTER:25:0:U",
118 "DS:remove:COUNTER:25:0:U",
119 "DS:rmdir:COUNTER:25:0:U",
120 "DS:rename:COUNTER:25:0:U",
121 "DS:link:COUNTER:25:0:U",
122 "DS:readdir:COUNTER:25:0:U",
123 "DS:readdirplus:COUNTER:25:0:U",
124 "DS:fsstat:COUNTER:25:0:U",
125 "DS:fsinfo:COUNTER:25:0:U",
126 "DS:pathconf:COUNTER:25:0:U",
127 "DS:commit:COUNTER:25:0:U",
130 static int nfs3_procedures_ds_num = 22;
133 extern kstat_ctl_t *kc;
134 static kstat_t *nfs2_ksp_client;
135 static kstat_t *nfs2_ksp_server;
136 static kstat_t *nfs3_ksp_client;
137 static kstat_t *nfs3_ksp_server;
138 static kstat_t *nfs4_ksp_client;
139 static kstat_t *nfs4_ksp_server;
142 /* Possibly TODO: NFSv4 statistics */
144 extern time_t curtime;
151 nfs2_ksp_client = NULL;
152 nfs2_ksp_server = NULL;
153 nfs3_ksp_client = NULL;
154 nfs3_ksp_server = NULL;
155 nfs4_ksp_client = NULL;
156 nfs4_ksp_server = NULL;
161 for (ksp_chain = kc->kc_chain; ksp_chain != NULL;
162 ksp_chain = ksp_chain->ks_next)
164 if (strncmp (ksp_chain->ks_module, "nfs", 3) != 0)
166 else if (strncmp (ksp_chain->ks_name, "rfsproccnt_v2", 13) == 0)
167 nfs2_ksp_server = ksp_chain;
168 else if (strncmp (ksp_chain->ks_name, "rfsproccnt_v3", 13) == 0)
169 nfs3_ksp_server = ksp_chain;
170 else if (strncmp (ksp_chain->ks_name, "rfsproccnt_v4", 13) == 0)
171 nfs4_ksp_server = ksp_chain;
172 else if (strncmp (ksp_chain->ks_name, "rfsreqcnt_v2", 12) == 0)
173 nfs2_ksp_client = ksp_chain;
174 else if (strncmp (ksp_chain->ks_name, "rfsreqcnt_v3", 12) == 0)
175 nfs3_ksp_client = ksp_chain;
176 else if (strncmp (ksp_chain->ks_name, "rfsreqcnt_v4", 12) == 0)
177 nfs4_ksp_client = ksp_chain;
185 void nfs2_procedures_write (char *host, char *inst, char *val)
187 char filename[BUFSIZE];
189 if (snprintf (filename, BUFSIZE, nfs2_procedures_file, inst) > BUFSIZE)
192 rrd_update_file (host, filename, val, nfs2_procedures_ds_def,
193 nfs2_procedures_ds_num);
196 void nfs3_procedures_write (char *host, char *inst, char *val)
198 char filename[BUFSIZE];
200 if (snprintf (filename, BUFSIZE, nfs3_procedures_file, inst) > BUFSIZE)
203 rrd_update_file (host, filename, val, nfs3_procedures_ds_def,
204 nfs3_procedures_ds_num);
207 void nfs2_procedures_submit (unsigned long long *val, char *inst)
212 retval = snprintf (buf, BUFSIZE, "%u:%llu:%llu:%llu:%llu:%llu:%llu:"
213 "%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:"
214 "%llu:%llu:%llu", /* 18x %llu */
215 (unsigned int) curtime,
216 val[0], val[1], val[2], val[3], val[4], val[5], val[6],
217 val[7], val[8], val[9], val[10], val[11], val[12],
218 val[13], val[14], val[15], val[16], val[17]);
221 if (retval >= BUFSIZE)
225 syslog (LOG_ERR, "nfs: snprintf's format failed: %s", strerror (errno));
229 plugin_submit ("nfs2_procedures", inst, buf);
232 void nfs3_procedures_submit (unsigned long long *val, char *inst)
237 retval = snprintf(buf, BUFSIZE, "%u:%llu:%llu:%llu:%llu:%llu:%llu:"
238 "%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:"
239 "%llu:%llu:%llu:%llu:%llu:%llu:%llu", /* 22x %llu */
240 (unsigned int) curtime,
241 val[0], val[1], val[2], val[3], val[4], val[5], val[6],
242 val[7], val[8], val[9], val[10], val[11], val[12],
243 val[13], val[14], val[15], val[16], val[17], val[18],
244 val[19], val[20], val[21]);
246 if (retval >= BUFSIZE)
250 syslog (LOG_ERR, "nfs: snprintf's format failed: %s", strerror (errno));
254 plugin_submit("nfs3_procedures", inst, buf);
257 #if defined(KERNEL_LINUX)
258 void nfs_read_stats_file (FILE *fh, char *inst)
260 char buffer[BUFSIZE];
268 while (fgets (buffer, BUFSIZE, fh) != NULL)
270 numfields = strsplit (buffer, fields, 48);
275 if (strncmp (fields[0], "proc2", 5) == 0)
278 unsigned long long *values;
280 if (numfields - 2 != nfs2_procedures_ds_num)
282 syslog (LOG_WARNING, "nfs: Wrong number of fields (= %i) for NFS2 statistics.", numfields - 2);
286 if ((values = (unsigned long long *) malloc (nfs2_procedures_ds_num * sizeof (unsigned long long))) == NULL)
288 syslog (LOG_ERR, "nfs: malloc: %s", strerror (errno));
292 for (i = 0; i < nfs2_procedures_ds_num; i++)
293 values[i] = atoll (fields[i + 2]);
295 nfs2_procedures_submit (values, inst);
299 else if (strncmp (fields[0], "proc3", 5) == 0)
302 unsigned long long *values;
304 if (numfields - 2 != nfs3_procedures_ds_num)
306 syslog (LOG_WARNING, "nfs: Wrong number of fields (= %i) for NFS3 statistics.", numfields - 2);
310 if ((values = (unsigned long long *) malloc (nfs3_procedures_ds_num * sizeof (unsigned long long))) == NULL)
312 syslog (LOG_ERR, "nfs: malloc: %s", strerror (errno));
316 for (i = 0; i < nfs3_procedures_ds_num; i++)
317 values[i] = atoll (fields[i + 2]);
319 nfs3_procedures_submit (values, inst);
325 #endif /* defined(KERNEL_LINUX) */
329 void nfs2_read_kstat (kstat_t *ksp, char *inst)
331 unsigned long long values[18];
333 values[0] = get_kstat_value (ksp, "null");
334 values[1] = get_kstat_value (ksp, "getattr");
335 values[2] = get_kstat_value (ksp, "setattr");
336 values[3] = get_kstat_value (ksp, "root");
337 values[4] = get_kstat_value (ksp, "lookup");
338 values[5] = get_kstat_value (ksp, "readlink");
339 values[6] = get_kstat_value (ksp, "read");
340 values[7] = get_kstat_value (ksp, "wrcache");
341 values[8] = get_kstat_value (ksp, "write");
342 values[9] = get_kstat_value (ksp, "create");
343 values[10] = get_kstat_value (ksp, "remove");
344 values[11] = get_kstat_value (ksp, "rename");
345 values[12] = get_kstat_value (ksp, "link");
346 values[13] = get_kstat_value (ksp, "symlink");
347 values[14] = get_kstat_value (ksp, "mkdir");
348 values[15] = get_kstat_value (ksp, "rmdir");
349 values[16] = get_kstat_value (ksp, "readdir");
350 values[17] = get_kstat_value (ksp, "statfs");
352 nfs2_procedures_submit (values, inst);
358 #if defined(KERNEL_LINUX)
361 if ((fh = fopen ("/proc/net/rpc/nfs", "r")) != NULL)
363 nfs_read_stats_file (fh, "client");
367 if ((fh = fopen ("/proc/net/rpc/nfsd", "r")) != NULL)
369 nfs_read_stats_file (fh, "server");
373 /* #endif defined(KERNEL_LINUX) */
375 #elif defined(HAVE_LIBKSTAT)
376 if (nfs2_ksp_client != NULL)
377 nfs2_read_kstat (nfs2_ksp_client, "client");
378 if (nfs2_ksp_server != NULL)
379 nfs2_read_kstat (nfs2_ksp_server, "server");
380 #endif /* defined(HAVE_LIBKSTAT) */
383 void module_register (void)
385 plugin_register (MODULE_NAME, nfs_init, nfs_read, NULL);
386 plugin_register ("nfs2_procedures", NULL, NULL, nfs2_procedures_write);
387 plugin_register ("nfs3_procedures", NULL, NULL, nfs3_procedures_write);
391 #endif /* COLLECT_LOAD */