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