xref: /original-bsd/usr.bin/nfsstat/nfsstat.c (revision 426ca381)
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.14 (Berkeley) 11/02/92";
19 #endif /* not lint */
20 
21 #include <sys/param.h>
22 #if BSD >= 199103
23 #define NEWVM
24 #endif
25 #ifndef NEWVM
26 #include <sys/vmmac.h>
27 #include <sys/ucred.h>
28 #include <machine/pte.h>
29 #endif
30 #include <sys/mount.h>
31 #include <nfs/nfsv2.h>
32 #include <nfs/nfs.h>
33 #include <signal.h>
34 #include <fcntl.h>
35 #include <ctype.h>
36 #include <errno.h>
37 #include <kvm.h>
38 #include <nlist.h>
39 #include <unistd.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <paths.h>
44 
45 struct nlist nl[] = {
46 #define	N_NFSSTAT	0
47 	{ "_nfsstats" },
48 	"",
49 };
50 kvm_t *kd;
51 
52 void intpr(), printhdr(), sidewaysintpr(), usage();
53 
54 main(argc, argv)
55 	int argc;
56 	char **argv;
57 {
58 	extern int optind;
59 	extern char *optarg;
60 	u_int interval;
61 	int ch;
62 	char *memf, *nlistf;
63 	char errbuf[80];
64 
65 	interval = 0;
66 	memf = nlistf = NULL;
67 	while ((ch = getopt(argc, argv, "M:N:w:")) != EOF)
68 		switch(ch) {
69 		case 'M':
70 			memf = optarg;
71 			break;
72 		case 'N':
73 			nlistf = optarg;
74 			break;
75 		case 'w':
76 			interval = atoi(optarg);
77 			break;
78 		case '?':
79 		default:
80 			usage();
81 		}
82 	argc -= optind;
83 	argv += optind;
84 
85 #define	BACKWARD_COMPATIBILITY
86 #ifdef	BACKWARD_COMPATIBILITY
87 	if (*argv) {
88 		interval = atoi(*argv);
89 		if (*++argv) {
90 			nlistf = *argv;
91 			if (*++argv)
92 				memf = *argv;
93 		}
94 	}
95 #endif
96 	/*
97 	 * Discard setgid privileges if not the running kernel so that bad
98 	 * guys can't print interesting stuff from kernel memory.
99 	 */
100 	if (nlistf != NULL || memf != NULL)
101 		setgid(getgid());
102 
103 	if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf)) == 0) {
104 		fprintf(stderr, "nfsstat: kvm_openfiles: %s\n", errbuf);
105 		exit(1);
106 	}
107 	if (kvm_nlist(kd, nl) != 0) {
108 		fprintf(stderr, "nfsstat: kvm_nlist: can't get names\n");
109 		exit(1);
110 	}
111 
112 	if (interval)
113 		sidewaysintpr(interval, nl[N_NFSSTAT].n_value);
114 	else
115 		intpr(nl[N_NFSSTAT].n_value);
116 	exit(0);
117 }
118 
119 /*
120  * Print a description of the nfs stats.
121  */
122 void
123 intpr(nfsstataddr)
124 	u_long nfsstataddr;
125 {
126 	struct nfsstats nfsstats;
127 
128 	if (kvm_read(kd, (u_long)nfsstataddr, (char *)&nfsstats, sizeof(struct nfsstats)) < 0) {
129 		fprintf(stderr, "nfsstat: kvm_read failed\n");
130 		exit(1);
131 	}
132 	printf("Client Info:\n");
133 	printf("Rpc Counts:\n");
134 	printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
135 		"Getattr", "Setattr", "Lookup", "Readlink", "Read",
136 		"Write", "Create", "Remove");
137 	printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
138 		nfsstats.rpccnt[NFSPROC_GETATTR],
139 		nfsstats.rpccnt[NFSPROC_SETATTR],
140 		nfsstats.rpccnt[NFSPROC_LOOKUP],
141 		nfsstats.rpccnt[NFSPROC_READLINK],
142 		nfsstats.rpccnt[NFSPROC_READ],
143 		nfsstats.rpccnt[NFSPROC_WRITE],
144 		nfsstats.rpccnt[NFSPROC_CREATE],
145 		nfsstats.rpccnt[NFSPROC_REMOVE]);
146 	printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
147 		"Rename", "Link", "Symlink", "Mkdir", "Rmdir",
148 		"Readdir", "Statfs", "RdirLook");
149 	printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
150 		nfsstats.rpccnt[NFSPROC_RENAME],
151 		nfsstats.rpccnt[NFSPROC_LINK],
152 		nfsstats.rpccnt[NFSPROC_SYMLINK],
153 		nfsstats.rpccnt[NFSPROC_MKDIR],
154 		nfsstats.rpccnt[NFSPROC_RMDIR],
155 		nfsstats.rpccnt[NFSPROC_READDIR],
156 		nfsstats.rpccnt[NFSPROC_STATFS],
157 		nfsstats.rpccnt[NQNFSPROC_READDIRLOOK]);
158 	printf("%9.9s %9.9s %9.9s\n",
159 		"GLease", "Vacate", "Evict");
160 	printf("%9d %9d %9d\n",
161 		nfsstats.rpccnt[NQNFSPROC_GETLEASE],
162 		nfsstats.rpccnt[NQNFSPROC_VACATED],
163 		nfsstats.rpccnt[NQNFSPROC_EVICTED]);
164 	printf("Rpc Info:\n");
165 	printf("%9.9s %9.9s %9.9s %9.9s %9.9s\n",
166 		"TimedOut", "Invalid", "X Replies", "Retries", "Requests");
167 	printf("%9d %9d %9d %9d %9d\n",
168 		nfsstats.rpctimeouts,
169 		nfsstats.rpcinvalid,
170 		nfsstats.rpcunexpected,
171 		nfsstats.rpcretries,
172 		nfsstats.rpcrequests);
173 	printf("Cache Info:\n");
174 	printf("%9.9s %9.9s %9.9s %9.9s",
175 		"Attr Hits", "Misses", "Lkup Hits", "Misses");
176 	printf(" %9.9s %9.9s %9.9s %9.9s\n",
177 		"BioR Hits", "Misses", "BioW Hits", "Misses");
178 	printf("%9d %9d %9d %9d",
179 		nfsstats.attrcache_hits, nfsstats.attrcache_misses,
180 		nfsstats.lookupcache_hits, nfsstats.lookupcache_misses);
181 	printf(" %9d %9d %9d %9d\n",
182 		nfsstats.biocache_reads-nfsstats.read_bios,
183 		nfsstats.read_bios,
184 		nfsstats.biocache_writes-nfsstats.write_bios,
185 		nfsstats.write_bios);
186 	printf("%9.9s %9.9s %9.9s %9.9s",
187 		"BioRLHits", "Misses", "BioD Hits", "Misses");
188 	printf(" %9.9s %9.9s\n", "DirE Hits", "Misses");
189 	printf("%9d %9d %9d %9d",
190 		nfsstats.biocache_readlinks-nfsstats.readlink_bios,
191 		nfsstats.readlink_bios,
192 		nfsstats.biocache_readdirs-nfsstats.readdir_bios,
193 		nfsstats.readdir_bios);
194 	printf(" %9d %9d\n",
195 		nfsstats.direofcache_hits, nfsstats.direofcache_misses);
196 	printf("\nServer Info:\n");
197 	printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
198 		"Getattr", "Setattr", "Lookup", "Readlink", "Read",
199 		"Write", "Create", "Remove");
200 	printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
201 		nfsstats.srvrpccnt[NFSPROC_GETATTR],
202 		nfsstats.srvrpccnt[NFSPROC_SETATTR],
203 		nfsstats.srvrpccnt[NFSPROC_LOOKUP],
204 		nfsstats.srvrpccnt[NFSPROC_READLINK],
205 		nfsstats.srvrpccnt[NFSPROC_READ],
206 		nfsstats.srvrpccnt[NFSPROC_WRITE],
207 		nfsstats.srvrpccnt[NFSPROC_CREATE],
208 		nfsstats.srvrpccnt[NFSPROC_REMOVE]);
209 	printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
210 		"Rename", "Link", "Symlink", "Mkdir", "Rmdir",
211 		"Readdir", "Statfs", "RdirLook");
212 	printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
213 		nfsstats.srvrpccnt[NFSPROC_RENAME],
214 		nfsstats.srvrpccnt[NFSPROC_LINK],
215 		nfsstats.srvrpccnt[NFSPROC_SYMLINK],
216 		nfsstats.srvrpccnt[NFSPROC_MKDIR],
217 		nfsstats.srvrpccnt[NFSPROC_RMDIR],
218 		nfsstats.srvrpccnt[NFSPROC_READDIR],
219 		nfsstats.srvrpccnt[NFSPROC_STATFS],
220 		nfsstats.srvrpccnt[NQNFSPROC_READDIRLOOK]);
221 	printf("%9.9s %9.9s %9.9s\n",
222 		"GLease", "Vacate", "Evict");
223 	printf("%9d %9d %9d\n",
224 		nfsstats.srvrpccnt[NQNFSPROC_GETLEASE],
225 		nfsstats.srvrpccnt[NQNFSPROC_VACATED],
226 		nfsstats.srvrpccnt[NQNFSPROC_EVICTED]);
227 	printf("Server Ret-Failed\n");
228 	printf("%17d\n", nfsstats.srvrpc_errs);
229 	printf("Server Faults\n");
230 	printf("%13d\n", nfsstats.srv_errs);
231 	printf("Server Cache Stats:\n");
232 	printf("%9.9s %9.9s %9.9s %9.9s\n",
233 		"Inprog", "Idem", "Non-idem", "Misses");
234 	printf("%9d %9d %9d %9d\n",
235 		nfsstats.srvcache_inproghits,
236 		nfsstats.srvcache_idemdonehits,
237 		nfsstats.srvcache_nonidemdonehits,
238 		nfsstats.srvcache_misses);
239 	printf("Server Lease Stats:\n");
240 	printf("%9.9s %9.9s %9.9s\n",
241 		"Leases", "PeakL", "GLeases");
242 	printf("%9d %9d %9d\n",
243 		nfsstats.srvnqnfs_leases,
244 		nfsstats.srvnqnfs_maxleases,
245 		nfsstats.srvnqnfs_getleases);
246 }
247 
248 u_char	signalled;			/* set if alarm goes off "early" */
249 
250 /*
251  * Print a running summary of nfs statistics.
252  * Repeat display every interval seconds, showing statistics
253  * collected over that interval.  Assumes that interval is non-zero.
254  * First line printed at top of screen is always cumulative.
255  */
256 void
257 sidewaysintpr(interval, off)
258 	u_int interval;
259 	u_long off;
260 {
261 	struct nfsstats nfsstats, lastst;
262 	int hdrcnt, oldmask;
263 	void catchalarm();
264 
265 	(void)signal(SIGALRM, catchalarm);
266 	signalled = 0;
267 	(void)alarm(interval);
268 	bzero((caddr_t)&lastst, sizeof(lastst));
269 
270 	for (hdrcnt = 1;;) {
271 		if (!--hdrcnt) {
272 			printhdr();
273 			hdrcnt = 20;
274 		}
275 		if (kvm_read(kd, off, (char *)&nfsstats, sizeof nfsstats) < 0) {
276 			fprintf(stderr, "nfsstat: kvm_read failed\n");
277 			exit(1);
278 		}
279 		printf("Client: %8d %8d %8d %8d %8d %8d %8d %8d\n",
280 		    nfsstats.rpccnt[1]-lastst.rpccnt[1],
281 		    nfsstats.rpccnt[4]-lastst.rpccnt[4],
282 		    nfsstats.rpccnt[5]-lastst.rpccnt[5],
283 		    nfsstats.rpccnt[6]-lastst.rpccnt[6],
284 		    nfsstats.rpccnt[8]-lastst.rpccnt[8],
285 		    nfsstats.rpccnt[11]-lastst.rpccnt[11],
286 		    nfsstats.rpccnt[12]-lastst.rpccnt[12],
287 		    nfsstats.rpccnt[16]-lastst.rpccnt[16]);
288 		printf("Server: %8d %8d %8d %8d %8d %8d %8d %8d\n",
289 		    nfsstats.srvrpccnt[1]-lastst.srvrpccnt[1],
290 		    nfsstats.srvrpccnt[4]-lastst.srvrpccnt[4],
291 		    nfsstats.srvrpccnt[5]-lastst.srvrpccnt[5],
292 		    nfsstats.srvrpccnt[6]-lastst.srvrpccnt[6],
293 		    nfsstats.srvrpccnt[8]-lastst.srvrpccnt[8],
294 		    nfsstats.srvrpccnt[11]-lastst.srvrpccnt[11],
295 		    nfsstats.srvrpccnt[12]-lastst.srvrpccnt[12],
296 		    nfsstats.srvrpccnt[16]-lastst.srvrpccnt[16]);
297 		lastst = nfsstats;
298 		fflush(stdout);
299 		oldmask = sigblock(sigmask(SIGALRM));
300 		if (!signalled)
301 			sigpause(0);
302 		sigsetmask(oldmask);
303 		signalled = 0;
304 		(void)alarm(interval);
305 	}
306 	/*NOTREACHED*/
307 }
308 
309 void
310 printhdr()
311 {
312 	printf("        %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s\n",
313 	    "Getattr", "Lookup", "Readlink", "Read", "Write", "Rename",
314 	    "Link", "Readdir");
315 	fflush(stdout);
316 }
317 
318 /*
319  * Called if an interval expires before sidewaysintpr has completed a loop.
320  * Sets a flag to not wait for the alarm.
321  */
322 void
323 catchalarm()
324 {
325 	signalled = 1;
326 }
327 
328 void
329 usage()
330 {
331 	(void)fprintf(stderr,
332 	    "usage: nfsstat [-M core] [-N system] [-w interval]\n");
333 	exit(1);
334 }
335