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.5 (Berkeley) 06/01/90"; 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 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 } 319