1*9bbbeef3Schristos /* $NetBSD: nfsstat.c,v 1.25 2014/04/24 18:40:35 christos Exp $ */
2c5f7cf3aSthorpej
361f28255Scgd /*
4b6109a20Smycroft * Copyright (c) 1983, 1989, 1993
5b6109a20Smycroft * The Regents of the University of California. All rights reserved.
661f28255Scgd *
761f28255Scgd * This code is derived from software contributed to Berkeley by
861f28255Scgd * Rick Macklem at The University of Guelph.
961f28255Scgd *
1061f28255Scgd * Redistribution and use in source and binary forms, with or without
1161f28255Scgd * modification, are permitted provided that the following conditions
1261f28255Scgd * are met:
1361f28255Scgd * 1. Redistributions of source code must retain the above copyright
1461f28255Scgd * notice, this list of conditions and the following disclaimer.
1561f28255Scgd * 2. Redistributions in binary form must reproduce the above copyright
1661f28255Scgd * notice, this list of conditions and the following disclaimer in the
1761f28255Scgd * documentation and/or other materials provided with the distribution.
1889aaa1bbSagc * 3. Neither the name of the University nor the names of its contributors
1961f28255Scgd * may be used to endorse or promote products derived from this software
2061f28255Scgd * without specific prior written permission.
2161f28255Scgd *
2261f28255Scgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2361f28255Scgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2461f28255Scgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2561f28255Scgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2661f28255Scgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2761f28255Scgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2861f28255Scgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2961f28255Scgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3061f28255Scgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3161f28255Scgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3261f28255Scgd * SUCH DAMAGE.
3361f28255Scgd */
3461f28255Scgd
350ef9bf00Slukem #include <sys/cdefs.h>
3661f28255Scgd #ifndef lint
3798e5374cSlukem __COPYRIGHT("@(#) Copyright (c) 1983, 1989, 1993\
3898e5374cSlukem The Regents of the University of California. All rights reserved.");
3961f28255Scgd #endif /* not lint */
4061f28255Scgd
4161f28255Scgd #ifndef lint
42c5f7cf3aSthorpej #if 0
43c5f7cf3aSthorpej static char sccsid[] = "from: @(#)nfsstat.c 8.1 (Berkeley) 6/6/93";
44c5f7cf3aSthorpej #else
45*9bbbeef3Schristos __RCSID("$NetBSD: nfsstat.c,v 1.25 2014/04/24 18:40:35 christos Exp $");
46c5f7cf3aSthorpej #endif
4761f28255Scgd #endif /* not lint */
4861f28255Scgd
4961f28255Scgd #include <sys/param.h>
5061f28255Scgd #include <sys/mount.h>
51aa58cf93Sfvdl #include <sys/sysctl.h>
525c1fdae7Sexplorer
53aa58cf93Sfvdl #include <nfs/rpcv2.h>
54aa58cf93Sfvdl #include <nfs/nfsproto.h>
5561f28255Scgd #include <nfs/nfs.h>
565c1fdae7Sexplorer
5761f28255Scgd #include <ctype.h>
58aa58cf93Sfvdl #include <err.h>
595c1fdae7Sexplorer #include <errno.h>
605c1fdae7Sexplorer #include <fcntl.h>
615c1fdae7Sexplorer #include <kvm.h>
625c1fdae7Sexplorer #include <limits.h>
635c1fdae7Sexplorer #include <nlist.h>
645c1fdae7Sexplorer #include <paths.h>
655c1fdae7Sexplorer #include <signal.h>
665c1fdae7Sexplorer #include <stdlib.h>
675c1fdae7Sexplorer #include <stdio.h>
685c1fdae7Sexplorer #include <string.h>
695c1fdae7Sexplorer #include <unistd.h>
7061f28255Scgd
71a2f897e7Sjoerg static struct nlist nl[] = {
7261f28255Scgd #define N_NFSSTAT 0
73fc99e5eaSlukem { "_nfsstats", 0, 0, 0, 0 },
74fc99e5eaSlukem { "", 0, 0, 0, 0 },
7561f28255Scgd };
7654736c47Ssimonb
77d25d8e4dSyamt #define MASK(a) (1 << NFSPROC_##a)
78d25d8e4dSyamt #define ALLMASK \
79d25d8e4dSyamt (MASK(GETATTR) | MASK(SETATTR) | MASK(LOOKUP) | MASK(READ) | \
80d25d8e4dSyamt MASK(WRITE) | MASK(RENAME)| MASK(ACCESS) | MASK(READDIR) | \
81d25d8e4dSyamt MASK(READDIRPLUS))
82d25d8e4dSyamt #define OTHERMASK (((1 << NFS_NPROCS) - 1) & ~ALLMASK)
83a2f897e7Sjoerg static const struct shortprocs {
84d25d8e4dSyamt int mask;
85d25d8e4dSyamt const char *name;
86d25d8e4dSyamt } shortprocs[] = {
87d25d8e4dSyamt {MASK(GETATTR), "Getattr"},
88d25d8e4dSyamt {MASK(SETATTR), "Setattr"},
89d25d8e4dSyamt {MASK(LOOKUP), "Lookup"},
90d25d8e4dSyamt {MASK(READ), "Read"},
91d25d8e4dSyamt {MASK(WRITE), "Write"},
92d25d8e4dSyamt {MASK(RENAME), "Rename"},
93d25d8e4dSyamt {MASK(ACCESS), "Access"},
94d25d8e4dSyamt {MASK(READDIR) | MASK(READDIRPLUS), "Readdir"},
95d25d8e4dSyamt {OTHERMASK, "Others"},
96d25d8e4dSyamt };
97d25d8e4dSyamt
98d25d8e4dSyamt #define NSHORTPROC (sizeof(shortprocs)/sizeof(shortprocs[0]))
9961f28255Scgd
100a2f897e7Sjoerg static void catchalarm(int);
101a2f897e7Sjoerg static void getstats(struct nfsstats *);
102a2f897e7Sjoerg static void intpr(void);
103a2f897e7Sjoerg static void printhdr(void);
104a2f897e7Sjoerg __dead static void sidewaysintpr(u_int);
105a2f897e7Sjoerg __dead static void usage(void);
10661f28255Scgd
107a2f897e7Sjoerg static kvm_t *kd;
108a2f897e7Sjoerg static int printall, clientinfo, serverinfo;
109a2f897e7Sjoerg static u_long nfsstataddr;
110b5232219Shubertf
1110ef9bf00Slukem int
main(int argc,char ** argv)112a2f897e7Sjoerg main(int argc, char **argv)
11361f28255Scgd {
11461f28255Scgd u_int interval;
11561f28255Scgd int ch;
116b6109a20Smycroft char *memf, *nlistf;
1175c1fdae7Sexplorer char errbuf[_POSIX2_LINE_MAX];
11861f28255Scgd
11961f28255Scgd interval = 0;
120b6109a20Smycroft memf = nlistf = NULL;
121b5232219Shubertf printall = 1;
122b5232219Shubertf while ((ch = getopt(argc, argv, "M:N:w:cs")) != -1)
12361f28255Scgd switch(ch) {
12461f28255Scgd case 'M':
125b6109a20Smycroft memf = optarg;
12661f28255Scgd break;
12761f28255Scgd case 'N':
128b6109a20Smycroft nlistf = optarg;
12961f28255Scgd break;
13061f28255Scgd case 'w':
13161f28255Scgd interval = atoi(optarg);
13261f28255Scgd break;
133b5232219Shubertf case 's':
134b5232219Shubertf serverinfo = 1;
135b5232219Shubertf printall = 0;
136b5232219Shubertf break;
137b5232219Shubertf case 'c':
138b5232219Shubertf clientinfo = 1;
139b5232219Shubertf printall = 0;
140b5232219Shubertf break;
14161f28255Scgd case '?':
14261f28255Scgd default:
14361f28255Scgd usage();
14461f28255Scgd }
14561f28255Scgd argc -= optind;
14661f28255Scgd argv += optind;
14761f28255Scgd
14861f28255Scgd #define BACKWARD_COMPATIBILITY
14961f28255Scgd #ifdef BACKWARD_COMPATIBILITY
15061f28255Scgd if (*argv) {
151b6109a20Smycroft interval = atoi(*argv);
15261f28255Scgd if (*++argv) {
153b6109a20Smycroft nlistf = *argv;
154b6109a20Smycroft if (*++argv)
155b6109a20Smycroft memf = *argv;
15661f28255Scgd }
15761f28255Scgd }
15861f28255Scgd #endif
15954736c47Ssimonb if (nlistf || memf) {
16054736c47Ssimonb if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf))
16154736c47Ssimonb == 0)
1620ef9bf00Slukem errx(1, "kvm_openfiles: %s", errbuf);
16380efe80bSmrg
1640ef9bf00Slukem if (kvm_nlist(kd, nl) != 0)
1650ef9bf00Slukem errx(1, "kvm_nlist: can't get names");
16654736c47Ssimonb nfsstataddr = nl[N_NFSSTAT].n_value;
16754736c47Ssimonb } else {
16854736c47Ssimonb kd = NULL;
16954736c47Ssimonb }
17061f28255Scgd
17161f28255Scgd if (interval)
17254736c47Ssimonb sidewaysintpr(interval);
17361f28255Scgd else
17454736c47Ssimonb intpr();
17561f28255Scgd exit(0);
17661f28255Scgd }
17761f28255Scgd
178a2f897e7Sjoerg static void
getstats(struct nfsstats * ns)179a2f897e7Sjoerg getstats(struct nfsstats *ns)
18054736c47Ssimonb {
18154736c47Ssimonb size_t size;
18254736c47Ssimonb int mib[3];
18354736c47Ssimonb
18454736c47Ssimonb if (kd) {
18554736c47Ssimonb if (kvm_read(kd, (u_long)nfsstataddr, ns, sizeof(*ns))
18654736c47Ssimonb != sizeof(*ns))
18754736c47Ssimonb errx(1, "kvm_read failed");
18854736c47Ssimonb } else {
18954736c47Ssimonb mib[0] = CTL_VFS;
19054736c47Ssimonb mib[1] = 2; /* XXX from CTL_VFS_NAMES in <sys/mount.h> */
19154736c47Ssimonb mib[2] = NFS_NFSSTATS;
19254736c47Ssimonb
19354736c47Ssimonb size = sizeof(*ns);
19454736c47Ssimonb if (sysctl(mib, 3, ns, &size, NULL, 0) == -1)
19554736c47Ssimonb err(1, "sysctl(NFS_NFSSTATS) failed");
19654736c47Ssimonb }
19754736c47Ssimonb }
19854736c47Ssimonb
19961f28255Scgd /*
200b6109a20Smycroft * Print a description of the nfs stats.
20161f28255Scgd */
202a2f897e7Sjoerg static void
intpr(void)203a2f897e7Sjoerg intpr(void)
20461f28255Scgd {
20561f28255Scgd struct nfsstats nfsstats;
206*9bbbeef3Schristos uint64_t total;
2078073bda8Slukem int i;
2088073bda8Slukem
2098073bda8Slukem #define PCT(x,y) ((y) == 0 ? 0 : (int)((int64_t)(x) * 100 / (y)))
2108073bda8Slukem #define NUMPCT(x,y) (x), PCT(x, (x)+(y))
2118073bda8Slukem #define RPCSTAT(x) (x), PCT(x, total)
21261f28255Scgd
21354736c47Ssimonb getstats(&nfsstats);
2148073bda8Slukem
215b5232219Shubertf if (printall || clientinfo) {
2168073bda8Slukem total = 0;
2178073bda8Slukem for (i = 0; i < NFS_NPROCS; i++)
2188073bda8Slukem total += nfsstats.rpccnt[i];
21961f28255Scgd printf("Client Info:\n");
220*9bbbeef3Schristos printf("RPC Counts: (%" PRIu64 " call%s)\n", total,
2218073bda8Slukem total == 1 ? "" : "s");
2228073bda8Slukem
2238073bda8Slukem printf("%10s %14s %14s %14s %14s\n",
2248073bda8Slukem "null", "getattr", "setattr", "lookup", "access");
2258073bda8Slukem printf(
226*9bbbeef3Schristos "%10u %2u%% %10u %2u%% %10u %2u%% %10u %2u%% %10u %2u%%\n",
2278073bda8Slukem RPCSTAT(nfsstats.rpccnt[NFSPROC_NULL]),
2288073bda8Slukem RPCSTAT(nfsstats.rpccnt[NFSPROC_GETATTR]),
2298073bda8Slukem RPCSTAT(nfsstats.rpccnt[NFSPROC_SETATTR]),
2308073bda8Slukem RPCSTAT(nfsstats.rpccnt[NFSPROC_LOOKUP]),
2318073bda8Slukem RPCSTAT(nfsstats.rpccnt[NFSPROC_ACCESS]));
2328073bda8Slukem printf("%10s %14s %14s %14s %14s\n",
2338073bda8Slukem "readlink", "read", "write", "create", "mkdir");
2348073bda8Slukem printf(
235*9bbbeef3Schristos "%10u %2u%% %10u %2u%% %10u %2u%% %10u %2u%% %10u %2u%%\n",
2368073bda8Slukem RPCSTAT(nfsstats.rpccnt[NFSPROC_READLINK]),
2378073bda8Slukem RPCSTAT(nfsstats.rpccnt[NFSPROC_READ]),
2388073bda8Slukem RPCSTAT(nfsstats.rpccnt[NFSPROC_WRITE]),
2398073bda8Slukem RPCSTAT(nfsstats.rpccnt[NFSPROC_CREATE]),
2408073bda8Slukem RPCSTAT(nfsstats.rpccnt[NFSPROC_MKDIR]));
2418073bda8Slukem printf("%10s %14s %14s %14s %14s\n",
2428073bda8Slukem "symlink", "mknod", "remove", "rmdir", "rename");
2438073bda8Slukem printf(
244*9bbbeef3Schristos "%10u %2u%% %10u %2u%% %10u %2u%% %10u %2u%% %10u %2u%%\n",
2458073bda8Slukem RPCSTAT(nfsstats.rpccnt[NFSPROC_SYMLINK]),
2468073bda8Slukem RPCSTAT(nfsstats.rpccnt[NFSPROC_MKNOD]),
2478073bda8Slukem RPCSTAT(nfsstats.rpccnt[NFSPROC_REMOVE]),
2488073bda8Slukem RPCSTAT(nfsstats.rpccnt[NFSPROC_RMDIR]),
2498073bda8Slukem RPCSTAT(nfsstats.rpccnt[NFSPROC_RENAME]));
2508073bda8Slukem printf("%10s %14s %14s %14s %14s\n",
2518073bda8Slukem "link", "readdir", "readdirplus", "fsstat", "fsinfo");
2528073bda8Slukem printf(
253*9bbbeef3Schristos "%10u %2u%% %10u %2u%% %10u %2u%% %10u %2u%% %10u %2u%%\n",
2548073bda8Slukem RPCSTAT(nfsstats.rpccnt[NFSPROC_LINK]),
2558073bda8Slukem RPCSTAT(nfsstats.rpccnt[NFSPROC_READDIR]),
2568073bda8Slukem RPCSTAT(nfsstats.rpccnt[NFSPROC_READDIRPLUS]),
2578073bda8Slukem RPCSTAT(nfsstats.rpccnt[NFSPROC_FSSTAT]),
2588073bda8Slukem RPCSTAT(nfsstats.rpccnt[NFSPROC_FSINFO]));
259a67f31f4Syamt printf("%10s %14s\n",
260a67f31f4Syamt "pathconf", "commit");
261*9bbbeef3Schristos printf("%10u %2u%% %10u %2u%%\n",
2628073bda8Slukem RPCSTAT(nfsstats.rpccnt[NFSPROC_PATHCONF]),
263d7e50df6Sdogcow RPCSTAT(nfsstats.rpccnt[NFSPROC_COMMIT]));
2648073bda8Slukem
2658073bda8Slukem printf("RPC Info:\n");
2668073bda8Slukem printf("%10s %14s %14s %14s %14s\n",
2678073bda8Slukem "timeout", "invalid", "unexpected", "retries", "requests");
268*9bbbeef3Schristos printf("%10u %14u %14u %14u %14u\n",
26961f28255Scgd nfsstats.rpctimeouts,
27061f28255Scgd nfsstats.rpcinvalid,
27161f28255Scgd nfsstats.rpcunexpected,
27261f28255Scgd nfsstats.rpcretries,
27361f28255Scgd nfsstats.rpcrequests);
2748073bda8Slukem
27561f28255Scgd printf("Cache Info:\n");
2768073bda8Slukem printf("%10s %14s %14s %14s %14s\n",
2778073bda8Slukem "attrcache", "lookupcache", "read", "write", "readlink");
2788073bda8Slukem printf(
279*9bbbeef3Schristos "%10u %2u%% %10u %2u%% %10u %2u%% %10u %2u%% %10u %2u%%\n",
2808073bda8Slukem NUMPCT(nfsstats.attrcache_hits,
2818073bda8Slukem nfsstats.attrcache_misses),
2828073bda8Slukem NUMPCT(nfsstats.lookupcache_hits,
2838073bda8Slukem nfsstats.lookupcache_misses),
2848073bda8Slukem NUMPCT(nfsstats.biocache_reads - nfsstats.read_bios,
2858073bda8Slukem nfsstats.read_bios),
2868073bda8Slukem NUMPCT(nfsstats.biocache_writes - nfsstats.write_bios,
2878073bda8Slukem nfsstats.write_bios),
2888073bda8Slukem NUMPCT(nfsstats.biocache_readlinks - nfsstats.readlink_bios,
2898073bda8Slukem nfsstats.readlink_bios));
2908073bda8Slukem printf("%10s %14s\n",
2918073bda8Slukem "readdir", "direofcache");
292*9bbbeef3Schristos printf("%10u %2u%% %10u %2u%%\n",
2938073bda8Slukem NUMPCT(nfsstats.biocache_readdirs - nfsstats.readdir_bios,
2948073bda8Slukem nfsstats.readdir_bios),
2958073bda8Slukem NUMPCT(nfsstats.direofcache_hits,
2968073bda8Slukem nfsstats.direofcache_misses));
297b5232219Shubertf }
2988073bda8Slukem
2998073bda8Slukem if (printall || (clientinfo && serverinfo))
300b5232219Shubertf printf("\n");
3018073bda8Slukem
302b5232219Shubertf if (printall || serverinfo) {
3038073bda8Slukem total = 0;
3048073bda8Slukem for (i = 0; i < NFS_NPROCS; i++)
3058073bda8Slukem total += nfsstats.srvrpccnt[i];
306b5232219Shubertf printf("Server Info:\n");
307*9bbbeef3Schristos printf("RPC Counts: (%" PRIu64 " call%s)\n", total,
3088073bda8Slukem total == 1 ? "" : "s");
3098073bda8Slukem
3108073bda8Slukem printf("%10s %14s %14s %14s %14s\n",
3118073bda8Slukem "null", "getattr", "setattr", "lookup", "access");
3128073bda8Slukem printf(
313*9bbbeef3Schristos "%10u %2u%% %10u %2u%% %10u %2u%% %10u %2u%% %10u %2u%%\n",
3148073bda8Slukem RPCSTAT(nfsstats.srvrpccnt[NFSPROC_NULL]),
3158073bda8Slukem RPCSTAT(nfsstats.srvrpccnt[NFSPROC_GETATTR]),
3168073bda8Slukem RPCSTAT(nfsstats.srvrpccnt[NFSPROC_SETATTR]),
3178073bda8Slukem RPCSTAT(nfsstats.srvrpccnt[NFSPROC_LOOKUP]),
3188073bda8Slukem RPCSTAT(nfsstats.srvrpccnt[NFSPROC_ACCESS]));
3198073bda8Slukem printf("%10s %14s %14s %14s %14s\n",
3208073bda8Slukem "readlink", "read", "write", "create", "mkdir");
3218073bda8Slukem printf(
322*9bbbeef3Schristos "%10u %2u%% %10u %2u%% %10u %2u%% %10u %2u%% %10u %2u%%\n",
3238073bda8Slukem RPCSTAT(nfsstats.srvrpccnt[NFSPROC_READLINK]),
3248073bda8Slukem RPCSTAT(nfsstats.srvrpccnt[NFSPROC_READ]),
3258073bda8Slukem RPCSTAT(nfsstats.srvrpccnt[NFSPROC_WRITE]),
3268073bda8Slukem RPCSTAT(nfsstats.srvrpccnt[NFSPROC_CREATE]),
3278073bda8Slukem RPCSTAT(nfsstats.srvrpccnt[NFSPROC_MKDIR]));
3288073bda8Slukem printf("%10s %14s %14s %14s %14s\n",
3298073bda8Slukem "symlink", "mknod", "remove", "rmdir", "rename");
3308073bda8Slukem printf(
331*9bbbeef3Schristos "%10u %2u%% %10u %2u%% %10u %2u%% %10u %2u%% %10u %2u%%\n",
3328073bda8Slukem RPCSTAT(nfsstats.srvrpccnt[NFSPROC_SYMLINK]),
3338073bda8Slukem RPCSTAT(nfsstats.srvrpccnt[NFSPROC_MKNOD]),
3348073bda8Slukem RPCSTAT(nfsstats.srvrpccnt[NFSPROC_REMOVE]),
3358073bda8Slukem RPCSTAT(nfsstats.srvrpccnt[NFSPROC_RMDIR]),
3368073bda8Slukem RPCSTAT(nfsstats.srvrpccnt[NFSPROC_RENAME]));
3378073bda8Slukem printf("%10s %14s %14s %14s %14s\n",
3388073bda8Slukem "link", "readdir", "readdirplus", "fsstat", "fsinfo");
3398073bda8Slukem printf(
340*9bbbeef3Schristos "%10u %2u%% %10u %2u%% %10u %2u%% %10u %2u%% %10u %2u%%\n",
3418073bda8Slukem RPCSTAT(nfsstats.srvrpccnt[NFSPROC_LINK]),
3428073bda8Slukem RPCSTAT(nfsstats.srvrpccnt[NFSPROC_READDIR]),
3438073bda8Slukem RPCSTAT(nfsstats.srvrpccnt[NFSPROC_READDIRPLUS]),
3448073bda8Slukem RPCSTAT(nfsstats.srvrpccnt[NFSPROC_FSSTAT]),
3458073bda8Slukem RPCSTAT(nfsstats.srvrpccnt[NFSPROC_FSINFO]));
346a67f31f4Syamt printf("%10s %14s\n",
347a67f31f4Syamt "pathconf", "commit");
348*9bbbeef3Schristos printf("%10u %2u%% %10u %2u%%\n",
3498073bda8Slukem RPCSTAT(nfsstats.srvrpccnt[NFSPROC_PATHCONF]),
350d7e50df6Sdogcow RPCSTAT(nfsstats.srvrpccnt[NFSPROC_COMMIT]));
3518073bda8Slukem
3528073bda8Slukem printf("Server Errors:\n");
3538073bda8Slukem printf("%10s %14s\n",
3548073bda8Slukem "RPC errors", "faults");
355*9bbbeef3Schristos printf("%10u %14u\n",
3568073bda8Slukem nfsstats.srvrpc_errs,
3578073bda8Slukem nfsstats.srv_errs);
35861f28255Scgd printf("Server Cache Stats:\n");
3598073bda8Slukem printf("%10s %14s %14s %14s\n",
3608073bda8Slukem "inprogress", "idem", "non-idem", "misses");
361*9bbbeef3Schristos printf("%10u %14u %14u %14u\n",
36261f28255Scgd nfsstats.srvcache_inproghits,
36361f28255Scgd nfsstats.srvcache_idemdonehits,
36461f28255Scgd nfsstats.srvcache_nonidemdonehits,
36561f28255Scgd nfsstats.srvcache_misses);
366aa58cf93Sfvdl printf("Server Write Gathering:\n");
3678073bda8Slukem printf("%10s %14s %14s\n",
3688073bda8Slukem "writes", "write RPC", "OPs saved");
369*9bbbeef3Schristos printf("%10u %14u %14u %2u%%\n",
370aa58cf93Sfvdl nfsstats.srvvop_writes,
371aa58cf93Sfvdl nfsstats.srvrpccnt[NFSPROC_WRITE],
3728073bda8Slukem NUMPCT(
3738073bda8Slukem nfsstats.srvrpccnt[NFSPROC_WRITE]-nfsstats.srvvop_writes,
3748073bda8Slukem nfsstats.srvrpccnt[NFSPROC_WRITE]));
37561f28255Scgd }
376b5232219Shubertf }
37761f28255Scgd
378a2f897e7Sjoerg static u_char signalled; /* set if alarm goes off "early" */
37961f28255Scgd
38061f28255Scgd /*
38161f28255Scgd * Print a running summary of nfs statistics.
38261f28255Scgd * Repeat display every interval seconds, showing statistics
38361f28255Scgd * collected over that interval. Assumes that interval is non-zero.
38461f28255Scgd * First line printed at top of screen is always cumulative.
38561f28255Scgd */
386a2f897e7Sjoerg static void
sidewaysintpr(u_int interval)387a2f897e7Sjoerg sidewaysintpr(u_int interval)
38861f28255Scgd {
389d25d8e4dSyamt struct nfsstats nfsstats;
39061f28255Scgd int hdrcnt, oldmask;
391d25d8e4dSyamt struct stats {
392d25d8e4dSyamt int client[NSHORTPROC];
393d25d8e4dSyamt int server[NSHORTPROC];
394d25d8e4dSyamt } current, last;
39561f28255Scgd
39661f28255Scgd (void)signal(SIGALRM, catchalarm);
39761f28255Scgd signalled = 0;
39861f28255Scgd (void)alarm(interval);
399d25d8e4dSyamt memset(&last, 0, sizeof(last));
40061f28255Scgd
40161f28255Scgd for (hdrcnt = 1;;) {
402fc99e5eaSlukem size_t i;
403d25d8e4dSyamt
40461f28255Scgd if (!--hdrcnt) {
40561f28255Scgd printhdr();
40661f28255Scgd hdrcnt = 20;
40761f28255Scgd }
40854736c47Ssimonb getstats(&nfsstats);
409d25d8e4dSyamt memset(¤t, 0, sizeof(current));
410d25d8e4dSyamt for (i = 0; i < NSHORTPROC; i++) {
411d25d8e4dSyamt int mask = shortprocs[i].mask;
412d25d8e4dSyamt int idx;
413d25d8e4dSyamt
414d25d8e4dSyamt while ((idx = ffs(mask)) != 0) {
415d25d8e4dSyamt idx--;
416d25d8e4dSyamt mask &= ~(1 << idx);
417d25d8e4dSyamt current.client[i] += nfsstats.rpccnt[idx];
418d25d8e4dSyamt current.server[i] += nfsstats.srvrpccnt[idx];
419d25d8e4dSyamt }
420d25d8e4dSyamt }
421d25d8e4dSyamt
422d25d8e4dSyamt if (printall || clientinfo) {
423d25d8e4dSyamt printf("Client:");
424d25d8e4dSyamt for (i = 0; i < NSHORTPROC; i++)
425*9bbbeef3Schristos printf(" %7u",
426d25d8e4dSyamt current.client[i] - last.client[i]);
427d25d8e4dSyamt printf("\n");
428d25d8e4dSyamt }
429d25d8e4dSyamt if (printall || serverinfo) {
430d25d8e4dSyamt printf("Server:");
431d25d8e4dSyamt for (i = 0; i < NSHORTPROC; i++)
432*9bbbeef3Schristos printf(" %7u",
433d25d8e4dSyamt current.server[i] - last.server[i]);
434d25d8e4dSyamt printf("\n");
435d25d8e4dSyamt }
436d25d8e4dSyamt memcpy(&last, ¤t, sizeof(last));
43761f28255Scgd fflush(stdout);
43861f28255Scgd oldmask = sigblock(sigmask(SIGALRM));
43961f28255Scgd if (!signalled)
44061f28255Scgd sigpause(0);
44161f28255Scgd sigsetmask(oldmask);
44261f28255Scgd signalled = 0;
44361f28255Scgd (void)alarm(interval);
44461f28255Scgd }
44561f28255Scgd /*NOTREACHED*/
44661f28255Scgd }
44761f28255Scgd
448a2f897e7Sjoerg static void
printhdr(void)449a2f897e7Sjoerg printhdr(void)
45061f28255Scgd {
451fc99e5eaSlukem size_t i;
452d717877cSmrg
453d25d8e4dSyamt printf(" ");
454d25d8e4dSyamt for (i = 0; i < NSHORTPROC; i++)
455d25d8e4dSyamt printf("%7.7s ", shortprocs[i].name);
456d25d8e4dSyamt printf("\n");
45761f28255Scgd fflush(stdout);
45861f28255Scgd }
45961f28255Scgd
46061f28255Scgd /*
46161f28255Scgd * Called if an interval expires before sidewaysintpr has completed a loop.
46261f28255Scgd * Sets a flag to not wait for the alarm.
46361f28255Scgd */
464a2f897e7Sjoerg static void
catchalarm(int dummy)465a2f897e7Sjoerg catchalarm(int dummy)
46661f28255Scgd {
467d717877cSmrg
46861f28255Scgd signalled = 1;
46961f28255Scgd }
47061f28255Scgd
471a2f897e7Sjoerg static void
usage(void)472a2f897e7Sjoerg usage(void)
47361f28255Scgd {
474d717877cSmrg
47561f28255Scgd (void)fprintf(stderr,
476*9bbbeef3Schristos "Usage: %s [-cs] [-M core] [-N system] [-w interval]\n",
477*9bbbeef3Schristos getprogname());
47861f28255Scgd exit(1);
47961f28255Scgd }
480