xref: /original-bsd/usr.bin/nfsstat/nfsstat.c (revision ee1b0b6c)
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.4 (Berkeley) 05/14/90";
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("Rpc Counts:\n");
162 	printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
163 		"Getattr", "Setattr", "Lookup", "Readlink", "Read",
164 		"Write", "Create", "Remove");
165 	printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
166 		nfsstats.rpccnt[1],
167 		nfsstats.rpccnt[2],
168 		nfsstats.rpccnt[4],
169 		nfsstats.rpccnt[5],
170 		nfsstats.rpccnt[6],
171 		nfsstats.rpccnt[8],
172 		nfsstats.rpccnt[9],
173 		nfsstats.rpccnt[10]);
174 	printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
175 		"Rename", "Link", "Symlink", "Mkdir", "Rmdir",
176 		"Readdir", "Statfs");
177 	printf("%9d %9d %9d %9d %9d %9d %9d\n",
178 		nfsstats.rpccnt[11],
179 		nfsstats.rpccnt[12],
180 		nfsstats.rpccnt[13],
181 		nfsstats.rpccnt[14],
182 		nfsstats.rpccnt[15],
183 		nfsstats.rpccnt[16],
184 		nfsstats.rpccnt[17]);
185 	printf("Rpc Info:\n");
186 	printf("%9.9s %9.9s %9.9s %9.9s %9.9s\n",
187 		"TimedOut", "Invalid", "X Replies", "Retries", "Requests");
188 	printf("%9d %9d %9d %9d %9d\n",
189 		nfsstats.rpctimeouts,
190 		nfsstats.rpcinvalid,
191 		nfsstats.rpcunexpected,
192 		nfsstats.rpcretries,
193 		nfsstats.rpcrequests);
194 	printf("Cache Info:\n");
195 	printf("%9.9s %9.9s %9.9s %9.9s",
196 		"Attr Hits", "Misses", "Lkup Hits", "Misses");
197 	printf(" %9.9s %9.9s %9.9s %9.9s\n",
198 		"BioR Hits", "Misses", "BioW Hits", "Misses");
199 	printf("%9d %9d %9d %9d",
200 		nfsstats.attrcache_hits, nfsstats.attrcache_misses,
201 		nfsstats.lookupcache_hits, nfsstats.lookupcache_misses);
202 	printf(" %9d %9d %9d %9d\n",
203 		nfsstats.biocache_reads-nfsstats.read_bios,
204 		nfsstats.read_bios,
205 		nfsstats.biocache_writes-nfsstats.write_bios,
206 		nfsstats.write_bios);
207 	printf("%9.9s %9.9s %9.9s %9.9s",
208 		"BioRLHits", "Misses", "BioD Hits", "Misses");
209 	printf(" %9.9s %9.9s\n", "DirE Hits", "Misses");
210 	printf("%9d %9d %9d %9d",
211 		nfsstats.biocache_readlinks-nfsstats.readlink_bios,
212 		nfsstats.readlink_bios,
213 		nfsstats.biocache_readdirs-nfsstats.readdir_bios,
214 		nfsstats.readdir_bios);
215 	printf(" %9d %9d\n",
216 		nfsstats.direofcache_hits, nfsstats.direofcache_misses);
217 	printf("\nServer Info:\n");
218 	printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
219 		"Getattr", "Setattr", "Lookup", "Readlink", "Read",
220 		"Write", "Create", "Remove");
221 	printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
222 		nfsstats.srvrpccnt[1],
223 		nfsstats.srvrpccnt[2],
224 		nfsstats.srvrpccnt[4],
225 		nfsstats.srvrpccnt[5],
226 		nfsstats.srvrpccnt[6],
227 		nfsstats.srvrpccnt[8],
228 		nfsstats.srvrpccnt[9],
229 		nfsstats.srvrpccnt[10]);
230 	printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
231 		"Rename", "Link", "Symlink", "Mkdir", "Rmdir",
232 		"Readdir", "Statfs");
233 	printf("%9d %9d %9d %9d %9d %9d %9d\n",
234 		nfsstats.srvrpccnt[11],
235 		nfsstats.srvrpccnt[12],
236 		nfsstats.srvrpccnt[13],
237 		nfsstats.srvrpccnt[14],
238 		nfsstats.srvrpccnt[15],
239 		nfsstats.srvrpccnt[16],
240 		nfsstats.srvrpccnt[17]);
241 	printf("Server Ret-Failed\n");
242 	printf("%17d\n", nfsstats.srvrpc_errs);
243 	printf("Server Faults\n");
244 	printf("%13d\n", nfsstats.srv_errs);
245 	printf("Server Cache Stats:\n");
246 	printf("%9.9s %9.9s %9.9s %9.9s\n",
247 		"Inprog", "Idem", "Non-idem", "Misses");
248 	printf("%9d %9d %9d %9d\n",
249 		nfsstats.srvcache_inproghits,
250 		nfsstats.srvcache_idemdonehits,
251 		nfsstats.srvcache_nonidemdonehits,
252 		nfsstats.srvcache_misses);
253 }
254 
255 u_char	signalled;			/* set if alarm goes off "early" */
256 
257 /*
258  * Print a running summary of nfs statistics.
259  * Repeat display every interval seconds, showing statistics
260  * collected over that interval.  Assumes that interval is non-zero.
261  * First line printed at top of screen is always cumulative.
262  */
263 sidewaysintpr(interval, off)
264 	unsigned interval;
265 	off_t off;
266 {
267 	struct nfsstats nfsstats, lastst;
268 	register int line;
269 	int oldmask;
270 	int catchalarm();
271 
272 	klseek(kmem, off, 0);
273 
274 	(void)signal(SIGALRM, catchalarm);
275 	signalled = NO;
276 	(void)alarm(interval);
277 	bzero((caddr_t)&lastst, sizeof(lastst));
278 banner:
279 	printf("        %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s\n",
280 		"Getattr", "Lookup", "Readlink", "Read",
281 		"Write", "Rename", "Link", "Readdir");
282 	fflush(stdout);
283 	line = 0;
284 loop:
285 	klseek(kmem, off, 0);
286 	read(kmem, (char *)&nfsstats, sizeof nfsstats);
287 	printf("Client: %8d %8d %8d %8d %8d %8d %8d %8d\n",
288 		nfsstats.rpccnt[1]-lastst.rpccnt[1],
289 		nfsstats.rpccnt[4]-lastst.rpccnt[4],
290 		nfsstats.rpccnt[5]-lastst.rpccnt[5],
291 		nfsstats.rpccnt[6]-lastst.rpccnt[6],
292 		nfsstats.rpccnt[8]-lastst.rpccnt[8],
293 		nfsstats.rpccnt[11]-lastst.rpccnt[11],
294 		nfsstats.rpccnt[12]-lastst.rpccnt[12],
295 		nfsstats.rpccnt[16]-lastst.rpccnt[16]);
296 	printf("Server: %8d %8d %8d %8d %8d %8d %8d %8d\n",
297 		nfsstats.srvrpccnt[1]-lastst.srvrpccnt[1],
298 		nfsstats.srvrpccnt[4]-lastst.srvrpccnt[4],
299 		nfsstats.srvrpccnt[5]-lastst.srvrpccnt[5],
300 		nfsstats.srvrpccnt[6]-lastst.srvrpccnt[6],
301 		nfsstats.srvrpccnt[8]-lastst.srvrpccnt[8],
302 		nfsstats.srvrpccnt[11]-lastst.srvrpccnt[11],
303 		nfsstats.srvrpccnt[12]-lastst.srvrpccnt[12],
304 		nfsstats.srvrpccnt[16]-lastst.srvrpccnt[16]);
305 	lastst = nfsstats;
306 	fflush(stdout);
307 	line++;
308 	oldmask = sigblock(sigmask(SIGALRM));
309 	if (! signalled) {
310 		sigpause(0);
311 	}
312 	sigsetmask(oldmask);
313 	signalled = NO;
314 	(void)alarm(interval);
315 	if (line == 21)
316 		goto banner;
317 	goto loop;
318 	/*NOTREACHED*/
319 }
320 
321 /*
322  * Called if an interval expires before sidewaysintpr has completed a loop.
323  * Sets a flag to not wait for the alarm.
324  */
325 catchalarm()
326 {
327 	signalled = YES;
328 }
329