xref: /titanic_41/usr/src/cmd/mdb/common/modules/md/dumpnamespace.c (revision 31e37bb439502e3f7c4c0a9a77d655ea5d56887a)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include "mdinclude.h"
30 #include <sys/lvm/md_names.h>
31 
32 /*
33  * work out the offset size
34  */
35 #define	MY_DID_SHR_NAMSIZ(n) \
36 	(((sizeof (struct did_shr_name) - 1) + \
37 	n + (sizeof (uint_t) - 1)) & ~(sizeof (uint_t) - 1))
38 #define	MY_SHR_NAMSIZ(n) \
39 	(((sizeof (struct nm_shared_name) - 1) + \
40 	n + (sizeof (uint_t) - 1)) & ~(sizeof (uint_t) - 1))
41 #define	MY_DID_NAMSIZ(n) \
42 	(((sizeof (struct did_min_name) - 1) + \
43 	n + (sizeof (uint_t) - 1)) & ~(sizeof (uint_t) - 1))
44 #define	MY_NAMSIZ(n) \
45 	(((sizeof (struct nm_name) - 1) + \
46 	n + (sizeof (uint_t) - 1)) & ~(sizeof (uint_t) - 1))
47 
48 static uintptr_t
49 print_did_shared_name(uintptr_t addr, int i)
50 {
51 	struct did_shr_name	shn;
52 	uintptr_t		sn_name_addr;
53 	void			*sn_name;
54 	uintptr_t		next_addr = addr;
55 
56 	if (mdb_vread(&shn, sizeof (struct did_shr_name), addr) !=
57 	    sizeof (struct did_shr_name)) {
58 		mdb_warn("failed to read did_shr_name at %p\n", addr);
59 		return (NULL);
60 	}
61 	if (shn.did_size == 0)
62 		return (NULL);
63 	mdb_printf("device_id[%d] at %p\n", i, addr);
64 	mdb_inc_indent(2);
65 	mdb_printf("did_key:    %d\n", shn.did_key);
66 	mdb_printf("did_count:  %u\n", shn.did_count);
67 	mdb_printf("did_data:   0x%x \n", shn.did_data);
68 	mdb_printf("did_size: %u\n", shn.did_size);
69 	sn_name_addr = addr + ((uintptr_t)&shn.did_devid - (uintptr_t)&shn);
70 	if (shn.did_size > 0) {
71 		sn_name = mdb_alloc(shn.did_size + 1, UM_SLEEP | UM_GC);
72 		if (mdb_readstr((char *)sn_name, shn.did_size + 1,
73 		    sn_name_addr) <= 0) {
74 			mdb_warn("failed to read sn_name at %p\n",
75 			    sn_name_addr);
76 			return (NULL);
77 		}
78 		mdb_printf("did_devid:   %s at %p\n", (char *)sn_name,
79 		    sn_name_addr);
80 		next_addr = addr + MY_DID_SHR_NAMSIZ(shn.did_size);
81 	}
82 	mdb_dec_indent(2);
83 	return (next_addr);
84 }
85 
86 static uintptr_t
87 print_nm_shared_name(uintptr_t addr, int i)
88 {
89 	struct nm_shared_name	shn;
90 	uintptr_t		sn_name_addr;
91 	void			*sn_name;
92 	uintptr_t		next_addr = addr;
93 
94 	if (mdb_vread(&shn, sizeof (struct nm_shared_name), addr) !=
95 	    sizeof (struct nm_shared_name)) {
96 		mdb_warn("failed to read nm_shared_name at %p\n", addr);
97 		return (NULL);
98 	}
99 	if (shn.sn_namlen == 0)
100 		return (NULL);
101 	mdb_printf("sr_name[%d] at %p\n", i, addr);
102 	mdb_inc_indent(2);
103 	mdb_printf("sn_key:    %d \n", shn.sn_key);
104 	mdb_printf("sn_count:  %u\n", shn.sn_count);
105 	mdb_printf("sn_data:   0x%x \n", shn.sn_data);
106 	mdb_printf("sn_namlen: %u\n", shn.sn_namlen);
107 	sn_name_addr = addr + ((uintptr_t)&shn.sn_name - (uintptr_t)&shn);
108 	if (shn.sn_namlen > 0) {
109 		sn_name = mdb_alloc(shn.sn_namlen + 1, UM_SLEEP | UM_GC);
110 		if (mdb_readstr((char *)sn_name, shn.sn_namlen + 1,
111 		    sn_name_addr) <= 0) {
112 			mdb_warn("failed to read sn_name at %p\n",
113 			    sn_name_addr);
114 		}
115 		mdb_printf("sn_name:   %s at %p\n", (char *)sn_name,
116 		    sn_name_addr);
117 		next_addr = addr + MY_SHR_NAMSIZ(shn.sn_namlen);
118 	}
119 	mdb_dec_indent(2);
120 	return (next_addr);
121 }
122 
123 static uintptr_t
124 print_devid_name(uintptr_t addr, int i)
125 {
126 	struct did_min_name	didmn;
127 	uintptr_t		did_name_addr;
128 	void			*min_name;
129 	uintptr_t		next_addr = addr;
130 
131 	if (mdb_vread(&didmn, sizeof (struct did_min_name), addr) !=
132 	    sizeof (struct did_min_name)) {
133 		mdb_warn("failed to read did_min_name at %p\n", addr);
134 		return (NULL);
135 	}
136 	if (didmn.min_namlen == 0)
137 		return (NULL);
138 	mdb_printf("minor_name[%d] at %p\n", i, addr);
139 	mdb_inc_indent(2);
140 	mdb_printf("min_key:    %d \n", didmn.min_key);
141 	mdb_printf("min_count:  %u\n", didmn.min_count);
142 	mdb_printf("min_devid_key:    %d \n", didmn.min_devid_key);
143 	mdb_printf("min_namlen: %u\n", didmn.min_namlen);
144 	did_name_addr = addr + ((uintptr_t)&didmn.min_name - (uintptr_t)&didmn);
145 	if (didmn.min_namlen > 0) {
146 		min_name = mdb_alloc(didmn.min_namlen + 1, UM_SLEEP | UM_GC);
147 		if (mdb_readstr((char *)min_name, didmn.min_namlen + 1,
148 		    did_name_addr) <= 0) {
149 			mdb_warn("failed to read min_name at %p\n",
150 			    did_name_addr);
151 		}
152 		mdb_printf("min_name:   %s at %p\n", (char *)min_name,
153 		    did_name_addr);
154 		next_addr = addr + MY_DID_NAMSIZ(didmn.min_namlen);
155 	}
156 	mdb_dec_indent(2);
157 	return (next_addr);
158 }
159 
160 static uintptr_t
161 print_nm_name(uintptr_t addr, int i)
162 {
163 	struct nm_name	nm;
164 	uintptr_t	nm_name_addr;
165 	void		*n_name;
166 	uintptr_t	next_addr = addr;
167 
168 	if (mdb_vread(&nm, sizeof (struct nm_name), addr) !=
169 	    sizeof (struct nm_name)) {
170 		mdb_warn("failed to read nm_name at %p\n", addr);
171 		return (NULL);
172 	}
173 	if (nm.n_namlen == 0)
174 		return (NULL);
175 	mdb_printf("r_name[%d] at %p\n", i, addr);
176 	mdb_inc_indent(2);
177 	mdb_printf("n_key:    %d \n", nm.n_key);
178 	mdb_printf("n_count:  %u\n", nm.n_count);
179 	mdb_printf("n_minor:  %x\n", nm.n_minor);
180 	mdb_printf("n_drv_key:    %d \n", nm.n_drv_key);
181 	mdb_printf("n_dir_key:    %d \n", nm.n_dir_key);
182 	mdb_printf("n_namlen: %u\n", nm.n_namlen);
183 	nm_name_addr = addr + ((uintptr_t)&nm.n_name - (uintptr_t)&nm);
184 	if (nm.n_namlen > 0) {
185 		n_name = mdb_alloc(nm.n_namlen + 1, UM_SLEEP | UM_GC);
186 		if (mdb_readstr((char *)n_name, nm.n_namlen + 1,
187 		    nm_name_addr) <= 0) {
188 			mdb_warn("failed to read n_name at %p\n", nm_name_addr);
189 		}
190 		mdb_printf("n_name:   %s at %p\n", (char *)n_name,
191 		    nm_name_addr);
192 		next_addr = addr + MY_NAMSIZ(nm.n_namlen);
193 	}
194 
195 	mdb_dec_indent(2);
196 	return (next_addr);
197 }
198 
199 static uint_t
200 process_nmn_record_hdr(uintptr_t addr)
201 {
202 	struct nm_rec_hdr	rhdr;
203 
204 	/*
205 	 * we read this anyway as the first part of nm_rec, devid_min_rec,
206 	 * nm_shr_rec, and devid_shr_rec record is a nm_rec_hdr
207 	 */
208 	if (mdb_vread(&rhdr, sizeof (struct nm_rec_hdr), addr) !=
209 	    sizeof (struct nm_rec_hdr)) {
210 		mdb_warn("failed to read nm_rec_hdr at %p\n", addr);
211 		return (0);
212 	}
213 
214 	mdb_printf("nmn_record: %p\n", addr);
215 	mdb_inc_indent(2);
216 	mdb_printf("r_revision:     %4u\n", rhdr.r_revision);
217 	mdb_printf("r_alloc_size:   %4u\n", rhdr.r_alloc_size);
218 	mdb_printf("r_used_size:    %4u\n", rhdr.r_used_size);
219 	mdb_printf("r_next_recid:   %4x\n", rhdr.r_next_recid);
220 	mdb_printf("xr_next_rec:    %4u\n", rhdr.xr_next_rec);
221 	mdb_printf("r_next_key:     %4d\n", rhdr.r_next_key);
222 	mdb_dec_indent(2);
223 	return (rhdr.r_used_size);
224 }
225 
226 static void
227 process_nmn_record(uintptr_t addr, int shared, int devid)
228 {
229 	struct nm_shr_rec	srhdr;
230 	struct devid_shr_rec	didsrhdr;
231 	struct nm_rec		nm_record;
232 	struct devid_min_rec	devid_record;
233 	uintptr_t		shn_addr;
234 	int			i;
235 	uintptr_t		next_addr, start_addr;
236 	uint_t			used_size;
237 
238 	used_size = process_nmn_record_hdr(addr);
239 
240 	if (devid) {
241 		if (shared) {
242 			if (mdb_vread(&didsrhdr, sizeof (struct devid_shr_rec),
243 			    addr) != sizeof (struct devid_shr_rec)) {
244 				mdb_warn("failed to read devid_shr_rec at %p\n",
245 				    addr);
246 				return;
247 			}
248 		} else {
249 			if (mdb_vread(&devid_record,
250 			    sizeof (struct devid_min_rec), addr)
251 			    != sizeof (struct devid_min_rec)) {
252 				mdb_warn("failed to read devid_min_rec at %p\n",
253 				    addr);
254 				return;
255 			}
256 		}
257 	} else {
258 		if (shared) {
259 			if (mdb_vread(&srhdr, sizeof (struct nm_shr_rec), addr)
260 			    != sizeof (struct nm_shr_rec)) {
261 				mdb_warn("failed to read nm_shr_rec at %p\n",
262 				    addr);
263 				return;
264 			}
265 		} else {
266 			if (mdb_vread(&nm_record, sizeof (struct nm_rec), addr)
267 			    != sizeof (struct nm_rec)) {
268 				mdb_warn("failed to read nm_rec at %p\n", addr);
269 				return;
270 			}
271 		}
272 	}
273 	mdb_inc_indent(2);
274 	if (devid) {
275 		if (shared) {
276 			/*
277 			 * Do the rest of the device_id records.
278 			 */
279 			next_addr = addr + ((uintptr_t)&didsrhdr.device_id[0] -
280 			    (uintptr_t)&didsrhdr);
281 			start_addr = next_addr;
282 			for (i = 0; ; i++) {
283 				shn_addr = next_addr;
284 				next_addr = print_did_shared_name(shn_addr, i);
285 				if (next_addr == NULL) {
286 					mdb_dec_indent(2);
287 					return;
288 				}
289 				/*
290 				 * Causes us to print one extra record.
291 				 */
292 				if ((next_addr - start_addr > used_size) ||
293 				    (next_addr == shn_addr)) {
294 					break;
295 				}
296 			}
297 		} else {
298 			/*
299 			 * Now do the rest of the record.
300 			 */
301 			next_addr = addr +
302 			    ((uintptr_t)&devid_record.minor_name[0] -
303 			    (uintptr_t)&devid_record);
304 			start_addr = next_addr;
305 			for (i = 0; ; i++) {
306 				shn_addr = next_addr;
307 				next_addr = print_devid_name(shn_addr, i);
308 				if (next_addr == NULL) {
309 					mdb_dec_indent(2);
310 					return;
311 				}
312 				if ((next_addr - start_addr > used_size) ||
313 				    (next_addr == shn_addr)) {
314 					break;
315 				}
316 			}
317 		}
318 	} else {
319 		if (shared) {
320 			/*
321 			 * Now do the rest of the sr_name records.
322 			 */
323 			next_addr = addr + ((uintptr_t)&srhdr.sr_name[0] -
324 			    (uintptr_t)&srhdr);
325 			start_addr = next_addr;
326 			for (i = 0; ; i++) {
327 				shn_addr = next_addr;
328 				next_addr = print_nm_shared_name(shn_addr, i);
329 				if (next_addr == NULL) {
330 					mdb_dec_indent(2);
331 					return;
332 				}
333 				/*
334 				 * Causes us to print one extra record
335 				 */
336 				if ((next_addr - start_addr > used_size) ||
337 				    (next_addr == shn_addr)) {
338 					break;
339 				}
340 			}
341 		} else {
342 			/*
343 			 * Now do the rest of the record
344 			 */
345 			next_addr = addr + ((uintptr_t)&nm_record.r_name[0] -
346 			    (uintptr_t)&nm_record);
347 			start_addr = next_addr;
348 			for (i = 0; ; i++) {
349 				shn_addr = next_addr;
350 				next_addr = print_nm_name(shn_addr, i);
351 				if (next_addr == NULL) {
352 					mdb_dec_indent(2);
353 					return;
354 				}
355 				if ((next_addr - start_addr > used_size) ||
356 				    (next_addr == shn_addr)) {
357 					break;
358 				}
359 			}
360 		}
361 	}
362 	mdb_dec_indent(2);
363 }
364 
365 static void
366 process_nm_next_hdr(uintptr_t addr, int shared, int devid)
367 {
368 	uintptr_t	next = addr;
369 	struct nm_next_hdr	nhdr;
370 
371 	mdb_inc_indent(2);
372 	mdb_printf("%p\n", next);
373 	if (mdb_vread(&nhdr, sizeof (struct nm_next_hdr), next) !=
374 	    sizeof (struct nm_next_hdr)) {
375 		mdb_warn("failed to read nm_next_hdr at %p", next);
376 		return;
377 	}
378 	(void) process_nmn_record_hdr((uintptr_t)nhdr.nmn_record);
379 	next = (uintptr_t)nhdr.nmn_nextp;
380 	while (next != (uintptr_t)0) {
381 
382 		mdb_printf("\n");
383 		mdb_printf("nmn_nextp %p\n", nhdr.nmn_nextp);
384 		if (mdb_vread(&nhdr, sizeof (struct nm_next_hdr), next) !=
385 		    sizeof (struct nm_next_hdr)) {
386 			mdb_warn("failed to read nm_next_hdr at %p\n", next);
387 			break;
388 		}
389 		process_nmn_record((uintptr_t)nhdr.nmn_record, shared, devid);
390 		next = (uintptr_t)nhdr.nmn_nextp;
391 	}
392 	mdb_printf("\n");
393 	mdb_dec_indent(2);
394 }
395 /*
396  * Start the processing of a nominated set
397  */
398 static void
399 process_set(int setno)
400 {
401 	uintptr_t	addr = (uintptr_t)mdset[setno].s_nm;
402 	uintptr_t	did_addr = (uintptr_t)mdset[setno].s_did_nm;
403 	uintptr_t	shared_addr, names_addr;
404 	uintptr_t	did_names_addr, did_shared_addr;
405 	struct nm_header_hdr	hdr, did_hdr;
406 
407 	mdb_printf("------ Name Space for setno %d ------\n", setno);
408 
409 	if (mdb_vread(&hdr, sizeof (struct nm_header_hdr), addr) !=
410 	    sizeof (struct nm_header_hdr)) {
411 		mdb_warn("failed to read nm_header_hdr at %p\n", addr);
412 		return;
413 	}
414 	mdb_printf("hh_header: %p  \n", hdr.hh_header);
415 	if (did_addr != NULL) {	/* device id's exist */
416 		if (mdb_vread(&did_hdr, sizeof (struct nm_header_hdr),
417 		    did_addr) != sizeof (struct nm_header_hdr)) {
418 			mdb_warn("failed to read nm_header_hdr at %p\n",
419 			    did_addr);
420 			return;
421 		}
422 		mdb_printf("did hh_header: %p \n", did_hdr.hh_header);
423 	did_names_addr =
424 	    (uintptr_t)&(((struct nm_header_hdr *)did_addr)->hh_names);
425 	did_shared_addr =
426 	    (uintptr_t)&(((struct nm_header_hdr *)did_addr)->hh_shared);
427 	}
428 
429 	names_addr = (uintptr_t)&(((struct nm_header_hdr *)addr)->hh_names);
430 	shared_addr = (uintptr_t)&(((struct nm_header_hdr *)addr)->hh_shared);
431 	mdb_printf("hh_names: %p \n", names_addr);
432 	mdb_printf("hh_shared: %p\n", shared_addr);
433 
434 	if (did_addr != NULL) {
435 		mdb_printf("did hh_names: %p \n", did_names_addr);
436 		mdb_printf("did hh_shared: %p\n", did_shared_addr);
437 	}
438 
439 	mdb_printf("hh_names:");
440 	process_nm_next_hdr(names_addr, 0, 0);
441 	mdb_printf("\nhh_shared:");
442 	process_nm_next_hdr(shared_addr, 1, 0);
443 
444 	if (did_addr != NULL) {
445 		mdb_printf("did hh_names:");
446 		process_nm_next_hdr(did_names_addr, 0, 1);
447 		mdb_printf("\ndid hh_shared:");
448 		process_nm_next_hdr(did_shared_addr, 1, 1);
449 	}
450 }
451 /*
452  * Dump the name space for all sets or specified set (-s option)
453  * usage: ::dumpnamespace [-s setname]
454  */
455 /* ARGSUSED */
456 int
457 dumpnamespace(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
458 {
459 	char	*s_opt = NULL;
460 	int	j;
461 	int	setno;
462 
463 	if (mdb_getopts(argc, argv, 's', MDB_OPT_STR, &s_opt,
464 	    NULL) != argc) {
465 		/* left over arguments ?? */
466 		return (DCMD_USAGE);
467 	}
468 
469 	snarf_sets();
470 
471 	if (argc == 0) {
472 		for (j = 0; j < md_nsets; j++) {
473 			if (mdset[j].s_status & MD_SET_NM_LOADED) {
474 				process_set(j);
475 			}
476 		}
477 	} else {
478 		setno = findset(s_opt);
479 		if (setno == -1) {
480 			mdb_warn("no such set: %s\n", s_opt);
481 			return (DCMD_ERR);
482 		}
483 		if (mdset[setno].s_status & MD_SET_NM_LOADED) {
484 			process_set(setno);
485 		}
486 	}
487 	return (DCMD_OK);
488 }
489