Code

nfs plugin: Minor coding style fixes.
[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 HAVE_KSTAT_H
28 #include <kstat.h>
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 };
97 static size_t nfs2_procedures_names_num = STATIC_ARRAY_SIZE (nfs2_procedures_names);
99 static const char *nfs3_procedures_names[] =
101         "null",
102         "getattr",
103         "setattr",
104         "lookup",
105         "access",
106         "readlink",
107         "read",
108         "write",
109         "create",
110         "mkdir",
111         "symlink",
112         "mknod",
113         "remove",
114         "rmdir",
115         "rename",
116         "link",
117         "readdir",
118         "readdirplus",
119         "fsstat",
120         "fsinfo",
121         "pathconf",
122         "commit"
123 };
124 static size_t nfs3_procedures_names_num = STATIC_ARRAY_SIZE (nfs3_procedures_names);
126 #if HAVE_LIBKSTAT
127 static const char *nfs4_procedures_names[] =
129         "null",
130         "compound",
131         "reserved",
132         "access",
133         "close",
134         "commit",
135         "create",
136         "delegpurge",
137         "delegreturn",
138         "getattr",
139         "getfh",
140         "link",
141         "lock",
142         "lockt",
143         "locku",
144         "lookup",
145         "lookupp",
146         "nverify",
147         "open",
148         "openattr",
149         "open_confirm",
150         "open_downgrade",
151         "putfh",
152         "putpubfh",
153         "putrootfh",
154         "read",
155         "readdir",
156         "readlink",
157         "remove",
158         "rename",
159         "renew",
160         "restorefh",
161         "savefh",
162         "secinfo",
163         "setattr",
164         "setclientid",
165         "setclientid_confirm",
166         "verify",
167         "write"
168 };
169 static size_t nfs4_procedures_names_num = STATIC_ARRAY_SIZE (nfs4_procedures_names);
170 #endif
172 #if HAVE_LIBKSTAT
173 extern kstat_ctl_t *kc;
174 static kstat_t *nfs2_ksp_client;
175 static kstat_t *nfs2_ksp_server;
176 static kstat_t *nfs3_ksp_client;
177 static kstat_t *nfs3_ksp_server;
178 static kstat_t *nfs4_ksp_client;
179 static kstat_t *nfs4_ksp_server;
180 #endif
182 /* Possibly TODO: NFSv4 statistics */
184 #if KERNEL_LINUX
185 static int nfs_init (void)
187         return (0);
189 /* #endif KERNEL_LINUX */
191 #elif HAVE_LIBKSTAT
192 static int nfs_init (void)
194         kstat_t *ksp_chain = NULL;
196         nfs2_ksp_client = NULL;
197         nfs2_ksp_server = NULL;
198         nfs3_ksp_client = NULL;
199         nfs3_ksp_server = NULL;
200         nfs4_ksp_client = NULL;
201         nfs4_ksp_server = NULL;
203         if (kc == NULL)
204                 return (-1);
206         for (ksp_chain = kc->kc_chain; ksp_chain != NULL;
207                         ksp_chain = ksp_chain->ks_next)
208         {
209                 if (strncmp (ksp_chain->ks_module, "nfs", 3) != 0)
210                         continue;
211                 else if (strncmp (ksp_chain->ks_name, "rfsproccnt_v2", 13) == 0)
212                         nfs2_ksp_server = ksp_chain;
213                 else if (strncmp (ksp_chain->ks_name, "rfsproccnt_v3", 13) == 0)
214                         nfs3_ksp_server = ksp_chain;
215                 else if (strncmp (ksp_chain->ks_name, "rfsproccnt_v4", 13) == 0)
216                         nfs4_ksp_server = ksp_chain;
217                 else if (strncmp (ksp_chain->ks_name, "rfsreqcnt_v2", 12) == 0)
218                         nfs2_ksp_client = ksp_chain;
219                 else if (strncmp (ksp_chain->ks_name, "rfsreqcnt_v3", 12) == 0)
220                         nfs3_ksp_client = ksp_chain;
221                 else if (strncmp (ksp_chain->ks_name, "rfsreqcnt_v4", 12) == 0)
222                         nfs4_ksp_client = ksp_chain;
223         }
225         return (0);
226 } /* int nfs_init */
227 #endif
229 static void nfs_procedures_submit (const char *plugin_instance,
230                 const char **type_instances,
231                 value_t *values, size_t values_num)
233         value_list_t vl = VALUE_LIST_INIT;
234         size_t i;
236         vl.values_len = 1;
237         sstrncpy (vl.host, hostname_g, sizeof (vl.host));
238         sstrncpy (vl.plugin, "nfs", sizeof (vl.plugin));
239         sstrncpy (vl.plugin_instance, plugin_instance,
240                         sizeof (vl.plugin_instance));
241         sstrncpy (vl.type, "nfs_procedure", sizeof (vl.type));
243         for (i = 0; i < values_num; i++)
244         {
245                 vl.values = values + i;
246                 sstrncpy (vl.type_instance, type_instances[i],
247                                 sizeof (vl.type_instance));
248                 plugin_dispatch_values_secure (&vl);
249         }
250 } /* void nfs_procedures_submit */
252 #if KERNEL_LINUX
253 static int nfs_submit_fields (int nfs_version, const char *instance,
254                 char **fields, size_t fields_num,
255                 const char **proc_names, size_t proc_names_num)
257         char plugin_instance[DATA_MAX_NAME_LEN];
258         value_t values[fields_num];
259         size_t i;
261         if (fields_num != proc_names_num)
262         {
263                 WARNING ("nfs plugin: Wrong number of fields for "
264                                 "NFSv%i %s statistics. Expected %zu, got %zu.",
265                                 nfs_version, instance,
266                                 proc_names_num, fields_num);
267                 return (EINVAL);
268         }
270         ssnprintf (plugin_instance, sizeof (plugin_instance), "v%i%s",
271                         nfs_version, instance);
273         for (i = 0; i < proc_names_num; i++)
274                 (void) parse_value (fields[i], &values[i], DS_TYPE_DERIVE);
276         nfs_procedures_submit (plugin_instance, proc_names, values,
277                         proc_names_num);
279         return (0);
282 static void nfs_read_linux (FILE *fh, char *inst)
284         char buffer[1024];
286         char *fields[48];
287         int fields_num = 0;
289         if (fh == NULL)
290                 return;
292         while (fgets (buffer, sizeof (buffer), fh) != NULL)
293         {
294                 fields_num = strsplit (buffer,
295                                 fields, STATIC_ARRAY_SIZE (fields));
297                 if (fields_num < 3)
298                         continue;
300                 if (strcmp (fields[0], "proc2") == 0)
301                 {
302                         nfs_submit_fields (/* version = */ 2, inst,
303                                         fields + 2, (size_t) (fields_num - 2),
304                                         nfs2_procedures_names,
305                                         nfs2_procedures_names_num);
306                 }
307                 else if (strncmp (fields[0], "proc3", 5) == 0)
308                 {
309                         nfs_submit_fields (/* version = */ 3, inst,
310                                         fields + 2, (size_t) (fields_num - 2),
311                                         nfs3_procedures_names,
312                                         nfs3_procedures_names_num);
313                 }
314         } /* while (fgets) */
315 } /* void nfs_read_linux */
316 #endif /* KERNEL_LINUX */
318 #if HAVE_LIBKSTAT
319 static int nfs_read_kstat (kstat_t *ksp, int nfs_version, char *inst,
320                 const char **proc_names, size_t proc_names_num)
322         char plugin_instance[DATA_MAX_NAME_LEN];
323         value_t values[proc_names_num];
324         size_t i;
326         if (ksp == NULL)
327                 return (EINVAL);
329         ssnprintf (plugin_instance, sizeof (plugin_instance), "v%i%s",
330                         nfs_version, inst);
332         kstat_read(kc, ksp, NULL);
333         for (i = 0; i < proc_names_num; i++)
334                 values[i] = (derive_t) get_kstat_value (ksp, proc_names[i]);
336         nfs_procedures_submit (plugin_instance, proc_names, values,
337                         proc_names_num);
339 #endif
341 #if KERNEL_LINUX
342 static int nfs_read (void)
344         FILE *fh;
346         if ((fh = fopen ("/proc/net/rpc/nfs", "r")) != NULL)
347         {
348                 nfs_read_linux (fh, "client");
349                 fclose (fh);
350         }
352         if ((fh = fopen ("/proc/net/rpc/nfsd", "r")) != NULL)
353         {
354                 nfs_read_linux (fh, "server");
355                 fclose (fh);
356         }
358         return (0);
360 /* #endif KERNEL_LINUX */
362 #elif HAVE_LIBKSTAT
363 static int nfs_read (void)
365         nfs_read_kstat (nfs2_ksp_client, /* version = */ 2, "client",
366                         nfs2_procedures_names, nfs2_procedures_names_num);
367         nfs_read_kstat (nfs2_ksp_server, /* version = */ 2, "server",
368                         nfs2_procedures_names, nfs2_procedures_names_num);
369         nfs_read_kstat (nfs3_ksp_client, /* version = */ 3, "client",
370                         nfs3_procedures_names, nfs3_procedures_names_num);
371         nfs_read_kstat (nfs3_ksp_server, /* version = */ 3, "server",
372                         nfs3_procedures_names, nfs3_procedures_names_num);
373         nfs_read_kstat (nfs4_ksp_client, /* version = */ 4, "client",
374                         nfs4_procedures_names, nfs4_procedures_names_num);
375         nfs_read_kstat (nfs4_ksp_server, /* version = */ 4, "server",
376                         nfs4_procedures_names, nfs4_procedures_names_num);
378         return (0);
380 #endif /* HAVE_LIBKSTAT */
382 void module_register (void)
384         plugin_register_init ("nfs", nfs_init);
385         plugin_register_read ("nfs", nfs_read);
386 } /* void module_register */