Code

Merge branch 'collectd-4.4' into collectd-4.5
[collectd.git] / src / nfs.c
1 /**
2  * collectd - src/nfs.c
3  * Copyright (C) 2005,2006  Jason Pepas
4  *
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.
8  *
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.
13  *
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
17  *
18  * Authors:
19  *   Jason Pepas <cell at ices.utexas.edu>
20  *   Florian octo Forster <octo at verplant.org>
21  **/
23 #include "collectd.h"
24 #include "common.h"
25 #include "plugin.h"
27 #if !KERNEL_LINUX
28 # error "No applicable input method."
29 #endif
31 /*
32 see /proc/net/rpc/nfs
33 see http://www.missioncriticallinux.com/orph/NFS-Statistics
35 net x x x x
36 rpc_stat.netcnt         Not used; always zero.
37 rpc_stat.netudpcnt      Not used; always zero.
38 rpc_stat.nettcpcnt      Not used; always zero.
39 rpc_stat.nettcpconn     Not used; always zero.
41 rpc x x x
42 rpc_stat.rpccnt             The number of RPC calls.
43 rpc_stat.rpcretrans         The number of retransmitted RPC calls.
44 rpc_stat.rpcauthrefresh     The number of credential refreshes.
46 proc2 x x x...
47 proc3 x x x...
49 Procedure   NFS Version NFS Version 3
50 Number      Procedures  Procedures
52 0           null        null
53 1           getattr     getattr
54 2           setattr     setattr
55 3           root        lookup
56 4           lookup      access
57 5           readlink    readlink
58 6           read        read
59 7           wrcache     write
60 8           write       create
61 9           create      mkdir
62 10          remove      symlink
63 11          rename      mknod
64 12          link        remove
65 13          symlink     rmdir
66 14          mkdir       rename
67 15          rmdir       link
68 16          readdir     readdir
69 17          fsstat      readdirplus
70 18                      fsstat
71 19                      fsinfo
72 20                      pathconf
73 21                      commit
74 */
76 static const char *nfs2_procedures_names[] =
77 {
78         "null",
79         "getattr",
80         "setattr",
81         "root",
82         "lookup",
83         "readlink",
84         "read",
85         "wrcache",
86         "write",
87         "create",
88         "remove",
89         "rename",
90         "link",
91         "symlink",
92         "mkdir",
93         "rmdir",
94         "readdir",
95         "fsstat",
96         NULL
97 };
98 static int nfs2_procedures_names_num = 18;
100 static const char *nfs3_procedures_names[] =
102         "null",
103         "getattr",
104         "setattr",
105         "lookup",
106         "access",
107         "readlink",
108         "read",
109         "write",
110         "create",
111         "mkdir",
112         "symlink",
113         "mknod",
114         "remove",
115         "rmdir",
116         "rename",
117         "link",
118         "readdir",
119         "readdirplus",
120         "fsstat",
121         "fsinfo",
122         "pathconf",
123         "commit",
124         NULL
125 };
126 static int nfs3_procedures_names_num = 22;
128 #if HAVE_LIBKSTAT && 0
129 extern kstat_ctl_t *kc;
130 static kstat_t *nfs2_ksp_client;
131 static kstat_t *nfs2_ksp_server;
132 static kstat_t *nfs3_ksp_client;
133 static kstat_t *nfs3_ksp_server;
134 static kstat_t *nfs4_ksp_client;
135 static kstat_t *nfs4_ksp_server;
136 #endif
138 /* Possibly TODO: NFSv4 statistics */
140 #if 0
141 static int nfs_init (void)
143 #if HAVE_LIBKSTAT && 0
144         kstat_t *ksp_chain;
146         nfs2_ksp_client = NULL;
147         nfs2_ksp_server = NULL;
148         nfs3_ksp_client = NULL;
149         nfs3_ksp_server = NULL;
150         nfs4_ksp_client = NULL;
151         nfs4_ksp_server = NULL;
152         
153         if (kc == NULL)
154                 return;
156         for (ksp_chain = kc->kc_chain; ksp_chain != NULL;
157                         ksp_chain = ksp_chain->ks_next)
158         {
159                 if (strncmp (ksp_chain->ks_module, "nfs", 3) != 0)
160                         continue;
161                 else if (strncmp (ksp_chain->ks_name, "rfsproccnt_v2", 13) == 0)
162                         nfs2_ksp_server = ksp_chain;
163                 else if (strncmp (ksp_chain->ks_name, "rfsproccnt_v3", 13) == 0)
164                         nfs3_ksp_server = ksp_chain;
165                 else if (strncmp (ksp_chain->ks_name, "rfsproccnt_v4", 13) == 0)
166                         nfs4_ksp_server = ksp_chain;
167                 else if (strncmp (ksp_chain->ks_name, "rfsreqcnt_v2", 12) == 0)
168                         nfs2_ksp_client = ksp_chain;
169                 else if (strncmp (ksp_chain->ks_name, "rfsreqcnt_v3", 12) == 0)
170                         nfs3_ksp_client = ksp_chain;
171                 else if (strncmp (ksp_chain->ks_name, "rfsreqcnt_v4", 12) == 0)
172                         nfs4_ksp_client = ksp_chain;
173         }
174 #endif
176         return (0);
177 } /* int nfs_init */
178 #endif
180 #define BUFSIZE 1024
181 static void nfs_procedures_submit (const char *plugin_instance,
182                 unsigned long long *val, const char **names, int len)
184         value_t values[1];
185         value_list_t vl = VALUE_LIST_INIT;
186         int i;
188         vl.values = values;
189         vl.values_len = 1;
190         vl.time = time (NULL);
191         sstrncpy (vl.host, hostname_g, sizeof (vl.host));
192         sstrncpy (vl.plugin, "nfs", sizeof (vl.plugin));
193         sstrncpy (vl.plugin_instance, plugin_instance,
194                         sizeof (vl.plugin_instance));
195         sstrncpy (vl.type, "nfs_procedure", sizeof (vl.type));
197         for (i = 0; i < len; i++)
198         {
199                 values[0].counter = val[i];
200                 sstrncpy (vl.type_instance, names[i],
201                                 sizeof (vl.type_instance));
202                 DEBUG ("%s-%s/nfs_procedure-%s = %llu",
203                                 vl.plugin, vl.plugin_instance,
204                                 vl.type_instance, val[i]);
205                 plugin_dispatch_values (&vl);
206         }
207 } /* void nfs_procedures_submit */
209 static void nfs_read_stats_file (FILE *fh, char *inst)
211         char buffer[BUFSIZE];
213         char plugin_instance[DATA_MAX_NAME_LEN];
215         char *fields[48];
216         int numfields = 0;
218         if (fh == NULL)
219                 return;
221         while (fgets (buffer, BUFSIZE, fh) != NULL)
222         {
223                 numfields = strsplit (buffer, fields, 48);
225                 if (((numfields - 2) != nfs2_procedures_names_num)
226                                 && ((numfields - 2)
227                                         != nfs3_procedures_names_num))
228                         continue;
230                 if (strcmp (fields[0], "proc2") == 0)
231                 {
232                         int i;
233                         unsigned long long *values;
235                         if ((numfields - 2) != nfs2_procedures_names_num)
236                         {
237                                 WARNING ("nfs plugin: Wrong "
238                                                 "number of fields (= %i) "
239                                                 "for NFSv2 statistics.",
240                                                 numfields - 2);
241                                 continue;
242                         }
244                         ssnprintf (plugin_instance, sizeof (plugin_instance),
245                                         "v2%s", inst);
247                         values = (unsigned long long *) malloc (nfs2_procedures_names_num * sizeof (unsigned long long));
248                         if (values == NULL)
249                         {
250                                 char errbuf[1024];
251                                 ERROR ("nfs plugin: malloc "
252                                                 "failed: %s",
253                                                 sstrerror (errno, errbuf, sizeof (errbuf)));
254                                 continue;
255                         }
257                         for (i = 0; i < nfs2_procedures_names_num; i++)
258                                 values[i] = atoll (fields[i + 2]);
260                         nfs_procedures_submit (plugin_instance, values,
261                                         nfs2_procedures_names,
262                                         nfs2_procedures_names_num);
264                         free (values);
265                 }
266                 else if (strncmp (fields[0], "proc3", 5) == 0)
267                 {
268                         int i;
269                         unsigned long long *values;
271                         if ((numfields - 2) != nfs3_procedures_names_num)
272                         {
273                                 WARNING ("nfs plugin: Wrong "
274                                                 "number of fields (= %i) "
275                                                 "for NFSv3 statistics.",
276                                                 numfields - 2);
277                                 continue;
278                         }
280                         ssnprintf (plugin_instance, sizeof (plugin_instance),
281                                         "v3%s", inst);
283                         values = (unsigned long long *) malloc (nfs3_procedures_names_num * sizeof (unsigned long long));
284                         if (values == NULL)
285                         {
286                                 char errbuf[1024];
287                                 ERROR ("nfs plugin: malloc "
288                                                 "failed: %s",
289                                                 sstrerror (errno, errbuf, sizeof (errbuf)));
290                                 continue;
291                         }
293                         for (i = 0; i < nfs3_procedures_names_num; i++)
294                                 values[i] = atoll (fields[i + 2]);
296                         nfs_procedures_submit (plugin_instance, values,
297                                         nfs3_procedures_names,
298                                         nfs3_procedures_names_num);
300                         free (values);
301                 }
302         } /* while (fgets (buffer, BUFSIZE, fh) != NULL) */
303 } /* void nfs_read_stats_file */
304 #undef BUFSIZE
306 #if HAVE_LIBKSTAT && 0
307 static void nfs2_read_kstat (kstat_t *ksp, char *inst)
309         unsigned long long values[18];
311         values[0] = get_kstat_value (ksp, "null");
312         values[1] = get_kstat_value (ksp, "getattr");
313         values[2] = get_kstat_value (ksp, "setattr");
314         values[3] = get_kstat_value (ksp, "root");
315         values[4] = get_kstat_value (ksp, "lookup");
316         values[5] = get_kstat_value (ksp, "readlink");
317         values[6] = get_kstat_value (ksp, "read");
318         values[7] = get_kstat_value (ksp, "wrcache");
319         values[8] = get_kstat_value (ksp, "write");
320         values[9] = get_kstat_value (ksp, "create");
321         values[10] = get_kstat_value (ksp, "remove");
322         values[11] = get_kstat_value (ksp, "rename");
323         values[12] = get_kstat_value (ksp, "link");
324         values[13] = get_kstat_value (ksp, "symlink");
325         values[14] = get_kstat_value (ksp, "mkdir");
326         values[15] = get_kstat_value (ksp, "rmdir");
327         values[16] = get_kstat_value (ksp, "readdir");
328         values[17] = get_kstat_value (ksp, "statfs");
330         nfs2_procedures_submit (values, inst);
332 #endif
334 static int nfs_read (void)
336         FILE *fh;
338         if ((fh = fopen ("/proc/net/rpc/nfs", "r")) != NULL)
339         {
340                 nfs_read_stats_file (fh, "client");
341                 fclose (fh);
342         }
344         if ((fh = fopen ("/proc/net/rpc/nfsd", "r")) != NULL)
345         {
346                 nfs_read_stats_file (fh, "server");
347                 fclose (fh);
348         }
350 #if HAVE_LIBKSTAT && 0
351         if (nfs2_ksp_client != NULL)
352                 nfs2_read_kstat (nfs2_ksp_client, "client");
353         if (nfs2_ksp_server != NULL)
354                 nfs2_read_kstat (nfs2_ksp_server, "server");
355 #endif /* defined(HAVE_LIBKSTAT) */
357         return (0);
360 void module_register (void)
362         plugin_register_read ("nfs", nfs_read);
363 } /* void module_register */