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>
28 #define MODULE_NAME "nfs"
30 #if defined(KERNEL_LINUX) || defined(HAVE_LIBKSTAT)
31 # define NFS_HAVE_READ 1
33 # define NFS_HAVE_READ 0
36 static char *nfs2_procedures_file = "nfs2_procedures-%s.rrd";
37 static char *nfs3_procedures_file = "nfs3_procedures-%s.rrd";
41 see http://www.missioncriticallinux.com/orph/NFS-Statistics
44 rpc_stat.netcnt Not used; always zero.
45 rpc_stat.netudpcnt Not used; always zero.
46 rpc_stat.nettcpcnt Not used; always zero.
47 rpc_stat.nettcpconn Not used; always zero.
50 rpc_stat.rpccnt The number of RPC calls.
51 rpc_stat.rpcretrans The number of retransmitted RPC calls.
52 rpc_stat.rpcauthrefresh The number of credential refreshes.
57 Procedure NFS Version NFS Version 3
58 Number Procedures Procedures
84 static char *nfs2_procedures_ds_def[] =
86 "DS:null:COUNTER:25:0:U",
87 "DS:getattr:COUNTER:25:0:U",
88 "DS:setattr:COUNTER:25:0:U",
89 "DS:root:COUNTER:25:0:U",
90 "DS:lookup:COUNTER:25:0:U",
91 "DS:readlink:COUNTER:25:0:U",
92 "DS:read:COUNTER:25:0:U",
93 "DS:wrcache:COUNTER:25:0:U",
94 "DS:write:COUNTER:25:0:U",
95 "DS:create:COUNTER:25:0:U",
96 "DS:remove:COUNTER:25:0:U",
97 "DS:rename:COUNTER:25:0:U",
98 "DS:link:COUNTER:25:0:U",
99 "DS:symlink:COUNTER:25:0:U",
100 "DS:mkdir:COUNTER:25:0:U",
101 "DS:rmdir:COUNTER:25:0:U",
102 "DS:readdir:COUNTER:25:0:U",
103 "DS:fsstat:COUNTER:25:0:U",
106 static int nfs2_procedures_ds_num = 18;
108 static char *nfs3_procedures_ds_def[] =
110 "DS:null:COUNTER:25:0:U",
111 "DS:getattr:COUNTER:25:0:U",
112 "DS:setattr:COUNTER:25:0:U",
113 "DS:lookup:COUNTER:25:0:U",
114 "DS:access:COUNTER:25:0:U",
115 "DS:readlink:COUNTER:25:0:U",
116 "DS:read:COUNTER:25:0:U",
117 "DS:write:COUNTER:25:0:U",
118 "DS:create:COUNTER:25:0:U",
119 "DS:mkdir:COUNTER:25:0:U",
120 "DS:symlink:COUNTER:25:0:U",
121 "DS:mknod:COUNTER:25:0:U",
122 "DS:remove:COUNTER:25:0:U",
123 "DS:rmdir:COUNTER:25:0:U",
124 "DS:rename:COUNTER:25:0:U",
125 "DS:link:COUNTER:25:0:U",
126 "DS:readdir:COUNTER:25:0:U",
127 "DS:readdirplus:COUNTER:25:0:U",
128 "DS:fsstat:COUNTER:25:0:U",
129 "DS:fsinfo:COUNTER:25:0:U",
130 "DS:pathconf:COUNTER:25:0:U",
131 "DS:commit:COUNTER:25:0:U",
134 static int nfs3_procedures_ds_num = 22;
137 extern kstat_ctl_t *kc;
138 static kstat_t *nfs2_ksp_client;
139 static kstat_t *nfs2_ksp_server;
140 static kstat_t *nfs3_ksp_client;
141 static kstat_t *nfs3_ksp_server;
142 static kstat_t *nfs4_ksp_client;
143 static kstat_t *nfs4_ksp_server;
146 /* Possibly TODO: NFSv4 statistics */
148 static void nfs_init (void)
153 nfs2_ksp_client = NULL;
154 nfs2_ksp_server = NULL;
155 nfs3_ksp_client = NULL;
156 nfs3_ksp_server = NULL;
157 nfs4_ksp_client = NULL;
158 nfs4_ksp_server = NULL;
163 for (ksp_chain = kc->kc_chain; ksp_chain != NULL;
164 ksp_chain = ksp_chain->ks_next)
166 if (strncmp (ksp_chain->ks_module, "nfs", 3) != 0)
168 else if (strncmp (ksp_chain->ks_name, "rfsproccnt_v2", 13) == 0)
169 nfs2_ksp_server = ksp_chain;
170 else if (strncmp (ksp_chain->ks_name, "rfsproccnt_v3", 13) == 0)
171 nfs3_ksp_server = ksp_chain;
172 else if (strncmp (ksp_chain->ks_name, "rfsproccnt_v4", 13) == 0)
173 nfs4_ksp_server = ksp_chain;
174 else if (strncmp (ksp_chain->ks_name, "rfsreqcnt_v2", 12) == 0)
175 nfs2_ksp_client = ksp_chain;
176 else if (strncmp (ksp_chain->ks_name, "rfsreqcnt_v3", 12) == 0)
177 nfs3_ksp_client = ksp_chain;
178 else if (strncmp (ksp_chain->ks_name, "rfsreqcnt_v4", 12) == 0)
179 nfs4_ksp_client = ksp_chain;
187 static void nfs2_procedures_write (char *host, char *inst, char *val)
189 char filename[BUFSIZE];
191 if (snprintf (filename, BUFSIZE, nfs2_procedures_file, inst) > BUFSIZE)
194 rrd_update_file (host, filename, val, nfs2_procedures_ds_def,
195 nfs2_procedures_ds_num);
198 static void nfs3_procedures_write (char *host, char *inst, char *val)
200 char filename[BUFSIZE];
202 if (snprintf (filename, BUFSIZE, nfs3_procedures_file, inst) > BUFSIZE)
205 rrd_update_file (host, filename, val, nfs3_procedures_ds_def,
206 nfs3_procedures_ds_num);
210 static void nfs2_procedures_submit (unsigned long long *val, char *inst)
215 retval = snprintf (buf, BUFSIZE, "%u:%llu:%llu:%llu:%llu:%llu:%llu:"
216 "%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:"
217 "%llu:%llu:%llu", /* 18x %llu */
218 (unsigned int) curtime,
219 val[0], val[1], val[2], val[3], val[4], val[5], val[6],
220 val[7], val[8], val[9], val[10], val[11], val[12],
221 val[13], val[14], val[15], val[16], val[17]);
224 if (retval >= BUFSIZE)
228 syslog (LOG_ERR, "nfs: snprintf's format failed: %s", strerror (errno));
232 plugin_submit ("nfs2_procedures", inst, buf);
235 static void nfs3_procedures_submit (unsigned long long *val, char *inst)
240 retval = snprintf(buf, BUFSIZE, "%u:%llu:%llu:%llu:%llu:%llu:%llu:"
241 "%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:"
242 "%llu:%llu:%llu:%llu:%llu:%llu:%llu", /* 22x %llu */
243 (unsigned int) curtime,
244 val[0], val[1], val[2], val[3], val[4], val[5], val[6],
245 val[7], val[8], val[9], val[10], val[11], val[12],
246 val[13], val[14], val[15], val[16], val[17], val[18],
247 val[19], val[20], val[21]);
249 if (retval >= BUFSIZE)
253 syslog (LOG_ERR, "nfs: snprintf's format failed: %s", strerror (errno));
257 plugin_submit("nfs3_procedures", inst, buf);
259 #endif /* NFS_HAVE_READ */
261 #if defined(KERNEL_LINUX)
262 static void nfs_read_stats_file (FILE *fh, char *inst)
264 char buffer[BUFSIZE];
272 while (fgets (buffer, BUFSIZE, fh) != NULL)
274 numfields = strsplit (buffer, fields, 48);
279 if (strncmp (fields[0], "proc2", 5) == 0)
282 unsigned long long *values;
284 if (numfields - 2 != nfs2_procedures_ds_num)
286 syslog (LOG_WARNING, "nfs: Wrong number of fields (= %i) for NFS2 statistics.", numfields - 2);
290 if ((values = (unsigned long long *) malloc (nfs2_procedures_ds_num * sizeof (unsigned long long))) == NULL)
292 syslog (LOG_ERR, "nfs: malloc: %s", strerror (errno));
296 for (i = 0; i < nfs2_procedures_ds_num; i++)
297 values[i] = atoll (fields[i + 2]);
299 nfs2_procedures_submit (values, inst);
303 else if (strncmp (fields[0], "proc3", 5) == 0)
306 unsigned long long *values;
308 if (numfields - 2 != nfs3_procedures_ds_num)
310 syslog (LOG_WARNING, "nfs: Wrong number of fields (= %i) for NFS3 statistics.", numfields - 2);
314 if ((values = (unsigned long long *) malloc (nfs3_procedures_ds_num * sizeof (unsigned long long))) == NULL)
316 syslog (LOG_ERR, "nfs: malloc: %s", strerror (errno));
320 for (i = 0; i < nfs3_procedures_ds_num; i++)
321 values[i] = atoll (fields[i + 2]);
323 nfs3_procedures_submit (values, inst);
329 #endif /* defined(KERNEL_LINUX) */
333 static void nfs2_read_kstat (kstat_t *ksp, char *inst)
335 unsigned long long values[18];
337 values[0] = get_kstat_value (ksp, "null");
338 values[1] = get_kstat_value (ksp, "getattr");
339 values[2] = get_kstat_value (ksp, "setattr");
340 values[3] = get_kstat_value (ksp, "root");
341 values[4] = get_kstat_value (ksp, "lookup");
342 values[5] = get_kstat_value (ksp, "readlink");
343 values[6] = get_kstat_value (ksp, "read");
344 values[7] = get_kstat_value (ksp, "wrcache");
345 values[8] = get_kstat_value (ksp, "write");
346 values[9] = get_kstat_value (ksp, "create");
347 values[10] = get_kstat_value (ksp, "remove");
348 values[11] = get_kstat_value (ksp, "rename");
349 values[12] = get_kstat_value (ksp, "link");
350 values[13] = get_kstat_value (ksp, "symlink");
351 values[14] = get_kstat_value (ksp, "mkdir");
352 values[15] = get_kstat_value (ksp, "rmdir");
353 values[16] = get_kstat_value (ksp, "readdir");
354 values[17] = get_kstat_value (ksp, "statfs");
356 nfs2_procedures_submit (values, inst);
361 static void nfs_read (void)
363 #if defined(KERNEL_LINUX)
366 if ((fh = fopen ("/proc/net/rpc/nfs", "r")) != NULL)
368 nfs_read_stats_file (fh, "client");
372 if ((fh = fopen ("/proc/net/rpc/nfsd", "r")) != NULL)
374 nfs_read_stats_file (fh, "server");
378 /* #endif defined(KERNEL_LINUX) */
380 #elif defined(HAVE_LIBKSTAT)
381 if (nfs2_ksp_client != NULL)
382 nfs2_read_kstat (nfs2_ksp_client, "client");
383 if (nfs2_ksp_server != NULL)
384 nfs2_read_kstat (nfs2_ksp_server, "server");
385 #endif /* defined(HAVE_LIBKSTAT) */
388 # define nfs_read NULL
389 #endif /* NFS_HAVE_READ */
391 void module_register (void)
393 plugin_register (MODULE_NAME, nfs_init, nfs_read, NULL);
394 plugin_register ("nfs2_procedures", NULL, NULL, nfs2_procedures_write);
395 plugin_register ("nfs3_procedures", NULL, NULL, nfs3_procedures_write);