Home | History | Annotate | Download | only in nfsstat
      1      0      stevel /*
      2      0      stevel  * CDDL HEADER START
      3      0      stevel  *
      4      0      stevel  * The contents of this file are subject to the terms of the
      5   3406    th199096  * Common Development and Distribution License (the "License").
      6   3406    th199096  * You may not use this file except in compliance with the License.
      7      0      stevel  *
      8      0      stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9      0      stevel  * or http://www.opensolaris.org/os/licensing.
     10      0      stevel  * See the License for the specific language governing permissions
     11      0      stevel  * and limitations under the License.
     12      0      stevel  *
     13      0      stevel  * When distributing Covered Code, include this CDDL HEADER in each
     14      0      stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15      0      stevel  * If applicable, add the following below this CDDL HEADER, with the
     16      0      stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     17      0      stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     18      0      stevel  *
     19      0      stevel  * CDDL HEADER END
     20      0      stevel  */
     21   3406    th199096 
     22      0      stevel /* LINTLIBRARY */
     23      0      stevel /* PROTOLIB1 */
     24      0      stevel 
     25      0      stevel /*
     26  10265  Krishnendu  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     27      0      stevel  * Use is subject to license terms.
     28      0      stevel  */
     29      0      stevel 
     30      0      stevel /*
     31      0      stevel  * nfsstat: Network File System statistics
     32      0      stevel  *
     33      0      stevel  */
     34      0      stevel 
     35      0      stevel #include <stdio.h>
     36      0      stevel #include <stdlib.h>
     37      0      stevel #include <unistd.h>
     38      0      stevel #include <stdarg.h>
     39      0      stevel #include <string.h>
     40      0      stevel #include <errno.h>
     41      0      stevel #include <fcntl.h>
     42      0      stevel #include <kvm.h>
     43      0      stevel #include <kstat.h>
     44      0      stevel #include <sys/param.h>
     45      0      stevel #include <sys/types.h>
     46      0      stevel #include <sys/t_lock.h>
     47      0      stevel #include <sys/tiuser.h>
     48      0      stevel #include <sys/statvfs.h>
     49      0      stevel #include <sys/mntent.h>
     50      0      stevel #include <sys/mnttab.h>
     51      0      stevel #include <sys/sysmacros.h>
     52      0      stevel #include <sys/mkdev.h>
     53      0      stevel #include <rpc/types.h>
     54      0      stevel #include <rpc/xdr.h>
     55      0      stevel #include <rpc/auth.h>
     56      0      stevel #include <rpc/clnt.h>
     57      0      stevel #include <nfs/nfs.h>
     58      0      stevel #include <nfs/nfs_clnt.h>
     59      0      stevel #include <nfs/nfs_sec.h>
     60      0      stevel #include <inttypes.h>
     61      0      stevel #include <signal.h>
     62      0      stevel #include <time.h>
     63      0      stevel #include <sys/time.h>
     64      0      stevel #include <strings.h>
     65      0      stevel #include <ctype.h>
     66  10265  Krishnendu #include <locale.h>
     67      0      stevel 
     68  10265  Krishnendu #include "statcommon.h"
     69      0      stevel 
     70      0      stevel static kstat_ctl_t *kc = NULL;		/* libkstat cookie */
     71      0      stevel static kstat_t *rpc_clts_client_kstat, *rpc_clts_server_kstat;
     72      0      stevel static kstat_t *rpc_cots_client_kstat, *rpc_cots_server_kstat;
     73      0      stevel static kstat_t *rpc_rdma_client_kstat, *rpc_rdma_server_kstat;
     74      0      stevel static kstat_t *nfs_client_kstat, *nfs_server_v2_kstat, *nfs_server_v3_kstat;
     75      0      stevel static kstat_t *nfs4_client_kstat, *nfs_server_v4_kstat;
     76      0      stevel static kstat_t *rfsproccnt_v2_kstat, *rfsproccnt_v3_kstat, *rfsproccnt_v4_kstat;
     77      0      stevel static kstat_t *rfsreqcnt_v2_kstat, *rfsreqcnt_v3_kstat, *rfsreqcnt_v4_kstat;
     78      0      stevel static kstat_t *aclproccnt_v2_kstat, *aclproccnt_v3_kstat;
     79      0      stevel static kstat_t *aclreqcnt_v2_kstat, *aclreqcnt_v3_kstat;
     80      0      stevel static kstat_t *ksum_kstat;
     81      0      stevel 
     82      0      stevel static void handle_sig(int);
     83      0      stevel static int getstats_rpc(void);
     84      0      stevel static int getstats_nfs(void);
     85      0      stevel static int getstats_rfsproc(int);
     86      0      stevel static int getstats_rfsreq(int);
     87      0      stevel static int getstats_aclproc(void);
     88      0      stevel static int getstats_aclreq(void);
     89      0      stevel static void putstats(void);
     90      0      stevel static void setup(void);
     91      0      stevel static void cr_print(int);
     92      0      stevel static void sr_print(int);
     93      0      stevel static void cn_print(int, int);
     94      0      stevel static void sn_print(int, int);
     95      0      stevel static void ca_print(int, int);
     96      0      stevel static void sa_print(int, int);
     97      0      stevel static void req_print(kstat_t *, kstat_t *, int, int, int);
     98      0      stevel static void req_print_v4(kstat_t *, kstat_t *, int, int);
     99      0      stevel static void stat_print(const char *, kstat_t *, kstat_t *, int, int);
    100  10265  Krishnendu static void nfsstat_kstat_sum(kstat_t *, kstat_t *, kstat_t *);
    101      0      stevel static void stats_timer(int);
    102      0      stevel static void safe_zalloc(void **, uint_t, int);
    103      0      stevel static int safe_strtoi(char const *, char *);
    104      0      stevel 
    105      0      stevel 
    106  10265  Krishnendu static void nfsstat_kstat_copy(kstat_t *, kstat_t *, int);
    107      0      stevel static kid_t safe_kstat_read(kstat_ctl_t *, kstat_t *, void *);
    108      0      stevel static kid_t safe_kstat_write(kstat_ctl_t *, kstat_t *, void *);
    109      0      stevel 
    110      0      stevel static void usage(void);
    111      0      stevel static void mi_print(void);
    112      0      stevel static int ignore(char *);
    113      0      stevel static int interval;		/* interval between stats */
    114      0      stevel static int count;		/* number of iterations the stat is printed */
    115      0      stevel #define	MAX_COLUMNS	80
    116      0      stevel #define	MAX_PATHS	50	/* max paths that can be taken by -m */
    117      0      stevel 
    118   5302    th199096 /*
    119   5302    th199096  * MI4_MIRRORMOUNT is canonically defined in nfs4_clnt.h, but we cannot
    120   5302    th199096  * include that file here.
    121   5302    th199096  */
    122   5302    th199096 #define	MI4_MIRRORMOUNT 0x4000
    123   5302    th199096 #define	NFS_V4		4
    124   5302    th199096 
    125      0      stevel static int req_width(kstat_t *, int);
    126      0      stevel static int stat_width(kstat_t *, int);
    127      0      stevel static char *path [MAX_PATHS] = {NULL};  /* array to store the multiple paths */
    128      0      stevel 
    129      0      stevel /*
    130      0      stevel  * Struct holds the previous kstat values so
    131      0      stevel  * we can compute deltas when using the -i flag
    132      0      stevel  */
    133      0      stevel typedef struct old_kstat
    134      0      stevel {
    135      0      stevel 	kstat_t kst;
    136      0      stevel 	int tot;
    137      0      stevel } old_kstat_t;
    138      0      stevel 
    139      0      stevel static old_kstat_t old_rpc_clts_client_kstat, old_rpc_clts_server_kstat;
    140      0      stevel static old_kstat_t old_rpc_cots_client_kstat, old_rpc_cots_server_kstat;
    141      0      stevel static old_kstat_t old_rpc_rdma_client_kstat, old_rpc_rdma_server_kstat;
    142      0      stevel static old_kstat_t old_nfs_client_kstat, old_nfs_server_v2_kstat;
    143      0      stevel static old_kstat_t old_nfs_server_v3_kstat, old_ksum_kstat;
    144      0      stevel static old_kstat_t old_nfs4_client_kstat, old_nfs_server_v4_kstat;
    145      0      stevel static old_kstat_t old_rfsproccnt_v2_kstat, old_rfsproccnt_v3_kstat;
    146      0      stevel static old_kstat_t old_rfsproccnt_v4_kstat, old_rfsreqcnt_v2_kstat;
    147      0      stevel static old_kstat_t old_rfsreqcnt_v3_kstat, old_rfsreqcnt_v4_kstat;
    148      0      stevel static old_kstat_t old_aclproccnt_v2_kstat, old_aclproccnt_v3_kstat;
    149      0      stevel static old_kstat_t old_aclreqcnt_v2_kstat, old_aclreqcnt_v3_kstat;
    150      0      stevel 
    151  10265  Krishnendu static uint_t timestamp_fmt = NODATE;
    152      0      stevel 
    153  10265  Krishnendu #if !defined(TEXT_DOMAIN)		/* Should be defined by cc -D */
    154  10265  Krishnendu #define	TEXT_DOMAIN "SYS_TEST"		/* Use this only if it isn't */
    155  10265  Krishnendu #endif
    156      0      stevel 
    157    249     jwahlig int
    158      0      stevel main(int argc, char *argv[])
    159      0      stevel {
    160      0      stevel 	int c, go_forever, j;
    161      0      stevel 	int cflag = 0;		/* client stats */
    162      0      stevel 	int sflag = 0;		/* server stats */
    163      0      stevel 	int nflag = 0;		/* nfs stats */
    164      0      stevel 	int rflag = 0;		/* rpc stats */
    165      0      stevel 	int mflag = 0;		/* mount table stats */
    166      0      stevel 	int aflag = 0;		/* print acl statistics */
    167      0      stevel 	int vflag = 0;		/* version specified, 0 specifies all */
    168      0      stevel 	int zflag = 0;		/* zero stats after printing */
    169      0      stevel 	char *split_line = "*******************************************"
    170   5302    th199096 	    "*************************************";
    171      0      stevel 
    172      0      stevel 	interval = 0;
    173      0      stevel 	count = 0;
    174      0      stevel 	go_forever = 0;
    175      0      stevel 
    176  10265  Krishnendu 	(void) setlocale(LC_ALL, "");
    177  10265  Krishnendu 	(void) textdomain(TEXT_DOMAIN);
    178  10265  Krishnendu 
    179  10265  Krishnendu 	while ((c = getopt(argc, argv, "cnrsmzav:T:")) != EOF) {
    180      0      stevel 		switch (c) {
    181      0      stevel 		case 'c':
    182      0      stevel 			cflag++;
    183      0      stevel 			break;
    184      0      stevel 		case 'n':
    185      0      stevel 			nflag++;
    186      0      stevel 			break;
    187      0      stevel 		case 'r':
    188      0      stevel 			rflag++;
    189      0      stevel 			break;
    190      0      stevel 		case 's':
    191      0      stevel 			sflag++;
    192      0      stevel 			break;
    193      0      stevel 		case 'm':
    194      0      stevel 			mflag++;
    195      0      stevel 			break;
    196      0      stevel 		case 'z':
    197      0      stevel 			if (geteuid())
    198      0      stevel 				fail(0, "Must be root for z flag\n");
    199      0      stevel 			zflag++;
    200      0      stevel 			break;
    201      0      stevel 		case 'a':
    202      0      stevel 			aflag++;
    203      0      stevel 			break;
    204      0      stevel 		case 'v':
    205      0      stevel 			vflag = atoi(optarg);
    206      0      stevel 			if ((vflag < 2) || (vflag > 4))
    207      0      stevel 				fail(0, "Invalid version number\n");
    208  10265  Krishnendu 			break;
    209  10265  Krishnendu 		case 'T':
    210  10265  Krishnendu 			if (optarg) {
    211  10265  Krishnendu 				if (*optarg == 'u')
    212  10265  Krishnendu 					timestamp_fmt = UDATE;
    213  10265  Krishnendu 				else if (*optarg == 'd')
    214  10265  Krishnendu 					timestamp_fmt = DDATE;
    215  10265  Krishnendu 				else
    216  10265  Krishnendu 					usage();
    217  10265  Krishnendu 			} else {
    218  10265  Krishnendu 				usage();
    219  10265  Krishnendu 			}
    220      0      stevel 			break;
    221      0      stevel 		case '?':
    222      0      stevel 		default:
    223      0      stevel 			usage();
    224      0      stevel 		}
    225      0      stevel 	}
    226      0      stevel 
    227      0      stevel 	if (((argc - optind) > 0) && !mflag) {
    228      0      stevel 
    229      0      stevel 		interval = safe_strtoi(argv[optind], "invalid interval");
    230      0      stevel 		if (interval < 1)
    231      0      stevel 			fail(0, "invalid interval\n");
    232      0      stevel 		optind++;
    233      0      stevel 
    234      0      stevel 		if ((argc - optind) > 0) {
    235      0      stevel 			count = safe_strtoi(argv[optind], "invalid count");
    236      0      stevel 			if ((count <= 0) || (count == NULL))
    237      0      stevel 				fail(0, "invalid count\n");
    238      0      stevel 		}
    239      0      stevel 		optind++;
    240      0      stevel 
    241      0      stevel 		if ((argc - optind) > 0)
    242      0      stevel 			usage();
    243      0      stevel 
    244      0      stevel 		/*
    245      0      stevel 		 * no count number was set, so we will loop infinitely
    246      0      stevel 		 * at interval specified
    247      0      stevel 		 */
    248      0      stevel 		if (!count)
    249      0      stevel 			go_forever = 1;
    250      0      stevel 		stats_timer(interval);
    251      0      stevel 	} else if (mflag) {
    252      0      stevel 
    253      0      stevel 		if (cflag || rflag || sflag || zflag || nflag || aflag || vflag)
    254   5302    th199096 			fail(0,
    255   5302    th199096 			    "The -m flag may not be used with any other flags");
    256      0      stevel 
    257      0      stevel 		for (j = 0; (argc - optind > 0) && (j < (MAX_PATHS - 1)); j++) {
    258      0      stevel 			path[j] =  argv[optind];
    259      0      stevel 			if (*path[j] != '/')
    260      0      stevel 				fail(0, "Please fully qualify your pathname "
    261      0      stevel 				    "with a leading '/'");
    262      0      stevel 			optind++;
    263      0      stevel 		}
    264      0      stevel 		path[j] = NULL;
    265      0      stevel 		if (argc - optind > 0)
    266      0      stevel 			fprintf(stderr, "Only the first 50 paths "
    267   5302    th199096 			    "will be searched for\n");
    268      0      stevel 	}
    269      0      stevel 
    270      0      stevel 	setup();
    271      0      stevel 
    272      0      stevel 	do {
    273      0      stevel 		if (mflag) {
    274      0      stevel 			mi_print();
    275      0      stevel 		} else {
    276  10265  Krishnendu 			if (timestamp_fmt != NODATE)
    277  10265  Krishnendu 				print_timestamp(timestamp_fmt);
    278      0      stevel 
    279      0      stevel 			if (sflag &&
    280      0      stevel 			    (rpc_clts_server_kstat == NULL ||
    281      0      stevel 			    nfs_server_v4_kstat == NULL)) {
    282      0      stevel 				fprintf(stderr,
    283      0      stevel 				    "nfsstat: kernel is not configured with "
    284      0      stevel 				    "the server nfs and rpc code.\n");
    285      0      stevel 			}
    286      0      stevel 
    287      0      stevel 			/* if s and nothing else, all 3 prints are called */
    288      0      stevel 			if (sflag || (!sflag && !cflag)) {
    289      0      stevel 				if (rflag || (!rflag && !nflag && !aflag))
    290      0      stevel 					sr_print(zflag);
    291      0      stevel 				if (nflag || (!rflag && !nflag && !aflag))
    292      0      stevel 					sn_print(zflag, vflag);
    293      0      stevel 				if (aflag || (!rflag && !nflag && !aflag))
    294      0      stevel 					sa_print(zflag, vflag);
    295      0      stevel 			}
    296      0      stevel 			if (cflag &&
    297      0      stevel 			    (rpc_clts_client_kstat == NULL ||
    298      0      stevel 			    nfs_client_kstat == NULL)) {
    299      0      stevel 				fprintf(stderr,
    300   5302    th199096 				    "nfsstat: kernel is not configured with"
    301   5302    th199096 				    " the client nfs and rpc code.\n");
    302      0      stevel 			}
    303      0      stevel 			if (cflag || (!sflag && !cflag)) {
    304      0      stevel 				if (rflag || (!rflag && !nflag && !aflag))
    305      0      stevel 					cr_print(zflag);
    306      0      stevel 				if (nflag || (!rflag && !nflag && !aflag))
    307      0      stevel 					cn_print(zflag, vflag);
    308      0      stevel 				if (aflag || (!rflag && !nflag && !aflag))
    309      0      stevel 					ca_print(zflag, vflag);
    310      0      stevel 			}
    311      0      stevel 		}
    312      0      stevel 
    313      0      stevel 		if (zflag)
    314      0      stevel 			putstats();
    315      0      stevel 		if (interval)
    316      0      stevel 			printf("%s\n", split_line);
    317      0      stevel 
    318      0      stevel 		if (interval > 0)
    319      0      stevel 			(void) pause();
    320      0      stevel 	} while ((--count > 0) || go_forever);
    321      0      stevel 
    322      0      stevel 	kstat_close(kc);
    323      0      stevel 	free(ksum_kstat);
    324      0      stevel 	return (0);
    325      0      stevel }
    326      0      stevel 
    327      0      stevel 
    328      0      stevel static int
    329      0      stevel getstats_rpc(void)
    330      0      stevel {
    331      0      stevel 	int field_width = 0;
    332      0      stevel 
    333      0      stevel 	if (rpc_clts_client_kstat != NULL) {
    334      0      stevel 		safe_kstat_read(kc, rpc_clts_client_kstat, NULL);
    335      0      stevel 		field_width = stat_width(rpc_clts_client_kstat, field_width);
    336      0      stevel 	}
    337      0      stevel 
    338      0      stevel 	if (rpc_cots_client_kstat != NULL) {
    339      0      stevel 		safe_kstat_read(kc, rpc_cots_client_kstat, NULL);
    340      0      stevel 		field_width = stat_width(rpc_cots_client_kstat, field_width);
    341      0      stevel 	}
    342      0      stevel 
    343      0      stevel 	if (rpc_rdma_client_kstat != NULL) {
    344      0      stevel 		safe_kstat_read(kc, rpc_rdma_client_kstat, NULL);
    345      0      stevel 		field_width = stat_width(rpc_rdma_client_kstat, field_width);
    346      0      stevel 	}
    347      0      stevel 
    348      0      stevel 	if (rpc_clts_server_kstat != NULL) {
    349      0      stevel 		safe_kstat_read(kc, rpc_clts_server_kstat, NULL);
    350      0      stevel 		field_width =  stat_width(rpc_clts_server_kstat, field_width);
    351      0      stevel 	}
    352      0      stevel 	if (rpc_cots_server_kstat != NULL) {
    353      0      stevel 		safe_kstat_read(kc, rpc_cots_server_kstat, NULL);
    354      0      stevel 		field_width = stat_width(rpc_cots_server_kstat, field_width);
    355      0      stevel 	}
    356      0      stevel 	if (rpc_rdma_server_kstat != NULL) {
    357      0      stevel 		safe_kstat_read(kc, rpc_rdma_server_kstat, NULL);
    358      0      stevel 		field_width = stat_width(rpc_rdma_server_kstat, field_width);
    359      0      stevel 	}
    360      0      stevel 	return (field_width);
    361      0      stevel }
    362      0      stevel 
    363      0      stevel static int
    364      0      stevel getstats_nfs(void)
    365      0      stevel {
    366      0      stevel 	int field_width = 0;
    367      0      stevel 
    368      0      stevel 	if (nfs_client_kstat != NULL) {
    369      0      stevel 		safe_kstat_read(kc, nfs_client_kstat, NULL);
    370      0      stevel 		field_width = stat_width(nfs_client_kstat, field_width);
    371      0      stevel 	}
    372      0      stevel 	if (nfs4_client_kstat != NULL) {
    373      0      stevel 		safe_kstat_read(kc, nfs4_client_kstat, NULL);
    374      0      stevel 		field_width = stat_width(nfs4_client_kstat, field_width);
    375      0      stevel 	}
    376      0      stevel 	if (nfs_server_v2_kstat != NULL) {
    377      0      stevel 		safe_kstat_read(kc, nfs_server_v2_kstat, NULL);
    378      0      stevel 		field_width = stat_width(nfs_server_v2_kstat, field_width);
    379      0      stevel 	}
    380      0      stevel 	if (nfs_server_v3_kstat != NULL) {
    381      0      stevel 		safe_kstat_read(kc, nfs_server_v3_kstat, NULL);
    382      0      stevel 		field_width = stat_width(nfs_server_v3_kstat, field_width);
    383      0      stevel 	}
    384      0      stevel 	if (nfs_server_v4_kstat != NULL) {
    385      0      stevel 		safe_kstat_read(kc, nfs_server_v4_kstat, NULL);
    386      0      stevel 		field_width = stat_width(nfs_server_v4_kstat, field_width);
    387      0      stevel 	}
    388      0      stevel 	return (field_width);
    389      0      stevel }
    390      0      stevel 
    391      0      stevel static int
    392      0      stevel getstats_rfsproc(int ver)
    393      0      stevel {
    394      0      stevel 	int field_width = 0;
    395      0      stevel 
    396      0      stevel 	if ((ver == 2) && (rfsproccnt_v2_kstat != NULL)) {
    397      0      stevel 		safe_kstat_read(kc, rfsproccnt_v2_kstat, NULL);
    398      0      stevel 		field_width = req_width(rfsproccnt_v2_kstat, field_width);
    399      0      stevel 	}
    400      0      stevel 	if ((ver == 3) && (rfsproccnt_v3_kstat != NULL)) {
    401      0      stevel 		safe_kstat_read(kc, rfsproccnt_v3_kstat, NULL);
    402      0      stevel 		field_width = req_width(rfsproccnt_v3_kstat, field_width);
    403      0      stevel 	}
    404      0      stevel 	if ((ver == 4) && (rfsproccnt_v4_kstat != NULL)) {
    405      0      stevel 		safe_kstat_read(kc, rfsproccnt_v4_kstat, NULL);
    406      0      stevel 		field_width = req_width(rfsproccnt_v4_kstat, field_width);
    407      0      stevel 	}
    408      0      stevel 	return (field_width);
    409      0      stevel }
    410      0      stevel 
    411      0      stevel static int
    412      0      stevel getstats_rfsreq(int ver)
    413      0      stevel {
    414      0      stevel 	int field_width = 0;
    415      0      stevel 	if ((ver == 2) && (rfsreqcnt_v2_kstat != NULL)) {
    416      0      stevel 		safe_kstat_read(kc, rfsreqcnt_v2_kstat, NULL);
    417      0      stevel 		field_width = req_width(rfsreqcnt_v2_kstat, field_width);
    418      0      stevel 	}
    419      0      stevel 	if ((ver == 3) && (rfsreqcnt_v3_kstat != NULL)) {
    420      0      stevel 		safe_kstat_read(kc, rfsreqcnt_v3_kstat, NULL);
    421      0      stevel 		field_width = req_width(rfsreqcnt_v3_kstat,  field_width);
    422      0      stevel 	}
    423      0      stevel 	if ((ver == 4) && (rfsreqcnt_v4_kstat != NULL)) {
    424      0      stevel 		safe_kstat_read(kc, rfsreqcnt_v4_kstat, NULL);
    425      0      stevel 		field_width = req_width(rfsreqcnt_v4_kstat, field_width);
    426      0      stevel 	}
    427      0      stevel 	return (field_width);
    428      0      stevel }
    429      0      stevel 
    430      0      stevel static int
    431      0      stevel getstats_aclproc(void)
    432      0      stevel {
    433      0      stevel 	int field_width = 0;
    434      0      stevel 	if (aclproccnt_v2_kstat != NULL) {
    435      0      stevel 		safe_kstat_read(kc, aclproccnt_v2_kstat, NULL);
    436      0      stevel 		field_width = req_width(aclproccnt_v2_kstat, field_width);
    437      0      stevel 	}
    438      0      stevel 	if (aclproccnt_v3_kstat != NULL) {
    439      0      stevel 		safe_kstat_read(kc, aclproccnt_v3_kstat, NULL);
    440      0      stevel 		field_width = req_width(aclproccnt_v3_kstat, field_width);
    441      0      stevel 	}
    442      0      stevel 	return (field_width);
    443      0      stevel }
    444      0      stevel 
    445      0      stevel static int
    446      0      stevel getstats_aclreq(void)
    447      0      stevel {
    448      0      stevel 	int field_width = 0;
    449      0      stevel 	if (aclreqcnt_v2_kstat != NULL) {
    450      0      stevel 		safe_kstat_read(kc, aclreqcnt_v2_kstat, NULL);
    451      0      stevel 		field_width = req_width(aclreqcnt_v2_kstat, field_width);
    452      0      stevel 	}
    453      0      stevel 	if (aclreqcnt_v3_kstat != NULL) {
    454      0      stevel 		safe_kstat_read(kc, aclreqcnt_v3_kstat, NULL);
    455      0      stevel 		field_width = req_width(aclreqcnt_v3_kstat, field_width);
    456      0      stevel 	}
    457      0      stevel 	return (field_width);
    458      0      stevel }
    459      0      stevel 
    460      0      stevel static void
    461      0      stevel putstats(void)
    462      0      stevel {
    463      0      stevel 	if (rpc_clts_client_kstat != NULL)
    464      0      stevel 		safe_kstat_write(kc, rpc_clts_client_kstat, NULL);
    465      0      stevel 	if (rpc_cots_client_kstat != NULL)
    466      0      stevel 		safe_kstat_write(kc, rpc_cots_client_kstat, NULL);
    467      0      stevel 	if (rpc_rdma_client_kstat != NULL)
    468      0      stevel 		safe_kstat_write(kc, rpc_rdma_client_kstat, NULL);
    469      0      stevel 	if (nfs_client_kstat != NULL)
    470      0      stevel 		safe_kstat_write(kc, nfs_client_kstat, NULL);
    471      0      stevel 	if (nfs4_client_kstat != NULL)
    472      0      stevel 		safe_kstat_write(kc, nfs4_client_kstat, NULL);
    473      0      stevel 	if (rpc_clts_server_kstat != NULL)
    474      0      stevel 		safe_kstat_write(kc, rpc_clts_server_kstat, NULL);
    475      0      stevel 	if (rpc_cots_server_kstat != NULL)
    476      0      stevel 		safe_kstat_write(kc, rpc_cots_server_kstat, NULL);
    477      0      stevel 	if (rpc_rdma_server_kstat != NULL)
    478      0      stevel 		safe_kstat_write(kc, rpc_rdma_server_kstat, NULL);
    479      0      stevel 	if (nfs_server_v2_kstat != NULL)
    480      0      stevel 		safe_kstat_write(kc, nfs_server_v2_kstat, NULL);
    481      0      stevel 	if (nfs_server_v3_kstat != NULL)
    482      0      stevel 		safe_kstat_write(kc, nfs_server_v3_kstat, NULL);
    483      0      stevel 	if (nfs_server_v4_kstat != NULL)
    484      0      stevel 		safe_kstat_write(kc, nfs_server_v4_kstat, NULL);
    485      0      stevel 	if (rfsproccnt_v2_kstat != NULL)
    486      0      stevel 		safe_kstat_write(kc, rfsproccnt_v2_kstat, NULL);
    487      0      stevel 	if (rfsproccnt_v3_kstat != NULL)
    488      0      stevel 		safe_kstat_write(kc, rfsproccnt_v3_kstat, NULL);
    489      0      stevel 	if (rfsproccnt_v4_kstat != NULL)
    490      0      stevel 		safe_kstat_write(kc, rfsproccnt_v4_kstat, NULL);
    491      0      stevel 	if (rfsreqcnt_v2_kstat != NULL)
    492      0      stevel 		safe_kstat_write(kc, rfsreqcnt_v2_kstat, NULL);
    493      0      stevel 	if (rfsreqcnt_v3_kstat != NULL)
    494      0      stevel 		safe_kstat_write(kc, rfsreqcnt_v3_kstat, NULL);
    495      0      stevel 	if (rfsreqcnt_v4_kstat != NULL)
    496      0      stevel 		safe_kstat_write(kc, rfsreqcnt_v4_kstat, NULL);
    497      0      stevel 	if (aclproccnt_v2_kstat != NULL)
    498      0      stevel 		safe_kstat_write(kc, aclproccnt_v2_kstat, NULL);
    499      0      stevel 	if (aclproccnt_v3_kstat != NULL)
    500      0      stevel 		safe_kstat_write(kc, aclproccnt_v3_kstat, NULL);
    501      0      stevel 	if (aclreqcnt_v2_kstat != NULL)
    502      0      stevel 		safe_kstat_write(kc, aclreqcnt_v2_kstat, NULL);
    503      0      stevel 	if (aclreqcnt_v3_kstat != NULL)
    504      0      stevel 		safe_kstat_write(kc, aclreqcnt_v3_kstat, NULL);
    505      0      stevel }
    506      0      stevel 
    507      0      stevel static void
    508      0      stevel setup(void)
    509      0      stevel {
    510      0      stevel 	if ((kc = kstat_open()) == NULL)
    511      0      stevel 		fail(1, "kstat_open(): can't open /dev/kstat");
    512      0      stevel 
    513  10429      Marcel 	/* alloc space for our temporary kstat */
    514  10429      Marcel 	safe_zalloc((void **)&ksum_kstat, sizeof (kstat_t), 0);
    515      0      stevel 	rpc_clts_client_kstat = kstat_lookup(kc, "unix", 0, "rpc_clts_client");
    516      0      stevel 	rpc_clts_server_kstat = kstat_lookup(kc, "unix", 0, "rpc_clts_server");
    517      0      stevel 	rpc_cots_client_kstat = kstat_lookup(kc, "unix", 0, "rpc_cots_client");
    518      0      stevel 	rpc_cots_server_kstat = kstat_lookup(kc, "unix", 0, "rpc_cots_server");
    519      0      stevel 	rpc_rdma_client_kstat = kstat_lookup(kc, "unix", 0, "rpc_rdma_client");
    520      0      stevel 	rpc_rdma_server_kstat = kstat_lookup(kc, "unix", 0, "rpc_rdma_server");
    521      0      stevel 	nfs_client_kstat = kstat_lookup(kc, "nfs", 0, "nfs_client");
    522      0      stevel 	nfs4_client_kstat = kstat_lookup(kc, "nfs", 0, "nfs4_client");
    523      0      stevel 	nfs_server_v2_kstat = kstat_lookup(kc, "nfs", 2, "nfs_server");
    524      0      stevel 	nfs_server_v3_kstat = kstat_lookup(kc, "nfs", 3, "nfs_server");
    525      0      stevel 	nfs_server_v4_kstat = kstat_lookup(kc, "nfs", 4, "nfs_server");
    526      0      stevel 	rfsproccnt_v2_kstat = kstat_lookup(kc, "nfs", 0, "rfsproccnt_v2");
    527      0      stevel 	rfsproccnt_v3_kstat = kstat_lookup(kc, "nfs", 0, "rfsproccnt_v3");
    528      0      stevel 	rfsproccnt_v4_kstat = kstat_lookup(kc, "nfs", 0, "rfsproccnt_v4");
    529      0      stevel 	rfsreqcnt_v2_kstat = kstat_lookup(kc, "nfs", 0, "rfsreqcnt_v2");
    530      0      stevel 	rfsreqcnt_v3_kstat = kstat_lookup(kc, "nfs", 0, "rfsreqcnt_v3");
    531      0      stevel 	rfsreqcnt_v4_kstat = kstat_lookup(kc, "nfs", 0, "rfsreqcnt_v4");
    532      0      stevel 	aclproccnt_v2_kstat = kstat_lookup(kc, "nfs_acl", 0, "aclproccnt_v2");
    533      0      stevel 	aclproccnt_v3_kstat = kstat_lookup(kc, "nfs_acl", 0, "aclproccnt_v3");
    534      0      stevel 	aclreqcnt_v2_kstat = kstat_lookup(kc, "nfs_acl", 0, "aclreqcnt_v2");
    535      0      stevel 	aclreqcnt_v3_kstat = kstat_lookup(kc, "nfs_acl", 0, "aclreqcnt_v3");
    536      0      stevel 	if (rpc_clts_client_kstat == NULL && rpc_cots_server_kstat == NULL &&
    537      0      stevel 	    rfsproccnt_v2_kstat == NULL && rfsreqcnt_v3_kstat == NULL)
    538      0      stevel 		fail(0, "Multiple kstat lookups failed."
    539   3406    th199096 		    "Your kernel module may not be loaded\n");
    540      0      stevel }
    541      0      stevel 
    542      0      stevel static int
    543      0      stevel req_width(kstat_t *req, int field_width)
    544      0      stevel {
    545      0      stevel 	int i, nreq, per, len;
    546      0      stevel 	char fixlen[128];
    547      0      stevel 	kstat_named_t *knp;
    548      0      stevel 	uint64_t tot;
    549      0      stevel 
    550      0      stevel 	tot = 0;
    551      0      stevel 	knp = KSTAT_NAMED_PTR(req);
    552      0      stevel 	for (i = 0; i < req->ks_ndata; i++)
    553      0      stevel 		tot += knp[i].value.ui64;
    554      0      stevel 
    555      0      stevel 	knp = kstat_data_lookup(req, "null");
    556      0      stevel 	nreq = req->ks_ndata - (knp - KSTAT_NAMED_PTR(req));
    557      0      stevel 
    558      0      stevel 	for (i = 0; i < nreq; i++) {
    559      0      stevel 		len = strlen(knp[i].name) + 1;
    560      0      stevel 		if (field_width < len)
    561      0      stevel 			field_width = len;
    562      0      stevel 		if (tot)
    563      0      stevel 			per = (int)(knp[i].value.ui64 * 100 / tot);
    564      0      stevel 		else
    565      0      stevel 			per = 0;
    566      0      stevel 		(void) sprintf(fixlen, "%" PRIu64 " %d%%",
    567   5302    th199096 		    knp[i].value.ui64, per);
    568      0      stevel 		len = strlen(fixlen) + 1;
    569      0      stevel 		if (field_width < len)
    570      0      stevel 			field_width = len;
    571      0      stevel 	}
    572      0      stevel 	return (field_width);
    573      0      stevel }
    574      0      stevel 
    575      0      stevel static int
    576      0      stevel stat_width(kstat_t *req, int field_width)
    577      0      stevel {
    578      0      stevel 	int i, nreq, len;
    579      0      stevel 	char fixlen[128];
    580      0      stevel 	kstat_named_t *knp;
    581      0      stevel 
    582      0      stevel 	knp = KSTAT_NAMED_PTR(req);
    583      0      stevel 	nreq = req->ks_ndata;
    584      0      stevel 
    585      0      stevel 	for (i = 0; i < nreq; i++) {
    586      0      stevel 		len = strlen(knp[i].name) + 1;
    587      0      stevel 		if (field_width < len)
    588      0      stevel 			field_width = len;
    589      0      stevel 		(void) sprintf(fixlen, "%" PRIu64, knp[i].value.ui64);
    590      0      stevel 		len = strlen(fixlen) + 1;
    591      0      stevel 		if (field_width < len)
    592      0      stevel 			field_width = len;
    593      0      stevel 	}
    594      0      stevel 	return (field_width);
    595      0      stevel }
    596      0      stevel 
    597      0      stevel static void
    598      0      stevel cr_print(int zflag)
    599      0      stevel {
    600      0      stevel 	int field_width;
    601      0      stevel 
    602      0      stevel 	field_width = getstats_rpc();
    603   3406    th199096 	if (field_width == 0)
    604   3406    th199096 		return;
    605   3406    th199096 
    606      0      stevel 	stat_print("\nClient rpc:\nConnection oriented:",
    607   5302    th199096 	    rpc_cots_client_kstat,
    608   5302    th199096 	    &old_rpc_cots_client_kstat.kst, field_width, zflag);
    609      0      stevel 	stat_print("Connectionless:", rpc_clts_client_kstat,
    610   5302    th199096 	    &old_rpc_clts_client_kstat.kst, field_width, zflag);
    611      0      stevel 	stat_print("RDMA based:", rpc_rdma_client_kstat,
    612   5302    th199096 	    &old_rpc_rdma_client_kstat.kst, field_width, zflag);
    613      0      stevel }
    614      0      stevel 
    615      0      stevel static void
    616      0      stevel sr_print(int zflag)
    617      0      stevel {
    618      0      stevel 	int field_width;
    619      0      stevel 
    620      0      stevel 	field_width = getstats_rpc();
    621   3406    th199096 	if (field_width == 0)
    622   3406    th199096 		return;
    623   3406    th199096 
    624      0      stevel 	stat_print("\nServer rpc:\nConnection oriented:", rpc_cots_server_kstat,
    625   5302    th199096 	    &old_rpc_cots_server_kstat.kst, field_width, zflag);
    626      0      stevel 	stat_print("Connectionless:", rpc_clts_server_kstat,
    627   5302    th199096 	    &old_rpc_clts_server_kstat.kst, field_width, zflag);
    628      0      stevel 	stat_print("RDMA based:", rpc_rdma_server_kstat,
    629   5302    th199096 	    &old_rpc_rdma_server_kstat.kst, field_width, zflag);
    630      0      stevel }
    631      0      stevel 
    632      0      stevel static void
    633      0      stevel cn_print(int zflag, int vflag)
    634      0      stevel {
    635      0      stevel 	int field_width;
    636      0      stevel 
    637      0      stevel 	field_width = getstats_nfs();
    638   3406    th199096 	if (field_width == 0)
    639   3406    th199096 		return;
    640      0      stevel 
    641      0      stevel 	if (vflag == 0) {
    642  10265  Krishnendu 		nfsstat_kstat_sum(nfs_client_kstat, nfs4_client_kstat,
    643  10265  Krishnendu 		    ksum_kstat);
    644      0      stevel 		stat_print("\nClient nfs:", ksum_kstat, &old_ksum_kstat.kst,
    645   5302    th199096 		    field_width, zflag);
    646      0      stevel 	}
    647      0      stevel 
    648      0      stevel 	if (vflag == 2 || vflag == 3) {
    649      0      stevel 		stat_print("\nClient nfs:", nfs_client_kstat,
    650   5302    th199096 		    &old_nfs_client_kstat.kst, field_width, zflag);
    651      0      stevel 	}
    652      0      stevel 
    653      0      stevel 	if (vflag == 4) {
    654      0      stevel 		stat_print("\nClient nfs:", nfs4_client_kstat,
    655   5302    th199096 		    &old_nfs4_client_kstat.kst, field_width, zflag);
    656      0      stevel 	}
    657      0      stevel 
    658      0      stevel 	if (vflag == 2 || vflag == 0) {
    659      0      stevel 		field_width = getstats_rfsreq(2);
    660      0      stevel 		req_print(rfsreqcnt_v2_kstat, &old_rfsreqcnt_v2_kstat.kst,
    661   5302    th199096 		    2, field_width, zflag);
    662      0      stevel 	}
    663      0      stevel 
    664      0      stevel 	if (vflag == 3 || vflag == 0) {
    665      0      stevel 		field_width = getstats_rfsreq(3);
    666      0      stevel 		req_print(rfsreqcnt_v3_kstat, &old_rfsreqcnt_v3_kstat.kst, 3,
    667   5302    th199096 		    field_width, zflag);
    668      0      stevel 	}
    669      0      stevel 
    670      0      stevel 	if (vflag == 4 || vflag == 0) {
    671      0      stevel 		field_width = getstats_rfsreq(4);
    672      0      stevel 		req_print_v4(rfsreqcnt_v4_kstat, &old_rfsreqcnt_v4_kstat.kst,
    673   5302    th199096 		    field_width, zflag);
    674      0      stevel 	}
    675      0      stevel }
    676      0      stevel 
    677      0      stevel static void
    678      0      stevel sn_print(int zflag, int vflag)
    679      0      stevel {
    680      0      stevel 	int  field_width;
    681      0      stevel 
    682      0      stevel 	field_width = getstats_nfs();
    683   3406    th199096 	if (field_width == 0)
    684   3406    th199096 		return;
    685   3406    th199096 
    686      0      stevel 	if (vflag == 2 || vflag == 0) {
    687      0      stevel 		stat_print("\nServer NFSv2:", nfs_server_v2_kstat,
    688   5302    th199096 		    &old_nfs_server_v2_kstat.kst, field_width, zflag);
    689      0      stevel 	}
    690      0      stevel 
    691      0      stevel 	if (vflag == 3 || vflag == 0) {
    692      0      stevel 		stat_print("\nServer NFSv3:", nfs_server_v3_kstat,
    693   5302    th199096 		    &old_nfs_server_v3_kstat.kst, field_width, zflag);
    694      0      stevel 	}
    695      0      stevel 
    696      0      stevel 	if (vflag == 4 || vflag == 0) {
    697      0      stevel 		stat_print("\nServer NFSv4:", nfs_server_v4_kstat,
    698   5302    th199096 		    &old_nfs_server_v4_kstat.kst, field_width, zflag);
    699      0      stevel 	}
    700      0      stevel 
    701      0      stevel 	if (vflag == 2 || vflag == 0) {
    702      0      stevel 		field_width = getstats_rfsproc(2);
    703      0      stevel 		req_print(rfsproccnt_v2_kstat, &old_rfsproccnt_v2_kstat.kst,
    704   5302    th199096 		    2, field_width, zflag);
    705      0      stevel 	}
    706      0      stevel 
    707      0      stevel 	if (vflag == 3 || vflag == 0) {
    708      0      stevel 		field_width = getstats_rfsproc(3);
    709      0      stevel 		req_print(rfsproccnt_v3_kstat, &old_rfsproccnt_v3_kstat.kst,
    710   5302    th199096 		    3, field_width, zflag);
    711      0      stevel 	}
    712      0      stevel 
    713      0      stevel 	if (vflag == 4 || vflag == 0) {
    714      0      stevel 		field_width = getstats_rfsproc(4);
    715      0      stevel 		req_print_v4(rfsproccnt_v4_kstat, &old_rfsproccnt_v4_kstat.kst,
    716   5302    th199096 		    field_width, zflag);
    717      0      stevel 	}
    718      0      stevel }
    719      0      stevel 
    720      0      stevel static void
    721      0      stevel ca_print(int zflag, int vflag)
    722      0      stevel {
    723      0      stevel 	int  field_width;
    724      0      stevel 
    725      0      stevel 	field_width = getstats_aclreq();
    726   3406    th199096 	if (field_width == 0)
    727   3406    th199096 		return;
    728   3406    th199096 
    729      0      stevel 	printf("\nClient nfs_acl:\n");
    730      0      stevel 
    731      0      stevel 	if (vflag == 2 || vflag == 0) {
    732      0      stevel 		req_print(aclreqcnt_v2_kstat, &old_aclreqcnt_v2_kstat.kst, 2,
    733   5302    th199096 		    field_width, zflag);
    734      0      stevel 	}
    735      0      stevel 
    736      0      stevel 	if (vflag == 3 || vflag == 0) {
    737      0      stevel 		req_print(aclreqcnt_v3_kstat, &old_aclreqcnt_v3_kstat.kst,
    738   5302    th199096 		    3, field_width, zflag);
    739      0      stevel 	}
    740      0      stevel }
    741      0      stevel 
    742      0      stevel static void
    743      0      stevel sa_print(int zflag, int vflag)
    744      0      stevel {
    745      0      stevel 	int  field_width;
    746      0      stevel 
    747      0      stevel 	field_width = getstats_aclproc();
    748   3406    th199096 	if (field_width == 0)
    749   3406    th199096 		return;
    750      0      stevel 
    751      0      stevel 	printf("\nServer nfs_acl:\n");
    752      0      stevel 
    753      0      stevel 	if (vflag == 2 || vflag == 0) {
    754      0      stevel 		req_print(aclproccnt_v2_kstat, &old_aclproccnt_v2_kstat.kst,
    755   5302    th199096 		    2, field_width, zflag);
    756      0      stevel 	}
    757      0      stevel 
    758      0      stevel 	if (vflag == 3 || vflag == 0) {
    759      0      stevel 		req_print(aclproccnt_v3_kstat, &old_aclproccnt_v3_kstat.kst,
    760   5302    th199096 		    3, field_width, zflag);
    761      0      stevel 	}
    762      0      stevel }
    763      0      stevel 
    764      0      stevel #define	MIN(a, b)	((a) < (b) ? (a) : (b))
    765      0      stevel 
    766      0      stevel static void
    767      0      stevel req_print(kstat_t *req, kstat_t *req_old, int ver, int field_width,
    768   5302    th199096     int zflag)
    769      0      stevel {
    770      0      stevel 	int i, j, nreq, per, ncolumns;
    771      0      stevel 	uint64_t tot, old_tot;
    772      0      stevel 	char fixlen[128];
    773      0      stevel 	kstat_named_t *knp;
    774      0      stevel 	kstat_named_t *kptr;
    775      0      stevel 	kstat_named_t *knp_old;
    776      0      stevel 
    777      0      stevel 	if (req == NULL)
    778      0      stevel 		return;
    779      0      stevel 
    780   3406    th199096 	if (field_width == 0)
    781   3406    th199096 		return;
    782   3406    th199096 
    783      0      stevel 	ncolumns = (MAX_COLUMNS -1)/field_width;
    784      0      stevel 	knp = kstat_data_lookup(req, "null");
    785      0      stevel 	knp_old = KSTAT_NAMED_PTR(req_old);
    786      0      stevel 
    787      0      stevel 	kptr = KSTAT_NAMED_PTR(req);
    788      0      stevel 	nreq = req->ks_ndata - (knp - KSTAT_NAMED_PTR(req));
    789      0      stevel 
    790      0      stevel 	tot = 0;
    791      0      stevel 	old_tot = 0;
    792      0      stevel 
    793      0      stevel 	if (knp_old == NULL) {
    794      0      stevel 		old_tot = 0;
    795      0      stevel 	}
    796      0      stevel 
    797      0      stevel 	for (i = 0; i < req->ks_ndata; i++)
    798      0      stevel 		tot += kptr[i].value.ui64;
    799      0      stevel 
    800      0      stevel 	if (interval && knp_old != NULL) {
    801      0      stevel 		for (i = 0; i < req_old->ks_ndata; i++)
    802      0      stevel 			old_tot += knp_old[i].value.ui64;
    803      0      stevel 		tot -= old_tot;
    804      0      stevel 	}
    805      0      stevel 
    806      0      stevel 	printf("Version %d: (%" PRIu64 " calls)\n", ver, tot);
    807      0      stevel 
    808      0      stevel 	for (i = 0; i < nreq; i += ncolumns) {
    809      0      stevel 		for (j = i; j < MIN(i + ncolumns, nreq); j++) {
    810      0      stevel 			printf("%-*s", field_width, knp[j].name);
    811      0      stevel 		}
    812      0      stevel 		printf("\n");
    813      0      stevel 		for (j = i; j < MIN(i + ncolumns, nreq); j++) {
    814      0      stevel 			if (tot && interval && knp_old != NULL)
    815      0      stevel 				per = (int)((knp[j].value.ui64 -
    816      0      stevel 				    knp_old[j].value.ui64) * 100 / tot);
    817      0      stevel 			else if (tot)
    818      0      stevel 				per = (int)(knp[j].value.ui64 * 100 / tot);
    819      0      stevel 			else
    820      0      stevel 				per = 0;
    821      0      stevel 			(void) sprintf(fixlen, "%" PRIu64 " %d%% ",
    822   5302    th199096 			    ((interval && knp_old != NULL) ?
    823   5302    th199096 			    (knp[j].value.ui64 - knp_old[j].value.ui64)
    824   5302    th199096 			    : knp[j].value.ui64), per);
    825      0      stevel 			printf("%-*s", field_width, fixlen);
    826      0      stevel 		}
    827      0      stevel 		printf("\n");
    828      0      stevel 	}
    829   5998     gt29601 	if (zflag) {
    830   5998     gt29601 		for (i = 0; i < req->ks_ndata; i++)
    831   5998     gt29601 			knp[i].value.ui64 = 0;
    832   5998     gt29601 	}
    833   5998     gt29601 	if (knp_old != NULL)
    834  10265  Krishnendu 		nfsstat_kstat_copy(req, req_old, 1);
    835   5998     gt29601 	else
    836  10265  Krishnendu 		nfsstat_kstat_copy(req, req_old, 0);
    837      0      stevel }
    838      0      stevel 
    839      0      stevel /*
    840      0      stevel  * Separate version of the req_print() to deal with V4 and its use of
    841      0      stevel  * procedures and operations.  It looks odd to have the counts for
    842      0      stevel  * both of those lumped into the same set of statistics so this
    843      0      stevel  * function (copy of req_print() does the separation and titles).
    844      0      stevel  */
    845      0      stevel 
    846      0      stevel #define	COUNT	2
    847      0      stevel 
    848      0      stevel static void
    849      0      stevel req_print_v4(kstat_t *req, kstat_t *req_old, int field_width, int zflag)
    850      0      stevel {
    851      0      stevel 	int i, j, nreq, per, ncolumns;
    852      0      stevel 	uint64_t tot, tot_ops, old_tot, old_tot_ops;
    853      0      stevel 	char fixlen[128];
    854      0      stevel 	kstat_named_t *kptr;
    855      0      stevel 	kstat_named_t *knp;
    856      0      stevel 	kstat_named_t *kptr_old;
    857      0      stevel 
    858      0      stevel 	if (req == NULL)
    859   3406    th199096 		return;
    860   3406    th199096 
    861   3406    th199096 	if (field_width == 0)
    862      0      stevel 		return;
    863      0      stevel 
    864      0      stevel 	ncolumns = (MAX_COLUMNS)/field_width;
    865      0      stevel 	kptr = KSTAT_NAMED_PTR(req);
    866      0      stevel 	kptr_old = KSTAT_NAMED_PTR(req_old);
    867      0      stevel 
    868      0      stevel 	if (kptr_old == NULL) {
    869      0      stevel 		old_tot_ops = 0;
    870      0      stevel 		old_tot = 0;
    871      0      stevel 	} else {
    872      0      stevel 		old_tot =  kptr_old[0].value.ui64 + kptr_old[1].value.ui64;
    873      0      stevel 		for (i = 2, old_tot_ops = 0; i < req_old->ks_ndata; i++)
    874      0      stevel 			old_tot_ops += kptr_old[i].value.ui64;
    875      0      stevel 	}
    876      0      stevel 
    877      0      stevel 	/* Count the number of operations sent */
    878      0      stevel 	for (i = 2, tot_ops = 0; i < req->ks_ndata; i++)
    879      0      stevel 		tot_ops += kptr[i].value.ui64;
    880      0      stevel 	/* For v4 NULL/COMPOUND are the only procedures */
    881      0      stevel 	tot = kptr[0].value.ui64 + kptr[1].value.ui64;
    882      0      stevel 
    883      0      stevel 	if (interval) {
    884      0      stevel 		tot -= old_tot;
    885      0      stevel 		tot_ops -= old_tot_ops;
    886      0      stevel 	}
    887      0      stevel 
    888      0      stevel 	printf("Version 4: (%" PRIu64 " calls)\n", tot);
    889      0      stevel 
    890      0      stevel 	knp = kstat_data_lookup(req, "null");
    891      0      stevel 	nreq = req->ks_ndata - (knp - KSTAT_NAMED_PTR(req));
    892      0      stevel 
    893      0      stevel 	for (i = 0; i < COUNT; i += ncolumns) {
    894      0      stevel 		for (j = i; j < MIN(i + ncolumns, 2); j++) {
    895      0      stevel 			printf("%-*s", field_width, knp[j].name);
    896      0      stevel 		}
    897      0      stevel 		printf("\n");
    898      0      stevel 		for (j = i; j < MIN(i + ncolumns, 2); j++) {
    899      0      stevel 			if (tot && interval && kptr_old != NULL)
    900      0      stevel 				per = (int)((knp[j].value.ui64 -
    901      0      stevel 				    kptr_old[j].value.ui64) * 100 / tot);
    902      0      stevel 			else if (tot)
    903      0      stevel 				per = (int)(knp[j].value.ui64 * 100 / tot);
    904      0      stevel 			else
    905      0      stevel 				per = 0;
    906      0      stevel 			(void) sprintf(fixlen, "%" PRIu64 " %d%% ",
    907   5302    th199096 			    ((interval && kptr_old != NULL) ?
    908   5302    th199096 			    (knp[j].value.ui64 - kptr_old[j].value.ui64)
    909   5302    th199096 			    : knp[j].value.ui64), per);
    910      0      stevel 			printf("%-*s", field_width, fixlen);
    911      0      stevel 		}
    912      0      stevel 		printf("\n");
    913      0      stevel 	}
    914      0      stevel 
    915      0      stevel 	printf("Version 4: (%" PRIu64 " operations)\n", tot_ops);
    916      0      stevel 	for (i = 2; i < nreq; i += ncolumns) {
    917      0      stevel 		for (j = i; j < MIN(i + ncolumns, nreq); j++) {
    918      0      stevel 			printf("%-*s", field_width, knp[j].name);
    919      0      stevel 		}
    920      0      stevel 		printf("\n");
    921      0      stevel 		for (j = i; j < MIN(i + ncolumns, nreq); j++) {
    922      0      stevel 			if (tot_ops && interval && kptr_old != NULL)
    923      0      stevel 				per = (int)((knp[j].value.ui64 -
    924      0      stevel 				    kptr_old[j].value.ui64) * 100 / tot_ops);
    925      0      stevel 			else if (tot_ops)
    926      0      stevel 				per = (int)(knp[j].value.ui64 * 100 / tot_ops);
    927      0      stevel 			else
    928      0      stevel 				per = 0;
    929      0      stevel 			(void) sprintf(fixlen, "%" PRIu64 " %d%% ",
    930   5302    th199096 			    ((interval && kptr_old != NULL) ?
    931   5302    th199096 			    (knp[j].value.ui64 - kptr_old[j].value.ui64)
    932   5302    th199096 			    : knp[j].value.ui64), per);
    933      0      stevel 			printf("%-*s", field_width, fixlen);
    934      0      stevel 		}
    935      0      stevel 		printf("\n");
    936      0      stevel 	}
    937      0      stevel 	if (zflag) {
    938      0      stevel 		for (i = 0; i < req->ks_ndata; i++)
    939      0      stevel 			kptr[i].value.ui64 = 0;
    940      0      stevel 	}
    941      0      stevel 	if (kptr_old != NULL)
    942  10265  Krishnendu 		nfsstat_kstat_copy(req, req_old, 1);
    943      0      stevel 	else
    944  10265  Krishnendu 		nfsstat_kstat_copy(req, req_old, 0);
    945      0      stevel }
    946      0      stevel 
    947      0      stevel static void
    948      0      stevel stat_print(const char *title_string, kstat_t *req, kstat_t  *req_old,
    949   5302    th199096     int field_width, int zflag)
    950      0      stevel {
    951      0      stevel 	int i, j, nreq, ncolumns;
    952      0      stevel 	char fixlen[128];
    953      0      stevel 	kstat_named_t *knp;
    954      0      stevel 	kstat_named_t *knp_old;
    955      0      stevel 
    956      0      stevel 	if (req == NULL)
    957      0      stevel 		return;
    958      0      stevel 
    959   3406    th199096 	if (field_width == 0)
    960   3406    th199096 		return;
    961   3406    th199096 
    962      0      stevel 	printf("%s\n", title_string);
    963      0      stevel 	ncolumns = (MAX_COLUMNS -1)/field_width;
    964      0      stevel 
    965      0      stevel 	/* MEANS knp =  (kstat_named_t *)req->ks_data */
    966      0      stevel 	knp = KSTAT_NAMED_PTR(req);
    967      0      stevel 	nreq = req->ks_ndata;
    968      0      stevel 	knp_old = KSTAT_NAMED_PTR(req_old);
    969      0      stevel 
    970      0      stevel 	for (i = 0; i < nreq; i += ncolumns) {
    971      0      stevel 		/* prints out the titles of the columns */
    972      0      stevel 		for (j = i; j < MIN(i + ncolumns, nreq); j++) {
    973      0      stevel 			printf("%-*s", field_width, knp[j].name);
    974      0      stevel 		}
    975      0      stevel 		printf("\n");
    976      0      stevel 		/* prints out the stat numbers */
    977      0      stevel 		for (j = i; j < MIN(i + ncolumns, nreq); j++) {
    978      0      stevel 			(void) sprintf(fixlen, "%" PRIu64 " ",
    979   5302    th199096 			    (interval && knp_old != NULL) ?
    980   5302    th199096 			    (knp[j].value.ui64 - knp_old[j].value.ui64)
    981   5302    th199096 			    : knp[j].value.ui64);
    982      0      stevel 			printf("%-*s", field_width, fixlen);
    983      0      stevel 		}
    984      0      stevel 		printf("\n");
    985      0      stevel 
    986      0      stevel 	}
    987      0      stevel 	if (zflag) {
    988      0      stevel 		for (i = 0; i < req->ks_ndata; i++)
    989      0      stevel 			knp[i].value.ui64 = 0;
    990      0      stevel 	}
    991      0      stevel 
    992      0      stevel 	if (knp_old != NULL)
    993  10265  Krishnendu 		nfsstat_kstat_copy(req, req_old, 1);
    994      0      stevel 	else
    995  10265  Krishnendu 		nfsstat_kstat_copy(req, req_old, 0);
    996      0      stevel }
    997   3406    th199096 
    998      0      stevel static void
    999  10265  Krishnendu nfsstat_kstat_sum(kstat_t *kstat1, kstat_t *kstat2, kstat_t *sum)
   1000      0      stevel {
   1001      0      stevel 	int i;
   1002      0      stevel 	kstat_named_t *knp1, *knp2, *knpsum;
   1003      0      stevel 	if (kstat1 == NULL || kstat2 == NULL)
   1004      0      stevel 		return;
   1005      0      stevel 
   1006      0      stevel 	knp1 = KSTAT_NAMED_PTR(kstat1);
   1007      0      stevel 	knp2 = KSTAT_NAMED_PTR(kstat2);
   1008      0      stevel 	if (sum->ks_data == NULL)
   1009  10265  Krishnendu 		nfsstat_kstat_copy(kstat1, sum, 0);
   1010      0      stevel 	knpsum = KSTAT_NAMED_PTR(sum);
   1011      0      stevel 
   1012      0      stevel 	for (i = 0; i < (kstat1->ks_ndata); i++)
   1013      0      stevel 		knpsum[i].value.ui64 =  knp1[i].value.ui64 + knp2[i].value.ui64;
   1014      0      stevel }
   1015      0      stevel 
   1016      0      stevel /*
   1017      0      stevel  * my_dir and my_path could be pointers
   1018      0      stevel  */
   1019      0      stevel struct myrec {
   1020      0      stevel 	ulong_t my_fsid;
   1021      0      stevel 	char my_dir[MAXPATHLEN];
   1022      0      stevel 	char *my_path;
   1023      0      stevel 	char *ig_path;
   1024      0      stevel 	struct myrec *next;
   1025      0      stevel };
   1026      0      stevel 
   1027      0      stevel /*
   1028      0      stevel  * Print the mount table info
   1029      0      stevel  */
   1030      0      stevel static void
   1031      0      stevel mi_print(void)
   1032      0      stevel {
   1033      0      stevel 	FILE *mt;
   1034      0      stevel 	struct extmnttab m;
   1035      0      stevel 	struct myrec *list, *mrp, *pmrp;
   1036      0      stevel 	char *flavor;
   1037      0      stevel 	int ignored = 0;
   1038      0      stevel 	seconfig_t nfs_sec;
   1039      0      stevel 	kstat_t *ksp;
   1040      0      stevel 	struct mntinfo_kstat mik;
   1041      0      stevel 	int transport_flag = 0;
   1042      0      stevel 	int path_count;
   1043      0      stevel 	int found;
   1044      0      stevel 	char *timer_name[] = {
   1045      0      stevel 		"Lookups",
   1046      0      stevel 		"Reads",
   1047      0      stevel 		"Writes",
   1048      0      stevel 		"All"
   1049      0      stevel 	};
   1050      0      stevel 
   1051      0      stevel 	mt = fopen(MNTTAB, "r");
   1052      0      stevel 	if (mt == NULL) {
   1053      0      stevel 		perror(MNTTAB);
   1054      0      stevel 		exit(0);
   1055      0      stevel 	}
   1056      0      stevel 
   1057      0      stevel 	list = NULL;
   1058      0      stevel 	resetmnttab(mt);
   1059      0      stevel 
   1060      0      stevel 	while (getextmntent(mt, &m, sizeof (struct extmnttab)) == 0) {
   1061      0      stevel 		/* ignore non "nfs" and save the "ignore" entries */
   1062      0      stevel 		if (strcmp(m.mnt_fstype, MNTTYPE_NFS) != 0)
   1063      0      stevel 			continue;
   1064      0      stevel 		/*
   1065      0      stevel 		 * Check to see here if user gave a path(s) to
   1066      0      stevel 		 * only show the mount point they wanted
   1067      0      stevel 		 * Iterate through the list of paths the user gave and see
   1068   5302    th199096 		 * if any of them match our current nfs mount
   1069      0      stevel 		 */
   1070      0      stevel 		if (path[0] != NULL) {
   1071      0      stevel 			found = 0;
   1072      0      stevel 			for (path_count = 0; path[path_count] != NULL;
   1073      0      stevel 			    path_count++) {
   1074      0      stevel 				if (strcmp(path[path_count], m.mnt_mountp)
   1075      0      stevel 				    == 0) {
   1076      0      stevel 					found = 1;
   1077      0      stevel 					break;
   1078      0      stevel 				}
   1079      0      stevel 			}
   1080      0      stevel 			if (!found)
   1081      0      stevel 				continue;
   1082      0      stevel 		}
   1083      0      stevel 
   1084      0      stevel 		if ((mrp = malloc(sizeof (struct myrec))) == 0) {
   1085      0      stevel 			fprintf(stderr, "nfsstat: not enough memory\n");
   1086      0      stevel 			exit(1);
   1087      0      stevel 		}
   1088      0      stevel 		mrp->my_fsid = makedev(m.mnt_major, m.mnt_minor);
   1089      0      stevel 		if (ignore(m.mnt_mntopts)) {
   1090      0      stevel 			/*
   1091      0      stevel 			 * ignored entries cannot be ignored for this
   1092      0      stevel 			 * option. We have to display the info for this
   1093      0      stevel 			 * nfs mount. The ignore is an indication
   1094      0      stevel 			 * that the actual mount point is different and
   1095      0      stevel 			 * something is in between the nfs mount.
   1096      0      stevel 			 * So save the mount point now
   1097      0      stevel 			 */
   1098      0      stevel 			if ((mrp->ig_path = malloc(
   1099   5302    th199096 			    strlen(m.mnt_mountp) + 1)) == 0) {
   1100      0      stevel 				fprintf(stderr, "nfsstat: not enough memory\n");
   1101      0      stevel 				exit(1);
   1102      0      stevel 			}
   1103      0      stevel 			(void) strcpy(mrp->ig_path, m.mnt_mountp);
   1104      0      stevel 			ignored++;
   1105      0      stevel 		} else {
   1106      0      stevel 			mrp->ig_path = 0;
   1107      0      stevel 			(void) strcpy(mrp->my_dir, m.mnt_mountp);
   1108      0      stevel 		}
   1109      0      stevel 		if ((mrp->my_path = strdup(m.mnt_special)) == NULL) {
   1110      0      stevel 			fprintf(stderr, "nfsstat: not enough memory\n");
   1111      0      stevel 			exit(1);
   1112      0      stevel 		}
   1113      0      stevel 		mrp->next = list;
   1114      0      stevel 		list = mrp;
   1115      0      stevel 	}
   1116      0      stevel 
   1117      0      stevel 	/*
   1118      0      stevel 	 * If something got ignored, go to the beginning of the mnttab
   1119      0      stevel 	 * and look for the cachefs entries since they are the one
   1120      0      stevel 	 * causing this. The mount point saved for the ignored entries
   1121      0      stevel 	 * is matched against the special to get the actual mount point.
   1122      0      stevel 	 * We are interested in the acutal mount point so that the output
   1123      0      stevel 	 * look nice too.
   1124      0      stevel 	 */
   1125      0      stevel 	if (ignored) {
   1126      0      stevel 		rewind(mt);
   1127      0      stevel 		resetmnttab(mt);
   1128      0      stevel 		while (getextmntent(mt, &m, sizeof (struct extmnttab)) == 0) {
   1129      0      stevel 
   1130      0      stevel 			/* ignore non "cachefs" */
   1131      0      stevel 			if (strcmp(m.mnt_fstype, MNTTYPE_CACHEFS) != 0)
   1132      0      stevel 				continue;
   1133      0      stevel 
   1134      0      stevel 			for (mrp = list; mrp; mrp = mrp->next) {
   1135      0      stevel 				if (mrp->ig_path == 0)
   1136      0      stevel 					continue;
   1137      0      stevel 				if (strcmp(mrp->ig_path, m.mnt_special) == 0) {
   1138      0      stevel 					mrp->ig_path = 0;
   1139      0      stevel 					(void) strcpy(mrp->my_dir,
   1140   5302    th199096 					    m.mnt_mountp);
   1141      0      stevel 				}
   1142      0      stevel 			}
   1143      0      stevel 		}
   1144      0      stevel 		/*
   1145      0      stevel 		 * Now ignored entries which do not have
   1146      0      stevel 		 * the my_dir initialized are really ignored; This never
   1147      0      stevel 		 * happens unless the mnttab is corrupted.
   1148      0      stevel 		 */
   1149      0      stevel 		for (pmrp = 0, mrp = list; mrp; mrp = mrp->next) {
   1150      0      stevel 			if (mrp->ig_path == 0)
   1151      0      stevel 				pmrp = mrp;
   1152      0      stevel 			else if (pmrp)
   1153      0      stevel 				pmrp->next = mrp->next;
   1154      0      stevel 			else
   1155      0      stevel 				list = mrp->next;
   1156      0      stevel 		}
   1157      0      stevel 	}
   1158      0      stevel 
   1159      0      stevel 	(void) fclose(mt);
   1160      0      stevel 
   1161      0      stevel 
   1162      0      stevel 	for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
   1163      0      stevel 		int i;
   1164      0      stevel 
   1165      0      stevel 		if (ksp->ks_type != KSTAT_TYPE_RAW)
   1166      0      stevel 			continue;
   1167      0      stevel 		if (strcmp(ksp->ks_module, "nfs") != 0)
   1168      0      stevel 			continue;
   1169      0      stevel 		if (strcmp(ksp->ks_name, "mntinfo") != 0)
   1170      0      stevel 			continue;
   1171      0      stevel 
   1172      0      stevel 		for (mrp = list; mrp; mrp = mrp->next) {
   1173      0      stevel 			if ((mrp->my_fsid & MAXMIN) == ksp->ks_instance)
   1174      0      stevel 				break;
   1175      0      stevel 		}
   1176      0      stevel 		if (mrp == 0)
   1177      0      stevel 			continue;
   1178      0      stevel 
   1179      0      stevel 		if (safe_kstat_read(kc, ksp, &mik) == -1)
   1180      0      stevel 			continue;
   1181      0      stevel 
   1182      0      stevel 		printf("%s from %s\n", mrp->my_dir, mrp->my_path);
   1183      0      stevel 
   1184      0      stevel 		/*
   1185      0      stevel 		 * for printing rdma transport and provider string.
   1186      0      stevel 		 * This way we avoid modifying the kernel mntinfo_kstat
   1187      0      stevel 		 * struct for protofmly.
   1188      0      stevel 		 */
   1189      0      stevel 		if (strcmp(mik.mik_proto, "ibtf") == 0) {
   1190      0      stevel 			printf(" Flags:		vers=%u,proto=rdma",
   1191      0      stevel 			    mik.mik_vers);
   1192      0      stevel 			transport_flag = 1;
   1193      0      stevel 		} else {
   1194      0      stevel 			printf(" Flags:		vers=%u,proto=%s",
   1195      0      stevel 			    mik.mik_vers, mik.mik_proto);
   1196      0      stevel 			transport_flag = 0;
   1197      0      stevel 		}
   1198      0      stevel 
   1199      0      stevel 		/*
   1200      0      stevel 		 *  get the secmode name from /etc/nfssec.conf.
   1201      0      stevel 		 */
   1202      0      stevel 		if (!nfs_getseconfig_bynumber(mik.mik_secmod, &nfs_sec)) {
   1203      0      stevel 			flavor = nfs_sec.sc_name;
   1204      0      stevel 		} else
   1205      0      stevel 			flavor = NULL;
   1206      0      stevel 
   1207      0      stevel 		if (flavor != NULL)
   1208      0      stevel 			printf(",sec=%s", flavor);
   1209      0      stevel 		else
   1210      0      stevel 			printf(",sec#=%d", mik.mik_secmod);
   1211      0      stevel 
   1212      0      stevel 		printf(",%s", (mik.mik_flags & MI_HARD) ? "hard" : "soft");
   1213      0      stevel 		if (mik.mik_flags & MI_PRINTED)
   1214      0      stevel 			printf(",printed");
   1215      0      stevel 		printf(",%s", (mik.mik_flags & MI_INT) ? "intr" : "nointr");
   1216      0      stevel 		if (mik.mik_flags & MI_DOWN)
   1217      0      stevel 			printf(",down");
   1218      0      stevel 		if (mik.mik_flags & MI_NOAC)
   1219      0      stevel 			printf(",noac");
   1220      0      stevel 		if (mik.mik_flags & MI_NOCTO)
   1221      0      stevel 			printf(",nocto");
   1222      0      stevel 		if (mik.mik_flags & MI_DYNAMIC)
   1223      0      stevel 			printf(",dynamic");
   1224      0      stevel 		if (mik.mik_flags & MI_LLOCK)
   1225      0      stevel 			printf(",llock");
   1226      0      stevel 		if (mik.mik_flags & MI_GRPID)
   1227      0      stevel 			printf(",grpid");
   1228      0      stevel 		if (mik.mik_flags & MI_RPCTIMESYNC)
   1229      0      stevel 			printf(",rpctimesync");
   1230      0      stevel 		if (mik.mik_flags & MI_LINK)
   1231      0      stevel 			printf(",link");
   1232      0      stevel 		if (mik.mik_flags & MI_SYMLINK)
   1233      0      stevel 			printf(",symlink");
   1234   5897    th199096 		if (mik.mik_vers < NFS_V4 && mik.mik_flags & MI_READDIRONLY)
   1235      0      stevel 			printf(",readdironly");
   1236      0      stevel 		if (mik.mik_flags & MI_ACL)
   1237      0      stevel 			printf(",acl");
   1238  10924      Marcel 		if (mik.mik_flags & MI_DIRECTIO)
   1239  10924      Marcel 			printf(",forcedirectio");
   1240      0      stevel 
   1241   5302    th199096 		if (mik.mik_vers >= NFS_V4) {
   1242   5302    th199096 			if (mik.mik_flags & MI4_MIRRORMOUNT)
   1243   5302    th199096 				printf(",mirrormount");
   1244   5302    th199096 		}
   1245   5302    th199096 
   1246      0      stevel 		printf(",rsize=%d,wsize=%d,retrans=%d,timeo=%d",
   1247   5302    th199096 		    mik.mik_curread, mik.mik_curwrite, mik.mik_retrans,
   1248   5302    th199096 		    mik.mik_timeo);
   1249      0      stevel 		printf("\n");
   1250      0      stevel 		printf(" Attr cache:	acregmin=%d,acregmax=%d"
   1251   5302    th199096 		    ",acdirmin=%d,acdirmax=%d\n", mik.mik_acregmin,
   1252   5302    th199096 		    mik.mik_acregmax, mik.mik_acdirmin, mik.mik_acdirmax);
   1253      0      stevel 
   1254      0      stevel 		if (transport_flag) {
   1255      0      stevel 			printf(" Transport:	proto=rdma, plugin=%s\n",
   1256      0      stevel 			    mik.mik_proto);
   1257      0      stevel 		}
   1258      0      stevel 
   1259      0      stevel #define	srtt_to_ms(x) x, (x * 2 + x / 2)
   1260      0      stevel #define	dev_to_ms(x) x, (x * 5)
   1261      0      stevel 
   1262      0      stevel 		for (i = 0; i < NFS_CALLTYPES + 1; i++) {
   1263      0      stevel 			int j;
   1264      0      stevel 
   1265      0      stevel 			j = (i == NFS_CALLTYPES ? i - 1 : i);
   1266      0      stevel 			if (mik.mik_timers[j].srtt ||
   1267      0      stevel 			    mik.mik_timers[j].rtxcur) {
   1268   5302    th199096 				printf(" %s:     srtt=%d (%dms), "
   1269   5302    th199096 				    "dev=%d (%dms), cur=%u (%ums)\n",
   1270   5302    th199096 				    timer_name[i],
   1271   5302    th199096 				    srtt_to_ms(mik.mik_timers[i].srtt),
   1272   5302    th199096 				    dev_to_ms(mik.mik_timers[i].deviate),
   1273   5302    th199096 				    mik.mik_timers[i].rtxcur,
   1274   5302    th199096 				    mik.mik_timers[i].rtxcur * 20);
   1275      0      stevel 			}
   1276      0      stevel 		}
   1277      0      stevel 
   1278      0      stevel 		if (strchr(mrp->my_path, ','))
   1279      0      stevel 			printf(
   1280      0      stevel 			    " Failover:	noresponse=%d,failover=%d,"
   1281      0      stevel 			    "remap=%d,currserver=%s\n",
   1282      0      stevel 			    mik.mik_noresponse, mik.mik_failover,
   1283      0      stevel 			    mik.mik_remap, mik.mik_curserver);
   1284      0      stevel 		printf("\n");
   1285      0      stevel 	}
   1286      0      stevel }
   1287      0      stevel 
   1288      0      stevel static char *mntopts[] = { MNTOPT_IGNORE, MNTOPT_DEV, NULL };
   1289      0      stevel #define	IGNORE  0
   1290      0      stevel #define	DEV	1
   1291      0      stevel 
   1292      0      stevel /*
   1293      0      stevel  * Return 1 if "ignore" appears in the options string
   1294      0      stevel  */
   1295      0      stevel static int
   1296      0      stevel ignore(char *opts)
   1297      0      stevel {
   1298      0      stevel 	char *value;
   1299      0      stevel 	char *s;
   1300      0      stevel 
   1301      0      stevel 	if (opts == NULL)
   1302      0      stevel 		return (0);
   1303      0      stevel 	s = strdup(opts);
   1304      0      stevel 	if (s == NULL)
   1305      0      stevel 		return (0);
   1306      0      stevel 	opts = s;
   1307      0      stevel 
   1308      0      stevel 	while (*opts != '\0') {
   1309      0      stevel 		if (getsubopt(&opts, mntopts, &value) == IGNORE) {
   1310      0      stevel 			free(s);
   1311      0      stevel 			return (1);
   1312      0      stevel 		}
   1313      0      stevel 	}
   1314      0      stevel 
   1315      0      stevel 	free(s);
   1316      0      stevel 	return (0);
   1317      0      stevel }
   1318      0      stevel 
   1319      0      stevel void
   1320      0      stevel usage(void)
   1321      0      stevel {
   1322      0      stevel 	fprintf(stderr, "Usage: nfsstat [-cnrsza [-v version] "
   1323  10265  Krishnendu 	    "[-T d|u] [interval [count]]\n");
   1324      0      stevel 	fprintf(stderr, "Usage: nfsstat -m [pathname..]\n");
   1325      0      stevel 	exit(1);
   1326      0      stevel }
   1327      0      stevel 
   1328  10265  Krishnendu void
   1329      0      stevel fail(int do_perror, char *message, ...)
   1330      0      stevel {
   1331      0      stevel 	va_list args;
   1332      0      stevel 
   1333      0      stevel 	va_start(args, message);
   1334      0      stevel 	fprintf(stderr, "nfsstat: ");
   1335      0      stevel 	vfprintf(stderr, message, args);
   1336      0      stevel 	va_end(args);
   1337      0      stevel 	if (do_perror)
   1338      0      stevel 		fprintf(stderr, ": %s", strerror(errno));
   1339      0      stevel 	fprintf(stderr, "\n");
   1340      0      stevel 	exit(1);
   1341      0      stevel }
   1342      0      stevel 
   1343      0      stevel kid_t
   1344      0      stevel safe_kstat_read(kstat_ctl_t *kc, kstat_t *ksp, void *data)
   1345      0      stevel {
   1346      0      stevel 	kid_t kstat_chain_id = kstat_read(kc, ksp, data);
   1347      0      stevel 
   1348      0      stevel 	if (kstat_chain_id == -1)
   1349      0      stevel 		fail(1, "kstat_read(%x, '%s') failed", kc, ksp->ks_name);
   1350      0      stevel 	return (kstat_chain_id);
   1351      0      stevel }
   1352      0      stevel 
   1353      0      stevel kid_t
   1354      0      stevel safe_kstat_write(kstat_ctl_t *kc, kstat_t *ksp, void *data)
   1355      0      stevel {
   1356      0      stevel 	kid_t kstat_chain_id = 0;
   1357      0      stevel 
   1358      0      stevel 	if (ksp->ks_data != NULL) {
   1359      0      stevel 		kstat_chain_id = kstat_write(kc, ksp, data);
   1360      0      stevel 
   1361      0      stevel 		if (kstat_chain_id == -1)
   1362      0      stevel 			fail(1, "kstat_write(%x, '%s') failed", kc,
   1363      0      stevel 			    ksp->ks_name);
   1364      0      stevel 	}
   1365      0      stevel 	return (kstat_chain_id);
   1366      0      stevel }
   1367      0      stevel 
   1368      0      stevel void
   1369      0      stevel stats_timer(int interval)
   1370      0      stevel {
   1371      0      stevel 	timer_t t_id;
   1372      0      stevel 	itimerspec_t time_struct;
   1373      0      stevel 	struct sigevent sig_struct;
   1374      0      stevel 	struct sigaction act;
   1375      0      stevel 
   1376      0      stevel 	bzero(&sig_struct, sizeof (struct sigevent));
   1377      0      stevel 	bzero(&act, sizeof (struct sigaction));
   1378      0      stevel 
   1379      0      stevel 	/* Create timer */
   1380      0      stevel 	sig_struct.sigev_notify = SIGEV_SIGNAL;
   1381      0      stevel 	sig_struct.sigev_signo = SIGUSR1;
   1382      0      stevel 	sig_struct.sigev_value.sival_int = 0;
   1383      0      stevel 
   1384      0      stevel 	if (timer_create(CLOCK_REALTIME, &sig_struct, &t_id) != 0) {
   1385      0      stevel 		fail(1, "Timer creation failed");
   1386      0      stevel 	}
   1387      0      stevel 
   1388      0      stevel 	act.sa_handler = handle_sig;
   1389      0      stevel 
   1390      0      stevel 	if (sigaction(SIGUSR1, &act, NULL) != 0) {
   1391      0      stevel 		fail(1, "Could not set up signal handler");
   1392      0      stevel 	}
   1393      0      stevel 
   1394      0      stevel 	time_struct.it_value.tv_sec = interval;
   1395      0      stevel 	time_struct.it_value.tv_nsec = 0;
   1396      0      stevel 	time_struct.it_interval.tv_sec = interval;
   1397      0      stevel 	time_struct.it_interval.tv_nsec = 0;
   1398      0      stevel 
   1399      0      stevel 	/* Arm timer */
   1400      0      stevel 	if ((timer_settime(t_id, 0, &time_struct, NULL)) != 0) {
   1401      0      stevel 		fail(1, "Setting timer failed");
   1402      0      stevel 	}
   1403      0      stevel }
   1404      0      stevel 
   1405      0      stevel void
   1406      0      stevel handle_sig(int x)
   1407      0      stevel {
   1408      0      stevel }
   1409      0      stevel 
   1410      0      stevel static void
   1411  10265  Krishnendu nfsstat_kstat_copy(kstat_t *src, kstat_t *dst, int fr)
   1412      0      stevel {
   1413      0      stevel 
   1414      0      stevel 	if (fr)
   1415      0      stevel 		free(dst->ks_data);
   1416      0      stevel 
   1417      0      stevel 	*dst = *src;
   1418      0      stevel 
   1419      0      stevel 	if (src->ks_data != NULL) {
   1420      0      stevel 		safe_zalloc(&dst->ks_data, src->ks_data_size, 0);
   1421      0      stevel 		(void) memcpy(dst->ks_data, src->ks_data, src->ks_data_size);
   1422      0      stevel 	} else {
   1423      0      stevel 		dst->ks_data = NULL;
   1424      0      stevel 		dst->ks_data_size = 0;
   1425      0      stevel 	}
   1426      0      stevel }
   1427      0      stevel 
   1428      0      stevel /*
   1429  10429      Marcel  * "Safe" allocators - if we return we're guaranteed to have the desired space
   1430  10429      Marcel  * allocated and zero-filled. We exit via fail if we can't get the space.
   1431      0      stevel  */
   1432      0      stevel void
   1433      0      stevel safe_zalloc(void **ptr, uint_t size, int free_first)
   1434      0      stevel {
   1435  10429      Marcel 	if (ptr == NULL)
   1436      0      stevel 		fail(1, "invalid pointer");
   1437      0      stevel 	if (free_first && *ptr != NULL)
   1438      0      stevel 		free(*ptr);
   1439      0      stevel 	if ((*ptr = (void *)malloc(size)) == NULL)
   1440      0      stevel 		fail(1, "malloc failed");
   1441      0      stevel 	(void) memset(*ptr, 0, size);
   1442      0      stevel }
   1443      0      stevel 
   1444      0      stevel static int
   1445      0      stevel safe_strtoi(char const *val, char *errmsg)
   1446      0      stevel {
   1447      0      stevel 	char *end;
   1448      0      stevel 	long tmp;
   1449      0      stevel 	errno = 0;
   1450      0      stevel 	tmp = strtol(val, &end, 10);
   1451      0      stevel 	if (*end != '\0' || errno)
   1452      0      stevel 		fail(0, "%s %s", errmsg, val);
   1453      0      stevel 	return ((int)tmp);
   1454      0      stevel }
   1455