Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 13 Aug 2016 20:14:45 +0000 (UTC)
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r304058 - head/usr.bin/nfsstat
Message-ID:  <201608132014.u7DKEjuk036979@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rmacklem
Date: Sat Aug 13 20:14:44 2016
New Revision: 304058
URL: https://svnweb.freebsd.org/changeset/base/304058

Log:
  Update nfsstat.c to use the new kernel nfsstat structure and
  add the new "-d" flag from D1626.
  The man page will be updated in a subsequent commit.
  
  Submitted by:	will (earlier version)
  Reviewed by:	ken
  MFC after:	1 month
  Relnotes:	yes
  Differential Revision:	https://reviews.freebsd.org/D1626

Modified:
  head/usr.bin/nfsstat/nfsstat.c

Modified: head/usr.bin/nfsstat/nfsstat.c
==============================================================================
--- head/usr.bin/nfsstat/nfsstat.c	Sat Aug 13 19:57:36 2016	(r304057)
+++ head/usr.bin/nfsstat/nfsstat.c	Sat Aug 13 20:14:44 2016	(r304058)
@@ -29,6 +29,36 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
+/*-
+ * Copyright (c) 2004, 2008, 2009 Silicon Graphics International Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
 
 #ifndef lint
 static const char copyright[] =
@@ -64,33 +94,57 @@ static const char rcsid[] =
 #include <nlist.h>
 #include <unistd.h>
 #include <stdio.h>
+#include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
 #include <paths.h>
+#include <devstat.h>
 #include <err.h>
 
 static int widemode = 0;
 static int zflag = 0;
 static int printtitle = 1;
-static struct ext_nfsstats ext_nfsstats;
+static struct nfsstatsv1 ext_nfsstats;
 static int extra_output = 0;
 
 static void intpr(int, int);
-static void printhdr(int, int);
+static void printhdr(int, int, int);
 static void usage(void);
 static char *sperc1(int, int);
 static char *sperc2(int, int);
 static void exp_intpr(int, int);
-static void exp_sidewaysintpr(u_int, int, int);
+static void exp_sidewaysintpr(u_int, int, int, int);
+static void compute_new_stats(struct nfsstatsv1 *cur_stats,
+    struct nfsstatsv1 *prev_stats, int curop, long double etime,
+    long double *mbsec, long double *kb_per_transfer,
+    long double *transfers_per_second, long double *ms_per_transfer,
+    uint64_t *queue_len, long double *busy_pct);
 
 #define DELTA(field)	(nfsstats.field - lastst.field)
 
+#define	STAT_TYPE_READ		0
+#define	STAT_TYPE_WRITE		1
+#define	STAT_TYPE_COMMIT	2
+#define	NUM_STAT_TYPES		3
+
+struct stattypes {
+	int stat_type;
+	int nfs_type;
+} static statstruct[] = {
+	{STAT_TYPE_READ, NFSV4OP_READ},
+	{STAT_TYPE_WRITE, NFSV4OP_WRITE},
+	{STAT_TYPE_COMMIT, NFSV4OP_COMMIT}
+};
+
+#define	STAT_TYPE_TO_NFS(stat_type)	statstruct[stat_type].nfs_type
+
 int
 main(int argc, char **argv)
 {
 	u_int interval;
 	int clientOnly = -1;
 	int serverOnly = -1;
+	int newStats = 0;
 	int ch;
 	char *memf, *nlistf;
 	int mntlen, i;
@@ -100,7 +154,7 @@ main(int argc, char **argv)
 
 	interval = 0;
 	memf = nlistf = NULL;
-	while ((ch = getopt(argc, argv, "cesWM:mN:w:z")) != -1)
+	while ((ch = getopt(argc, argv, "cdesWM:mN:w:z")) != -1)
 		switch(ch) {
 		case 'M':
 			memf = optarg;
@@ -140,6 +194,11 @@ main(int argc, char **argv)
 			if (serverOnly < 0)
 				serverOnly = 0;
 			break;
+		case 'd':
+			newStats = 1;
+			if (interval == 0)
+				interval = 1;
+			break;
 		case 's':
 			serverOnly = 1;
 			if (clientOnly < 0)
@@ -173,7 +232,8 @@ main(int argc, char **argv)
 		errx(1, "NFS client/server not loaded");
 
 	if (interval) {
-		exp_sidewaysintpr(interval, clientOnly, serverOnly);
+		exp_sidewaysintpr(interval, clientOnly, serverOnly,
+		    newStats);
 	} else {
 		if (extra_output != 0)
 			exp_intpr(clientOnly, serverOnly);
@@ -191,13 +251,14 @@ intpr(int clientOnly, int serverOnly)
 {
 	int nfssvc_flag;
 
-	nfssvc_flag = NFSSVC_GETSTATS;
+	nfssvc_flag = NFSSVC_GETSTATS | NFSSVC_NEWSTRUCT;
 	if (zflag != 0) {
 		if (clientOnly != 0)
 			nfssvc_flag |= NFSSVC_ZEROCLTSTATS;
 		if (serverOnly != 0)
 			nfssvc_flag |= NFSSVC_ZEROSRVSTATS;
 	}
+	ext_nfsstats.vers = NFSSTATS_V1;
 	if (nfssvc(nfssvc_flag, &ext_nfsstats) < 0)
 		err(1, "Can't get stats");
 	if (clientOnly) {
@@ -206,124 +267,124 @@ intpr(int clientOnly, int serverOnly)
 		printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
 			"Getattr", "Setattr", "Lookup", "Readlink", "Read",
 			"Write", "Create", "Remove");
-		printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
-			ext_nfsstats.rpccnt[NFSPROC_GETATTR],
-			ext_nfsstats.rpccnt[NFSPROC_SETATTR],
-			ext_nfsstats.rpccnt[NFSPROC_LOOKUP],
-			ext_nfsstats.rpccnt[NFSPROC_READLINK],
-			ext_nfsstats.rpccnt[NFSPROC_READ],
-			ext_nfsstats.rpccnt[NFSPROC_WRITE],
-			ext_nfsstats.rpccnt[NFSPROC_CREATE],
-			ext_nfsstats.rpccnt[NFSPROC_REMOVE]);
+		printf("%9ju %9ju %9ju %9ju %9ju %9ju %9ju %9ju\n",
+			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_GETATTR],
+			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SETATTR],
+			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LOOKUP],
+			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READLINK],
+			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READ],
+			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_WRITE],
+			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_CREATE],
+			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_REMOVE]);
 		printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
 			"Rename", "Link", "Symlink", "Mkdir", "Rmdir",
 			"Readdir", "RdirPlus", "Access");
-		printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
-			ext_nfsstats.rpccnt[NFSPROC_RENAME],
-			ext_nfsstats.rpccnt[NFSPROC_LINK],
-			ext_nfsstats.rpccnt[NFSPROC_SYMLINK],
-			ext_nfsstats.rpccnt[NFSPROC_MKDIR],
-			ext_nfsstats.rpccnt[NFSPROC_RMDIR],
-			ext_nfsstats.rpccnt[NFSPROC_READDIR],
-			ext_nfsstats.rpccnt[NFSPROC_READDIRPLUS],
-			ext_nfsstats.rpccnt[NFSPROC_ACCESS]);
+		printf("%9ju %9ju %9ju %9ju %9ju %9ju %9ju %9ju\n",
+			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_RENAME],
+			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LINK],
+			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SYMLINK],
+			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_MKDIR],
+			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_RMDIR],
+			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READDIR],
+			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READDIRPLUS],
+			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_ACCESS]);
 		printf("%9.9s %9.9s %9.9s %9.9s %9.9s\n",
 			"Mknod", "Fsstat", "Fsinfo", "PathConf", "Commit");
-		printf("%9d %9d %9d %9d %9d\n",
-			ext_nfsstats.rpccnt[NFSPROC_MKNOD],
-			ext_nfsstats.rpccnt[NFSPROC_FSSTAT],
-			ext_nfsstats.rpccnt[NFSPROC_FSINFO],
-			ext_nfsstats.rpccnt[NFSPROC_PATHCONF],
-			ext_nfsstats.rpccnt[NFSPROC_COMMIT]);
+		printf("%9ju %9ju %9ju %9ju %9ju\n",
+			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_MKNOD],
+			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_FSSTAT],
+			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_FSINFO],
+			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_PATHCONF],
+			(uintmax_t)ext_nfsstats.rpccnt[NFSPROC_COMMIT]);
 		printf("Rpc Info:\n");
 		printf("%9.9s %9.9s %9.9s %9.9s %9.9s\n",
 			"TimedOut", "Invalid", "X Replies", "Retries", 
 			"Requests");
-		printf("%9d %9d %9d %9d %9d\n",
-			ext_nfsstats.rpctimeouts,
-			ext_nfsstats.rpcinvalid,
-			ext_nfsstats.rpcunexpected,
-			ext_nfsstats.rpcretries,
-			ext_nfsstats.rpcrequests);
+		printf("%9ju %9ju %9ju %9ju %9ju\n",
+			(uintmax_t)ext_nfsstats.rpctimeouts,
+			(uintmax_t)ext_nfsstats.rpcinvalid,
+			(uintmax_t)ext_nfsstats.rpcunexpected,
+			(uintmax_t)ext_nfsstats.rpcretries,
+			(uintmax_t)ext_nfsstats.rpcrequests);
 		printf("Cache Info:\n");
 		printf("%9.9s %9.9s %9.9s %9.9s",
 			"Attr Hits", "Misses", "Lkup Hits", "Misses");
 		printf(" %9.9s %9.9s %9.9s %9.9s\n",
 			"BioR Hits", "Misses", "BioW Hits", "Misses");
-		printf("%9d %9d %9d %9d",
-			ext_nfsstats.attrcache_hits,
-			ext_nfsstats.attrcache_misses,
-			ext_nfsstats.lookupcache_hits,
-			ext_nfsstats.lookupcache_misses);
-		printf(" %9d %9d %9d %9d\n",
-			ext_nfsstats.biocache_reads -
-			ext_nfsstats.read_bios,
-			ext_nfsstats.read_bios,
-			ext_nfsstats.biocache_writes -
-			ext_nfsstats.write_bios,
-			ext_nfsstats.write_bios);
+		printf("%9ju %9ju %9ju %9ju",
+			(uintmax_t)ext_nfsstats.attrcache_hits,
+			(uintmax_t)ext_nfsstats.attrcache_misses,
+			(uintmax_t)ext_nfsstats.lookupcache_hits,
+			(uintmax_t)ext_nfsstats.lookupcache_misses);
+		printf(" %9ju %9ju %9ju %9ju\n",
+			(uintmax_t)(ext_nfsstats.biocache_reads -
+			ext_nfsstats.read_bios),
+			(uintmax_t)ext_nfsstats.read_bios,
+			(uintmax_t)(ext_nfsstats.biocache_writes -
+			ext_nfsstats.write_bios),
+			(uintmax_t)ext_nfsstats.write_bios);
 		printf("%9.9s %9.9s %9.9s %9.9s",
 			"BioRLHits", "Misses", "BioD Hits", "Misses");
 		printf(" %9.9s %9.9s %9.9s %9.9s\n", "DirE Hits", "Misses", "Accs Hits", "Misses");
-		printf("%9d %9d %9d %9d",
-			ext_nfsstats.biocache_readlinks -
-			ext_nfsstats.readlink_bios,
-			ext_nfsstats.readlink_bios,
-			ext_nfsstats.biocache_readdirs -
-			ext_nfsstats.readdir_bios,
-			ext_nfsstats.readdir_bios);
-		printf(" %9d %9d %9d %9d\n",
-			ext_nfsstats.direofcache_hits,
-			ext_nfsstats.direofcache_misses,
-			ext_nfsstats.accesscache_hits,
-			ext_nfsstats.accesscache_misses);
+		printf("%9ju %9ju %9ju %9ju",
+			(uintmax_t)(ext_nfsstats.biocache_readlinks -
+			ext_nfsstats.readlink_bios),
+			(uintmax_t)ext_nfsstats.readlink_bios,
+			(uintmax_t)(ext_nfsstats.biocache_readdirs -
+			ext_nfsstats.readdir_bios),
+			(uintmax_t)ext_nfsstats.readdir_bios);
+		printf(" %9ju %9ju %9ju %9ju\n",
+			(uintmax_t)ext_nfsstats.direofcache_hits,
+			(uintmax_t)ext_nfsstats.direofcache_misses,
+			(uintmax_t)ext_nfsstats.accesscache_hits,
+			(uintmax_t)ext_nfsstats.accesscache_misses);
 	}
 	if (serverOnly) {
 		printf("\nServer Info:\n");
 		printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
 			"Getattr", "Setattr", "Lookup", "Readlink", "Read",
 			"Write", "Create", "Remove");
-		printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
-			ext_nfsstats.srvrpccnt[NFSV4OP_GETATTR],
-			ext_nfsstats.srvrpccnt[NFSV4OP_SETATTR],
-			ext_nfsstats.srvrpccnt[NFSV4OP_LOOKUP],
-			ext_nfsstats.srvrpccnt[NFSV4OP_READLINK],
-			ext_nfsstats.srvrpccnt[NFSV4OP_READ],
-			ext_nfsstats.srvrpccnt[NFSV4OP_WRITE],
-			ext_nfsstats.srvrpccnt[NFSV4OP_CREATE],
-			ext_nfsstats.srvrpccnt[NFSV4OP_REMOVE]);
+		printf("%9ju %9ju %9ju %9ju %9ju %9ju %9ju %9ju\n",
+			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_GETATTR],
+			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SETATTR],
+			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LOOKUP],
+			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READLINK],
+			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READ],
+			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_WRITE],
+			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_CREATE],
+			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_REMOVE]);
 		printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
 			"Rename", "Link", "Symlink", "Mkdir", "Rmdir",
 			"Readdir", "RdirPlus", "Access");
-		printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
-			ext_nfsstats.srvrpccnt[NFSV4OP_RENAME],
-			ext_nfsstats.srvrpccnt[NFSV4OP_LINK],
-			ext_nfsstats.srvrpccnt[NFSV4OP_SYMLINK],
-			ext_nfsstats.srvrpccnt[NFSV4OP_MKDIR],
-			ext_nfsstats.srvrpccnt[NFSV4OP_RMDIR],
-			ext_nfsstats.srvrpccnt[NFSV4OP_READDIR],
-			ext_nfsstats.srvrpccnt[NFSV4OP_READDIRPLUS],
-			ext_nfsstats.srvrpccnt[NFSV4OP_ACCESS]);
+		printf("%9ju %9ju %9ju %9ju %9ju %9ju %9ju %9ju\n",
+			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RENAME],
+			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LINK],
+			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SYMLINK],
+			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_MKDIR],
+			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RMDIR],
+			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READDIR],
+			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READDIRPLUS],
+			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_ACCESS]);
 		printf("%9.9s %9.9s %9.9s %9.9s %9.9s\n",
 			"Mknod", "Fsstat", "Fsinfo", "PathConf", "Commit");
-		printf("%9d %9d %9d %9d %9d\n",
-			ext_nfsstats.srvrpccnt[NFSV4OP_MKNOD],
-			ext_nfsstats.srvrpccnt[NFSV4OP_FSSTAT],
-			ext_nfsstats.srvrpccnt[NFSV4OP_FSINFO],
-			ext_nfsstats.srvrpccnt[NFSV4OP_PATHCONF],
-			ext_nfsstats.srvrpccnt[NFSV4OP_COMMIT]);
+		printf("%9ju %9ju %9ju %9ju %9ju\n",
+			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_MKNOD],
+			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_FSSTAT],
+			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_FSINFO],
+			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_PATHCONF],
+			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_COMMIT]);
 		printf("Server Ret-Failed\n");
-		printf("%17d\n", ext_nfsstats.srvrpc_errs);
+		printf("%17ju\n", (uintmax_t)ext_nfsstats.srvrpc_errs);
 		printf("Server Faults\n");
-		printf("%13d\n", ext_nfsstats.srv_errs);
+		printf("%13ju\n", (uintmax_t)ext_nfsstats.srv_errs);
 		printf("Server Cache Stats:\n");
 		printf("%9.9s %9.9s %9.9s %9.9s\n",
 			"Inprog", "Idem", "Non-idem", "Misses");
-		printf("%9d %9d %9d %9d\n",
-			ext_nfsstats.srvcache_inproghits,
-			ext_nfsstats.srvcache_idemdonehits,
-			ext_nfsstats.srvcache_nonidemdonehits,
-			ext_nfsstats.srvcache_misses);
+		printf("%9ju %9ju %9ju %9ju\n",
+			(uintmax_t)ext_nfsstats.srvcache_inproghits,
+			(uintmax_t)ext_nfsstats.srvcache_idemdonehits,
+			(uintmax_t)ext_nfsstats.srvcache_nonidemdonehits,
+			(uintmax_t)ext_nfsstats.srvcache_misses);
 		printf("Server Write Gathering:\n");
 		printf("%9.9s %9.9s %9.9s\n",
 			"WriteOps", "WriteRPC", "Opsaved");
@@ -331,21 +392,37 @@ intpr(int clientOnly, int serverOnly)
 		 * The new client doesn't do write gathering. It was
 		 * only useful for NFSv2.
 		 */
