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