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