1*86d949f9SVitaliy Gusev /*
2*86d949f9SVitaliy Gusev  * This file and its contents are supplied under the terms of the
3*86d949f9SVitaliy Gusev  * Common Development and Distribution License ("CDDL"), version 1.0.
4*86d949f9SVitaliy Gusev  * You may only use this file in accordance with the terms of version
5*86d949f9SVitaliy Gusev  * 1.0 of the CDDL.
6*86d949f9SVitaliy Gusev  *
7*86d949f9SVitaliy Gusev  * A full copy of the text of the CDDL should have accompanied this
8*86d949f9SVitaliy Gusev  * source.  A copy of the CDDL is also available via the Internet at
9*86d949f9SVitaliy Gusev  * http://www.illumos.org/license/CDDL.
10*86d949f9SVitaliy Gusev  */
11*86d949f9SVitaliy Gusev /*
12*86d949f9SVitaliy Gusev  * Copyright 2021 Tintri by DDN, Inc. All rights reserved.
13*86d949f9SVitaliy Gusev  */
14*86d949f9SVitaliy Gusev 
15*86d949f9SVitaliy Gusev #include <sys/types.h>
16*86d949f9SVitaliy Gusev #include <sys/kstat.h>
17*86d949f9SVitaliy Gusev #include <sys/mdb_modapi.h>
18*86d949f9SVitaliy Gusev #include <rpc/clnt.h>
19*86d949f9SVitaliy Gusev #include <nfs/nfs_clnt.h>
20*86d949f9SVitaliy Gusev #include <nfs/nfs4_clnt.h>
21*86d949f9SVitaliy Gusev 
22*86d949f9SVitaliy Gusev #include "svc.h"
23*86d949f9SVitaliy Gusev #include "rfs4.h"
24*86d949f9SVitaliy Gusev #include "nfssrv.h"
25*86d949f9SVitaliy Gusev #include "common.h"
26*86d949f9SVitaliy Gusev 
27*86d949f9SVitaliy Gusev #define	NFS4_MINOR_VERS_COUNT 0
28*86d949f9SVitaliy Gusev #define	NFS_STAT_NUM_STATS 79
29*86d949f9SVitaliy Gusev 
30*86d949f9SVitaliy Gusev /*
31*86d949f9SVitaliy Gusev  * Structure used to group kstats we want to print.
32*86d949f9SVitaliy Gusev  */
33*86d949f9SVitaliy Gusev typedef struct nfs_mdb_stats {
34*86d949f9SVitaliy Gusev 	struct nfs_stats nfsstats;
35*86d949f9SVitaliy Gusev 	struct rpcstat rpcstats;
36*86d949f9SVitaliy Gusev 	struct nfs_globals nfsglbls;
37*86d949f9SVitaliy Gusev 	uintptr_t clntstat;
38*86d949f9SVitaliy Gusev 	uintptr_t clntstat4; /* extend this for NFS4.X */
39*86d949f9SVitaliy Gusev 	uintptr_t callback_stats;
40*86d949f9SVitaliy Gusev } nfs_mdb_stats_t;
41*86d949f9SVitaliy Gusev 
42*86d949f9SVitaliy Gusev static int nfs_stat_clnt(nfs_mdb_stats_t *, int, int);
43*86d949f9SVitaliy Gusev static int nfs_stat_srv(nfs_mdb_stats_t *, int, int);
44*86d949f9SVitaliy Gusev static int nfs_srvstat(nfs_mdb_stats_t *, int);
45*86d949f9SVitaliy Gusev static int nfs_srvstat_rpc(nfs_mdb_stats_t *);
46*86d949f9SVitaliy Gusev static int nfs_srvstat_acl(nfs_mdb_stats_t *, int);
47*86d949f9SVitaliy Gusev static int nfs_clntstat(nfs_mdb_stats_t *, int);
48*86d949f9SVitaliy Gusev static int nfs_clntstat_rpc(nfs_mdb_stats_t *);
49*86d949f9SVitaliy Gusev static int nfs_clntstat_acl(nfs_mdb_stats_t *, int);
50*86d949f9SVitaliy Gusev static int nfs_srvstat_cb(nfs_mdb_stats_t *);
51*86d949f9SVitaliy Gusev 
52*86d949f9SVitaliy Gusev #define	NFS_SRV_STAT	0x1
53*86d949f9SVitaliy Gusev #define	NFS_CLNT_STAT	0x2
54*86d949f9SVitaliy Gusev #define	NFS_CB_STAT	0x4
55*86d949f9SVitaliy Gusev #define	NFS_NFS_STAT	0x1
56*86d949f9SVitaliy Gusev #define	NFS_ACL_STAT	0x2
57*86d949f9SVitaliy Gusev #define	NFS_RPC_STAT	0x4
58*86d949f9SVitaliy Gusev #define	NFS_V2_STAT	0x1
59*86d949f9SVitaliy Gusev #define	NFS_V3_STAT	0x2
60*86d949f9SVitaliy Gusev #define	NFS_V4_STAT	0x4
61*86d949f9SVitaliy Gusev 
62*86d949f9SVitaliy Gusev static int prt_nfs_stats(uintptr_t, char *);
63*86d949f9SVitaliy Gusev static void kstat_prtout(char *, uint64_t *, int);
64*86d949f9SVitaliy Gusev 
65*86d949f9SVitaliy Gusev void
nfs_stat_help(void)66*86d949f9SVitaliy Gusev nfs_stat_help(void)
67*86d949f9SVitaliy Gusev {
68*86d949f9SVitaliy Gusev 	mdb_printf("Switches similar to those of nfsstat command.\n",
69*86d949f9SVitaliy Gusev 	    "            ::nfs_stat -a	-> ACL    Statistics.\n"
70*86d949f9SVitaliy Gusev 	    "            ::nfs_stat -b  -> Callback Stats. (V4 only)\n"
71*86d949f9SVitaliy Gusev 	    "            ::nfs_stat -c  -> Client Statistics.\n"
72*86d949f9SVitaliy Gusev 	    "            ::nfs_stat -n	-> NFS    Statistics.\n"
73*86d949f9SVitaliy Gusev 	    "            ::nfs_stat -r	-> RPC    Statistics.\n"
74*86d949f9SVitaliy Gusev 	    "            ::nfs_stat -s	-> Server Statistics.\n"
75*86d949f9SVitaliy Gusev 	    "            ::nfs_stat -2	-> Version 2.\n"
76*86d949f9SVitaliy Gusev 	    "            ::nfs_stat -3	-> Version 3.\n"
77*86d949f9SVitaliy Gusev 	    "            ::nfs_stat -4	-> Version 4.\n");
78*86d949f9SVitaliy Gusev }
79*86d949f9SVitaliy Gusev 
80*86d949f9SVitaliy Gusev int
nfs_stat_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)81*86d949f9SVitaliy Gusev nfs_stat_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
82*86d949f9SVitaliy Gusev {
83*86d949f9SVitaliy Gusev 	int host_flag = 0; /* host or client flag */
84*86d949f9SVitaliy Gusev 	int type_flag = 0; /* type acl, rpc of nfs */
85*86d949f9SVitaliy Gusev 	int vers_flag = 0; /* NFS version flag */
86*86d949f9SVitaliy Gusev 	nfs_mdb_stats_t mdb_stats;
87*86d949f9SVitaliy Gusev 	uintptr_t glbls;
88*86d949f9SVitaliy Gusev 	uintptr_t cb_glbls;
89*86d949f9SVitaliy Gusev 	uintptr_t zonep;
90*86d949f9SVitaliy Gusev 
91*86d949f9SVitaliy Gusev 	if (argc == 1 && argv->a_type == MDB_TYPE_IMMEDIATE) {
92*86d949f9SVitaliy Gusev 		kstat_named_t ksts;
93*86d949f9SVitaliy Gusev 		int i;
94*86d949f9SVitaliy Gusev 		for (i = argv->a_un.a_val; i; i--) {
95*86d949f9SVitaliy Gusev 			if (mdb_vread(&ksts, sizeof (ksts), addr) < 0) {
96*86d949f9SVitaliy Gusev 				mdb_warn("failed to read kstat_name_t");
97*86d949f9SVitaliy Gusev 				return (DCMD_ERR);
98*86d949f9SVitaliy Gusev 			}
99*86d949f9SVitaliy Gusev 			mdb_printf(" %8s %30d\n", ksts.name, ksts.value.ui64);
100*86d949f9SVitaliy Gusev 			addr += sizeof (ksts);
101*86d949f9SVitaliy Gusev 		}
102*86d949f9SVitaliy Gusev 		return (DCMD_OK);
103*86d949f9SVitaliy Gusev 	}
104*86d949f9SVitaliy Gusev 
105*86d949f9SVitaliy Gusev 	if (mdb_getopts(argc, argv,
106*86d949f9SVitaliy Gusev 	    'a', MDB_OPT_SETBITS, NFS_ACL_STAT, &type_flag,
107*86d949f9SVitaliy Gusev 	    'b', MDB_OPT_SETBITS, NFS_CB_STAT, &host_flag,
108*86d949f9SVitaliy Gusev 	    'c', MDB_OPT_SETBITS, NFS_CLNT_STAT, &host_flag,
109*86d949f9SVitaliy Gusev 	    'n', MDB_OPT_SETBITS, NFS_NFS_STAT, &type_flag,
110*86d949f9SVitaliy Gusev 	    'r', MDB_OPT_SETBITS, NFS_RPC_STAT, &type_flag,
111*86d949f9SVitaliy Gusev 	    's', MDB_OPT_SETBITS, NFS_SRV_STAT, &host_flag,
112*86d949f9SVitaliy Gusev 	    '2', MDB_OPT_SETBITS, NFS_V2_STAT, &vers_flag,
113*86d949f9SVitaliy Gusev 	    '3', MDB_OPT_SETBITS, NFS_V3_STAT, &vers_flag,
114*86d949f9SVitaliy Gusev 	    '4', MDB_OPT_SETBITS, NFS_V4_STAT, &vers_flag,
115*86d949f9SVitaliy Gusev 	    NULL) != argc) {
116*86d949f9SVitaliy Gusev 		return (DCMD_USAGE);
117*86d949f9SVitaliy Gusev 	}
118*86d949f9SVitaliy Gusev 
119*86d949f9SVitaliy Gusev 
120*86d949f9SVitaliy Gusev 	if (flags & DCMD_ADDRSPEC) {
121*86d949f9SVitaliy Gusev 		zonep = addr;
122*86d949f9SVitaliy Gusev 	} else {
123*86d949f9SVitaliy Gusev 		if (mdb_readsym(&zonep, sizeof (uintptr_t),
124*86d949f9SVitaliy Gusev 		    "global_zone") == -1) {
125*86d949f9SVitaliy Gusev 			mdb_warn("Failed to find global_zone");
126*86d949f9SVitaliy Gusev 			return (DCMD_ERR);
127*86d949f9SVitaliy Gusev 		}
128*86d949f9SVitaliy Gusev 	}
129*86d949f9SVitaliy Gusev 
130*86d949f9SVitaliy Gusev 	if (zoned_get_zsd(zonep, "nfssrv_zone_key", &glbls)) {
131*86d949f9SVitaliy Gusev 		mdb_warn("Failed to find nfssrv_zone_key");
132*86d949f9SVitaliy Gusev 		return (DCMD_ERR);
133*86d949f9SVitaliy Gusev 	}
134*86d949f9SVitaliy Gusev 
135*86d949f9SVitaliy Gusev 	if (mdb_vread(&mdb_stats.nfsglbls, sizeof (struct nfs_globals),
136*86d949f9SVitaliy Gusev 	    glbls) == -1) {
137*86d949f9SVitaliy Gusev 		mdb_warn("Failed to read nfs_stats at %p", glbls);
138*86d949f9SVitaliy Gusev 		return (DCMD_ERR);
139*86d949f9SVitaliy Gusev 	}
140*86d949f9SVitaliy Gusev 
141*86d949f9SVitaliy Gusev 	if (zoned_get_zsd(zonep, "nfsstat_zone_key", &glbls)) {
142*86d949f9SVitaliy Gusev 		mdb_warn("Failed to find %s", "nfsstat_zone_key");
143*86d949f9SVitaliy Gusev 		return (DCMD_ERR);
144*86d949f9SVitaliy Gusev 	}
145*86d949f9SVitaliy Gusev 
146*86d949f9SVitaliy Gusev 	if (mdb_vread(&mdb_stats.nfsstats, sizeof (struct nfs_stats),
147*86d949f9SVitaliy Gusev 	    glbls) == -1) {
148*86d949f9SVitaliy Gusev 		mdb_warn("Failed to read nfs_stats at %p", glbls);
149*86d949f9SVitaliy Gusev 		return (DCMD_ERR);
150*86d949f9SVitaliy Gusev 	}
151*86d949f9SVitaliy Gusev 
152*86d949f9SVitaliy Gusev 	if (zoned_get_zsd(zonep, "rpcstat_zone_key", &glbls)) {
153*86d949f9SVitaliy Gusev 		mdb_warn("Failed to find %s", "rpcstat_zone_key");
154*86d949f9SVitaliy Gusev 		return (DCMD_ERR);
155*86d949f9SVitaliy Gusev 	}
156*86d949f9SVitaliy Gusev 
157*86d949f9SVitaliy Gusev 	if (mdb_vread(&mdb_stats.rpcstats, sizeof (struct rpcstat),
158*86d949f9SVitaliy Gusev 	    glbls) == -1) {
159*86d949f9SVitaliy Gusev 		mdb_warn("Failed to read nfs_stats at %p", glbls);
160*86d949f9SVitaliy Gusev 		return (DCMD_ERR);
161*86d949f9SVitaliy Gusev 	}
162*86d949f9SVitaliy Gusev 
163*86d949f9SVitaliy Gusev 	if (zoned_get_zsd(zonep, "nfsclnt_zone_key", &glbls)) {
164*86d949f9SVitaliy Gusev 		mdb_warn("Failed to find %s", "nfsclnt_zone_key");
165*86d949f9SVitaliy Gusev 		return (DCMD_ERR);
166*86d949f9SVitaliy Gusev 	}
167*86d949f9SVitaliy Gusev 	mdb_stats.clntstat = glbls + offsetof(struct nfs_clnt, nfscl_stat);
168*86d949f9SVitaliy Gusev 
169*86d949f9SVitaliy Gusev 	if (zoned_get_zsd(zonep, "nfs4clnt_zone_key", &glbls)) {
170*86d949f9SVitaliy Gusev 		mdb_warn("Failed to find %s", "nfs4clnt_zone_key");
171*86d949f9SVitaliy Gusev 		return (DCMD_ERR);
172*86d949f9SVitaliy Gusev 	}
173*86d949f9SVitaliy Gusev 	/*
174*86d949f9SVitaliy Gusev 	 * currently only have NFSv4.0 is availble. When NFSv4.1 and above are
175*86d949f9SVitaliy Gusev 	 * available stats support will need to be added.
176*86d949f9SVitaliy Gusev 	 */
177*86d949f9SVitaliy Gusev 	mdb_stats.clntstat4 = glbls + offsetof(struct nfs4_clnt, nfscl_stat);
178*86d949f9SVitaliy Gusev 
179*86d949f9SVitaliy Gusev 	if (zoned_get_zsd(zonep, "nfs4_callback_zone_key",
180*86d949f9SVitaliy Gusev 	    (uintptr_t *)&cb_glbls)) {
181*86d949f9SVitaliy Gusev 		mdb_warn("Failed to find %s", "nfs4_callback_zone_key");
182*86d949f9SVitaliy Gusev 		return (DCMD_ERR);
183*86d949f9SVitaliy Gusev 	}
184*86d949f9SVitaliy Gusev 
185*86d949f9SVitaliy Gusev 	mdb_stats.callback_stats =
186*86d949f9SVitaliy Gusev 	    (cb_glbls + offsetof(struct nfs4_callback_globals,
187*86d949f9SVitaliy Gusev 	    nfs4_callback_stats));
188*86d949f9SVitaliy Gusev 
189*86d949f9SVitaliy Gusev 	if (host_flag == 0)
190*86d949f9SVitaliy Gusev 		host_flag = NFS_SRV_STAT | NFS_CLNT_STAT | NFS_CB_STAT;
191*86d949f9SVitaliy Gusev 	if (vers_flag == 0)
192*86d949f9SVitaliy Gusev 		vers_flag = NFS_V2_STAT | NFS_V3_STAT | NFS_V4_STAT;
193*86d949f9SVitaliy Gusev 	if (type_flag == 0)
194*86d949f9SVitaliy Gusev 		type_flag = NFS_NFS_STAT | NFS_ACL_STAT | NFS_RPC_STAT;
195*86d949f9SVitaliy Gusev 
196*86d949f9SVitaliy Gusev 	if (host_flag & NFS_CB_STAT)
197*86d949f9SVitaliy Gusev 		if (nfs_srvstat_cb(&mdb_stats))
198*86d949f9SVitaliy Gusev 			return (DCMD_ERR);
199*86d949f9SVitaliy Gusev 	if (host_flag & NFS_SRV_STAT)
200*86d949f9SVitaliy Gusev 		if (nfs_stat_srv(&mdb_stats, type_flag, vers_flag))
201*86d949f9SVitaliy Gusev 			return (DCMD_ERR);
202*86d949f9SVitaliy Gusev 	if (host_flag & NFS_CLNT_STAT)
203*86d949f9SVitaliy Gusev 		if (nfs_stat_clnt(&mdb_stats, type_flag, vers_flag))
204*86d949f9SVitaliy Gusev 			return (DCMD_ERR);
205*86d949f9SVitaliy Gusev 	return (DCMD_OK);
206*86d949f9SVitaliy Gusev }
207*86d949f9SVitaliy Gusev 
208*86d949f9SVitaliy Gusev static int
nfs_srvstat_cb(nfs_mdb_stats_t * stptr)209*86d949f9SVitaliy Gusev nfs_srvstat_cb(nfs_mdb_stats_t *stptr)
210*86d949f9SVitaliy Gusev {
211*86d949f9SVitaliy Gusev 	int ret = 0;
212*86d949f9SVitaliy Gusev 	mdb_printf("CALLBACK STATISTICS:\n");
213*86d949f9SVitaliy Gusev 
214*86d949f9SVitaliy Gusev 	ret = prt_nfs_stats(stptr->callback_stats, "nfs4_callback_stats_tmpl");
215*86d949f9SVitaliy Gusev 
216*86d949f9SVitaliy Gusev 	return (ret);
217*86d949f9SVitaliy Gusev }
218*86d949f9SVitaliy Gusev 
219*86d949f9SVitaliy Gusev static int
nfs_stat_srv(nfs_mdb_stats_t * stptr,int type_flag,int vers_flag)220*86d949f9SVitaliy Gusev nfs_stat_srv(nfs_mdb_stats_t *stptr, int type_flag, int vers_flag)
221*86d949f9SVitaliy Gusev {
222*86d949f9SVitaliy Gusev 	mdb_printf("NFS SERVER STATS:\n");
223*86d949f9SVitaliy Gusev 	if (type_flag & NFS_SRV_STAT) {
224*86d949f9SVitaliy Gusev 		if (nfs_srvstat(stptr, vers_flag) != 0)
225*86d949f9SVitaliy Gusev 			return (1);
226*86d949f9SVitaliy Gusev 	}
227*86d949f9SVitaliy Gusev 	if (type_flag & NFS_RPC_STAT) {
228*86d949f9SVitaliy Gusev 		if (nfs_srvstat_rpc(stptr) != 0)
229*86d949f9SVitaliy Gusev 			return (1);
230*86d949f9SVitaliy Gusev 	}
231*86d949f9SVitaliy Gusev 	if (type_flag & NFS_ACL_STAT) {
232*86d949f9SVitaliy Gusev 		if (nfs_srvstat_acl(stptr, vers_flag) != 0)
233*86d949f9SVitaliy Gusev 			return (1);
234*86d949f9SVitaliy Gusev 	}
235*86d949f9SVitaliy Gusev 	return (0);
236*86d949f9SVitaliy Gusev }
237*86d949f9SVitaliy Gusev 
238*86d949f9SVitaliy Gusev static int
nfs_stat_clnt(nfs_mdb_stats_t * stptr,int type_flag,int vers_flag)239*86d949f9SVitaliy Gusev nfs_stat_clnt(nfs_mdb_stats_t *stptr, int type_flag, int vers_flag)
240*86d949f9SVitaliy Gusev {
241*86d949f9SVitaliy Gusev 	mdb_printf("CLIENT STATISTICS:\n");
242*86d949f9SVitaliy Gusev 	if (type_flag & NFS_CLNT_STAT) {
243*86d949f9SVitaliy Gusev 		if (nfs_clntstat(stptr, vers_flag))
244*86d949f9SVitaliy Gusev 			return (1);
245*86d949f9SVitaliy Gusev 	}
246*86d949f9SVitaliy Gusev 	if (type_flag & NFS_ACL_STAT) {
247*86d949f9SVitaliy Gusev 		if (nfs_clntstat_acl(stptr, vers_flag))
248*86d949f9SVitaliy Gusev 			return (1);
249*86d949f9SVitaliy Gusev 	}
250*86d949f9SVitaliy Gusev 	if (type_flag & NFS_RPC_STAT) {
251*86d949f9SVitaliy Gusev 		if (nfs_clntstat_rpc(stptr))
252*86d949f9SVitaliy Gusev 			return (1);
253*86d949f9SVitaliy Gusev 	}
254*86d949f9SVitaliy Gusev 	return (0);
255*86d949f9SVitaliy Gusev }
256*86d949f9SVitaliy Gusev 
257*86d949f9SVitaliy Gusev 
258*86d949f9SVitaliy Gusev static int
nfs_srvstat(nfs_mdb_stats_t * stptr,int flag)259*86d949f9SVitaliy Gusev nfs_srvstat(nfs_mdb_stats_t *stptr, int flag)
260*86d949f9SVitaliy Gusev {
261*86d949f9SVitaliy Gusev 	mdb_printf("NFS Statistics\n");
262*86d949f9SVitaliy Gusev 	if (flag & NFS_V2_STAT) {
263*86d949f9SVitaliy Gusev 		mdb_printf("NFSv2\n");
264*86d949f9SVitaliy Gusev 		if (prt_nfs_stats((uintptr_t)stptr->nfsglbls.svstat[2],
265*86d949f9SVitaliy Gusev 		    "svstat_tmpl") ||
266*86d949f9SVitaliy Gusev 		    prt_nfs_stats((uintptr_t)stptr->nfsglbls.rfsproccnt[2],
267*86d949f9SVitaliy Gusev 		    "rfsproccnt_v2_tmpl"))
268*86d949f9SVitaliy Gusev 			return (-1);
269*86d949f9SVitaliy Gusev 	}
270*86d949f9SVitaliy Gusev 	if (flag & NFS_V3_STAT) {
271*86d949f9SVitaliy Gusev 		mdb_printf("NFSv3\n");
272*86d949f9SVitaliy Gusev 		if (prt_nfs_stats((uintptr_t)stptr->nfsglbls.svstat[3],
273*86d949f9SVitaliy Gusev 		    "svstat_tmpl") ||
274*86d949f9SVitaliy Gusev 		    prt_nfs_stats((uintptr_t)stptr->nfsglbls.rfsproccnt[3],
275*86d949f9SVitaliy Gusev 		    "rfsproccnt_v3_tmpl"))
276*86d949f9SVitaliy Gusev 			return (-1);
277*86d949f9SVitaliy Gusev 	}
278*86d949f9SVitaliy Gusev 	if (flag & NFS_V4_STAT) {
279*86d949f9SVitaliy Gusev 		mdb_printf("NFSv4\n");
280*86d949f9SVitaliy Gusev 		if (prt_nfs_stats((uintptr_t)stptr->nfsglbls.svstat[4],
281*86d949f9SVitaliy Gusev 		    "svstat_tmpl") ||
282*86d949f9SVitaliy Gusev 		    prt_nfs_stats((uintptr_t)stptr->nfsglbls.rfsproccnt[4],
283*86d949f9SVitaliy Gusev 		    "rfsproccnt_v4_tmpl"))
284*86d949f9SVitaliy Gusev 			return (-1);
285*86d949f9SVitaliy Gusev 	}
286*86d949f9SVitaliy Gusev 	return (0);
287*86d949f9SVitaliy Gusev }
288*86d949f9SVitaliy Gusev 
289*86d949f9SVitaliy Gusev 
290*86d949f9SVitaliy Gusev static int
nfs_srvstat_rpc(nfs_mdb_stats_t * stptr)291*86d949f9SVitaliy Gusev nfs_srvstat_rpc(nfs_mdb_stats_t *stptr)
292*86d949f9SVitaliy Gusev {
293*86d949f9SVitaliy Gusev 	mdb_printf("NFS RPC Statistics\n");
294*86d949f9SVitaliy Gusev 	mdb_printf("ConnectionLess\n");
295*86d949f9SVitaliy Gusev 	if (prt_nfs_stats((uintptr_t)stptr->rpcstats.rpc_clts_server,
296*86d949f9SVitaliy Gusev 	    "clts_rsstat_tmpl"))
297*86d949f9SVitaliy Gusev 		return (-1);
298*86d949f9SVitaliy Gusev 	mdb_printf("ConnectionOriented\n");
299*86d949f9SVitaliy Gusev 	if (prt_nfs_stats((uintptr_t)stptr->rpcstats.rpc_cots_server,
300*86d949f9SVitaliy Gusev 	    "cots_rsstat_tmpl"))
301*86d949f9SVitaliy Gusev 		return (-1);
302*86d949f9SVitaliy Gusev 	return (0);
303*86d949f9SVitaliy Gusev }
304*86d949f9SVitaliy Gusev 
305*86d949f9SVitaliy Gusev 
306*86d949f9SVitaliy Gusev static int
nfs_srvstat_acl(nfs_mdb_stats_t * stptr,int flags)307*86d949f9SVitaliy Gusev nfs_srvstat_acl(nfs_mdb_stats_t *stptr, int flags)
308*86d949f9SVitaliy Gusev {
309*86d949f9SVitaliy Gusev 	mdb_printf("NFS ACL Statistics\n");
310*86d949f9SVitaliy Gusev 	if (flags & NFS_V2_STAT) {
311*86d949f9SVitaliy Gusev 		mdb_printf("NFSv2\n");
312*86d949f9SVitaliy Gusev 		if (prt_nfs_stats((uintptr_t)stptr->nfsglbls.aclproccnt[2],
313*86d949f9SVitaliy Gusev 		    "aclproccnt_v2_tmpl"))
314*86d949f9SVitaliy Gusev 			return (-1);
315*86d949f9SVitaliy Gusev 	}
316*86d949f9SVitaliy Gusev 	if (flags & NFS_V3_STAT) {
317*86d949f9SVitaliy Gusev 		mdb_printf("NFSv3\n");
318*86d949f9SVitaliy Gusev 		if (prt_nfs_stats((uintptr_t)stptr->nfsglbls.aclproccnt[3],
319*86d949f9SVitaliy Gusev 		    "aclproccnt_v3_tmpl"))
320*86d949f9SVitaliy Gusev 			return (-1);
321*86d949f9SVitaliy Gusev 	}
322*86d949f9SVitaliy Gusev 	if (flags & NFS_V4_STAT) {
323*86d949f9SVitaliy Gusev 		mdb_printf("NFSv4\n");
324*86d949f9SVitaliy Gusev 		if (prt_nfs_stats((uintptr_t)stptr->nfsglbls.aclproccnt[4],
325*86d949f9SVitaliy Gusev 		    "aclreqcnt_v4_tmpl"))
326*86d949f9SVitaliy Gusev 			return (-1);
327*86d949f9SVitaliy Gusev 	}
328*86d949f9SVitaliy Gusev 	return (0);
329*86d949f9SVitaliy Gusev }
330*86d949f9SVitaliy Gusev 
331*86d949f9SVitaliy Gusev static int
nfs_clntstat(nfs_mdb_stats_t * stptr,int flags)332*86d949f9SVitaliy Gusev nfs_clntstat(nfs_mdb_stats_t *stptr, int flags)
333*86d949f9SVitaliy Gusev {
334*86d949f9SVitaliy Gusev 	mdb_printf("NFS Statistics\n");
335*86d949f9SVitaliy Gusev 	if (prt_nfs_stats((uintptr_t)stptr->clntstat, "clstat_tmpl"))
336*86d949f9SVitaliy Gusev 		return (-1);
337*86d949f9SVitaliy Gusev 	if (flags & NFS_V2_STAT) {
338*86d949f9SVitaliy Gusev 		mdb_printf("Version 2\n");
339*86d949f9SVitaliy Gusev 		if (prt_nfs_stats(
340*86d949f9SVitaliy Gusev 		    (uintptr_t)stptr->nfsstats.nfs_stats_v2.rfsreqcnt_ptr,
341*86d949f9SVitaliy Gusev 		    "rfsreqcnt_v2_tmpl"))
342*86d949f9SVitaliy Gusev 			return (-1);
343*86d949f9SVitaliy Gusev 	}
344*86d949f9SVitaliy Gusev 	if (flags & NFS_V3_STAT) {
345*86d949f9SVitaliy Gusev 		mdb_printf("Version 3\n");
346*86d949f9SVitaliy Gusev 		if (prt_nfs_stats(
347*86d949f9SVitaliy Gusev 		    (uintptr_t)stptr->nfsstats.nfs_stats_v3.rfsreqcnt_ptr,
348*86d949f9SVitaliy Gusev 		    "rfsreqcnt_v3_tmpl"))
349*86d949f9SVitaliy Gusev 			return (-1);
350*86d949f9SVitaliy Gusev 	}
351*86d949f9SVitaliy Gusev 	if (flags & NFS_V4_STAT) {
352*86d949f9SVitaliy Gusev 		mdb_printf("NFSv4 client\n");
353*86d949f9SVitaliy Gusev 		if (prt_nfs_stats((uintptr_t)stptr->clntstat, "clstat4_tmpl"))
354*86d949f9SVitaliy Gusev 			return (-1);
355*86d949f9SVitaliy Gusev 		mdb_printf("Version 4\n");
356*86d949f9SVitaliy Gusev 		if (prt_nfs_stats(
357*86d949f9SVitaliy Gusev 		    (uintptr_t)stptr->nfsstats.nfs_stats_v4.rfsreqcnt_ptr,
358*86d949f9SVitaliy Gusev 		    "rfsreqcnt_v4_tmpl"))
359*86d949f9SVitaliy Gusev 			return (-1);
360*86d949f9SVitaliy Gusev 	}
361*86d949f9SVitaliy Gusev 	return (0);
362*86d949f9SVitaliy Gusev }
363*86d949f9SVitaliy Gusev 
364*86d949f9SVitaliy Gusev static int
nfs_clntstat_rpc(nfs_mdb_stats_t * stptr)365*86d949f9SVitaliy Gusev nfs_clntstat_rpc(nfs_mdb_stats_t *stptr)
366*86d949f9SVitaliy Gusev {
367*86d949f9SVitaliy Gusev 	mdb_printf("NFS RPC Statistics\n");
368*86d949f9SVitaliy Gusev 	mdb_printf("ConnectionLess\n");
369*86d949f9SVitaliy Gusev 	if (prt_nfs_stats((uintptr_t)stptr->rpcstats.rpc_clts_client,
370*86d949f9SVitaliy Gusev 	    "clts_rcstat_tmpl"))
371*86d949f9SVitaliy Gusev 		return (-1);
372*86d949f9SVitaliy Gusev 	mdb_printf("ConnectionOriented\n");
373*86d949f9SVitaliy Gusev 	if (prt_nfs_stats((uintptr_t)stptr->rpcstats.rpc_cots_client,
374*86d949f9SVitaliy Gusev 	    "cots_rcstat_tmpl"))
375*86d949f9SVitaliy Gusev 		return (-1);
376*86d949f9SVitaliy Gusev 	return (0);
377*86d949f9SVitaliy Gusev }
378*86d949f9SVitaliy Gusev 
379*86d949f9SVitaliy Gusev static int
nfs_clntstat_acl(nfs_mdb_stats_t * stptr,int flags)380*86d949f9SVitaliy Gusev nfs_clntstat_acl(nfs_mdb_stats_t *stptr, int flags)
381*86d949f9SVitaliy Gusev {
382*86d949f9SVitaliy Gusev 	mdb_printf("ACL Statistics\n");
383*86d949f9SVitaliy Gusev 	if (flags & NFS_V2_STAT) {
384*86d949f9SVitaliy Gusev 		mdb_printf("Version 2\n");
385*86d949f9SVitaliy Gusev 		if (prt_nfs_stats(
386*86d949f9SVitaliy Gusev 		    (uintptr_t)stptr->nfsstats.nfs_stats_v2.aclreqcnt_ptr,
387*86d949f9SVitaliy Gusev 		    "aclreqcnt_v2_tmpl"))
388*86d949f9SVitaliy Gusev 			return (-1);
389*86d949f9SVitaliy Gusev 	}
390*86d949f9SVitaliy Gusev 	if (flags & NFS_V3_STAT) {
391*86d949f9SVitaliy Gusev 		mdb_printf("Version 3\n");
392*86d949f9SVitaliy Gusev 		if (prt_nfs_stats(
393*86d949f9SVitaliy Gusev 		    (uintptr_t)stptr->nfsstats.nfs_stats_v3.aclreqcnt_ptr,
394*86d949f9SVitaliy Gusev 		    "aclreqcnt_v3_tmpl"))
395*86d949f9SVitaliy Gusev 			return (-1);
396*86d949f9SVitaliy Gusev 	}
397*86d949f9SVitaliy Gusev 	if (flags & NFS_V4_STAT) {
398*86d949f9SVitaliy Gusev 		mdb_printf("Version 4\n");
399*86d949f9SVitaliy Gusev 		if (prt_nfs_stats(
400*86d949f9SVitaliy Gusev 		    (uintptr_t)stptr->nfsstats.nfs_stats_v4.aclreqcnt_ptr,
401*86d949f9SVitaliy Gusev 		    "aclreqcnt_v4_tmpl"))
402*86d949f9SVitaliy Gusev 			return (-1);
403*86d949f9SVitaliy Gusev 	}
404*86d949f9SVitaliy Gusev 	return (0);
405*86d949f9SVitaliy Gusev }
406*86d949f9SVitaliy Gusev 
407*86d949f9SVitaliy Gusev 
408*86d949f9SVitaliy Gusev /*
409*86d949f9SVitaliy Gusev  * helper functions for printing out the kstat data
410*86d949f9SVitaliy Gusev  */
411*86d949f9SVitaliy Gusev 
412*86d949f9SVitaliy Gusev #define	NFS_STAT_NUM_CLMNS 16
413*86d949f9SVitaliy Gusev 
414*86d949f9SVitaliy Gusev static int
prt_nfs_stats(uintptr_t addr,char * name)415*86d949f9SVitaliy Gusev prt_nfs_stats(uintptr_t addr, char *name)
416*86d949f9SVitaliy Gusev {
417*86d949f9SVitaliy Gusev 
418*86d949f9SVitaliy Gusev 	GElf_Sym sym;
419*86d949f9SVitaliy Gusev 	kstat_named_t kstats;
420*86d949f9SVitaliy Gusev 	char *kstat_line;
421*86d949f9SVitaliy Gusev 	uint64_t *value;
422*86d949f9SVitaliy Gusev 	uint_t count;
423*86d949f9SVitaliy Gusev 	int i = 0, status = 0;
424*86d949f9SVitaliy Gusev 
425*86d949f9SVitaliy Gusev 
426*86d949f9SVitaliy Gusev 	if (mdb_lookup_by_name(name, &sym) != 0) {
427*86d949f9SVitaliy Gusev 		mdb_warn("failed to find %s", name);
428*86d949f9SVitaliy Gusev 		return (1);
429*86d949f9SVitaliy Gusev 	}
430*86d949f9SVitaliy Gusev 
431*86d949f9SVitaliy Gusev 	count = sym.st_size / sizeof (kstat_named_t);
432*86d949f9SVitaliy Gusev 
433*86d949f9SVitaliy Gusev 	kstat_line = mdb_alloc(count * NFS_STAT_NUM_CLMNS, UM_SLEEP);
434*86d949f9SVitaliy Gusev 	value = mdb_alloc(count * sizeof (uint64_t), UM_SLEEP);
435*86d949f9SVitaliy Gusev 	for (i = 0; i < count; i++) {
436*86d949f9SVitaliy Gusev 		if (mdb_vread(&kstats, sizeof (kstat_named_t),
437*86d949f9SVitaliy Gusev 		    addr + (i * sizeof (kstat_named_t))) < 0) {
438*86d949f9SVitaliy Gusev 			status = 1;
439*86d949f9SVitaliy Gusev 			goto done;
440*86d949f9SVitaliy Gusev 		}
441*86d949f9SVitaliy Gusev 		mdb_snprintf(&kstat_line[NFS_STAT_NUM_CLMNS * i],
442*86d949f9SVitaliy Gusev 		    NFS_STAT_NUM_CLMNS, "%s", kstats.name);
443*86d949f9SVitaliy Gusev 		value[i] = kstats.value.ui64;
444*86d949f9SVitaliy Gusev 	}
445*86d949f9SVitaliy Gusev 	kstat_prtout(kstat_line, value, count);
446*86d949f9SVitaliy Gusev done:
447*86d949f9SVitaliy Gusev 	mdb_free(kstat_line, count * NFS_STAT_NUM_CLMNS);
448*86d949f9SVitaliy Gusev 	mdb_free(value, count * sizeof (uint64_t));
449*86d949f9SVitaliy Gusev 	return (status);
450*86d949f9SVitaliy Gusev }
451*86d949f9SVitaliy Gusev 
452*86d949f9SVitaliy Gusev static void
kstat_prtout(char * ks_line,uint64_t * values,int count)453*86d949f9SVitaliy Gusev kstat_prtout(char *ks_line, uint64_t *values, int count)
454*86d949f9SVitaliy Gusev {
455*86d949f9SVitaliy Gusev 	char val_str[32];
456*86d949f9SVitaliy Gusev 	int i = 0, num = 0;
457*86d949f9SVitaliy Gusev 
458*86d949f9SVitaliy Gusev 	while (i < count) {
459*86d949f9SVitaliy Gusev 		mdb_printf("%-*s", NFS_STAT_NUM_CLMNS,
460*86d949f9SVitaliy Gusev 		    &ks_line[NFS_STAT_NUM_CLMNS * i]);
461*86d949f9SVitaliy Gusev 
462*86d949f9SVitaliy Gusev 		num++;
463*86d949f9SVitaliy Gusev 		if (num == NFS_STAT_NUM_STATS / NFS_STAT_NUM_CLMNS) {
464*86d949f9SVitaliy Gusev 			mdb_printf("\n");
465*86d949f9SVitaliy Gusev 			while (num > 0) {
466*86d949f9SVitaliy Gusev 				mdb_snprintf(val_str, 24, "%ld  ",
467*86d949f9SVitaliy Gusev 				    values[i+1-num]);
468*86d949f9SVitaliy Gusev 				mdb_printf("%-*s", NFS_STAT_NUM_CLMNS, val_str);
469*86d949f9SVitaliy Gusev 				--num;
470*86d949f9SVitaliy Gusev 			}
471*86d949f9SVitaliy Gusev 			mdb_printf("\n");
472*86d949f9SVitaliy Gusev 		}
473*86d949f9SVitaliy Gusev 		i++;
474*86d949f9SVitaliy Gusev 	}
475*86d949f9SVitaliy Gusev 	mdb_printf("\n");
476*86d949f9SVitaliy Gusev }
477