1 /* 2 * Copyright (c) 1983, 1989, 1993 3 * The Regents of the University of California. 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, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 #ifndef lint 38 static const char copyright[] = 39 "@(#) Copyright (c) 1983, 1989, 1993\n\ 40 The Regents of the University of California. All rights reserved.\n"; 41 #endif /* not lint */ 42 43 #ifndef lint 44 #if 0 45 static char sccsid[] = "@(#)nfsstat.c 8.2 (Berkeley) 3/31/95"; 46 #endif 47 static const char rcsid[] = 48 "$FreeBSD$"; 49 #endif /* not lint */ 50 51 #include <sys/param.h> 52 #include <sys/module.h> 53 #include <sys/mount.h> 54 #include <sys/time.h> 55 #include <sys/sysctl.h> 56 #include <nfs/nfsproto.h> 57 #include <nfsclient/nfs.h> 58 #include <nfsserver/nfs.h> 59 #include <nfs/nfssvc.h> 60 61 #include <fs/nfs/nfsport.h> 62 63 #include <signal.h> 64 #include <fcntl.h> 65 #include <ctype.h> 66 #include <errno.h> 67 #include <kvm.h> 68 #include <limits.h> 69 #include <nlist.h> 70 #include <unistd.h> 71 #include <stdio.h> 72 #include <stdlib.h> 73 #include <string.h> 74 #include <paths.h> 75 #include <err.h> 76 77 struct nlist nl[] = { 78 #define N_NFSSTAT 0 79 { .n_name = "nfsstats" }, 80 #define N_NFSRVSTAT 1 81 { .n_name = "nfsrvstats" }, 82 { .n_name = NULL }, 83 }; 84 kvm_t *kd; 85 86 static int deadkernel = 0; 87 static int widemode = 0; 88 static int zflag = 0; 89 static int run_v4 = 0; 90 static int printtitle = 1; 91 static struct ext_nfsstats ext_nfsstats; 92 93 void intpr(int, int); 94 void printhdr(int, int); 95 void sidewaysintpr(u_int, int, int); 96 void usage(void); 97 char *sperc1(int, int); 98 char *sperc2(int, int); 99 void exp_intpr(int, int); 100 void exp_sidewaysintpr(u_int, int, int); 101 102 #define DELTA(field) (nfsstats.field - lastst.field) 103 104 int 105 main(int argc, char **argv) 106 { 107 u_int interval; 108 int clientOnly = -1; 109 int serverOnly = -1; 110 int ch; 111 char *memf, *nlistf; 112 char errbuf[_POSIX2_LINE_MAX]; 113 114 interval = 0; 115 memf = nlistf = NULL; 116 while ((ch = getopt(argc, argv, "cesWM:N:w:z")) != -1) 117 switch(ch) { 118 case 'M': 119 memf = optarg; 120 break; 121 case 'N': 122 nlistf = optarg; 123 break; 124 case 'W': 125 widemode = 1; 126 break; 127 case 'w': 128 interval = atoi(optarg); 129 break; 130 case 'c': 131 clientOnly = 1; 132 if (serverOnly < 0) 133 serverOnly = 0; 134 break; 135 case 's': 136 serverOnly = 1; 137 if (clientOnly < 0) 138 clientOnly = 0; 139 break; 140 case 'z': 141 zflag = 1; 142 break; 143 case 'e': 144 run_v4 = 1; 145 break; 146 case '?': 147 default: 148 usage(); 149 } 150 argc -= optind; 151 argv += optind; 152 153 #define BACKWARD_COMPATIBILITY 154 #ifdef BACKWARD_COMPATIBILITY 155 if (*argv) { 156 interval = atoi(*argv); 157 if (*++argv) { 158 nlistf = *argv; 159 if (*++argv) 160 memf = *argv; 161 } 162 } 163 #endif 164 if (run_v4 != 0 && modfind("nfscommon") < 0) 165 errx(1, "experimental client/server not loaded"); 166 167 if (run_v4 != 0) { 168 if (nfssvc(NFSSVC_GETSTATS, &ext_nfsstats) < 0) 169 err(1, "Can't get stats"); 170 } else if (nlistf != NULL || memf != NULL) { 171 deadkernel = 1; 172 173 if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, 174 errbuf)) == 0) { 175 errx(1, "kvm_openfiles: %s", errbuf); 176 } 177 if (kvm_nlist(kd, nl) != 0) { 178 errx(1, "kvm_nlist: can't get names"); 179 } 180 } 181 182 if (interval) { 183 if (run_v4 > 0) 184 exp_sidewaysintpr(interval, clientOnly, serverOnly); 185 else 186 sidewaysintpr(interval, clientOnly, serverOnly); 187 } else { 188 if (run_v4 > 0) 189 exp_intpr(clientOnly, serverOnly); 190 else 191 intpr(clientOnly, serverOnly); 192 } 193 exit(0); 194 } 195 196 /* 197 * Read the nfs stats using sysctl(3) for live kernels, or kvm_read 198 * for dead ones. 199 */ 200 static void 201 readstats(struct nfsstats **stp, struct nfsrvstats **srvstp, int zero) 202 { 203 union { 204 struct nfsstats client; 205 struct nfsrvstats server; 206 } zerostat; 207 size_t buflen; 208 209 if (deadkernel) { 210 if (*stp != NULL && kvm_read(kd, (u_long)nl[N_NFSSTAT].n_value, 211 *stp, sizeof(struct nfsstats)) < 0) { 212 *stp = NULL; 213 } 214 if (*srvstp != NULL && kvm_read(kd, 215 (u_long)nl[N_NFSRVSTAT].n_value, *srvstp, 216 sizeof(struct nfsrvstats)) < 0) { 217 *srvstp = NULL; 218 } 219 } else { 220 if (zero) 221 bzero(&zerostat, sizeof(zerostat)); 222 buflen = sizeof(struct nfsstats); 223 if (*stp != NULL && sysctlbyname("vfs.nfs.nfsstats", *stp, 224 &buflen, zero ? &zerostat : NULL, zero ? buflen : 0) < 0) { 225 if (errno != ENOENT) 226 err(1, "sysctl: vfs.nfs.nfsstats"); 227 *stp = NULL; 228 } 229 buflen = sizeof(struct nfsrvstats); 230 if (*srvstp != NULL && sysctlbyname("vfs.nfsrv.nfsrvstats", 231 *srvstp, &buflen, zero ? &zerostat : NULL, 232 zero ? buflen : 0) < 0) { 233 if (errno != ENOENT) 234 err(1, "sysctl: vfs.nfsrv.nfsrvstats"); 235 *srvstp = NULL; 236 } 237 } 238 } 239 240 /* 241 * Print a description of the nfs stats. 242 */ 243 void 244 intpr(int clientOnly, int serverOnly) 245 { 246 struct nfsstats nfsstats, *nfsstatsp; 247 struct nfsrvstats nfsrvstats, *nfsrvstatsp; 248 249 /* 250 * Only read the stats we are going to display to avoid zeroing 251 * stats the user didn't request. 252 */ 253 if (clientOnly) 254 nfsstatsp = &nfsstats; 255 else 256 nfsstatsp = NULL; 257 if (serverOnly) 258 nfsrvstatsp = &nfsrvstats; 259 else 260 nfsrvstatsp = NULL; 261 262 readstats(&nfsstatsp, &nfsrvstatsp, zflag); 263 264 if (clientOnly && !nfsstatsp) { 265 printf("Client not present!\n"); 266 clientOnly = 0; 267 } 268 if (clientOnly) { 269 printf("Client Info:\n"); 270 printf("Rpc Counts:\n"); 271 printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n", 272 "Getattr", "Setattr", "Lookup", "Readlink", "Read", 273 "Write", "Create", "Remove"); 274 printf("%9d %9d %9d %9d %9d %9d %9d %9d\n", 275 nfsstats.rpccnt[NFSPROC_GETATTR], 276 nfsstats.rpccnt[NFSPROC_SETATTR], 277 nfsstats.rpccnt[NFSPROC_LOOKUP], 278 nfsstats.rpccnt[NFSPROC_READLINK], 279 nfsstats.rpccnt[NFSPROC_READ], 280 nfsstats.rpccnt[NFSPROC_WRITE], 281 nfsstats.rpccnt[NFSPROC_CREATE], 282 nfsstats.rpccnt[NFSPROC_REMOVE]); 283 printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n", 284 "Rename", "Link", "Symlink", "Mkdir", "Rmdir", 285 "Readdir", "RdirPlus", "Access"); 286 printf("%9d %9d %9d %9d %9d %9d %9d %9d\n", 287 nfsstats.rpccnt[NFSPROC_RENAME], 288 nfsstats.rpccnt[NFSPROC_LINK], 289 nfsstats.rpccnt[NFSPROC_SYMLINK], 290 nfsstats.rpccnt[NFSPROC_MKDIR], 291 nfsstats.rpccnt[NFSPROC_RMDIR], 292 nfsstats.rpccnt[NFSPROC_READDIR], 293 nfsstats.rpccnt[NFSPROC_READDIRPLUS], 294 nfsstats.rpccnt[NFSPROC_ACCESS]); 295 printf("%9.9s %9.9s %9.9s %9.9s %9.9s\n", 296 "Mknod", "Fsstat", "Fsinfo", "PathConf", "Commit"); 297 printf("%9d %9d %9d %9d %9d\n", 298 nfsstats.rpccnt[NFSPROC_MKNOD], 299 nfsstats.rpccnt[NFSPROC_FSSTAT], 300 nfsstats.rpccnt[NFSPROC_FSINFO], 301 nfsstats.rpccnt[NFSPROC_PATHCONF], 302 nfsstats.rpccnt[NFSPROC_COMMIT]); 303 printf("Rpc Info:\n"); 304 printf("%9.9s %9.9s %9.9s %9.9s %9.9s\n", 305 "TimedOut", "Invalid", "X Replies", "Retries", 306 "Requests"); 307 printf("%9d %9d %9d %9d %9d\n", 308 nfsstats.rpctimeouts, 309 nfsstats.rpcinvalid, 310 nfsstats.rpcunexpected, 311 nfsstats.rpcretries, 312 nfsstats.rpcrequests); 313 printf("Cache Info:\n"); 314 printf("%9.9s %9.9s %9.9s %9.9s", 315 "Attr Hits", "Misses", "Lkup Hits", "Misses"); 316 printf(" %9.9s %9.9s %9.9s %9.9s\n", 317 "BioR Hits", "Misses", "BioW Hits", "Misses"); 318 printf("%9d %9d %9d %9d", 319 nfsstats.attrcache_hits, nfsstats.attrcache_misses, 320 nfsstats.lookupcache_hits, nfsstats.lookupcache_misses); 321 printf(" %9d %9d %9d %9d\n", 322 nfsstats.biocache_reads-nfsstats.read_bios, 323 nfsstats.read_bios, 324 nfsstats.biocache_writes-nfsstats.write_bios, 325 nfsstats.write_bios); 326 printf("%9.9s %9.9s %9.9s %9.9s", 327 "BioRLHits", "Misses", "BioD Hits", "Misses"); 328 printf(" %9.9s %9.9s\n", "DirE Hits", "Misses"); 329 printf("%9d %9d %9d %9d", 330 nfsstats.biocache_readlinks-nfsstats.readlink_bios, 331 nfsstats.readlink_bios, 332 nfsstats.biocache_readdirs-nfsstats.readdir_bios, 333 nfsstats.readdir_bios); 334 printf(" %9d %9d\n", 335 nfsstats.direofcache_hits, nfsstats.direofcache_misses); 336 } 337 if (serverOnly && !nfsrvstatsp) { 338 printf("Server not present!\n"); 339 serverOnly = 0; 340 } 341 if (serverOnly) { 342 printf("\nServer Info:\n"); 343 printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n", 344 "Getattr", "Setattr", "Lookup", "Readlink", "Read", 345 "Write", "Create", "Remove"); 346 printf("%9d %9d %9d %9d %9d %9d %9d %9d\n", 347 nfsrvstats.srvrpccnt[NFSPROC_GETATTR], 348 nfsrvstats.srvrpccnt[NFSPROC_SETATTR], 349 nfsrvstats.srvrpccnt[NFSPROC_LOOKUP], 350 nfsrvstats.srvrpccnt[NFSPROC_READLINK], 351 nfsrvstats.srvrpccnt[NFSPROC_READ], 352 nfsrvstats.srvrpccnt[NFSPROC_WRITE], 353 nfsrvstats.srvrpccnt[NFSPROC_CREATE], 354 nfsrvstats.srvrpccnt[NFSPROC_REMOVE]); 355 printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n", 356 "Rename", "Link", "Symlink", "Mkdir", "Rmdir", 357 "Readdir", "RdirPlus", "Access"); 358 printf("%9d %9d %9d %9d %9d %9d %9d %9d\n", 359 nfsrvstats.srvrpccnt[NFSPROC_RENAME], 360 nfsrvstats.srvrpccnt[NFSPROC_LINK], 361 nfsrvstats.srvrpccnt[NFSPROC_SYMLINK], 362 nfsrvstats.srvrpccnt[NFSPROC_MKDIR], 363 nfsrvstats.srvrpccnt[NFSPROC_RMDIR], 364 nfsrvstats.srvrpccnt[NFSPROC_READDIR], 365 nfsrvstats.srvrpccnt[NFSPROC_READDIRPLUS], 366 nfsrvstats.srvrpccnt[NFSPROC_ACCESS]); 367 printf("%9.9s %9.9s %9.9s %9.9s %9.9s\n", 368 "Mknod", "Fsstat", "Fsinfo", "PathConf", "Commit"); 369 printf("%9d %9d %9d %9d %9d\n", 370 nfsrvstats.srvrpccnt[NFSPROC_MKNOD], 371 nfsrvstats.srvrpccnt[NFSPROC_FSSTAT], 372 nfsrvstats.srvrpccnt[NFSPROC_FSINFO], 373 nfsrvstats.srvrpccnt[NFSPROC_PATHCONF], 374 nfsrvstats.srvrpccnt[NFSPROC_COMMIT]); 375 printf("Server Ret-Failed\n"); 376 printf("%17d\n", nfsrvstats.srvrpc_errs); 377 printf("Server Faults\n"); 378 printf("%13d\n", nfsrvstats.srv_errs); 379 printf("Server Cache Stats:\n"); 380 printf("%9.9s %9.9s %9.9s %9.9s\n", 381 "Inprog", "Idem", "Non-idem", "Misses"); 382 printf("%9d %9d %9d %9d\n", 383 nfsrvstats.srvcache_inproghits, 384 nfsrvstats.srvcache_idemdonehits, 385 nfsrvstats.srvcache_nonidemdonehits, 386 nfsrvstats.srvcache_misses); 387 printf("Server Write Gathering:\n"); 388 printf("%9.9s %9.9s %9.9s\n", 389 "WriteOps", "WriteRPC", "Opsaved"); 390 printf("%9d %9d %9d\n", 391 nfsrvstats.srvvop_writes, 392 nfsrvstats.srvrpccnt[NFSPROC_WRITE], 393 nfsrvstats.srvrpccnt[NFSPROC_WRITE] - 394 nfsrvstats.srvvop_writes); 395 } 396 } 397 398 u_char signalled; /* set if alarm goes off "early" */ 399 400 /* 401 * Print a running summary of nfs statistics. 402 * Repeat display every interval seconds, showing statistics 403 * collected over that interval. Assumes that interval is non-zero. 404 * First line printed at top of screen is always cumulative. 405 */ 406 void 407 sidewaysintpr(u_int interval, int clientOnly, int serverOnly) 408 { 409 struct nfsstats nfsstats, lastst, *nfsstatsp; 410 struct nfsrvstats nfsrvstats, lastsrvst, *nfsrvstatsp; 411 int hdrcnt = 1; 412 413 nfsstatsp = &lastst; 414 nfsrvstatsp = &lastsrvst; 415 readstats(&nfsstatsp, &nfsrvstatsp, 0); 416 if (clientOnly && !nfsstatsp) { 417 printf("Client not present!\n"); 418 clientOnly = 0; 419 } 420 if (serverOnly && !nfsrvstatsp) { 421 printf("Server not present!\n"); 422 serverOnly = 0; 423 } 424 sleep(interval); 425 426 for (;;) { 427 nfsstatsp = &nfsstats; 428 nfsrvstatsp = &nfsrvstats; 429 readstats(&nfsstatsp, &nfsrvstatsp, 0); 430 431 if (--hdrcnt == 0) { 432 printhdr(clientOnly, serverOnly); 433 if (clientOnly && serverOnly) 434 hdrcnt = 10; 435 else 436 hdrcnt = 20; 437 } 438 if (clientOnly) { 439 printf("%s %6d %6d %6d %6d %6d %6d %6d %6d", 440 ((clientOnly && serverOnly) ? "Client:" : ""), 441 DELTA(attrcache_hits) + DELTA(attrcache_misses), 442 DELTA(lookupcache_hits) + DELTA(lookupcache_misses), 443 DELTA(biocache_readlinks), 444 DELTA(biocache_reads), 445 DELTA(biocache_writes), 446 nfsstats.rpccnt[NFSPROC_RENAME]-lastst.rpccnt[NFSPROC_RENAME], 447 DELTA(accesscache_hits) + DELTA(accesscache_misses), 448 DELTA(biocache_readdirs) 449 ); 450 if (widemode) { 451 printf(" %s %s %s %s %s %s", 452 sperc1(DELTA(attrcache_hits), 453 DELTA(attrcache_misses)), 454 sperc1(DELTA(lookupcache_hits), 455 DELTA(lookupcache_misses)), 456 sperc2(DELTA(biocache_reads), 457 DELTA(read_bios)), 458 sperc2(DELTA(biocache_writes), 459 DELTA(write_bios)), 460 sperc1(DELTA(accesscache_hits), 461 DELTA(accesscache_misses)), 462 sperc2(DELTA(biocache_readdirs), 463 DELTA(readdir_bios)) 464 ); 465 } 466 printf("\n"); 467 lastst = nfsstats; 468 } 469 if (serverOnly) { 470 printf("%s %6d %6d %6d %6d %6d %6d %6d %6d", 471 ((clientOnly && serverOnly) ? "Server:" : ""), 472 nfsrvstats.srvrpccnt[NFSPROC_GETATTR]-lastsrvst.srvrpccnt[NFSPROC_GETATTR], 473 nfsrvstats.srvrpccnt[NFSPROC_LOOKUP]-lastsrvst.srvrpccnt[NFSPROC_LOOKUP], 474 nfsrvstats.srvrpccnt[NFSPROC_READLINK]-lastsrvst.srvrpccnt[NFSPROC_READLINK], 475 nfsrvstats.srvrpccnt[NFSPROC_READ]-lastsrvst.srvrpccnt[NFSPROC_READ], 476 nfsrvstats.srvrpccnt[NFSPROC_WRITE]-lastsrvst.srvrpccnt[NFSPROC_WRITE], 477 nfsrvstats.srvrpccnt[NFSPROC_RENAME]-lastsrvst.srvrpccnt[NFSPROC_RENAME], 478 nfsrvstats.srvrpccnt[NFSPROC_ACCESS]-lastsrvst.srvrpccnt[NFSPROC_ACCESS], 479 (nfsrvstats.srvrpccnt[NFSPROC_READDIR]-lastsrvst.srvrpccnt[NFSPROC_READDIR]) 480 +(nfsrvstats.srvrpccnt[NFSPROC_READDIRPLUS]-lastsrvst.srvrpccnt[NFSPROC_READDIRPLUS])); 481 printf("\n"); 482 lastsrvst = nfsrvstats; 483 } 484 fflush(stdout); 485 sleep(interval); 486 } 487 /*NOTREACHED*/ 488 } 489 490 void 491 printhdr(int clientOnly, int serverOnly) 492 { 493 printf("%s%6.6s %6.6s %6.6s %6.6s %6.6s %6.6s %6.6s %6.6s", 494 ((serverOnly && clientOnly) ? " " : " "), 495 "GtAttr", "Lookup", "Rdlink", "Read", "Write", "Rename", 496 "Access", "Rddir"); 497 if (widemode && clientOnly) { 498 printf(" Attr Lkup BioR BioW Accs BioD"); 499 } 500 printf("\n"); 501 fflush(stdout); 502 } 503 504 void 505 usage(void) 506 { 507 (void)fprintf(stderr, 508 "usage: nfsstat [-ceszW] [-M core] [-N system] [-w interval]\n"); 509 exit(1); 510 } 511 512 static char SPBuf[64][8]; 513 static int SPIndex; 514 515 char * 516 sperc1(int hits, int misses) 517 { 518 char *p = SPBuf[SPIndex]; 519 520 if (hits + misses) { 521 sprintf(p, "%3d%%", 522 (int)(char)((quad_t)hits * 100 / (hits + misses))); 523 } else { 524 sprintf(p, " -"); 525 } 526 SPIndex = (SPIndex + 1) & 63; 527 return(p); 528 } 529 530 char * 531 sperc2(int ttl, int misses) 532 { 533 char *p = SPBuf[SPIndex]; 534 535 if (ttl) { 536 sprintf(p, "%3d%%", 537 (int)(char)((quad_t)(ttl - misses) * 100 / ttl)); 538 } else { 539 sprintf(p, " -"); 540 } 541 SPIndex = (SPIndex + 1) & 63; 542 return(p); 543 } 544 545 /* 546 * Print a description of the nfs stats for the experimental client/server. 547 */ 548 void 549 exp_intpr(int clientOnly, int serverOnly) 550 { 551 552 if (clientOnly != 0) { 553 if (printtitle) { 554 printf("Client Info:\n"); 555 printf("Rpc Counts:\n"); 556 printf( 557 "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n" 558 , "Getattr", "Setattr", "Lookup", "Readlink", 559 "Read", "Write", "Create", "Remove"); 560 } 561 printf("%9d %9d %9d %9d %9d %9d %9d %9d\n", 562 ext_nfsstats.rpccnt[NFSPROC_GETATTR], 563 ext_nfsstats.rpccnt[NFSPROC_SETATTR], 564 ext_nfsstats.rpccnt[NFSPROC_LOOKUP], 565 ext_nfsstats.rpccnt[NFSPROC_READLINK], 566 ext_nfsstats.rpccnt[NFSPROC_READ], 567 ext_nfsstats.rpccnt[NFSPROC_WRITE], 568 ext_nfsstats.rpccnt[NFSPROC_CREATE], 569 ext_nfsstats.rpccnt[NFSPROC_REMOVE]); 570 if (printtitle) 571 printf( 572 "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n" 573 , "Rename", "Link", "Symlink", "Mkdir", "Rmdir", 574 "Readdir", "RdirPlus", "Access"); 575 printf("%9d %9d %9d %9d %9d %9d %9d %9d\n", 576 ext_nfsstats.rpccnt[NFSPROC_RENAME], 577 ext_nfsstats.rpccnt[NFSPROC_LINK], 578 ext_nfsstats.rpccnt[NFSPROC_SYMLINK], 579 ext_nfsstats.rpccnt[NFSPROC_MKDIR], 580 ext_nfsstats.rpccnt[NFSPROC_RMDIR], 581 ext_nfsstats.rpccnt[NFSPROC_READDIR], 582 ext_nfsstats.rpccnt[NFSPROC_READDIRPLUS], 583 ext_nfsstats.rpccnt[NFSPROC_ACCESS]); 584 if (printtitle) 585 printf( 586 "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n" 587 , "Mknod", "Fsstat", "Fsinfo", "PathConf", 588 "Commit", "SetClId", "SetClIdCf", "Lock"); 589 printf("%9d %9d %9d %9d %9d %9d %9d %9d\n", 590 ext_nfsstats.rpccnt[NFSPROC_MKNOD], 591 ext_nfsstats.rpccnt[NFSPROC_FSSTAT], 592 ext_nfsstats.rpccnt[NFSPROC_FSINFO], 593 ext_nfsstats.rpccnt[NFSPROC_PATHCONF], 594 ext_nfsstats.rpccnt[NFSPROC_COMMIT], 595 ext_nfsstats.rpccnt[NFSPROC_SETCLIENTID], 596 ext_nfsstats.rpccnt[NFSPROC_SETCLIENTIDCFRM], 597 ext_nfsstats.rpccnt[NFSPROC_LOCK]); 598 if (printtitle) 599 printf("%9.9s %9.9s %9.9s %9.9s\n", 600 "LockT", "LockU", "Open", "OpenCfr"); 601 printf("%9d %9d %9d %9d\n", 602 ext_nfsstats.rpccnt[NFSPROC_LOCKT], 603 ext_nfsstats.rpccnt[NFSPROC_LOCKU], 604 ext_nfsstats.rpccnt[NFSPROC_OPEN], 605 ext_nfsstats.rpccnt[NFSPROC_OPENCONFIRM]); 606 if (printtitle) 607 printf( 608 "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n" 609 , "OpenOwner", "Opens", "LockOwner", 610 "Locks", "Delegs", "LocalOwn", 611 "LocalOpen", "LocalLOwn"); 612 printf("%9d %9d %9d %9d %9d %9d %9d %9d\n", 613 ext_nfsstats.clopenowners, 614 ext_nfsstats.clopens, 615 ext_nfsstats.cllockowners, 616 ext_nfsstats.cllocks, 617 ext_nfsstats.cldelegates, 618 ext_nfsstats.cllocalopenowners, 619 ext_nfsstats.cllocalopens, 620 ext_nfsstats.cllocallockowners); 621 if (printtitle) 622 printf("%9.9s\n", "LocalLock"); 623 printf("%9d\n", ext_nfsstats.cllocallocks); 624 if (printtitle) { 625 printf("Rpc Info:\n"); 626 printf("%9.9s %9.9s %9.9s %9.9s %9.9s\n", 627 "TimedOut", "Invalid", "X Replies", "Retries", 628 "Requests"); 629 } 630 printf("%9d %9d %9d %9d %9d\n", 631 ext_nfsstats.rpctimeouts, 632 ext_nfsstats.rpcinvalid, 633 ext_nfsstats.rpcunexpected, 634 ext_nfsstats.rpcretries, 635 ext_nfsstats.rpcrequests); 636 if (printtitle) { 637 printf("Cache Info:\n"); 638 printf("%9.9s %9.9s %9.9s %9.9s", 639 "Attr Hits", "Misses", "Lkup Hits", "Misses"); 640 printf(" %9.9s %9.9s %9.9s %9.9s\n", 641 "BioR Hits", "Misses", "BioW Hits", "Misses"); 642 } 643 printf("%9d %9d %9d %9d", 644 ext_nfsstats.attrcache_hits, 645 ext_nfsstats.attrcache_misses, 646 ext_nfsstats.lookupcache_hits, 647 ext_nfsstats.lookupcache_misses); 648 printf(" %9d %9d %9d %9d\n", 649 ext_nfsstats.biocache_reads, 650 ext_nfsstats.read_bios, 651 ext_nfsstats.biocache_writes, 652 ext_nfsstats.write_bios); 653 if (printtitle) { 654 printf("%9.9s %9.9s %9.9s %9.9s", 655 "BioRLHits", "Misses", "BioD Hits", "Misses"); 656 printf(" %9.9s %9.9s\n", "DirE Hits", "Misses"); 657 } 658 printf("%9d %9d %9d %9d", 659 ext_nfsstats.biocache_readlinks, 660 ext_nfsstats.readlink_bios, 661 ext_nfsstats.biocache_readdirs, 662 ext_nfsstats.readdir_bios); 663 printf(" %9d %9d\n", 664 ext_nfsstats.direofcache_hits, 665 ext_nfsstats.direofcache_misses); 666 } 667 if (serverOnly != 0) { 668 if (printtitle) { 669 printf("\nServer Info:\n"); 670 printf( 671 "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n" 672 , "Getattr", "Setattr", "Lookup", "Readlink", 673 "Read", "Write", "Create", "Remove"); 674 } 675 printf("%9d %9d %9d %9d %9d %9d %9d %9d\n", 676 ext_nfsstats.srvrpccnt[NFSV4OP_GETATTR], 677 ext_nfsstats.srvrpccnt[NFSV4OP_SETATTR], 678 ext_nfsstats.srvrpccnt[NFSV4OP_LOOKUP], 679 ext_nfsstats.srvrpccnt[NFSV4OP_READLINK], 680 ext_nfsstats.srvrpccnt[NFSV4OP_READ], 681 ext_nfsstats.srvrpccnt[NFSV4OP_WRITE], 682 ext_nfsstats.srvrpccnt[NFSV4OP_V3CREATE], 683 ext_nfsstats.srvrpccnt[NFSV4OP_REMOVE]); 684 if (printtitle) 685 printf( 686 "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n" 687 , "Rename", "Link", "Symlink", "Mkdir", "Rmdir", 688 "Readdir", "RdirPlus", "Access"); 689 printf("%9d %9d %9d %9d %9d %9d %9d %9d\n", 690 ext_nfsstats.srvrpccnt[NFSV4OP_RENAME], 691 ext_nfsstats.srvrpccnt[NFSV4OP_LINK], 692 ext_nfsstats.srvrpccnt[NFSV4OP_SYMLINK], 693 ext_nfsstats.srvrpccnt[NFSV4OP_MKDIR], 694 ext_nfsstats.srvrpccnt[NFSV4OP_RMDIR], 695 ext_nfsstats.srvrpccnt[NFSV4OP_READDIR], 696 ext_nfsstats.srvrpccnt[NFSV4OP_READDIRPLUS], 697 ext_nfsstats.srvrpccnt[NFSV4OP_ACCESS]); 698 if (printtitle) 699 printf( 700 "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n" 701 , "Mknod", "Fsstat", "Fsinfo", "PathConf", 702 "Commit", "LookupP", "SetClId", "SetClIdCf"); 703 printf("%9d %9d %9d %9d %9d %9d %9d %9d\n", 704 ext_nfsstats.srvrpccnt[NFSV4OP_MKNOD], 705 ext_nfsstats.srvrpccnt[NFSV4OP_FSSTAT], 706 ext_nfsstats.srvrpccnt[NFSV4OP_FSINFO], 707 ext_nfsstats.srvrpccnt[NFSV4OP_PATHCONF], 708 ext_nfsstats.srvrpccnt[NFSV4OP_COMMIT], 709 ext_nfsstats.srvrpccnt[NFSV4OP_LOOKUPP], 710 ext_nfsstats.srvrpccnt[NFSV4OP_SETCLIENTID], 711 ext_nfsstats.srvrpccnt[NFSV4OP_SETCLIENTIDCFRM]); 712 if (printtitle) 713 printf( 714 "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n" 715 , "Open", "OpenAttr", "OpenDwnGr", "OpenCfrm", 716 "DelePurge", "DeleRet", "GetFH", "Lock"); 717 printf("%9d %9d %9d %9d %9d %9d %9d %9d\n", 718 ext_nfsstats.srvrpccnt[NFSV4OP_OPEN], 719 ext_nfsstats.srvrpccnt[NFSV4OP_OPENATTR], 720 ext_nfsstats.srvrpccnt[NFSV4OP_OPENDOWNGRADE], 721 ext_nfsstats.srvrpccnt[NFSV4OP_OPENCONFIRM], 722 ext_nfsstats.srvrpccnt[NFSV4OP_DELEGPURGE], 723 ext_nfsstats.srvrpccnt[NFSV4OP_DELEGRETURN], 724 ext_nfsstats.srvrpccnt[NFSV4OP_GETFH], 725 ext_nfsstats.srvrpccnt[NFSV4OP_LOCK]); 726 if (printtitle) 727 printf( 728 "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n" 729 , "LockT", "LockU", "Close", "Verify", "NVerify", 730 "PutFH", "PutPubFH", "PutRootFH"); 731 printf("%9d %9d %9d %9d %9d %9d %9d %9d\n", 732 ext_nfsstats.srvrpccnt[NFSV4OP_LOCKT], 733 ext_nfsstats.srvrpccnt[NFSV4OP_LOCKU], 734 ext_nfsstats.srvrpccnt[NFSV4OP_CLOSE], 735 ext_nfsstats.srvrpccnt[NFSV4OP_VERIFY], 736 ext_nfsstats.srvrpccnt[NFSV4OP_NVERIFY], 737 ext_nfsstats.srvrpccnt[NFSV4OP_PUTFH], 738 ext_nfsstats.srvrpccnt[NFSV4OP_PUTPUBFH], 739 ext_nfsstats.srvrpccnt[NFSV4OP_PUTROOTFH]); 740 if (printtitle) 741 printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n", 742 "Renew", "RestoreFH", "SaveFH", "Secinfo", 743 "RelLckOwn", "V4Create"); 744 printf("%9d %9d %9d %9d %9d %9d\n", 745 ext_nfsstats.srvrpccnt[NFSV4OP_RENEW], 746 ext_nfsstats.srvrpccnt[NFSV4OP_RESTOREFH], 747 ext_nfsstats.srvrpccnt[NFSV4OP_SAVEFH], 748 ext_nfsstats.srvrpccnt[NFSV4OP_SECINFO], 749 ext_nfsstats.srvrpccnt[NFSV4OP_RELEASELCKOWN], 750 ext_nfsstats.srvrpccnt[NFSV4OP_CREATE]); 751 if (printtitle) { 752 printf("Server:\n"); 753 printf("%9.9s %9.9s %9.9s\n", 754 "Retfailed", "Faults", "Clients"); 755 } 756 printf("%9d %9d %9d\n", 757 ext_nfsstats.srv_errs, ext_nfsstats.srvrpc_errs, 758 ext_nfsstats.srvclients); 759 if (printtitle) 760 printf("%9.9s %9.9s %9.9s %9.9s %9.9s \n", 761 "OpenOwner", "Opens", "LockOwner", 762 "Locks", "Delegs"); 763 printf("%9d %9d %9d %9d %9d \n", 764 ext_nfsstats.srvopenowners, 765 ext_nfsstats.srvopens, 766 ext_nfsstats.srvlockowners, 767 ext_nfsstats.srvlocks, 768 ext_nfsstats.srvdelegates); 769 if (printtitle) { 770 printf("Server Cache Stats:\n"); 771 printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n", 772 "Inprog", "Idem", "Non-idem", "Misses", 773 "CacheSize", "TCPPeak"); 774 } 775 printf("%9d %9d %9d %9d %9d %9d\n", 776 ext_nfsstats.srvcache_inproghits, 777 ext_nfsstats.srvcache_idemdonehits, 778 ext_nfsstats.srvcache_nonidemdonehits, 779 ext_nfsstats.srvcache_misses, 780 ext_nfsstats.srvcache_size, 781 ext_nfsstats.srvcache_tcppeak); 782 } 783 } 784 785 /* 786 * Print a running summary of nfs statistics for the experimental client and/or 787 * server. 788 * Repeat display every interval seconds, showing statistics 789 * collected over that interval. Assumes that interval is non-zero. 790 * First line printed at top of screen is always cumulative. 791 */ 792 void 793 exp_sidewaysintpr(u_int interval, int clientOnly, int serverOnly) 794 { 795 struct ext_nfsstats nfsstats, lastst, *ext_nfsstatsp; 796 int hdrcnt = 1; 797 798 ext_nfsstatsp = &lastst; 799 if (nfssvc(NFSSVC_GETSTATS, ext_nfsstatsp) < 0) 800 err(1, "Can't get stats"); 801 sleep(interval); 802 803 for (;;) { 804 ext_nfsstatsp = &nfsstats; 805 if (nfssvc(NFSSVC_GETSTATS, ext_nfsstatsp) < 0) 806 err(1, "Can't get stats"); 807 808 if (--hdrcnt == 0) { 809 printhdr(clientOnly, serverOnly); 810 if (clientOnly && serverOnly) 811 hdrcnt = 10; 812 else 813 hdrcnt = 20; 814 } 815 if (clientOnly) { 816 printf("%s %6d %6d %6d %6d %6d %6d %6d %6d", 817 ((clientOnly && serverOnly) ? "Client:" : ""), 818 DELTA(attrcache_hits) + DELTA(attrcache_misses), 819 DELTA(lookupcache_hits) + DELTA(lookupcache_misses), 820 DELTA(biocache_readlinks), 821 DELTA(biocache_reads), 822 DELTA(biocache_writes), 823 nfsstats.rpccnt[NFSPROC_RENAME] - 824 lastst.rpccnt[NFSPROC_RENAME], 825 DELTA(accesscache_hits) + DELTA(accesscache_misses), 826 DELTA(biocache_readdirs) 827 ); 828 if (widemode) { 829 printf(" %s %s %s %s %s %s", 830 sperc1(DELTA(attrcache_hits), 831 DELTA(attrcache_misses)), 832 sperc1(DELTA(lookupcache_hits), 833 DELTA(lookupcache_misses)), 834 sperc2(DELTA(biocache_reads), 835 DELTA(read_bios)), 836 sperc2(DELTA(biocache_writes), 837 DELTA(write_bios)), 838 sperc1(DELTA(accesscache_hits), 839 DELTA(accesscache_misses)), 840 sperc2(DELTA(biocache_readdirs), 841 DELTA(readdir_bios)) 842 ); 843 } 844 printf("\n"); 845 lastst = nfsstats; 846 } 847 if (serverOnly) { 848 printf("%s %6d %6d %6d %6d %6d %6d %6d %6d", 849 ((clientOnly && serverOnly) ? "Server:" : ""), 850 nfsstats.srvrpccnt[NFSPROC_GETATTR] - 851 lastst.srvrpccnt[NFSPROC_GETATTR], 852 nfsstats.srvrpccnt[NFSPROC_LOOKUP] - 853 lastst.srvrpccnt[NFSPROC_LOOKUP], 854 nfsstats.srvrpccnt[NFSPROC_READLINK] - 855 lastst.srvrpccnt[NFSPROC_READLINK], 856 nfsstats.srvrpccnt[NFSPROC_READ] - 857 lastst.srvrpccnt[NFSPROC_READ], 858 nfsstats.srvrpccnt[NFSPROC_WRITE] - 859 lastst.srvrpccnt[NFSPROC_WRITE], 860 nfsstats.srvrpccnt[NFSPROC_RENAME] - 861 lastst.srvrpccnt[NFSPROC_RENAME], 862 nfsstats.srvrpccnt[NFSPROC_ACCESS] - 863 lastst.srvrpccnt[NFSPROC_ACCESS], 864 (nfsstats.srvrpccnt[NFSPROC_READDIR] - 865 lastst.srvrpccnt[NFSPROC_READDIR]) + 866 (nfsstats.srvrpccnt[NFSPROC_READDIRPLUS] - 867 lastst.srvrpccnt[NFSPROC_READDIRPLUS])); 868 printf("\n"); 869 lastst = nfsstats; 870 } 871 fflush(stdout); 872 sleep(interval); 873 } 874 /*NOTREACHED*/ 875 } 876 877