-		printf("%9d %9d %9d\n",
-			ext_nfsstats.srvrpccnt[NFSV4OP_WRITE],
-			ext_nfsstats.srvrpccnt[NFSV4OP_WRITE], 0);
+		printf("%9ju %9ju %9d\n",
+			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_WRITE],
+			(uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_WRITE], 0);
 	}
 }
 
 static void
-printhdr(int clientOnly, int serverOnly)
+printhdr(int clientOnly, int serverOnly, int newStats)
 {
-	printf("%s%6.6s %6.6s %6.6s %6.6s %6.6s %6.6s %6.6s %6.6s",
-	    ((serverOnly && clientOnly) ? "        " : " "),
-	    "GtAttr", "Lookup", "Rdlink", "Read", "Write", "Rename",
-	    "Access", "Rddir");
-	if (widemode && clientOnly) {
-		printf(" Attr Lkup BioR BioW Accs BioD");
+
+	if (newStats) {
+		printf(" [%s Read %s]  [%s Write %s]  "
+		    "%s[=========== Total ============]\n"
+		    " KB/t   tps    MB/s%s  KB/t   tps    MB/s%s  "
+		    "%sKB/t   tps    MB/s    ms  ql  %%b",
+		    widemode ? "========" : "=====",
+		    widemode ? "========" : "=====",
+		    widemode ? "========" : "=====",
+		    widemode ? "======="  : "====",
+		    widemode ? "[Commit ]  " : "",
+		    widemode ? "    ms" : "",
+		    widemode ? "    ms" : "",
+		    widemode ? "tps    ms  " : "");
+	} else {
+		printf("%s%6.6s %6.6s %6.6s %6.6s %6.6s %6.6s %6.6s %6.6s",
+		    ((serverOnly && clientOnly) ? "        " : " "),
+		    "GtAttr", "Lookup", "Rdlink", "Read", "Write", "Rename",
+		    "Access", "Rddir");
+		if (widemode && clientOnly) {
+			printf(" Attr Lkup BioR BioW Accs BioD");
+		}
 	}
 	printf("\n");
 	fflush(stdout);
@@ -355,7 +432,7 @@ static void
 usage(void)
 {
 	(void)fprintf(stderr,
-	    "usage: nfsstat [-cemszW] [-M core] [-N system] [-w wait]\n");
+	    "usage: nfsstat [-cdemszW] [-M core] [-N system] [-w wait]\n");
 	exit(1);
 }
 
@@ -392,6 +469,75 @@ sperc2(int ttl, int misses)
 	return(p);
 }
 
