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