nfs.c revision 1.1
1/*	$OpenBSD: nfs.c,v 1.1 2009/06/19 07:48:45 jasper Exp $	*/
2
3/*
4 * Copyright (c) 2009 Jasper Lievisse Adriaanse <jasper@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 */
19
20#include <sys/param.h>
21#include <sys/mount.h>
22#include <sys/sysctl.h>
23#include <sys/types.h>
24#include <nfs/rpcv2.h>
25#include <nfs/nfsproto.h>
26#include <nfs/nfs.h>
27
28#include <err.h>
29#include <errno.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33
34#include "systat.h"
35
36int	check_nfs(void);
37int	select_client(void);
38int	select_server(void);
39int	read_nfs(void);
40void	print_client(void);
41void	print_server(void);
42
43struct	nfsstats nfsstats;
44int	num_client = 0;
45int	num_server = 0;
46
47field_def fields_nfs[] = {
48	/* Client */
49	{"Rpc Counts", 10, 12, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
50	{"", 12, 14, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
51	{"Rpc Info", 14, 12, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
52	{"", 12, 14, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
53	{"Cache Info", 10, 12, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
54	{"", 12, 14, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
55
56	/* Server */
57	{"Rpc Counts", 10, 12, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
58	{"", 12, 14, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
59	{"Cache Stats", 14, 12, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
60	{"", 12, 14, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
61	{"Writes", 10, 12, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
62	{"", 12, 14, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
63};
64
65/* _V suffixed fields indicate a value column. */
66#define FIELD_ADDR(x) (&fields_nfs[x])
67
68/* Client */
69#define	FLD_NFS_C_RPC_COUNTS	FIELD_ADDR(0)
70#define	FLD_NFS_C_RPC_COUNTS_V	FIELD_ADDR(1)
71#define	FLD_NFS_C_RPC_INFO	FIELD_ADDR(2)
72#define	FLD_NFS_C_RPC_INFO_V	FIELD_ADDR(3)
73#define	FLD_NFS_C_CACHE_INFO	FIELD_ADDR(4)
74#define	FLD_NFS_C_CACHE_V	FIELD_ADDR(5)
75
76/* Server */
77#define	FLD_NFS_S_RPC_COUNTS	FIELD_ADDR(6)
78#define	FLD_NFS_S_RPC_COUNTS_V	FIELD_ADDR(7)
79#define	FLD_NFS_S_CACHE_STATS	FIELD_ADDR(8)
80#define	FLD_NFS_S_CACHE_STATS_V	FIELD_ADDR(9)
81#define	FLD_NFS_S_WRITES	FIELD_ADDR(10)
82#define	FLD_NFS_S_WRITES_V	FIELD_ADDR(11)
83
84/* Define views */
85field_def *view_nfs_0[] = {
86	FLD_NFS_C_RPC_COUNTS, FLD_NFS_C_RPC_COUNTS_V, FLD_NFS_C_RPC_INFO,
87	FLD_NFS_C_RPC_INFO_V, FLD_NFS_C_CACHE_INFO, FLD_NFS_C_CACHE_V ,NULL
88};
89
90field_def *view_nfs_1[] = {
91	FLD_NFS_S_RPC_COUNTS, FLD_NFS_S_RPC_COUNTS_V, FLD_NFS_S_CACHE_STATS,
92	FLD_NFS_S_CACHE_STATS_V, FLD_NFS_S_WRITES, FLD_NFS_S_WRITES_V, NULL
93};
94
95/* Define view managers */
96struct view_manager nfs_client_mgr = {
97	"Client", select_client, read_nfs, NULL, print_header,
98	print_client, keyboard_callback, NULL, NULL
99};
100
101struct view_manager nfs_server_mgr = {
102	"Server", select_server, read_nfs, NULL, print_header,
103	print_server, keyboard_callback, NULL, NULL
104};
105
106field_view views_nfs[] = {
107	{view_nfs_0, "nfsclient", '8', &nfs_client_mgr},
108	{view_nfs_1, "nfsserver", '9', &nfs_server_mgr},
109	{NULL, NULL, 0, NULL}
110};
111
112int
113select_client(void)
114{
115	num_disp = num_client;
116	return(0);
117}
118
119int
120select_server(void)
121{
122	num_disp = num_server;
123	return(0);
124}
125
126int
127initnfs(void)
128{
129	field_view *v;
130
131	for (v = views_nfs; v->name != NULL; v++)
132		add_view(v);
133
134	read_nfs();
135
136	return(0);
137}
138
139/*
140 * We get all the information in one go and don't care about
141 * server or client fields (those will be '0' if not applicable.
142 */
143int
144read_nfs(void)
145{
146	struct nfsstats *p = &nfsstats;
147	int mib[3];
148	size_t len = sizeof(*p);
149
150	mib[0] = CTL_VFS;
151	mib[1] = 2; /* NETDEV */
152	mib[2] = NFS_NFSSTATS;
153
154	if (sysctl(mib, 3, p, &len, NULL, 0) < 0)
155		return(-1);
156	else
157		return(0);
158}
159
160
161/*
162 * As we want a view with multiple columns, mixed with labels and values,
163 * we can't use the regular dance and have to use our own (looong) dance
164 * to build the layout.
165 */
166void
167print_client(void)
168{
169	print_fld_str(FLD_NFS_C_RPC_COUNTS, "Getattr");
170	print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V,
171	  nfsstats.rpccnt[NFSPROC_GETATTR]);
172	print_fld_str(FLD_NFS_C_RPC_INFO, "TimedOut");
173	print_fld_ssize(FLD_NFS_C_RPC_INFO_V, nfsstats.rpctimeouts);
174	print_fld_str(FLD_NFS_C_CACHE_INFO, "Attr Hits  ");
175	print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.attrcache_hits);
176	end_line();
177
178	print_fld_str(FLD_NFS_C_RPC_COUNTS, "Setattr");
179	print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V,
180	  nfsstats.rpccnt[NFSPROC_SETATTR]);
181	print_fld_str(FLD_NFS_C_RPC_INFO, "Invalid");
182	print_fld_ssize(FLD_NFS_C_RPC_INFO_V, nfsstats.rpcinvalid);
183	print_fld_str(FLD_NFS_C_CACHE_INFO, "Attr Misses");
184	print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.attrcache_misses);
185	end_line();
186
187	print_fld_str(FLD_NFS_C_RPC_COUNTS, "Lookup");
188	print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V,
189	  nfsstats.rpccnt[NFSPROC_LOOKUP]);
190	print_fld_str(FLD_NFS_C_RPC_INFO, "X Replies");
191	print_fld_ssize(FLD_NFS_C_RPC_INFO_V, nfsstats.rpcunexpected);
192	print_fld_str(FLD_NFS_C_CACHE_INFO, "Lkup Hits  ");
193	print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.lookupcache_hits);
194	end_line();
195
196	print_fld_str(FLD_NFS_C_RPC_COUNTS, "Readlink");
197	print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V,
198	  nfsstats.rpccnt[NFSPROC_READLINK]);
199	print_fld_str(FLD_NFS_C_RPC_INFO, "Retries");
200	print_fld_ssize(FLD_NFS_C_RPC_INFO_V, nfsstats.rpcretries);
201	print_fld_str(FLD_NFS_C_CACHE_INFO, "Lkup Misses  ");
202	print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.lookupcache_misses);
203	end_line();
204
205	print_fld_str(FLD_NFS_C_RPC_COUNTS, "Read");
206	print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V,
207	  nfsstats.rpccnt[NFSPROC_READ]);
208	print_fld_str(FLD_NFS_C_RPC_INFO, "Requests");
209	print_fld_ssize(FLD_NFS_C_RPC_INFO_V, nfsstats.rpcrequests);
210	print_fld_str(FLD_NFS_C_CACHE_INFO, "BioR Hits  ");
211	print_fld_ssize(FLD_NFS_C_CACHE_V,
212	  nfsstats.biocache_reads-nfsstats.read_bios);
213	end_line();
214
215	print_fld_str(FLD_NFS_C_RPC_COUNTS, "Write");
216	print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_WRITE]);
217	print_fld_str(FLD_NFS_C_RPC_INFO, "FrcSync");
218	print_fld_ssize(FLD_NFS_C_RPC_INFO_V, nfsstats.forcedsync);
219	print_fld_str(FLD_NFS_C_CACHE_INFO, "BioR Misses");
220	print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.read_bios);
221	end_line();
222
223	print_fld_str(FLD_NFS_C_RPC_COUNTS, "Create");
224	print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V,
225	  nfsstats.rpccnt[NFSPROC_CREATE]);
226	print_fld_str(FLD_NFS_C_CACHE_INFO, "BioW Hits  ");
227	print_fld_ssize(FLD_NFS_C_CACHE_V,
228	  nfsstats.biocache_writes-nfsstats.write_bios);
229	end_line();
230
231	print_fld_str(FLD_NFS_C_RPC_COUNTS, "Remove");
232	print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V,
233	  nfsstats.rpccnt[NFSPROC_REMOVE]);
234	print_fld_str(FLD_NFS_C_CACHE_INFO, "BioW Misses");
235	print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.write_bios);
236	end_line();
237
238	print_fld_str(FLD_NFS_C_RPC_COUNTS, "Rename");
239	print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V,
240	  nfsstats.rpccnt[NFSPROC_RENAME]);
241	print_fld_str(FLD_NFS_C_CACHE_INFO, "BioRL Hits  ");
242	print_fld_ssize(FLD_NFS_C_CACHE_V,
243	  nfsstats.biocache_readlinks-nfsstats.readlink_bios);
244	end_line();
245
246	print_fld_str(FLD_NFS_C_RPC_COUNTS, "Link");
247	print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_LINK]);
248	print_fld_str(FLD_NFS_C_CACHE_INFO, "BioRL Misses");
249	print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.readlink_bios);
250	end_line();
251
252	print_fld_str(FLD_NFS_C_RPC_COUNTS, "Symlink");
253	print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V,
254	  nfsstats.rpccnt[NFSPROC_SYMLINK]);
255	print_fld_str(FLD_NFS_C_CACHE_INFO, "BioD Hits  ");
256	print_fld_ssize(FLD_NFS_C_CACHE_V,
257	  nfsstats.biocache_readdirs-nfsstats.readdir_bios);
258	end_line();
259
260	print_fld_str(FLD_NFS_C_RPC_COUNTS, "Mkdir");
261	print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_MKDIR]);
262	print_fld_str(FLD_NFS_C_CACHE_INFO, "BioD Misses");
263	print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.readdir_bios);
264	end_line();
265
266	print_fld_str(FLD_NFS_C_RPC_COUNTS, "Rmdir");
267	print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_RMDIR]);
268	print_fld_str(FLD_NFS_C_CACHE_INFO, "DirE Hits  ");
269	print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.direofcache_hits);
270	end_line();
271
272	print_fld_str(FLD_NFS_C_RPC_COUNTS, "Readdir");
273	print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V,
274	  nfsstats.rpccnt[NFSPROC_READDIR]);
275	print_fld_str(FLD_NFS_C_CACHE_INFO, "DirE Misses");
276	print_fld_ssize(FLD_NFS_C_CACHE_V, nfsstats.direofcache_misses);
277	end_line();
278
279	print_fld_str(FLD_NFS_C_RPC_COUNTS, "RdirPlus");
280	print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V,
281	  nfsstats.rpccnt[NFSPROC_READDIRPLUS]);
282	end_line();
283
284	print_fld_str(FLD_NFS_C_RPC_COUNTS, "Access");
285	print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V,
286	  nfsstats.rpccnt[NFSPROC_ACCESS]);
287	end_line();
288
289	print_fld_str(FLD_NFS_C_RPC_COUNTS, "Mknod");
290	print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V, nfsstats.rpccnt[NFSPROC_MKNOD]);
291	end_line();
292
293	print_fld_str(FLD_NFS_C_RPC_COUNTS, "Fsstat");
294	print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V,
295	  nfsstats.rpccnt[NFSPROC_FSSTAT]);
296	end_line();
297
298	print_fld_str(FLD_NFS_C_RPC_COUNTS, "Fsinfo");
299	print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V,
300	  nfsstats.rpccnt[NFSPROC_FSINFO]);
301	end_line();
302
303	print_fld_str(FLD_NFS_C_RPC_COUNTS, "PathConf");
304	print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V,
305	  nfsstats.rpccnt[NFSPROC_PATHCONF]);
306	end_line();
307
308	print_fld_str(FLD_NFS_C_RPC_COUNTS, "Commit");
309	print_fld_ssize(FLD_NFS_C_RPC_COUNTS_V,
310	  nfsstats.rpccnt[NFSPROC_COMMIT]);
311	end_line();
312}
313
314void
315print_server(void)
316{
317	print_fld_str(FLD_NFS_S_RPC_COUNTS, "Getattr");
318	print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V,
319	  nfsstats.srvrpccnt[NFSPROC_GETATTR]);
320	print_fld_str(FLD_NFS_S_CACHE_STATS, "Inprog");
321	print_fld_ssize(FLD_NFS_S_CACHE_STATS_V, nfsstats.srvcache_inproghits);
322	print_fld_str(FLD_NFS_S_WRITES, "WriteOps");
323	print_fld_ssize(FLD_NFS_S_WRITES_V, nfsstats.srvvop_writes);
324	end_line();
325
326	print_fld_str(FLD_NFS_S_RPC_COUNTS, "Setattr");
327	print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V,
328	  nfsstats.srvrpccnt[NFSPROC_SETATTR]);
329	print_fld_str(FLD_NFS_S_CACHE_STATS, "Idem");
330	print_fld_ssize(FLD_NFS_S_CACHE_STATS_V,
331	  nfsstats.srvcache_idemdonehits);
332	print_fld_str(FLD_NFS_S_WRITES, "WriteRPC");
333	print_fld_ssize(FLD_NFS_S_WRITES_V, nfsstats.srvrpccnt[NFSPROC_WRITE]);
334	end_line();
335
336	print_fld_str(FLD_NFS_S_RPC_COUNTS, "Lookup");
337	print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V,
338	  nfsstats.srvrpccnt[NFSPROC_LOOKUP]);
339	print_fld_str(FLD_NFS_S_CACHE_STATS, "Non-idem");
340	print_fld_ssize(FLD_NFS_S_CACHE_STATS_V,
341	  nfsstats.srvcache_nonidemdonehits);
342	print_fld_str(FLD_NFS_S_WRITES, "Opsaved");
343	print_fld_ssize(FLD_NFS_S_WRITES_V,
344	  nfsstats.srvrpccnt[NFSPROC_WRITE] - nfsstats.srvvop_writes);
345	end_line();
346
347	print_fld_str(FLD_NFS_S_RPC_COUNTS, "Readlink");
348	print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V,
349	  nfsstats.srvrpccnt[NFSPROC_READLINK]);
350	print_fld_str(FLD_NFS_S_CACHE_STATS, "Misses");
351	print_fld_ssize(FLD_NFS_S_CACHE_STATS_V, nfsstats.srvcache_misses);
352	end_line();
353
354	print_fld_str(FLD_NFS_S_RPC_COUNTS, "Read");
355	print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V,
356	  nfsstats.srvrpccnt[NFSPROC_READ]);
357	end_line();
358
359	print_fld_str(FLD_NFS_S_RPC_COUNTS, "Write");
360	print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V,
361	  nfsstats.srvrpccnt[NFSPROC_WRITE]);
362	end_line();
363
364	print_fld_str(FLD_NFS_S_RPC_COUNTS, "Create");
365	print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V,
366	  nfsstats.srvrpccnt[NFSPROC_CREATE]);
367	end_line();
368
369	print_fld_str(FLD_NFS_S_RPC_COUNTS, "Remove");
370	print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V,
371	  nfsstats.srvrpccnt[NFSPROC_REMOVE]);
372	end_line();
373
374	print_fld_str(FLD_NFS_S_RPC_COUNTS, "Rename");
375	print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V,
376	  nfsstats.srvrpccnt[NFSPROC_RENAME]);
377	end_line();
378
379	print_fld_str(FLD_NFS_S_RPC_COUNTS, "Link");
380	print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V,
381	  nfsstats.srvrpccnt[NFSPROC_LINK]);
382	end_line();
383
384	print_fld_str(FLD_NFS_S_RPC_COUNTS, "Symlink");
385	print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V,
386	  nfsstats.srvrpccnt[NFSPROC_SYMLINK]);
387	end_line();
388
389	print_fld_str(FLD_NFS_S_RPC_COUNTS, "Mkdir");
390	print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V,
391	  nfsstats.srvrpccnt[NFSPROC_MKDIR]);
392	end_line();
393
394	print_fld_str(FLD_NFS_S_RPC_COUNTS, "Rmdir");
395	print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V,
396	  nfsstats.srvrpccnt[NFSPROC_RMDIR]);
397	end_line();
398
399	print_fld_str(FLD_NFS_S_RPC_COUNTS, "Readdir");
400	print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V,
401	  nfsstats.srvrpccnt[NFSPROC_READDIR]);
402	end_line();
403
404	print_fld_str(FLD_NFS_S_RPC_COUNTS, "RdirPlus");
405	print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V,
406	  nfsstats.srvrpccnt[NFSPROC_READDIRPLUS]);
407	end_line();
408
409	print_fld_str(FLD_NFS_S_RPC_COUNTS, "Access");
410	print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V,
411	  nfsstats.srvrpccnt[NFSPROC_ACCESS]);
412	end_line();
413
414	print_fld_str(FLD_NFS_S_RPC_COUNTS, "Mknod");
415	print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V,
416	  nfsstats.srvrpccnt[NFSPROC_MKNOD]);
417	end_line();
418
419	print_fld_str(FLD_NFS_S_RPC_COUNTS, "Fsstat");
420	print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V,
421	  nfsstats.srvrpccnt[NFSPROC_FSSTAT]);
422	end_line();
423
424	print_fld_str(FLD_NFS_S_RPC_COUNTS, "Fsinfo");
425	print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V,
426	  nfsstats.srvrpccnt[NFSPROC_FSINFO]);
427	end_line();
428
429	print_fld_str(FLD_NFS_S_RPC_COUNTS, "PathConf");
430	print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V,
431	  nfsstats.srvrpccnt[NFSPROC_PATHCONF]);
432	end_line();
433
434	print_fld_str(FLD_NFS_S_RPC_COUNTS, "Commit");
435	print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V,
436	  nfsstats.srvrpccnt[NFSPROC_COMMIT]);
437	end_line();
438
439	/* The following end_line() creates two seperate blocks on the screen */
440	end_line();
441
442	print_fld_str(FLD_NFS_S_RPC_COUNTS, "Ret-Failed");
443	print_fld_ssize(FLD_NFS_S_RPC_COUNTS_V, nfsstats.srvrpc_errs);
444	print_fld_str(FLD_NFS_S_CACHE_STATS, "Faults");
445	print_fld_ssize(FLD_NFS_S_CACHE_STATS_V, nfsstats.srv_errs);
446	end_line();
447}
448