Commit | Line | Data |
---|---|---|
4cbecdde KM |
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 | * | |
87198c0c | 8 | * %sccs.include.redist.c% |
4cbecdde KM |
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 | |
87198c0c | 18 | static char sccsid[] = "@(#)nfsstat.c 5.5 (Berkeley) %G%"; |
4cbecdde KM |
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"); | |
ab8b6a82 | 151 | printf("Rpc Counts:\n"); |
4cbecdde KM |
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]); | |
ab8b6a82 KM |
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); | |
4cbecdde | 184 | printf("Cache Info:\n"); |
1b3a818d | 185 | printf("%9.9s %9.9s %9.9s %9.9s", |
4cbecdde | 186 | "Attr Hits", "Misses", "Lkup Hits", "Misses"); |
1b3a818d KM |
187 | printf(" %9.9s %9.9s %9.9s %9.9s\n", |
188 | "BioR Hits", "Misses", "BioW Hits", "Misses"); | |
189 | printf("%9d %9d %9d %9d", | |
4cbecdde KM |
190 | nfsstats.attrcache_hits, nfsstats.attrcache_misses, |
191 | nfsstats.lookupcache_hits, nfsstats.lookupcache_misses); | |
1b3a818d KM |
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); | |
ab8b6a82 KM |
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", | |
e6c65482 | 206 | nfsstats.direofcache_hits, nfsstats.direofcache_misses); |
ab8b6a82 | 207 | printf("\nServer Info:\n"); |
4cbecdde KM |
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]); | |
1b3a818d | 231 | printf("Server Ret-Failed\n"); |
4cbecdde KM |
232 | printf("%17d\n", nfsstats.srvrpc_errs); |
233 | printf("Server Faults\n"); | |
234 | printf("%13d\n", nfsstats.srv_errs); | |
1b3a818d KM |
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); | |
4cbecdde KM |
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 | int 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 | catchalarm() | |
316 | { | |
317 | signalled = YES; | |
318 | } |