xref: /original-bsd/usr.bin/nfsstat/nfsstat.c (revision 7f22226e)
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  * %sccs.include.redist.c%
9  */
10 
11 #ifndef lint
12 char copyright[] =
13 "@(#) Copyright (c) 1983, 1989 Regents of the University of California.\n\
14  All rights reserved.\n";
15 #endif /* not lint */
16 
17 #ifndef lint
18 static char sccsid[] = "@(#)nfsstat.c	5.6 (Berkeley) 03/01/91";
19 #endif /* not lint */
20 
21 #include <sys/param.h>
22 #include <sys/vmmac.h>
23 #include <sys/file.h>
24 #include <machine/pte.h>
25 #include <sys/namei.h>
26 #include <sys/mount.h>
27 #include <nfs/nfsv2.h>
28 #include <nfs/nfs.h>
29 #include <ctype.h>
30 #include <errno.h>
31 #include <nlist.h>
32 #include <stdio.h>
33 #include <paths.h>
34 
35 #define	YES	1
36 #define	NO	0
37 
38 struct nlist nl[] = {
39 #define	N_NFSSTAT	0
40 	{ "_nfsstats" },
41 #define	N_SYSMAP	1
42 	{ "_Sysmap" },
43 #define	N_SYSSIZE	2
44 	{ "_Syssize" },
45 	"",
46 };
47 
48 struct	pte *Sysmap;
49 
50 char	*system = _PATH_UNIX;
51 char	*kmemf = _PATH_KMEM;
52 int	kmem;
53 int	kflag;
54 int	interval;
55 
56 extern	char *malloc();
57 extern	off_t lseek();
58 
59 main(argc, argv)
60 	int argc;
61 	char *argv[];
62 {
63 	int ch;
64 
65 	interval = 0;
66 	argc--;
67 	argv++;
68 	if (argc > 0) {
69 		interval = atoi(argv[0]);
70 		if (interval <= 0)
71 			usage();
72 		argv++, argc--;
73 		if (argc > 0) {
74 			system = *argv;
75 			argv++, argc--;
76 			if (argc > 0) {
77 				kmemf = *argv;
78 				kflag++;
79 			}
80 		}
81 	}
82 	if (nlist(system, nl) < 0 || nl[0].n_type == 0) {
83 		fprintf(stderr, "%s: no namelist\n", system);
84 		exit(1);
85 	}
86 	kmem = open(kmemf, O_RDONLY);
87 	if (kmem < 0) {
88 		perror(kmemf);
89 		exit(1);
90 	}
91 	if (kflag) {
92 		off_t off;
93 
94 		Sysmap = (struct pte *)
95 		   malloc((u_int)(nl[N_SYSSIZE].n_value * sizeof(struct pte)));
96 		if (!Sysmap) {
97 			fputs("nfsstat: can't get memory for Sysmap.\n", stderr);
98 			exit(1);
99 		}
100 		off = nl[N_SYSMAP].n_value & ~KERNBASE;
101 		(void)lseek(kmem, off, L_SET);
102 		(void)read(kmem, (char *)Sysmap,
103 			(int)(nl[N_SYSSIZE].n_value * sizeof(struct pte)));
104 	}
105 	intpr(interval, nl[N_NFSSTAT].n_value);
106 	exit(0);
107 }
108 
109 /*
110  * Seek into the kernel for a value.
111  */
112 off_t
113 klseek(fd, base, off)
114 	int fd, off;
115 	off_t base;
116 {
117 	if (kflag) {
118 		/* get kernel pte */
119 		base &= ~KERNBASE;
120 		base = ctob(Sysmap[btop(base)].pg_pfnum) + (base & PGOFSET);
121 	}
122 	return (lseek(fd, base, off));
123 }
124 
125 usage()
126 {
127 	fputs("Usage: nfsstat [interval [ system [ corefile ] ] ]\n", stderr);
128 	exit(1);
129 }
130 
131 /*
132  * Print a description of the network interfaces.
133  */
134 intpr(interval, nfsstataddr)
135 	int interval;
136 	off_t nfsstataddr;
137 {
138 	struct nfsstats nfsstats;
139 
140 	if (nfsstataddr == 0) {
141 		printf("nfsstat: symbol not defined\n");
142 		return;
143 	}
144 	if (interval) {
145 		sidewaysintpr((unsigned)interval, nfsstataddr);
146 		return;
147 	}
148 	klseek(kmem, nfsstataddr, 0);
149 	read(kmem, (char *)&nfsstats, sizeof(struct nfsstats));
150 	printf("Client Info:\n");
151 	printf("Rpc Counts:\n");
152 	printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
153 		"Getattr", "Setattr", "Lookup", "Readlink", "Read",
154 		"Write", "Create", "Remove");
155 	printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
156 		nfsstats.rpccnt[1],
157 		nfsstats.rpccnt[2],
158 		nfsstats.rpccnt[4],
159 		nfsstats.rpccnt[5],
160 		nfsstats.rpccnt[6],
161 		nfsstats.rpccnt[8],
162 		nfsstats.rpccnt[9],
163 		nfsstats.rpccnt[10]);
164 	printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
165 		"Rename", "Link", "Symlink", "Mkdir", "Rmdir",
166 		"Readdir", "Statfs");
167 	printf("%9d %9d %9d %9d %9d %9d %9d\n",
168 		nfsstats.rpccnt[11],
169 		nfsstats.rpccnt[12],
170 		nfsstats.rpccnt[13],
171 		nfsstats.rpccnt[14],
172 		nfsstats.rpccnt[15],
173 		nfsstats.rpccnt[16],
174 		nfsstats.rpccnt[17]);
175 	printf("Rpc Info:\n");
176 	printf("%9.9s %9.9s %9.9s %9.9s %9.9s\n",
177 		"TimedOut", "Invalid", "X Replies", "Retries", "Requests");
178 	printf("%9d %9d %9d %9d %9d\n",
179 		nfsstats.rpctimeouts,
180 		nfsstats.rpcinvalid,
181 		nfsstats.rpcunexpected,
182 		nfsstats.rpcretries,
183 		nfsstats.rpcrequests);
184 	printf("Cache Info:\n");
185 	printf("%9.9s %9.9s %9.9s %9.9s",
186 		"Attr Hits", "Misses", "Lkup Hits", "Misses");
187 	printf(" %9.9s %9.9s %9.9s %9.9s\n",
188 		"BioR Hits", "Misses", "BioW Hits", "Misses");
189 	printf("%9d %9d %9d %9d",
190 		nfsstats.attrcache_hits, nfsstats.attrcache_misses,
191 		nfsstats.lookupcache_hits, nfsstats.lookupcache_misses);
192 	printf(" %9d %9d %9d %9d\n",
193 		nfsstats.biocache_reads-nfsstats.read_bios,
194 		nfsstats.read_bios,
195 		nfsstats.biocache_writes-nfsstats.write_bios,
196 		nfsstats.write_bios);
197 	printf("%9.9s %9.9s %9.9s %9.9s",
198 		"BioRLHits", "Misses", "BioD Hits", "Misses");
199 	printf(" %9.9s %9.9s\n", "DirE Hits", "Misses");
200 	printf("%9d %9d %9d %9d",
201 		nfsstats.biocache_readlinks-nfsstats.readlink_bios,
202 		nfsstats.readlink_bios,
203 		nfsstats.biocache_readdirs-nfsstats.readdir_bios,
204 		nfsstats.readdir_bios);
205 	printf(" %9d %9d\n",
206 		nfsstats.direofcache_hits, nfsstats.direofcache_misses);
207 	printf("\nServer Info:\n");
208 	printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
209 		"Getattr", "Setattr", "Lookup", "Readlink", "Read",
210 		"Write", "Create", "Remove");
211 	printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
212 		nfsstats.srvrpccnt[1],
213 		nfsstats.srvrpccnt[2],
214 		nfsstats.srvrpccnt[4],
215 		nfsstats.srvrpccnt[5],
216 		nfsstats.srvrpccnt[6],
217 		nfsstats.srvrpccnt[8],
218 		nfsstats.srvrpccnt[9],
219 		nfsstats.srvrpccnt[10]);
220 	printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
221 		"Rename", "Link", "Symlink", "Mkdir", "Rmdir",
222 		"Readdir", "Statfs");
223 	printf("%9d %9d %9d %9d %9d %9d %9d\n",
224 		nfsstats.srvrpccnt[11],
225 		nfsstats.srvrpccnt[12],
226 		nfsstats.srvrpccnt[13],
227 		nfsstats.srvrpccnt[14],
228 		nfsstats.srvrpccnt[15],
229 		nfsstats.srvrpccnt[16],
230 		nfsstats.srvrpccnt[17]);
231 	printf("Server Ret-Failed\n");
232 	printf("%17d\n", nfsstats.srvrpc_errs);
233 	printf("Server Faults\n");
234 	printf("%13d\n", nfsstats.srv_errs);
235 	printf("Server Cache Stats:\n");
236 	printf("%9.9s %9.9s %9.9s %9.9s\n",
237 		"Inprog", "Idem", "Non-idem", "Misses");
238 	printf("%9d %9d %9d %9d\n",
239 		nfsstats.srvcache_inproghits,
240 		nfsstats.srvcache_idemdonehits,
241 		nfsstats.srvcache_nonidemdonehits,
242 		nfsstats.srvcache_misses);
243 }
244 
245 u_char	signalled;			/* set if alarm goes off "early" */
246 
247 /*
248  * Print a running summary of nfs statistics.
249  * Repeat display every interval seconds, showing statistics
250  * collected over that interval.  Assumes that interval is non-zero.
251  * First line printed at top of screen is always cumulative.
252  */
253 sidewaysintpr(interval, off)
254 	unsigned interval;
255 	off_t off;
256 {
257 	struct nfsstats nfsstats, lastst;
258 	register int line;
259 	int oldmask;
260 	void catchalarm();
261 
262 	klseek(kmem, off, 0);
263 
264 	(void)signal(SIGALRM, catchalarm);
265 	signalled = NO;
266 	(void)alarm(interval);
267 	bzero((caddr_t)&lastst, sizeof(lastst));
268 banner:
269 	printf("        %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s\n",
270 		"Getattr", "Lookup", "Readlink", "Read",
271 		"Write", "Rename", "Link", "Readdir");
272 	fflush(stdout);
273 	line = 0;
274 loop:
275 	klseek(kmem, off, 0);
276 	read(kmem, (char *)&nfsstats, sizeof nfsstats);
277 	printf("Client: %8d %8d %8d %8d %8d %8d %8d %8d\n",
278 		nfsstats.rpccnt[1]-lastst.rpccnt[1],
279 		nfsstats.rpccnt[4]-lastst.rpccnt[4],
280 		nfsstats.rpccnt[5]-lastst.rpccnt[5],
281 		nfsstats.rpccnt[6]-lastst.rpccnt[6],
282 		nfsstats.rpccnt[8]-lastst.rpccnt[8],
283 		nfsstats.rpccnt[11]-lastst.rpccnt[11],
284 		nfsstats.rpccnt[12]-lastst.rpccnt[12],
285 		nfsstats.rpccnt[16]-lastst.rpccnt[16]);
286 	printf("Server: %8d %8d %8d %8d %8d %8d %8d %8d\n",
287 		nfsstats.srvrpccnt[1]-lastst.srvrpccnt[1],
288 		nfsstats.srvrpccnt[4]-lastst.srvrpccnt[4],
289 		nfsstats.srvrpccnt[5]-lastst.srvrpccnt[5],
290 		nfsstats.srvrpccnt[6]-lastst.srvrpccnt[6],
291 		nfsstats.srvrpccnt[8]-lastst.srvrpccnt[8],
292 		nfsstats.srvrpccnt[11]-lastst.srvrpccnt[11],
293 		nfsstats.srvrpccnt[12]-lastst.srvrpccnt[12],
294 		nfsstats.srvrpccnt[16]-lastst.srvrpccnt[16]);
295 	lastst = nfsstats;
296 	fflush(stdout);
297 	line++;
298 	oldmask = sigblock(sigmask(SIGALRM));
299 	if (! signalled) {
300 		sigpause(0);
301 	}
302 	sigsetmask(oldmask);
303 	signalled = NO;
304 	(void)alarm(interval);
305 	if (line == 21)
306 		goto banner;
307 	goto loop;
308 	/*NOTREACHED*/
309 }
310 
311 /*
312  * Called if an interval expires before sidewaysintpr has completed a loop.
313  * Sets a flag to not wait for the alarm.
314  */
315 void
316 catchalarm()
317 {
318 	signalled = YES;
319 }
320