xref: /illumos-gate/usr/src/cmd/mdb/common/modules/klmmod/klmmod.c (revision 86d949f9497332fe19be6b5d711d265eb957439f)
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 /*
13*86d949f9SVitaliy Gusev  * Copyright 2021 Tintri by DDN, Inc. All rights reserved.
14*86d949f9SVitaliy Gusev  */
15*86d949f9SVitaliy Gusev 
16*86d949f9SVitaliy Gusev #include <sys/mdb_modapi.h>
17*86d949f9SVitaliy Gusev #include <mdb/mdb_ctf.h>
18*86d949f9SVitaliy Gusev #include <sys/vnode.h>
19*86d949f9SVitaliy Gusev #include <stddef.h>
20*86d949f9SVitaliy Gusev #include <nfs/rnode.h>
21*86d949f9SVitaliy Gusev #include <limits.h>
22*86d949f9SVitaliy Gusev #include <nfs/lm.h>
23*86d949f9SVitaliy Gusev #include <sys/flock_impl.h>
24*86d949f9SVitaliy Gusev #include <mdb/mdb_ks.h>
25*86d949f9SVitaliy Gusev 
26*86d949f9SVitaliy Gusev #include <rpcsvc/nlm_prot.h>
27*86d949f9SVitaliy Gusev #include <rpcsvc/sm_inter.h>
28*86d949f9SVitaliy Gusev #include <rpcsvc/nsm_addr.h>
29*86d949f9SVitaliy Gusev 
30*86d949f9SVitaliy Gusev #include "klm/nlm_impl.h"
31*86d949f9SVitaliy Gusev 
32*86d949f9SVitaliy Gusev #define	NLM_MAXNAMELEN	256
33*86d949f9SVitaliy Gusev #define	NLM_MAXADDRSTR	64
34*86d949f9SVitaliy Gusev 
35*86d949f9SVitaliy Gusev /*
36*86d949f9SVitaliy Gusev  * ****************************************************************
37*86d949f9SVitaliy Gusev  * Helper functions
38*86d949f9SVitaliy Gusev  */
39*86d949f9SVitaliy Gusev 
40*86d949f9SVitaliy Gusev /*
41*86d949f9SVitaliy Gusev  * Helper to get printable IP address into a buffer.
42*86d949f9SVitaliy Gusev  * Used by nlm_host_dcmd
43*86d949f9SVitaliy Gusev  */
44*86d949f9SVitaliy Gusev static int
nlm_netbuf_str(char * buf,size_t bufsz,const struct netbuf * nb)45*86d949f9SVitaliy Gusev nlm_netbuf_str(char *buf, size_t bufsz, const struct netbuf *nb)
46*86d949f9SVitaliy Gusev {
47*86d949f9SVitaliy Gusev 	struct sockaddr_storage sa;
48*86d949f9SVitaliy Gusev 	struct sockaddr_in *s_in;
49*86d949f9SVitaliy Gusev 	struct sockaddr_in6 *s_in6;
50*86d949f9SVitaliy Gusev 	uint_t salen = nb->len;
51*86d949f9SVitaliy Gusev 	in_port_t port;
52*86d949f9SVitaliy Gusev 
53*86d949f9SVitaliy Gusev 	if (salen < sizeof (sa_family_t))
54*86d949f9SVitaliy Gusev 		return (-1);
55*86d949f9SVitaliy Gusev 	if (salen > sizeof (sa))
56*86d949f9SVitaliy Gusev 		salen = sizeof (sa);
57*86d949f9SVitaliy Gusev 	if (mdb_vread(&sa, salen, (uintptr_t)nb->buf) < 0)
58*86d949f9SVitaliy Gusev 		return (-1);
59*86d949f9SVitaliy Gusev 
60*86d949f9SVitaliy Gusev 	switch (sa.ss_family) {
61*86d949f9SVitaliy Gusev 	case AF_INET:
62*86d949f9SVitaliy Gusev 		s_in = (struct sockaddr_in *)(void *)&sa;
63*86d949f9SVitaliy Gusev 		mdb_nhconvert(&port, &s_in->sin_port, sizeof (port));
64*86d949f9SVitaliy Gusev 		mdb_snprintf(buf, bufsz, "%I/%d",
65*86d949f9SVitaliy Gusev 		    s_in->sin_addr.s_addr, port);
66*86d949f9SVitaliy Gusev 		break;
67*86d949f9SVitaliy Gusev 
68*86d949f9SVitaliy Gusev 	case AF_INET6:
69*86d949f9SVitaliy Gusev 		s_in6 = (struct sockaddr_in6 *)(void *)&sa;
70*86d949f9SVitaliy Gusev 		mdb_nhconvert(&port, &s_in6->sin6_port, sizeof (port));
71*86d949f9SVitaliy Gusev 		mdb_snprintf(buf, bufsz, "%N/%d",
72*86d949f9SVitaliy Gusev 		    &(s_in6->sin6_addr), port);
73*86d949f9SVitaliy Gusev 		break;
74*86d949f9SVitaliy Gusev 
75*86d949f9SVitaliy Gusev 	default:
76*86d949f9SVitaliy Gusev 		mdb_printf("AF_%d", sa.ss_family);
77*86d949f9SVitaliy Gusev 		break;
78*86d949f9SVitaliy Gusev 	}
79*86d949f9SVitaliy Gusev 
80*86d949f9SVitaliy Gusev 	return (0);
81*86d949f9SVitaliy Gusev }
82*86d949f9SVitaliy Gusev 
83*86d949f9SVitaliy Gusev /*
84*86d949f9SVitaliy Gusev  * Get the name for an enum value
85*86d949f9SVitaliy Gusev  */
86*86d949f9SVitaliy Gusev static void
get_enum(char * obuf,size_t size,const char * type_str,int val,const char * prefix)87*86d949f9SVitaliy Gusev get_enum(char *obuf, size_t size, const char *type_str, int val,
88*86d949f9SVitaliy Gusev     const char *prefix)
89*86d949f9SVitaliy Gusev {
90*86d949f9SVitaliy Gusev 	mdb_ctf_id_t type_id;
91*86d949f9SVitaliy Gusev 	const char *cp;
92*86d949f9SVitaliy Gusev 
93*86d949f9SVitaliy Gusev 	if (mdb_ctf_lookup_by_name(type_str, &type_id) != 0)
94*86d949f9SVitaliy Gusev 		goto errout;
95*86d949f9SVitaliy Gusev 	if (mdb_ctf_type_resolve(type_id, &type_id) != 0)
96*86d949f9SVitaliy Gusev 		goto errout;
97*86d949f9SVitaliy Gusev 	if ((cp = mdb_ctf_enum_name(type_id, val)) == NULL)
98*86d949f9SVitaliy Gusev 		goto errout;
99*86d949f9SVitaliy Gusev 	if (prefix != NULL) {
100*86d949f9SVitaliy Gusev 		size_t len = strlen(prefix);
101*86d949f9SVitaliy Gusev 		if (strncmp(cp, prefix, len) == 0)
102*86d949f9SVitaliy Gusev 			cp += len;
103*86d949f9SVitaliy Gusev 	}
104*86d949f9SVitaliy Gusev 	(void) strlcpy(obuf, cp, size);
105*86d949f9SVitaliy Gusev 	return;
106*86d949f9SVitaliy Gusev 
107*86d949f9SVitaliy Gusev errout:
108*86d949f9SVitaliy Gusev 	mdb_snprintf(obuf, size, "? (%d)", val);
109*86d949f9SVitaliy Gusev }
110*86d949f9SVitaliy Gusev 
111*86d949f9SVitaliy Gusev static const mdb_bitmask_t
112*86d949f9SVitaliy Gusev host_flag_bits[] = {
113*86d949f9SVitaliy Gusev 	{
114*86d949f9SVitaliy Gusev 		"MONITORED",
115*86d949f9SVitaliy Gusev 		NLM_NH_MONITORED,
116*86d949f9SVitaliy Gusev 		NLM_NH_MONITORED },
117*86d949f9SVitaliy Gusev 	{
118*86d949f9SVitaliy Gusev 		"RECLAIM",
119*86d949f9SVitaliy Gusev 		NLM_NH_RECLAIM,
120*86d949f9SVitaliy Gusev 		NLM_NH_RECLAIM },
121*86d949f9SVitaliy Gusev 	{
122*86d949f9SVitaliy Gusev 		"INIDLE",
123*86d949f9SVitaliy Gusev 		NLM_NH_INIDLE,
124*86d949f9SVitaliy Gusev 		NLM_NH_INIDLE },
125*86d949f9SVitaliy Gusev 	{
126*86d949f9SVitaliy Gusev 		"SUSPEND",
127*86d949f9SVitaliy Gusev 		NLM_NH_SUSPEND,
128*86d949f9SVitaliy Gusev 		NLM_NH_SUSPEND },
129*86d949f9SVitaliy Gusev 	{
130*86d949f9SVitaliy Gusev 		NULL, 0, 0 }
131*86d949f9SVitaliy Gusev };
132*86d949f9SVitaliy Gusev 
133*86d949f9SVitaliy Gusev /*
134*86d949f9SVitaliy Gusev  * ****************************************************************
135*86d949f9SVitaliy Gusev  * NLM zones (top level)
136*86d949f9SVitaliy Gusev  */
137*86d949f9SVitaliy Gusev 
138*86d949f9SVitaliy Gusev /*
139*86d949f9SVitaliy Gusev  * nlm_zone walker implementation
140*86d949f9SVitaliy Gusev  */
141*86d949f9SVitaliy Gusev 
142*86d949f9SVitaliy Gusev int
nlm_zone_walk_init(mdb_walk_state_t * wsp)143*86d949f9SVitaliy Gusev nlm_zone_walk_init(mdb_walk_state_t *wsp)
144*86d949f9SVitaliy Gusev {
145*86d949f9SVitaliy Gusev 
146*86d949f9SVitaliy Gusev 	/*
147*86d949f9SVitaliy Gusev 	 * Technically, this is "cheating" with the knowledge that
148*86d949f9SVitaliy Gusev 	 * the TAILQ_HEAD link is at the beginning of this object.
149*86d949f9SVitaliy Gusev 	 */
150*86d949f9SVitaliy Gusev 	if (wsp->walk_addr == 0 && mdb_readsym(&wsp->walk_addr,
151*86d949f9SVitaliy Gusev 	    sizeof (wsp->walk_addr), "nlm_zones_list") == -1) {
152*86d949f9SVitaliy Gusev 		mdb_warn("failed to read 'nlm_zones_list'");
153*86d949f9SVitaliy Gusev 		return (WALK_ERR);
154*86d949f9SVitaliy Gusev 	}
155*86d949f9SVitaliy Gusev 
156*86d949f9SVitaliy Gusev 	return (WALK_NEXT);
157*86d949f9SVitaliy Gusev }
158*86d949f9SVitaliy Gusev 
159*86d949f9SVitaliy Gusev int
nlm_zone_walk_step(mdb_walk_state_t * wsp)160*86d949f9SVitaliy Gusev nlm_zone_walk_step(mdb_walk_state_t *wsp)
161*86d949f9SVitaliy Gusev {
162*86d949f9SVitaliy Gusev 	struct nlm_globals g;
163*86d949f9SVitaliy Gusev 	uintptr_t addr = wsp->walk_addr;
164*86d949f9SVitaliy Gusev 
165*86d949f9SVitaliy Gusev 	if (addr == 0)
166*86d949f9SVitaliy Gusev 		return (WALK_DONE);
167*86d949f9SVitaliy Gusev 
168*86d949f9SVitaliy Gusev 	if (mdb_vread(&g, sizeof (g), addr) < 0) {
169*86d949f9SVitaliy Gusev 		mdb_warn("failed to read nlm_globals at %p", addr);
170*86d949f9SVitaliy Gusev 		return (WALK_ERR);
171*86d949f9SVitaliy Gusev 	}
172*86d949f9SVitaliy Gusev 
173*86d949f9SVitaliy Gusev 	wsp->walk_addr = (uintptr_t)TAILQ_NEXT(&g, nlm_link);
174*86d949f9SVitaliy Gusev 	return (wsp->walk_callback(addr, &g, wsp->walk_cbdata));
175*86d949f9SVitaliy Gusev }
176*86d949f9SVitaliy Gusev 
177*86d949f9SVitaliy Gusev /*
178*86d949f9SVitaliy Gusev  * nlm_zone dcmd implementation
179*86d949f9SVitaliy Gusev  */
180*86d949f9SVitaliy Gusev 
181*86d949f9SVitaliy Gusev static void nlm_zone_print(uintptr_t, const struct nlm_globals *, uint_t);
182*86d949f9SVitaliy Gusev 
183*86d949f9SVitaliy Gusev void
nlm_zone_help(void)184*86d949f9SVitaliy Gusev nlm_zone_help(void)
185*86d949f9SVitaliy Gusev {
186*86d949f9SVitaliy Gusev 	mdb_printf("-v		verbose information\n");
187*86d949f9SVitaliy Gusev }
188*86d949f9SVitaliy Gusev 
189*86d949f9SVitaliy Gusev int
nlm_zone_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)190*86d949f9SVitaliy Gusev nlm_zone_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
191*86d949f9SVitaliy Gusev {
192*86d949f9SVitaliy Gusev 	struct nlm_globals g;
193*86d949f9SVitaliy Gusev 	char enum_val[32];
194*86d949f9SVitaliy Gusev 	uint_t opt_v = FALSE;
195*86d949f9SVitaliy Gusev 
196*86d949f9SVitaliy Gusev 	if (mdb_getopts(argc, argv,
197*86d949f9SVitaliy Gusev 	    'v', MDB_OPT_SETBITS, TRUE, &opt_v, NULL) != argc)
198*86d949f9SVitaliy Gusev 		return (DCMD_USAGE);
199*86d949f9SVitaliy Gusev 
200*86d949f9SVitaliy Gusev 	if ((flags & DCMD_ADDRSPEC) == 0) {
201*86d949f9SVitaliy Gusev 		mdb_warn("requires addr of nlm_zone");
202*86d949f9SVitaliy Gusev 		return (DCMD_ERR);
203*86d949f9SVitaliy Gusev 	}
204*86d949f9SVitaliy Gusev 
205*86d949f9SVitaliy Gusev 	if (mdb_vread(&g, sizeof (g), addr) == -1) {
206*86d949f9SVitaliy Gusev 		mdb_warn("failed to read nlm_globals at %p", addr);
207*86d949f9SVitaliy Gusev 		return (DCMD_ERR);
208*86d949f9SVitaliy Gusev 	}
209*86d949f9SVitaliy Gusev 
210*86d949f9SVitaliy Gusev 	if (opt_v == FALSE) {
211*86d949f9SVitaliy Gusev 		nlm_zone_print(addr, &g, flags);
212*86d949f9SVitaliy Gusev 		return (DCMD_OK);
213*86d949f9SVitaliy Gusev 	}
214*86d949f9SVitaliy Gusev 
215*86d949f9SVitaliy Gusev 	/*
216*86d949f9SVitaliy Gusev 	 * Print verbose format
217*86d949f9SVitaliy Gusev 	 */
218*86d949f9SVitaliy Gusev 	mdb_printf("%<b>%<u>NLM zone globals (%p):%</u>%</b>\n", addr);
219*86d949f9SVitaliy Gusev 	mdb_printf(" Lockd PID: %u\n", g.lockd_pid);
220*86d949f9SVitaliy Gusev 	get_enum(enum_val, sizeof (enum_val),
221*86d949f9SVitaliy Gusev 	    "nlm_run_status_t", g.run_status, "NLM_S_");
222*86d949f9SVitaliy Gusev 	mdb_printf("Run status: %d (%s)\n", g.run_status, enum_val);
223*86d949f9SVitaliy Gusev 	mdb_printf(" NSM state: %d\n", g.nsm_state);
224*86d949f9SVitaliy Gusev 
225*86d949f9SVitaliy Gusev 	return (DCMD_OK);
226*86d949f9SVitaliy Gusev }
227*86d949f9SVitaliy Gusev 
228*86d949f9SVitaliy Gusev /*
229*86d949f9SVitaliy Gusev  * Shared by nlm_zone_dcmd and nlm_list_zone_cb
230*86d949f9SVitaliy Gusev  * Print a zone (nlm_globals) summary line.
231*86d949f9SVitaliy Gusev  */
232*86d949f9SVitaliy Gusev static void
nlm_zone_print(uintptr_t addr,const struct nlm_globals * g,uint_t flags)233*86d949f9SVitaliy Gusev nlm_zone_print(uintptr_t addr, const struct nlm_globals *g, uint_t flags)
234*86d949f9SVitaliy Gusev {
235*86d949f9SVitaliy Gusev 
236*86d949f9SVitaliy Gusev 	if (DCMD_HDRSPEC(flags)) {
237*86d949f9SVitaliy Gusev 		mdb_printf(
238*86d949f9SVitaliy Gusev 		    "%<b>%<u>%?-s  %-16s %</u>%</b>\n",
239*86d949f9SVitaliy Gusev 		    "nlm_globals", "pid");
240*86d949f9SVitaliy Gusev 	}
241*86d949f9SVitaliy Gusev 
242*86d949f9SVitaliy Gusev 	mdb_printf("%-?p %6d\n", addr, (int)g->lockd_pid);
243*86d949f9SVitaliy Gusev }
244*86d949f9SVitaliy Gusev 
245*86d949f9SVitaliy Gusev /*
246*86d949f9SVitaliy Gusev  * ****************************************************************
247*86d949f9SVitaliy Gusev  * NLM hosts (under zones)
248*86d949f9SVitaliy Gusev  */
249*86d949f9SVitaliy Gusev 
250*86d949f9SVitaliy Gusev /*
251*86d949f9SVitaliy Gusev  * nlm_host walker implementation
252*86d949f9SVitaliy Gusev  */
253*86d949f9SVitaliy Gusev 
254*86d949f9SVitaliy Gusev int
nlm_host_walk_init(mdb_walk_state_t * wsp)255*86d949f9SVitaliy Gusev nlm_host_walk_init(mdb_walk_state_t *wsp)
256*86d949f9SVitaliy Gusev {
257*86d949f9SVitaliy Gusev 	static int avl_off = -1;
258*86d949f9SVitaliy Gusev 
259*86d949f9SVitaliy Gusev 	if (wsp->walk_addr == 0) {
260*86d949f9SVitaliy Gusev 		mdb_printf("requires address of struct nlm_globals\n");
261*86d949f9SVitaliy Gusev 		return (WALK_ERR);
262*86d949f9SVitaliy Gusev 	}
263*86d949f9SVitaliy Gusev 
264*86d949f9SVitaliy Gusev 	/*
265*86d949f9SVitaliy Gusev 	 * Need the address of the nlm_hosts_tree AVL head
266*86d949f9SVitaliy Gusev 	 * within the nlm_globals, for the AVL walker.
267*86d949f9SVitaliy Gusev 	 */
268*86d949f9SVitaliy Gusev 	if (avl_off < 0) {
269*86d949f9SVitaliy Gusev 		avl_off = mdb_ctf_offsetof_by_name(
270*86d949f9SVitaliy Gusev 		    "struct nlm_globals", "nlm_hosts_tree");
271*86d949f9SVitaliy Gusev 	}
272*86d949f9SVitaliy Gusev 	if (avl_off < 0) {
273*86d949f9SVitaliy Gusev 		mdb_warn("cannot lookup: nlm_globals .nlm_hosts_tree");
274*86d949f9SVitaliy Gusev 		return (WALK_ERR);
275*86d949f9SVitaliy Gusev 	}
276*86d949f9SVitaliy Gusev 	wsp->walk_addr += avl_off;
277*86d949f9SVitaliy Gusev 
278*86d949f9SVitaliy Gusev 	if (mdb_layered_walk("avl", wsp) == -1) {
279*86d949f9SVitaliy Gusev 		mdb_warn("failed to walk nlm_globals .nlm_hosts_tree");
280*86d949f9SVitaliy Gusev 		return (WALK_ERR);
281*86d949f9SVitaliy Gusev 	}
282*86d949f9SVitaliy Gusev 
283*86d949f9SVitaliy Gusev 	return (WALK_NEXT);
284*86d949f9SVitaliy Gusev }
285*86d949f9SVitaliy Gusev 
286*86d949f9SVitaliy Gusev int
nlm_host_walk_step(mdb_walk_state_t * wsp)287*86d949f9SVitaliy Gusev nlm_host_walk_step(mdb_walk_state_t *wsp)
288*86d949f9SVitaliy Gusev {
289*86d949f9SVitaliy Gusev 	struct nlm_host nh;
290*86d949f9SVitaliy Gusev 	uintptr_t addr = wsp->walk_addr;
291*86d949f9SVitaliy Gusev 
292*86d949f9SVitaliy Gusev 	if (mdb_vread(&nh, sizeof (nh), addr) < 0) {
293*86d949f9SVitaliy Gusev 		mdb_warn("failed to read nlm_host at %p", addr);
294*86d949f9SVitaliy Gusev 		return (WALK_ERR);
295*86d949f9SVitaliy Gusev 	}
296*86d949f9SVitaliy Gusev 
297*86d949f9SVitaliy Gusev 	/* layered walk avl */
298*86d949f9SVitaliy Gusev 	return (wsp->walk_callback(wsp->walk_addr, &nh,
299*86d949f9SVitaliy Gusev 	    wsp->walk_cbdata));
300*86d949f9SVitaliy Gusev }
301*86d949f9SVitaliy Gusev 
302*86d949f9SVitaliy Gusev /*
303*86d949f9SVitaliy Gusev  * nlm_host dcmd implementation
304*86d949f9SVitaliy Gusev  */
305*86d949f9SVitaliy Gusev 
306*86d949f9SVitaliy Gusev static void nlm_host_print(uintptr_t, const struct nlm_host *,
307*86d949f9SVitaliy Gusev     char *, char *, uint_t);
308*86d949f9SVitaliy Gusev 
309*86d949f9SVitaliy Gusev void
nlm_host_help(void)310*86d949f9SVitaliy Gusev nlm_host_help(void)
311*86d949f9SVitaliy Gusev {
312*86d949f9SVitaliy Gusev 	mdb_printf("-v       verbose information\n");
313*86d949f9SVitaliy Gusev }
314*86d949f9SVitaliy Gusev 
315*86d949f9SVitaliy Gusev int
nlm_host_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)316*86d949f9SVitaliy Gusev nlm_host_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
317*86d949f9SVitaliy Gusev {
318*86d949f9SVitaliy Gusev 	struct nlm_host nh;
319*86d949f9SVitaliy Gusev 	char hname[NLM_MAXNAMELEN];
320*86d949f9SVitaliy Gusev 	char haddr[NLM_MAXADDRSTR];
321*86d949f9SVitaliy Gusev 	uint_t opt_v = FALSE;
322*86d949f9SVitaliy Gusev 
323*86d949f9SVitaliy Gusev 	if (mdb_getopts(argc, argv,
324*86d949f9SVitaliy Gusev 	    'v', MDB_OPT_SETBITS, TRUE, &opt_v, NULL) != argc)
325*86d949f9SVitaliy Gusev 		return (DCMD_USAGE);
326*86d949f9SVitaliy Gusev 
327*86d949f9SVitaliy Gusev 	if ((flags & DCMD_ADDRSPEC) == 0) {
328*86d949f9SVitaliy Gusev 		mdb_warn("requires addr of nlm_host");
329*86d949f9SVitaliy Gusev 		return (DCMD_ERR);
330*86d949f9SVitaliy Gusev 	}
331*86d949f9SVitaliy Gusev 
332*86d949f9SVitaliy Gusev 	/* Get the nlm_host */
333*86d949f9SVitaliy Gusev 	if (mdb_vread(&nh, sizeof (nh), addr) == -1) {
334*86d949f9SVitaliy Gusev 		mdb_warn("failed to read nlm_host at %p", addr);
335*86d949f9SVitaliy Gusev 		return (DCMD_ERR);
336*86d949f9SVitaliy Gusev 	}
337*86d949f9SVitaliy Gusev 
338*86d949f9SVitaliy Gusev 	/* Get its name and address */
339*86d949f9SVitaliy Gusev 	if (mdb_readstr(hname, sizeof (hname),
340*86d949f9SVitaliy Gusev 	    (uintptr_t)nh.nh_name) < 0)
341*86d949f9SVitaliy Gusev 		strlcpy(hname, "?", sizeof (hname));
342*86d949f9SVitaliy Gusev 	if (nlm_netbuf_str(haddr, sizeof (haddr), &nh.nh_addr) < 0)
343*86d949f9SVitaliy Gusev 		strlcpy(haddr, "?", sizeof (haddr));
344*86d949f9SVitaliy Gusev 
345*86d949f9SVitaliy Gusev 	if (opt_v == FALSE) {
346*86d949f9SVitaliy Gusev 		nlm_host_print(addr, &nh, hname, haddr, flags);
347*86d949f9SVitaliy Gusev 		return (DCMD_OK);
348*86d949f9SVitaliy Gusev 	}
349*86d949f9SVitaliy Gusev 
350*86d949f9SVitaliy Gusev 	/*
351*86d949f9SVitaliy Gusev 	 * Print verbose format
352*86d949f9SVitaliy Gusev 	 */
353*86d949f9SVitaliy Gusev 
354*86d949f9SVitaliy Gusev 	mdb_printf("%<b>%<u>NLM host (%p):%</u>%</b>\n", addr);
355*86d949f9SVitaliy Gusev 
356*86d949f9SVitaliy Gusev 	mdb_printf("Refcnt: %u\n", nh.nh_refs);
357*86d949f9SVitaliy Gusev 	mdb_printf(" Sysid: %d\n", (int)nh.nh_sysid);
358*86d949f9SVitaliy Gusev 	mdb_printf("  Name: %s\n", hname);
359*86d949f9SVitaliy Gusev 	mdb_printf("  Addr: %s\n", haddr);
360*86d949f9SVitaliy Gusev 	mdb_printf(" State: %d\n", nh.nh_state);
361*86d949f9SVitaliy Gusev 	mdb_printf(" Flags: 0x%x <%b>\n",
362*86d949f9SVitaliy Gusev 	    nh.nh_flags, nh.nh_flags, host_flag_bits);
363*86d949f9SVitaliy Gusev 	mdb_printf("Vholds: %?p\n", nh.nh_vholds_list.tqh_first);
364*86d949f9SVitaliy Gusev 
365*86d949f9SVitaliy Gusev 	return (DCMD_OK);
366*86d949f9SVitaliy Gusev }
367*86d949f9SVitaliy Gusev 
368*86d949f9SVitaliy Gusev /*
369*86d949f9SVitaliy Gusev  * Shared by nlm_host_dcmd and nlm_list_host_cb
370*86d949f9SVitaliy Gusev  * Print an nlm_host summary line.
371*86d949f9SVitaliy Gusev  */
372*86d949f9SVitaliy Gusev static void
nlm_host_print(uintptr_t addr,const struct nlm_host * nh,char * hname,char * haddr,uint_t flags)373*86d949f9SVitaliy Gusev nlm_host_print(uintptr_t addr, const struct nlm_host *nh,
374*86d949f9SVitaliy Gusev     char *hname, char *haddr, uint_t flags)
375*86d949f9SVitaliy Gusev {
376*86d949f9SVitaliy Gusev 	int hname_width = 20;
377*86d949f9SVitaliy Gusev 
378*86d949f9SVitaliy Gusev 	if (DCMD_HDRSPEC(flags)) {
379*86d949f9SVitaliy Gusev 		mdb_printf("%<b>%<u>%-?s %-*s%10s %6s ", "nlm_host",
380*86d949f9SVitaliy Gusev 		    hname_width, "name", "refs", "sysid");
381*86d949f9SVitaliy Gusev 		mdb_printf("%s%</u>%</b>\n", "net_addr");
382*86d949f9SVitaliy Gusev 	}
383*86d949f9SVitaliy Gusev 
384*86d949f9SVitaliy Gusev 	mdb_printf("%?p %-*s%10i %6hi %s\n",
385*86d949f9SVitaliy Gusev 	    addr, hname_width, hname,
386*86d949f9SVitaliy Gusev 	    nh->nh_refs, nh->nh_sysid, haddr);
387*86d949f9SVitaliy Gusev }
388*86d949f9SVitaliy Gusev 
389*86d949f9SVitaliy Gusev /*
390*86d949f9SVitaliy Gusev  * ****************************************************************
391*86d949f9SVitaliy Gusev  * NLM vholds (under hosts)
392*86d949f9SVitaliy Gusev  */
393*86d949f9SVitaliy Gusev 
394*86d949f9SVitaliy Gusev /*
395*86d949f9SVitaliy Gusev  * nlm_vhold walker implementation
396*86d949f9SVitaliy Gusev  */
397*86d949f9SVitaliy Gusev 
398*86d949f9SVitaliy Gusev int
nlm_vhold_walk_init(mdb_walk_state_t * wsp)399*86d949f9SVitaliy Gusev nlm_vhold_walk_init(mdb_walk_state_t *wsp)
400*86d949f9SVitaliy Gusev {
401*86d949f9SVitaliy Gusev 	struct nlm_vhold_list head;
402*86d949f9SVitaliy Gusev 	uintptr_t addr;
403*86d949f9SVitaliy Gusev 	static int head_off = -1;
404*86d949f9SVitaliy Gusev 
405*86d949f9SVitaliy Gusev 	if (wsp->walk_addr == 0) {
406*86d949f9SVitaliy Gusev 		mdb_printf("requires address of struct nlm_host\n");
407*86d949f9SVitaliy Gusev 		return (WALK_ERR);
408*86d949f9SVitaliy Gusev 	}
409*86d949f9SVitaliy Gusev 
410*86d949f9SVitaliy Gusev 	/* Get offset of the list head and read it. */
411*86d949f9SVitaliy Gusev 	if (head_off < 0) {
412*86d949f9SVitaliy Gusev 		head_off = mdb_ctf_offsetof_by_name(
413*86d949f9SVitaliy Gusev 		    "struct nlm_host", "nh_vholds_list");
414*86d949f9SVitaliy Gusev 	}
415*86d949f9SVitaliy Gusev 	if (head_off < 0) {
416*86d949f9SVitaliy Gusev 		mdb_warn("cannot lookup: nlm_host .nh_vholds_list");
417*86d949f9SVitaliy Gusev 		return (WALK_ERR);
418*86d949f9SVitaliy Gusev 	}
419*86d949f9SVitaliy Gusev 
420*86d949f9SVitaliy Gusev 	addr = wsp->walk_addr + head_off;
421*86d949f9SVitaliy Gusev 	if (mdb_vread(&head, sizeof (head), addr) < 0) {
422*86d949f9SVitaliy Gusev 		mdb_warn("cannot read nlm_host at %p", wsp->walk_addr);
423*86d949f9SVitaliy Gusev 		return (WALK_ERR);
424*86d949f9SVitaliy Gusev 	}
425*86d949f9SVitaliy Gusev 
426*86d949f9SVitaliy Gusev 	wsp->walk_addr = (uintptr_t)head.tqh_first;
427*86d949f9SVitaliy Gusev 	return (WALK_NEXT);
428*86d949f9SVitaliy Gusev }
429*86d949f9SVitaliy Gusev 
430*86d949f9SVitaliy Gusev int
nlm_vhold_walk_step(mdb_walk_state_t * wsp)431*86d949f9SVitaliy Gusev nlm_vhold_walk_step(mdb_walk_state_t *wsp)
432*86d949f9SVitaliy Gusev {
433*86d949f9SVitaliy Gusev 	struct nlm_vhold nv;
434*86d949f9SVitaliy Gusev 	uintptr_t addr = wsp->walk_addr;
435*86d949f9SVitaliy Gusev 
436*86d949f9SVitaliy Gusev 	if (addr == 0)
437*86d949f9SVitaliy Gusev 		return (WALK_DONE);
438*86d949f9SVitaliy Gusev 
439*86d949f9SVitaliy Gusev 	if (mdb_vread(&nv, sizeof (nv), addr) < 0) {
440*86d949f9SVitaliy Gusev 		mdb_warn("failed to read nlm_vhold at %p", addr);
441*86d949f9SVitaliy Gusev 		return (WALK_ERR);
442*86d949f9SVitaliy Gusev 	}
443*86d949f9SVitaliy Gusev 
444*86d949f9SVitaliy Gusev 	wsp->walk_addr = (uintptr_t)nv.nv_link.tqe_next;
445*86d949f9SVitaliy Gusev 	return (wsp->walk_callback(addr, &nv, wsp->walk_cbdata));
446*86d949f9SVitaliy Gusev }
447*86d949f9SVitaliy Gusev 
448*86d949f9SVitaliy Gusev /*
449*86d949f9SVitaliy Gusev  * nlm_vhold dcmd implementation
450*86d949f9SVitaliy Gusev  */
451*86d949f9SVitaliy Gusev 
452*86d949f9SVitaliy Gusev static void nlm_vhold_print(uintptr_t, const struct nlm_vhold *, uint_t);
453*86d949f9SVitaliy Gusev 
454*86d949f9SVitaliy Gusev void
nlm_vhold_help(void)455*86d949f9SVitaliy Gusev nlm_vhold_help(void)
456*86d949f9SVitaliy Gusev {
457*86d949f9SVitaliy Gusev 	mdb_printf("-v       verbose information\n");
458*86d949f9SVitaliy Gusev }
459*86d949f9SVitaliy Gusev 
460*86d949f9SVitaliy Gusev int
nlm_vhold_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)461*86d949f9SVitaliy Gusev nlm_vhold_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
462*86d949f9SVitaliy Gusev {
463*86d949f9SVitaliy Gusev 	struct nlm_vhold nv;
464*86d949f9SVitaliy Gusev 	char path_buf[MAXPATHLEN];
465*86d949f9SVitaliy Gusev 	uint_t opt_v = FALSE;
466*86d949f9SVitaliy Gusev 
467*86d949f9SVitaliy Gusev 	if (mdb_getopts(argc, argv,
468*86d949f9SVitaliy Gusev 	    'v', MDB_OPT_SETBITS, TRUE, &opt_v, NULL) != argc)
469*86d949f9SVitaliy Gusev 		return (DCMD_USAGE);
470*86d949f9SVitaliy Gusev 
471*86d949f9SVitaliy Gusev 	if ((flags & DCMD_ADDRSPEC) == 0) {
472*86d949f9SVitaliy Gusev 		mdb_warn("requires addr of nlm_vhold");
473*86d949f9SVitaliy Gusev 		return (DCMD_ERR);
474*86d949f9SVitaliy Gusev 	}
475*86d949f9SVitaliy Gusev 
476*86d949f9SVitaliy Gusev 	if (mdb_vread(&nv, sizeof (nv), addr) == -1) {
477*86d949f9SVitaliy Gusev 		mdb_warn("failed to read nlm_vhold at %p", addr);
478*86d949f9SVitaliy Gusev 		return (DCMD_ERR);
479*86d949f9SVitaliy Gusev 	}
480*86d949f9SVitaliy Gusev 
481*86d949f9SVitaliy Gusev 	if (opt_v == FALSE) {
482*86d949f9SVitaliy Gusev 		nlm_vhold_print(addr, &nv, flags);
483*86d949f9SVitaliy Gusev 		return (DCMD_OK);
484*86d949f9SVitaliy Gusev 	}
485*86d949f9SVitaliy Gusev 
486*86d949f9SVitaliy Gusev 	/*
487*86d949f9SVitaliy Gusev 	 * Print verbose format
488*86d949f9SVitaliy Gusev 	 */
489*86d949f9SVitaliy Gusev 
490*86d949f9SVitaliy Gusev 	if (nv.nv_vp == NULL || mdb_vnode2path((uintptr_t)nv.nv_vp,
491*86d949f9SVitaliy Gusev 	    path_buf, sizeof (path_buf)) != 0)
492*86d949f9SVitaliy Gusev 		strlcpy(path_buf, "?", sizeof (path_buf));
493*86d949f9SVitaliy Gusev 
494*86d949f9SVitaliy Gusev 	mdb_printf("%<b>%<u>NLM vhold (%p):%</u>%</b>\n", addr);
495*86d949f9SVitaliy Gusev 
496*86d949f9SVitaliy Gusev 	mdb_printf("Refcnt: %u\n", nv.nv_refcnt);
497*86d949f9SVitaliy Gusev 	mdb_printf(" Vnode: %?p (%s)\n", nv.nv_vp, path_buf);
498*86d949f9SVitaliy Gusev 	mdb_printf(" Slreq: %?p\n", nv.nv_slreqs.tqh_first);
499*86d949f9SVitaliy Gusev 
500*86d949f9SVitaliy Gusev 	return (DCMD_OK);
501*86d949f9SVitaliy Gusev }
502*86d949f9SVitaliy Gusev 
503*86d949f9SVitaliy Gusev /*
504*86d949f9SVitaliy Gusev  * Shared by nlm_vhold_dcmd and nlm_list_vnode_cb
505*86d949f9SVitaliy Gusev  * Print an nlm_vhold summary line.
506*86d949f9SVitaliy Gusev  */
507*86d949f9SVitaliy Gusev static void
nlm_vhold_print(uintptr_t addr,const struct nlm_vhold * nv,uint_t flags)508*86d949f9SVitaliy Gusev nlm_vhold_print(uintptr_t addr, const struct nlm_vhold *nv, uint_t flags)
509*86d949f9SVitaliy Gusev {
510*86d949f9SVitaliy Gusev 
511*86d949f9SVitaliy Gusev 	if (DCMD_HDRSPEC(flags)) {
512*86d949f9SVitaliy Gusev 		mdb_printf("%<b>%<u>%-?s %10s %-?s %-?s%</u>%</b>\n",
513*86d949f9SVitaliy Gusev 		    "nlm_vhold", "refcnt", "vnode", "slreq");
514*86d949f9SVitaliy Gusev 	}
515*86d949f9SVitaliy Gusev 
516*86d949f9SVitaliy Gusev 	mdb_printf("%?p %10i %?p %?-p\n",
517*86d949f9SVitaliy Gusev 	    addr, nv->nv_refcnt, nv->nv_vp,
518*86d949f9SVitaliy Gusev 	    nv->nv_slreqs.tqh_first);
519*86d949f9SVitaliy Gusev }
520*86d949f9SVitaliy Gusev 
521*86d949f9SVitaliy Gusev /*
522*86d949f9SVitaliy Gusev  * ****************************************************************
523*86d949f9SVitaliy Gusev  * NLM slreqs (under vhold)
524*86d949f9SVitaliy Gusev  */
525*86d949f9SVitaliy Gusev 
526*86d949f9SVitaliy Gusev /*
527*86d949f9SVitaliy Gusev  * nlm_slreq walker implementation
528*86d949f9SVitaliy Gusev  */
529*86d949f9SVitaliy Gusev 
530*86d949f9SVitaliy Gusev int
nlm_slreq_walk_init(mdb_walk_state_t * wsp)531*86d949f9SVitaliy Gusev nlm_slreq_walk_init(mdb_walk_state_t *wsp)
532*86d949f9SVitaliy Gusev {
533*86d949f9SVitaliy Gusev 	struct nlm_slreq_list head;
534*86d949f9SVitaliy Gusev 	uintptr_t addr;
535*86d949f9SVitaliy Gusev 	static int head_off = -1;
536*86d949f9SVitaliy Gusev 
537*86d949f9SVitaliy Gusev 	if (wsp->walk_addr == 0) {
538*86d949f9SVitaliy Gusev 		mdb_printf("requires address of struct nlm_vhold\n");
539*86d949f9SVitaliy Gusev 		return (WALK_ERR);
540*86d949f9SVitaliy Gusev 	}
541*86d949f9SVitaliy Gusev 
542*86d949f9SVitaliy Gusev 	/* Get offset of the list head and read it. */
543*86d949f9SVitaliy Gusev 	if (head_off < 0) {
544*86d949f9SVitaliy Gusev 		head_off = mdb_ctf_offsetof_by_name(
545*86d949f9SVitaliy Gusev 		    "struct nlm_vhold", "nv_slreqs");
546*86d949f9SVitaliy Gusev 	}
547*86d949f9SVitaliy Gusev 	if (head_off < 0) {
548*86d949f9SVitaliy Gusev 		mdb_warn("cannot lookup: nlm_vhold .nv_slreqs");
549*86d949f9SVitaliy Gusev 		return (WALK_ERR);
550*86d949f9SVitaliy Gusev 	}
551*86d949f9SVitaliy Gusev 
552*86d949f9SVitaliy Gusev 	addr = wsp->walk_addr + head_off;
553*86d949f9SVitaliy Gusev 	if (mdb_vread(&head, sizeof (head), addr) < 0) {
554*86d949f9SVitaliy Gusev 		mdb_warn("cannot read nlm_vhold at %p", wsp->walk_addr);
555*86d949f9SVitaliy Gusev 		return (WALK_ERR);
556*86d949f9SVitaliy Gusev 	}
557*86d949f9SVitaliy Gusev 
558*86d949f9SVitaliy Gusev 	wsp->walk_addr = (uintptr_t)head.tqh_first;
559*86d949f9SVitaliy Gusev 	return (WALK_NEXT);
560*86d949f9SVitaliy Gusev }
561*86d949f9SVitaliy Gusev 
562*86d949f9SVitaliy Gusev int
nlm_slreq_walk_step(mdb_walk_state_t * wsp)563*86d949f9SVitaliy Gusev nlm_slreq_walk_step(mdb_walk_state_t *wsp)
564*86d949f9SVitaliy Gusev {
565*86d949f9SVitaliy Gusev 	struct nlm_slreq nsr;
566*86d949f9SVitaliy Gusev 	uintptr_t addr = wsp->walk_addr;
567*86d949f9SVitaliy Gusev 
568*86d949f9SVitaliy Gusev 	if (addr == 0)
569*86d949f9SVitaliy Gusev 		return (WALK_DONE);
570*86d949f9SVitaliy Gusev 
571*86d949f9SVitaliy Gusev 	if (mdb_vread(&nsr, sizeof (nsr), addr) < 0) {
572*86d949f9SVitaliy Gusev 		mdb_warn("failed to read nlm_slreq at %p", addr);
573*86d949f9SVitaliy Gusev 		return (WALK_ERR);
574*86d949f9SVitaliy Gusev 	}
575*86d949f9SVitaliy Gusev 
576*86d949f9SVitaliy Gusev 	wsp->walk_addr = (uintptr_t)nsr.nsr_link.tqe_next;
577*86d949f9SVitaliy Gusev 	return (wsp->walk_callback(addr, &nsr, wsp->walk_cbdata));
578*86d949f9SVitaliy Gusev }
579*86d949f9SVitaliy Gusev 
580*86d949f9SVitaliy Gusev /*
581*86d949f9SVitaliy Gusev  * nlm_slreq dcmd implementation
582*86d949f9SVitaliy Gusev  */
583*86d949f9SVitaliy Gusev 
584*86d949f9SVitaliy Gusev static void nlm_slreq_print(uintptr_t, const struct nlm_slreq *, uint_t);
585*86d949f9SVitaliy Gusev 
586*86d949f9SVitaliy Gusev void
nlm_slreq_help(void)587*86d949f9SVitaliy Gusev nlm_slreq_help(void)
588*86d949f9SVitaliy Gusev {
589*86d949f9SVitaliy Gusev 	mdb_printf("-v       verbose information\n");
590*86d949f9SVitaliy Gusev }
591*86d949f9SVitaliy Gusev 
592*86d949f9SVitaliy Gusev int
nlm_slreq_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)593*86d949f9SVitaliy Gusev nlm_slreq_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
594*86d949f9SVitaliy Gusev {
595*86d949f9SVitaliy Gusev 	struct nlm_slreq nsr;
596*86d949f9SVitaliy Gusev 	uint_t opt_v = FALSE;
597*86d949f9SVitaliy Gusev 
598*86d949f9SVitaliy Gusev 	if (mdb_getopts(argc, argv,
599*86d949f9SVitaliy Gusev 	    'v', MDB_OPT_SETBITS, TRUE, &opt_v, NULL) != argc)
600*86d949f9SVitaliy Gusev 		return (DCMD_USAGE);
601*86d949f9SVitaliy Gusev 
602*86d949f9SVitaliy Gusev 	if ((flags & DCMD_ADDRSPEC) == 0) {
603*86d949f9SVitaliy Gusev 		mdb_warn("requires addr of nlm_slreq");
604*86d949f9SVitaliy Gusev 		return (DCMD_ERR);
605*86d949f9SVitaliy Gusev 	}
606*86d949f9SVitaliy Gusev 
607*86d949f9SVitaliy Gusev 	if (mdb_vread(&nsr, sizeof (nsr), addr) == -1) {
608*86d949f9SVitaliy Gusev 		mdb_warn("failed to read nlm_slreq at %p", addr);
609*86d949f9SVitaliy Gusev 		return (DCMD_ERR);
610*86d949f9SVitaliy Gusev 	}
611*86d949f9SVitaliy Gusev 
612*86d949f9SVitaliy Gusev 	if (opt_v == FALSE) {
613*86d949f9SVitaliy Gusev 		nlm_slreq_print(addr, &nsr, flags);
614*86d949f9SVitaliy Gusev 		return (DCMD_OK);
615*86d949f9SVitaliy Gusev 	}
616*86d949f9SVitaliy Gusev 
617*86d949f9SVitaliy Gusev 	/*
618*86d949f9SVitaliy Gusev 	 * Print verbose format
619*86d949f9SVitaliy Gusev 	 */
620*86d949f9SVitaliy Gusev 
621*86d949f9SVitaliy Gusev 	mdb_printf("%<b>%<u>NLM slreq (%p):%</u>%</b>\n", addr);
622*86d949f9SVitaliy Gusev 
623*86d949f9SVitaliy Gusev 	mdb_printf(" type: %d (%s)\n", nsr.nsr_fl.l_type,
624*86d949f9SVitaliy Gusev 	    (nsr.nsr_fl.l_type == F_RDLCK) ? "RD" :
625*86d949f9SVitaliy Gusev 	    (nsr.nsr_fl.l_type == F_WRLCK) ? "WR" : "??");
626*86d949f9SVitaliy Gusev 	mdb_printf("sysid: %d\n", nsr.nsr_fl.l_sysid);
627*86d949f9SVitaliy Gusev 	mdb_printf("  pid: %d\n", nsr.nsr_fl.l_pid);
628*86d949f9SVitaliy Gusev 	mdb_printf("start: %lld\n", nsr.nsr_fl.l_start);
629*86d949f9SVitaliy Gusev 	mdb_printf("  len: %lld\n", nsr.nsr_fl.l_len);
630*86d949f9SVitaliy Gusev 
631*86d949f9SVitaliy Gusev 	return (DCMD_OK);
632*86d949f9SVitaliy Gusev }
633*86d949f9SVitaliy Gusev 
634*86d949f9SVitaliy Gusev /*
635*86d949f9SVitaliy Gusev  * Shared by nlm_slreq_dcmd and nlm_list_slreq_cb
636*86d949f9SVitaliy Gusev  * Print an nlm_slreq summary line.
637*86d949f9SVitaliy Gusev  */
638*86d949f9SVitaliy Gusev static void
nlm_slreq_print(uintptr_t addr,const struct nlm_slreq * nsr,uint_t flags)639*86d949f9SVitaliy Gusev nlm_slreq_print(uintptr_t addr, const struct nlm_slreq *nsr, uint_t flags)
640*86d949f9SVitaliy Gusev {
641*86d949f9SVitaliy Gusev 
642*86d949f9SVitaliy Gusev 	if (DCMD_HDRSPEC(flags)) {
643*86d949f9SVitaliy Gusev 		mdb_printf("%<b>%<u>%-?s %4s %5s %3s %6s %6s%</u>%</b>\n",
644*86d949f9SVitaliy Gusev 		    "nlm_slreq", "type", "sysid", "pid", "start", "len");
645*86d949f9SVitaliy Gusev 	}
646*86d949f9SVitaliy Gusev 
647*86d949f9SVitaliy Gusev 	mdb_printf(
648*86d949f9SVitaliy Gusev 	    "%?p %4d %5d %3d %6lld %6lld\n",
649*86d949f9SVitaliy Gusev 	    addr,
650*86d949f9SVitaliy Gusev 	    nsr->nsr_fl.l_type,
651*86d949f9SVitaliy Gusev 	    nsr->nsr_fl.l_sysid,
652*86d949f9SVitaliy Gusev 	    nsr->nsr_fl.l_pid,
653*86d949f9SVitaliy Gusev 	    nsr->nsr_fl.l_start,
654*86d949f9SVitaliy Gusev 	    nsr->nsr_fl.l_len);
655*86d949f9SVitaliy Gusev }
656*86d949f9SVitaliy Gusev 
657*86d949f9SVitaliy Gusev /*
658*86d949f9SVitaliy Gusev  * ****************************************************************
659*86d949f9SVitaliy Gusev  */
660*86d949f9SVitaliy Gusev 
661*86d949f9SVitaliy Gusev /*
662*86d949f9SVitaliy Gusev  * nlm_list dcmd implementation
663*86d949f9SVitaliy Gusev  *
664*86d949f9SVitaliy Gusev  * This is a fancy command command to walk the whole NLM
665*86d949f9SVitaliy Gusev  * data hierarchy, skipping uninteresting elements.
666*86d949f9SVitaliy Gusev  */
667*86d949f9SVitaliy Gusev 
668*86d949f9SVitaliy Gusev #define	NLM_LIST_DEPTH_HOSTS	1	/* just hosts */
669*86d949f9SVitaliy Gusev #define	NLM_LIST_DEPTH_VHOLDS	2	/* host and vholds */
670*86d949f9SVitaliy Gusev #define	NLM_LIST_DEPTH_SLREQS	3	/* sleeping lock requests */
671*86d949f9SVitaliy Gusev #define	NLM_LIST_DEPTH_DEFAULT	3	/* default: show all */
672*86d949f9SVitaliy Gusev 
673*86d949f9SVitaliy Gusev struct nlm_list_arg {
674*86d949f9SVitaliy Gusev 	uint_t	opt_v;
675*86d949f9SVitaliy Gusev 	uint_t	opt_a;
676*86d949f9SVitaliy Gusev 	uint_t	depth;
677*86d949f9SVitaliy Gusev 	int	sysid;
678*86d949f9SVitaliy Gusev 	char	*host;
679*86d949f9SVitaliy Gusev 	uint_t	zone_flags;
680*86d949f9SVitaliy Gusev 	uint_t	host_flags;
681*86d949f9SVitaliy Gusev 	uint_t	vhold_flags;
682*86d949f9SVitaliy Gusev 	uint_t	slreq_flags;
683*86d949f9SVitaliy Gusev 	char	namebuf[NLM_MAXNAMELEN];
684*86d949f9SVitaliy Gusev 	char	addrbuf[NLM_MAXADDRSTR];
685*86d949f9SVitaliy Gusev };
686*86d949f9SVitaliy Gusev 
687*86d949f9SVitaliy Gusev static int nlm_list_zone_cb(uintptr_t, const void *, void *);
688*86d949f9SVitaliy Gusev static int nlm_list_host_cb(uintptr_t, const void *, void *);
689*86d949f9SVitaliy Gusev static int nlm_list_vhold_cb(uintptr_t, const void *, void *);
690*86d949f9SVitaliy Gusev static int nlm_list_slreq_cb(uintptr_t, const void *, void *);
691*86d949f9SVitaliy Gusev 
692*86d949f9SVitaliy Gusev void
nlm_list_help(void)693*86d949f9SVitaliy Gusev nlm_list_help(void)
694*86d949f9SVitaliy Gusev {
695*86d949f9SVitaliy Gusev 	mdb_printf("-v		verbose information\n");
696*86d949f9SVitaliy Gusev 	mdb_printf("-a		include idle hosts\n");
697*86d949f9SVitaliy Gusev 	mdb_printf("-d depth	recursion depth (zones, hosts, ...)\n");
698*86d949f9SVitaliy Gusev 	mdb_printf("-h host	filter by host name\n");
699*86d949f9SVitaliy Gusev 	mdb_printf("-s sysid	filter by sysid (0tnnn for decimal)\n");
700*86d949f9SVitaliy Gusev }
701*86d949f9SVitaliy Gusev 
702*86d949f9SVitaliy Gusev int
nlm_list_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)703*86d949f9SVitaliy Gusev nlm_list_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
704*86d949f9SVitaliy Gusev {
705*86d949f9SVitaliy Gusev 	struct nlm_list_arg *arg;
706*86d949f9SVitaliy Gusev 	uintptr_t depth = NLM_LIST_DEPTH_DEFAULT;
707*86d949f9SVitaliy Gusev 	char *host = NULL;
708*86d949f9SVitaliy Gusev 	char *sysid = NULL;
709*86d949f9SVitaliy Gusev 
710*86d949f9SVitaliy Gusev 	if ((flags & DCMD_ADDRSPEC) != 0)
711*86d949f9SVitaliy Gusev 		return (DCMD_USAGE);
712*86d949f9SVitaliy Gusev 
713*86d949f9SVitaliy Gusev 	arg = mdb_zalloc(sizeof (*arg), UM_SLEEP | UM_GC);
714*86d949f9SVitaliy Gusev 
715*86d949f9SVitaliy Gusev 	if (mdb_getopts(argc, argv,
716*86d949f9SVitaliy Gusev 	    'v', MDB_OPT_SETBITS, TRUE, &arg->opt_v,
717*86d949f9SVitaliy Gusev 	    'a', MDB_OPT_SETBITS, TRUE, &arg->opt_a,
718*86d949f9SVitaliy Gusev 	    'd', MDB_OPT_UINTPTR, &depth,
719*86d949f9SVitaliy Gusev 	    'h', MDB_OPT_STR, &host,
720*86d949f9SVitaliy Gusev 	    's', MDB_OPT_STR, &sysid,
721*86d949f9SVitaliy Gusev 	    NULL) != argc)
722*86d949f9SVitaliy Gusev 		return (DCMD_USAGE);
723*86d949f9SVitaliy Gusev 
724*86d949f9SVitaliy Gusev 	arg->depth = (uint_t)depth;
725*86d949f9SVitaliy Gusev 	arg->sysid = -1;
726*86d949f9SVitaliy Gusev 	if (host != NULL)
727*86d949f9SVitaliy Gusev 		arg->host = host;
728*86d949f9SVitaliy Gusev 	if (sysid != NULL) {
729*86d949f9SVitaliy Gusev 		arg->sysid = (int)mdb_strtoull(sysid);
730*86d949f9SVitaliy Gusev 		if (arg->sysid < 1) {
731*86d949f9SVitaliy Gusev 			mdb_warn("invalid sysid");
732*86d949f9SVitaliy Gusev 			arg->sysid = -1;
733*86d949f9SVitaliy Gusev 		}
734*86d949f9SVitaliy Gusev 	}
735*86d949f9SVitaliy Gusev 
736*86d949f9SVitaliy Gusev 	/* Specifying host or sysid id implies -a */
737*86d949f9SVitaliy Gusev 	if (arg->host != NULL || arg->sysid >= 0)
738*86d949f9SVitaliy Gusev 		arg->opt_a = TRUE;
739*86d949f9SVitaliy Gusev 
740*86d949f9SVitaliy Gusev 	arg->zone_flags = (DCMD_LOOP | DCMD_LOOPFIRST);
741*86d949f9SVitaliy Gusev 	if (mdb_pwalk("nlm_zone", nlm_list_zone_cb, arg, 0)) {
742*86d949f9SVitaliy Gusev 		mdb_warn("cannot walk nlm_zone list");
743*86d949f9SVitaliy Gusev 		return (DCMD_ERR);
744*86d949f9SVitaliy Gusev 	}
745*86d949f9SVitaliy Gusev 
746*86d949f9SVitaliy Gusev 	return (DCMD_OK);
747*86d949f9SVitaliy Gusev }
748*86d949f9SVitaliy Gusev 
749*86d949f9SVitaliy Gusev /* Called for each zone's nlm_globals */
750*86d949f9SVitaliy Gusev static int
nlm_list_zone_cb(uintptr_t addr,const void * data,void * cb_data)751*86d949f9SVitaliy Gusev nlm_list_zone_cb(uintptr_t addr, const void *data, void *cb_data)
752*86d949f9SVitaliy Gusev {
753*86d949f9SVitaliy Gusev 	struct nlm_list_arg *arg = cb_data;
754*86d949f9SVitaliy Gusev 	const struct nlm_globals *g = data;
755*86d949f9SVitaliy Gusev 
756*86d949f9SVitaliy Gusev 	/* Add zone filtering? */
757*86d949f9SVitaliy Gusev 
758*86d949f9SVitaliy Gusev 	/*
759*86d949f9SVitaliy Gusev 	 * Summary line for a struct nlm_globals
760*86d949f9SVitaliy Gusev 	 */
761*86d949f9SVitaliy Gusev 	nlm_zone_print(addr, g, 0);
762*86d949f9SVitaliy Gusev 	arg->zone_flags &= ~DCMD_LOOPFIRST;
763*86d949f9SVitaliy Gusev 
764*86d949f9SVitaliy Gusev 	if (arg->depth >= NLM_LIST_DEPTH_HOSTS) {
765*86d949f9SVitaliy Gusev 		(void) mdb_inc_indent(2);
766*86d949f9SVitaliy Gusev 		arg->host_flags = (DCMD_LOOP | DCMD_LOOPFIRST);
767*86d949f9SVitaliy Gusev 		if (mdb_pwalk("nlm_host", nlm_list_host_cb, arg, addr) != 0) {
768*86d949f9SVitaliy Gusev 			mdb_warn("failed to walk hosts for zone %p", addr);
769*86d949f9SVitaliy Gusev 			/* keep going */
770*86d949f9SVitaliy Gusev 		}
771*86d949f9SVitaliy Gusev 		(void) mdb_dec_indent(2);
772*86d949f9SVitaliy Gusev 	}
773*86d949f9SVitaliy Gusev 
774*86d949f9SVitaliy Gusev 	return (WALK_NEXT);
775*86d949f9SVitaliy Gusev }
776*86d949f9SVitaliy Gusev 
777*86d949f9SVitaliy Gusev /* Called for each nlm_host */
778*86d949f9SVitaliy Gusev static int
nlm_list_host_cb(uintptr_t addr,const void * data,void * cb_data)779*86d949f9SVitaliy Gusev nlm_list_host_cb(uintptr_t addr, const void *data, void *cb_data)
780*86d949f9SVitaliy Gusev {
781*86d949f9SVitaliy Gusev 	struct nlm_list_arg *arg = cb_data;
782*86d949f9SVitaliy Gusev 	const struct nlm_host *nh = data;
783*86d949f9SVitaliy Gusev 
784*86d949f9SVitaliy Gusev 	/* Get the host name and net addr. */
785*86d949f9SVitaliy Gusev 	if (mdb_readstr(arg->namebuf, NLM_MAXNAMELEN,
786*86d949f9SVitaliy Gusev 	    (uintptr_t)nh->nh_name) < 0)
787*86d949f9SVitaliy Gusev 		(void) strlcpy(arg->namebuf, "?", sizeof (char));
788*86d949f9SVitaliy Gusev 	if (nlm_netbuf_str(arg->addrbuf, NLM_MAXADDRSTR, &nh->nh_addr) < 0)
789*86d949f9SVitaliy Gusev 		(void) strlcpy(arg->addrbuf, "?", sizeof (char));
790*86d949f9SVitaliy Gusev 
791*86d949f9SVitaliy Gusev 	/* Filter out uninteresting hosts */
792*86d949f9SVitaliy Gusev 	if (arg->opt_a == 0 && nh->nh_refs == 0)
793*86d949f9SVitaliy Gusev 		return (WALK_NEXT);
794*86d949f9SVitaliy Gusev 	if (arg->sysid != -1 && arg->sysid != (nh->nh_sysid & LM_SYSID_MAX))
795*86d949f9SVitaliy Gusev 		return (WALK_NEXT);
796*86d949f9SVitaliy Gusev 	if (arg->host != NULL && strcmp(arg->host, arg->namebuf) != 0)
797*86d949f9SVitaliy Gusev 		return (WALK_NEXT);
798*86d949f9SVitaliy Gusev 
799*86d949f9SVitaliy Gusev 	/*
800*86d949f9SVitaliy Gusev 	 * Summary line for struct nlm_host
801*86d949f9SVitaliy Gusev 	 */
802*86d949f9SVitaliy Gusev 	nlm_host_print(addr, nh, arg->namebuf, arg->addrbuf,
803*86d949f9SVitaliy Gusev 	    arg->host_flags);
804*86d949f9SVitaliy Gusev 	arg->host_flags &= ~DCMD_LOOPFIRST;
805*86d949f9SVitaliy Gusev 
806*86d949f9SVitaliy Gusev 	if (arg->depth >= NLM_LIST_DEPTH_VHOLDS) {
807*86d949f9SVitaliy Gusev 		(void) mdb_inc_indent(2);
808*86d949f9SVitaliy Gusev 		arg->vhold_flags = (DCMD_LOOP | DCMD_LOOPFIRST);
809*86d949f9SVitaliy Gusev 		if (mdb_pwalk("nlm_vhold", nlm_list_vhold_cb, arg, addr)) {
810*86d949f9SVitaliy Gusev 			mdb_warn("failed to walk vholds for host %p", addr);
811*86d949f9SVitaliy Gusev 			/* keep going */
812*86d949f9SVitaliy Gusev 		}
813*86d949f9SVitaliy Gusev 		(void) mdb_dec_indent(2);
814*86d949f9SVitaliy Gusev 	}
815*86d949f9SVitaliy Gusev 
816*86d949f9SVitaliy Gusev 	/*
817*86d949f9SVitaliy Gusev 	 * We printed some hosts, so tell nlm_list_zone_cb to
818*86d949f9SVitaliy Gusev 	 * print its header line again.
819*86d949f9SVitaliy Gusev 	 */
820*86d949f9SVitaliy Gusev 	arg->zone_flags |= DCMD_LOOPFIRST;
821*86d949f9SVitaliy Gusev 
822*86d949f9SVitaliy Gusev 	return (WALK_NEXT);
823*86d949f9SVitaliy Gusev }
824*86d949f9SVitaliy Gusev 
825*86d949f9SVitaliy Gusev /* Called for each nlm_vhold */
826*86d949f9SVitaliy Gusev static int
nlm_list_vhold_cb(uintptr_t addr,const void * data,void * cb_data)827*86d949f9SVitaliy Gusev nlm_list_vhold_cb(uintptr_t addr, const void *data, void *cb_data)
828*86d949f9SVitaliy Gusev {
829*86d949f9SVitaliy Gusev 	struct nlm_list_arg *arg = cb_data;
830*86d949f9SVitaliy Gusev 	const struct nlm_vhold *nv = data;
831*86d949f9SVitaliy Gusev 
832*86d949f9SVitaliy Gusev 	/* Filter out uninteresting vholds */
833*86d949f9SVitaliy Gusev 	if (arg->opt_a == 0 && nv->nv_refcnt == 0)
834*86d949f9SVitaliy Gusev 		return (WALK_NEXT);
835*86d949f9SVitaliy Gusev 
836*86d949f9SVitaliy Gusev 	/*
837*86d949f9SVitaliy Gusev 	 * Summary line for struct nlm_vhold
838*86d949f9SVitaliy Gusev 	 */
839*86d949f9SVitaliy Gusev 	nlm_vhold_print(addr, nv, arg->vhold_flags);
840*86d949f9SVitaliy Gusev 	arg->vhold_flags &= ~DCMD_LOOPFIRST;
841*86d949f9SVitaliy Gusev 
842*86d949f9SVitaliy Gusev 	if (arg->depth >= NLM_LIST_DEPTH_SLREQS) {
843*86d949f9SVitaliy Gusev 		(void) mdb_inc_indent(2);
844*86d949f9SVitaliy Gusev 		arg->slreq_flags = (DCMD_LOOP | DCMD_LOOPFIRST);
845*86d949f9SVitaliy Gusev 		if (mdb_pwalk("nlm_slreq", nlm_list_slreq_cb, arg, addr)) {
846*86d949f9SVitaliy Gusev 			mdb_warn("failed to walk slreqs for vhold %p", addr);
847*86d949f9SVitaliy Gusev 			/* keep going */
848*86d949f9SVitaliy Gusev 		}
849*86d949f9SVitaliy Gusev 		(void) mdb_dec_indent(2);
850*86d949f9SVitaliy Gusev 	}
851*86d949f9SVitaliy Gusev 
852*86d949f9SVitaliy Gusev 	/*
853*86d949f9SVitaliy Gusev 	 * We printed some vholds, so tell nlm_list_host_cb to
854*86d949f9SVitaliy Gusev 	 * print its header line again.
855*86d949f9SVitaliy Gusev 	 */
856*86d949f9SVitaliy Gusev 	arg->host_flags |= DCMD_LOOPFIRST;
857*86d949f9SVitaliy Gusev 
858*86d949f9SVitaliy Gusev 	return (WALK_NEXT);
859*86d949f9SVitaliy Gusev }
860*86d949f9SVitaliy Gusev 
861*86d949f9SVitaliy Gusev /* Called for each nlm_slreq */
862*86d949f9SVitaliy Gusev static int
nlm_list_slreq_cb(uintptr_t addr,const void * data,void * cb_data)863*86d949f9SVitaliy Gusev nlm_list_slreq_cb(uintptr_t addr, const void *data, void *cb_data)
864*86d949f9SVitaliy Gusev {
865*86d949f9SVitaliy Gusev 	struct nlm_list_arg *arg = cb_data;
866*86d949f9SVitaliy Gusev 	const struct nlm_slreq *nv = data;
867*86d949f9SVitaliy Gusev 
868*86d949f9SVitaliy Gusev 	/*
869*86d949f9SVitaliy Gusev 	 * Summary line for struct nlm_slreq
870*86d949f9SVitaliy Gusev 	 */
871*86d949f9SVitaliy Gusev 	nlm_slreq_print(addr, nv, arg->slreq_flags);
872*86d949f9SVitaliy Gusev 	arg->slreq_flags &= ~DCMD_LOOPFIRST;
873*86d949f9SVitaliy Gusev 
874*86d949f9SVitaliy Gusev 	/*
875*86d949f9SVitaliy Gusev 	 * We printed some slreqs, so tell nlm_list_vhold_cb to
876*86d949f9SVitaliy Gusev 	 * print its header line again.
877*86d949f9SVitaliy Gusev 	 */
878*86d949f9SVitaliy Gusev 	arg->vhold_flags |= DCMD_LOOPFIRST;
879*86d949f9SVitaliy Gusev 
880*86d949f9SVitaliy Gusev 	return (WALK_NEXT);
881*86d949f9SVitaliy Gusev }
882*86d949f9SVitaliy Gusev 
883*86d949f9SVitaliy Gusev /*
884*86d949f9SVitaliy Gusev  * ****************************************************************
885*86d949f9SVitaliy Gusev  */
886*86d949f9SVitaliy Gusev 
887*86d949f9SVitaliy Gusev /*
888*86d949f9SVitaliy Gusev  * nlm_lockson dcmd implementation
889*86d949f9SVitaliy Gusev  * Walk the lock_graph, filtered by sysid
890*86d949f9SVitaliy Gusev  */
891*86d949f9SVitaliy Gusev 
892*86d949f9SVitaliy Gusev struct nlm_locks_arg {
893*86d949f9SVitaliy Gusev 	/* dcmd options */
894*86d949f9SVitaliy Gusev 	uint_t	opt_v;
895*86d949f9SVitaliy Gusev 	int	sysid;
896*86d949f9SVitaliy Gusev 	char	*host;
897*86d949f9SVitaliy Gusev 	/* callback vars */
898*86d949f9SVitaliy Gusev 	uint_t	flags;
899*86d949f9SVitaliy Gusev 	int	lg_sysid;
900*86d949f9SVitaliy Gusev 	char	namebuf[NLM_MAXNAMELEN];
901*86d949f9SVitaliy Gusev 	char	addrbuf[NLM_MAXADDRSTR];
902*86d949f9SVitaliy Gusev 	char	pathbuf[PATH_MAX];
903*86d949f9SVitaliy Gusev };
904*86d949f9SVitaliy Gusev 
905*86d949f9SVitaliy Gusev static int nlm_locks_zone_cb(uintptr_t, const void *, void *);
906*86d949f9SVitaliy Gusev static int nlm_locks_host_cb(uintptr_t, const void *, void *);
907*86d949f9SVitaliy Gusev static int nlm_lockson_cb(uintptr_t, const void *, void *c);
908*86d949f9SVitaliy Gusev 
909*86d949f9SVitaliy Gusev void
nlm_lockson_help(void)910*86d949f9SVitaliy Gusev nlm_lockson_help(void)
911*86d949f9SVitaliy Gusev {
912*86d949f9SVitaliy Gusev 	mdb_printf("-v		verbose information\n");
913*86d949f9SVitaliy Gusev 	mdb_printf("-h host	filter by host name\n");
914*86d949f9SVitaliy Gusev 	mdb_printf("-s sysid	filter by sysid (0tnnn for decimal)\n");
915*86d949f9SVitaliy Gusev }
916*86d949f9SVitaliy Gusev 
917*86d949f9SVitaliy Gusev int
nlm_lockson_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)918*86d949f9SVitaliy Gusev nlm_lockson_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
919*86d949f9SVitaliy Gusev {
920*86d949f9SVitaliy Gusev 	struct nlm_locks_arg *arg;
921*86d949f9SVitaliy Gusev 	char *host = NULL;
922*86d949f9SVitaliy Gusev 	char *sysid = NULL;
923*86d949f9SVitaliy Gusev 
924*86d949f9SVitaliy Gusev 	if ((flags & DCMD_ADDRSPEC) != 0)
925*86d949f9SVitaliy Gusev 		return (DCMD_USAGE);
926*86d949f9SVitaliy Gusev 
927*86d949f9SVitaliy Gusev 	arg = mdb_zalloc(sizeof (*arg), UM_SLEEP | UM_GC);
928*86d949f9SVitaliy Gusev 
929*86d949f9SVitaliy Gusev 	if (mdb_getopts(argc, argv,
930*86d949f9SVitaliy Gusev 	    'v', MDB_OPT_SETBITS, TRUE, &arg->opt_v,
931*86d949f9SVitaliy Gusev 	    'h', MDB_OPT_STR, &host,
932*86d949f9SVitaliy Gusev 	    's', MDB_OPT_STR, &sysid,
933*86d949f9SVitaliy Gusev 	    NULL) != argc)
934*86d949f9SVitaliy Gusev 		return (DCMD_USAGE);
935*86d949f9SVitaliy Gusev 
936*86d949f9SVitaliy Gusev 	arg->sysid = -1;
937*86d949f9SVitaliy Gusev 	if (host != NULL)
938*86d949f9SVitaliy Gusev 		arg->host = host;
939*86d949f9SVitaliy Gusev 	if (sysid != NULL) {
940*86d949f9SVitaliy Gusev 		arg->sysid = (int)mdb_strtoull(sysid);
941*86d949f9SVitaliy Gusev 		if (arg->sysid < 1) {
942*86d949f9SVitaliy Gusev 			mdb_warn("invalid sysid");
943*86d949f9SVitaliy Gusev 			arg->sysid = -1;
944*86d949f9SVitaliy Gusev 		}
945*86d949f9SVitaliy Gusev 	}
946*86d949f9SVitaliy Gusev 
947*86d949f9SVitaliy Gusev 	if (mdb_pwalk("nlm_zone", nlm_locks_zone_cb, arg, 0)) {
948*86d949f9SVitaliy Gusev 		mdb_warn("cannot walk nlm_zone list");
949*86d949f9SVitaliy Gusev 		return (DCMD_ERR);
950*86d949f9SVitaliy Gusev 	}
951*86d949f9SVitaliy Gusev 
952*86d949f9SVitaliy Gusev 	return (DCMD_OK);
953*86d949f9SVitaliy Gusev }
954*86d949f9SVitaliy Gusev 
955*86d949f9SVitaliy Gusev /* Called for each zone's nlm_globals */
956*86d949f9SVitaliy Gusev static int
nlm_locks_zone_cb(uintptr_t addr,const void * data,void * cb_data)957*86d949f9SVitaliy Gusev nlm_locks_zone_cb(uintptr_t addr, const void *data, void *cb_data)
958*86d949f9SVitaliy Gusev {
959*86d949f9SVitaliy Gusev 	struct nlm_locks_arg *arg = cb_data;
960*86d949f9SVitaliy Gusev 	(void) data;
961*86d949f9SVitaliy Gusev 
962*86d949f9SVitaliy Gusev 	/*
963*86d949f9SVitaliy Gusev 	 * No filtering here. Don't even print zone addr.
964*86d949f9SVitaliy Gusev 	 * Just run the host list walker.
965*86d949f9SVitaliy Gusev 	 */
966*86d949f9SVitaliy Gusev 	if (mdb_pwalk("nlm_host", nlm_locks_host_cb, arg, addr) != 0) {
967*86d949f9SVitaliy Gusev 		mdb_warn("failed to walk hosts for zone %p", addr);
968*86d949f9SVitaliy Gusev 		/* keep going */
969*86d949f9SVitaliy Gusev 	}
970*86d949f9SVitaliy Gusev 
971*86d949f9SVitaliy Gusev 	return (WALK_NEXT);
972*86d949f9SVitaliy Gusev }
973*86d949f9SVitaliy Gusev 
974*86d949f9SVitaliy Gusev /* Called for each nlm_host */
975*86d949f9SVitaliy Gusev static int
nlm_locks_host_cb(uintptr_t addr,const void * data,void * cb_data)976*86d949f9SVitaliy Gusev nlm_locks_host_cb(uintptr_t addr, const void *data, void *cb_data)
977*86d949f9SVitaliy Gusev {
978*86d949f9SVitaliy Gusev 	struct nlm_locks_arg *arg = cb_data;
979*86d949f9SVitaliy Gusev 	const struct nlm_host *nh = data;
980*86d949f9SVitaliy Gusev 
981*86d949f9SVitaliy Gusev 	/* Get the host name and net addr. */
982*86d949f9SVitaliy Gusev 	if (mdb_readstr(arg->namebuf, NLM_MAXNAMELEN,
983*86d949f9SVitaliy Gusev 	    (uintptr_t)nh->nh_name) < 0)
984*86d949f9SVitaliy Gusev 		(void) strlcpy(arg->namebuf, "?", sizeof (char));
985*86d949f9SVitaliy Gusev 	if (nlm_netbuf_str(arg->addrbuf, NLM_MAXADDRSTR, &nh->nh_addr) < 0)
986*86d949f9SVitaliy Gusev 		(void) strlcpy(arg->addrbuf, "?", sizeof (char));
987*86d949f9SVitaliy Gusev 
988*86d949f9SVitaliy Gusev 	/* Filter out uninteresting hosts */
989*86d949f9SVitaliy Gusev 	if (arg->sysid != -1 && arg->sysid != (nh->nh_sysid & LM_SYSID_MAX))
990*86d949f9SVitaliy Gusev 		return (WALK_NEXT);
991*86d949f9SVitaliy Gusev 	if (arg->host != NULL && strcmp(arg->host, arg->namebuf) != 0)
992*86d949f9SVitaliy Gusev 		return (WALK_NEXT);
993*86d949f9SVitaliy Gusev 
994*86d949f9SVitaliy Gusev 	/*
995*86d949f9SVitaliy Gusev 	 * Summary line for struct nlm_host
996*86d949f9SVitaliy Gusev 	 */
997*86d949f9SVitaliy Gusev 	nlm_host_print(addr, nh, arg->namebuf, arg->addrbuf, 0);
998*86d949f9SVitaliy Gusev 
999*86d949f9SVitaliy Gusev 	/*
1000*86d949f9SVitaliy Gusev 	 * We run the lock_graph walker for every sysid, and the callback
1001*86d949f9SVitaliy Gusev 	 * uses arg->lg_sysid to filter graph elements.  Set that from
1002*86d949f9SVitaliy Gusev 	 * the host we're visiting now.
1003*86d949f9SVitaliy Gusev 	 */
1004*86d949f9SVitaliy Gusev 	arg->lg_sysid = (int)nh->nh_sysid;
1005*86d949f9SVitaliy Gusev 	arg->flags = (DCMD_LOOP | DCMD_LOOPFIRST);
1006*86d949f9SVitaliy Gusev 	if (mdb_pwalk("lock_graph", nlm_lockson_cb, arg, 0) < 0) {
1007*86d949f9SVitaliy Gusev 		mdb_warn("failed to walk lock_graph");
1008*86d949f9SVitaliy Gusev 		return (WALK_ERR);
1009*86d949f9SVitaliy Gusev 	}
1010*86d949f9SVitaliy Gusev 
1011*86d949f9SVitaliy Gusev 	return (WALK_NEXT);
1012*86d949f9SVitaliy Gusev }
1013*86d949f9SVitaliy Gusev 
1014*86d949f9SVitaliy Gusev static int
nlm_lockson_cb(uintptr_t addr,const void * data,void * cb_data)1015*86d949f9SVitaliy Gusev nlm_lockson_cb(uintptr_t addr, const void *data, void *cb_data)
1016*86d949f9SVitaliy Gusev {
1017*86d949f9SVitaliy Gusev 	struct nlm_locks_arg *arg = cb_data;
1018*86d949f9SVitaliy Gusev 	const lock_descriptor_t *ld = data;
1019*86d949f9SVitaliy Gusev 	proc_t p;
1020*86d949f9SVitaliy Gusev 	int local, sysid;
1021*86d949f9SVitaliy Gusev 	int host_width = 16;
1022*86d949f9SVitaliy Gusev 	char *s;
1023*86d949f9SVitaliy Gusev 
1024*86d949f9SVitaliy Gusev 	local = ld->l_flock.l_sysid & LM_SYSID_CLIENT;
1025*86d949f9SVitaliy Gusev 	sysid = ld->l_flock.l_sysid & LM_SYSID_MAX;
1026*86d949f9SVitaliy Gusev 
1027*86d949f9SVitaliy Gusev 	if (arg->lg_sysid != sysid)
1028*86d949f9SVitaliy Gusev 		return (WALK_NEXT);
1029*86d949f9SVitaliy Gusev 
1030*86d949f9SVitaliy Gusev 	if (DCMD_HDRSPEC(arg->flags)) {
1031*86d949f9SVitaliy Gusev 		mdb_printf("%<b>%<u>%-?s %-*s %5s(x) %-?s %-6s %-*s %-*s type",
1032*86d949f9SVitaliy Gusev 		    "lock_addr", host_width, "host", "sysid", "vnode", "pid",
1033*86d949f9SVitaliy Gusev 		    MAXCOMLEN, "cmd", arg->opt_v ? 9 : 5, "state");
1034*86d949f9SVitaliy Gusev 
1035*86d949f9SVitaliy Gusev 		if (arg->opt_v)
1036*86d949f9SVitaliy Gusev 			mdb_printf("%-11s srvstat %-10s", "(width)", "path");
1037*86d949f9SVitaliy Gusev 
1038*86d949f9SVitaliy Gusev 		mdb_printf("%</u>%</b>\n");
1039*86d949f9SVitaliy Gusev 	}
1040*86d949f9SVitaliy Gusev 	arg->flags &= ~DCMD_LOOPFIRST;
1041*86d949f9SVitaliy Gusev 
1042*86d949f9SVitaliy Gusev 	mdb_printf("%?p %-*s %5hi(%c) %?p %-6i %-*s ",
1043*86d949f9SVitaliy Gusev 	    addr, host_width, arg->namebuf,
1044*86d949f9SVitaliy Gusev 	    sysid, local ? 'L' : 'R', ld->l_vnode,
1045*86d949f9SVitaliy Gusev 	    ld->l_flock.l_pid, MAXCOMLEN,
1046*86d949f9SVitaliy Gusev 	    ld->l_flock.l_pid == 0 ? "<kernel>"
1047*86d949f9SVitaliy Gusev 	    : !local ? "<remote>"
1048*86d949f9SVitaliy Gusev 	    : mdb_pid2proc(ld->l_flock.l_pid, &p) == 0 ? "<defunct>"
1049*86d949f9SVitaliy Gusev 	    : p.p_user.u_comm);
1050*86d949f9SVitaliy Gusev 
1051*86d949f9SVitaliy Gusev 	if (arg->opt_v) {
1052*86d949f9SVitaliy Gusev 		switch (ld->l_status) {
1053*86d949f9SVitaliy Gusev 		case FLK_INITIAL_STATE:
1054*86d949f9SVitaliy Gusev 			s = "init";
1055*86d949f9SVitaliy Gusev 			break;
1056*86d949f9SVitaliy Gusev 		case FLK_START_STATE:
1057*86d949f9SVitaliy Gusev 			s = "execute";
1058*86d949f9SVitaliy Gusev 			break;
1059*86d949f9SVitaliy Gusev 		case FLK_ACTIVE_STATE:
1060*86d949f9SVitaliy Gusev 			s = "active";
1061*86d949f9SVitaliy Gusev 			break;
1062*86d949f9SVitaliy Gusev 		case FLK_SLEEPING_STATE:
1063*86d949f9SVitaliy Gusev 			s = "blocked";
1064*86d949f9SVitaliy Gusev 			break;
1065*86d949f9SVitaliy Gusev 		case FLK_GRANTED_STATE:
1066*86d949f9SVitaliy Gusev 			s = "granted";
1067*86d949f9SVitaliy Gusev 			break;
1068*86d949f9SVitaliy Gusev 		case FLK_INTERRUPTED_STATE:
1069*86d949f9SVitaliy Gusev 			s = "interrupt";
1070*86d949f9SVitaliy Gusev 			break;
1071*86d949f9SVitaliy Gusev 		case FLK_CANCELLED_STATE:
1072*86d949f9SVitaliy Gusev 			s = "cancel";
1073*86d949f9SVitaliy Gusev 			break;
1074*86d949f9SVitaliy Gusev 		case FLK_DEAD_STATE:
1075*86d949f9SVitaliy Gusev 			s = "done";
1076*86d949f9SVitaliy Gusev 			break;
1077*86d949f9SVitaliy Gusev 		default:
1078*86d949f9SVitaliy Gusev 			s = "??";
1079*86d949f9SVitaliy Gusev 			break;
1080*86d949f9SVitaliy Gusev 		}
1081*86d949f9SVitaliy Gusev 		mdb_printf("%-9s", s);
1082*86d949f9SVitaliy Gusev 	} else {
1083*86d949f9SVitaliy Gusev 		mdb_printf("%-5i", ld->l_status);
1084*86d949f9SVitaliy Gusev 	}
1085*86d949f9SVitaliy Gusev 
1086*86d949f9SVitaliy Gusev 	mdb_printf(" %-2s", ld->l_type == F_RDLCK ? "RD"
1087*86d949f9SVitaliy Gusev 	    : ld->l_type == F_WRLCK ? "WR" : "??");
1088*86d949f9SVitaliy Gusev 
1089*86d949f9SVitaliy Gusev 
1090*86d949f9SVitaliy Gusev 	if (!arg->opt_v) {
1091*86d949f9SVitaliy Gusev 		mdb_printf("\n");
1092*86d949f9SVitaliy Gusev 		return (WALK_NEXT);
1093*86d949f9SVitaliy Gusev 	}
1094*86d949f9SVitaliy Gusev 
1095*86d949f9SVitaliy Gusev 	switch (GET_NLM_STATE(ld)) {
1096*86d949f9SVitaliy Gusev 	case FLK_NLM_UP:
1097*86d949f9SVitaliy Gusev 		s = "up";
1098*86d949f9SVitaliy Gusev 		break;
1099*86d949f9SVitaliy Gusev 	case FLK_NLM_SHUTTING_DOWN:
1100*86d949f9SVitaliy Gusev 		s = "halting";
1101*86d949f9SVitaliy Gusev 		break;
1102*86d949f9SVitaliy Gusev 	case FLK_NLM_DOWN:
1103*86d949f9SVitaliy Gusev 		s = "down";
1104*86d949f9SVitaliy Gusev 		break;
1105*86d949f9SVitaliy Gusev 	case FLK_NLM_UNKNOWN:
1106*86d949f9SVitaliy Gusev 		s = "unknown";
1107*86d949f9SVitaliy Gusev 		break;
1108*86d949f9SVitaliy Gusev 	default:
1109*86d949f9SVitaliy Gusev 		s = "??";
1110*86d949f9SVitaliy Gusev 		break;
1111*86d949f9SVitaliy Gusev 	}
1112*86d949f9SVitaliy Gusev 
1113*86d949f9SVitaliy Gusev 	mdb_printf("(%5i:%-5i) %-7s ", ld->l_start, ld->l_len, s);
1114*86d949f9SVitaliy Gusev 	if (mdb_vnode2path((uintptr_t)ld->l_vnode,
1115*86d949f9SVitaliy Gusev 	    arg->pathbuf, PATH_MAX) == -1)
1116*86d949f9SVitaliy Gusev 		strlcpy(arg->pathbuf, "??", PATH_MAX);
1117*86d949f9SVitaliy Gusev 	mdb_printf("%s\n", arg->pathbuf);
1118*86d949f9SVitaliy Gusev 
1119*86d949f9SVitaliy Gusev 	return (WALK_NEXT);
1120*86d949f9SVitaliy Gusev }
1121*86d949f9SVitaliy Gusev 
1122*86d949f9SVitaliy Gusev 
1123*86d949f9SVitaliy Gusev static const mdb_walker_t walkers[] = {
1124*86d949f9SVitaliy Gusev 	{
1125*86d949f9SVitaliy Gusev 		"nlm_zone", "nlm_zone walker",
1126*86d949f9SVitaliy Gusev 		nlm_zone_walk_init, nlm_zone_walk_step
1127*86d949f9SVitaliy Gusev 	},
1128*86d949f9SVitaliy Gusev 	{
1129*86d949f9SVitaliy Gusev 		"nlm_host", "nlm_host walker",
1130*86d949f9SVitaliy Gusev 		nlm_host_walk_init, nlm_host_walk_step
1131*86d949f9SVitaliy Gusev 	},
1132*86d949f9SVitaliy Gusev 	{
1133*86d949f9SVitaliy Gusev 		"nlm_vhold", "nlm_vhold walker",
1134*86d949f9SVitaliy Gusev 		nlm_vhold_walk_init, nlm_vhold_walk_step
1135*86d949f9SVitaliy Gusev 	},
1136*86d949f9SVitaliy Gusev 	{
1137*86d949f9SVitaliy Gusev 		"nlm_slreq", "nlm_slreq walker",
1138*86d949f9SVitaliy Gusev 		nlm_slreq_walk_init, nlm_slreq_walk_step
1139*86d949f9SVitaliy Gusev 	},
1140*86d949f9SVitaliy Gusev 	{NULL, NULL, NULL, NULL}
1141*86d949f9SVitaliy Gusev };
1142*86d949f9SVitaliy Gusev 
1143*86d949f9SVitaliy Gusev static const mdb_dcmd_t dcmds[] = {
1144*86d949f9SVitaliy Gusev 	{
1145*86d949f9SVitaliy Gusev 		"nlm_zone", "?[-v]",
1146*86d949f9SVitaliy Gusev 		"dump per-zone nlm_globals",
1147*86d949f9SVitaliy Gusev 		nlm_zone_dcmd, nlm_zone_help
1148*86d949f9SVitaliy Gusev 	},
1149*86d949f9SVitaliy Gusev 	{
1150*86d949f9SVitaliy Gusev 		"nlm_host", "?[-v]",
1151*86d949f9SVitaliy Gusev 		"dump nlm_host structures (hosts/sysids)",
1152*86d949f9SVitaliy Gusev 		nlm_host_dcmd, nlm_host_help
1153*86d949f9SVitaliy Gusev 	},
1154*86d949f9SVitaliy Gusev 	{
1155*86d949f9SVitaliy Gusev 		"nlm_vhold", "?[-v]",
1156*86d949f9SVitaliy Gusev 		"dump nlm_vhold structures (vnode holds)",
1157*86d949f9SVitaliy Gusev 		nlm_vhold_dcmd, nlm_vhold_help
1158*86d949f9SVitaliy Gusev 	},
1159*86d949f9SVitaliy Gusev 	{
1160*86d949f9SVitaliy Gusev 		"nlm_slreq", "?[-v]",
1161*86d949f9SVitaliy Gusev 		"dump nlm_slreq structures (sleeping lock requests)",
1162*86d949f9SVitaliy Gusev 		nlm_slreq_dcmd, nlm_slreq_help
1163*86d949f9SVitaliy Gusev 	},
1164*86d949f9SVitaliy Gusev 	{
1165*86d949f9SVitaliy Gusev 		"nlm_list", "[-v][-a][-d depth][-h host][-s 0tSysID]",
1166*86d949f9SVitaliy Gusev 		"list all zones, optionally filter hosts ",
1167*86d949f9SVitaliy Gusev 		nlm_list_dcmd, nlm_list_help
1168*86d949f9SVitaliy Gusev 	},
1169*86d949f9SVitaliy Gusev 	{
1170*86d949f9SVitaliy Gusev 		"nlm_lockson", "[-v] [-h host] [-s 0tSysID]",
1171*86d949f9SVitaliy Gusev 		"dump NLM locks from host (or sysid)",
1172*86d949f9SVitaliy Gusev 		nlm_lockson_dcmd, nlm_lockson_help
1173*86d949f9SVitaliy Gusev 	},
1174*86d949f9SVitaliy Gusev 	{NULL, NULL, NULL, NULL}
1175*86d949f9SVitaliy Gusev };
1176*86d949f9SVitaliy Gusev 
1177*86d949f9SVitaliy Gusev static const mdb_modinfo_t modinfo = {
1178*86d949f9SVitaliy Gusev 	MDB_API_VERSION,
1179*86d949f9SVitaliy Gusev 	dcmds,
1180*86d949f9SVitaliy Gusev 	walkers
1181*86d949f9SVitaliy Gusev };
1182*86d949f9SVitaliy Gusev 
1183*86d949f9SVitaliy Gusev const mdb_modinfo_t *
_mdb_init(void)1184*86d949f9SVitaliy Gusev _mdb_init(void)
1185*86d949f9SVitaliy Gusev {
1186*86d949f9SVitaliy Gusev 	return (&modinfo);
1187*86d949f9SVitaliy Gusev }
1188