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