1*e0687fa3SGordon Ross /*
2*e0687fa3SGordon Ross  * This file and its contents are supplied under the terms of the
3*e0687fa3SGordon Ross  * Common Development and Distribution License ("CDDL"), version 1.0.
4*e0687fa3SGordon Ross  * You may only use this file in accordance with the terms of version
5*e0687fa3SGordon Ross  * 1.0 of the CDDL.
6*e0687fa3SGordon Ross  *
7*e0687fa3SGordon Ross  * A full copy of the text of the CDDL should have accompanied this
8*e0687fa3SGordon Ross  * source.  A copy of the CDDL is also available via the Internet at
9*e0687fa3SGordon Ross  * http://www.illumos.org/license/CDDL.
10*e0687fa3SGordon Ross  */
11*e0687fa3SGordon Ross 
12*e0687fa3SGordon Ross /*
13*e0687fa3SGordon Ross  * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
14*e0687fa3SGordon Ross  */
15*e0687fa3SGordon Ross 
16*e0687fa3SGordon Ross /*
17*e0687fa3SGordon Ross  * mdb module for libmlsvc, which contains interesting data structures
18*e0687fa3SGordon Ross  * including: the share cache
19*e0687fa3SGordon Ross  */
20*e0687fa3SGordon Ross 
21*e0687fa3SGordon Ross #include <mdb/mdb_modapi.h>
22*e0687fa3SGordon Ross #include <mdb/mdb_ks.h>
23*e0687fa3SGordon Ross #include <mdb/mdb_ctf.h>
24*e0687fa3SGordon Ross 
25*e0687fa3SGordon Ross #include <synch.h>
26*e0687fa3SGordon Ross #include <smbsrv/hash_table.h>
27*e0687fa3SGordon Ross #include <smbsrv/libsmb.h>
28*e0687fa3SGordon Ross #include <smbsrv/smb_share.h>
29*e0687fa3SGordon Ross 
30*e0687fa3SGordon Ross #define	MLSVC_OBJNAME	"libmlsvc.so.1"
31*e0687fa3SGordon Ross #define	MLSVC_SCOPE	MLSVC_OBJNAME "`"
32*e0687fa3SGordon Ross 
33*e0687fa3SGordon Ross #define	AFLAG		1
34*e0687fa3SGordon Ross #define	VFLAG		2
35*e0687fa3SGordon Ross 
36*e0687fa3SGordon Ross typedef struct dump_shr_args {
37*e0687fa3SGordon Ross 	uint_t dsa_opts;
38*e0687fa3SGordon Ross 	uintptr_t dsa_hdl;
39*e0687fa3SGordon Ross 	smb_share_t dsa_shr;
40*e0687fa3SGordon Ross } dump_shr_args_t;
41*e0687fa3SGordon Ross 
42*e0687fa3SGordon Ross /*ARGSUSED*/
43*e0687fa3SGordon Ross static int
dump_shr_cb(uintptr_t addr,const void * data,void * varg)44*e0687fa3SGordon Ross dump_shr_cb(uintptr_t addr, const void *data, void *varg)
45*e0687fa3SGordon Ross {
46*e0687fa3SGordon Ross 	dump_shr_args_t *args = varg;
47*e0687fa3SGordon Ross 	const HT_ITEM *hi = data;
48*e0687fa3SGordon Ross 	smb_share_t *shr = &args->dsa_shr;
49*e0687fa3SGordon Ross 
50*e0687fa3SGordon Ross 	if (hi->hi_data == NULL)
51*e0687fa3SGordon Ross 		return (WALK_NEXT);
52*e0687fa3SGordon Ross 
53*e0687fa3SGordon Ross 	if ((hi->hi_flags & HT_DELETE) != 0 &&
54*e0687fa3SGordon Ross 	    (args->dsa_opts & AFLAG) == 0)
55*e0687fa3SGordon Ross 		return (WALK_NEXT);
56*e0687fa3SGordon Ross 
57*e0687fa3SGordon Ross 	if (args->dsa_opts & VFLAG) {
58*e0687fa3SGordon Ross 		mdb_arg_t argv;
59*e0687fa3SGordon Ross 		int flags = DCMD_ADDRSPEC;
60*e0687fa3SGordon Ross 
61*e0687fa3SGordon Ross 		argv.a_type = MDB_TYPE_STRING;
62*e0687fa3SGordon Ross 		argv.a_un.a_str = MLSVC_SCOPE "smb_share_t";
63*e0687fa3SGordon Ross 		/* Don't fail the walk if this fails. */
64*e0687fa3SGordon Ross 		mdb_printf("%-?p ", hi->hi_data);
65*e0687fa3SGordon Ross 		mdb_call_dcmd("print", (uintptr_t)hi->hi_data,
66*e0687fa3SGordon Ross 		    flags, 1, &argv);
67*e0687fa3SGordon Ross 	} else {
68*e0687fa3SGordon Ross 		if (mdb_vread(shr, sizeof (*shr),
69*e0687fa3SGordon Ross 		    (uintptr_t)hi->hi_data) == -1) {
70*e0687fa3SGordon Ross 			mdb_warn("failed to read %s at %p",
71*e0687fa3SGordon Ross 			    "smb_share_t", hi->hi_data);
72*e0687fa3SGordon Ross 			return (WALK_NEXT);
73*e0687fa3SGordon Ross 		}
74*e0687fa3SGordon Ross 
75*e0687fa3SGordon Ross 		mdb_printf("%-?p ", hi->hi_data);
76*e0687fa3SGordon Ross 		mdb_printf("name=%s path=%s desc=\"%s\"\n",
77*e0687fa3SGordon Ross 		    shr->shr_name, shr->shr_path, shr->shr_cmnt);
78*e0687fa3SGordon Ross 	}
79*e0687fa3SGordon Ross 
80*e0687fa3SGordon Ross 	return (WALK_NEXT);
81*e0687fa3SGordon Ross }
82*e0687fa3SGordon Ross 
83*e0687fa3SGordon Ross 
84*e0687fa3SGordon Ross /*
85*e0687fa3SGordon Ross  * *************************** Top level dcmds ****************************
86*e0687fa3SGordon Ross  */
87*e0687fa3SGordon Ross 
88*e0687fa3SGordon Ross typedef struct mdb_smb_shr_cache {
89*e0687fa3SGordon Ross 	HT_HANDLE	*sc_cache;
90*e0687fa3SGordon Ross 	rwlock_t	sc_cache_lck;
91*e0687fa3SGordon Ross 	mutex_t		sc_mtx;
92*e0687fa3SGordon Ross 	cond_t		sc_cv;
93*e0687fa3SGordon Ross 	uint32_t	sc_state;
94*e0687fa3SGordon Ross 	uint32_t	sc_nops;
95*e0687fa3SGordon Ross } mdb_smb_shr_cache_t;
96*e0687fa3SGordon Ross 
97*e0687fa3SGordon Ross 
98*e0687fa3SGordon Ross static void
smb_shr_cache_help(void)99*e0687fa3SGordon Ross smb_shr_cache_help(void)
100*e0687fa3SGordon Ross {
101*e0687fa3SGordon Ross 	mdb_printf(
102*e0687fa3SGordon Ross 	    "Displays the list of shares in the smbd smb_shr_cache.\n"
103*e0687fa3SGordon Ross 	    "With -a, also show deleted entries.\n"
104*e0687fa3SGordon Ross 	    "With -v, print full smb_share_t objects.\n\n");
105*e0687fa3SGordon Ross }
106*e0687fa3SGordon Ross 
107*e0687fa3SGordon Ross /*
108*e0687fa3SGordon Ross  * ::smb_shr_cache
109*e0687fa3SGordon Ross  */
110*e0687fa3SGordon Ross /*ARGSUSED*/
111*e0687fa3SGordon Ross static int
smb_shr_cache_dcmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)112*e0687fa3SGordon Ross smb_shr_cache_dcmd(uintptr_t addr, uint_t flags, int argc,
113*e0687fa3SGordon Ross     const mdb_arg_t *argv)
114*e0687fa3SGordon Ross {
115*e0687fa3SGordon Ross 	dump_shr_args_t *args;
116*e0687fa3SGordon Ross 	mdb_smb_shr_cache_t *ssc;
117*e0687fa3SGordon Ross 
118*e0687fa3SGordon Ross 	args = mdb_zalloc(sizeof (*args), UM_SLEEP | UM_GC);
119*e0687fa3SGordon Ross 
120*e0687fa3SGordon Ross 	if (mdb_getopts(argc, argv,
121*e0687fa3SGordon Ross 	    'a', MDB_OPT_SETBITS, AFLAG, &args->dsa_opts,
122*e0687fa3SGordon Ross 	    'v', MDB_OPT_SETBITS, VFLAG, &args->dsa_opts,
123*e0687fa3SGordon Ross 	    NULL) != argc)
124*e0687fa3SGordon Ross 		return (DCMD_USAGE);
125*e0687fa3SGordon Ross 
126*e0687fa3SGordon Ross 	if (!(flags & DCMD_ADDRSPEC)) {
127*e0687fa3SGordon Ross 		GElf_Sym	sym;
128*e0687fa3SGordon Ross 
129*e0687fa3SGordon Ross 		/* Locate the shr hash head. */
130*e0687fa3SGordon Ross 		if (mdb_lookup_by_obj(MLSVC_OBJNAME, "smb_shr_cache", &sym)) {
131*e0687fa3SGordon Ross 			mdb_warn("failed to lookup `smb_shr_cache'\n");
132*e0687fa3SGordon Ross 			return (DCMD_ERR);
133*e0687fa3SGordon Ross 		}
134*e0687fa3SGordon Ross 		addr = sym.st_value;
135*e0687fa3SGordon Ross 	}
136*e0687fa3SGordon Ross 
137*e0687fa3SGordon Ross 	ssc = mdb_zalloc(sizeof (*ssc), UM_SLEEP | UM_GC);
138*e0687fa3SGordon Ross 	if (mdb_ctf_vread(ssc, MLSVC_SCOPE "smb_shr_cache_t",
139*e0687fa3SGordon Ross 	    "mdb_smb_shr_cache_t", addr, 0) < 0) {
140*e0687fa3SGordon Ross 		mdb_warn("failed to read smb_shr_cache at %p", addr);
141*e0687fa3SGordon Ross 		return (DCMD_ERR);
142*e0687fa3SGordon Ross 	}
143*e0687fa3SGordon Ross 
144*e0687fa3SGordon Ross 	/* Now walk HT_HANDLE *sc_cache */
145*e0687fa3SGordon Ross 	args->dsa_hdl = (uintptr_t)ssc->sc_cache;
146*e0687fa3SGordon Ross 
147*e0687fa3SGordon Ross 	if (mdb_pwalk(MLSVC_SCOPE "smb_ht_walker",
148*e0687fa3SGordon Ross 	    dump_shr_cb, args, args->dsa_hdl) == -1) {
149*e0687fa3SGordon Ross 		mdb_warn("cannot walk smb_shr_cache list");
150*e0687fa3SGordon Ross 		return (DCMD_ERR);
151*e0687fa3SGordon Ross 	}
152*e0687fa3SGordon Ross 	return (DCMD_OK);
153*e0687fa3SGordon Ross }
154*e0687fa3SGordon Ross 
155*e0687fa3SGordon Ross 
156*e0687fa3SGordon Ross 
157*e0687fa3SGordon Ross /*
158*e0687fa3SGordon Ross  * MDB module linkage information:
159*e0687fa3SGordon Ross  *
160*e0687fa3SGordon Ross  * We declare a list of structures describing our dcmds, a list of structures
161*e0687fa3SGordon Ross  * describing our walkers and a function named _mdb_init to return a pointer
162*e0687fa3SGordon Ross  * to our module information.
163*e0687fa3SGordon Ross  */
164*e0687fa3SGordon Ross static const mdb_dcmd_t dcmds[] = {
165*e0687fa3SGordon Ross 
166*e0687fa3SGordon Ross 	/* Avoiding name conflict with smbsrv`smb_shr_cache */
167*e0687fa3SGordon Ross 	{   "smbd_shr_cache",
168*e0687fa3SGordon Ross 	    "[-av]",
169*e0687fa3SGordon Ross 	    "print SMB share cache",
170*e0687fa3SGordon Ross 	    smb_shr_cache_dcmd,
171*e0687fa3SGordon Ross 	    smb_shr_cache_help },
172*e0687fa3SGordon Ross 
173*e0687fa3SGordon Ross 	{ NULL }
174*e0687fa3SGordon Ross };
175*e0687fa3SGordon Ross 
176*e0687fa3SGordon Ross int smb_ht_walk_init(mdb_walk_state_t *wsp);
177*e0687fa3SGordon Ross int smb_ht_walk_step(mdb_walk_state_t *wsp);
178*e0687fa3SGordon Ross 
179*e0687fa3SGordon Ross static const mdb_walker_t walkers[] = {
180*e0687fa3SGordon Ross 	{   "smb_ht_walker",
181*e0687fa3SGordon Ross 	    "walk an smb_hash_t structure",
182*e0687fa3SGordon Ross 	    smb_ht_walk_init,
183*e0687fa3SGordon Ross 	    smb_ht_walk_step,
184*e0687fa3SGordon Ross 	    NULL,
185*e0687fa3SGordon Ross 	    NULL },
186*e0687fa3SGordon Ross 	{ NULL }
187*e0687fa3SGordon Ross };
188*e0687fa3SGordon Ross 
189*e0687fa3SGordon Ross static const mdb_modinfo_t modinfo = {
190*e0687fa3SGordon Ross 	MDB_API_VERSION, dcmds, walkers
191*e0687fa3SGordon Ross };
192*e0687fa3SGordon Ross 
193*e0687fa3SGordon Ross const mdb_modinfo_t *
_mdb_init(void)194*e0687fa3SGordon Ross _mdb_init(void)
195*e0687fa3SGordon Ross {
196*e0687fa3SGordon Ross 	return (&modinfo);
197*e0687fa3SGordon Ross }
198