+#define DELTA_T(field)					\
+	devstat_compute_etime(&cur_stats->field,	\
+	(prev_stats ? &prev_stats->field : NULL))
+
+/*
+ * XXX KDM mostly copied from ctlstat.  We should commonize the code (and
+ * the devstat code) somehow.
+ */
+static void
+compute_new_stats(struct nfsstatsv1 *cur_stats,
+		  struct nfsstatsv1 *prev_stats, int curop,
+		  long double etime, long double *mbsec,
+		  long double *kb_per_transfer,
+		  long double *transfers_per_second,
+		  long double *ms_per_transfer, uint64_t *queue_len,
+		  long double *busy_pct)
+{
+	uint64_t total_bytes = 0, total_operations = 0;
+	struct bintime total_time_bt;
+	struct timespec total_time_ts;
+
+	bzero(&total_time_bt, sizeof(total_time_bt));
+	bzero(&total_time_ts, sizeof(total_time_ts));
+
+	total_bytes = cur_stats->srvbytes[curop];
+	total_operations = cur_stats->srvops[curop];
+	if (prev_stats != NULL) {
+		total_bytes -= prev_stats->srvbytes[curop];
+		total_operations -= prev_stats->srvops[curop];
+	}
+
+	*mbsec = total_bytes;
+	*mbsec /= 1024 * 1024;
+	if (etime > 0.0) {
+		*busy_pct = DELTA_T(busytime);
+		if (*busy_pct < 0)
+			*busy_pct = 0;
+		*busy_pct /= etime;
+		*busy_pct *= 100;
+		if (*busy_pct < 0)
+			*busy_pct = 0;
+		*mbsec /= etime;
+	} else {
+		*busy_pct = 0;
+		*mbsec = 0;
+	}
+	*kb_per_transfer = total_bytes;
+	*kb_per_transfer /= 1024;
+	if (total_operations > 0)
+		*kb_per_transfer /= total_operations;
+	else
+		*kb_per_transfer = 0;
+	if (etime > 0.0) {
+		*transfers_per_second = total_operations;
+		*transfers_per_second /= etime;
+	} else {
+		*transfers_per_second = 0.0;
+	}
+                        
+	if (total_operations > 0) {
+		*ms_per_transfer = DELTA_T(srvduration[curop]);
+		*ms_per_transfer /= total_operations;
+		*ms_per_transfer *= 1000;
+	} else
+		*ms_per_transfer = 0.0;
+
+	*queue_len = cur_stats->srvstartcnt - cur_stats->srvdonecnt;
+}
+
 /*
  * Print a description of the nfs stats for the experimental client/server.
  */
