1/*
2 * Copyright (c) 1983, 1989, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Rick Macklem at The University of Guelph.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 4. Neither the name of the University nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32/*-
33 * Copyright (c) 2004, 2008, 2009 Silicon Graphics International Corp.
34 * All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 *    notice, this list of conditions, and the following disclaimer,
41 *    without modification.
42 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
43 *    substantially similar to the "NO WARRANTY" disclaimer below
44 *    ("Disclaimer") and any redistribution must be conditioned upon
45 *    including a substantially similar Disclaimer requirement for further
46 *    binary redistribution.
47 *
48 * NO WARRANTY
49 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
50 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
51 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
52 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
53 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
57 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
58 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
59 * POSSIBILITY OF SUCH DAMAGES.
60 */
61
62
63#ifndef lint
64static const char copyright[] =
65"@(#) Copyright (c) 1983, 1989, 1993\n\
66	The Regents of the University of California.  All rights reserved.\n";
67#endif /* not lint */
68
69#ifndef lint
70#if 0
71static char sccsid[] = "@(#)nfsstat.c	8.2 (Berkeley) 3/31/95";
72#endif
73static const char rcsid[] =
74  "$FreeBSD: stable/11/usr.bin/nfsstat/nfsstat.c 321000 2017-07-14 21:43:57Z rmacklem $";
75#endif /* not lint */
76
77#include <sys/param.h>
78#include <sys/module.h>
79#include <sys/mount.h>
80#include <sys/time.h>
81#include <sys/sysctl.h>
82#include <nfs/nfsproto.h>
83#include <nfsclient/nfs.h>
84#include <nfsserver/nfs.h>
85#include <nfs/nfssvc.h>
86
87#include <fs/nfs/nfsport.h>
88
89#include <signal.h>
90#include <fcntl.h>
91#include <ctype.h>
92#include <errno.h>
93#include <limits.h>
94#include <nlist.h>
95#include <unistd.h>
96#include <stdio.h>
97#include <stdint.h>
98#include <stdlib.h>
99#include <string.h>
100#include <paths.h>
101#include <devstat.h>
102#include <err.h>
103
104static int widemode = 0;
105static int zflag = 0;
106static int printtitle = 1;
107static struct nfsstatsv1 ext_nfsstats;
108static int extra_output = 0;
109
110static void intpr(int, int);
111static void printhdr(int, int, int);
112static void usage(void);
113static char *sperc1(int, int);
114static char *sperc2(int, int);
115static void exp_intpr(int, int);
116static void exp41_intpr(int, int);
117static void exp_sidewaysintpr(u_int, int, int, int);
118static void compute_new_stats(struct nfsstatsv1 *cur_stats,
119    struct nfsstatsv1 *prev_stats, int curop, long double etime,
120    long double *mbsec, long double *kb_per_transfer,
121    long double *transfers_per_second, long double *ms_per_transfer,
122    uint64_t *queue_len, long double *busy_pct);
123
124#define DELTA(field)	(nfsstats.field - lastst.field)
125
126#define	STAT_TYPE_READ		0
127#define	STAT_TYPE_WRITE		1
128#define	STAT_TYPE_COMMIT	2
129#define	NUM_STAT_TYPES		3
130
131struct stattypes {
132	int stat_type;
133	int nfs_type;
134};
135static struct stattypes statstruct[] = {
136	{STAT_TYPE_READ, NFSV4OP_READ},
137	{STAT_TYPE_WRITE, NFSV4OP_WRITE},
138	{STAT_TYPE_COMMIT, NFSV4OP_COMMIT}
139};
140
141#define	STAT_TYPE_TO_NFS(stat_type)	statstruct[stat_type].nfs_type
142
143int
144main(int argc, char **argv)
145{
146	u_int interval;
147	int clientOnly = -1;
148	int serverOnly = -1;
149	int newStats = 0;
150	int ch;
151	char *memf, *nlistf;
152	int mntlen, i;
153	char buf[1024];
154	struct statfs *mntbuf;
155	struct nfscl_dumpmntopts dumpmntopts;
156
157	interval = 0;
158	memf = nlistf = NULL;
159	while ((ch = getopt(argc, argv, "cdEesWM:mN:w:z")) != -1)
160		switch(ch) {
161		case 'M':
162			memf = optarg;
163			break;
164		case 'm':
165			/* Display mount options for NFS mount points. */
166			mntlen = getmntinfo(&mntbuf, MNT_NOWAIT);
167			for (i = 0; i < mntlen; i++) {
168				if (strcmp(mntbuf->f_fstypename, "nfs") == 0) {
169					dumpmntopts.ndmnt_fname =
170					    mntbuf->f_mntonname;
171					dumpmntopts.ndmnt_buf = buf;
172					dumpmntopts.ndmnt_blen = sizeof(buf);
173					if (nfssvc(NFSSVC_DUMPMNTOPTS,
174					    &dumpmntopts) >= 0)
175						printf("%s on %s\n%s\n",
176						    mntbuf->f_mntfromname,
177						    mntbuf->f_mntonname, buf);
178					else if (errno == EPERM)
179						errx(1, "Only priviledged users"
180						    " can use the -m option");
181				}
182				mntbuf++;
183			}
184			exit(0);
185		case 'N':
186			nlistf = optarg;
187			break;
188		case 'W':
189			widemode = 1;
190			break;
191		case 'w':
192			interval = atoi(optarg);
193			break;
194		case 'c':
195			clientOnly = 1;
196			if (serverOnly < 0)
197				serverOnly = 0;
198			break;
199		case 'd':
200			newStats = 1;
201			if (interval == 0)
202				interval = 1;
203			break;
204		case 's':
205			serverOnly = 1;
206			if (clientOnly < 0)
207				clientOnly = 0;
208			break;
209		case 'z':
210			zflag = 1;
211			break;
212		case 'E':
213			if (extra_output != 0)
214				errx(1, "-e and -E are mutually exclusive");
215			extra_output = 2;
216			break;
217		case 'e':
218			if (extra_output != 0)
219				errx(1, "-e and -E are mutually exclusive");
220			extra_output = 1;
221			break;
222		case '?':
223		default:
224			usage();
225		}
226	argc -= optind;
227	argv += optind;
228
229#define	BACKWARD_COMPATIBILITY
230#ifdef	BACKWARD_COMPATIBILITY
231	if (*argv) {
232		interval = atoi(*argv);
233		if (*++argv) {
234			nlistf = *argv;
235			if (*++argv)
236				memf = *argv;
237		}
238	}
239#endif
240	if (modfind("nfscommon") < 0)
241		errx(1, "NFS client/server not loaded");
242
243	if (interval) {
244		exp_sidewaysintpr(interval, clientOnly, serverOnly,
245		    newStats);
246	} else {
247		if (extra_output == 2)
248			exp41_intpr(clientOnly, serverOnly);
249		else if (extra_output == 1)
250			exp_intpr(clientOnly, serverOnly);
251		else
252			intpr(clientOnly, serverOnly);
253	}
254	exit(0);
255}
256
257/*
258 * Print a description of the nfs stats.
259 */
260static void
261intpr(int clientOnly, int serverOnly)
262{
263	int nfssvc_flag;
264
265	nfssvc_flag = NFSSVC_GETSTATS | NFSSVC_NEWSTRUCT;
266	if (zflag != 0) {
267		if (clientOnly != 0)
268			nfssvc_flag |= NFSSVC_ZEROCLTSTATS;
269		if (serverOnly != 0)
270			nfssvc_flag |= NFSSVC_ZEROSRVSTATS;
271	}
272	ext_nfsstats.vers = NFSSTATS_V1;
273	if (nfssvc(nfssvc_flag, &ext_nfsstats) < 0)
274		err(1, "Can't get stats");
275	if (clientOnly) {
276		printf("Client Info:\n");
277		printf("Rpc Counts:\n");
278		printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
279			"Getattr", "Setattr", "Lookup", "Readlink", "Read",
280			"Write", "Create", "Remove");
281		printf("%9ju %9ju %9ju %9ju %9ju %9ju %9ju %9ju\n",
282			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_GETATTR],
283			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SETATTR],
284			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LOOKUP],
285			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READLINK],
286			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READ],
287			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_WRITE],
288			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_CREATE],
289			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_REMOVE]);
290		printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
291			"Rename", "Link", "Symlink", "Mkdir", "Rmdir",
292			"Readdir", "RdirPlus", "Access");
293		printf("%9ju %9ju %9ju %9ju %9ju %9ju %9ju %9ju\n",
294			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_RENAME],
295			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LINK],
296			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SYMLINK],
297			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_MKDIR],
298			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_RMDIR],
299			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READDIR],
300			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READDIRPLUS],
301			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_ACCESS]);
302		printf("%9.9s %9.9s %9.9s %9.9s %9.9s\n",
303			"Mknod", "Fsstat", "Fsinfo", "PathConf", "Commit");
304		printf("%9ju %9ju %9ju %9ju %9ju\n",
305			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_MKNOD],
306			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_FSSTAT],
307			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_FSINFO],
308			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_PATHCONF],
309			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_COMMIT]);
310		printf("Rpc Info:\n");
311		printf("%9.9s %9.9s %9.9s %9.9s %9.9s\n",
312			"TimedOut", "Invalid", "X Replies", "Retries",
313			"Requests");
314		printf("%9ju %9ju %9ju %9ju %9ju\n",
315			(uintmax_t)ext_nfsstats.rpctimeouts,
316			(uintmax_t)ext_nfsstats.rpcinvalid,
317			(uintmax_t)ext_nfsstats.rpcunexpected,
318			(uintmax_t)ext_nfsstats.rpcretries,
319			(uintmax_t)ext_nfsstats.rpcrequests);
320		printf("Cache Info:\n");
321		printf("%9.9s %9.9s %9.9s %9.9s",
322			"Attr Hits", "Misses", "Lkup Hits", "Misses");
323		printf(" %9.9s %9.9s %9.9s %9.9s\n",
324			"BioR Hits", "Misses", "BioW Hits", "Misses");
325		printf("%9ju %9ju %9ju %9ju",
326			(uintmax_t)ext_nfsstats.attrcache_hits,
327			(uintmax_t)ext_nfsstats.attrcache_misses,
328			(uintmax_t)ext_nfsstats.lookupcache_hits,
329			(uintmax_t)ext_nfsstats.lookupcache_misses);
330		printf(" %9ju %9ju %9ju %9ju\n",
331			(uintmax_t)(ext_nfsstats.biocache_reads -
332			ext_nfsstats.read_bios),
333			(uintmax_t)ext_nfsstats.read_bios,
334			(uintmax_t)(ext_nfsstats.biocache_writes -
335			ext_nfsstats.write_bios),
336			(uintmax_t)ext_nfsstats.write_bios);
337		printf("%9.9s %9.9s %9.9s %9.9s",
338			"BioRLHits", "Misses", "BioD Hits", "Misses");
339		printf(" %9.9s %9.9s %9.9s %9.9s\n", "DirE Hits", "Misses", "Accs Hits", "Misses");
340		printf("%9ju %9ju %9ju %9ju",
341			(uintmax_t)(ext_nfsstats.biocache_readlinks -
342			ext_nfsstats.readlink_bios),
343			(uintmax_t)ext_nfsstats.readlink_bios,
344			(uintmax_t)(ext_nfsstats.biocache_readdirs -
345			ext_nfsstats.readdir_bios),
346			(uintmax_t)ext_nfsstats.readdir_bios);
347		printf(" %9ju %9ju %9ju %9ju\n",
348			(uintmax_t)ext_nfsstats.direofcache_hits,
349			(uintmax_t)ext_nfsstats.direofcache_misses,
350			(uintmax_t)ext_nfsstats.accesscache_hits,
351			(uintmax_t)ext_nfsstats.accesscache_misses);
352	}
353	if (serverOnly) {
354		printf("\nServer Info:\n");
355		printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
356			"Getattr", "Setattr", "Lookup", "Readlink", "Read",
357			"Write", "Create", "Remove");
358		printf("%9ju %9ju %9ju %9ju %9ju %9ju %9ju %9ju\n",
359			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_GETATTR],
360			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SETATTR],
361			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LOOKUP],
362			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READLINK],
363			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READ],
364			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_WRITE],
365			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_CREATE],
366			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_REMOVE]);
367		printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
368			"Rename", "Link", "Symlink", "Mkdir", "Rmdir",
369			"Readdir", "RdirPlus", "Access");
370		printf("%9ju %9ju %9ju %9ju %9ju %9ju %9ju %9ju\n",
371			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RENAME],
372			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LINK],
373			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SYMLINK],
374			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_MKDIR],
375			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RMDIR],
376			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READDIR],
377			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READDIRPLUS],
378			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_ACCESS]);
379		printf("%9.9s %9.9s %9.9s %9.9s %9.9s\n",
380			"Mknod", "Fsstat", "Fsinfo", "PathConf", "Commit");
381		printf("%9ju %9ju %9ju %9ju %9ju\n",
382			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_MKNOD],
383			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_FSSTAT],
384			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_FSINFO],
385			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_PATHCONF],
386			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_COMMIT]);
387		printf("Server Ret-Failed\n");
388		printf("%17ju\n", (uintmax_t)ext_nfsstats.srvrpc_errs);
389		printf("Server Faults\n");
390		printf("%13ju\n", (uintmax_t)ext_nfsstats.srv_errs);
391		printf("Server Cache Stats:\n");
392		printf("%9.9s %9.9s %9.9s %9.9s\n",
393			"Inprog", "Idem", "Non-idem", "Misses");
394		printf("%9ju %9ju %9ju %9ju\n",
395			(uintmax_t)ext_nfsstats.srvcache_inproghits,
396			(uintmax_t)ext_nfsstats.srvcache_idemdonehits,
397			(uintmax_t)ext_nfsstats.srvcache_nonidemdonehits,
398			(uintmax_t)ext_nfsstats.srvcache_misses);
399		printf("Server Write Gathering:\n");
400		printf("%9.9s %9.9s %9.9s\n",
401			"WriteOps", "WriteRPC", "Opsaved");
402		/*
403		 * The new client doesn't do write gathering. It was
404		 * only useful for NFSv2.
405		 */
406		printf("%9ju %9ju %9d\n",
407			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_WRITE],
408			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_WRITE], 0);
409	}
410}
411
412static void
413printhdr(int clientOnly, int serverOnly, int newStats)
414{
415
416	if (newStats) {
417		printf(" [%s Read %s]  [%s Write %s]  "
418		    "%s[=========== Total ============]\n"
419		    " KB/t   tps    MB/s%s  KB/t   tps    MB/s%s  "
420		    "%sKB/t   tps    MB/s    ms  ql  %%b",
421		    widemode ? "========" : "=====",
422		    widemode ? "========" : "=====",
423		    widemode ? "========" : "=====",
424		    widemode ? "======="  : "====",
425		    widemode ? "[Commit ]  " : "",
426		    widemode ? "    ms" : "",
427		    widemode ? "    ms" : "",
428		    widemode ? "tps    ms  " : "");
429	} else {
430		printf("%s%6.6s %6.6s %6.6s %6.6s %6.6s %6.6s %6.6s %6.6s",
431		    ((serverOnly && clientOnly) ? "        " : " "),
432		    "GtAttr", "Lookup", "Rdlink", "Read", "Write", "Rename",
433		    "Access", "Rddir");
434		if (widemode && clientOnly) {
435			printf(" Attr Lkup BioR BioW Accs BioD");
436		}
437	}
438	printf("\n");
439	fflush(stdout);
440}
441
442static void
443usage(void)
444{
445	(void)fprintf(stderr,
446	    "usage: nfsstat [-cdemszW] [-M core] [-N system] [-w wait]\n");
447	exit(1);
448}
449
450static char SPBuf[64][8];
451static int SPIndex;
452
453static char *
454sperc1(int hits, int misses)
455{
456	char *p = SPBuf[SPIndex];
457
458	if (hits + misses) {
459		sprintf(p, "%3d%%",
460		    (int)(char)((quad_t)hits * 100 / (hits + misses)));
461	} else {
462		sprintf(p, "   -");
463	}
464	SPIndex = (SPIndex + 1) & 63;
465	return(p);
466}
467
468static char *
469sperc2(int ttl, int misses)
470{
471	char *p = SPBuf[SPIndex];
472
473	if (ttl) {
474		sprintf(p, "%3d%%",
475		    (int)(char)((quad_t)(ttl - misses) * 100 / ttl));
476	} else {
477		sprintf(p, "   -");
478	}
479	SPIndex = (SPIndex + 1) & 63;
480	return(p);
481}
482
483#define DELTA_T(field)					\
484	devstat_compute_etime(&cur_stats->field,	\
485	(prev_stats ? &prev_stats->field : NULL))
486
487/*
488 * XXX KDM mostly copied from ctlstat.  We should commonize the code (and
489 * the devstat code) somehow.
490 */
491static void
492compute_new_stats(struct nfsstatsv1 *cur_stats,
493		  struct nfsstatsv1 *prev_stats, int curop,
494		  long double etime, long double *mbsec,
495		  long double *kb_per_transfer,
496		  long double *transfers_per_second,
497		  long double *ms_per_transfer, uint64_t *queue_len,
498		  long double *busy_pct)
499{
500	uint64_t total_bytes = 0, total_operations = 0;
501	struct bintime total_time_bt;
502	struct timespec total_time_ts;
503
504	bzero(&total_time_bt, sizeof(total_time_bt));
505	bzero(&total_time_ts, sizeof(total_time_ts));
506
507	total_bytes = cur_stats->srvbytes[curop];
508	total_operations = cur_stats->srvops[curop];
509	if (prev_stats != NULL) {
510		total_bytes -= prev_stats->srvbytes[curop];
511		total_operations -= prev_stats->srvops[curop];
512	}
513
514	*mbsec = total_bytes;
515	*mbsec /= 1024 * 1024;
516	if (etime > 0.0) {
517		*busy_pct = DELTA_T(busytime);
518		if (*busy_pct < 0)
519			*busy_pct = 0;
520		*busy_pct /= etime;
521		*busy_pct *= 100;
522		if (*busy_pct < 0)
523			*busy_pct = 0;
524		*mbsec /= etime;
525	} else {
526		*busy_pct = 0;
527		*mbsec = 0;
528	}
529	*kb_per_transfer = total_bytes;
530	*kb_per_transfer /= 1024;
531	if (total_operations > 0)
532		*kb_per_transfer /= total_operations;
533	else
534		*kb_per_transfer = 0;
535	if (etime > 0.0) {
536		*transfers_per_second = total_operations;
537		*transfers_per_second /= etime;
538	} else {
539		*transfers_per_second = 0.0;
540	}
541
542	if (total_operations > 0) {
543		*ms_per_transfer = DELTA_T(srvduration[curop]);
544		*ms_per_transfer /= total_operations;
545		*ms_per_transfer *= 1000;
546	} else
547		*ms_per_transfer = 0.0;
548
549	*queue_len = cur_stats->srvstartcnt - cur_stats->srvdonecnt;
550}
551
552/*
553 * Print a description of the nfs stats for the experimental client/server.
554 */
555static void
556exp_intpr(int clientOnly, int serverOnly)
557{
558	int nfssvc_flag;
559
560	nfssvc_flag = NFSSVC_GETSTATS | NFSSVC_NEWSTRUCT;
561	if (zflag != 0) {
562		if (clientOnly != 0)
563			nfssvc_flag |= NFSSVC_ZEROCLTSTATS;
564		if (serverOnly != 0)
565			nfssvc_flag |= NFSSVC_ZEROSRVSTATS;
566	}
567	ext_nfsstats.vers = NFSSTATS_V1;
568	if (nfssvc(nfssvc_flag, &ext_nfsstats) < 0)
569		err(1, "Can't get stats");
570	if (clientOnly != 0) {
571		if (printtitle) {
572			printf("Client Info:\n");
573			printf("Rpc Counts:\n");
574			printf(
575			    "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n"
576			    , "Getattr", "Setattr", "Lookup", "Readlink",
577			    "Read", "Write", "Create", "Remove");
578		}
579		printf("%9ju %9ju %9ju %9ju %9ju %9ju %9ju %9ju\n",
580		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_GETATTR],
581		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SETATTR],
582		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LOOKUP],
583		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READLINK],
584		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READ],
585		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_WRITE],
586		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_CREATE],
587		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_REMOVE]);
588		if (printtitle)
589			printf(
590			    "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n"
591			    , "Rename", "Link", "Symlink", "Mkdir", "Rmdir",
592			    "Readdir", "RdirPlus", "Access");
593		printf("%9ju %9ju %9ju %9ju %9ju %9ju %9ju %9ju\n",
594		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_RENAME],
595		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LINK],
596		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SYMLINK],
597		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_MKDIR],
598		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_RMDIR],
599		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READDIR],
600		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READDIRPLUS],
601		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_ACCESS]);
602		if (printtitle)
603			printf(
604			    "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n"
605			    , "Mknod", "Fsstat", "Fsinfo", "PathConf",
606			    "Commit", "SetClId", "SetClIdCf", "Lock");
607		printf("%9ju %9ju %9ju %9ju %9ju %9ju %9ju %9ju\n",
608		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_MKNOD],
609		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_FSSTAT],
610		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_FSINFO],
611		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_PATHCONF],
612		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_COMMIT],
613		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SETCLIENTID],
614		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SETCLIENTIDCFRM],
615		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LOCK]);
616		if (printtitle)
617			printf("%9.9s %9.9s %9.9s %9.9s\n",
618			    "LockT", "LockU", "Open", "OpenCfr");
619		printf("%9ju %9ju %9ju %9ju\n",
620		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LOCKT],
621		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LOCKU],
622		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_OPEN],
623		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_OPENCONFIRM]);
624		if (printtitle)
625			printf(
626			    "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n"
627			    , "OpenOwner", "Opens", "LockOwner",
628			    "Locks", "Delegs", "LocalOwn",
629			    "LocalOpen", "LocalLOwn");
630		printf("%9ju %9ju %9ju %9ju %9ju %9ju %9ju %9ju\n",
631		    (uintmax_t)ext_nfsstats.clopenowners,
632		    (uintmax_t)ext_nfsstats.clopens,
633		    (uintmax_t)ext_nfsstats.cllockowners,
634		    (uintmax_t)ext_nfsstats.cllocks,
635		    (uintmax_t)ext_nfsstats.cldelegates,
636		    (uintmax_t)ext_nfsstats.cllocalopenowners,
637		    (uintmax_t)ext_nfsstats.cllocalopens,
638		    (uintmax_t)ext_nfsstats.cllocallockowners);
639		if (printtitle)
640			printf("%9.9s\n", "LocalLock");
641		printf("%9ju\n", (uintmax_t)ext_nfsstats.cllocallocks);
642		if (printtitle) {
643			printf("Rpc Info:\n");
644			printf("%9.9s %9.9s %9.9s %9.9s %9.9s\n",
645			    "TimedOut", "Invalid", "X Replies", "Retries",
646			    "Requests");
647		}
648		printf("%9ju %9ju %9ju %9ju %9ju\n",
649		    (uintmax_t)ext_nfsstats.rpctimeouts,
650		    (uintmax_t)ext_nfsstats.rpcinvalid,
651		    (uintmax_t)ext_nfsstats.rpcunexpected,
652		    (uintmax_t)ext_nfsstats.rpcretries,
653		    (uintmax_t)ext_nfsstats.rpcrequests);
654		if (printtitle) {
655			printf("Cache Info:\n");
656			printf("%9.9s %9.9s %9.9s %9.9s",
657			    "Attr Hits", "Misses", "Lkup Hits", "Misses");
658			printf(" %9.9s %9.9s %9.9s %9.9s\n",
659			    "BioR Hits", "Misses", "BioW Hits", "Misses");
660		}
661		printf("%9ju %9ju %9ju %9ju",
662		    (uintmax_t)ext_nfsstats.attrcache_hits,
663		    (uintmax_t)ext_nfsstats.attrcache_misses,
664		    (uintmax_t)ext_nfsstats.lookupcache_hits,
665		    (uintmax_t)ext_nfsstats.lookupcache_misses);
666		printf(" %9ju %9ju %9ju %9ju\n",
667		    (uintmax_t)(ext_nfsstats.biocache_reads -
668		    ext_nfsstats.read_bios),
669		    (uintmax_t)ext_nfsstats.read_bios,
670		    (uintmax_t)(ext_nfsstats.biocache_writes -
671		    ext_nfsstats.write_bios),
672		    (uintmax_t)ext_nfsstats.write_bios);
673		if (printtitle) {
674			printf("%9.9s %9.9s %9.9s %9.9s",
675			    "BioRLHits", "Misses", "BioD Hits", "Misses");
676			printf(" %9.9s %9.9s\n", "DirE Hits", "Misses");
677		}
678		printf("%9ju %9ju %9ju %9ju",
679		    (uintmax_t)(ext_nfsstats.biocache_readlinks -
680		    ext_nfsstats.readlink_bios),
681		    (uintmax_t)ext_nfsstats.readlink_bios,
682		    (uintmax_t)(ext_nfsstats.biocache_readdirs -
683		    ext_nfsstats.readdir_bios),
684		    (uintmax_t)ext_nfsstats.readdir_bios);
685		printf(" %9ju %9ju\n",
686		    (uintmax_t)ext_nfsstats.direofcache_hits,
687		    (uintmax_t)ext_nfsstats.direofcache_misses);
688	}
689	if (serverOnly != 0) {
690		if (printtitle) {
691			printf("\nServer Info:\n");
692			printf(
693			    "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n"
694			    , "Getattr", "Setattr", "Lookup", "Readlink",
695			    "Read", "Write", "Create", "Remove");
696		}
697		printf("%9ju %9ju %9ju %9ju %9ju %9ju %9ju %9ju\n",
698		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_GETATTR],
699		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SETATTR],
700		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LOOKUP],
701		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READLINK],
702		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READ],
703		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_WRITE],
704		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_V3CREATE],
705		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_REMOVE]);
706		if (printtitle)
707			printf(
708			    "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n"
709			    , "Rename", "Link", "Symlink", "Mkdir", "Rmdir",
710			    "Readdir", "RdirPlus", "Access");
711		printf("%9ju %9ju %9ju %9ju %9ju %9ju %9ju %9ju\n",
712		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RENAME],
713		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LINK],
714		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SYMLINK],
715		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_MKDIR],
716		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RMDIR],
717		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READDIR],
718		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READDIRPLUS],
719		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_ACCESS]);
720		if (printtitle)
721			printf(
722			    "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n"
723			    , "Mknod", "Fsstat", "Fsinfo", "PathConf",
724			    "Commit", "LookupP", "SetClId", "SetClIdCf");
725		printf("%9ju %9ju %9ju %9ju %9ju %9ju %9ju %9ju\n",
726		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_MKNOD],
727		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_FSSTAT],
728		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_FSINFO],
729		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_PATHCONF],
730		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_COMMIT],
731		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LOOKUPP],
732		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SETCLIENTID],
733		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SETCLIENTIDCFRM]);
734		if (printtitle)
735			printf(
736			    "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n"
737			    , "Open", "OpenAttr", "OpenDwnGr", "OpenCfrm",
738			    "DelePurge", "DeleRet", "GetFH", "Lock");
739		printf("%9ju %9ju %9ju %9ju %9ju %9ju %9ju %9ju\n",
740		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_OPEN],
741		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_OPENATTR],
742		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_OPENDOWNGRADE],
743		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_OPENCONFIRM],
744		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_DELEGPURGE],
745		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_DELEGRETURN],
746		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_GETFH],
747		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LOCK]);
748		if (printtitle)
749			printf(
750			    "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n"
751			    , "LockT", "LockU", "Close", "Verify", "NVerify",
752			    "PutFH", "PutPubFH", "PutRootFH");
753		printf("%9ju %9ju %9ju %9ju %9ju %9ju %9ju %9ju\n",
754		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LOCKT],
755		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LOCKU],
756		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_CLOSE],
757		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_VERIFY],
758		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_NVERIFY],
759		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_PUTFH],
760		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_PUTPUBFH],
761		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_PUTROOTFH]);
762		if (printtitle)
763			printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
764			    "Renew", "RestoreFH", "SaveFH", "Secinfo",
765			    "RelLckOwn", "V4Create");
766		printf("%9ju %9ju %9ju %9ju %9ju %9ju\n",
767		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RENEW],
768		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RESTOREFH],
769		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SAVEFH],
770		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SECINFO],
771		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RELEASELCKOWN],
772		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_CREATE]);
773		if (printtitle) {
774			printf("Server:\n");
775			printf("%9.9s %9.9s %9.9s\n",
776			    "Retfailed", "Faults", "Clients");
777		}
778		printf("%9ju %9ju %9ju\n",
779		    (uintmax_t)ext_nfsstats.srv_errs,
780		    (uintmax_t)ext_nfsstats.srvrpc_errs,
781		    (uintmax_t)ext_nfsstats.srvclients);
782		if (printtitle)
783			printf("%9.9s %9.9s %9.9s %9.9s %9.9s \n",
784			    "OpenOwner", "Opens", "LockOwner",
785			    "Locks", "Delegs");
786		printf("%9ju %9ju %9ju %9ju %9ju \n",
787		    (uintmax_t)ext_nfsstats.srvopenowners,
788		    (uintmax_t)ext_nfsstats.srvopens,
789		    (uintmax_t)ext_nfsstats.srvlockowners,
790		    (uintmax_t)ext_nfsstats.srvlocks,
791		    (uintmax_t)ext_nfsstats.srvdelegates);
792		if (printtitle) {
793			printf("Server Cache Stats:\n");
794			printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
795			    "Inprog", "Idem", "Non-idem", "Misses",
796			    "CacheSize", "TCPPeak");
797		}
798		printf("%9ju %9ju %9ju %9ju %9ju %9ju\n",
799		    (uintmax_t)ext_nfsstats.srvcache_inproghits,
800		    (uintmax_t)ext_nfsstats.srvcache_idemdonehits,
801		    (uintmax_t)ext_nfsstats.srvcache_nonidemdonehits,
802		    (uintmax_t)ext_nfsstats.srvcache_misses,
803		    (uintmax_t)ext_nfsstats.srvcache_size,
804		    (uintmax_t)ext_nfsstats.srvcache_tcppeak);
805	}
806}
807
808/*
809 * Print a description of the nfs stats for the client/server,
810 * including NFSv4.1.
811 */
812static void
813exp41_intpr(int clientOnly, int serverOnly)
814{
815	int nfssvc_flag;
816
817	nfssvc_flag = NFSSVC_GETSTATS | NFSSVC_NEWSTRUCT;
818	if (zflag != 0) {
819		if (clientOnly != 0)
820			nfssvc_flag |= NFSSVC_ZEROCLTSTATS;
821		if (serverOnly != 0)
822			nfssvc_flag |= NFSSVC_ZEROSRVSTATS;
823	}
824	ext_nfsstats.vers = NFSSTATS_V1;
825	if (nfssvc(nfssvc_flag, &ext_nfsstats) < 0)
826		err(1, "Can't get stats");
827	if (clientOnly != 0) {
828		if (printtitle) {
829			printf("Client Info:\n");
830			printf("RPC Counts:\n");
831			printf(
832			    "%12.12s %12.12s %12.12s %12.12s %12.12s %12.12s\n",
833			    "Getattr", "Setattr", "Lookup", "Readlink", "Read",
834			    "Write");
835		}
836		printf("%12ju %12ju %12ju %12ju %12ju %12ju\n",
837		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_GETATTR],
838		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SETATTR],
839		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LOOKUP],
840		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READLINK],
841		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READ],
842		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_WRITE]);
843		if (printtitle)
844			printf(
845			    "%12.12s %12.12s %12.12s %12.12s %12.12s %12.12s\n",
846			    "Create", "Remove", "Rename", "Link", "Symlink",
847			    "Mkdir");
848		printf("%12ju %12ju %12ju %12ju %12ju %12ju\n",
849		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_CREATE],
850		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_REMOVE],
851		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_RENAME],
852		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LINK],
853		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SYMLINK],
854		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_MKDIR]);
855		if (printtitle)
856			printf(
857			    "%12.12s %12.12s %12.12s %12.12s %12.12s %12.12s\n",
858			    "Rmdir", "Readdir", "RdirPlus", "Access", "Mknod",
859			    "Fsstat");
860		printf("%12ju %12ju %12ju %12ju %12ju %12ju\n",
861		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_RMDIR],
862		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READDIR],
863		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READDIRPLUS],
864		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_ACCESS],
865		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_MKNOD],
866		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_FSSTAT]);
867		if (printtitle)
868			printf(
869			    "%12.12s %12.12s %12.12s %12.12s %12.12s %12.12s\n",
870			    "Fsinfo", "PathConf", "Commit", "SetClId",
871			    "SetClIdCf", "Lock");
872		printf("%12ju %12ju %12ju %12ju %12ju %12ju\n",
873		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_FSINFO],
874		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_PATHCONF],
875		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_COMMIT],
876		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SETCLIENTID],
877		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SETCLIENTIDCFRM],
878		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LOCK]);
879		if (printtitle)
880			printf(
881			    "%12.12s %12.12s %12.12s %12.12s %12.12s %12.12s\n",
882			    "LockT", "LockU", "Open", "OpenCfr", "OpenDownGr",
883			    "Close");
884		printf("%12ju %12ju %12ju %12ju %12ju %12ju\n",
885		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LOCKT],
886		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LOCKU],
887		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_OPEN],
888		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_OPENCONFIRM],
889		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_OPENDOWNGRADE],
890		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_CLOSE]);
891		if (printtitle)
892			printf(
893			    "%12.12s %12.12s %12.12s %12.12s %12.12s %12.12s\n",
894			    "RelLckOwn", "FreeStateID", "PutRootFH", "DelegRet",
895			    "GetACL", "SetACL");
896		printf("%12ju %12ju %12ju %12ju %12ju %12ju\n",
897		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_RELEASELCKOWN],
898		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_FREESTATEID],
899		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_PUTROOTFH],
900		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_DELEGRETURN],
901		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_GETACL],
902		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SETACL]);
903		if (printtitle)
904			printf(
905			    "%12.12s %12.12s %12.12s %12.12s %12.12s %12.12s\n",
906			    "ExchangeID", "CreateSess", "DestroySess",
907			    "DestroyClId", "LayoutGet", "GetDevInfo");
908		printf("%12ju %12ju %12ju %12ju %12ju %12ju\n",
909		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_EXCHANGEID],
910		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_CREATESESSION],
911		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_DESTROYSESSION],
912		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_DESTROYCLIENT],
913		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LAYOUTGET],
914		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_GETDEVICEINFO]);
915		if (printtitle)
916			printf(
917			    "%12.12s %12.12s %12.12s %12.12s %12.12s %12.12s\n",
918			    "LayoutCommit", "LayoutReturn", "ReclaimCompl",
919			    "ReadDataS", "WriteDataS", "CommitDataS");
920		printf("%12ju %12ju %12ju %12ju %12ju %12ju\n",
921		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LAYOUTCOMMIT],
922		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LAYOUTRETURN],
923		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_RECLAIMCOMPL],
924		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READDS],
925		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_WRITEDS],
926		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_COMMITDS]);
927		if (printtitle)
928			printf(
929			    "%12.12s %12.12s\n",
930			    "OpenLayout", "CreateLayout");
931		printf("%12ju %12ju\n",
932		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_OPENLAYGET],
933		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_CREATELAYGET]);
934		if (printtitle)
935			printf(
936			    "%12.12s %12.12s %12.12s %12.12s %12.12s %12.12s\n",
937			    "OpenOwner", "Opens", "LockOwner", "Locks",
938			    "Delegs", "LocalOwn");
939		printf("%12ju %12ju %12ju %12ju %12ju %12ju\n",
940		    (uintmax_t)ext_nfsstats.clopenowners,
941		    (uintmax_t)ext_nfsstats.clopens,
942		    (uintmax_t)ext_nfsstats.cllockowners,
943		    (uintmax_t)ext_nfsstats.cllocks,
944		    (uintmax_t)ext_nfsstats.cldelegates,
945		    (uintmax_t)ext_nfsstats.cllocalopenowners);
946		if (printtitle)
947			printf("%12.12s %12.12s %12.12s\n",
948			    "LocalOpen", "LocalLOwn", "LocalLock");
949		printf("%12ju %12ju %12ju\n",
950		    (uintmax_t)ext_nfsstats.cllocalopens,
951		    (uintmax_t)ext_nfsstats.cllocallockowners,
952		    (uintmax_t)ext_nfsstats.cllocallocks);
953		if (printtitle) {
954			printf("Rpc Info:\n");
955			printf("%12.12s %12.12s %12.12s %12.12s %12.12s\n",
956			    "TimedOut", "Invalid", "X Replies", "Retries",
957			    "Requests");
958		}
959		printf("%12ju %12ju %12ju %12ju %12ju\n",
960		    (uintmax_t)ext_nfsstats.rpctimeouts,
961		    (uintmax_t)ext_nfsstats.rpcinvalid,
962		    (uintmax_t)ext_nfsstats.rpcunexpected,
963		    (uintmax_t)ext_nfsstats.rpcretries,
964		    (uintmax_t)ext_nfsstats.rpcrequests);
965		if (printtitle) {
966			printf("Cache Info:\n");
967			printf("%12.12s %12.12s %12.12s %12.12s\n",
968			    "Attr Hits", "Misses", "Lkup Hits", "Misses");
969		}
970		printf("%12ju %12ju %12ju %12ju\n",
971		    (uintmax_t)ext_nfsstats.attrcache_hits,
972		    (uintmax_t)ext_nfsstats.attrcache_misses,
973		    (uintmax_t)ext_nfsstats.lookupcache_hits,
974		    (uintmax_t)ext_nfsstats.lookupcache_misses);
975		if (printtitle)
976			printf("%12.12s %12.12s %12.12s %12.12s\n",
977			    "BioR Hits", "Misses", "BioW Hits", "Misses");
978		printf("%12ju %12ju %12ju %12ju\n",
979		    (uintmax_t)(ext_nfsstats.biocache_reads -
980		    ext_nfsstats.read_bios),
981		    (uintmax_t)ext_nfsstats.read_bios,
982		    (uintmax_t)(ext_nfsstats.biocache_writes -
983		    ext_nfsstats.write_bios),
984		    (uintmax_t)ext_nfsstats.write_bios);
985		if (printtitle)
986			printf("%12.12s %12.12s %12.12s %12.12s\n",
987			    "BioRLHits", "Misses", "BioD Hits", "Misses");
988		printf("%12ju %12ju %12ju %12ju\n",
989		    (uintmax_t)(ext_nfsstats.biocache_readlinks -
990		    ext_nfsstats.readlink_bios),
991		    (uintmax_t)ext_nfsstats.readlink_bios,
992		    (uintmax_t)(ext_nfsstats.biocache_readdirs -
993		    ext_nfsstats.readdir_bios),
994		    (uintmax_t)ext_nfsstats.readdir_bios);
995		if (printtitle)
996			printf("%12.12s %12.12s\n", "DirE Hits", "Misses");
997		printf("%12ju %12ju\n",
998		    (uintmax_t)ext_nfsstats.direofcache_hits,
999		    (uintmax_t)ext_nfsstats.direofcache_misses);
1000	}
1001	if (serverOnly != 0) {
1002		if (printtitle) {
1003			printf("\nServer Info:\n");
1004			printf(
1005			    "%12.12s %12.12s %12.12s %12.12s %12.12s %12.12s\n",
1006			    "Getattr", "Setattr", "Lookup", "Readlink",
1007			    "Read", "Write");
1008		}
1009		printf("%12ju %12ju %12ju %12ju %12ju %12ju\n",
1010		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_GETATTR],
1011		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SETATTR],
1012		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LOOKUP],
1013		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READLINK],
1014		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READ],
1015		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_WRITE]);
1016		if (printtitle)
1017			printf(
1018			    "%12.12s %12.12s %12.12s %12.12s %12.12s %12.12s\n",
1019			    "Create", "Remove", "Rename", "Link", "Symlink",
1020			    "Mkdir");
1021		printf("%12ju %12ju %12ju %12ju %12ju %12ju\n",
1022		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_V3CREATE],
1023		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_REMOVE],
1024		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RENAME],
1025		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LINK],
1026		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SYMLINK],
1027		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_MKDIR]);
1028		if (printtitle)
1029			printf(
1030			    "%12.12s %12.12s %12.12s %12.12s %12.12s %12.12s\n",
1031			    "Rmdir", "Readdir", "RdirPlus", "Access", "Mknod",
1032			    "Fsstat");
1033		printf("%12ju %12ju %12ju %12ju %12ju %12ju\n",
1034		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RMDIR],
1035		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READDIR],
1036		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READDIRPLUS],
1037		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_ACCESS],
1038		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_MKNOD],
1039		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_FSSTAT]);
1040		if (printtitle)
1041			printf(
1042			    "%12.12s %12.12s %12.12s %12.12s %12.12s %12.12s\n",
1043			    "Fsinfo", "PathConf", "Commit", "LookupP",
1044			    "SetClId", "SetClIdCf");
1045		printf("%12ju %12ju %12ju %12ju %12ju %12ju\n",
1046		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_FSINFO],
1047		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_PATHCONF],
1048		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_COMMIT],
1049		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LOOKUPP],
1050		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SETCLIENTID],
1051		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SETCLIENTIDCFRM]);
1052		if (printtitle)
1053			printf(
1054			    "%12.12s %12.12s %12.12s %12.12s %12.12s %12.12s\n",
1055			    "Open", "OpenAttr", "OpenDwnGr", "OpenCfrm",
1056			    "DelePurge", "DeleRet");
1057		printf("%12ju %12ju %12ju %12ju %12ju %12ju\n",
1058		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_OPEN],
1059		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_OPENATTR],
1060		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_OPENDOWNGRADE],
1061		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_OPENCONFIRM],
1062		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_DELEGPURGE],
1063		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_DELEGRETURN]);
1064		if (printtitle)
1065			printf(
1066			    "%12.12s %12.12s %12.12s %12.12s %12.12s %12.12s\n",
1067			    "GetFH", "Lock", "LockT", "LockU", "Close",
1068			    "Verify");
1069		printf("%12ju %12ju %12ju %12ju %12ju %12ju\n",
1070		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_GETFH],
1071		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LOCK],
1072		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LOCKT],
1073		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LOCKU],
1074		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_CLOSE],
1075		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_VERIFY]);
1076		if (printtitle)
1077			printf(
1078			    "%12.12s %12.12s %12.12s %12.12s %12.12s %12.12s\n",
1079			    "NVerify", "PutFH", "PutPubFH", "PutRootFH",
1080			    "Renew", "RestoreFH");
1081		printf("%12ju %12ju %12ju %12ju %12ju %12ju\n",
1082		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_NVERIFY],
1083		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_PUTFH],
1084		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_PUTPUBFH],
1085		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_PUTROOTFH],
1086		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RENEW],
1087		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RESTOREFH]);
1088		if (printtitle)
1089			printf(
1090			    "%12.12s %12.12s %12.12s %12.12s %12.12s %12.12s\n",
1091			    "SaveFH", "Secinfo", "RelLckOwn", "V4Create",
1092			    "BackChannelCtrl", "BindConnToSess");
1093		printf("%12ju %12ju %12ju %12ju %12ju %12ju\n",
1094		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SAVEFH],
1095		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SECINFO],
1096		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RELEASELCKOWN],
1097		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_CREATE],
1098		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_BACKCHANNELCTL],
1099		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_BINDCONNTOSESS]);
1100		if (printtitle)
1101			printf(
1102			    "%12.12s %12.12s %12.12s %12.12s %12.12s %12.12s\n",
1103			    "ExchangeID", "CreateSess", "DestroySess",
1104			    "FreeStateID", "GetDirDeleg", "GetDevInfo");
1105		printf("%12ju %12ju %12ju %12ju %12ju %12ju\n",
1106		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_EXCHANGEID],
1107		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_CREATESESSION],
1108		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_DESTROYSESSION],
1109		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_FREESTATEID],
1110		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_GETDIRDELEG],
1111		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_GETDEVINFO]);
1112		if (printtitle)
1113			printf(
1114			    "%12.12s %12.12s %12.12s %12.12s %12.12s %12.12s\n",
1115			    "GetDevList", "LayoutCommit", "LayoutGet",
1116			    "LayoutReturn", "SecInfNoName", "Sequence");
1117		printf("%12ju %12ju %12ju %12ju %12ju %12ju\n",
1118		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_GETDEVLIST],
1119		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LAYOUTCOMMIT],
1120		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LAYOUTGET],
1121		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LAYOUTRETURN],
1122		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SECINFONONAME],
1123		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SEQUENCE]);
1124		if (printtitle)
1125			printf(
1126			    "%12.12s %12.12s %12.12s %12.12s %12.12s\n",
1127			    "SetSSV", "TestStateID", "WantDeleg",
1128			    "DestroyClID", "ReclaimCompl");
1129		printf("%12ju %12ju %12ju %12ju %12ju\n",
1130		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SETSSV],
1131		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_TESTSTATEID],
1132		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_WANTDELEG],
1133		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_DESTROYCLIENTID],
1134		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RECLAIMCOMPL]);
1135		if (printtitle) {
1136			printf("Server:\n");
1137			printf("%12.12s %12.12s %12.12s\n",
1138			    "Retfailed", "Faults", "Clients");
1139		}
1140		printf("%12ju %12ju %12ju\n",
1141		    (uintmax_t)ext_nfsstats.srv_errs,
1142		    (uintmax_t)ext_nfsstats.srvrpc_errs,
1143		    (uintmax_t)ext_nfsstats.srvclients);
1144		if (printtitle)
1145			printf("%12.12s %12.12s %12.12s %12.12s %12.12s\n",
1146			    "OpenOwner", "Opens", "LockOwner",
1147			    "Locks", "Delegs");
1148		printf("%12ju %12ju %12ju %12ju %12ju\n",
1149		    (uintmax_t)ext_nfsstats.srvopenowners,
1150		    (uintmax_t)ext_nfsstats.srvopens,
1151		    (uintmax_t)ext_nfsstats.srvlockowners,
1152		    (uintmax_t)ext_nfsstats.srvlocks,
1153		    (uintmax_t)ext_nfsstats.srvdelegates);
1154		if (printtitle) {
1155			printf("Server Cache Stats:\n");
1156			printf(
1157			    "%12.12s %12.12s %12.12s %12.12s %12.12s %12.12s\n",
1158			    "Inprog", "Idem", "Non-idem", "Misses",
1159			    "CacheSize", "TCPPeak");
1160		}
1161		printf("%12ju %12ju %12ju %12ju %12ju %12ju\n",
1162		    (uintmax_t)ext_nfsstats.srvcache_inproghits,
1163		    (uintmax_t)ext_nfsstats.srvcache_idemdonehits,
1164		    (uintmax_t)ext_nfsstats.srvcache_nonidemdonehits,
1165		    (uintmax_t)ext_nfsstats.srvcache_misses,
1166		    (uintmax_t)ext_nfsstats.srvcache_size,
1167		    (uintmax_t)ext_nfsstats.srvcache_tcppeak);
1168	}
1169}
1170
1171static void
1172compute_totals(struct nfsstatsv1 *total_stats, struct nfsstatsv1 *cur_stats)
1173{
1174	int i;
1175
1176	bzero(total_stats, sizeof(*total_stats));
1177	for (i = 0; i < (NFSV42_NOPS + NFSV4OP_FAKENOPS); i++) {
1178		total_stats->srvbytes[0] += cur_stats->srvbytes[i];
1179		total_stats->srvops[0] += cur_stats->srvops[i];
1180		bintime_add(&total_stats->srvduration[0],
1181			    &cur_stats->srvduration[i]);
1182		total_stats->srvrpccnt[i] = cur_stats->srvrpccnt[i];
1183	}
1184	total_stats->srvstartcnt = cur_stats->srvstartcnt;
1185	total_stats->srvdonecnt = cur_stats->srvdonecnt;
1186	total_stats->busytime = cur_stats->busytime;
1187
1188}
1189
1190/*
1191 * Print a running summary of nfs statistics for the experimental client and/or
1192 * server.
1193 * Repeat display every interval seconds, showing statistics
1194 * collected over that interval.  Assumes that interval is non-zero.
1195 * First line printed at top of screen is always cumulative.
1196 */
1197static void
1198exp_sidewaysintpr(u_int interval, int clientOnly, int serverOnly,
1199    int newStats)
1200{
1201	struct nfsstatsv1 nfsstats, lastst, *ext_nfsstatsp;
1202	struct nfsstatsv1 curtotal, lasttotal;
1203	struct timespec ts, lastts;
1204	int hdrcnt = 1;
1205
1206	ext_nfsstatsp = &lastst;
1207	ext_nfsstatsp->vers = NFSSTATS_V1;
1208	if (nfssvc(NFSSVC_GETSTATS | NFSSVC_NEWSTRUCT, ext_nfsstatsp) < 0)
1209		err(1, "Can't get stats");
1210	clock_gettime(CLOCK_MONOTONIC, &lastts);
1211	compute_totals(&lasttotal, ext_nfsstatsp);
1212	sleep(interval);
1213
1214	for (;;) {
1215		ext_nfsstatsp = &nfsstats;
1216		ext_nfsstatsp->vers = NFSSTATS_V1;
1217		if (nfssvc(NFSSVC_GETSTATS | NFSSVC_NEWSTRUCT, ext_nfsstatsp)
1218		    < 0)
1219			err(1, "Can't get stats");
1220		clock_gettime(CLOCK_MONOTONIC, &ts);
1221
1222		if (--hdrcnt == 0) {
1223			printhdr(clientOnly, serverOnly, newStats);
1224			if (newStats)
1225				hdrcnt = 20;
1226			else if (clientOnly && serverOnly)
1227				hdrcnt = 10;
1228			else
1229				hdrcnt = 20;
1230		}
1231		if (clientOnly && newStats == 0) {
1232		    printf("%s %6ju %6ju %6ju %6ju %6ju %6ju %6ju %6ju",
1233			((clientOnly && serverOnly) ? "Client:" : ""),
1234			(uintmax_t)DELTA(rpccnt[NFSPROC_GETATTR]),
1235			(uintmax_t)DELTA(rpccnt[NFSPROC_LOOKUP]),
1236			(uintmax_t)DELTA(rpccnt[NFSPROC_READLINK]),
1237			(uintmax_t)DELTA(rpccnt[NFSPROC_READ]),
1238			(uintmax_t)DELTA(rpccnt[NFSPROC_WRITE]),
1239			(uintmax_t)DELTA(rpccnt[NFSPROC_RENAME]),
1240			(uintmax_t)DELTA(rpccnt[NFSPROC_ACCESS]),
1241			(uintmax_t)(DELTA(rpccnt[NFSPROC_READDIR]) +
1242			DELTA(rpccnt[NFSPROC_READDIRPLUS]))
1243		    );
1244		    if (widemode) {
1245			    printf(" %s %s %s %s %s %s",
1246				sperc1(DELTA(attrcache_hits),
1247				    DELTA(attrcache_misses)),
1248				sperc1(DELTA(lookupcache_hits),
1249				    DELTA(lookupcache_misses)),
1250				sperc2(DELTA(biocache_reads),
1251				    DELTA(read_bios)),
1252				sperc2(DELTA(biocache_writes),
1253				    DELTA(write_bios)),
1254				sperc1(DELTA(accesscache_hits),
1255				    DELTA(accesscache_misses)),
1256				sperc2(DELTA(biocache_readdirs),
1257				    DELTA(readdir_bios))
1258			    );
1259		    }
1260		    printf("\n");
1261		}
1262
1263		if (serverOnly && newStats) {
1264			long double cur_secs, last_secs, etime;
1265			long double mbsec;
1266			long double kb_per_transfer;
1267			long double transfers_per_second;
1268			long double ms_per_transfer;
1269			uint64_t queue_len;
1270			long double busy_pct;
1271			int i;
1272
1273			cur_secs = ts.tv_sec +
1274			    ((long double)ts.tv_nsec / 1000000000);
1275			last_secs = lastts.tv_sec +
1276			    ((long double)lastts.tv_nsec / 1000000000);
1277			etime = cur_secs - last_secs;
1278
1279			compute_totals(&curtotal, &nfsstats);
1280
1281			for (i = 0; i < NUM_STAT_TYPES; i++) {
1282				compute_new_stats(&nfsstats, &lastst,
1283				    STAT_TYPE_TO_NFS(i), etime, &mbsec,
1284				    &kb_per_transfer,
1285				    &transfers_per_second,
1286				    &ms_per_transfer, &queue_len,
1287				    &busy_pct);
1288
1289				if (i == STAT_TYPE_COMMIT) {
1290					if (widemode == 0)
1291						continue;
1292
1293					printf("%2.0Lf %7.2Lf ",
1294					    transfers_per_second,
1295					    ms_per_transfer);
1296				} else {
1297					printf("%5.2Lf %5.0Lf %7.2Lf ",
1298					    kb_per_transfer,
1299					    transfers_per_second, mbsec);
1300					if (widemode)
1301						printf("%5.2Lf ",
1302						    ms_per_transfer);
1303				}
1304			}
1305
1306			compute_new_stats(&curtotal, &lasttotal, 0, etime,
1307			    &mbsec, &kb_per_transfer, &transfers_per_second,
1308			    &ms_per_transfer, &queue_len, &busy_pct);
1309
1310			printf("%5.2Lf %5.0Lf %7.2Lf %5.2Lf %3ju %3.0Lf\n",
1311			    kb_per_transfer, transfers_per_second, mbsec,
1312			    ms_per_transfer, queue_len, busy_pct);
1313		} else if (serverOnly) {
1314		    printf("%s %6ju %6ju %6ju %6ju %6ju %6ju %6ju %6ju",
1315			((clientOnly && serverOnly) ? "Server:" : ""),
1316			(uintmax_t)DELTA(srvrpccnt[NFSV4OP_GETATTR]),
1317			(uintmax_t)DELTA(srvrpccnt[NFSV4OP_LOOKUP]),
1318			(uintmax_t)DELTA(srvrpccnt[NFSV4OP_READLINK]),
1319			(uintmax_t)DELTA(srvrpccnt[NFSV4OP_READ]),
1320			(uintmax_t)DELTA(srvrpccnt[NFSV4OP_WRITE]),
1321			(uintmax_t)DELTA(srvrpccnt[NFSV4OP_RENAME]),
1322			(uintmax_t)DELTA(srvrpccnt[NFSV4OP_ACCESS]),
1323			(uintmax_t)(DELTA(srvrpccnt[NFSV4OP_READDIR]) +
1324			DELTA(srvrpccnt[NFSV4OP_READDIRPLUS])));
1325		    printf("\n");
1326		}
1327		bcopy(&nfsstats, &lastst, sizeof(lastst));
1328		bcopy(&curtotal, &lasttotal, sizeof(lasttotal));
1329		lastts = ts;
1330		fflush(stdout);
1331		sleep(interval);
1332	}
1333	/*NOTREACHED*/
1334}
1335