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 ***
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to