@@ -400,13 +546,14 @@ exp_intpr(int clientOnly, int serverOnly
 {
 	int nfssvc_flag;
 
-	nfssvc_flag = NFSSVC_GETSTATS;
+	nfssvc_flag = NFSSVC_GETSTATS | NFSSVC_NEWSTRUCT;
 	if (zflag != 0) {
 		if (clientOnly != 0)
 			nfssvc_flag |= NFSSVC_ZEROCLTSTATS;
 		if (serverOnly != 0)
 			nfssvc_flag |= NFSSVC_ZEROSRVSTATS;
 	}
+	ext_nfsstats.vers = NFSSTATS_V1;
 	if (nfssvc(nfssvc_flag, &ext_nfsstats) < 0)
 		err(1, "Can't get stats");
 	if (clientOnly != 0) {
@@ -418,81 +565,81 @@ exp_intpr(int clientOnly, int serverOnly
 			    , "Getattr", "Setattr", "Lookup", "Readlink",
 			    "Read", "Write", "Create", "Remove");
 		}
-		printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
-		    ext_nfsstats.rpccnt[NFSPROC_GETATTR],
-		    ext_nfsstats.rpccnt[NFSPROC_SETATTR],
-		    ext_nfsstats.rpccnt[NFSPROC_LOOKUP],
-		    ext_nfsstats.rpccnt[NFSPROC_READLINK],
-		    ext_nfsstats.rpccnt[NFSPROC_READ],
-		    ext_nfsstats.rpccnt[NFSPROC_WRITE],
-		    ext_nfsstats.rpccnt[NFSPROC_CREATE],
-		    ext_nfsstats.rpccnt[NFSPROC_REMOVE]);
+		printf("%9ju %9ju %9ju %9ju %9ju %9ju %9ju %9ju\n",
+		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_GETATTR],
+		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SETATTR],
+		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LOOKUP],
+		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READLINK],
+		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READ],
+		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_WRITE],
+		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_CREATE],
+		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_REMOVE]);
 		if (printtitle)
 			printf(
 			    "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n"
 			    , "Rename", "Link", "Symlink", "Mkdir", "Rmdir",
 			    "Readdir", "RdirPlus", "Access");
