Code

Fix Linux compilation errors
[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         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
129 static const char *nfs4_procedures_names[] =
131         "null",
132         "compound",
133         "reserved",
134         "access",
135         "close",
136         "commit",
137         "create",
138         "delegpurge",
139         "delegreturn",
140         "getattr",
141         "getfh",
142         "link",
143         "lock",
144         "lockt",
145         "locku",
146         "lookup",
147         "lookupp",
148         "nverify",
149         "open",
150         "openattr",
151         "open_confirm",
152         "open_downgrade",
153         "putfh",
154         "putpubfh",
155         "putrootfh",
156         "read",
157         "readdir",
158         "readlink",
159         "remove",
160         "rename",
161         "renew",
162         "restorefh",
163         "savefh",
164         "secinfo",
165         "setattr",
166         "setclientid",
167         "setclientid_confirm",
168         "verify",
169         "write",
170         NULL
171 };
172 static int nfs4_procedures_names_num = 39;
173 #endif
175 #if HAVE_LIBKSTAT
176 extern kstat_ctl_t *kc;
177 static kstat_t *nfs2_ksp_client;
178 static kstat_t *nfs2_ksp_server;
179 static kstat_t *nfs3_ksp_client;
180 static kstat_t *nfs3_ksp_server;
181 static kstat_t *nfs4_ksp_client;
182 static kstat_t *nfs4_ksp_server;
183 #endif
185 /* Possibly TODO: NFSv4 statistics */
187 #if HAVE_LIBKSTAT
188 static int nfs_init (void)
190         kstat_t *ksp_chain = NULL;
192         nfs2_ksp_client = NULL;
193         nfs2_ksp_server = NULL;
194         nfs3_ksp_client = NULL;
195         nfs3_ksp_server = NULL;
196         nfs4_ksp_client = NULL;
197         nfs4_ksp_server = NULL;
199         if (kc == NULL)
200                 return (-1);
202         for (ksp_chain = kc->kc_chain; ksp_chain != NULL;
203                         ksp_chain = ksp_chain->ks_next)
204         {
205                 if (strncmp (ksp_chain->ks_module, "nfs", 3) != 0)
206                         continue;
207                 else if (strncmp (ksp_chain->ks_name, "rfsproccnt_v2", 13) == 0)
208                         nfs2_ksp_server = ksp_chain;
209                 else if (strncmp (ksp_chain->ks_name, "rfsproccnt_v3", 13) == 0)
210                         nfs3_ksp_server = ksp_chain;
211                 else if (strncmp (ksp_chain->ks_name, "rfsproccnt_v4", 13) == 0)
212                         nfs4_ksp_server = ksp_chain;
213                 else if (strncmp (ksp_chain->ks_name, "rfsreqcnt_v2", 12) == 0)
214                         nfs2_ksp_client = ksp_chain;
215                 else if (strncmp (ksp_chain->ks_name, "rfsreqcnt_v3", 12) == 0)
216                         nfs3_ksp_client = ksp_chain;
217                 else if (strncmp (ksp_chain->ks_name, "rfsreqcnt_v4", 12) == 0)
218                         nfs4_ksp_client = ksp_chain;
219         }
221         return (0);
222 } /* int nfs_init */
223 #endif
225 #define BUFSIZE 1024
226 #if HAVE_LIBKSTAT
228 static void nfs2_procedures_submit(unsigned long long *val,
229                 const char *plugin_instance, char *nfs_ver, int len)
231         value_t values[1];
232         value_list_t vl = VALUE_LIST_INIT;
233         char pl_instance[30];
234         int i;
236         vl.values = values;
237         vl.values_len = 1;
238         sstrncpy(vl.host, hostname_g, sizeof (vl.host));
239         sstrncpy(vl.plugin, "nfs", sizeof (vl.plugin));
240         sstrncpy(pl_instance, nfs_ver, strlen(nfs_ver) + 1);
241         strcat(pl_instance, plugin_instance);
242         sstrncpy(vl.plugin_instance, pl_instance,
243                         sizeof (vl.plugin_instance));
244         sstrncpy(vl.type, "nfs_procedure", sizeof (vl.type));
247         for (i = 0; i < len; i++)
248         {
249                 values[0].derive = val[i];
250                 if (strcmp(nfs_ver, "nfs2") == 0)
251                         sstrncpy(vl.type_instance, nfs2_procedures_names[i],
252                                         sizeof (vl.type_instance));
253                 else if (strcmp(nfs_ver, "nfs3") == 0)
254                         sstrncpy(vl.type_instance, nfs3_procedures_names[i],
255                                         sizeof (vl.type_instance));
256                 else if (strcmp(nfs_ver, "nfs4") == 0) {
257                         sstrncpy(vl.type_instance, nfs4_procedures_names[i],
258                                         sizeof (vl.type_instance));
259                 }
261                 DEBUG("%s-%s/nfs_procedure-%s = %lld",
262                                 vl.plugin, vl.plugin_instance,
263                                 vl.type_instance, val[i]);
264                 plugin_dispatch_values (&vl);
265         }
267 #endif
269 static void nfs_procedures_submit (const char *plugin_instance,
270                 unsigned long long *val, const char **names, int len)
273         value_t values[1];
274         value_list_t vl = VALUE_LIST_INIT;
275         int i;
277         vl.values = values;
278         vl.values_len = 1;
279         sstrncpy(vl.host, hostname_g, sizeof (vl.host));
280         sstrncpy(vl.plugin, "nfs", sizeof (vl.plugin));
281         sstrncpy(vl.plugin_instance, plugin_instance,
282                         sizeof (vl.plugin_instance));
283         sstrncpy(vl.type, "nfs_procedure", sizeof (vl.type));
285         for (i = 0; (i < len); i++) {
286                 values[0].derive = val[i];
287                 sstrncpy(vl.type_instance, names[i],
288                                 sizeof (vl.type_instance));
289                 DEBUG("%s-%s/nfs_procedure-%s = %llu",
290                                 vl.plugin, vl.plugin_instance,
291                                 vl.type_instance, val[i]);
292                 plugin_dispatch_values(&vl);
293         }
294 } /* void nfs_procedures_submit */
296 static void nfs_read_stats_file (FILE *fh, char *inst)
298         char buffer[BUFSIZE];
300         char plugin_instance[DATA_MAX_NAME_LEN];
302         char *fields[48];
303         int numfields = 0;
305         if (fh == NULL)
306                 return;
308         while (fgets (buffer, BUFSIZE, fh) != NULL)
309         {
310                 numfields = strsplit (buffer, fields, 48);
312                 if (((numfields - 2) != nfs2_procedures_names_num)
313                                 && ((numfields - 2)
314                                         != nfs3_procedures_names_num))
315                         continue;
317                 if (strcmp (fields[0], "proc2") == 0)
318                 {
319                         int i;
320                         unsigned long long *values;
322                         if ((numfields - 2) != nfs2_procedures_names_num)
323                         {
324                                 WARNING ("nfs plugin: Wrong "
325                                                 "number of fields (= %i) "
326                                                 "for NFSv2 statistics.",
327                                                 numfields - 2);
328                                 continue;
329                         }
331                         ssnprintf (plugin_instance, sizeof (plugin_instance),
332                                         "v2%s", inst);
334                         values = (unsigned long long *) malloc (nfs2_procedures_names_num * sizeof (unsigned long long));
335                         if (values == NULL)
336                         {
337                                 char errbuf[1024];
338                                 ERROR ("nfs plugin: malloc "
339                                                 "failed: %s",
340                                                 sstrerror (errno, errbuf, sizeof (errbuf)));
341                                 continue;
342                         }
344                         for (i = 0; i < nfs2_procedures_names_num; i++)
345                                 values[i] = atoll (fields[i + 2]);
347                         nfs_procedures_submit (plugin_instance, values,
348                                         nfs2_procedures_names,
349                                         nfs2_procedures_names_num);
351                         free (values);
352                 }
353                 else if (strncmp (fields[0], "proc3", 5) == 0)
354                 {
355                         int i;
356                         unsigned long long *values;
358                         if ((numfields - 2) != nfs3_procedures_names_num)
359                         {
360                                 WARNING ("nfs plugin: Wrong "
361                                                 "number of fields (= %i) "
362                                                 "for NFSv3 statistics.",
363                                                 numfields - 2);
364                                 continue;
365                         }
367                         ssnprintf (plugin_instance, sizeof (plugin_instance),
368                                         "v3%s", inst);
370                         values = (unsigned long long *) malloc (nfs3_procedures_names_num * sizeof (unsigned long long));
371                         if (values == NULL)
372                         {
373                                 char errbuf[1024];
374                                 ERROR ("nfs plugin: malloc "
375                                                 "failed: %s",
376                                                 sstrerror (errno, errbuf, sizeof (errbuf)));
377                                 continue;
378                         }
380                         for (i = 0; i < nfs3_procedures_names_num; i++)
381                                 values[i] = atoll (fields[i + 2]);
383                         nfs_procedures_submit (plugin_instance, values,
384                                         nfs3_procedures_names,
385                                         nfs3_procedures_names_num);
387                         free (values);
388                 }
389         } /* while (fgets (buffer, BUFSIZE, fh) != NULL) */
390 } /* void nfs_read_stats_file */
391 #undef BUFSIZE
393 #if HAVE_LIBKSTAT
394 static void nfs2_read_kstat (kstat_t *ksp, char *inst)
396         unsigned long long values[nfs2_procedures_names_num];
398         kstat_read(kc, ksp, NULL);
399         values[0] = get_kstat_value (ksp, "null");
400         values[1] = get_kstat_value (ksp, "getattr");
401         values[2] = get_kstat_value (ksp, "setattr");
402         values[3] = get_kstat_value (ksp, "root");
403         values[4] = get_kstat_value (ksp, "lookup");
404         values[5] = get_kstat_value (ksp, "readlink");
405         values[6] = get_kstat_value (ksp, "read");
406         values[7] = get_kstat_value (ksp, "wrcache");
407         values[8] = get_kstat_value (ksp, "write");
408         values[9] = get_kstat_value (ksp, "create");
409         values[10] = get_kstat_value (ksp, "remove");
410         values[11] = get_kstat_value (ksp, "rename");
411         values[12] = get_kstat_value (ksp, "link");
412         values[13] = get_kstat_value (ksp, "symlink");
413         values[14] = get_kstat_value (ksp, "mkdir");
414         values[15] = get_kstat_value (ksp, "rmdir");
415         values[16] = get_kstat_value (ksp, "readdir");
416         values[17] = get_kstat_value (ksp, "statfs");
418         nfs2_procedures_submit (values, inst, "nfs2", nfs2_procedures_names_num);
421 static void nfs3_read_kstat(kstat_t *ksp, char *inst)
423         unsigned long long values[nfs3_procedures_names_num];
425         kstat_read(kc, ksp, NULL);
426         values[0] = get_kstat_value (ksp, "null");
427         values[1] = get_kstat_value (ksp, "getattr");
428         values[2] = get_kstat_value (ksp, "setattr");
429         values[3] = get_kstat_value (ksp, "lookup");
430         values[4] = get_kstat_value (ksp, "access");
431         values[5] = get_kstat_value (ksp, "readlink");
432         values[6] = get_kstat_value (ksp, "read");
433         values[7] = get_kstat_value (ksp, "write");
434         values[8] = get_kstat_value (ksp, "create");
435         values[9] = get_kstat_value (ksp, "mkdir");
436         values[10] = get_kstat_value (ksp, "symlink");
437         values[11] = get_kstat_value (ksp, "mknod");
438         values[12] = get_kstat_value (ksp, "remove");
439         values[13] = get_kstat_value (ksp, "rmdir");
440         values[14] = get_kstat_value (ksp, "rename");
441         values[15] = get_kstat_value (ksp, "link");
442         values[16] = get_kstat_value (ksp, "readdir");
443         values[17] = get_kstat_value (ksp, "readdirplus");
444         values[18] = get_kstat_value (ksp, "fsstat");
445         values[19] = get_kstat_value (ksp, "fsinfo");
446         values[20] = get_kstat_value (ksp, "pathconf");
447         values[21] = get_kstat_value (ksp, "commit");
449         nfs2_procedures_submit (values, inst, "nfs3", nfs3_procedures_names_num);
452 static void nfs4_read_kstat(kstat_t *ksp, char *inst)
454         unsigned long long values[nfs4_procedures_names_num];
456         kstat_read(kc, ksp, NULL);
458         values[0] = get_kstat_value (ksp, "null");
459         values[1] = get_kstat_value (ksp, "compound");
460         values[2] = get_kstat_value (ksp, "reserved");
461         values[3] = get_kstat_value (ksp, "access");
462         values[4] = get_kstat_value (ksp, "close");
463         values[5] = get_kstat_value (ksp, "commit");
464         values[6] = get_kstat_value (ksp, "create");
465         values[7] = get_kstat_value (ksp, "delegpurge");
466         values[8] = get_kstat_value (ksp, "delegreturn");
467         values[9] = get_kstat_value (ksp, "getattr");
468         values[10] = get_kstat_value (ksp, "getfh");
469         values[11] = get_kstat_value (ksp, "link");
470         values[12] = get_kstat_value (ksp, "lock");
471         values[13] = get_kstat_value (ksp, "lockt");
472         values[14] = get_kstat_value (ksp, "locku");
473         values[15] = get_kstat_value (ksp, "lookup");
474         values[16] = get_kstat_value (ksp, "lookupp");
475         values[17] = get_kstat_value (ksp, "nverify");
476         values[18] = get_kstat_value (ksp, "open");
477         values[19] = get_kstat_value (ksp, "openattr");
478         values[20] = get_kstat_value (ksp, "open_confirm");
479         values[21] = get_kstat_value (ksp, "open_downgrade");
480         values[22] = get_kstat_value (ksp, "putfh");
481         values[23] = get_kstat_value (ksp, "putpubfh");
482         values[24] = get_kstat_value (ksp, "putrootfh");
483         values[25] = get_kstat_value (ksp, "read");
484         values[26] = get_kstat_value (ksp, "readdir");
485         values[27] = get_kstat_value (ksp, "readlink");
486         values[28] = get_kstat_value (ksp, "remove");
487         values[29] = get_kstat_value (ksp, "rename");
488         values[30] = get_kstat_value (ksp, "renew");
489         values[31] = get_kstat_value (ksp, "restorefh");
490         values[32] = get_kstat_value (ksp, "savefh");
491         values[33] = get_kstat_value (ksp, "secinfo");
492         values[34] = get_kstat_value (ksp, "setattr");
493         values[35] = get_kstat_value (ksp, "setclientid");
494         values[36] = get_kstat_value (ksp, "setclientid_confirm");
495         values[37] = get_kstat_value (ksp, "verify");
496         values[38] = get_kstat_value (ksp, "write");
498         nfs2_procedures_submit (values, inst, "nfs4", nfs4_procedures_names_num);
500 #endif
502 static int nfs_read (void)
504         FILE *fh;
506         if ((fh = fopen ("/proc/net/rpc/nfs", "r")) != NULL)
507         {
508                 nfs_read_stats_file (fh, "client");
509                 fclose (fh);
510         }
512         if ((fh = fopen ("/proc/net/rpc/nfsd", "r")) != NULL)
513         {
514                 nfs_read_stats_file (fh, "server");
515                 fclose (fh);
516         }
518 #if HAVE_LIBKSTAT
519         nfs_init ();
520         if (nfs2_ksp_client != NULL)
521                 nfs2_read_kstat (nfs2_ksp_client, "client");
522         if (nfs2_ksp_server != NULL)
523                 nfs2_read_kstat (nfs2_ksp_server, "server");
524         if (nfs3_ksp_client != NULL)
525                 nfs3_read_kstat (nfs3_ksp_client, "client");
526         if (nfs3_ksp_server != NULL)
527                 nfs3_read_kstat (nfs3_ksp_server, "server");
528         if (nfs4_ksp_client != NULL)
529                 nfs4_read_kstat (nfs4_ksp_client, "client");
530         if (nfs4_ksp_server != NULL)
531                 nfs4_read_kstat (nfs4_ksp_server, "server");
532         /* nfs_kstat(nfs3_ksp_client); */
533 #endif /* defined(HAVE_LIBKSTAT) */
535         return (0);
538 void module_register (void)
540         plugin_register_read ("nfs", nfs_read);
541 } /* void module_register */