]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/nfsstat/nfsstat.c
MFV r285191: tcpdump 4.7.4.
[FreeBSD/FreeBSD.git] / usr.bin / nfsstat / nfsstat.c
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 #ifndef lint
34 static const char copyright[] =
35 "@(#) Copyright (c) 1983, 1989, 1993\n\
36         The Regents of the University of California.  All rights reserved.\n";
37 #endif /* not lint */
38
39 #ifndef lint
40 #if 0
41 static char sccsid[] = "@(#)nfsstat.c   8.2 (Berkeley) 3/31/95";
42 #endif
43 static const char rcsid[] =
44   "$FreeBSD$";
45 #endif /* not lint */
46
47 #include <sys/param.h>
48 #include <sys/module.h>
49 #include <sys/mount.h>
50 #include <sys/time.h>
51 #include <sys/sysctl.h>
52 #include <nfs/nfsproto.h>
53 #include <nfsclient/nfs.h>
54 #include <nfsserver/nfs.h>
55 #include <nfs/nfssvc.h>
56
57 #include <fs/nfs/nfsport.h>
58
59 #include <signal.h>
60 #include <fcntl.h>
61 #include <ctype.h>
62 #include <errno.h>
63 #include <kvm.h>
64 #include <limits.h>
65 #include <nlist.h>
66 #include <unistd.h>
67 #include <stdio.h>
68 #include <stdlib.h>
69 #include <string.h>
70 #include <paths.h>
71 #include <err.h>
72
73 static int widemode = 0;
74 static int zflag = 0;
75 static int printtitle = 1;
76 static struct ext_nfsstats ext_nfsstats;
77 static int extra_output = 0;
78
79 static void intpr(int, int);
80 static void printhdr(int, int);
81 static void usage(void);
82 static char *sperc1(int, int);
83 static char *sperc2(int, int);
84 static void exp_intpr(int, int);
85 static void exp_sidewaysintpr(u_int, int, int);
86
87 #define DELTA(field)    (nfsstats.field - lastst.field)
88
89 int
90 main(int argc, char **argv)
91 {
92         u_int interval;
93         int clientOnly = -1;
94         int serverOnly = -1;
95         int ch;
96         char *memf, *nlistf;
97         int mntlen, i;
98         char buf[1024];
99         struct statfs *mntbuf;
100         struct nfscl_dumpmntopts dumpmntopts;
101
102         interval = 0;
103         memf = nlistf = NULL;
104         while ((ch = getopt(argc, argv, "cesWM:mN:w:z")) != -1)
105                 switch(ch) {
106                 case 'M':
107                         memf = optarg;
108                         break;
109                 case 'm':
110                         /* Display mount options for NFS mount points. */
111                         mntlen = getmntinfo(&mntbuf, MNT_NOWAIT);
112                         for (i = 0; i < mntlen; i++) {
113                                 if (strcmp(mntbuf->f_fstypename, "nfs") == 0) {
114                                         dumpmntopts.ndmnt_fname =
115                                             mntbuf->f_mntonname;
116                                         dumpmntopts.ndmnt_buf = buf;
117                                         dumpmntopts.ndmnt_blen = sizeof(buf);
118                                         if (nfssvc(NFSSVC_DUMPMNTOPTS,
119                                             &dumpmntopts) >= 0)
120                                                 printf("%s on %s\n%s\n",
121                                                     mntbuf->f_mntfromname,
122                                                     mntbuf->f_mntonname, buf);
123                                         else if (errno == EPERM)
124                                                 errx(1, "Only priviledged users"
125                                                     " can use the -m option");
126                                 }
127                                 mntbuf++;
128                         }
129                         exit(0);
130                 case 'N':
131                         nlistf = optarg;
132                         break;
133                 case 'W':
134                         widemode = 1;
135                         break;
136                 case 'w':
137                         interval = atoi(optarg);
138                         break;
139                 case 'c':
140                         clientOnly = 1;
141                         if (serverOnly < 0)
142                                 serverOnly = 0;
143                         break;
144                 case 's':
145                         serverOnly = 1;
146                         if (clientOnly < 0)
147                                 clientOnly = 0;
148                         break;
149                 case 'z':
150                         zflag = 1;
151                         break;
152                 case 'e':
153                         extra_output = 1;
154                         break;
155                 case '?':
156                 default:
157                         usage();
158                 }
159         argc -= optind;
160         argv += optind;
161
162 #define BACKWARD_COMPATIBILITY
163 #ifdef  BACKWARD_COMPATIBILITY
164         if (*argv) {
165                 interval = atoi(*argv);
166                 if (*++argv) {
167                         nlistf = *argv;
168                         if (*++argv)
169                                 memf = *argv;
170                 }
171         }
172 #endif
173         if (modfind("nfscommon") < 0)
174                 errx(1, "NFS client/server not loaded");
175
176         if (interval) {
177                 exp_sidewaysintpr(interval, clientOnly, serverOnly);
178         } else {
179                 if (extra_output != 0)
180                         exp_intpr(clientOnly, serverOnly);
181                 else
182                         intpr(clientOnly, serverOnly);
183         }
184         exit(0);
185 }
186
187 /*
188  * Print a description of the nfs stats.
189  */
190 static void
191 intpr(int clientOnly, int serverOnly)
192 {
193         int nfssvc_flag;
194
195         nfssvc_flag = NFSSVC_GETSTATS;
196         if (zflag != 0) {
197                 if (clientOnly != 0)
198                         nfssvc_flag |= NFSSVC_ZEROCLTSTATS;
199                 if (serverOnly != 0)
200                         nfssvc_flag |= NFSSVC_ZEROSRVSTATS;
201         }
202         if (nfssvc(nfssvc_flag, &ext_nfsstats) < 0)
203                 err(1, "Can't get stats");
204         if (clientOnly) {
205                 printf("Client Info:\n");
206                 printf("Rpc Counts:\n");
207                 printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
208                         "Getattr", "Setattr", "Lookup", "Readlink", "Read",
209                         "Write", "Create", "Remove");
210                 printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
211                         ext_nfsstats.rpccnt[NFSPROC_GETATTR],
212                         ext_nfsstats.rpccnt[NFSPROC_SETATTR],
213                         ext_nfsstats.rpccnt[NFSPROC_LOOKUP],
214                         ext_nfsstats.rpccnt[NFSPROC_READLINK],
215                         ext_nfsstats.rpccnt[NFSPROC_READ],
216                         ext_nfsstats.rpccnt[NFSPROC_WRITE],
217                         ext_nfsstats.rpccnt[NFSPROC_CREATE],
218                         ext_nfsstats.rpccnt[NFSPROC_REMOVE]);
219                 printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
220                         "Rename", "Link", "Symlink", "Mkdir", "Rmdir",
221                         "Readdir", "RdirPlus", "Access");
222                 printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
223                         ext_nfsstats.rpccnt[NFSPROC_RENAME],
224                         ext_nfsstats.rpccnt[NFSPROC_LINK],
225                         ext_nfsstats.rpccnt[NFSPROC_SYMLINK],
226                         ext_nfsstats.rpccnt[NFSPROC_MKDIR],
227                         ext_nfsstats.rpccnt[NFSPROC_RMDIR],
228                         ext_nfsstats.rpccnt[NFSPROC_READDIR],
229                         ext_nfsstats.rpccnt[NFSPROC_READDIRPLUS],
230                         ext_nfsstats.rpccnt[NFSPROC_ACCESS]);
231                 printf("%9.9s %9.9s %9.9s %9.9s %9.9s\n",
232                         "Mknod", "Fsstat", "Fsinfo", "PathConf", "Commit");
233                 printf("%9d %9d %9d %9d %9d\n",
234                         ext_nfsstats.rpccnt[NFSPROC_MKNOD],
235                         ext_nfsstats.rpccnt[NFSPROC_FSSTAT],
236                         ext_nfsstats.rpccnt[NFSPROC_FSINFO],
237                         ext_nfsstats.rpccnt[NFSPROC_PATHCONF],
238                         ext_nfsstats.rpccnt[NFSPROC_COMMIT]);
239                 printf("Rpc Info:\n");
240                 printf("%9.9s %9.9s %9.9s %9.9s %9.9s\n",
241                         "TimedOut", "Invalid", "X Replies", "Retries", 
242                         "Requests");
243                 printf("%9d %9d %9d %9d %9d\n",
244                         ext_nfsstats.rpctimeouts,
245                         ext_nfsstats.rpcinvalid,
246                         ext_nfsstats.rpcunexpected,
247                         ext_nfsstats.rpcretries,
248                         ext_nfsstats.rpcrequests);
249                 printf("Cache Info:\n");
250                 printf("%9.9s %9.9s %9.9s %9.9s",
251                         "Attr Hits", "Misses", "Lkup Hits", "Misses");
252                 printf(" %9.9s %9.9s %9.9s %9.9s\n",
253                         "BioR Hits", "Misses", "BioW Hits", "Misses");
254                 printf("%9d %9d %9d %9d",
255                         ext_nfsstats.attrcache_hits,
256                         ext_nfsstats.attrcache_misses,
257                         ext_nfsstats.lookupcache_hits,
258                         ext_nfsstats.lookupcache_misses);
259                 printf(" %9d %9d %9d %9d\n",
260                         ext_nfsstats.biocache_reads -
261                         ext_nfsstats.read_bios,
262                         ext_nfsstats.read_bios,
263                         ext_nfsstats.biocache_writes -
264                         ext_nfsstats.write_bios,
265                         ext_nfsstats.write_bios);
266                 printf("%9.9s %9.9s %9.9s %9.9s",
267                         "BioRLHits", "Misses", "BioD Hits", "Misses");
268                 printf(" %9.9s %9.9s %9.9s %9.9s\n", "DirE Hits", "Misses", "Accs Hits", "Misses");
269                 printf("%9d %9d %9d %9d",
270                         ext_nfsstats.biocache_readlinks -
271                         ext_nfsstats.readlink_bios,
272                         ext_nfsstats.readlink_bios,
273                         ext_nfsstats.biocache_readdirs -
274                         ext_nfsstats.readdir_bios,
275                         ext_nfsstats.readdir_bios);
276                 printf(" %9d %9d %9d %9d\n",
277                         ext_nfsstats.direofcache_hits,
278                         ext_nfsstats.direofcache_misses,
279                         ext_nfsstats.accesscache_hits,
280                         ext_nfsstats.accesscache_misses);
281         }
282         if (serverOnly) {
283                 printf("\nServer Info:\n");
284                 printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
285                         "Getattr", "Setattr", "Lookup", "Readlink", "Read",
286                         "Write", "Create", "Remove");
287                 printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
288                         ext_nfsstats.srvrpccnt[NFSV4OP_GETATTR],
289                         ext_nfsstats.srvrpccnt[NFSV4OP_SETATTR],
290                         ext_nfsstats.srvrpccnt[NFSV4OP_LOOKUP],
291                         ext_nfsstats.srvrpccnt[NFSV4OP_READLINK],
292                         ext_nfsstats.srvrpccnt[NFSV4OP_READ],
293                         ext_nfsstats.srvrpccnt[NFSV4OP_WRITE],
294                         ext_nfsstats.srvrpccnt[NFSV4OP_CREATE],
295                         ext_nfsstats.srvrpccnt[NFSV4OP_REMOVE]);
296                 printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
297                         "Rename", "Link", "Symlink", "Mkdir", "Rmdir",
298                         "Readdir", "RdirPlus", "Access");
299                 printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
300                         ext_nfsstats.srvrpccnt[NFSV4OP_RENAME],
301                         ext_nfsstats.srvrpccnt[NFSV4OP_LINK],
302                         ext_nfsstats.srvrpccnt[NFSV4OP_SYMLINK],
303                         ext_nfsstats.srvrpccnt[NFSV4OP_MKDIR],
304                         ext_nfsstats.srvrpccnt[NFSV4OP_RMDIR],
305                         ext_nfsstats.srvrpccnt[NFSV4OP_READDIR],
306                         ext_nfsstats.srvrpccnt[NFSV4OP_READDIRPLUS],
307                         ext_nfsstats.srvrpccnt[NFSV4OP_ACCESS]);
308                 printf("%9.9s %9.9s %9.9s %9.9s %9.9s\n",
309                         "Mknod", "Fsstat", "Fsinfo", "PathConf", "Commit");
310                 printf("%9d %9d %9d %9d %9d\n",
311                         ext_nfsstats.srvrpccnt[NFSV4OP_MKNOD],
312                         ext_nfsstats.srvrpccnt[NFSV4OP_FSSTAT],
313                         ext_nfsstats.srvrpccnt[NFSV4OP_FSINFO],
314                         ext_nfsstats.srvrpccnt[NFSV4OP_PATHCONF],
315                         ext_nfsstats.srvrpccnt[NFSV4OP_COMMIT]);
316                 printf("Server Ret-Failed\n");
317                 printf("%17d\n", ext_nfsstats.srvrpc_errs);
318                 printf("Server Faults\n");
319                 printf("%13d\n", ext_nfsstats.srv_errs);
320                 printf("Server Cache Stats:\n");
321                 printf("%9.9s %9.9s %9.9s %9.9s\n",
322                         "Inprog", "Idem", "Non-idem", "Misses");
323                 printf("%9d %9d %9d %9d\n",
324                         ext_nfsstats.srvcache_inproghits,
325                         ext_nfsstats.srvcache_idemdonehits,
326                         ext_nfsstats.srvcache_nonidemdonehits,
327                         ext_nfsstats.srvcache_misses);
328                 printf("Server Write Gathering:\n");
329                 printf("%9.9s %9.9s %9.9s\n",
330                         "WriteOps", "WriteRPC", "Opsaved");
331                 /*
332                  * The new client doesn't do write gathering. It was
333                  * only useful for NFSv2.
334                  */
335                 printf("%9d %9d %9d\n",
336                         ext_nfsstats.srvrpccnt[NFSV4OP_WRITE],
337                         ext_nfsstats.srvrpccnt[NFSV4OP_WRITE], 0);
338         }
339 }
340
341 static void
342 printhdr(int clientOnly, int serverOnly)
343 {
344         printf("%s%6.6s %6.6s %6.6s %6.6s %6.6s %6.6s %6.6s %6.6s",
345             ((serverOnly && clientOnly) ? "        " : " "),
346             "GtAttr", "Lookup", "Rdlink", "Read", "Write", "Rename",
347             "Access", "Rddir");
348         if (widemode && clientOnly) {
349                 printf(" Attr Lkup BioR BioW Accs BioD");
350         }
351         printf("\n");
352         fflush(stdout);
353 }
354
355 static void
356 usage(void)
357 {
358         (void)fprintf(stderr,
359             "usage: nfsstat [-cemszW] [-M core] [-N system] [-w wait]\n");
360         exit(1);
361 }
362
363 static char SPBuf[64][8];
364 static int SPIndex;
365
366 static char * 
367 sperc1(int hits, int misses)
368 {
369         char *p = SPBuf[SPIndex];
370
371         if (hits + misses) {
372                 sprintf(p, "%3d%%", 
373                     (int)(char)((quad_t)hits * 100 / (hits + misses)));
374         } else {
375                 sprintf(p, "   -");
376         }
377         SPIndex = (SPIndex + 1) & 63;
378         return(p);
379 }
380
381 static char * 
382 sperc2(int ttl, int misses)
383 {
384         char *p = SPBuf[SPIndex];
385
386         if (ttl) {
387                 sprintf(p, "%3d%%",
388                     (int)(char)((quad_t)(ttl - misses) * 100 / ttl));
389         } else {
390                 sprintf(p, "   -");
391         }
392         SPIndex = (SPIndex + 1) & 63;
393         return(p);
394 }
395
396 /*
397  * Print a description of the nfs stats for the experimental client/server.
398  */
399 static void
400 exp_intpr(int clientOnly, int serverOnly)
401 {
402         int nfssvc_flag;
403
404         nfssvc_flag = NFSSVC_GETSTATS;
405         if (zflag != 0) {
406                 if (clientOnly != 0)
407                         nfssvc_flag |= NFSSVC_ZEROCLTSTATS;
408                 if (serverOnly != 0)
409                         nfssvc_flag |= NFSSVC_ZEROSRVSTATS;
410         }
411         if (nfssvc(nfssvc_flag, &ext_nfsstats) < 0)
412                 err(1, "Can't get stats");
413         if (clientOnly != 0) {
414                 if (printtitle) {
415                         printf("Client Info:\n");
416                         printf("Rpc Counts:\n");
417                         printf(
418                             "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n"
419                             , "Getattr", "Setattr", "Lookup", "Readlink",
420                             "Read", "Write", "Create", "Remove");
421                 }
422                 printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
423                     ext_nfsstats.rpccnt[NFSPROC_GETATTR],
424                     ext_nfsstats.rpccnt[NFSPROC_SETATTR],
425                     ext_nfsstats.rpccnt[NFSPROC_LOOKUP],
426                     ext_nfsstats.rpccnt[NFSPROC_READLINK],
427                     ext_nfsstats.rpccnt[NFSPROC_READ],
428                     ext_nfsstats.rpccnt[NFSPROC_WRITE],
429                     ext_nfsstats.rpccnt[NFSPROC_CREATE],
430                     ext_nfsstats.rpccnt[NFSPROC_REMOVE]);
431                 if (printtitle)
432                         printf(
433                             "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n"
434                             , "Rename", "Link", "Symlink", "Mkdir", "Rmdir",
435                             "Readdir", "RdirPlus", "Access");
436                 printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
437                     ext_nfsstats.rpccnt[NFSPROC_RENAME],
438                     ext_nfsstats.rpccnt[NFSPROC_LINK],
439                     ext_nfsstats.rpccnt[NFSPROC_SYMLINK],
440                     ext_nfsstats.rpccnt[NFSPROC_MKDIR],
441                     ext_nfsstats.rpccnt[NFSPROC_RMDIR],
442                     ext_nfsstats.rpccnt[NFSPROC_READDIR],
443                     ext_nfsstats.rpccnt[NFSPROC_READDIRPLUS],
444                     ext_nfsstats.rpccnt[NFSPROC_ACCESS]);
445                 if (printtitle)
446                         printf(
447                             "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n"
448                             , "Mknod", "Fsstat", "Fsinfo", "PathConf",
449                             "Commit", "SetClId", "SetClIdCf", "Lock");
450                 printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
451                     ext_nfsstats.rpccnt[NFSPROC_MKNOD],
452                     ext_nfsstats.rpccnt[NFSPROC_FSSTAT],
453                     ext_nfsstats.rpccnt[NFSPROC_FSINFO],
454                     ext_nfsstats.rpccnt[NFSPROC_PATHCONF],
455                     ext_nfsstats.rpccnt[NFSPROC_COMMIT],
456                     ext_nfsstats.rpccnt[NFSPROC_SETCLIENTID],
457                     ext_nfsstats.rpccnt[NFSPROC_SETCLIENTIDCFRM],
458                     ext_nfsstats.rpccnt[NFSPROC_LOCK]);
459                 if (printtitle)
460                         printf("%9.9s %9.9s %9.9s %9.9s\n",
461                             "LockT", "LockU", "Open", "OpenCfr");
462                 printf("%9d %9d %9d %9d\n",
463                     ext_nfsstats.rpccnt[NFSPROC_LOCKT],
464                     ext_nfsstats.rpccnt[NFSPROC_LOCKU],
465                     ext_nfsstats.rpccnt[NFSPROC_OPEN],
466                     ext_nfsstats.rpccnt[NFSPROC_OPENCONFIRM]);
467                 if (printtitle)
468                         printf(
469                             "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n"
470                             , "OpenOwner", "Opens", "LockOwner",
471                             "Locks", "Delegs", "LocalOwn",
472                             "LocalOpen", "LocalLOwn");
473                 printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
474                     ext_nfsstats.clopenowners,
475                     ext_nfsstats.clopens,
476                     ext_nfsstats.cllockowners,
477                     ext_nfsstats.cllocks,
478                     ext_nfsstats.cldelegates,
479                     ext_nfsstats.cllocalopenowners,
480                     ext_nfsstats.cllocalopens,
481                     ext_nfsstats.cllocallockowners);
482                 if (printtitle)
483                         printf("%9.9s\n", "LocalLock");
484                 printf("%9d\n", ext_nfsstats.cllocallocks);
485                 if (printtitle) {
486                         printf("Rpc Info:\n");
487                         printf("%9.9s %9.9s %9.9s %9.9s %9.9s\n",
488                             "TimedOut", "Invalid", "X Replies", "Retries",
489                             "Requests");
490                 }
491                 printf("%9d %9d %9d %9d %9d\n",
492                     ext_nfsstats.rpctimeouts,
493                     ext_nfsstats.rpcinvalid,
494                     ext_nfsstats.rpcunexpected,
495                     ext_nfsstats.rpcretries,
496                     ext_nfsstats.rpcrequests);
497                 if (printtitle) {
498                         printf("Cache Info:\n");
499                         printf("%9.9s %9.9s %9.9s %9.9s",
500                             "Attr Hits", "Misses", "Lkup Hits", "Misses");
501                         printf(" %9.9s %9.9s %9.9s %9.9s\n",
502                             "BioR Hits", "Misses", "BioW Hits", "Misses");
503                 }
504                 printf("%9d %9d %9d %9d",
505                     ext_nfsstats.attrcache_hits,
506                     ext_nfsstats.attrcache_misses,
507                     ext_nfsstats.lookupcache_hits,
508                     ext_nfsstats.lookupcache_misses);
509                 printf(" %9d %9d %9d %9d\n",
510                     ext_nfsstats.biocache_reads - ext_nfsstats.read_bios,
511                     ext_nfsstats.read_bios,
512                     ext_nfsstats.biocache_writes - ext_nfsstats.write_bios,
513                     ext_nfsstats.write_bios);
514                 if (printtitle) {
515                         printf("%9.9s %9.9s %9.9s %9.9s",
516                             "BioRLHits", "Misses", "BioD Hits", "Misses");
517                         printf(" %9.9s %9.9s\n", "DirE Hits", "Misses");
518                 }
519                 printf("%9d %9d %9d %9d",
520                     ext_nfsstats.biocache_readlinks -
521                     ext_nfsstats.readlink_bios,
522                     ext_nfsstats.readlink_bios,
523                     ext_nfsstats.biocache_readdirs -
524                     ext_nfsstats.readdir_bios,
525                     ext_nfsstats.readdir_bios);
526                 printf(" %9d %9d\n",
527                     ext_nfsstats.direofcache_hits,
528                     ext_nfsstats.direofcache_misses);
529         }
530         if (serverOnly != 0) {
531                 if (printtitle) {
532                         printf("\nServer Info:\n");
533                         printf(
534                             "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n"
535                             , "Getattr", "Setattr", "Lookup", "Readlink",
536                             "Read", "Write", "Create", "Remove");
537                 }
538                 printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
539                     ext_nfsstats.srvrpccnt[NFSV4OP_GETATTR],
540                     ext_nfsstats.srvrpccnt[NFSV4OP_SETATTR],
541                     ext_nfsstats.srvrpccnt[NFSV4OP_LOOKUP],
542                     ext_nfsstats.srvrpccnt[NFSV4OP_READLINK],
543                     ext_nfsstats.srvrpccnt[NFSV4OP_READ],
544                     ext_nfsstats.srvrpccnt[NFSV4OP_WRITE],
545                     ext_nfsstats.srvrpccnt[NFSV4OP_V3CREATE],
546                     ext_nfsstats.srvrpccnt[NFSV4OP_REMOVE]);
547                 if (printtitle)
548                         printf(
549                             "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n"
550                             , "Rename", "Link", "Symlink", "Mkdir", "Rmdir",
551                             "Readdir", "RdirPlus", "Access");
552                 printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
553                     ext_nfsstats.srvrpccnt[NFSV4OP_RENAME],
554                     ext_nfsstats.srvrpccnt[NFSV4OP_LINK],
555                     ext_nfsstats.srvrpccnt[NFSV4OP_SYMLINK],
556                     ext_nfsstats.srvrpccnt[NFSV4OP_MKDIR],
557                     ext_nfsstats.srvrpccnt[NFSV4OP_RMDIR],
558                     ext_nfsstats.srvrpccnt[NFSV4OP_READDIR],
559                     ext_nfsstats.srvrpccnt[NFSV4OP_READDIRPLUS],
560                     ext_nfsstats.srvrpccnt[NFSV4OP_ACCESS]);
561                 if (printtitle)
562                         printf(
563                             "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n"
564                             , "Mknod", "Fsstat", "Fsinfo", "PathConf",
565                             "Commit", "LookupP", "SetClId", "SetClIdCf");
566                 printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
567                     ext_nfsstats.srvrpccnt[NFSV4OP_MKNOD],
568                     ext_nfsstats.srvrpccnt[NFSV4OP_FSSTAT],
569                     ext_nfsstats.srvrpccnt[NFSV4OP_FSINFO],
570                     ext_nfsstats.srvrpccnt[NFSV4OP_PATHCONF],
571                     ext_nfsstats.srvrpccnt[NFSV4OP_COMMIT],
572                     ext_nfsstats.srvrpccnt[NFSV4OP_LOOKUPP],
573                     ext_nfsstats.srvrpccnt[NFSV4OP_SETCLIENTID],
574                     ext_nfsstats.srvrpccnt[NFSV4OP_SETCLIENTIDCFRM]);
575                 if (printtitle)
576                         printf(
577                             "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n"
578                             , "Open", "OpenAttr", "OpenDwnGr", "OpenCfrm",
579                             "DelePurge", "DeleRet", "GetFH", "Lock");
580                 printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
581                     ext_nfsstats.srvrpccnt[NFSV4OP_OPEN],
582                     ext_nfsstats.srvrpccnt[NFSV4OP_OPENATTR],
583                     ext_nfsstats.srvrpccnt[NFSV4OP_OPENDOWNGRADE],
584                     ext_nfsstats.srvrpccnt[NFSV4OP_OPENCONFIRM],
585                     ext_nfsstats.srvrpccnt[NFSV4OP_DELEGPURGE],
586                     ext_nfsstats.srvrpccnt[NFSV4OP_DELEGRETURN],
587                     ext_nfsstats.srvrpccnt[NFSV4OP_GETFH],
588                     ext_nfsstats.srvrpccnt[NFSV4OP_LOCK]);
589                 if (printtitle)
590                         printf(
591                             "%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n"
592                             , "LockT", "LockU", "Close", "Verify", "NVerify",
593                             "PutFH", "PutPubFH", "PutRootFH");
594                 printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
595                     ext_nfsstats.srvrpccnt[NFSV4OP_LOCKT],
596                     ext_nfsstats.srvrpccnt[NFSV4OP_LOCKU],
597                     ext_nfsstats.srvrpccnt[NFSV4OP_CLOSE],
598                     ext_nfsstats.srvrpccnt[NFSV4OP_VERIFY],
599                     ext_nfsstats.srvrpccnt[NFSV4OP_NVERIFY],
600                     ext_nfsstats.srvrpccnt[NFSV4OP_PUTFH],
601                     ext_nfsstats.srvrpccnt[NFSV4OP_PUTPUBFH],
602                     ext_nfsstats.srvrpccnt[NFSV4OP_PUTROOTFH]);
603                 if (printtitle)
604                         printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
605                             "Renew", "RestoreFH", "SaveFH", "Secinfo",
606                             "RelLckOwn", "V4Create");
607                 printf("%9d %9d %9d %9d %9d %9d\n",
608                     ext_nfsstats.srvrpccnt[NFSV4OP_RENEW],
609                     ext_nfsstats.srvrpccnt[NFSV4OP_RESTOREFH],
610                     ext_nfsstats.srvrpccnt[NFSV4OP_SAVEFH],
611                     ext_nfsstats.srvrpccnt[NFSV4OP_SECINFO],
612                     ext_nfsstats.srvrpccnt[NFSV4OP_RELEASELCKOWN],
613                     ext_nfsstats.srvrpccnt[NFSV4OP_CREATE]);
614                 if (printtitle) {
615                         printf("Server:\n");
616                         printf("%9.9s %9.9s %9.9s\n",
617                             "Retfailed", "Faults", "Clients");
618                 }
619                 printf("%9d %9d %9d\n",
620                     ext_nfsstats.srv_errs, ext_nfsstats.srvrpc_errs,
621                     ext_nfsstats.srvclients);
622                 if (printtitle)
623                         printf("%9.9s %9.9s %9.9s %9.9s %9.9s \n",
624                             "OpenOwner", "Opens", "LockOwner",
625                             "Locks", "Delegs");
626                 printf("%9d %9d %9d %9d %9d \n",
627                     ext_nfsstats.srvopenowners,
628                     ext_nfsstats.srvopens,
629                     ext_nfsstats.srvlockowners,
630                     ext_nfsstats.srvlocks,
631                     ext_nfsstats.srvdelegates);
632                 if (printtitle) {
633                         printf("Server Cache Stats:\n");
634                         printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
635                             "Inprog", "Idem", "Non-idem", "Misses", 
636                             "CacheSize", "TCPPeak");
637                 }
638                 printf("%9d %9d %9d %9d %9d %9d\n",
639                     ext_nfsstats.srvcache_inproghits,
640                     ext_nfsstats.srvcache_idemdonehits,
641                     ext_nfsstats.srvcache_nonidemdonehits,
642                     ext_nfsstats.srvcache_misses,
643                     ext_nfsstats.srvcache_size,
644                     ext_nfsstats.srvcache_tcppeak);
645         }
646 }
647
648 /*
649  * Print a running summary of nfs statistics for the experimental client and/or
650  * server.
651  * Repeat display every interval seconds, showing statistics
652  * collected over that interval.  Assumes that interval is non-zero.
653  * First line printed at top of screen is always cumulative.
654  */
655 static void
656 exp_sidewaysintpr(u_int interval, int clientOnly, int serverOnly)
657 {
658         struct ext_nfsstats nfsstats, lastst, *ext_nfsstatsp;
659         int hdrcnt = 1;
660
661         ext_nfsstatsp = &lastst;
662         if (nfssvc(NFSSVC_GETSTATS, ext_nfsstatsp) < 0)
663                 err(1, "Can't get stats");
664         sleep(interval);
665
666         for (;;) {
667                 ext_nfsstatsp = &nfsstats;
668                 if (nfssvc(NFSSVC_GETSTATS, ext_nfsstatsp) < 0)
669                         err(1, "Can't get stats");
670
671                 if (--hdrcnt == 0) {
672                         printhdr(clientOnly, serverOnly);
673                         if (clientOnly && serverOnly)
674                                 hdrcnt = 10;
675                         else
676                                 hdrcnt = 20;
677                 }
678                 if (clientOnly) {
679                     printf("%s %6d %6d %6d %6d %6d %6d %6d %6d",
680                         ((clientOnly && serverOnly) ? "Client:" : ""),
681                         DELTA(rpccnt[NFSPROC_GETATTR]),
682                         DELTA(rpccnt[NFSPROC_LOOKUP]),
683                         DELTA(rpccnt[NFSPROC_READLINK]),
684                         DELTA(rpccnt[NFSPROC_READ]),
685                         DELTA(rpccnt[NFSPROC_WRITE]),
686                         DELTA(rpccnt[NFSPROC_RENAME]),
687                         DELTA(rpccnt[NFSPROC_ACCESS]),
688                         DELTA(rpccnt[NFSPROC_READDIR]) +
689                         DELTA(rpccnt[NFSPROC_READDIRPLUS])
690                     );
691                     if (widemode) {
692                             printf(" %s %s %s %s %s %s",
693                                 sperc1(DELTA(attrcache_hits),
694                                     DELTA(attrcache_misses)),
695                                 sperc1(DELTA(lookupcache_hits), 
696                                     DELTA(lookupcache_misses)),
697                                 sperc2(DELTA(biocache_reads),
698                                     DELTA(read_bios)),
699                                 sperc2(DELTA(biocache_writes),
700                                     DELTA(write_bios)),
701                                 sperc1(DELTA(accesscache_hits),
702                                     DELTA(accesscache_misses)),
703                                 sperc2(DELTA(biocache_readdirs),
704                                     DELTA(readdir_bios))
705                             );
706                     }
707                     printf("\n");
708                 }
709                 if (serverOnly) {
710                     printf("%s %6d %6d %6d %6d %6d %6d %6d %6d",
711                         ((clientOnly && serverOnly) ? "Server:" : ""),
712                         DELTA(srvrpccnt[NFSV4OP_GETATTR]),
713                         DELTA(srvrpccnt[NFSV4OP_LOOKUP]),
714                         DELTA(srvrpccnt[NFSV4OP_READLINK]),
715                         DELTA(srvrpccnt[NFSV4OP_READ]),
716                         DELTA(srvrpccnt[NFSV4OP_WRITE]),
717                         DELTA(srvrpccnt[NFSV4OP_RENAME]),
718                         DELTA(srvrpccnt[NFSV4OP_ACCESS]),
719                         DELTA(srvrpccnt[NFSV4OP_READDIR]) +
720                         DELTA(srvrpccnt[NFSV4OP_READDIRPLUS]));
721                     printf("\n");
722                 }
723                 lastst = nfsstats;
724                 fflush(stdout);
725                 sleep(interval);
726         }
727         /*NOTREACHED*/
728 }