-		printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
-		    ext_nfsstats.rpccnt[NFSPROC_RENAME],
-		    ext_nfsstats.rpccnt[NFSPROC_LINK],
-		    ext_nfsstats.rpccnt[NFSPROC_SYMLINK],
-		    ext_nfsstats.rpccnt[NFSPROC_MKDIR],
-		    ext_nfsstats.rpccnt[NFSPROC_RMDIR],
-		    ext_nfsstats.rpccnt[NFSPROC_READDIR],
-		    ext_nfsstats.rpccnt[NFSPROC_READDIRPLUS],
-		    ext_nfsstats.rpccnt[NFSPROC_ACCESS]);
+		printf("%9ju %9ju %9ju %9ju %9ju %9ju %9ju %9ju\n",
+		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_RENAME],
+		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LINK],
+		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SYMLINK],
+		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_MKDIR],
+		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_RMDIR],
+		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READDIR],
+		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_READDIRPLUS],
+		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_ACCESS]);
 		if (printtitle)
 			printf(
 			    "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n"
 			    , "Mknod", "Fsstat", "Fsinfo", "PathConf",
 			    "Commit", "SetClId", "SetClIdCf", "Lock");
-		printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
-		    ext_nfsstats.rpccnt[NFSPROC_MKNOD],
-		    ext_nfsstats.rpccnt[NFSPROC_FSSTAT],
-		    ext_nfsstats.rpccnt[NFSPROC_FSINFO],
-		    ext_nfsstats.rpccnt[NFSPROC_PATHCONF],
-		    ext_nfsstats.rpccnt[NFSPROC_COMMIT],
-		    ext_nfsstats.rpccnt[NFSPROC_SETCLIENTID],
-		    ext_nfsstats.rpccnt[NFSPROC_SETCLIENTIDCFRM],
-		    ext_nfsstats.rpccnt[NFSPROC_LOCK]);
+		printf("%9ju %9ju %9ju %9ju %9ju %9ju %9ju %9ju\n",
+		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_MKNOD],
+		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_FSSTAT],
+		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_FSINFO],
+		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_PATHCONF],
+		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_COMMIT],
+		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SETCLIENTID],
+		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_SETCLIENTIDCFRM],
+		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LOCK]);
 		if (printtitle)
 			printf("%9.9s %9.9s %9.9s %9.9s\n",
 			    "LockT", "LockU", "Open", "OpenCfr");
-		printf("%9d %9d %9d %9d\n",
-		    ext_nfsstats.rpccnt[NFSPROC_LOCKT],
-		    ext_nfsstats.rpccnt[NFSPROC_LOCKU],
-		    ext_nfsstats.rpccnt[NFSPROC_OPEN],
-		    ext_nfsstats.rpccnt[NFSPROC_OPENCONFIRM]);
+		printf("%9ju %9ju %9ju %9ju\n",
+		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LOCKT],
+		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_LOCKU],
+		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_OPEN],
+		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_OPENCONFIRM]);
 		if (printtitle)
 			printf(
 			    "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n"
 			    , "OpenOwner", "Opens", "LockOwner",
 			    "Locks", "Delegs", "LocalOwn",
 			    "LocalOpen", "LocalLOwn");
-		printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
-		    ext_nfsstats.clopenowners,
-		    ext_nfsstats.clopens,
-		    ext_nfsstats.cllockowners,
-		    ext_nfsstats.cllocks,
-		    ext_nfsstats.cldelegates,
-		    ext_nfsstats.cllocalopenowners,
-		    ext_nfsstats.cllocalopens,
-		    ext_nfsstats.cllocallockowners);
+		printf("%9ju %9ju %9ju %9ju %9ju %9ju %9ju %9ju\n",
+		    (uintmax_t)ext_nfsstats.clopenowners,
+		    (uintmax_t)ext_nfsstats.clopens,
+		    (uintmax_t)ext_nfsstats.cllockowners,
+		    (uintmax_t)ext_nfsstats.cllocks,
+		    (uintmax_t)ext_nfsstats.cldelegates,
+		    (uintmax_t)ext_nfsstats.cllocalopenowners,
+		    (uintmax_t)ext_nfsstats.cllocalopens,
+		    (uintmax_t)ext_nfsstats.cllocallockowners);
 		if (printtitle)
 			printf("%9.9s\n", "LocalLock");
-		printf("%9d\n", ext_nfsstats.cllocallocks);
+		printf("%9ju\n", (uintmax_t)ext_nfsstats.cllocallocks);
 		if (printtitle) {
 			printf("Rpc Info:\n");
 			printf("%9.9s %9.9s %9.9s %9.9s %9.9s\n",
 			    "TimedOut", "Invalid", "X Replies", "Retries",
 			    "Requests");
 		}
