master
c 436 lines 16.1 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include "plugin_proc.h"
4
5 #define PLUGIN_PROC_MODULE_NFS_NAME "/proc/net/rpc/nfs"
6 #define CONFIG_SECTION_PLUGIN_PROC_NFS "plugin:" PLUGIN_PROC_CONFIG_NAME ":" PLUGIN_PROC_MODULE_NFS_NAME
7
8 struct nfs_procs {
9 char name[30];
10 unsigned long long value;
11 int present;
12 RRDDIM *rd;
13 };
14
15 struct nfs_procs nfs_proc2_values[] = {
16 { "null" , 0ULL, 0, NULL}
17 , {"getattr" , 0ULL, 0, NULL}
18 , {"setattr" , 0ULL, 0, NULL}
19 , {"root" , 0ULL, 0, NULL}
20 , {"lookup" , 0ULL, 0, NULL}
21 , {"readlink", 0ULL, 0, NULL}
22 , {"read" , 0ULL, 0, NULL}
23 , {"wrcache" , 0ULL, 0, NULL}
24 , {"write" , 0ULL, 0, NULL}
25 , {"create" , 0ULL, 0, NULL}
26 , {"remove" , 0ULL, 0, NULL}
27 , {"rename" , 0ULL, 0, NULL}
28 , {"link" , 0ULL, 0, NULL}
29 , {"symlink" , 0ULL, 0, NULL}
30 , {"mkdir" , 0ULL, 0, NULL}
31 , {"rmdir" , 0ULL, 0, NULL}
32 , {"readdir" , 0ULL, 0, NULL}
33 , {"fsstat" , 0ULL, 0, NULL}
34 ,
35
36 /* termination */
37 { "" , 0ULL, 0, NULL}
38 };
39
40 struct nfs_procs nfs_proc3_values[] = {
41 { "null" , 0ULL, 0, NULL}
42 , {"getattr" , 0ULL, 0, NULL}
43 , {"setattr" , 0ULL, 0, NULL}
44 , {"lookup" , 0ULL, 0, NULL}
45 , {"access" , 0ULL, 0, NULL}
46 , {"readlink" , 0ULL, 0, NULL}
47 , {"read" , 0ULL, 0, NULL}
48 , {"write" , 0ULL, 0, NULL}
49 , {"create" , 0ULL, 0, NULL}
50 , {"mkdir" , 0ULL, 0, NULL}
51 , {"symlink" , 0ULL, 0, NULL}
52 , {"mknod" , 0ULL, 0, NULL}
53 , {"remove" , 0ULL, 0, NULL}
54 , {"rmdir" , 0ULL, 0, NULL}
55 , {"rename" , 0ULL, 0, NULL}
56 , {"link" , 0ULL, 0, NULL}
57 , {"readdir" , 0ULL, 0, NULL}
58 , {"readdirplus", 0ULL, 0, NULL}
59 , {"fsstat" , 0ULL, 0, NULL}
60 , {"fsinfo" , 0ULL, 0, NULL}
61 , {"pathconf" , 0ULL, 0, NULL}
62 , {"commit" , 0ULL, 0, NULL}
63 ,
64
65 /* termination */
66 { "" , 0ULL, 0, NULL}
67 };
68
69 struct nfs_procs nfs_proc4_values[] = {
70 { "null" , 0ULL, 0, NULL}
71 , {"read" , 0ULL, 0, NULL}
72 , {"write" , 0ULL, 0, NULL}
73 , {"commit" , 0ULL, 0, NULL}
74 , {"open" , 0ULL, 0, NULL}
75 , {"open_conf" , 0ULL, 0, NULL}
76 , {"open_noat" , 0ULL, 0, NULL}
77 , {"open_dgrd" , 0ULL, 0, NULL}
78 , {"close" , 0ULL, 0, NULL}
79 , {"setattr" , 0ULL, 0, NULL}
80 , {"fsinfo" , 0ULL, 0, NULL}
81 , {"renew" , 0ULL, 0, NULL}
82 , {"setclntid" , 0ULL, 0, NULL}
83 , {"confirm" , 0ULL, 0, NULL}
84 , {"lock" , 0ULL, 0, NULL}
85 , {"lockt" , 0ULL, 0, NULL}
86 , {"locku" , 0ULL, 0, NULL}
87 , {"access" , 0ULL, 0, NULL}
88 , {"getattr" , 0ULL, 0, NULL}
89 , {"lookup" , 0ULL, 0, NULL}
90 , {"lookup_root" , 0ULL, 0, NULL}
91 , {"remove" , 0ULL, 0, NULL}
92 , {"rename" , 0ULL, 0, NULL}
93 , {"link" , 0ULL, 0, NULL}
94 , {"symlink" , 0ULL, 0, NULL}
95 , {"create" , 0ULL, 0, NULL}
96 , {"pathconf" , 0ULL, 0, NULL}
97 , {"statfs" , 0ULL, 0, NULL}
98 , {"readlink" , 0ULL, 0, NULL}
99 , {"readdir" , 0ULL, 0, NULL}
100 , {"server_caps" , 0ULL, 0, NULL}
101 , {"delegreturn" , 0ULL, 0, NULL}
102 , {"getacl" , 0ULL, 0, NULL}
103 , {"setacl" , 0ULL, 0, NULL}
104 , {"fs_locations" , 0ULL, 0, NULL}
105 , {"rel_lkowner" , 0ULL, 0, NULL}
106 , {"secinfo" , 0ULL, 0, NULL}
107 , {"fsid_present" , 0ULL, 0, NULL}
108 ,
109
110 /* nfsv4.1 client ops */
111 { "exchange_id" , 0ULL, 0, NULL}
112 , {"create_session" , 0ULL, 0, NULL}
113 , {"destroy_session" , 0ULL, 0, NULL}
114 , {"sequence" , 0ULL, 0, NULL}
115 , {"get_lease_time" , 0ULL, 0, NULL}
116 , {"reclaim_comp" , 0ULL, 0, NULL}
117 , {"layoutget" , 0ULL, 0, NULL}
118 , {"getdevinfo" , 0ULL, 0, NULL}
119 , {"layoutcommit" , 0ULL, 0, NULL}
120 , {"layoutreturn" , 0ULL, 0, NULL}
121 , {"secinfo_no" , 0ULL, 0, NULL}
122 , {"test_stateid" , 0ULL, 0, NULL}
123 , {"free_stateid" , 0ULL, 0, NULL}
124 , {"getdevicelist" , 0ULL, 0, NULL}
125 , {"bind_conn_to_ses", 0ULL, 0, NULL}
126 , {"destroy_clientid", 0ULL, 0, NULL}
127 ,
128
129 /* nfsv4.2 client ops */
130 { "seek" , 0ULL, 0, NULL}
131 , {"allocate" , 0ULL, 0, NULL}
132 , {"deallocate" , 0ULL, 0, NULL}
133 , {"layoutstats" , 0ULL, 0, NULL}
134 , {"clone" , 0ULL, 0, NULL}
135 ,
136
137 /* termination */
138 { "" , 0ULL, 0, NULL}
139 };
140
141 int do_proc_net_rpc_nfs(int update_every, usec_t dt) {
142 (void)dt;
143
144 static procfile *ff = NULL;
145 static int do_net = -1, do_rpc = -1, do_proc2 = -1, do_proc3 = -1, do_proc4 = -1;
146 static int proc2_warning = 0, proc3_warning = 0, proc4_warning = 0;
147
148 if(!ff) {
149 char filename[FILENAME_MAX + 1];
150 snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/rpc/nfs");
151 ff = procfile_open(inicfg_get(&netdata_config, CONFIG_SECTION_PLUGIN_PROC_NFS, "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT);
152 }
153 if(!ff) return 1;
154
155 ff = procfile_readall(ff);
156 if(!ff) return 0; // we return 0, so that we will retry to open it next time
157
158 if(do_net == -1) do_net = inicfg_get_boolean(&netdata_config, CONFIG_SECTION_PLUGIN_PROC_NFS, "network", 1);
159 if(do_rpc == -1) do_rpc = inicfg_get_boolean(&netdata_config, CONFIG_SECTION_PLUGIN_PROC_NFS, "rpc", 1);
160 if(do_proc2 == -1) do_proc2 = inicfg_get_boolean(&netdata_config, CONFIG_SECTION_PLUGIN_PROC_NFS, "NFS v2 procedures", 1);
161 if(do_proc3 == -1) do_proc3 = inicfg_get_boolean(&netdata_config, CONFIG_SECTION_PLUGIN_PROC_NFS, "NFS v3 procedures", 1);
162 if(do_proc4 == -1) do_proc4 = inicfg_get_boolean(&netdata_config, CONFIG_SECTION_PLUGIN_PROC_NFS, "NFS v4 procedures", 1);
163
164 // if they are enabled, reset them to 1
165 // later we do them =2 to avoid doing strcmp() for all lines
166 if(do_net) do_net = 1;
167 if(do_rpc) do_rpc = 1;
168 if(do_proc2) do_proc2 = 1;
169 if(do_proc3) do_proc3 = 1;
170 if(do_proc4) do_proc4 = 1;
171
172 size_t lines = procfile_lines(ff), l;
173
174 char *type;
175 unsigned long long net_count = 0, net_udp_count = 0, net_tcp_count = 0, net_tcp_connections = 0;
176 unsigned long long rpc_calls = 0, rpc_retransmits = 0, rpc_auth_refresh = 0;
177
178 for(l = 0; l < lines ;l++) {
179 size_t words = procfile_linewords(ff, l);
180 if(!words) continue;
181
182 type = procfile_lineword(ff, l, 0);
183
184 if(do_net == 1 && strcmp(type, "net") == 0) {
185 if(words < 5) {
186 collector_error("%s line of /proc/net/rpc/nfs has %zu words, expected %d", type, words, 5);
187 continue;
188 }
189
190 net_count = str2ull(procfile_lineword(ff, l, 1), NULL);
191 net_udp_count = str2ull(procfile_lineword(ff, l, 2), NULL);
192 net_tcp_count = str2ull(procfile_lineword(ff, l, 3), NULL);
193 net_tcp_connections = str2ull(procfile_lineword(ff, l, 4), NULL);
194
195 unsigned long long sum = net_count + net_udp_count + net_tcp_count + net_tcp_connections;
196 if(sum == 0ULL) do_net = -1;
197 else do_net = 2;
198 }
199 else if(do_rpc == 1 && strcmp(type, "rpc") == 0) {
200 if(words < 4) {
201 collector_error("%s line of /proc/net/rpc/nfs has %zu words, expected %d", type, words, 6);
202 continue;
203 }
204
205 rpc_calls = str2ull(procfile_lineword(ff, l, 1), NULL);
206 rpc_retransmits = str2ull(procfile_lineword(ff, l, 2), NULL);
207 rpc_auth_refresh = str2ull(procfile_lineword(ff, l, 3), NULL);
208
209 unsigned long long sum = rpc_calls + rpc_retransmits + rpc_auth_refresh;
210 if(sum == 0ULL) do_rpc = -1;
211 else do_rpc = 2;
212 }
213 else if(do_proc2 == 1 && strcmp(type, "proc2") == 0) {
214 // the first number is the count of numbers present
215 // so we start for word 2
216
217 unsigned long long sum = 0;
218 unsigned int i, j;
219 for(i = 0, j = 2; j < words && nfs_proc2_values[i].name[0] ; i++, j++) {
220 nfs_proc2_values[i].value = str2ull(procfile_lineword(ff, l, j), NULL);
221 nfs_proc2_values[i].present = 1;
222 sum += nfs_proc2_values[i].value;
223 }
224
225 if(sum == 0ULL) {
226 if(!proc2_warning) {
227 collector_error("Disabling /proc/net/rpc/nfs v2 procedure calls chart. It seems unused on this machine. It will be enabled automatically when found with data in it.");
228 proc2_warning = 1;
229 }
230 do_proc2 = 0;
231 }
232 else do_proc2 = 2;
233 }
234 else if(do_proc3 == 1 && strcmp(type, "proc3") == 0) {
235 // the first number is the count of numbers present
236 // so we start for word 2
237
238 unsigned long long sum = 0;
239 unsigned int i, j;
240 for(i = 0, j = 2; j < words && nfs_proc3_values[i].name[0] ; i++, j++) {
241 nfs_proc3_values[i].value = str2ull(procfile_lineword(ff, l, j), NULL);
242 nfs_proc3_values[i].present = 1;
243 sum += nfs_proc3_values[i].value;
244 }
245
246 if(sum == 0ULL) {
247 if(!proc3_warning) {
248 collector_info("Disabling /proc/net/rpc/nfs v3 procedure calls chart. It seems unused on this machine. It will be enabled automatically when found with data in it.");
249 proc3_warning = 1;
250 }
251 do_proc3 = 0;
252 }
253 else do_proc3 = 2;
254 }
255 else if(do_proc4 == 1 && strcmp(type, "proc4") == 0) {
256 // the first number is the count of numbers present
257 // so we start for word 2
258
259 unsigned long long sum = 0;
260 unsigned int i, j;
261 for(i = 0, j = 2; j < words && nfs_proc4_values[i].name[0] ; i++, j++) {
262 nfs_proc4_values[i].value = str2ull(procfile_lineword(ff, l, j), NULL);
263 nfs_proc4_values[i].present = 1;
264 sum += nfs_proc4_values[i].value;
265 }
266
267 if(sum == 0ULL) {
268 if(!proc4_warning) {
269 collector_info("Disabling /proc/net/rpc/nfs v4 procedure calls chart. It seems unused on this machine. It will be enabled automatically when found with data in it.");
270 proc4_warning = 1;
271 }
272 do_proc4 = 0;
273 }
274 else do_proc4 = 2;
275 }
276 }
277
278 if(do_net == 2) {
279 static RRDSET *st = NULL;
280 static RRDDIM *rd_udp = NULL,
281 *rd_tcp = NULL;
282
283 if(unlikely(!st)) {
284 st = rrdset_create_localhost(
285 "nfs"
286 , "net"
287 , NULL
288 , "network"
289 , NULL
290 , "NFS Client Network"
291 , "operations/s"
292 , PLUGIN_PROC_NAME
293 , PLUGIN_PROC_MODULE_NFS_NAME
294 , NETDATA_CHART_PRIO_NFS_NET
295 , update_every
296 , RRDSET_TYPE_STACKED
297 );
298
299 rd_udp = rrddim_add(st, "udp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
300 rd_tcp = rrddim_add(st, "tcp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
301 }
302
303 // ignore net_count, net_tcp_connections
304 (void)net_count;
305 (void)net_tcp_connections;
306
307 rrddim_set_by_pointer(st, rd_udp, net_udp_count);
308 rrddim_set_by_pointer(st, rd_tcp, net_tcp_count);
309 rrdset_done(st);
310 }
311
312 if(do_rpc == 2) {
313 static RRDSET *st = NULL;
314 static RRDDIM *rd_calls = NULL,
315 *rd_retransmits = NULL,
316 *rd_auth_refresh = NULL;
317
318 if(unlikely(!st)) {
319 st = rrdset_create_localhost(
320 "nfs"
321 , "rpc"
322 , NULL
323 , "rpc"
324 , NULL
325 , "NFS Client Remote Procedure Calls Statistics"
326 , "calls/s"
327 , PLUGIN_PROC_NAME
328 , PLUGIN_PROC_MODULE_NFS_NAME
329 , NETDATA_CHART_PRIO_NFS_RPC
330 , update_every
331 , RRDSET_TYPE_LINE
332 );
333
334 rd_calls = rrddim_add(st, "calls", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
335 rd_retransmits = rrddim_add(st, "retransmits", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
336 rd_auth_refresh = rrddim_add(st, "auth_refresh", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
337 }
338
339 rrddim_set_by_pointer(st, rd_calls, rpc_calls);
340 rrddim_set_by_pointer(st, rd_retransmits, rpc_retransmits);
341 rrddim_set_by_pointer(st, rd_auth_refresh, rpc_auth_refresh);
342 rrdset_done(st);
343 }
344
345 if(do_proc2 == 2) {
346 static RRDSET *st = NULL;
347 if(unlikely(!st)) {
348 st = rrdset_create_localhost(
349 "nfs"
350 , "proc2"
351 , NULL
352 , "nfsv2rpc"
353 , NULL
354 , "NFS v2 Client Remote Procedure Calls"
355 , "calls/s"
356 , PLUGIN_PROC_NAME
357 , PLUGIN_PROC_MODULE_NFS_NAME
358 , NETDATA_CHART_PRIO_NFS_PROC2
359 , update_every
360 , RRDSET_TYPE_STACKED
361 );
362 }
363
364 size_t i;
365 for(i = 0; nfs_proc2_values[i].present ; i++) {
366 if(unlikely(!nfs_proc2_values[i].rd))
367 nfs_proc2_values[i].rd = rrddim_add(st, nfs_proc2_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
368
369 rrddim_set_by_pointer(st, nfs_proc2_values[i].rd, nfs_proc2_values[i].value);
370 }
371
372 rrdset_done(st);
373 }
374
375 if(do_proc3 == 2) {
376 static RRDSET *st = NULL;
377 if(unlikely(!st)) {
378 st = rrdset_create_localhost(
379 "nfs"
380 , "proc3"
381 , NULL
382 , "nfsv3rpc"
383 , NULL
384 , "NFS v3 Client Remote Procedure Calls"
385 , "calls/s"
386 , PLUGIN_PROC_NAME
387 , PLUGIN_PROC_MODULE_NFS_NAME
388 , NETDATA_CHART_PRIO_NFS_PROC3
389 , update_every
390 , RRDSET_TYPE_STACKED
391 );
392 }
393
394 size_t i;
395 for(i = 0; nfs_proc3_values[i].present ; i++) {
396 if(unlikely(!nfs_proc3_values[i].rd))
397 nfs_proc3_values[i].rd = rrddim_add(st, nfs_proc3_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
398
399 rrddim_set_by_pointer(st, nfs_proc3_values[i].rd, nfs_proc3_values[i].value);
400 }
401
402 rrdset_done(st);
403 }
404
405 if(do_proc4 == 2) {
406 static RRDSET *st = NULL;
407 if(unlikely(!st)) {
408 st = rrdset_create_localhost(
409 "nfs"
410 , "proc4"
411 , NULL
412 , "nfsv4rpc"
413 , NULL
414 , "NFS v4 Client Remote Procedure Calls"
415 , "calls/s"
416 , PLUGIN_PROC_NAME
417 , PLUGIN_PROC_MODULE_NFS_NAME
418 , NETDATA_CHART_PRIO_NFS_PROC4
419 , update_every
420 , RRDSET_TYPE_STACKED
421 );
422 }
423
424 size_t i;
425 for(i = 0; nfs_proc4_values[i].present ; i++) {
426 if(unlikely(!nfs_proc4_values[i].rd))
427 nfs_proc4_values[i].rd = rrddim_add(st, nfs_proc4_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
428
429 rrddim_set_by_pointer(st, nfs_proc4_values[i].rd, nfs_proc4_values[i].value);
430 }
431
432 rrdset_done(st);
433 }
434
435 return 0;
436 }