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.1 (Berkeley) 07/16/89"; 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("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n", 162 "Getattr", "Setattr", "Lookup", "Readlink", "Read", 163 "Write", "Create", "Remove"); 164 printf("%9d %9d %9d %9d %9d %9d %9d %9d\n", 165 nfsstats.rpccnt[1], 166 nfsstats.rpccnt[2], 167 nfsstats.rpccnt[4], 168 nfsstats.rpccnt[5], 169 nfsstats.rpccnt[6], 170 nfsstats.rpccnt[8], 171 nfsstats.rpccnt[9], 172 nfsstats.rpccnt[10]); 173 printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n", 174 "Rename", "Link", "Symlink", "Mkdir", "Rmdir", 175 "Readdir", "Statfs"); 176 printf("%9d %9d %9d %9d %9d %9d %9d\n", 177 nfsstats.rpccnt[11], 178 nfsstats.rpccnt[12], 179 nfsstats.rpccnt[13], 180 nfsstats.rpccnt[14], 181 nfsstats.rpccnt[15], 182 nfsstats.rpccnt[16], 183 nfsstats.rpccnt[17]); 184 printf("Rpc retries\n%11d\n",nfsstats.rpcretries); 185 printf("Cache Info:\n"); 186 printf("%9.9s %9.9s %9.9s %9.9s\n", 187 "Attr Hits", "Misses", "Lkup Hits", "Misses"); 188 printf("%9d %9d %9d %9d\n", 189 nfsstats.attrcache_hits, nfsstats.attrcache_misses, 190 nfsstats.lookupcache_hits, nfsstats.lookupcache_misses); 191 printf("Server Info:\n"); 192 printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n", 193 "Getattr", "Setattr", "Lookup", "Readlink", "Read", 194 "Write", "Create", "Remove"); 195 printf("%9d %9d %9d %9d %9d %9d %9d %9d\n", 196 nfsstats.srvrpccnt[1], 197 nfsstats.srvrpccnt[2], 198 nfsstats.srvrpccnt[4], 199 nfsstats.srvrpccnt[5], 200 nfsstats.srvrpccnt[6], 201 nfsstats.srvrpccnt[8], 202 nfsstats.srvrpccnt[9], 203 nfsstats.srvrpccnt[10]); 204 printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n", 205 "Rename", "Link", "Symlink", "Mkdir", "Rmdir", 206 "Readdir", "Statfs"); 207 printf("%9d %9d %9d %9d %9d %9d %9d\n", 208 nfsstats.srvrpccnt[11], 209 nfsstats.srvrpccnt[12], 210 nfsstats.srvrpccnt[13], 211 nfsstats.srvrpccnt[14], 212 nfsstats.srvrpccnt[15], 213 nfsstats.srvrpccnt[16], 214 nfsstats.srvrpccnt[17]); 215 printf("Server Rpc Errors\n"); 216 printf("%17d\n", nfsstats.srvrpc_errs); 217 printf("Server Faults\n"); 218 printf("%13d\n", nfsstats.srv_errs); 219 } 220 221 u_char signalled; /* set if alarm goes off "early" */ 222 223 /* 224 * Print a running summary of nfs statistics. 225 * Repeat display every interval seconds, showing statistics 226 * collected over that interval. Assumes that interval is non-zero. 227 * First line printed at top of screen is always cumulative. 228 */ 229 sidewaysintpr(interval, off) 230 unsigned interval; 231 off_t off; 232 { 233 struct nfsstats nfsstats, lastst; 234 register int line; 235 int oldmask; 236 int catchalarm(); 237 238 klseek(kmem, off, 0); 239 240 (void)signal(SIGALRM, catchalarm); 241 signalled = NO; 242 (void)alarm(interval); 243 bzero((caddr_t)&lastst, sizeof(lastst)); 244 banner: 245 printf(" %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s\n", 246 "Getattr", "Lookup", "Readlink", "Read", 247 "Write", "Rename", "Link", "Readdir"); 248 fflush(stdout); 249 line = 0; 250 loop: 251 klseek(kmem, off, 0); 252 read(kmem, (char *)&nfsstats, sizeof nfsstats); 253 printf("Client: %8d %8d %8d %8d %8d %8d %8d %8d\n", 254 nfsstats.rpccnt[1]-lastst.rpccnt[1], 255 nfsstats.rpccnt[4]-lastst.rpccnt[4], 256 nfsstats.rpccnt[5]-lastst.rpccnt[5], 257 nfsstats.rpccnt[6]-lastst.rpccnt[6], 258 nfsstats.rpccnt[8]-lastst.rpccnt[8], 259 nfsstats.rpccnt[11]-lastst.rpccnt[11], 260 nfsstats.rpccnt[12]-lastst.rpccnt[12], 261 nfsstats.rpccnt[16]-lastst.rpccnt[16]); 262 printf("Server: %8d %8d %8d %8d %8d %8d %8d %8d\n", 263 nfsstats.srvrpccnt[1]-lastst.srvrpccnt[1], 264 nfsstats.srvrpccnt[4]-lastst.srvrpccnt[4], 265 nfsstats.srvrpccnt[5]-lastst.srvrpccnt[5], 266 nfsstats.srvrpccnt[6]-lastst.srvrpccnt[6], 267 nfsstats.srvrpccnt[8]-lastst.srvrpccnt[8], 268 nfsstats.srvrpccnt[11]-lastst.srvrpccnt[11], 269 nfsstats.srvrpccnt[12]-lastst.srvrpccnt[12], 270 nfsstats.srvrpccnt[16]-lastst.srvrpccnt[16]); 271 lastst = nfsstats; 272 fflush(stdout); 273 line++; 274 oldmask = sigblock(sigmask(SIGALRM)); 275 if (! signalled) { 276 sigpause(0); 277 } 278 sigsetmask(oldmask); 279 signalled = NO; 280 (void)alarm(interval); 281 if (line == 21) 282 goto banner; 283 goto loop; 284 /*NOTREACHED*/ 285 } 286 287 /* 288 * Called if an interval expires before sidewaysintpr has completed a loop. 289 * Sets a flag to not wait for the alarm. 290 */ 291 catchalarm() 292 { 293 signalled = YES; 294 } 295