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