Home | History | Annotate | Line # | Download | only in nfsstat
nfsstat.c revision 1.22.6.1
      1  1.22.6.1       jym /*	$NetBSD: nfsstat.c,v 1.22.6.1 2009/05/13 19:20:00 jym Exp $	*/
      2       1.7   thorpej 
      3       1.1       cgd /*
      4       1.5   mycroft  * Copyright (c) 1983, 1989, 1993
      5       1.5   mycroft  *	The Regents of the University of California.  All rights reserved.
      6       1.1       cgd  *
      7       1.1       cgd  * This code is derived from software contributed to Berkeley by
      8       1.1       cgd  * Rick Macklem at The University of Guelph.
      9       1.1       cgd  *
     10       1.1       cgd  * Redistribution and use in source and binary forms, with or without
     11       1.1       cgd  * modification, are permitted provided that the following conditions
     12       1.1       cgd  * are met:
     13       1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     14       1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     15       1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     16       1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     17       1.1       cgd  *    documentation and/or other materials provided with the distribution.
     18      1.18       agc  * 3. Neither the name of the University nor the names of its contributors
     19       1.1       cgd  *    may be used to endorse or promote products derived from this software
     20       1.1       cgd  *    without specific prior written permission.
     21       1.1       cgd  *
     22       1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     23       1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24       1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25       1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     26       1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27       1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28       1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29       1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30       1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31       1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32       1.1       cgd  * SUCH DAMAGE.
     33       1.1       cgd  */
     34       1.1       cgd 
     35       1.9     lukem #include <sys/cdefs.h>
     36       1.1       cgd #ifndef lint
     37      1.22     lukem __COPYRIGHT("@(#) Copyright (c) 1983, 1989, 1993\
     38      1.22     lukem  The Regents of the University of California.  All rights reserved.");
     39       1.1       cgd #endif /* not lint */
     40       1.1       cgd 
     41       1.1       cgd #ifndef lint
     42       1.7   thorpej #if 0
     43       1.7   thorpej static char sccsid[] = "from: @(#)nfsstat.c	8.1 (Berkeley) 6/6/93";
     44       1.7   thorpej #else
     45  1.22.6.1       jym __RCSID("$NetBSD: nfsstat.c,v 1.22.6.1 2009/05/13 19:20:00 jym Exp $");
     46       1.7   thorpej #endif
     47       1.1       cgd #endif /* not lint */
     48       1.1       cgd 
     49       1.1       cgd #include <sys/param.h>
     50       1.1       cgd #include <sys/mount.h>
     51       1.6      fvdl #include <sys/sysctl.h>
     52       1.8  explorer 
     53       1.6      fvdl #include <nfs/rpcv2.h>
     54       1.6      fvdl #include <nfs/nfsproto.h>
     55       1.1       cgd #include <nfs/nfs.h>
     56       1.8  explorer 
     57       1.1       cgd #include <ctype.h>
     58       1.8  explorer #include <err.h>
     59       1.1       cgd #include <errno.h>
     60       1.8  explorer #include <fcntl.h>
     61       1.5   mycroft #include <kvm.h>
     62       1.8  explorer #include <limits.h>
     63       1.1       cgd #include <nlist.h>
     64       1.8  explorer #include <paths.h>
     65       1.8  explorer #include <signal.h>
     66       1.8  explorer #include <stdlib.h>
     67       1.1       cgd #include <stdio.h>
     68       1.1       cgd #include <string.h>
     69       1.8  explorer #include <unistd.h>
     70       1.1       cgd 
     71       1.1       cgd struct nlist nl[] = {
     72       1.1       cgd #define	N_NFSSTAT	0
     73  1.22.6.1       jym 	{ "_nfsstats", 0, 0, 0, 0 },
     74  1.22.6.1       jym 	{ "", 0, 0, 0, 0 },
     75       1.1       cgd };
     76      1.16    simonb 
     77      1.19      yamt #define	MASK(a)	(1 << NFSPROC_##a)
     78      1.19      yamt #define ALLMASK								\
     79      1.19      yamt 	(MASK(GETATTR) | MASK(SETATTR) | MASK(LOOKUP) | MASK(READ) |	\
     80      1.19      yamt 	MASK(WRITE) | MASK(RENAME)| MASK(ACCESS) | MASK(READDIR) |	\
     81      1.19      yamt 	MASK(READDIRPLUS))
     82      1.19      yamt #define	OTHERMASK	(((1 << NFS_NPROCS) - 1) & ~ALLMASK)
     83      1.19      yamt const struct shortprocs {
     84      1.19      yamt 	int mask;
     85      1.19      yamt 	const char *name;
     86      1.19      yamt } shortprocs[] = {
     87      1.19      yamt 	{MASK(GETATTR),	"Getattr"},
     88      1.19      yamt 	{MASK(SETATTR),	"Setattr"},
     89      1.19      yamt 	{MASK(LOOKUP),	"Lookup"},
     90      1.19      yamt 	{MASK(READ),	"Read"},
     91      1.19      yamt 	{MASK(WRITE),	"Write"},
     92      1.19      yamt 	{MASK(RENAME),	"Rename"},
     93      1.19      yamt 	{MASK(ACCESS),	"Access"},
     94      1.19      yamt 	{MASK(READDIR) | MASK(READDIRPLUS), "Readdir"},
     95      1.19      yamt 	{OTHERMASK, "Others"},
     96      1.19      yamt };
     97      1.19      yamt 
     98      1.19      yamt #define	NSHORTPROC	(sizeof(shortprocs)/sizeof(shortprocs[0]))
     99       1.1       cgd 
    100       1.9     lukem void	catchalarm __P((int));
    101      1.16    simonb void	getstats __P((struct nfsstats *));
    102      1.16    simonb void	intpr __P((void));
    103       1.9     lukem int	main __P((int, char **));
    104       1.9     lukem void	printhdr __P((void));
    105      1.16    simonb void	sidewaysintpr __P((u_int));
    106       1.9     lukem void	usage __P((void));
    107       1.1       cgd 
    108      1.16    simonb kvm_t  *kd;
    109      1.10   hubertf int     printall, clientinfo, serverinfo;
    110      1.16    simonb u_long	nfsstataddr;
    111      1.10   hubertf 
    112       1.9     lukem int
    113       1.1       cgd main(argc, argv)
    114       1.1       cgd 	int argc;
    115       1.1       cgd 	char **argv;
    116       1.1       cgd {
    117       1.1       cgd 	u_int interval;
    118       1.1       cgd 	int ch;
    119       1.5   mycroft 	char *memf, *nlistf;
    120       1.8  explorer 	char errbuf[_POSIX2_LINE_MAX];
    121       1.1       cgd 
    122       1.1       cgd 	interval = 0;
    123       1.5   mycroft 	memf = nlistf = NULL;
    124      1.10   hubertf 	printall = 1;
    125      1.10   hubertf 	while ((ch = getopt(argc, argv, "M:N:w:cs")) != -1)
    126       1.1       cgd 		switch(ch) {
    127       1.1       cgd 		case 'M':
    128       1.5   mycroft 			memf = optarg;
    129       1.1       cgd 			break;
    130       1.1       cgd 		case 'N':
    131       1.5   mycroft 			nlistf = optarg;
    132       1.1       cgd 			break;
    133       1.1       cgd 		case 'w':
    134       1.1       cgd 			interval = atoi(optarg);
    135       1.1       cgd 			break;
    136      1.10   hubertf 		case 's':
    137      1.10   hubertf 		        serverinfo = 1;
    138      1.10   hubertf 			printall = 0;
    139      1.10   hubertf 			break;
    140      1.10   hubertf 		case 'c':
    141      1.10   hubertf 		        clientinfo = 1;
    142      1.10   hubertf 			printall = 0;
    143      1.10   hubertf 			break;
    144       1.1       cgd 		case '?':
    145       1.1       cgd 		default:
    146       1.1       cgd 			usage();
    147       1.1       cgd 		}
    148       1.1       cgd 	argc -= optind;
    149       1.1       cgd 	argv += optind;
    150       1.1       cgd 
    151       1.1       cgd #define	BACKWARD_COMPATIBILITY
    152       1.1       cgd #ifdef	BACKWARD_COMPATIBILITY
    153       1.1       cgd 	if (*argv) {
    154       1.5   mycroft 		interval = atoi(*argv);
    155       1.1       cgd 		if (*++argv) {
    156       1.5   mycroft 			nlistf = *argv;
    157       1.5   mycroft 			if (*++argv)
    158       1.5   mycroft 				memf = *argv;
    159       1.1       cgd 		}
    160       1.1       cgd 	}
    161       1.1       cgd #endif
    162      1.16    simonb 	if (nlistf || memf) {
    163      1.16    simonb 		if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf))
    164      1.16    simonb 		    == 0)
    165      1.16    simonb 			errx(1, "kvm_openfiles: %s", errbuf);
    166      1.16    simonb 
    167      1.16    simonb 		if (kvm_nlist(kd, nl) != 0)
    168      1.16    simonb 			errx(1, "kvm_nlist: can't get names");
    169      1.16    simonb 		nfsstataddr = nl[N_NFSSTAT].n_value;
    170      1.16    simonb 	} else {
    171      1.16    simonb 		kd = NULL;
    172      1.16    simonb 	}
    173       1.1       cgd 
    174       1.1       cgd 	if (interval)
    175      1.16    simonb 		sidewaysintpr(interval);
    176       1.1       cgd 	else
    177      1.16    simonb 		intpr();
    178       1.1       cgd 	exit(0);
    179       1.1       cgd }
    180       1.1       cgd 
    181      1.16    simonb void
    182      1.16    simonb getstats(ns)
    183      1.16    simonb 	struct nfsstats *ns;
    184      1.16    simonb {
    185      1.16    simonb 	size_t size;
    186      1.16    simonb 	int mib[3];
    187      1.16    simonb 
    188      1.16    simonb 	if (kd) {
    189      1.16    simonb 		if (kvm_read(kd, (u_long)nfsstataddr, ns, sizeof(*ns))
    190      1.16    simonb 		    != sizeof(*ns))
    191      1.16    simonb 			errx(1, "kvm_read failed");
    192      1.16    simonb 	} else {
    193      1.16    simonb 		mib[0] = CTL_VFS;
    194      1.16    simonb 		mib[1] = 2;	/* XXX from CTL_VFS_NAMES in <sys/mount.h> */
    195      1.16    simonb 		mib[2] = NFS_NFSSTATS;
    196      1.16    simonb 
    197      1.16    simonb 		size = sizeof(*ns);
    198      1.16    simonb 		if (sysctl(mib, 3, ns, &size, NULL, 0) == -1)
    199      1.16    simonb 			err(1, "sysctl(NFS_NFSSTATS) failed");
    200      1.16    simonb 	}
    201      1.16    simonb }
    202      1.16    simonb 
    203       1.1       cgd /*
    204       1.5   mycroft  * Print a description of the nfs stats.
    205       1.1       cgd  */
    206       1.1       cgd void
    207      1.16    simonb intpr()
    208       1.1       cgd {
    209       1.1       cgd 	struct nfsstats nfsstats;
    210      1.17     lukem 	int64_t	total;
    211      1.17     lukem 	int	i;
    212      1.17     lukem 
    213      1.17     lukem #define PCT(x,y)	((y) == 0 ? 0 : (int)((int64_t)(x) * 100 / (y)))
    214      1.17     lukem #define NUMPCT(x,y)	(x), PCT(x, (x)+(y))
    215      1.17     lukem #define	RPCSTAT(x)	(x), PCT(x, total)
    216       1.1       cgd 
    217      1.16    simonb 	getstats(&nfsstats);
    218      1.17     lukem 
    219      1.13       mrg 	if (printall || clientinfo) {
    220      1.17     lukem 		total = 0;
    221      1.17     lukem 		for (i = 0; i < NFS_NPROCS; i++)
    222      1.17     lukem 			total += nfsstats.rpccnt[i];
    223      1.13       mrg 		printf("Client Info:\n");
    224      1.17     lukem 		printf("RPC Counts: (%lld call%s)\n", (long long)total,
    225      1.17     lukem 		    total == 1 ? "" : "s");
    226      1.17     lukem 
    227      1.17     lukem 		printf("%10s  %14s  %14s  %14s  %14s\n",
    228      1.17     lukem 		    "null", "getattr", "setattr", "lookup", "access");
    229      1.17     lukem 		printf(
    230      1.17     lukem 	    "%10d %2d%%  %10d %2d%%  %10d %2d%%  %10d %2d%%  %10d %2d%%\n",
    231      1.17     lukem 		    RPCSTAT(nfsstats.rpccnt[NFSPROC_NULL]),
    232      1.17     lukem 		    RPCSTAT(nfsstats.rpccnt[NFSPROC_GETATTR]),
    233      1.17     lukem 		    RPCSTAT(nfsstats.rpccnt[NFSPROC_SETATTR]),
    234      1.17     lukem 		    RPCSTAT(nfsstats.rpccnt[NFSPROC_LOOKUP]),
    235      1.17     lukem 		    RPCSTAT(nfsstats.rpccnt[NFSPROC_ACCESS]));
    236      1.17     lukem 		printf("%10s  %14s  %14s  %14s  %14s\n",
    237      1.17     lukem 		    "readlink", "read", "write", "create", "mkdir");
    238      1.17     lukem 		printf(
    239      1.17     lukem 	    "%10d %2d%%  %10d %2d%%  %10d %2d%%  %10d %2d%%  %10d %2d%%\n",
    240      1.17     lukem 		    RPCSTAT(nfsstats.rpccnt[NFSPROC_READLINK]),
    241      1.17     lukem 		    RPCSTAT(nfsstats.rpccnt[NFSPROC_READ]),
    242      1.17     lukem 		    RPCSTAT(nfsstats.rpccnt[NFSPROC_WRITE]),
    243      1.17     lukem 		    RPCSTAT(nfsstats.rpccnt[NFSPROC_CREATE]),
    244      1.17     lukem 		    RPCSTAT(nfsstats.rpccnt[NFSPROC_MKDIR]));
    245      1.17     lukem 		printf("%10s  %14s  %14s  %14s  %14s\n",
    246      1.17     lukem 		    "symlink", "mknod", "remove", "rmdir", "rename");
    247      1.17     lukem 		printf(
    248      1.17     lukem 	    "%10d %2d%%  %10d %2d%%  %10d %2d%%  %10d %2d%%  %10d %2d%%\n",
    249      1.17     lukem 		    RPCSTAT(nfsstats.rpccnt[NFSPROC_SYMLINK]),
    250      1.17     lukem 		    RPCSTAT(nfsstats.rpccnt[NFSPROC_MKNOD]),
    251      1.17     lukem 		    RPCSTAT(nfsstats.rpccnt[NFSPROC_REMOVE]),
    252      1.17     lukem 		    RPCSTAT(nfsstats.rpccnt[NFSPROC_RMDIR]),
    253      1.17     lukem 		    RPCSTAT(nfsstats.rpccnt[NFSPROC_RENAME]));
    254      1.17     lukem 		printf("%10s  %14s  %14s  %14s  %14s\n",
    255      1.17     lukem 		    "link", "readdir", "readdirplus", "fsstat", "fsinfo");
    256      1.17     lukem 		printf(
    257      1.17     lukem 	    "%10d %2d%%  %10d %2d%%  %10d %2d%%  %10d %2d%%  %10d %2d%%\n",
    258      1.17     lukem 		    RPCSTAT(nfsstats.rpccnt[NFSPROC_LINK]),
    259      1.17     lukem 		    RPCSTAT(nfsstats.rpccnt[NFSPROC_READDIR]),
    260      1.17     lukem 		    RPCSTAT(nfsstats.rpccnt[NFSPROC_READDIRPLUS]),
    261      1.17     lukem 		    RPCSTAT(nfsstats.rpccnt[NFSPROC_FSSTAT]),
    262      1.17     lukem 		    RPCSTAT(nfsstats.rpccnt[NFSPROC_FSINFO]));
    263      1.21      yamt 		printf("%10s  %14s\n",
    264      1.21      yamt 		    "pathconf", "commit");
    265      1.20    dogcow 		printf("%10d %2d%%  %10d %2d%%\n",
    266      1.17     lukem 		    RPCSTAT(nfsstats.rpccnt[NFSPROC_PATHCONF]),
    267      1.20    dogcow 		    RPCSTAT(nfsstats.rpccnt[NFSPROC_COMMIT]));
    268      1.17     lukem 
    269      1.17     lukem 		printf("RPC Info:\n");
    270      1.17     lukem 		printf("%10s  %14s  %14s  %14s  %14s\n",
    271      1.17     lukem 		    "timeout", "invalid", "unexpected", "retries", "requests");
    272      1.17     lukem 		printf("%10d  %14d  %14d  %14d  %14d\n",
    273      1.13       mrg 		    nfsstats.rpctimeouts,
    274      1.13       mrg 		    nfsstats.rpcinvalid,
    275      1.13       mrg 		    nfsstats.rpcunexpected,
    276      1.13       mrg 		    nfsstats.rpcretries,
    277      1.13       mrg 		    nfsstats.rpcrequests);
    278      1.17     lukem 
    279      1.13       mrg 		printf("Cache Info:\n");
    280      1.17     lukem 		printf("%10s  %14s  %14s  %14s  %14s\n",
    281      1.17     lukem 		    "attrcache", "lookupcache", "read", "write", "readlink");
    282      1.17     lukem 		printf(
    283      1.17     lukem 	    "%10d %2d%%  %10d %2d%%  %10d %2d%%  %10d %2d%%  %10d %2d%%\n",
    284      1.17     lukem 		    NUMPCT(nfsstats.attrcache_hits,
    285      1.17     lukem 			nfsstats.attrcache_misses),
    286      1.17     lukem 		    NUMPCT(nfsstats.lookupcache_hits,
    287      1.17     lukem 			nfsstats.lookupcache_misses),
    288      1.17     lukem 		    NUMPCT(nfsstats.biocache_reads - nfsstats.read_bios,
    289      1.17     lukem 			nfsstats.read_bios),
    290      1.17     lukem 		    NUMPCT(nfsstats.biocache_writes - nfsstats.write_bios,
    291      1.17     lukem 			nfsstats.write_bios),
    292      1.17     lukem 		    NUMPCT(nfsstats.biocache_readlinks - nfsstats.readlink_bios,
    293      1.17     lukem 			nfsstats.readlink_bios));
    294      1.17     lukem 		printf("%10s  %14s\n",
    295      1.17     lukem 		    "readdir", "direofcache");
    296      1.17     lukem 		printf("%10d %2d%%  %10d %2d%%\n",
    297      1.17     lukem 		    NUMPCT(nfsstats.biocache_readdirs - nfsstats.readdir_bios,
    298      1.17     lukem 			nfsstats.readdir_bios),
    299      1.17     lukem 		    NUMPCT(nfsstats.direofcache_hits,
    300      1.17     lukem 			nfsstats.direofcache_misses));
    301      1.10   hubertf 	}
    302      1.17     lukem 
    303      1.17     lukem 	if (printall || (clientinfo && serverinfo))
    304      1.13       mrg 		printf("\n");
    305      1.17     lukem 
    306      1.17     lukem 	if (printall || serverinfo) {
    307      1.17     lukem 		total = 0;
    308      1.17     lukem 		for (i = 0; i < NFS_NPROCS; i++)
    309      1.17     lukem 			total += nfsstats.srvrpccnt[i];
    310      1.13       mrg 		printf("Server Info:\n");
    311      1.17     lukem 		printf("RPC Counts: (%lld call%s)\n", (long long)total,
    312      1.17     lukem 		    total == 1 ? "" : "s");
    313      1.17     lukem 
    314      1.17     lukem 		printf("%10s  %14s  %14s  %14s  %14s\n",
    315      1.17     lukem 		    "null", "getattr", "setattr", "lookup", "access");
    316      1.17     lukem 		printf(
    317      1.17     lukem 	    "%10d %2d%%  %10d %2d%%  %10d %2d%%  %10d %2d%%  %10d %2d%%\n",
    318      1.17     lukem 		    RPCSTAT(nfsstats.srvrpccnt[NFSPROC_NULL]),
    319      1.17     lukem 		    RPCSTAT(nfsstats.srvrpccnt[NFSPROC_GETATTR]),
    320      1.17     lukem 		    RPCSTAT(nfsstats.srvrpccnt[NFSPROC_SETATTR]),
    321      1.17     lukem 		    RPCSTAT(nfsstats.srvrpccnt[NFSPROC_LOOKUP]),
    322      1.17     lukem 		    RPCSTAT(nfsstats.srvrpccnt[NFSPROC_ACCESS]));
    323      1.17     lukem 		printf("%10s  %14s  %14s  %14s  %14s\n",
    324      1.17     lukem 		    "readlink", "read", "write", "create", "mkdir");
    325      1.17     lukem 		printf(
    326      1.17     lukem 	    "%10d %2d%%  %10d %2d%%  %10d %2d%%  %10d %2d%%  %10d %2d%%\n",
    327      1.17     lukem 		    RPCSTAT(nfsstats.srvrpccnt[NFSPROC_READLINK]),
    328      1.17     lukem 		    RPCSTAT(nfsstats.srvrpccnt[NFSPROC_READ]),
    329      1.17     lukem 		    RPCSTAT(nfsstats.srvrpccnt[NFSPROC_WRITE]),
    330      1.17     lukem 		    RPCSTAT(nfsstats.srvrpccnt[NFSPROC_CREATE]),
    331      1.17     lukem 		    RPCSTAT(nfsstats.srvrpccnt[NFSPROC_MKDIR]));
    332      1.17     lukem 		printf("%10s  %14s  %14s  %14s  %14s\n",
    333      1.17     lukem 		    "symlink", "mknod", "remove", "rmdir", "rename");
    334      1.17     lukem 		printf(
    335      1.17     lukem 	    "%10d %2d%%  %10d %2d%%  %10d %2d%%  %10d %2d%%  %10d %2d%%\n",
    336      1.17     lukem 		    RPCSTAT(nfsstats.srvrpccnt[NFSPROC_SYMLINK]),
    337      1.17     lukem 		    RPCSTAT(nfsstats.srvrpccnt[NFSPROC_MKNOD]),
    338      1.17     lukem 		    RPCSTAT(nfsstats.srvrpccnt[NFSPROC_REMOVE]),
    339      1.17     lukem 		    RPCSTAT(nfsstats.srvrpccnt[NFSPROC_RMDIR]),
    340      1.17     lukem 		    RPCSTAT(nfsstats.srvrpccnt[NFSPROC_RENAME]));
    341      1.17     lukem 		printf("%10s  %14s  %14s  %14s  %14s\n",
    342      1.17     lukem 		    "link", "readdir", "readdirplus", "fsstat", "fsinfo");
    343      1.17     lukem 		printf(
    344      1.17     lukem 	    "%10d %2d%%  %10d %2d%%  %10d %2d%%  %10d %2d%%  %10d %2d%%\n",
    345      1.17     lukem 		    RPCSTAT(nfsstats.srvrpccnt[NFSPROC_LINK]),
    346      1.17     lukem 		    RPCSTAT(nfsstats.srvrpccnt[NFSPROC_READDIR]),
    347      1.17     lukem 		    RPCSTAT(nfsstats.srvrpccnt[NFSPROC_READDIRPLUS]),
    348      1.17     lukem 		    RPCSTAT(nfsstats.srvrpccnt[NFSPROC_FSSTAT]),
    349      1.17     lukem 		    RPCSTAT(nfsstats.srvrpccnt[NFSPROC_FSINFO]));
    350      1.21      yamt 		printf("%10s  %14s\n",
    351      1.21      yamt 		    "pathconf", "commit");
    352      1.20    dogcow 		printf("%10d %2d%%  %10d %2d%%\n",
    353      1.17     lukem 		    RPCSTAT(nfsstats.srvrpccnt[NFSPROC_PATHCONF]),
    354      1.20    dogcow 		    RPCSTAT(nfsstats.srvrpccnt[NFSPROC_COMMIT]));
    355      1.17     lukem 
    356      1.17     lukem 		printf("Server Errors:\n");
    357      1.17     lukem 		printf("%10s  %14s\n",
    358      1.17     lukem 		    "RPC errors", "faults");
    359      1.17     lukem 		printf("%10d  %14d\n",
    360      1.17     lukem 		    nfsstats.srvrpc_errs,
    361      1.17     lukem 		    nfsstats.srv_errs);
    362      1.13       mrg 		printf("Server Cache Stats:\n");
    363      1.17     lukem 		printf("%10s  %14s  %14s  %14s\n",
    364      1.17     lukem 		    "inprogress", "idem", "non-idem", "misses");
    365      1.17     lukem 		printf("%10d  %14d  %14d  %14d\n",
    366      1.13       mrg 		    nfsstats.srvcache_inproghits,
    367      1.13       mrg 		    nfsstats.srvcache_idemdonehits,
    368      1.13       mrg 		    nfsstats.srvcache_nonidemdonehits,
    369      1.13       mrg 		    nfsstats.srvcache_misses);
    370      1.13       mrg 		printf("Server Write Gathering:\n");
    371      1.17     lukem 		printf("%10s  %14s  %14s\n",
    372      1.17     lukem 		    "writes", "write RPC", "OPs saved");
    373      1.17     lukem 		printf("%10d  %14d  %14d %2d%%\n",
    374      1.13       mrg 		    nfsstats.srvvop_writes,
    375      1.13       mrg 		    nfsstats.srvrpccnt[NFSPROC_WRITE],
    376      1.17     lukem 		    NUMPCT(
    377      1.17     lukem 		      nfsstats.srvrpccnt[NFSPROC_WRITE]-nfsstats.srvvop_writes,
    378      1.17     lukem 		      nfsstats.srvrpccnt[NFSPROC_WRITE]));
    379      1.10   hubertf 	}
    380       1.1       cgd }
    381       1.1       cgd 
    382       1.1       cgd u_char	signalled;			/* set if alarm goes off "early" */
    383       1.1       cgd 
    384       1.1       cgd /*
    385       1.1       cgd  * Print a running summary of nfs statistics.
    386       1.1       cgd  * Repeat display every interval seconds, showing statistics
    387       1.1       cgd  * collected over that interval.  Assumes that interval is non-zero.
    388       1.1       cgd  * First line printed at top of screen is always cumulative.
    389       1.1       cgd  */
    390       1.1       cgd void
    391      1.16    simonb sidewaysintpr(interval)
    392       1.1       cgd 	u_int interval;
    393       1.1       cgd {
    394      1.19      yamt 	struct nfsstats nfsstats;
    395       1.1       cgd 	int hdrcnt, oldmask;
    396      1.19      yamt 	struct stats {
    397      1.19      yamt 		int client[NSHORTPROC];
    398      1.19      yamt 		int server[NSHORTPROC];
    399      1.19      yamt 	} current, last;
    400       1.1       cgd 
    401       1.1       cgd 	(void)signal(SIGALRM, catchalarm);
    402       1.1       cgd 	signalled = 0;
    403       1.1       cgd 	(void)alarm(interval);
    404      1.19      yamt 	memset(&last, 0, sizeof(last));
    405       1.1       cgd 
    406       1.1       cgd 	for (hdrcnt = 1;;) {
    407  1.22.6.1       jym 		size_t i;
    408      1.19      yamt 
    409       1.1       cgd 		if (!--hdrcnt) {
    410       1.1       cgd 			printhdr();
    411       1.1       cgd 			hdrcnt = 20;
    412       1.1       cgd 		}
    413      1.16    simonb 		getstats(&nfsstats);
    414      1.19      yamt 		memset(&current, 0, sizeof(current));
    415      1.19      yamt 		for (i = 0; i < NSHORTPROC; i++) {
    416      1.19      yamt 			int mask = shortprocs[i].mask;
    417      1.19      yamt 			int idx;
    418      1.19      yamt 
    419      1.19      yamt 			while ((idx = ffs(mask)) != 0) {
    420      1.19      yamt 				idx--;
    421      1.19      yamt 				mask &= ~(1 << idx);
    422      1.19      yamt 				current.client[i] += nfsstats.rpccnt[idx];
    423      1.19      yamt 				current.server[i] += nfsstats.srvrpccnt[idx];
    424      1.19      yamt 			}
    425      1.19      yamt 		}
    426      1.19      yamt 
    427      1.19      yamt 		if (printall || clientinfo) {
    428      1.19      yamt 			printf("Client:");
    429      1.19      yamt 			for (i = 0; i < NSHORTPROC; i++)
    430      1.19      yamt 				printf(" %7d",
    431      1.19      yamt 				    current.client[i] - last.client[i]);
    432      1.19      yamt 			printf("\n");
    433      1.19      yamt 		}
    434      1.19      yamt 		if (printall || serverinfo) {
    435      1.19      yamt 			printf("Server:");
    436      1.19      yamt 			for (i = 0; i < NSHORTPROC; i++)
    437      1.19      yamt 				printf(" %7d",
    438      1.19      yamt 				    current.server[i] - last.server[i]);
    439      1.19      yamt 			printf("\n");
    440      1.19      yamt 		}
    441      1.19      yamt 		memcpy(&last, &current, sizeof(last));
    442       1.1       cgd 		fflush(stdout);
    443       1.1       cgd 		oldmask = sigblock(sigmask(SIGALRM));
    444       1.1       cgd 		if (!signalled)
    445       1.1       cgd 			sigpause(0);
    446       1.1       cgd 		sigsetmask(oldmask);
    447       1.1       cgd 		signalled = 0;
    448       1.1       cgd 		(void)alarm(interval);
    449       1.1       cgd 	}
    450       1.1       cgd 	/*NOTREACHED*/
    451       1.1       cgd }
    452       1.1       cgd 
    453       1.1       cgd void
    454       1.1       cgd printhdr()
    455       1.1       cgd {
    456  1.22.6.1       jym 	size_t i;
    457      1.13       mrg 
    458      1.19      yamt 	printf("        ");
    459      1.19      yamt 	for (i = 0; i < NSHORTPROC; i++)
    460      1.19      yamt 		printf("%7.7s ", shortprocs[i].name);
    461      1.19      yamt 	printf("\n");
    462       1.1       cgd 	fflush(stdout);
    463       1.1       cgd }
    464       1.1       cgd 
    465       1.1       cgd /*
    466       1.1       cgd  * Called if an interval expires before sidewaysintpr has completed a loop.
    467       1.1       cgd  * Sets a flag to not wait for the alarm.
    468       1.1       cgd  */
    469       1.1       cgd void
    470       1.9     lukem catchalarm(dummy)
    471       1.9     lukem 	int dummy;
    472       1.1       cgd {
    473      1.13       mrg 
    474       1.1       cgd 	signalled = 1;
    475       1.1       cgd }
    476       1.1       cgd 
    477       1.1       cgd void
    478       1.1       cgd usage()
    479       1.1       cgd {
    480      1.13       mrg 
    481       1.1       cgd 	(void)fprintf(stderr,
    482      1.13       mrg 		  "usage: nfsstat [-cs] [-M core] [-N system] [-w interval]\n");
    483       1.1       cgd 	exit(1);
    484       1.1       cgd }
    485