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