-		printf("%9d %9d %9d %9d %9d\n",
-		    ext_nfsstats.rpctimeouts,
-		    ext_nfsstats.rpcinvalid,
-		    ext_nfsstats.rpcunexpected,
-		    ext_nfsstats.rpcretries,
-		    ext_nfsstats.rpcrequests);
+		printf("%9ju %9ju %9ju %9ju %9ju\n",
+		    (uintmax_t)ext_nfsstats.rpctimeouts,
+		    (uintmax_t)ext_nfsstats.rpcinvalid,
+		    (uintmax_t)ext_nfsstats.rpcunexpected,
+		    (uintmax_t)ext_nfsstats.rpcretries,
+		    (uintmax_t)ext_nfsstats.rpcrequests);
 		if (printtitle) {
 			printf("Cache Info:\n");
 			printf("%9.9s %9.9s %9.9s %9.9s",
@@ -500,31 +647,33 @@ exp_intpr(int clientOnly, int serverOnly
 			printf(" %9.9s %9.9s %9.9s %9.9s\n",
 			    "BioR Hits", "Misses", "BioW Hits", "Misses");
 		}
-		printf("%9d %9d %9d %9d",
-		    ext_nfsstats.attrcache_hits,
-		    ext_nfsstats.attrcache_misses,
-		    ext_nfsstats.lookupcache_hits,
-		    ext_nfsstats.lookupcache_misses);
-		printf(" %9d %9d %9d %9d\n",
-		    ext_nfsstats.biocache_reads - ext_nfsstats.read_bios,
-		    ext_nfsstats.read_bios,
-		    ext_nfsstats.biocache_writes - ext_nfsstats.write_bios,
-		    ext_nfsstats.write_bios);
+		printf("%9ju %9ju %9ju %9ju",
+		    (uintmax_t)ext_nfsstats.attrcache_hits,
+		    (uintmax_t)ext_nfsstats.attrcache_misses,
+		    (uintmax_t)ext_nfsstats.lookupcache_hits,
+		    (uintmax_t)ext_nfsstats.lookupcache_misses);
+		printf(" %9ju %9ju %9ju %9ju\n",
+		    (uintmax_t)(ext_nfsstats.biocache_reads -
+		    ext_nfsstats.read_bios),
+		    (uintmax_t)ext_nfsstats.read_bios,
+		    (uintmax_t)(ext_nfsstats.biocache_writes -
+		    ext_nfsstats.write_bios),
+		    (uintmax_t)ext_nfsstats.write_bios);
 		if (printtitle) {
 			printf("%9.9s %9.9s %9.9s %9.9s",
 			    "BioRLHits", "Misses", "BioD Hits", "Misses");
 			printf(" %9.9s %9.9s\n", "DirE Hits", "Misses");
 		}
-		printf("%9d %9d %9d %9d",
-		    ext_nfsstats.biocache_readlinks -
-		    ext_nfsstats.readlink_bios,
-		    ext_nfsstats.readlink_bios,
-		    ext_nfsstats.biocache_readdirs -
-		    ext_nfsstats.readdir_bios,
-		    ext_nfsstats.readdir_bios);
-		printf(" %9d %9d\n",
-		    ext_nfsstats.direofcache_hits,
-		    ext_nfsstats.direofcache_misses);
+		printf("%9ju %9ju %9ju %9ju",
+		    (uintmax_t)(ext_nfsstats.biocache_readlinks -
+		    ext_nfsstats.readlink_bios),
+		    (uintmax_t)ext_nfsstats.readlink_bios,
+		    (uintmax_t)(ext_nfsstats.biocache_readdirs -
+		    ext_nfsstats.readdir_bios),
+		    (uintmax_t)ext_nfsstats.readdir_bios);
+		printf(" %9ju %9ju\n",
+		    (uintmax_t)ext_nfsstats.direofcache_hits,
+		    (uintmax_t)ext_nfsstats.direofcache_misses);
 	}
 	if (serverOnly != 0) {
 		if (printtitle) {
@@ -534,116 +683,136 @@ exp_intpr(int clientOnly, int serverOnly
 			    , "Getattr", "Setattr", "Lookup", "Readlink",
 			    "Read", "Write", "Create", "Remove");
 		}
-		printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
-		    ext_nfsstats.srvrpccnt[NFSV4OP_GETATTR],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_SETATTR],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_LOOKUP],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_READLINK],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_READ],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_WRITE],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_V3CREATE],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_REMOVE]);
+		printf("%9ju %9ju %9ju %9ju %9ju %9ju %9ju %9ju\n",
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_GETATTR],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SETATTR],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LOOKUP],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READLINK],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READ],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_WRITE],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_V3CREATE],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_REMOVE]);
 		if (printtitle)
 			printf(
 			    "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n"
 			    , "Rename", "Link", "Symlink", "Mkdir", "Rmdir",
 			    "Readdir", "RdirPlus", "Access");
-		printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
-		    ext_nfsstats.srvrpccnt[NFSV4OP_RENAME],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_LINK],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_SYMLINK],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_MKDIR],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_RMDIR],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_READDIR],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_READDIRPLUS],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_ACCESS]);
+		printf("%9ju %9ju %9ju %9ju %9ju %9ju %9ju %9ju\n",
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RENAME],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LINK],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SYMLINK],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_MKDIR],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RMDIR],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READDIR],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_READDIRPLUS],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_ACCESS]);
 		if (printtitle)
 			printf(
 			    "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n"
 			    , "Mknod", "Fsstat", "Fsinfo", "PathConf",
 			    "Commit", "LookupP", "SetClId", "SetClIdCf");
