nfsstat.c revision 52493
11590Srgrimes/* 21590Srgrimes * Copyright (c) 1983, 1989, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * This code is derived from software contributed to Berkeley by 61590Srgrimes * Rick Macklem at The University of Guelph. 71590Srgrimes * 81590Srgrimes * Redistribution and use in source and binary forms, with or without 91590Srgrimes * modification, are permitted provided that the following conditions 101590Srgrimes * are met: 111590Srgrimes * 1. Redistributions of source code must retain the above copyright 121590Srgrimes * notice, this list of conditions and the following disclaimer. 131590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141590Srgrimes * notice, this list of conditions and the following disclaimer in the 151590Srgrimes * documentation and/or other materials provided with the distribution. 161590Srgrimes * 3. All advertising materials mentioning features or use of this software 171590Srgrimes * must display the following acknowledgement: 181590Srgrimes * This product includes software developed by the University of 191590Srgrimes * California, Berkeley and its contributors. 201590Srgrimes * 4. Neither the name of the University nor the names of its contributors 211590Srgrimes * may be used to endorse or promote products derived from this software 221590Srgrimes * without specific prior written permission. 231590Srgrimes * 241590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 251590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 261590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 271590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 281590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 291590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 301590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 311590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 321590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 331590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 341590Srgrimes * SUCH DAMAGE. 351590Srgrimes */ 361590Srgrimes 371590Srgrimes#ifndef lint 381590Srgrimesstatic char copyright[] = 391590Srgrimes"@(#) Copyright (c) 1983, 1989, 1993\n\ 401590Srgrimes The Regents of the University of California. All rights reserved.\n"; 411590Srgrimes#endif /* not lint */ 421590Srgrimes 431590Srgrimes#ifndef lint 4432649Sbde#if 0 4532649Sbdestatic char sccsid[] = "@(#)nfsstat.c 8.2 (Berkeley) 3/31/95"; 4632649Sbde#endif 473819Swollmanstatic const char rcsid[] = 4850477Speter "$FreeBSD: head/usr.bin/nfsstat/nfsstat.c 52493 1999-10-25 19:39:17Z dillon $"; 491590Srgrimes#endif /* not lint */ 501590Srgrimes 511590Srgrimes#include <sys/param.h> 521590Srgrimes#include <sys/mount.h> 5311936Sphk#include <sys/time.h> 543819Swollman#include <sys/sysctl.h> 559336Sdfr#include <nfs/rpcv2.h> 569336Sdfr#include <nfs/nfsproto.h> 571590Srgrimes#include <nfs/nfs.h> 581590Srgrimes#include <signal.h> 591590Srgrimes#include <fcntl.h> 601590Srgrimes#include <ctype.h> 611590Srgrimes#include <errno.h> 621590Srgrimes#include <kvm.h> 631590Srgrimes#include <nlist.h> 641590Srgrimes#include <unistd.h> 651590Srgrimes#include <stdio.h> 661590Srgrimes#include <stdlib.h> 671590Srgrimes#include <string.h> 681590Srgrimes#include <paths.h> 693819Swollman#include <err.h> 701590Srgrimes 711590Srgrimesstruct nlist nl[] = { 721590Srgrimes#define N_NFSSTAT 0 731590Srgrimes { "_nfsstats" }, 741590Srgrimes "", 751590Srgrimes}; 761590Srgrimeskvm_t *kd; 771590Srgrimes 783819Swollmanstatic int deadkernel = 0; 7952493Sdillonstatic int widemode = 0; 801590Srgrimes 8152493Sdillonvoid intpr __P((int, int)); 8252493Sdillonvoid printhdr __P((int, int)); 8352493Sdillonvoid sidewaysintpr __P((u_int, int, int)); 849336Sdfrvoid usage __P((void)); 8552493Sdillonchar *sperc1 __P((int, int)); 8652493Sdillonchar *sperc2 __P((int, int)); 873819Swollman 8852493Sdillon#define DELTA(field) (nfsstats.field - lastst.field) 8952493Sdillon 901590Srgrimesmain(argc, argv) 911590Srgrimes int argc; 921590Srgrimes char **argv; 931590Srgrimes{ 941590Srgrimes extern int optind; 951590Srgrimes extern char *optarg; 961590Srgrimes u_int interval; 9752493Sdillon int clientOnly = -1; 9852493Sdillon int serverOnly = -1; 991590Srgrimes int ch; 1001590Srgrimes char *memf, *nlistf; 1011590Srgrimes char errbuf[80]; 1021590Srgrimes 1031590Srgrimes interval = 0; 1041590Srgrimes memf = nlistf = NULL; 10552493Sdillon while ((ch = getopt(argc, argv, "csWM:N:w:")) != -1) 1061590Srgrimes switch(ch) { 1071590Srgrimes case 'M': 1081590Srgrimes memf = optarg; 1091590Srgrimes break; 1101590Srgrimes case 'N': 1111590Srgrimes nlistf = optarg; 1121590Srgrimes break; 11352493Sdillon case 'W': 11452493Sdillon widemode = 1; 11552493Sdillon break; 1161590Srgrimes case 'w': 1171590Srgrimes interval = atoi(optarg); 1181590Srgrimes break; 11952493Sdillon case 'c': 12052493Sdillon clientOnly = 1; 12152493Sdillon if (serverOnly < 0) 12252493Sdillon serverOnly = 0; 12352493Sdillon break; 12452493Sdillon case 's': 12552493Sdillon serverOnly = 1; 12652493Sdillon if (clientOnly < 0) 12752493Sdillon clientOnly = 0; 12852493Sdillon break; 1291590Srgrimes case '?': 1301590Srgrimes default: 1311590Srgrimes usage(); 1321590Srgrimes } 1331590Srgrimes argc -= optind; 1341590Srgrimes argv += optind; 1351590Srgrimes 1361590Srgrimes#define BACKWARD_COMPATIBILITY 1371590Srgrimes#ifdef BACKWARD_COMPATIBILITY 1381590Srgrimes if (*argv) { 1391590Srgrimes interval = atoi(*argv); 1401590Srgrimes if (*++argv) { 1411590Srgrimes nlistf = *argv; 1421590Srgrimes if (*++argv) 1431590Srgrimes memf = *argv; 1441590Srgrimes } 1451590Srgrimes } 1461590Srgrimes#endif 1471590Srgrimes /* 1481590Srgrimes * Discard setgid privileges if not the running kernel so that bad 1491590Srgrimes * guys can't print interesting stuff from kernel memory. 1501590Srgrimes */ 1513819Swollman if (nlistf != NULL || memf != NULL) { 1521590Srgrimes setgid(getgid()); 1533819Swollman deadkernel = 1; 1541590Srgrimes 1553819Swollman if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, 1563819Swollman errbuf)) == 0) { 1573819Swollman errx(1, "kvm_openfiles: %s", errbuf); 1583819Swollman } 1593819Swollman if (kvm_nlist(kd, nl) != 0) { 1603819Swollman errx(1, "kvm_nlist: can't get names"); 1613819Swollman } 1621590Srgrimes } 1631590Srgrimes 1641590Srgrimes if (interval) 16552493Sdillon sidewaysintpr(interval, clientOnly, serverOnly); 1661590Srgrimes else 16752493Sdillon intpr(clientOnly, serverOnly); 1681590Srgrimes exit(0); 1691590Srgrimes} 1701590Srgrimes 1711590Srgrimes/* 1723819Swollman * Read the nfs stats using sysctl(3) for live kernels, or kvm_read 1733819Swollman * for dead ones. 1743819Swollman */ 1753819Swollmanvoid 1769336Sdfrreadstats(stp) 1779336Sdfr struct nfsstats *stp; 1783819Swollman{ 1793819Swollman if(deadkernel) { 1803819Swollman if(kvm_read(kd, (u_long)nl[N_NFSSTAT].n_value, stp, 1813819Swollman sizeof *stp) < 0) { 1823819Swollman err(1, "kvm_read"); 1833819Swollman } 1843819Swollman } else { 18540638Sbde int name[3]; 1863819Swollman size_t buflen = sizeof *stp; 18740638Sbde struct vfsconf vfc; 1883819Swollman 18940638Sbde if (getvfsbyname("nfs", &vfc) < 0) 19040638Sbde err(1, "getvfsbyname: NFS not compiled into kernel"); 19140638Sbde name[0] = CTL_VFS; 19240638Sbde name[1] = vfc.vfc_typenum; 19340638Sbde name[2] = NFS_NFSSTATS; 19440638Sbde if (sysctl(name, 3, stp, &buflen, (void *)0, (size_t)0) < 0) { 1953819Swollman err(1, "sysctl"); 1963819Swollman } 1973819Swollman } 1983819Swollman} 1993819Swollman 2003819Swollman/* 2011590Srgrimes * Print a description of the nfs stats. 2021590Srgrimes */ 2031590Srgrimesvoid 20452493Sdillonintpr(int clientOnly, int serverOnly) 2051590Srgrimes{ 2061590Srgrimes struct nfsstats nfsstats; 2071590Srgrimes 2083819Swollman readstats(&nfsstats); 2093819Swollman 21052493Sdillon if (clientOnly) { 21152493Sdillon printf("Client Info:\n"); 21252493Sdillon printf("Rpc Counts:\n"); 21352493Sdillon printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n", 21452493Sdillon "Getattr", "Setattr", "Lookup", "Readlink", "Read", 21552493Sdillon "Write", "Create", "Remove"); 21652493Sdillon printf("%9d %9d %9d %9d %9d %9d %9d %9d\n", 21752493Sdillon nfsstats.rpccnt[NFSPROC_GETATTR], 21852493Sdillon nfsstats.rpccnt[NFSPROC_SETATTR], 21952493Sdillon nfsstats.rpccnt[NFSPROC_LOOKUP], 22052493Sdillon nfsstats.rpccnt[NFSPROC_READLINK], 22152493Sdillon nfsstats.rpccnt[NFSPROC_READ], 22252493Sdillon nfsstats.rpccnt[NFSPROC_WRITE], 22352493Sdillon nfsstats.rpccnt[NFSPROC_CREATE], 22452493Sdillon nfsstats.rpccnt[NFSPROC_REMOVE]); 22552493Sdillon printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n", 22652493Sdillon "Rename", "Link", "Symlink", "Mkdir", "Rmdir", 22752493Sdillon "Readdir", "RdirPlus", "Access"); 22852493Sdillon printf("%9d %9d %9d %9d %9d %9d %9d %9d\n", 22952493Sdillon nfsstats.rpccnt[NFSPROC_RENAME], 23052493Sdillon nfsstats.rpccnt[NFSPROC_LINK], 23152493Sdillon nfsstats.rpccnt[NFSPROC_SYMLINK], 23252493Sdillon nfsstats.rpccnt[NFSPROC_MKDIR], 23352493Sdillon nfsstats.rpccnt[NFSPROC_RMDIR], 23452493Sdillon nfsstats.rpccnt[NFSPROC_READDIR], 23552493Sdillon nfsstats.rpccnt[NFSPROC_READDIRPLUS], 23652493Sdillon nfsstats.rpccnt[NFSPROC_ACCESS]); 23752493Sdillon printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n", 23852493Sdillon "Mknod", "Fsstat", "Fsinfo", "PathConf", "Commit", 23952493Sdillon "GLease", "Vacate", "Evict"); 24052493Sdillon printf("%9d %9d %9d %9d %9d %9d %9d %9d\n", 24152493Sdillon nfsstats.rpccnt[NFSPROC_MKNOD], 24252493Sdillon nfsstats.rpccnt[NFSPROC_FSSTAT], 24352493Sdillon nfsstats.rpccnt[NFSPROC_FSINFO], 24452493Sdillon nfsstats.rpccnt[NFSPROC_PATHCONF], 24552493Sdillon nfsstats.rpccnt[NFSPROC_COMMIT], 24652493Sdillon nfsstats.rpccnt[NQNFSPROC_GETLEASE], 24752493Sdillon nfsstats.rpccnt[NQNFSPROC_VACATED], 24852493Sdillon nfsstats.rpccnt[NQNFSPROC_EVICTED]); 24952493Sdillon printf("Rpc Info:\n"); 25052493Sdillon printf("%9.9s %9.9s %9.9s %9.9s %9.9s\n", 25152493Sdillon "TimedOut", "Invalid", "X Replies", "Retries", 25252493Sdillon "Requests"); 25352493Sdillon printf("%9d %9d %9d %9d %9d\n", 25452493Sdillon nfsstats.rpctimeouts, 25552493Sdillon nfsstats.rpcinvalid, 25652493Sdillon nfsstats.rpcunexpected, 25752493Sdillon nfsstats.rpcretries, 25852493Sdillon nfsstats.rpcrequests); 25952493Sdillon printf("Cache Info:\n"); 26052493Sdillon printf("%9.9s %9.9s %9.9s %9.9s", 26152493Sdillon "Attr Hits", "Misses", "Lkup Hits", "Misses"); 26252493Sdillon printf(" %9.9s %9.9s %9.9s %9.9s\n", 26352493Sdillon "BioR Hits", "Misses", "BioW Hits", "Misses"); 26452493Sdillon printf("%9d %9d %9d %9d", 26552493Sdillon nfsstats.attrcache_hits, nfsstats.attrcache_misses, 26652493Sdillon nfsstats.lookupcache_hits, nfsstats.lookupcache_misses); 26752493Sdillon printf(" %9d %9d %9d %9d\n", 26852493Sdillon nfsstats.biocache_reads-nfsstats.read_bios, 26952493Sdillon nfsstats.read_bios, 27052493Sdillon nfsstats.biocache_writes-nfsstats.write_bios, 27152493Sdillon nfsstats.write_bios); 27252493Sdillon printf("%9.9s %9.9s %9.9s %9.9s", 27352493Sdillon "BioRLHits", "Misses", "BioD Hits", "Misses"); 27452493Sdillon printf(" %9.9s %9.9s\n", "DirE Hits", "Misses"); 27552493Sdillon printf("%9d %9d %9d %9d", 27652493Sdillon nfsstats.biocache_readlinks-nfsstats.readlink_bios, 27752493Sdillon nfsstats.readlink_bios, 27852493Sdillon nfsstats.biocache_readdirs-nfsstats.readdir_bios, 27952493Sdillon nfsstats.readdir_bios); 28052493Sdillon printf(" %9d %9d\n", 28152493Sdillon nfsstats.direofcache_hits, nfsstats.direofcache_misses); 28252493Sdillon } 28352493Sdillon if (serverOnly) { 28452493Sdillon printf("\nServer Info:\n"); 28552493Sdillon printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n", 28652493Sdillon "Getattr", "Setattr", "Lookup", "Readlink", "Read", 28752493Sdillon "Write", "Create", "Remove"); 28852493Sdillon printf("%9d %9d %9d %9d %9d %9d %9d %9d\n", 28952493Sdillon nfsstats.srvrpccnt[NFSPROC_GETATTR], 29052493Sdillon nfsstats.srvrpccnt[NFSPROC_SETATTR], 29152493Sdillon nfsstats.srvrpccnt[NFSPROC_LOOKUP], 29252493Sdillon nfsstats.srvrpccnt[NFSPROC_READLINK], 29352493Sdillon nfsstats.srvrpccnt[NFSPROC_READ], 29452493Sdillon nfsstats.srvrpccnt[NFSPROC_WRITE], 29552493Sdillon nfsstats.srvrpccnt[NFSPROC_CREATE], 29652493Sdillon nfsstats.srvrpccnt[NFSPROC_REMOVE]); 29752493Sdillon printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n", 29852493Sdillon "Rename", "Link", "Symlink", "Mkdir", "Rmdir", 29952493Sdillon "Readdir", "RdirPlus", "Access"); 30052493Sdillon printf("%9d %9d %9d %9d %9d %9d %9d %9d\n", 30152493Sdillon nfsstats.srvrpccnt[NFSPROC_RENAME], 30252493Sdillon nfsstats.srvrpccnt[NFSPROC_LINK], 30352493Sdillon nfsstats.srvrpccnt[NFSPROC_SYMLINK], 30452493Sdillon nfsstats.srvrpccnt[NFSPROC_MKDIR], 30552493Sdillon nfsstats.srvrpccnt[NFSPROC_RMDIR], 30652493Sdillon nfsstats.srvrpccnt[NFSPROC_READDIR], 30752493Sdillon nfsstats.srvrpccnt[NFSPROC_READDIRPLUS], 30852493Sdillon nfsstats.srvrpccnt[NFSPROC_ACCESS]); 30952493Sdillon printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n", 31052493Sdillon "Mknod", "Fsstat", "Fsinfo", "PathConf", "Commit", 31152493Sdillon "GLease", "Vacate", "Evict"); 31252493Sdillon printf("%9d %9d %9d %9d %9d %9d %9d %9d\n", 31352493Sdillon nfsstats.srvrpccnt[NFSPROC_MKNOD], 31452493Sdillon nfsstats.srvrpccnt[NFSPROC_FSSTAT], 31552493Sdillon nfsstats.srvrpccnt[NFSPROC_FSINFO], 31652493Sdillon nfsstats.srvrpccnt[NFSPROC_PATHCONF], 31752493Sdillon nfsstats.srvrpccnt[NFSPROC_COMMIT], 31852493Sdillon nfsstats.srvrpccnt[NQNFSPROC_GETLEASE], 31952493Sdillon nfsstats.srvrpccnt[NQNFSPROC_VACATED], 32052493Sdillon nfsstats.srvrpccnt[NQNFSPROC_EVICTED]); 32152493Sdillon printf("Server Ret-Failed\n"); 32252493Sdillon printf("%17d\n", nfsstats.srvrpc_errs); 32352493Sdillon printf("Server Faults\n"); 32452493Sdillon printf("%13d\n", nfsstats.srv_errs); 32552493Sdillon printf("Server Cache Stats:\n"); 32652493Sdillon printf("%9.9s %9.9s %9.9s %9.9s\n", 32752493Sdillon "Inprog", "Idem", "Non-idem", "Misses"); 32852493Sdillon printf("%9d %9d %9d %9d\n", 32952493Sdillon nfsstats.srvcache_inproghits, 33052493Sdillon nfsstats.srvcache_idemdonehits, 33152493Sdillon nfsstats.srvcache_nonidemdonehits, 33252493Sdillon nfsstats.srvcache_misses); 33352493Sdillon printf("Server Lease Stats:\n"); 33452493Sdillon printf("%9.9s %9.9s %9.9s\n", 3351590Srgrimes "Leases", "PeakL", "GLeases"); 33652493Sdillon printf("%9d %9d %9d\n", 33752493Sdillon nfsstats.srvnqnfs_leases, 33852493Sdillon nfsstats.srvnqnfs_maxleases, 33952493Sdillon nfsstats.srvnqnfs_getleases); 34052493Sdillon printf("Server Write Gathering:\n"); 34152493Sdillon printf("%9.9s %9.9s %9.9s\n", 34252493Sdillon "WriteOps", "WriteRPC", "Opsaved"); 34352493Sdillon printf("%9d %9d %9d\n", 34452493Sdillon nfsstats.srvvop_writes, 34552493Sdillon nfsstats.srvrpccnt[NFSPROC_WRITE], 34652493Sdillon nfsstats.srvrpccnt[NFSPROC_WRITE] - 34752493Sdillon nfsstats.srvvop_writes); 34852493Sdillon } 3491590Srgrimes} 3501590Srgrimes 3511590Srgrimesu_char signalled; /* set if alarm goes off "early" */ 3521590Srgrimes 3531590Srgrimes/* 3541590Srgrimes * Print a running summary of nfs statistics. 3551590Srgrimes * Repeat display every interval seconds, showing statistics 3561590Srgrimes * collected over that interval. Assumes that interval is non-zero. 3571590Srgrimes * First line printed at top of screen is always cumulative. 3581590Srgrimes */ 3591590Srgrimesvoid 36052493Sdillonsidewaysintpr(u_int interval, int clientOnly, int serverOnly) 3611590Srgrimes{ 3621590Srgrimes struct nfsstats nfsstats, lastst; 36352493Sdillon int hdrcnt = 1; 3641590Srgrimes 36552493Sdillon readstats(&lastst); 36652493Sdillon sleep(interval); 3671590Srgrimes 36852493Sdillon for (;;) { 36952493Sdillon readstats(&nfsstats); 37052493Sdillon 37152493Sdillon if (--hdrcnt == 0) { 37252493Sdillon printhdr(clientOnly, serverOnly); 37352493Sdillon if (clientOnly && serverOnly) 37452493Sdillon hdrcnt = 10; 37552493Sdillon else 37652493Sdillon hdrcnt = 20; 3771590Srgrimes } 37852493Sdillon if (clientOnly) { 37952493Sdillon printf("%s %6d %6d %6d %6d %6d %6d %6d %6d", 38052493Sdillon ((clientOnly && serverOnly) ? "Client:" : ""), 38152493Sdillon DELTA(attrcache_hits) + DELTA(attrcache_misses), 38252493Sdillon DELTA(lookupcache_hits) + DELTA(lookupcache_misses), 38352493Sdillon DELTA(biocache_readlinks), 38452493Sdillon DELTA(biocache_reads), 38552493Sdillon DELTA(biocache_writes), 38652493Sdillon nfsstats.rpccnt[NFSPROC_RENAME]-lastst.rpccnt[NFSPROC_RENAME], 38752493Sdillon DELTA(accesscache_hits) + DELTA(accesscache_misses), 38852493Sdillon DELTA(biocache_readdirs) 38952493Sdillon ); 39052493Sdillon if (widemode) { 39152493Sdillon printf(" %s %s %s %s %s %s", 39252493Sdillon sperc1(DELTA(attrcache_hits), 39352493Sdillon DELTA(attrcache_misses)), 39452493Sdillon sperc1(DELTA(lookupcache_hits), 39552493Sdillon DELTA(lookupcache_misses)), 39652493Sdillon sperc2(DELTA(biocache_reads), 39752493Sdillon DELTA(read_bios)), 39852493Sdillon sperc2(DELTA(biocache_writes), 39952493Sdillon DELTA(write_bios)), 40052493Sdillon sperc1(DELTA(accesscache_hits), 40152493Sdillon DELTA(accesscache_misses)), 40252493Sdillon sperc2(DELTA(biocache_readdirs), 40352493Sdillon DELTA(readdir_bios)) 40452493Sdillon ); 40552493Sdillon } 40652493Sdillon printf("\n"); 40752493Sdillon } 40852493Sdillon if (serverOnly) { 40952493Sdillon printf("%s %6d %6d %6d %6d %6d %6d %6d %6d", 41052493Sdillon ((clientOnly && serverOnly) ? "Server:" : ""), 41152493Sdillon nfsstats.srvrpccnt[NFSPROC_GETATTR]-lastst.srvrpccnt[NFSPROC_GETATTR], 41252493Sdillon nfsstats.srvrpccnt[NFSPROC_LOOKUP]-lastst.srvrpccnt[NFSPROC_LOOKUP], 41352493Sdillon nfsstats.srvrpccnt[NFSPROC_READLINK]-lastst.srvrpccnt[NFSPROC_READLINK], 41452493Sdillon nfsstats.srvrpccnt[NFSPROC_READ]-lastst.srvrpccnt[NFSPROC_READ], 41552493Sdillon nfsstats.srvrpccnt[NFSPROC_WRITE]-lastst.srvrpccnt[NFSPROC_WRITE], 41652493Sdillon nfsstats.srvrpccnt[NFSPROC_RENAME]-lastst.srvrpccnt[NFSPROC_RENAME], 41752493Sdillon nfsstats.srvrpccnt[NFSPROC_ACCESS]-lastst.srvrpccnt[NFSPROC_ACCESS], 41852493Sdillon (nfsstats.srvrpccnt[NFSPROC_READDIR]-lastst.srvrpccnt[NFSPROC_READDIR]) 41952493Sdillon +(nfsstats.srvrpccnt[NFSPROC_READDIRPLUS]-lastst.srvrpccnt[NFSPROC_READDIRPLUS])); 42052493Sdillon printf("\n"); 42152493Sdillon } 4221590Srgrimes lastst = nfsstats; 4231590Srgrimes fflush(stdout); 42452493Sdillon sleep(interval); 4251590Srgrimes } 4261590Srgrimes /*NOTREACHED*/ 4271590Srgrimes} 4281590Srgrimes 4291590Srgrimesvoid 43052493Sdillonprinthdr(int clientOnly, int serverOnly) 4311590Srgrimes{ 43252493Sdillon printf("%s%6.6s %6.6s %6.6s %6.6s %6.6s %6.6s %6.6s %6.6s", 43352493Sdillon ((serverOnly && clientOnly) ? " " : " "), 43452493Sdillon "GtAttr", "Lookup", "Rdlink", "Read", "Write", "Rename", 43552493Sdillon "Access", "Rddir"); 43652493Sdillon if (widemode && clientOnly) { 43752493Sdillon printf(" Attr Lkup BioR BioW Accs BioD"); 43852493Sdillon } 43952493Sdillon printf("\n"); 4401590Srgrimes fflush(stdout); 4411590Srgrimes} 4421590Srgrimes 4431590Srgrimesvoid 4441590Srgrimesusage() 4451590Srgrimes{ 4461590Srgrimes (void)fprintf(stderr, 4471590Srgrimes "usage: nfsstat [-M core] [-N system] [-w interval]\n"); 4481590Srgrimes exit(1); 4491590Srgrimes} 45052493Sdillon 45152493Sdillonstatic char SPBuf[64][8]; 45252493Sdillonstatic int SPIndex; 45352493Sdillon 45452493Sdillonchar * 45552493Sdillonsperc1(int hits, int misses) 45652493Sdillon{ 45752493Sdillon char *p = SPBuf[SPIndex]; 45852493Sdillon 45952493Sdillon if (hits + misses) { 46052493Sdillon sprintf(p, "%3d%%", 46152493Sdillon (int)(char)((quad_t)hits * 100 / (hits + misses))); 46252493Sdillon } else { 46352493Sdillon sprintf(p, " -"); 46452493Sdillon } 46552493Sdillon SPIndex = (SPIndex + 1) & 63; 46652493Sdillon return(p); 46752493Sdillon} 46852493Sdillon 46952493Sdillonchar * 47052493Sdillonsperc2(int ttl, int misses) 47152493Sdillon{ 47252493Sdillon char *p = SPBuf[SPIndex]; 47352493Sdillon 47452493Sdillon if (ttl) { 47552493Sdillon sprintf(p, "%3d%%", 47652493Sdillon (int)(char)((quad_t)(ttl - misses) * 100 / ttl)); 47752493Sdillon } else { 47852493Sdillon sprintf(p, " -"); 47952493Sdillon } 48052493Sdillon SPIndex = (SPIndex + 1) & 63; 48152493Sdillon return(p); 48252493Sdillon} 48352493Sdillon 484