xref: /original-bsd/usr.bin/nfsstat/nfsstat.c (revision c0f053f7)
1 /*
2  * Copyright (c) 1983, 1989 Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Rick Macklem at The University of Guelph.
7  *
8  * Redistribution and use in source and binary forms are permitted
9  * provided that the above copyright notice and this paragraph are
10  * duplicated in all such forms and that any documentation,
11  * advertising materials, and other materials related to such
12  * distribution and use acknowledge that the software was developed
13  * by the University of California, Berkeley.  The name of the
14  * University may not be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19  */
20 
21 #ifndef lint
22 char copyright[] =
23 "@(#) Copyright (c) 1983, 1989 Regents of the University of California.\n\
24  All rights reserved.\n";
25 #endif /* not lint */
26 
27 #ifndef lint
28 static char sccsid[] = "@(#)nfsstat.c	5.1 (Berkeley) 07/16/89";
29 #endif /* not lint */
30 
31 #include <sys/param.h>
32 #include <sys/vmmac.h>
33 #include <sys/file.h>
34 #include <machine/pte.h>
35 #include <sys/namei.h>
36 #include <sys/mount.h>
37 #include <nfs/nfsv2.h>
38 #include <nfs/nfs.h>
39 #include <ctype.h>
40 #include <errno.h>
41 #include <nlist.h>
42 #include <stdio.h>
43 #include <paths.h>
44 
45 #define	YES	1
46 #define	NO	0
47 
48 struct nlist nl[] = {
49 #define	N_NFSSTAT	0
50 	{ "_nfsstats" },
51 #define	N_SYSMAP	1
52 	{ "_Sysmap" },
53 #define	N_SYSSIZE	2
54 	{ "_Syssize" },
55 	"",
56 };
57 
58 struct	pte *Sysmap;
59 
60 char	*system = _PATH_UNIX;
61 char	*kmemf = _PATH_KMEM;
62 int	kmem;
63 int	kflag;
64 int	interval;
65 
66 extern	char *malloc();
67 extern	off_t lseek();
68 
69 main(argc, argv)
70 	int argc;
71 	char *argv[];
72 {
73 	int ch;
74 
75 	interval = 0;
76 	argc--;
77 	argv++;
78 	if (argc > 0) {
79 		interval = atoi(argv[0]);
80 		if (interval <= 0)
81 			usage();
82 		argv++, argc--;
83 		if (argc > 0) {
84 			system = *argv;
85 			argv++, argc--;
86 			if (argc > 0) {
87 				kmemf = *argv;
88 				kflag++;
89 			}
90 		}
91 	}
92 	if (nlist(system, nl) < 0 || nl[0].n_type == 0) {
93 		fprintf(stderr, "%s: no namelist\n", system);
94 		exit(1);
95 	}
96 	kmem = open(kmemf, O_RDONLY);
97 	if (kmem < 0) {
98 		perror(kmemf);
99 		exit(1);
100 	}
101 	if (kflag) {
102 		off_t off;
103 
104 		Sysmap = (struct pte *)
105 		   malloc((u_int)(nl[N_SYSSIZE].n_value * sizeof(struct pte)));
106 		if (!Sysmap) {
107 			fputs("nfsstat: can't get memory for Sysmap.\n", stderr);
108 			exit(1);
109 		}
110 		off = nl[N_SYSMAP].n_value & ~KERNBASE;
111 		(void)lseek(kmem, off, L_SET);
112 		(void)read(kmem, (char *)Sysmap,
113 			(int)(nl[N_SYSSIZE].n_value * sizeof(struct pte)));
114 	}
115 	intpr(interval, nl[N_NFSSTAT].n_value);
116 	exit(0);
117 }
118 
119 /*
120  * Seek into the kernel for a value.
121  */
122 off_t
123 klseek(fd, base, off)
124 	int fd, off;
125 	off_t base;
126 {
127 	if (kflag) {
128 		/* get kernel pte */
129 		base &= ~KERNBASE;
130 		base = ctob(Sysmap[btop(base)].pg_pfnum) + (base & PGOFSET);
131 	}
132 	return (lseek(fd, base, off));
133 }
134 
135 usage()
136 {
137 	fputs("Usage: nfsstat [interval [ system [ corefile ] ] ]\n", stderr);
138 	exit(1);
139 }
140 
141 /*
142  * Print a description of the network interfaces.
143  */
144 intpr(interval, nfsstataddr)
145 	int interval;
146 	off_t nfsstataddr;
147 {
148 	struct nfsstats nfsstats;
149 
150 	if (nfsstataddr == 0) {
151 		printf("nfsstat: symbol not defined\n");
152 		return;
153 	}
154 	if (interval) {
155 		sidewaysintpr((unsigned)interval, nfsstataddr);
156 		return;
157 	}
158 	klseek(kmem, nfsstataddr, 0);
159 	read(kmem, (char *)&nfsstats, sizeof(struct nfsstats));
160 	printf("Client Info:\n");
161 	printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
162 		"Getattr", "Setattr", "Lookup", "Readlink", "Read",
163 		"Write", "Create", "Remove");
164 	printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
165 		nfsstats.rpccnt[1],
166 		nfsstats.rpccnt[2],
167 		nfsstats.rpccnt[4],
168 		nfsstats.rpccnt[5],
169 		nfsstats.rpccnt[6],
170 		nfsstats.rpccnt[8],
171 		nfsstats.rpccnt[9],
172 		nfsstats.rpccnt[10]);
173 	printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
174 		"Rename", "Link", "Symlink", "Mkdir", "Rmdir",
175 		"Readdir", "Statfs");
176 	printf("%9d %9d %9d %9d %9d %9d %9d\n",
177 		nfsstats.rpccnt[11],
178 		nfsstats.rpccnt[12],
179 		nfsstats.rpccnt[13],
180 		nfsstats.rpccnt[14],
181 		nfsstats.rpccnt[15],
182 		nfsstats.rpccnt[16],
183 		nfsstats.rpccnt[17]);
184 	printf("Rpc retries\n%11d\n",nfsstats.rpcretries);
185 	printf("Cache Info:\n");
186 	printf("%9.9s %9.9s %9.9s %9.9s\n",
187 		"Attr Hits", "Misses", "Lkup Hits", "Misses");
188 	printf("%9d %9d %9d %9d\n",
189 		nfsstats.attrcache_hits, nfsstats.attrcache_misses,
190 		nfsstats.lookupcache_hits, nfsstats.lookupcache_misses);
191 	printf("Server Info:\n");
192 	printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
193 		"Getattr", "Setattr", "Lookup", "Readlink", "Read",
194 		"Write", "Create", "Remove");
195 	printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
196 		nfsstats.srvrpccnt[1],
197 		nfsstats.srvrpccnt[2],
198 		nfsstats.srvrpccnt[4],
199 		nfsstats.srvrpccnt[5],
200 		nfsstats.srvrpccnt[6],
201 		nfsstats.srvrpccnt[8],
202 		nfsstats.srvrpccnt[9],
203 		nfsstats.srvrpccnt[10]);
204 	printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
205 		"Rename", "Link", "Symlink", "Mkdir", "Rmdir",
206 		"Readdir", "Statfs");
207 	printf("%9d %9d %9d %9d %9d %9d %9d\n",
208 		nfsstats.srvrpccnt[11],
209 		nfsstats.srvrpccnt[12],
210 		nfsstats.srvrpccnt[13],
211 		nfsstats.srvrpccnt[14],
212 		nfsstats.srvrpccnt[15],
213 		nfsstats.srvrpccnt[16],
214 		nfsstats.srvrpccnt[17]);
215 	printf("Server Rpc Errors\n");
216 	printf("%17d\n", nfsstats.srvrpc_errs);
217 	printf("Server Faults\n");
218 	printf("%13d\n", nfsstats.srv_errs);
219 }
220 
221 u_char	signalled;			/* set if alarm goes off "early" */
222 
223 /*
224  * Print a running summary of nfs statistics.
225  * Repeat display every interval seconds, showing statistics
226  * collected over that interval.  Assumes that interval is non-zero.
227  * First line printed at top of screen is always cumulative.
228  */
229 sidewaysintpr(interval, off)
230 	unsigned interval;
231 	off_t off;
232 {
233 	struct nfsstats nfsstats, lastst;
234 	register int line;
235 	int oldmask;
236 	int catchalarm();
237 
238 	klseek(kmem, off, 0);
239 
240 	(void)signal(SIGALRM, catchalarm);
241 	signalled = NO;
242 	(void)alarm(interval);
243 	bzero((caddr_t)&lastst, sizeof(lastst));
244 banner:
245 	printf("        %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s\n",
246 		"Getattr", "Lookup", "Readlink", "Read",
247 		"Write", "Rename", "Link", "Readdir");
248 	fflush(stdout);
249 	line = 0;
250 loop:
251 	klseek(kmem, off, 0);
252 	read(kmem, (char *)&nfsstats, sizeof nfsstats);
253 	printf("Client: %8d %8d %8d %8d %8d %8d %8d %8d\n",
254 		nfsstats.rpccnt[1]-lastst.rpccnt[1],
255 		nfsstats.rpccnt[4]-lastst.rpccnt[4],
256 		nfsstats.rpccnt[5]-lastst.rpccnt[5],
257 		nfsstats.rpccnt[6]-lastst.rpccnt[6],
258 		nfsstats.rpccnt[8]-lastst.rpccnt[8],
259 		nfsstats.rpccnt[11]-lastst.rpccnt[11],
260 		nfsstats.rpccnt[12]-lastst.rpccnt[12],
261 		nfsstats.rpccnt[16]-lastst.rpccnt[16]);
262 	printf("Server: %8d %8d %8d %8d %8d %8d %8d %8d\n",
263 		nfsstats.srvrpccnt[1]-lastst.srvrpccnt[1],
264 		nfsstats.srvrpccnt[4]-lastst.srvrpccnt[4],
265 		nfsstats.srvrpccnt[5]-lastst.srvrpccnt[5],
266 		nfsstats.srvrpccnt[6]-lastst.srvrpccnt[6],
267 		nfsstats.srvrpccnt[8]-lastst.srvrpccnt[8],
268 		nfsstats.srvrpccnt[11]-lastst.srvrpccnt[11],
269 		nfsstats.srvrpccnt[12]-lastst.srvrpccnt[12],
270 		nfsstats.srvrpccnt[16]-lastst.srvrpccnt[16]);
271 	lastst = nfsstats;
272 	fflush(stdout);
273 	line++;
274 	oldmask = sigblock(sigmask(SIGALRM));
275 	if (! signalled) {
276 		sigpause(0);
277 	}
278 	sigsetmask(oldmask);
279 	signalled = NO;
280 	(void)alarm(interval);
281 	if (line == 21)
282 		goto banner;
283 	goto loop;
284 	/*NOTREACHED*/
285 }
286 
287 /*
288  * Called if an interval expires before sidewaysintpr has completed a loop.
289  * Sets a flag to not wait for the alarm.
290  */
291 catchalarm()
292 {
293 	signalled = YES;
294 }
295