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. 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 #include <sys/param.h> 64 #include <sys/module.h> 65 #include <sys/mount.h> 66 #include <sys/time.h> 67 #include <sys/sysctl.h> 68 #include <nfs/nfssvc.h> 69 70 #include <fs/nfs/nfsproto.h> 71 #include <fs/nfs/nfsport.h> 72 73 #include <signal.h> 74 #include <fcntl.h> 75 #include <ctype.h> 76 #include <errno.h> 77 #include <limits.h> 78 #include <nlist.h> 79 #include <unistd.h> 80 #include <stdio.h> 81 #include <stdint.h> 82 #include <stdlib.h> 83 #include <string.h> 84 #include <paths.h> 85 #include <devstat.h> 86 87 #include <libxo/xo.h> 88 89 static int widemode = 0; 90 static int zflag = 0; 91 static int printtitle = 1; 92 static struct nfsstatsv1 ext_nfsstats; 93 static int extra_output = 0; 94 95 static void intpr(int, int); 96 static void printhdr(int, int, int); 97 static void usage(void) __dead2; 98 static char *sperc1(int, int); 99 static char *sperc2(int, int); 100 static void exp_intpr(int, int, int); 101 static void exp_sidewaysintpr(u_int, int, int, int); 102 static void compute_new_stats(struct nfsstatsv1 *cur_stats, 103 struct nfsstatsv1 *prev_stats, int curop, long double etime, 104 long double *mbsec, long double *kb_per_transfer, 105 long double *transfers_per_second, long double *ms_per_transfer, 106 uint64_t *queue_len, long double *busy_pct); 107 108 #define DELTA(field) (nfsstats.field - lastst.field) 109 110 #define STAT_TYPE_READ 0 111 #define STAT_TYPE_WRITE 1 112 #define STAT_TYPE_COMMIT 2 113 #define NUM_STAT_TYPES 3 114 115 struct stattypes { 116 int stat_type; 117 int nfs_type; 118 }; 119 static struct stattypes statstruct[] = { 120 {STAT_TYPE_READ, NFSV4OP_READ}, 121 {STAT_TYPE_WRITE, NFSV4OP_WRITE}, 122 {STAT_TYPE_COMMIT, NFSV4OP_COMMIT} 123 }; 124 125 #define STAT_TYPE_TO_NFS(stat_type) statstruct[stat_type].nfs_type 126 127 #define NFSSTAT_XO_VERSION "1" 128 129 int 130 main(int argc, char **argv) 131 { 132 u_int interval; 133 int clientOnly = -1; 134 int serverOnly = -1; 135 int newStats = 0; 136 int ch; 137 int mntlen, i; 138 char buf[1024]; 139 struct statfs *mntbuf; 140 struct nfscl_dumpmntopts dumpmntopts; 141 142 interval = 0; 143 144 argc = xo_parse_args(argc, argv); 145 if (argc < 0) 146 exit(1); 147 148 xo_set_version(NFSSTAT_XO_VERSION); 149 150 while ((ch = getopt(argc, argv, "cdEesWM:mN:w:zq")) != -1) 151 switch(ch) { 152 case 'M': 153 printf("*** -M option deprecated, ignored\n\n"); 154 break; 155 case 'm': 156 /* Display mount options for NFS mount points. */ 157 mntlen = getmntinfo(&mntbuf, MNT_NOWAIT); 158 for (i = 0; i < mntlen; i++) { 159 if (strcmp(mntbuf->f_fstypename, "nfs") == 0) { 160 dumpmntopts.ndmnt_fname = 161 mntbuf->f_mntonname; 162 dumpmntopts.ndmnt_buf = buf; 163 dumpmntopts.ndmnt_blen = sizeof(buf); 164 if (nfssvc(NFSSVC_DUMPMNTOPTS, 165 &dumpmntopts) >= 0) 166 printf("%s on %s\n%s\n", 167 mntbuf->f_mntfromname, 168 mntbuf->f_mntonname, buf); 169 else if (errno == EPERM) 170 xo_errx(1, "Only privileged users" 171 " can use the -m option"); 172 } 173 mntbuf++; 174 } 175 exit(0); 176 case 'N': 177 printf("*** -N option deprecated, ignored\n\n"); 178 break; 179 case 'W': 180 widemode = 1; 181 break; 182 case 'w': 183 interval = atoi(optarg); 184 break; 185 case 'c': 186 clientOnly = 1; 187 if (serverOnly < 0) 188 serverOnly = 0; 189 break; 190 case 'd': 191 newStats = 1; 192 if (interval == 0) 193 interval = 1; 194 break; 195 case 's': 196 serverOnly = 1; 197 if (clientOnly < 0) 198 clientOnly = 0; 199 break; 200 case 'z': 201 zflag = 1; 202 break; 203 case 'E': 204 if (extra_output != 0) 205 xo_err(1, "-e and -E are mutually exclusive"); 206 extra_output = 2; 207 break; 208 case 'e': 209 if (extra_output != 0) 210 xo_err(1, "-e and -E are mutually exclusive"); 211 extra_output = 1; 212 break; 213 case 'q': 214 printtitle = 0; 215 break; 216 case '?': 217 default: 218 usage(); 219 } 220 argc -= optind; 221 argv += optind; 222 223 #define BACKWARD_COMPATIBILITY 224 #ifdef BACKWARD_COMPATIBILITY 225 if (*argv) 226 interval = atoi(*argv); 227 #endif 228 if (modfind("nfscommon") < 0) 229 xo_err(1, "NFS client/server not loaded"); 230 231 if (interval) { 232 exp_sidewaysintpr(interval, clientOnly, serverOnly, 233 newStats); 234 } else { 235 xo_open_container("nfsstat"); 236 if (extra_output != 0) 237 exp_intpr(clientOnly, serverOnly, extra_output - 1); 238 else 239 intpr(clientOnly, serverOnly); 240 xo_close_container("nfsstat"); 241 } 242 243 if (xo_finish() < 0) 244 xo_err(1, "stdout"); 245 exit(0); 246 } 247 248 /* 249 * Print a description of the nfs stats. 250 */ 251 static void 252 intpr(int clientOnly, int serverOnly) 253 { 254 int nfssvc_flag; 255 256 nfssvc_flag = NFSSVC_GETSTATS | NFSSVC_NEWSTRUCT; 257 if (zflag != 0) { 258 if (clientOnly != 0) 259 nfssvc_flag |= NFSSVC_ZEROCLTSTATS; 260 if (serverOnly != 0) 261 nfssvc_flag |= NFSSVC_ZEROSRVSTATS; 262 } 263 ext_nfsstats.vers = NFSSTATS_V1; 264 if (nfssvc(nfssvc_flag, &ext_nfsstats) < 0) 265 xo_err(1, "Can't get stats"); 266 if (clientOnly) { 267 xo_open_container("clientstats"); 268 269 if (printtitle) 270 xo_emit("{T:Client Info:\n"); 271 272 xo_open_container("operations"); 273 if (printtitle) 274 xo_emit("{T:Rpc Counts:}\n"); 275 276 xo_emit("{T:Getattr/%13.13s}{T:Setattr/%13.13s}" 277 "{T:Lookup/%13.13s}{T:Readlink/%13.13s}" 278 "{T:Read/%13.13s}{T:Write/%13.13s}" 279 "{T:Create/%13.13s}{T:Remove/%13.13s}\n"); 280 xo_emit("{:getattr/%13ju}{:setattr/%13ju}" 281 "{:lookup/%13ju}{:readlink/%13ju}" 282 "{:read/%13ju}{:write/%13ju}" 283 "{:create/%13ju}{:remove/%13ju}\n", 284 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_GETATTR], 285 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SETATTR], 286 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LOOKUP], 287 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READLINK], 288 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READ], 289 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_WRITE], 290 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_CREATE], 291 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_REMOVE]); 292 293 xo_emit("{T:Rename/%13.13s}{T:Link/%13.13s}" 294 "{T:Symlink/%13.13s}{T:Mkdir/%13.13s}" 295 "{T:Rmdir/%13.13s}{T:Readdir/%13.13s}" 296 "{T:RdirPlus/%13.13s}{T:Access/%13.13s}\n"); 297 xo_emit("{:rename/%13ju}{:link/%13ju}" 298 "{:symlink/%13ju}{:mkdir/%13ju}" 299 "{:rmdir/%13ju}{:readdir/%13ju}" 300 "{:rdirplus/%13ju}{:access/%13ju}\n", 301 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_RENAME], 302 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LINK], 303 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SYMLINK], 304 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_MKDIR], 305 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_RMDIR], 306 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READDIR], 307 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READDIRPLUS], 308 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_ACCESS]); 309 310 xo_emit("{T:Mknod/%13.13s}{T:Fsstat/%13.13s}" 311 "{T:Fsinfo/%13.13s}{T:PathConf/%13.13s}" 312 "{T:Commit/%13.13s}\n"); 313 xo_emit("{:mknod/%13ju}{:fsstat/%13ju}" 314 "{:fsinfo/%13ju}{:pathconf/%13ju}" 315 "{:commit/%13ju}\n", 316 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_MKNOD], 317 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_FSSTAT], 318 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_FSINFO], 319 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_PATHCONF], 320 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_COMMIT]); 321 322 xo_close_container("operations"); 323 324 xo_open_container("rpcs"); 325 if (printtitle) 326 xo_emit("{T:Rpc Info:}\n"); 327 328 xo_emit("{T:TimedOut/%13.13s}{T:Invalid/%13.13s}" 329 "{T:X Replies/%13.13s}{T:Retries/%13.13s}" 330 "{T:Requests/%13.13s}\n"); 331 xo_emit("{:timedout/%13ju}{:invalid/%13ju}" 332 "{:xreplies/%13ju}{:retries/%13ju}" 333 "{:requests/%13ju}\n", 334 (uintmax_t)ext_nfsstats.rpctimeouts, 335 (uintmax_t)ext_nfsstats.rpcinvalid, 336 (uintmax_t)ext_nfsstats.rpcunexpected, 337 (uintmax_t)ext_nfsstats.rpcretries, 338 (uintmax_t)ext_nfsstats.rpcrequests); 339 xo_close_container("rpcs"); 340 341 xo_open_container("cache"); 342 if (printtitle) 343 xo_emit("{T:Cache Info:}\n"); 344 345 xo_emit("{T:Attr Hits/%13.13s}{T:Attr Misses/%13.13s}" 346 "{T:Lkup Hits/%13.13s}{T:Lkup Misses/%13.13s}" 347 "{T:BioR Hits/%13.13s}{T:BioR Misses/%13.13s}" 348 "{T:BioW Hits/%13.13s}{T:BioW Misses/%13.13s}\n"); 349 xo_emit("{:attrhits/%13ju}{:attrmisses/%13ju}" 350 "{:lkuphits/%13ju}{:lkupmisses/%13ju}" 351 "{:biorhits/%13ju}{:biormisses/%13ju}" 352 "{:biowhits/%13ju}{:biowmisses/%13ju}\n", 353 (uintmax_t)ext_nfsstats.attrcache_hits, 354 (uintmax_t)ext_nfsstats.attrcache_misses, 355 (uintmax_t)ext_nfsstats.lookupcache_hits, 356 (uintmax_t)ext_nfsstats.lookupcache_misses, 357 (uintmax_t)(ext_nfsstats.biocache_reads - 358 ext_nfsstats.read_bios), 359 (uintmax_t)ext_nfsstats.read_bios, 360 (uintmax_t)(ext_nfsstats.biocache_writes - 361 ext_nfsstats.write_bios), 362 (uintmax_t)ext_nfsstats.write_bios); 363 364 xo_emit("{T:BioRL Hits/%13.13s}{T:BioRL Misses/%13.13s}" 365 "{T:BioD Hits/%13.13s}{T:BioD Misses/%13.13s}" 366 "{T:DirE Hits/%13.13s}{T:DirE Misses/%13.13s}" 367 "{T:Accs Hits/%13.13s}{T:Accs Misses/%13.13s}\n"); 368 xo_emit("{:biosrlhits/%13ju}{:biorlmisses/%13ju}" 369 "{:biodhits/%13ju}{:biodmisses/%13ju}" 370 "{:direhits/%13ju}{:diremisses/%13ju}" 371 "{:accshits/%13ju}{:accsmisses/%13ju}\n", 372 (uintmax_t)(ext_nfsstats.biocache_readlinks - 373 ext_nfsstats.readlink_bios), 374 (uintmax_t)ext_nfsstats.readlink_bios, 375 (uintmax_t)(ext_nfsstats.biocache_readdirs - 376 ext_nfsstats.readdir_bios), 377 (uintmax_t)ext_nfsstats.readdir_bios, 378 (uintmax_t)ext_nfsstats.direofcache_hits, 379 (uintmax_t)ext_nfsstats.direofcache_misses, 380 (uintmax_t)ext_nfsstats.accesscache_hits, 381 (uintmax_t)ext_nfsstats.accesscache_misses); 382 383 xo_close_container("cache"); 384 385 xo_close_container("clientstats"); 386 } 387 if (serverOnly) { 388 xo_open_container("serverstats"); 389 390 if (printtitle) 391 xo_emit("{T:Server Info:}\n"); 392 xo_open_container("operations"); 393 394 xo_emit("{T:Getattr/%13.13s}{T:Setattr/%13.13s}" 395 "{T:Lookup/%13.13s}{T:Readlink/%13.13s}" 396 "{T:Read/%13.13s}{T:Write/%13.13s}" 397 "{T:Create/%13.13s}{T:Remove/%13.13s}\n"); 398 xo_emit("{:getattr/%13ju}{:setattr/%13ju}" 399 "{:lookup/%13ju}{:readlink/%13ju}" 400 "{:read/%13ju}{:write/%13ju}" 401 "{:create/%13ju}{:remove/%13ju}\n", 402 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_GETATTR], 403 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SETATTR], 404 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LOOKUP], 405 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READLINK], 406 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READ], 407 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_WRITE], 408 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_CREATE], 409 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_REMOVE]); 410 411 xo_emit("{T:Rename/%13.13s}{T:Link/%13.13s}" 412 "{T:Symlink/%13.13s}{T:Mkdir/%13.13s}" 413 "{T:Rmdir/%13.13s}{T:Readdir/%13.13s}" 414 "{T:RdirPlus/%13.13s}{T:Access/%13.13s}\n"); 415 xo_emit("{:rename/%13ju}{:link/%13ju}" 416 "{:symlink/%13ju}{:mkdir/%13ju}" 417 "{:rmdir/%13ju}{:readdir/%13ju}" 418 "{:rdirplus/%13ju}{:access/%13ju}\n", 419 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RENAME], 420 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LINK], 421 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SYMLINK], 422 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_MKDIR], 423 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RMDIR], 424 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READDIR], 425 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READDIRPLUS], 426 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_ACCESS]); 427 428 xo_emit("{T:Mknod/%13.13s}{T:Fsstat/%13.13s}" 429 "{T:Fsinfo/%13.13s}{T:PathConf/%13.13s}" 430 "{T:Commit/%13.13s}\n"); 431 xo_emit("{:mknod/%13ju}{:fsstat/%13ju}" 432 "{:fsinfo/%13ju}{:pathconf/%13ju}" 433 "{:commit/%13ju}\n", 434 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_MKNOD], 435 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_FSSTAT], 436 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_FSINFO], 437 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_PATHCONF], 438 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_COMMIT]); 439 440 xo_close_container("operations"); 441 442 xo_open_container("server"); 443 444 if (printtitle) 445 xo_emit("{T:Server Write Gathering:/%13.13s}\n"); 446 447 xo_emit("{T:WriteOps/%13.13s}{T:WriteRPC/%13.13s}" 448 "{T:Opsaved/%13.13s}\n"); 449 xo_emit("{:writeops/%13ju}{:writerpc/%13ju}" 450 "{:opsaved/%13ju}\n", 451 /* 452 * The new client doesn't do write gathering. It was 453 * only useful for NFSv2. 454 */ 455 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_WRITE], 456 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_WRITE], 0); 457 458 xo_close_container("server"); 459 460 xo_open_container("cache"); 461 if (printtitle) 462 xo_emit("{T:Server Cache Stats:/%13.13s}\n"); 463 xo_emit("{T:Inprog/%13.13s}" 464 "{T:Non-Idem/%13.13s}{T:Misses/%13.13s}\n"); 465 xo_emit("{:inprog/%13ju}{:nonidem/%13ju}{:misses/%13ju}\n", 466 (uintmax_t)ext_nfsstats.srvcache_inproghits, 467 (uintmax_t)ext_nfsstats.srvcache_nonidemdonehits, 468 (uintmax_t)ext_nfsstats.srvcache_misses); 469 xo_close_container("cache"); 470 471 xo_close_container("serverstats"); 472 } 473 } 474 475 static void 476 printhdr(int clientOnly, int serverOnly, int newStats) 477 { 478 479 if (newStats) { 480 printf(" [%s Read %s] [%s Write %s] " 481 "%s[=========== Total ============]\n" 482 " KB/t tps MB/s%s KB/t tps MB/s%s " 483 "%sKB/t tps MB/s ms ql %%b", 484 widemode ? "========" : "=====", 485 widemode ? "========" : "=====", 486 widemode ? "========" : "=====", 487 widemode ? "=======" : "====", 488 widemode ? "[Commit ] " : "", 489 widemode ? " ms" : "", 490 widemode ? " ms" : "", 491 widemode ? "tps ms " : ""); 492 } else { 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 } 501 printf("\n"); 502 fflush(stdout); 503 } 504 505 static void 506 usage(void) 507 { 508 xo_error("usage: nfsstat [-cdEemqszW] [-w wait]\n"); 509 exit(1); 510 } 511 512 static char SPBuf[64][8]; 513 static int SPIndex; 514 515 static 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 static 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 #define DELTA_T(field) \ 546 devstat_compute_etime(&cur_stats->field, \ 547 (prev_stats ? &prev_stats->field : NULL)) 548 549 /* 550 * XXX KDM mostly copied from ctlstat. We should commonize the code (and 551 * the devstat code) somehow. 552 */ 553 static void 554 compute_new_stats(struct nfsstatsv1 *cur_stats, 555 struct nfsstatsv1 *prev_stats, int curop, 556 long double etime, long double *mbsec, 557 long double *kb_per_transfer, 558 long double *transfers_per_second, 559 long double *ms_per_transfer, uint64_t *queue_len, 560 long double *busy_pct) 561 { 562 uint64_t total_bytes = 0, total_operations = 0; 563 struct bintime total_time_bt; 564 struct timespec total_time_ts; 565 566 bzero(&total_time_bt, sizeof(total_time_bt)); 567 bzero(&total_time_ts, sizeof(total_time_ts)); 568 569 total_bytes = cur_stats->srvbytes[curop]; 570 total_operations = cur_stats->srvops[curop]; 571 if (prev_stats != NULL) { 572 total_bytes -= prev_stats->srvbytes[curop]; 573 total_operations -= prev_stats->srvops[curop]; 574 } 575 576 *mbsec = total_bytes; 577 *mbsec /= 1024 * 1024; 578 if (etime > 0.0) { 579 *busy_pct = DELTA_T(busytime); 580 if (*busy_pct < 0) 581 *busy_pct = 0; 582 *busy_pct /= etime; 583 *busy_pct *= 100; 584 if (*busy_pct < 0) 585 *busy_pct = 0; 586 *mbsec /= etime; 587 } else { 588 *busy_pct = 0; 589 *mbsec = 0; 590 } 591 *kb_per_transfer = total_bytes; 592 *kb_per_transfer /= 1024; 593 if (total_operations > 0) 594 *kb_per_transfer /= total_operations; 595 else 596 *kb_per_transfer = 0; 597 if (etime > 0.0) { 598 *transfers_per_second = total_operations; 599 *transfers_per_second /= etime; 600 } else { 601 *transfers_per_second = 0.0; 602 } 603 604 if (total_operations > 0) { 605 *ms_per_transfer = DELTA_T(srvduration[curop]); 606 *ms_per_transfer /= total_operations; 607 *ms_per_transfer *= 1000; 608 } else 609 *ms_per_transfer = 0.0; 610 611 *queue_len = cur_stats->srvstartcnt - cur_stats->srvdonecnt; 612 } 613 614 /* 615 * Print a description of the nfs stats for the client/server, 616 * including NFSv4.1. 617 */ 618 static void 619 exp_intpr(int clientOnly, int serverOnly, int nfs41) 620 { 621 int nfssvc_flag; 622 623 xo_open_container("nfsv4"); 624 625 nfssvc_flag = NFSSVC_GETSTATS | NFSSVC_NEWSTRUCT; 626 if (zflag != 0) { 627 if (clientOnly != 0) 628 nfssvc_flag |= NFSSVC_ZEROCLTSTATS; 629 if (serverOnly != 0) 630 nfssvc_flag |= NFSSVC_ZEROSRVSTATS; 631 } 632 ext_nfsstats.vers = NFSSTATS_V1; 633 if (nfssvc(nfssvc_flag, &ext_nfsstats) < 0) 634 xo_err(1, "Can't get stats"); 635 if (clientOnly != 0) { 636 xo_open_container("clientstats"); 637 638 xo_open_container("operations"); 639 if (printtitle) { 640 xo_emit("{T:Client Info:}\n"); 641 xo_emit("{T:RPC Counts:}\n"); 642 } 643 xo_emit("{T:Getattr/%13.13s}{T:Setattr/%13.13s}" 644 "{T:Lookup/%13.13s}{T:Readlink/%13.13s}" 645 "{T:Read/%13.13s}{T:Write/%13.13s}\n"); 646 xo_emit("{:getattr/%13ju}{:setattr/%13ju}{:lookup/%13ju}" 647 "{:readlink/%13ju}{:read/%13ju}{:write/%13ju}\n", 648 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_GETATTR], 649 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SETATTR], 650 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LOOKUP], 651 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READLINK], 652 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READ], 653 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_WRITE]); 654 xo_emit("{T:Create/%13.13s}{T:Remove/%13.13s}" 655 "{T:Rename/%13.13s}{T:Link/%13.13s}" 656 "{T:Symlink/%13.13s}{T:Mkdir/%13.13s}\n"); 657 xo_emit("{:create/%13ju}{:remove/%13ju}{:rename/%13ju}" 658 "{:link/%13ju}{:symlink/%13ju}{:mkdir/%13ju}\n", 659 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_CREATE], 660 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_REMOVE], 661 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_RENAME], 662 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LINK], 663 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SYMLINK], 664 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_MKDIR]); 665 xo_emit("{T:Rmdir/%13.13s}{T:Readdir/%13.13s}" 666 "{T:RdirPlus/%13.13s}{T:Access/%13.13s}" 667 "{T:Mknod/%13.13s}{T:Fsstat/%13.13s}\n"); 668 xo_emit("{:rmdir/%13ju}{:readdir/%13ju}{:rdirplus/%13ju}" 669 "{:access/%13ju}{:mknod/%13ju}{:fsstat/%13ju}\n", 670 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_RMDIR], 671 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READDIR], 672 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READDIRPLUS], 673 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_ACCESS], 674 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_MKNOD], 675 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_FSSTAT]); 676 xo_emit("{T:FSinfo/%13.13s}{T:pathConf/%13.13s}" 677 "{T:Commit/%13.13s}{T:SetClId/%13.13s}" 678 "{T:SetClIdCf/%13.13s}{T:Lock/%13.13s}\n"); 679 xo_emit("{:fsinfo/%13ju}{:pathconf/%13ju}{:commit/%13ju}" 680 "{:setclientid/%13ju}{:setclientidcf/%13ju}{:lock/%13ju}\n", 681 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_FSINFO], 682 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_PATHCONF], 683 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_COMMIT], 684 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SETCLIENTID], 685 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SETCLIENTIDCFRM], 686 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LOCK]); 687 xo_emit("{T:LockT/%13.13s}{T:LockU/%13.13s}" 688 "{T:Open/%13.13s}{T:OpenCfr/%13.13s}\n"); 689 xo_emit("{:lockt/%13ju}{:locku/%13ju}" 690 "{:open/%13ju}{:opencfr/%13ju}\n", 691 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LOCKT], 692 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LOCKU], 693 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_OPEN], 694 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_OPENCONFIRM]); 695 696 if (nfs41) { 697 xo_open_container("nfsv41"); 698 699 xo_emit("{T:OpenDownGr/%13.13s}{T:Close/%13.13s}\n"); 700 xo_emit("{:opendowngr/%13ju}{:close/%13ju}\n", 701 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_OPENDOWNGRADE], 702 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_CLOSE]); 703 704 xo_emit("{T:RelLckOwn/%13.13s}{T:FreeStateID/%13.13s}" 705 "{T:PutRootFH/%13.13s}{T:DelegRet/%13.13s}" 706 "{T:GetAcl/%13.13s}{T:SetAcl/%13.13s}\n"); 707 xo_emit("{:rellckown/%13ju}{:freestateid/%13ju}" 708 "{:putrootfh/%13ju}{:delegret/%13ju}" 709 "{:getacl/%13ju}{:setacl/%13ju}\n", 710 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_RELEASELCKOWN], 711 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_FREESTATEID], 712 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_PUTROOTFH], 713 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_DELEGRETURN], 714 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_GETACL], 715 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SETACL]); 716 717 xo_emit("{T:ExchangeId/%13.13s}{T:CreateSess/%13.13s}" 718 "{T:DestroySess/%13.13s}{T:DestroyClId/%13.13s}" 719 "{T:LayoutGet/%13.13s}{T:GetDevInfo/%13.13s}\n"); 720 xo_emit("{:exchangeid/%13ju}{:createsess/%13ju}" 721 "{:destroysess/%13ju}{:destroyclid/%13ju}" 722 "{:layoutget/%13ju}{:getdevinfo/%13ju}\n", 723 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_EXCHANGEID], 724 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_CREATESESSION], 725 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_DESTROYSESSION], 726 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_DESTROYCLIENT], 727 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LAYOUTGET], 728 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_GETDEVICEINFO]); 729 730 xo_emit("{T:LayoutCommit/%13.13s}{T:LayoutReturn/%13.13s}" 731 "{T:ReclaimCompl/%13.13s}{T:ReadDataS/%13.13s}" 732 "{T:WriteDataS/%13.13s}{T:CommitDataS/%13.13s}\n"); 733 xo_emit("{:layoutcomit/%13ju}{:layoutreturn/%13ju}" 734 "{:reclaimcompl/%13ju}{:readdatas/%13ju}" 735 "{:writedatas/%13ju}{:commitdatas/%13ju}\n", 736 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LAYOUTCOMMIT], 737 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LAYOUTRETURN], 738 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_RECLAIMCOMPL], 739 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READDS], 740 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_WRITEDS], 741 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_COMMITDS]); 742 743 xo_emit("{T:OpenLayout/%13.13s}{T:CreateLayout/%13.13s}" 744 "{T:BindConnSess/%13.13s}{T:LookupOpen/%13.13s}" 745 "{T:AppendWrite/%13.13s}\n"); 746 xo_emit("{:openlayout/%13ju}{:createlayout/%13ju}" 747 "{:bindconnsess/%13ju}{:lookupopen/%13ju}" 748 "{:appendwrite/%13ju}\n", 749 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_OPENLAYGET], 750 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_CREATELAYGET], 751 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_BINDCONNTOSESS], 752 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LOOKUPOPEN], 753 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_APPENDWRITE]); 754 755 xo_close_container("nfsv41"); 756 757 xo_open_container("nfsv42"); 758 759 xo_emit("{T:IOAdvise/%13.13s}{T:Allocate/%13.13s}" 760 "{T:Copy/%13.13s}{T:Seek/%13.13s}" 761 "{T:SeekDataS/%13.13s}{T:GetExtattr/%13.13s}\n"); 762 xo_emit("{:ioadvise/%13ju}{:allocate/%13ju}" 763 "{:copy/%13ju}{:seek/%13ju}" 764 "{:seekdatas/%13ju}{:getextattr/%13ju}\n", 765 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_IOADVISE], 766 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_ALLOCATE], 767 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_COPY], 768 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SEEK], 769 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SEEKDS], 770 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_GETEXTATTR]); 771 772 xo_emit("{T:SetExtattr/%13.13s}{T:RmExtattr/%13.13s}" 773 "{T:ListExtattr/%13.13s}{T:Deallocate/%13.13s}" 774 "{T:LayoutError/%13.13s}\n"); 775 xo_emit("{:setextattr/%13ju}{:rmextattr/%13ju}" 776 "{:listextattr/%13ju}{:deallocate/%13ju}" 777 "{:layouterror/%13ju}\n", 778 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SETEXTATTR], 779 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_RMEXTATTR], 780 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LISTEXTATTR], 781 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_DEALLOCATE], 782 (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LAYOUTERROR]); 783 784 xo_close_container("nfsv42"); 785 } 786 xo_close_container("operations"); 787 788 if (printtitle) 789 xo_emit("{T:Client:}\n"); 790 xo_open_container("client"); 791 xo_emit("{T:OpenOwner/%13.13s}{T:Opens/%13.13s}" 792 "{T:LockOwner/%13.13s}{T:Locks/%13.13s}" 793 "{T:Delegs/%13.13s}{T:LocalOwn/%13.13s}\n"); 794 xo_emit("{:openowner/%13ju}{:opens/%13ju}" 795 "{:lockowner/%13ju}{:locks/%13ju}" 796 "{:delegs/%13ju}{:localown/%13ju}\n", 797 (uintmax_t)ext_nfsstats.clopenowners, 798 (uintmax_t)ext_nfsstats.clopens, 799 (uintmax_t)ext_nfsstats.cllockowners, 800 (uintmax_t)ext_nfsstats.cllocks, 801 (uintmax_t)ext_nfsstats.cldelegates, 802 (uintmax_t)ext_nfsstats.cllocalopenowners); 803 804 xo_emit("{T:LocalOpen/%13.13s}{T:LocalLown/%13.13s}" 805 "{T:LocalLock/%13.13s}{T:Layouts/%13.13s}\n"); 806 xo_emit("{:localopen/%13ju}{:locallown/%13ju}" 807 "{:locallock/%13ju}{:layouts/%13ju}\n", 808 (uintmax_t)ext_nfsstats.cllocalopens, 809 (uintmax_t)ext_nfsstats.cllocallockowners, 810 (uintmax_t)ext_nfsstats.cllocallocks, 811 (uintmax_t)ext_nfsstats.cllayouts); 812 xo_close_container("client"); 813 814 xo_open_container("rpc"); 815 if (printtitle) 816 xo_emit("{T:Rpc Info:}\n"); 817 xo_emit("{T:TimedOut/%13.13s}{T:Invalid/%13.13s}" 818 "{T:X Replies/%13.13s}{T:Retries/%13.13s}" 819 "{T:Requests/%13.13s}\n"); 820 xo_emit("{:timedout/%13ju}{:invalid/%13ju}" 821 "{:xreplies/%13ju}{:retries/%13ju}" 822 "{:requests/%13ju}\n", 823 (uintmax_t)ext_nfsstats.rpctimeouts, 824 (uintmax_t)ext_nfsstats.rpcinvalid, 825 (uintmax_t)ext_nfsstats.rpcunexpected, 826 (uintmax_t)ext_nfsstats.rpcretries, 827 (uintmax_t)ext_nfsstats.rpcrequests); 828 xo_close_container("rpc"); 829 830 xo_open_container("cache"); 831 if (printtitle) 832 xo_emit("{T:Cache Info:}\n"); 833 xo_emit("{T:Attr Hits/%13.13s}{T:Attr Misses/%13.13s}" 834 "{T:Lkup Hits/%13.13s}{T:Lkup Misses/%13.13s}\n"); 835 xo_emit("{:attrhits/%13ju}{:attrmisses/%13ju}" 836 "{:lkuphits/%13ju}{:lkupmisses/%13ju}\n", 837 (uintmax_t)ext_nfsstats.attrcache_hits, 838 (uintmax_t)ext_nfsstats.attrcache_misses, 839 (uintmax_t)ext_nfsstats.lookupcache_hits, 840 (uintmax_t)ext_nfsstats.lookupcache_misses); 841 842 xo_emit("{T:BioR Hits/%13.13s}{T:BioR Misses/%13.13s}" 843 "{T:BioW Hits/%13.13s}{T:BioW Misses/%13.13s}\n"); 844 xo_emit("{:biorhits/%13ju}{:biormisses/%13ju}" 845 "{:biowhits/%13ju}{:biowmisses/%13ju}\n", 846 (uintmax_t)(ext_nfsstats.biocache_reads - 847 ext_nfsstats.read_bios), 848 (uintmax_t)ext_nfsstats.read_bios, 849 (uintmax_t)(ext_nfsstats.biocache_writes - 850 ext_nfsstats.write_bios), 851 (uintmax_t)ext_nfsstats.write_bios); 852 853 xo_emit("{T:BioRL Hits/%13.13s}{T:BioRL Misses/%13.13s}" 854 "{T:BioD Hits/%13.13s}{T:BioD Misses/%13.13s}\n"); 855 xo_emit("{:biorlhits/%13ju}{:biorlmisses/%13ju}" 856 "{:biodhits/%13ju}{:biodmisses/%13ju}\n", 857 (uintmax_t)(ext_nfsstats.biocache_readlinks - 858 ext_nfsstats.readlink_bios), 859 (uintmax_t)ext_nfsstats.readlink_bios, 860 (uintmax_t)(ext_nfsstats.biocache_readdirs - 861 ext_nfsstats.readdir_bios), 862 (uintmax_t)ext_nfsstats.readdir_bios); 863 864 xo_emit("{T:DirE Hits/%13.13s}{T:DirE Misses/%13.13s}\n"); 865 xo_emit("{:direhits/%13ju}{:diremisses/%13ju}\n", 866 (uintmax_t)ext_nfsstats.direofcache_hits, 867 (uintmax_t)ext_nfsstats.direofcache_misses); 868 xo_open_container("cache"); 869 870 xo_close_container("clientstats"); 871 } 872 if (serverOnly != 0) { 873 xo_open_container("serverstats"); 874 875 xo_open_container("operations"); 876 if (printtitle) 877 xo_emit("{T:Server Info:}\n"); 878 xo_emit("{T:Getattr/%13.13s}{T:Setattr/%13.13s}" 879 "{T:Lookup/%13.13s}{T:Readlink/%13.13s}" 880 "{T:Read/%13.13s}{T:Write/%13.13s}\n"); 881 xo_emit("{:getattr/%13ju}{:setattr/%13ju}{:lookup/%13ju}" 882 "{:readlink/%13ju}{:read/%13ju}{:write/%13ju}\n", 883 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_GETATTR], 884 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SETATTR], 885 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LOOKUP], 886 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READLINK], 887 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READ], 888 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_WRITE]); 889 xo_emit("{T:Create/%13.13s}{T:Remove/%13.13s}" 890 "{T:Rename/%13.13s}{T:Link/%13.13s}" 891 "{T:Symlink/%13.13s}{T:Mkdir/%13.13s}\n"); 892 xo_emit("{:create/%13ju}{:remove/%13ju}{:rename/%13ju}" 893 "{:link/%13ju}{:symlink/%13ju}{:mkdir/%13ju}\n", 894 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_V3CREATE], 895 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_REMOVE], 896 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RENAME], 897 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LINK], 898 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SYMLINK], 899 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_MKDIR]); 900 xo_emit("{T:Rmdir/%13.13s}{T:Readdir/%13.13s}" 901 "{T:RdirPlus/%13.13s}{T:Access/%13.13s}" 902 "{T:Mknod/%13.13s}{T:Fsstat/%13.13s}\n"); 903 xo_emit("{:rmdir/%13ju}{:readdir/%13ju}{:rdirplus/%13ju}" 904 "{:access/%13ju}{:mknod/%13ju}{:fsstat/%13ju}\n", 905 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RMDIR], 906 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READDIR], 907 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READDIRPLUS], 908 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_ACCESS], 909 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_MKNOD], 910 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_FSSTAT]); 911 xo_emit("{T:FSinfo/%13.13s}{T:pathConf/%13.13s}" 912 "{T:Commit/%13.13s}{T:LookupP/%13.13s}" 913 "{T:SetClId/%13.13s}{T:SetClIdCf/%13.13s}\n"); 914 xo_emit("{:fsinfo/%13ju}{:pathconf/%13ju}{:commit/%13ju}" 915 "{:lookupp/%13ju}{:setclientid/%13ju}{:setclientidcfrm/%13ju}\n", 916 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_FSINFO], 917 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_PATHCONF], 918 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_COMMIT], 919 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LOOKUPP], 920 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SETCLIENTID], 921 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SETCLIENTIDCFRM]); 922 xo_emit("{T:Open/%13.13s}{T:OpenAttr/%13.13s}" 923 "{T:OpenDwnGr/%13.13s}{T:OpenCfrm/%13.13s}" 924 "{T:DelePurge/%13.13s}{T:DelRet/%13.13s}\n"); 925 xo_emit("{:open/%13ju}{:openattr/%13ju}{:opendwgr/%13ju}" 926 "{:opencfrm/%13ju}{:delepurge/%13ju}{:delreg/%13ju}\n", 927 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_OPEN], 928 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_OPENATTR], 929 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_OPENDOWNGRADE], 930 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_OPENCONFIRM], 931 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_DELEGPURGE], 932 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_DELEGRETURN]); 933 xo_emit("{T:GetFH/%13.13s}{T:Lock/%13.13s}" 934 "{T:LockT/%13.13s}{T:LockU/%13.13s}" 935 "{T:Close/%13.13s}{T:Verify/%13.13s}\n"); 936 xo_emit("{:getfh/%13ju}{:lock/%13ju}{:lockt/%13ju}" 937 "{:locku/%13ju}{:close/%13ju}{:verify/%13ju}\n", 938 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_GETFH], 939 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LOCK], 940 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LOCKT], 941 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LOCKU], 942 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_CLOSE], 943 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_VERIFY]); 944 xo_emit("{T:NVerify/%13.13s}{T:PutFH/%13.13s}" 945 "{T:PutPubFH/%13.13s}{T:PutRootFH/%13.13s}" 946 "{T:Renew/%13.13s}{T:RestoreFH/%13.13s}\n"); 947 xo_emit("{:nverify/%13ju}{:putfh/%13ju}{:putpubfh/%13ju}" 948 "{:putrootfh/%13ju}{:renew/%13ju}{:restore/%13ju}\n", 949 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_NVERIFY], 950 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_PUTFH], 951 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_PUTPUBFH], 952 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_PUTROOTFH], 953 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RENEW], 954 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RESTOREFH]); 955 xo_emit("{T:SaveFH/%13.13s}{T:Secinfo/%13.13s}" 956 "{T:RelLockOwn/%13.13s}{T:V4Create/%13.13s}\n"); 957 xo_emit("{:savefh/%13ju}{:secinfo/%13ju}{:rellockown/%13ju}" 958 "{:v4create/%13ju}\n", 959 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SAVEFH], 960 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SECINFO], 961 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RELEASELCKOWN], 962 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_CREATE]); 963 if (nfs41) { 964 xo_open_container("nfsv41"); 965 xo_emit("{T:BackChannelCtrl/%13.13s}{T:BindConnToSess/%13.13s}" 966 "{T:ExchangeID/%13.13s}{T:CreateSess/%13.13s}" 967 "{T:DestroySess/%13.13s}{T:FreeStateID/%13.13s}\n"); 968 xo_emit("{:backchannelctrl/%13ju}{:bindconntosess/%13ju}" 969 "{:exchangeid/%13ju}{:createsess/%13ju}" 970 "{:destroysess/%13ju}{:freestateid/%13ju}\n", 971 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_BACKCHANNELCTL], 972 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_BINDCONNTOSESS], 973 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_EXCHANGEID], 974 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_CREATESESSION], 975 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_DESTROYSESSION], 976 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_FREESTATEID]), 977 978 xo_emit("{T:GetDirDeleg/%13.13s}{T:GetDevInfo/%13.13s}" 979 "{T:GetDevList/%13.13s}{T:layoutCommit/%13.13s}" 980 "{T:LayoutGet/%13.13s}{T:LayoutReturn/%13.13s}\n"); 981 xo_emit("{:getdirdeleg/%13ju}{:getdevinfo/%13ju}" 982 "{:getdevlist/%13ju}{:layoutcommit/%13ju}" 983 "{:layoutget/%13ju}{:layoutreturn/%13ju}\n", 984 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_GETDIRDELEG], 985 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_GETDEVINFO], 986 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_GETDEVLIST], 987 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LAYOUTCOMMIT], 988 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LAYOUTGET], 989 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LAYOUTRETURN]); 990 991 xo_emit("{T:SecInfNoName/%13.13s}{T:Sequence/%13.13s}" 992 "{T:SetSSV/%13.13s}{T:TestStateID/%13.13s}" 993 "{T:WantDeleg/%13.13s}{T:DestroyClId/%13.13s}\n"); 994 xo_emit("{:secinfnoname/%13ju}{:sequence/%13ju}" 995 "{:setssv/%13ju}{:teststateid/%13ju}{:wantdeleg/%13ju}" 996 "{:destroyclid/%13ju}\n", 997 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SECINFONONAME], 998 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SEQUENCE], 999 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SETSSV], 1000 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_TESTSTATEID], 1001 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_WANTDELEG], 1002 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_DESTROYCLIENTID]); 1003 1004 xo_emit("{T:ReclaimCompl/%13.13s}\n"); 1005 xo_emit("{:reclaimcompl/%13ju}\n", 1006 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RECLAIMCOMPL]); 1007 1008 xo_close_container("nfsv41"); 1009 1010 xo_open_container("nfsv42"); 1011 1012 xo_emit("{T:Allocate/%13.13s}{T:Copy/%13.13s}" 1013 "{T:CopyNotify/%13.13s}{T:Deallocate/%13.13s}" 1014 "{T:IOAdvise/%13.13s}{T:LayoutError/%13.13s}\n"); 1015 xo_emit("{:allocate/%13ju}{:copy/%13ju}" 1016 "{:copynotify/%13ju}{:deallocate/%13ju}" 1017 "{:ioadvise/%13ju}{:layouterror/%13ju}\n", 1018 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_ALLOCATE], 1019 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_COPY], 1020 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_COPYNOTIFY], 1021 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_DEALLOCATE], 1022 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_IOADVISE], 1023 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LAYOUTERROR]); 1024 1025 xo_emit("{T:LayoutStats/%13.13s}{T:OffloadCncl/%13.13s}" 1026 "{T:OffloadStat/%13.13s}{T:ReadPlus/%13.13s}" 1027 "{T:Seek/%13.13s}{T:WriteSame/%13.13s}\n"); 1028 xo_emit("{:layoutstats/%13ju}{:offloadcncl/%13ju}" 1029 "{:offloadstat/%13ju}{:readplus/%13ju}" 1030 "{:seek/%13ju}{:writesame/%13ju}\n", 1031 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LAYOUTSTATS], 1032 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_OFFLOADCANCEL], 1033 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_OFFLOADSTATUS], 1034 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READPLUS], 1035 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SEEK], 1036 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_WRITESAME]); 1037 1038 xo_emit("{T:Clone/%13.13s}{T:GetExtattr/%13.13s}" 1039 "{T:SetExtattr/%13.13s}{T:ListExtattr/%13.13s}" 1040 "{T:RmExtattr/%13.13s}\n"); 1041 xo_emit("{:clone/%13ju}{:getextattr/%13ju}" 1042 "{:setextattr/%13ju}{:listextattr/%13ju}" 1043 "{:rmextattr/%13ju}\n", 1044 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_CLONE], 1045 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_GETXATTR], 1046 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SETXATTR], 1047 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LISTXATTRS], 1048 (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_REMOVEXATTR]); 1049 1050 xo_close_container("nfsv42"); 1051 } 1052 1053 xo_close_container("operations"); 1054 1055 if (printtitle) 1056 xo_emit("{T:Server:}\n"); 1057 xo_open_container("server"); 1058 xo_emit("{T:Clients/%13.13s}{T:OpenOwner/%13.13s}" 1059 "{T:Opens/%13.13s}{T:LockOwner/%13.13s}{T:Locks/%13.13s}" 1060 "{T:Delegs/%13.13s}\n"); 1061 xo_emit("{:clients/%13ju}{:openowner/%13ju}{:opens/%13ju}" 1062 "{:lockowner/%13ju}{:locks/%13ju}{:delegs/%13ju}\n", 1063 (uintmax_t)ext_nfsstats.srvclients, 1064 (uintmax_t)ext_nfsstats.srvopenowners, 1065 (uintmax_t)ext_nfsstats.srvopens, 1066 (uintmax_t)ext_nfsstats.srvlockowners, 1067 (uintmax_t)ext_nfsstats.srvlocks, 1068 (uintmax_t)ext_nfsstats.srvdelegates); 1069 xo_emit("{T:Layouts/%13.13s}\n"); 1070 xo_emit("{:layouts/%13ju}\n", 1071 (uintmax_t)ext_nfsstats.srvlayouts); 1072 xo_close_container("server"); 1073 1074 if (printtitle) 1075 xo_emit("{T:Server Cache Stats:}\n"); 1076 xo_open_container("cache"); 1077 xo_emit("{T:Inprog/%13.13s}" 1078 "{T:Non-idem/%13.13s}{T:Misses/%13.13s}" 1079 "{T:CacheSize/%13.13s}{T:TCPPeak/%13.13s}\n"); 1080 xo_emit("{:inprog/%13ju}{:nonidem/%13ju}" 1081 "{:misses/%13ju}{:cachesize/%13ju}{:tcppeak/%13ju}\n", 1082 (uintmax_t)ext_nfsstats.srvcache_inproghits, 1083 (uintmax_t)ext_nfsstats.srvcache_nonidemdonehits, 1084 (uintmax_t)ext_nfsstats.srvcache_misses, 1085 (uintmax_t)ext_nfsstats.srvcache_size, 1086 (uintmax_t)ext_nfsstats.srvcache_tcppeak); 1087 xo_close_container("cache"); 1088 1089 xo_close_container("serverstats"); 1090 } 1091 1092 xo_close_container("nfsv4"); 1093 } 1094 1095 static void 1096 compute_totals(struct nfsstatsv1 *total_stats, struct nfsstatsv1 *cur_stats) 1097 { 1098 int i; 1099 1100 bzero(total_stats, sizeof(*total_stats)); 1101 for (i = 0; i < (NFSV42_NOPS + NFSV4OP_FAKENOPS); i++) { 1102 total_stats->srvbytes[0] += cur_stats->srvbytes[i]; 1103 total_stats->srvops[0] += cur_stats->srvops[i]; 1104 bintime_add(&total_stats->srvduration[0], 1105 &cur_stats->srvduration[i]); 1106 total_stats->srvrpccnt[i] = cur_stats->srvrpccnt[i]; 1107 } 1108 total_stats->srvstartcnt = cur_stats->srvstartcnt; 1109 total_stats->srvdonecnt = cur_stats->srvdonecnt; 1110 total_stats->busytime = cur_stats->busytime; 1111 1112 } 1113 1114 /* 1115 * Print a running summary of nfs statistics for the experimental client and/or 1116 * server. 1117 * Repeat display every interval seconds, showing statistics 1118 * collected over that interval. Assumes that interval is non-zero. 1119 * First line printed at top of screen is always cumulative. 1120 */ 1121 static void 1122 exp_sidewaysintpr(u_int interval, int clientOnly, int serverOnly, 1123 int newStats) 1124 { 1125 struct nfsstatsv1 nfsstats, lastst, *ext_nfsstatsp; 1126 struct nfsstatsv1 curtotal, lasttotal; 1127 struct timespec ts, lastts; 1128 int hdrcnt = 1; 1129 1130 ext_nfsstatsp = &lastst; 1131 ext_nfsstatsp->vers = NFSSTATS_V1; 1132 if (nfssvc(NFSSVC_GETSTATS | NFSSVC_NEWSTRUCT, ext_nfsstatsp) < 0) 1133 xo_err(1, "Can't get stats"); 1134 clock_gettime(CLOCK_MONOTONIC, &lastts); 1135 compute_totals(&lasttotal, ext_nfsstatsp); 1136 sleep(interval); 1137 1138 for (;;) { 1139 ext_nfsstatsp = &nfsstats; 1140 ext_nfsstatsp->vers = NFSSTATS_V1; 1141 if (nfssvc(NFSSVC_GETSTATS | NFSSVC_NEWSTRUCT, ext_nfsstatsp) 1142 < 0) 1143 xo_err(1, "Can't get stats"); 1144 clock_gettime(CLOCK_MONOTONIC, &ts); 1145 1146 if (--hdrcnt == 0) { 1147 printhdr(clientOnly, serverOnly, newStats); 1148 if (newStats) 1149 hdrcnt = 20; 1150 else if (clientOnly && serverOnly) 1151 hdrcnt = 10; 1152 else 1153 hdrcnt = 20; 1154 } 1155 if (clientOnly && newStats == 0) { 1156 printf("%s %6ju %6ju %6ju %6ju %6ju %6ju %6ju %6ju", 1157 ((clientOnly && serverOnly) ? "Client:" : ""), 1158 (uintmax_t)DELTA(rpccnt[NFSPROC_GETATTR]), 1159 (uintmax_t)DELTA(rpccnt[NFSPROC_LOOKUP]), 1160 (uintmax_t)DELTA(rpccnt[NFSPROC_READLINK]), 1161 (uintmax_t)DELTA(rpccnt[NFSPROC_READ]), 1162 (uintmax_t)DELTA(rpccnt[NFSPROC_WRITE]), 1163 (uintmax_t)DELTA(rpccnt[NFSPROC_RENAME]), 1164 (uintmax_t)DELTA(rpccnt[NFSPROC_ACCESS]), 1165 (uintmax_t)(DELTA(rpccnt[NFSPROC_READDIR]) + 1166 DELTA(rpccnt[NFSPROC_READDIRPLUS])) 1167 ); 1168 if (widemode) { 1169 printf(" %s %s %s %s %s %s", 1170 sperc1(DELTA(attrcache_hits), 1171 DELTA(attrcache_misses)), 1172 sperc1(DELTA(lookupcache_hits), 1173 DELTA(lookupcache_misses)), 1174 sperc2(DELTA(biocache_reads), 1175 DELTA(read_bios)), 1176 sperc2(DELTA(biocache_writes), 1177 DELTA(write_bios)), 1178 sperc1(DELTA(accesscache_hits), 1179 DELTA(accesscache_misses)), 1180 sperc2(DELTA(biocache_readdirs), 1181 DELTA(readdir_bios)) 1182 ); 1183 } 1184 printf("\n"); 1185 } 1186 1187 if (serverOnly && newStats) { 1188 long double cur_secs, last_secs, etime; 1189 long double mbsec; 1190 long double kb_per_transfer; 1191 long double transfers_per_second; 1192 long double ms_per_transfer; 1193 uint64_t queue_len; 1194 long double busy_pct; 1195 int i; 1196 1197 cur_secs = ts.tv_sec + 1198 ((long double)ts.tv_nsec / 1000000000); 1199 last_secs = lastts.tv_sec + 1200 ((long double)lastts.tv_nsec / 1000000000); 1201 etime = cur_secs - last_secs; 1202 1203 compute_totals(&curtotal, &nfsstats); 1204 1205 for (i = 0; i < NUM_STAT_TYPES; i++) { 1206 compute_new_stats(&nfsstats, &lastst, 1207 STAT_TYPE_TO_NFS(i), etime, &mbsec, 1208 &kb_per_transfer, 1209 &transfers_per_second, 1210 &ms_per_transfer, &queue_len, 1211 &busy_pct); 1212 1213 if (i == STAT_TYPE_COMMIT) { 1214 if (widemode == 0) 1215 continue; 1216 1217 printf("%2.0Lf %7.2Lf ", 1218 transfers_per_second, 1219 ms_per_transfer); 1220 } else { 1221 printf("%5.2Lf %5.0Lf %7.2Lf ", 1222 kb_per_transfer, 1223 transfers_per_second, mbsec); 1224 if (widemode) 1225 printf("%5.2Lf ", 1226 ms_per_transfer); 1227 } 1228 } 1229 1230 compute_new_stats(&curtotal, &lasttotal, 0, etime, 1231 &mbsec, &kb_per_transfer, &transfers_per_second, 1232 &ms_per_transfer, &queue_len, &busy_pct); 1233 1234 printf("%5.2Lf %5.0Lf %7.2Lf %5.2Lf %3ju %3.0Lf\n", 1235 kb_per_transfer, transfers_per_second, mbsec, 1236 ms_per_transfer, queue_len, busy_pct); 1237 } else if (serverOnly) { 1238 printf("%s %6ju %6ju %6ju %6ju %6ju %6ju %6ju %6ju", 1239 ((clientOnly && serverOnly) ? "Server:" : ""), 1240 (uintmax_t)DELTA(srvrpccnt[NFSV4OP_GETATTR]), 1241 (uintmax_t)DELTA(srvrpccnt[NFSV4OP_LOOKUP]), 1242 (uintmax_t)DELTA(srvrpccnt[NFSV4OP_READLINK]), 1243 (uintmax_t)DELTA(srvrpccnt[NFSV4OP_READ]), 1244 (uintmax_t)DELTA(srvrpccnt[NFSV4OP_WRITE]), 1245 (uintmax_t)DELTA(srvrpccnt[NFSV4OP_RENAME]), 1246 (uintmax_t)DELTA(srvrpccnt[NFSV4OP_ACCESS]), 1247 (uintmax_t)(DELTA(srvrpccnt[NFSV4OP_READDIR]) + 1248 DELTA(srvrpccnt[NFSV4OP_READDIRPLUS]))); 1249 printf("\n"); 1250 } 1251 bcopy(&nfsstats, &lastst, sizeof(lastst)); 1252 bcopy(&curtotal, &lasttotal, sizeof(lasttotal)); 1253 lastts = ts; 1254 fflush(stdout); 1255 sleep(interval); 1256 } 1257 /*NOTREACHED*/ 1258 } 1259