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
print_did_shared_name(uintptr_t addr,int i)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
print_nm_shared_name(uintptr_t addr,int i)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
print_devid_name(uintptr_t addr,int i)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
print_nm_name(uintptr_t addr,int i)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
process_nmn_record_hdr(uintptr_t addr)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
process_nmn_record(uintptr_t addr,int shared,int devid)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
process_nm_next_hdr(uintptr_t addr,int shared,int devid)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
process_set(int setno)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
dumpnamespace(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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