-		printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
-		    ext_nfsstats.srvrpccnt[NFSV4OP_MKNOD],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_FSSTAT],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_FSINFO],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_PATHCONF],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_COMMIT],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_LOOKUPP],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_SETCLIENTID],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_SETCLIENTIDCFRM]);
+		printf("%9ju %9ju %9ju %9ju %9ju %9ju %9ju %9ju\n",
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_MKNOD],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_FSSTAT],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_FSINFO],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_PATHCONF],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_COMMIT],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LOOKUPP],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SETCLIENTID],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SETCLIENTIDCFRM]);
 		if (printtitle)
 			printf(
 			    "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n"
 			    , "Open", "OpenAttr", "OpenDwnGr", "OpenCfrm",
 			    "DelePurge", "DeleRet", "GetFH", "Lock");
-		printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
-		    ext_nfsstats.srvrpccnt[NFSV4OP_OPEN],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_OPENATTR],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_OPENDOWNGRADE],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_OPENCONFIRM],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_DELEGPURGE],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_DELEGRETURN],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_GETFH],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_LOCK]);
+		printf("%9ju %9ju %9ju %9ju %9ju %9ju %9ju %9ju\n",
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_OPEN],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_OPENATTR],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_OPENDOWNGRADE],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_OPENCONFIRM],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_DELEGPURGE],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_DELEGRETURN],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_GETFH],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LOCK]);
 		if (printtitle)
 			printf(
 			    "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n"
 			    , "LockT", "LockU", "Close", "Verify", "NVerify",
 			    "PutFH", "PutPubFH", "PutRootFH");
-		printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
-		    ext_nfsstats.srvrpccnt[NFSV4OP_LOCKT],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_LOCKU],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_CLOSE],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_VERIFY],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_NVERIFY],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_PUTFH],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_PUTPUBFH],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_PUTROOTFH]);
+		printf("%9ju %9ju %9ju %9ju %9ju %9ju %9ju %9ju\n",
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LOCKT],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_LOCKU],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_CLOSE],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_VERIFY],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_NVERIFY],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_PUTFH],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_PUTPUBFH],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_PUTROOTFH]);
 		if (printtitle)
 			printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
 			    "Renew", "RestoreFH", "SaveFH", "Secinfo",
 			    "RelLckOwn", "V4Create");
-		printf("%9d %9d %9d %9d %9d %9d\n",
-		    ext_nfsstats.srvrpccnt[NFSV4OP_RENEW],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_RESTOREFH],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_SAVEFH],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_SECINFO],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_RELEASELCKOWN],
-		    ext_nfsstats.srvrpccnt[NFSV4OP_CREATE]);
+		printf("%9ju %9ju %9ju %9ju %9ju %9ju\n",
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RENEW],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RESTOREFH],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SAVEFH],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_SECINFO],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_RELEASELCKOWN],
+		    (uintmax_t)ext_nfsstats.srvrpccnt[NFSV4OP_CREATE]);
 		if (printtitle) {
 			printf("Server:\n");
 			printf("%9.9s %9.9s %9.9s\n",
 			    "Retfailed", "Faults", "Clients");
 		}
-		printf("%9d %9d %9d\n",
-		    ext_nfsstats.srv_errs, ext_nfsstats.srvrpc_errs,
-		    ext_nfsstats.srvclients);
+		printf("%9ju %9ju %9ju\n",
+		    (uintmax_t)ext_nfsstats.srv_errs,
+		    (uintmax_t)ext_nfsstats.srvrpc_errs,
+		    (uintmax_t)ext_nfsstats.srvclients);
 		if (printtitle)
 			printf("%9.9s %9.9s %9.9s %9.9s %9.9s \n",
 			    "OpenOwner", "Opens", "LockOwner",
 			    "Locks", "Delegs");
-		printf("%9d %9d %9d %9d %9d \n",
-		    ext_nfsstats.srvopenowners,
-		    ext_nfsstats.srvopens,
-		    ext_nfsstats.srvlockowners,
-		    ext_nfsstats.srvlocks,
-		    ext_nfsstats.srvdelegates);
+		printf("%9ju %9ju %9ju %9ju %9ju \n",
+		    (uintmax_t)ext_nfsstats.srvopenowners,
+		    (uintmax_t)ext_nfsstats.srvopens,
+		    (uintmax_t)ext_nfsstats.srvlockowners,
+		    (uintmax_t)ext_nfsstats.srvlocks,
+		    (uintmax_t)ext_nfsstats.srvdelegates);
 		if (printtitle) {
 			printf("Server Cache Stats:\n");
 			printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
 			    "Inprog", "Idem", "Non-idem", "Misses", 
 			    "CacheSize", "TCPPeak");
 		}
-		printf("%9d %9d %9d %9d %9d %9d\n",
-		    ext_nfsstats.srvcache_inproghits,
-		    ext_nfsstats.srvcache_idemdonehits,
-		    ext_nfsstats.srvcache_nonidemdonehits,
-		    ext_nfsstats.srvcache_misses,
-		    ext_nfsstats.srvcache_size,
-		    ext_nfsstats.srvcache_tcppeak);
+		printf("%9ju %9ju %9ju %9ju %9ju %9ju\n",
+		    (uintmax_t)ext_nfsstats.srvcache_inproghits,
+		    (uintmax_t)ext_nfsstats.srvcache_idemdonehits,
+		    (uintmax_t)ext_nfsstats.srvcache_nonidemdonehits,
+		    (uintmax_t)ext_nfsstats.srvcache_misses,
+		    (uintmax_t)ext_nfsstats.srvcache_size,
+		    (uintmax_t)ext_nfsstats.srvcache_tcppeak);
 	}
 }
 
