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