+static void
+compute_totals(struct nfsstatsv1 *total_stats, struct nfsstatsv1 *cur_stats)
+{
+	int i;
+
+	bzero(total_stats, sizeof(*total_stats));
+	for (i = 0; i < (NFSV42_NOPS + NFSV4OP_FAKENOPS); i++) {
+		total_stats->srvbytes[0] += cur_stats->srvbytes[i];
+		total_stats->srvops[0] += cur_stats->srvops[i];
+		bintime_add(&total_stats->srvduration[0],
+			    &cur_stats->srvduration[i]);
+		total_stats->srvrpccnt[i] = cur_stats->srvrpccnt[i];
+	}
+	total_stats->srvstartcnt = cur_stats->srvstartcnt;
+	total_stats->srvdonecnt = cur_stats->srvdonecnt;
+	total_stats->busytime = cur_stats->busytime;
+
+}
+
 /*
  * Print a running summary of nfs statistics for the experimental client and/or
  * server.
@@ -652,40 +821,51 @@ exp_intpr(int clientOnly, int serverOnly
  * First line printed at top of screen is always cumulative.
  */
 static void
-exp_sidewaysintpr(u_int interval, int clientOnly, int serverOnly)
+exp_sidewaysintpr(u_int interval, int clientOnly, int serverOnly,
+    int newStats)
 {
-	struct ext_nfsstats nfsstats, lastst, *ext_nfsstatsp;
+	struct nfsstatsv1 nfsstats, lastst, *ext_nfsstatsp;
+	struct nfsstatsv1 curtotal, lasttotal;
+	struct timespec ts, lastts;
 	int hdrcnt = 1;
 
 	ext_nfsstatsp = &lastst;
-	if (nfssvc(NFSSVC_GETSTATS, ext_nfsstatsp) < 0)
+	ext_nfsstatsp->vers = NFSSTATS_V1;
+	if (nfssvc(NFSSVC_GETSTATS | NFSSVC_NEWSTRUCT, ext_nfsstatsp) < 0)
 		err(1, "Can't get stats");
+	clock_gettime(CLOCK_MONOTONIC, &lastts);
+	compute_totals(&lasttotal, ext_nfsstatsp);
 	sleep(interval);
 
 	for (;;) {
 		ext_nfsstatsp = &nfsstats;
-		if (nfssvc(NFSSVC_GETSTATS, ext_nfsstatsp) < 0)
+		ext_nfsstatsp->vers = NFSSTATS_V1;
+		if (nfssvc(NFSSVC_GETSTATS | NFSSVC_NEWSTRUCT, ext_nfsstatsp)
+		    < 0)
 			err(1, "Can't get stats");
+		clock_gettime(CLOCK_MONOTONIC, &ts);
 
 		if (--hdrcnt == 0) {
-			printhdr(clientOnly, serverOnly);
-			if (clientOnly && serverOnly)
+			printhdr(clientOnly, serverOnly, newStats);
+			if (newStats)
+				hdrcnt = 20;
+			else if (clientOnly && serverOnly)
 				hdrcnt = 10;
 			else
 				hdrcnt = 20;
 		}
-		if (clientOnly) {
-		    printf("%s %6d %6d %6d %6d %6d %6d %6d %6d",
+		if (clientOnly && newStats == 0) {
+		    printf("%s %6ju %6ju %6ju %6ju %6ju %6ju %6ju %6ju",
 			((clientOnly && serverOnly) ? "Client:" : ""),
-			DELTA(rpccnt[NFSPROC_GETATTR]),
-			DELTA(rpccnt[NFSPROC_LOOKUP]),
-			DELTA(rpccnt[NFSPROC_READLINK]),
-			DELTA(rpccnt[NFSPROC_READ]),
-			DELTA(rpccnt[NFSPROC_WRITE]),
-			DELTA(rpccnt[NFSPROC_RENAME]),
-			DELTA(rpccnt[NFSPROC_ACCESS]),
-			DELTA(rpccnt[NFSPROC_READDIR]) +
-			DELTA(rpccnt[NFSPROC_READDIRPLUS])
+			(uintmax_t)DELTA(rpccnt[NFSPROC_GETATTR]),
+			(uintmax_t)DELTA(rpccnt[NFSPROC_LOOKUP]),
+			(uintmax_t)DELTA(rpccnt[NFSPROC_READLINK]),
+			(uintmax_t)DELTA(rpccnt[NFSPROC_READ]),
+			(uintmax_t)DELTA(rpccnt[NFSPROC_WRITE]),
+			(uintmax_t)DELTA(rpccnt[NFSPROC_RENAME]),
+			(uintmax_t)DELTA(rpccnt[NFSPROC_ACCESS]),
+			(uintmax_t)(DELTA(rpccnt[NFSPROC_READDIR]) +
+			DELTA(rpccnt[NFSPROC_READDIRPLUS]))
 		    );
 		    if (widemode) {
 			    printf(" %s %s %s %s %s %s",
@@ -705,21 +885,74 @@ exp_sidewaysintpr(u_int interval, int cl
 		    }
 		    printf("\n");
 		}
-		if (serverOnly) {
-		    printf("%s %6d %6d %6d %6d %6d %6d %6d %6d",
+
+		if (serverOnly && newStats) {
+			long double cur_secs, last_secs, etime;
+			long double mbsec;
+			long double kb_per_transfer;
+			long double transfers_per_second;
+			long double ms_per_transfer;
+			uint64_t queue_len;
+			long double busy_pct;
+			int i;
+
+			cur_secs = ts.tv_sec +
+			    ((long double)ts.tv_nsec / 1000000000);
+			last_secs = lastts.tv_sec +
+			    ((long double)lastts.tv_nsec / 1000000000);
+			etime = cur_secs - last_secs;
+
+			compute_totals(&curtotal, &nfsstats);
+
+			for (i = 0; i < NUM_STAT_TYPES; i++) {
+				compute_new_stats(&nfsstats, &lastst,
+				    STAT_TYPE_TO_NFS(i), etime, &mbsec,
+				    &kb_per_transfer,
+				    &transfers_per_second,
+				    &ms_per_transfer, &queue_len,
+				    &busy_pct);
+
+				if (i == STAT_TYPE_COMMIT) {
+					if (widemode == 0)
+						continue;

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201608132014.u7DKEjuk036979>