xref: /illumos-gate/usr/src/cmd/mdb/common/modules/stmf_sbd/stmf_sbd.c (revision 892ad1623e11186cba8b2eb40d70318d2cb89605)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
23  */
24 
25 #include <sys/dditypes.h>
26 #include <sys/mdb_modapi.h>
27 #include <sys/modctl.h>
28 #include <sys/sunddi.h>
29 
30 #include <lpif.h>
31 #include <stmf.h>
32 #include <stmf_ioctl.h>
33 #include <portif.h>
34 #include <stmf_sbd.h>
35 #include <sbd_impl.h>
36 #include <scsi/generic/persist.h>
37 
38 #define	STMF_SBD_STR_MAX	2048
39 #define	STMF_SBD_VERBOSE	0x00000001
40 
41 #define	ARRAY_SIZE(a)	(sizeof (a) / sizeof (*a))
42 
43 /* structure to pass arguments to mdb_walker callback function */
44 typedef struct stmf_sbd_cb_s {
45 	uint32_t flag;
46 } stmf_sbd_cb_t;
47 
48 
49 static const char *stmf_protocol_str[] = {
50 	"FIBRE_CHANNEL",	/* PROTOCOL_FIBRE_CHANNEL	0 */
51 	"PARALLEL_SCSI",	/* PROTOCOL_PARALLEL_SCSI	1 */
52 	"SSA",			/* PROTOCOL_SSA			2 */
53 	"IEEE_1394",		/* PROTOCOL_IEEE_1394		3 */
54 	"SRP",			/* PROTOCOL_SRP			4 */
55 	"iSCSI",		/* PROTOCOL_iSCSI		5 */
56 	"SAS",			/* PROTOCOL_SAS			6 */
57 	"ADT",			/* PROTOCOL_ADT			7 */
58 	"ATAPI"			/* PROTOCOL_ATAPI		8 */
59 };
60 
61 
62 /*
63  * Support functions.
64  */
65 
66 static uint64_t
67 nhconvert_8bytes(const void *src) {
68 	uint64_t dest;
69 	mdb_nhconvert(&dest, src, 8);
70 	return (dest);
71 }
72 
73 /*
74  *        Variable 'bits' is a collection of flags for which a corresponding
75  *        description string is available at flag_ary.
76  *        So flag_ary should be an ary of strings with total_bits strings.
77  */
78 static void
79 stmf_sbd_print_bit_flags(const char *flag_ary[],
80 				int total_bits, uint32_t bits) {
81 	uint32_t curbit = 0x01;
82 	int i, delim = 0;
83 
84 	for (i = 0; i < total_bits; i++) {
85 		if (bits & curbit) {
86 			mdb_printf("%s%s", (delim) ? " | " : "", flag_ary[i]);
87 			delim = 1;
88 		}
89 		curbit <<= 1;
90 	}
91 	mdb_printf("\n");
92 }
93 
94 
95 static void
96 stmf_sbd_print_pgr_info(sbd_pgr_t *pgr)
97 {
98 	static const char *pgr_flag_str[] = {
99 		"SBD_PGR_APTPL",			/* 0x01 */
100 		"SBD_PGR_RSVD_ONE",			/* 0x02 */
101 		"SBD_PGR_RSVD_ALL_REGISTRANTS",		/* 0x04 */
102 		"SBD_PGR_ALL_KEYS_HAS_IT"		/* 0x08 */
103 	};
104 
105 	static const char *pgr_type_desc[] = {
106 		"ILLEGAL",				/* 0x0 */
107 		"Write Exclusive",			/* 0x1 */
108 		"ILLEGAL",				/* 0x2 */
109 		"Exclusive Access",			/* 0x3 */
110 		"ILLEGAL",				/* 0x4 */
111 		"Write Exclusive, Registrants Only",	/* 0x5 */
112 		"Exclusive Access, Registrants Only",	/* 0x6 */
113 		"Write Exclusive, All Registrants",	/* 0x7 */
114 		"Exclusive Access, All Registrants"	/* 0x8 */
115 	};
116 
117 	mdb_printf("PGR flags: ");
118 	stmf_sbd_print_bit_flags(pgr_flag_str, ARRAY_SIZE(pgr_flag_str),
119 	    pgr->pgr_flags);
120 	if (pgr->pgr_rsvholder || pgr->pgr_flags &
121 	    SBD_PGR_RSVD_ALL_REGISTRANTS) {
122 		mdb_printf("Reservation Details \n");
123 		mdb_printf("\tReservation holder: ");
124 		if (pgr->pgr_rsvholder)
125 			mdb_printf("%p\n", pgr->pgr_rsvholder);
126 		else
127 			mdb_printf("All Registrants\n");
128 
129 		mdb_printf("\t            type  : %d => %s\n",
130 		    pgr->pgr_rsv_type,
131 		    (pgr->pgr_rsv_type < ARRAY_SIZE(pgr_type_desc)) ?
132 		    pgr_type_desc[pgr->pgr_rsv_type] : "ILLEGAL");
133 		mdb_printf("\t            scope : %d\n", pgr->pgr_rsv_scope);
134 	} else {
135 		mdb_printf("No reservations.\n");
136 	}
137 }
138 
139 void
140 print_scsi_devid_desc(uintptr_t addr, uint16_t len, char *spacer)
141 {
142 	scsi_devid_desc_t   *id;
143 
144 	if (len < sizeof (*id)) {
145 		mdb_warn("%sError: Devid Size = %d < sizeof(scsi_devid_desc_t)"
146 		    "\n", spacer, len);
147 		return;
148 	}
149 
150 	id = mdb_zalloc(len, UM_SLEEP);
151 	if (mdb_vread(id, len, addr) == -1) {
152 		mdb_warn("failed to read scsi_devid_desc at %p\n", addr);
153 		mdb_free(id, len);
154 		return;
155 	}
156 
157 	mdb_printf("%sTotal length:\t%d\n", spacer, len);
158 	mdb_printf("%sProtocol:\t%d => %-16s\n", spacer, id->protocol_id,
159 	    (id->protocol_id < ARRAY_SIZE(stmf_protocol_str)) ?
160 	    stmf_protocol_str[id->protocol_id] : "");
161 	mdb_printf("%sCode Set:\t%d\n", spacer, id->code_set);
162 	mdb_printf("%sIdent Length:\t%d\n", spacer, id->ident_length);
163 
164 	if (len < sizeof (*id) + id->ident_length - 1) {
165 		mdb_printf("%s(Can not recognize ident data)\n", spacer);
166 	} else {
167 		id->ident[id->ident_length] = '\0';
168 		mdb_printf("%sIdent:\t\t%s\n", spacer, id->ident);
169 	}
170 	mdb_free(id, len);
171 	mdb_printf("\n");
172 }
173 
174 /*
175  * Decipher and print transport id  which is pointed by addr variable.
176  */
177 static int
178 print_transport_id(uintptr_t addr, uint16_t tpd_len, char *spacer)
179 {
180 	scsi_transport_id_t *tpd;
181 
182 	if (tpd_len < sizeof (*tpd)) {
183 		mdb_warn("%sError: Transport ID Size = %d < "
184 		    "sizeof (scsi_transport_id_t)\n", spacer, tpd_len);
185 		return (DCMD_ERR);
186 	}
187 
188 	tpd = mdb_zalloc(tpd_len, UM_SLEEP);
189 	if (mdb_vread(tpd, tpd_len, addr) == -1) {
190 		mdb_warn("failed to read scsi_transport_id at %p\n", addr);
191 		mdb_free(tpd, tpd_len);
192 		return (DCMD_ERR);
193 	}
194 
195 	mdb_printf("%sTotal length:\t%d\n", spacer, tpd_len);
196 	mdb_printf("%sProtocol:\t%d => %16s\n", spacer, tpd->protocol_id,
197 	    (tpd->protocol_id < ARRAY_SIZE(stmf_protocol_str)) ?
198 	    stmf_protocol_str[tpd->protocol_id] : "");
199 	mdb_printf("%sFormat Code:\t0x%x\n", spacer, tpd->format_code);
200 
201 	switch (tpd->protocol_id) {
202 	case PROTOCOL_FIBRE_CHANNEL:
203 		{
204 		uint8_t *p = ((scsi_fc_transport_id_t *)tpd)->port_name;
205 		mdb_printf("%sFC Port Name:\t%016llX\n", spacer,
206 		    nhconvert_8bytes(p));
207 		}
208 		break;
209 	case PROTOCOL_PARALLEL_SCSI:
210 	case PROTOCOL_SSA:
211 	case PROTOCOL_IEEE_1394:
212 		break;
213 	case PROTOCOL_SRP:
214 		{
215 		uint8_t *p = ((scsi_srp_transport_id_t *)tpd)->srp_name;
216 		/* Print 8 byte initiator extention and guid in order */
217 		mdb_printf("%sSRP Name:\t%016llX:%016llX\n", spacer,
218 		    nhconvert_8bytes(&p[8]), nhconvert_8bytes(&p[0]));
219 		}
220 		break;
221 	case PROTOCOL_iSCSI:
222 		mdb_printf("%sISCSI Name:\t%s\n", spacer,
223 		    ((iscsi_transport_id_t *)tpd)->iscsi_name);
224 		break;
225 	case PROTOCOL_SAS:
226 	case PROTOCOL_ADT:
227 	case PROTOCOL_ATAPI:
228 	default:
229 		break;
230 	}
231 
232 	mdb_free(tpd, tpd_len);
233 	return (DCMD_OK);
234 }
235 
236 void
237 stmf_sbd_pgr_key_dcmd_help(void)
238 {
239 	mdb_printf(
240 	    "Prints info about pgr keys and reservations on the given lun.\n\n"
241 	    "Usage:  <addr>::stmf_sbd_pgr_key [-akv]\n"
242 	    "    where <addr> represent the address of\n"
243 	    "          sbd_lu_t by default\n"
244 	    "             or\n"
245 	    "          sbd_pgr_key_t if '-a' option is specified.\n"
246 	    "Options:\n"
247 	    "   -a   if specified, <addr> represents address of sbd_pgr_key_t\n"
248 	    "   -k   if specified, only prints key information\n"
249 	    "   -v   verbose output\n");
250 }
251 
252 
253 /*
254  * MDB WALKERS implementations
255  */
256 
257 static int
258 stmf_sbd_lu_walk_init(mdb_walk_state_t *wsp)
259 {
260 	if (wsp->walk_addr == 0) {
261 		if (mdb_readvar(&wsp->walk_addr, "sbd_lu_list") == -1) {
262 			mdb_warn("failed to read sbd_lu_list\n");
263 			return (WALK_ERR);
264 		}
265 	}
266 	return (WALK_NEXT);
267 }
268 
269 static int
270 stmf_sbd_lu_walk_step(mdb_walk_state_t *wsp)
271 {
272 	uintptr_t	addr = wsp->walk_addr;
273 	sbd_lu_t	slu;
274 
275 	if (wsp->walk_addr == 0)
276 		return (WALK_DONE);
277 
278 	if (mdb_vread(&slu, sizeof (sbd_lu_t), addr) == -1) {
279 		mdb_warn("failed to read sbd_lu_t at %p\n", addr);
280 		return (WALK_ERR);
281 	}
282 	wsp->walk_addr = (uintptr_t)slu.sl_next;
283 	return (wsp->walk_callback(addr, &slu, wsp->walk_cbdata));
284 }
285 
286 char *
287 stmf_sbd_getstr(uintptr_t addr, char *str) {
288 	if ((addr == 0) || (mdb_readstr(str, STMF_SBD_STR_MAX, addr) == -1))
289 		str = NULL;
290 	return (str);
291 }
292 
293 static int
294 stmf_sbd_lu_cb(uintptr_t addr, const sbd_lu_t *slu, stmf_sbd_cb_t *cb_st)
295 {
296 	if (cb_st->flag & STMF_SBD_VERBOSE) {
297 		char str[STMF_SBD_STR_MAX];
298 
299 		mdb_printf("\nsbd_lu - %p\n", addr);
300 
301 		/* sl_device_id contains 4 bytes hdr + 16 bytes(GUID) */
302 		mdb_printf("\tsl_deviceid:      %-?p  GUID => %016llX%016llX\n",
303 		    slu->sl_device_id, nhconvert_8bytes(&slu->sl_device_id[4]),
304 		    nhconvert_8bytes(&slu->sl_device_id[12]));
305 		mdb_printf("\tsl_name:          %-?p  %s\n", slu->sl_name,
306 		    stmf_sbd_getstr((uintptr_t)slu->sl_name, str));
307 		mdb_printf("\tsl_alias:         %-?p  %s\n", slu->sl_alias,
308 		    stmf_sbd_getstr((uintptr_t)slu->sl_alias, str));
309 		mdb_printf("\tsl_meta_filename: %-?p  %s\n",
310 		    slu->sl_meta_filename,
311 		    stmf_sbd_getstr((uintptr_t)slu->sl_meta_filename, str));
312 		mdb_printf("\tsl_data_filename: %-?p  %s\n",
313 		    slu->sl_data_filename,
314 		    stmf_sbd_getstr((uintptr_t)slu->sl_data_filename, str));
315 		mdb_printf("\tsl_mgmt_url:      %-?p  %s\n", slu->sl_mgmt_url,
316 		    stmf_sbd_getstr((uintptr_t)slu->sl_mgmt_url, str));
317 		mdb_printf("\tsl_zfs_meta:      %-?p\n", slu->sl_zfs_meta);
318 		mdb_printf("\tsl_it_list:       %-?p\n", slu->sl_it_list);
319 		mdb_printf("\tsl_pgr:           %-?p\n", slu->sl_pgr);
320 	} else {
321 		mdb_printf("%p\n", addr);
322 	}
323 	return (WALK_NEXT);
324 }
325 
326 static int
327 stmf_sbd_pgr_key_walk_init(mdb_walk_state_t *wsp)
328 {
329 	if (wsp->walk_addr == 0) {
330 		mdb_warn("<pgr_key_list addr>::walk stmf_sbd_pgr_key\n");
331 		return (WALK_ERR);
332 	}
333 	return (WALK_NEXT);
334 }
335 
336 static int
337 stmf_sbd_pgr_key_walk_step(mdb_walk_state_t *wsp)
338 {
339 	uintptr_t	addr = wsp->walk_addr;
340 	sbd_pgr_key_t	key;
341 
342 	if (wsp->walk_addr == 0)
343 		return (WALK_DONE);
344 
345 	if (mdb_vread(&key, sizeof (sbd_pgr_key_t), addr) == -1) {
346 		mdb_warn("failed to read sbd_pgr_key_t at %p\n", addr);
347 		return (WALK_ERR);
348 	}
349 	wsp->walk_addr = (uintptr_t)key.pgr_key_next;
350 	return (wsp->walk_callback(addr, &key, wsp->walk_cbdata));
351 }
352 
353 static int
354 stmf_sbd_pgr_key_cb(uintptr_t addr, const sbd_pgr_key_t *key,
355 					stmf_sbd_cb_t *cb_st)
356 {
357 	static const char *key_flag_str [] = {
358 		"SBD_PGR_KEY_ALL_TG_PT",   /* 0x01 */
359 		"SBD_PGR_KEY_TPT_ID_FLAG"  /* 0x02 */
360 	};
361 
362 	if (cb_st->flag & STMF_SBD_VERBOSE) {
363 		mdb_printf("sbd_pgr_key - %p\n", addr);
364 		mdb_printf("\tRegistered key:      0x%016llx\n", key->pgr_key);
365 		mdb_printf("\tKey Flags:           ");
366 		stmf_sbd_print_bit_flags(key_flag_str, ARRAY_SIZE(key_flag_str),
367 		    key->pgr_key_flags);
368 		mdb_printf("\tpgr_key_it:          %?-p\n", key->pgr_key_it);
369 		mdb_printf("\tLocal Device ID:     %?-p\n",
370 		    key->pgr_key_lpt_id);
371 		print_scsi_devid_desc((uintptr_t)key->pgr_key_lpt_id,
372 		    key->pgr_key_lpt_len, "		");
373 		mdb_printf("\tRemote Transport ID: %?-p\n",
374 		    key->pgr_key_rpt_id);
375 		print_transport_id((uintptr_t)key->pgr_key_rpt_id,
376 		    key->pgr_key_rpt_len, "		");
377 	} else {
378 		mdb_printf("%p\n", addr);
379 	}
380 	return (WALK_NEXT);
381 }
382 
383 static int
384 stmf_sbd_it_walk_init(mdb_walk_state_t *wsp)
385 {
386 	if (wsp->walk_addr == 0) {
387 		mdb_warn("<sbd_it_list addr>::walk stmf_sbd_pgr_key\n");
388 		return (WALK_ERR);
389 	}
390 	return (WALK_NEXT);
391 }
392 
393 static int
394 stmf_sbd_it_walk_step(mdb_walk_state_t *wsp)
395 {
396 	uintptr_t	addr = wsp->walk_addr;
397 	sbd_it_data_t	it;
398 
399 	if (wsp->walk_addr == 0)
400 		return (WALK_DONE);
401 
402 	if (mdb_vread(&it, sizeof (sbd_it_data_t), addr) == -1) {
403 		mdb_warn("failed to read sbd_it_data_t at %p\n", addr);
404 		return (WALK_ERR);
405 	}
406 	wsp->walk_addr = (uintptr_t)it.sbd_it_next;
407 	return (wsp->walk_callback(addr, &it, wsp->walk_cbdata));
408 }
409 
410 static int
411 stmf_sbd_it_cb(uintptr_t addr, const sbd_it_data_t *it, stmf_sbd_cb_t *cb_st)
412 {
413 	static const char *it_flag_str [] = {
414 		"SBD_IT_HAS_SCSI2_RESERVATION",		/* 0x0001 */
415 		"SBD_IT_PGR_REGISTERED",		/* 0x0002 */
416 		"SBD_IT_PGR_EXCLUSIVE_RSV_HOLDER",	/* 0x0004 */
417 		"SBD_IT_PGR_CHECK_FLAG"			/* 0x0008 */
418 	};
419 
420 	if (cb_st->flag & STMF_SBD_VERBOSE) {
421 		mdb_printf("SBD IT DATA - %p\n", addr);
422 		mdb_printf("\tSession ID: 0x%0-lx\n", it->sbd_it_session_id);
423 		mdb_printf("\tIT Flags:   ");
424 		stmf_sbd_print_bit_flags(it_flag_str, ARRAY_SIZE(it_flag_str),
425 		    it->sbd_it_flags);
426 		mdb_printf("\tPGR Key:    %-p\n", it->pgr_key_ptr);
427 	} else {
428 		mdb_printf("%p\n", addr);
429 	}
430 	return (WALK_NEXT);
431 }
432 
433 /*
434  * MDB DCMDS implementations.
435  */
436 
437 int
438 stmf_sbd_lu(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
439 {
440 	uint_t		verbose = FALSE;
441 	sbd_lu_t	slu;
442 	stmf_sbd_cb_t	cb_st = {0};
443 
444 	if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL)
445 	    != argc)
446 		return (DCMD_USAGE);
447 	if (verbose)
448 		cb_st.flag |= STMF_SBD_VERBOSE;
449 
450 	if (flags & DCMD_ADDRSPEC) {
451 		cb_st.flag |= STMF_SBD_VERBOSE;
452 		if (mdb_vread(&slu, sizeof (sbd_lu_t), addr) == -1) {
453 			mdb_warn("failed to read sbd_lu_t at %p\n", addr);
454 			return (DCMD_ERR);
455 		}
456 		if (stmf_sbd_lu_cb(addr, &slu, &cb_st) == WALK_ERR)
457 			return (DCMD_ERR);
458 	} else {
459 		if (mdb_walk("stmf_sbd_lu", (mdb_walk_cb_t)stmf_sbd_lu_cb,
460 		    &cb_st) == -1) {
461 			mdb_warn("failed to walk sbd_lu_list\n");
462 			return (DCMD_ERR);
463 		}
464 	}
465 	return (DCMD_OK);
466 }
467 
468 static int
469 stmf_sbd_pgr_key(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
470 {
471 	uint_t		verbose = FALSE, keyonly = FALSE, pgrkeyaddr = FALSE;
472 	sbd_lu_t	slu;
473 	sbd_pgr_t	pgr;
474 	sbd_pgr_key_t	key;
475 	stmf_sbd_cb_t	cb_st = {0};
476 
477 	if (!(flags & DCMD_ADDRSPEC))
478 		return (DCMD_USAGE);
479 
480 	if (mdb_getopts(argc, argv,
481 	    'a', MDB_OPT_SETBITS, TRUE, &pgrkeyaddr,
482 	    'k', MDB_OPT_SETBITS, TRUE, &keyonly,
483 	    'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL) != argc)
484 		return (DCMD_USAGE);
485 
486 	if (pgrkeyaddr || verbose)
487 		cb_st.flag |= STMF_SBD_VERBOSE;
488 
489 	/* If address of pgr_key is given, just print that key and return */
490 	if (pgrkeyaddr) {
491 		if (mdb_vread(&key, sizeof (sbd_pgr_key_t), addr) == -1) {
492 			mdb_warn("failed to read sbd_pgr_key at %p\n", addr);
493 			return (DCMD_ERR);
494 		}
495 		if (stmf_sbd_pgr_key_cb(addr, &key, &cb_st) == WALK_ERR) {
496 			return (DCMD_ERR);
497 		}
498 		return (DCMD_OK);
499 	} else {
500 		if (mdb_vread(&slu, sizeof (sbd_lu_t), addr) == -1) {
501 			mdb_warn("failed to read sbd_lu at %p\n", addr);
502 			return (DCMD_ERR);
503 		}
504 	}
505 
506 	if (verbose) {
507 		mdb_printf("\nLU:- %p\n", addr);
508 	}
509 	/* Just a sanity check, not necessarily needed */
510 	if (slu.sl_pgr == NULL) {
511 		if (verbose)
512 			mdb_warn("pgr structure not found for lun %p\n", addr);
513 		return (DCMD_OK);
514 	}
515 
516 	if (mdb_vread(&pgr, sizeof (sbd_pgr_t), (uintptr_t)slu.sl_pgr) == -1) {
517 		mdb_warn("failed to read sbd_lu at %p\n", slu.sl_pgr);
518 		return (DCMD_ERR);
519 	}
520 
521 	if (!keyonly)
522 		stmf_sbd_print_pgr_info(&pgr);
523 
524 	if (pgr.pgr_keylist == NULL) {
525 		if (verbose)
526 			mdb_printf("No registered pgr keys found\n");
527 		return (DCMD_OK);
528 	} else {
529 		if (!keyonly)
530 			mdb_printf("\nKeys\n");
531 	}
532 
533 	if (mdb_pwalk("stmf_sbd_pgr_key", (mdb_walk_cb_t)stmf_sbd_pgr_key_cb,
534 	    &cb_st, (uintptr_t)pgr.pgr_keylist) == -1) {
535 		mdb_warn("failed to walk pgr_keylist\n");
536 		return (DCMD_ERR);
537 	}
538 	return (DCMD_OK);
539 }
540 
541 /*ARGSUSED*/
542 static int
543 stmf_remote_port(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
544 {
545 	stmf_remote_port_t rpt;
546 	int	ret = DCMD_OK;
547 
548 	if (!(flags & DCMD_ADDRSPEC))
549 		return (DCMD_USAGE);
550 
551 	if (mdb_vread(&rpt, sizeof (stmf_remote_port_t), addr) == -1) {
552 		mdb_warn("failed to read stmf_remote_port_t at %p\n", addr);
553 		return (DCMD_ERR);
554 	}
555 
556 	ret = print_transport_id((uintptr_t)rpt.rport_tptid,
557 	    rpt.rport_tptid_sz, "		");
558 	return (ret);
559 }
560 
561 static int
562 stmf_sbd_it(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
563 {
564 	uint_t		verbose = FALSE;
565 	sbd_lu_t	slu;
566 	stmf_sbd_cb_t	cb_st = {0};
567 
568 	if (!(flags & DCMD_ADDRSPEC))
569 		return (DCMD_USAGE);
570 
571 	if (mdb_getopts(argc, argv,
572 	    'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL) != argc)
573 		return (DCMD_USAGE);
574 
575 	if (verbose) {
576 		cb_st.flag |= STMF_SBD_VERBOSE;
577 		mdb_printf("\nLU:- %p\n", addr);
578 	}
579 
580 	/* If address of pgr_key is given, just print that key and return */
581 	if (mdb_vread(&slu, sizeof (sbd_lu_t), addr) == -1) {
582 		mdb_warn("failed to read sbd_lu at %p\n", addr);
583 		return (DCMD_ERR);
584 	}
585 
586 	/* Just a sanity check, not necessarily needed */
587 	if (slu.sl_it_list == NULL) {
588 		if (verbose)
589 			mdb_printf("sbd_it_list is empty\n", addr);
590 		return (DCMD_OK);
591 	}
592 
593 	if (mdb_pwalk("stmf_sbd_it", (mdb_walk_cb_t)stmf_sbd_it_cb, &cb_st,
594 	    (uintptr_t)slu.sl_it_list) == -1) {
595 		mdb_warn("failed to walk sbd_lu_it_list\n");
596 		return (DCMD_ERR);
597 	}
598 	return (DCMD_OK);
599 }
600 
601 /*
602  * MDB dmcds and walkers definitions
603  */
604 
605 static const mdb_dcmd_t dcmds[] = {
606 	{ "stmf_sbd_lu", "?[-v]", "Print the list of sbd_lu_t",
607 	    stmf_sbd_lu, NULL },
608 	{ "stmf_sbd_it", ":[-v]", "Print the list of sbd_it_data for given lu",
609 	    stmf_sbd_it, NULL },
610 	{ "stmf_sbd_pgr_key", ":[-kov]", "Print the list of pgr keys",
611 	    stmf_sbd_pgr_key, stmf_sbd_pgr_key_dcmd_help },
612 	{ "stmf_remote_port", ":", "decipher info in a stmf_remote_port",
613 	    stmf_remote_port, NULL },
614 	{ NULL }
615 };
616 
617 static const mdb_walker_t walkers[] = {
618 	{ "stmf_sbd_lu", "walk list of stmf_sbd_lu structures",
619 	    stmf_sbd_lu_walk_init, stmf_sbd_lu_walk_step, NULL },
620 	{ "stmf_sbd_pgr_key", "walk the pgr keys of the given pgr key list",
621 	    stmf_sbd_pgr_key_walk_init, stmf_sbd_pgr_key_walk_step, NULL },
622 	{ "stmf_sbd_it", "walk the sbd_it_data for the given it list",
623 	    stmf_sbd_it_walk_init, stmf_sbd_it_walk_step, NULL },
624 	{ NULL }
625 };
626 
627 static const mdb_modinfo_t modinfo = {
628 	MDB_API_VERSION, dcmds, walkers
629 };
630 
631 const mdb_modinfo_t *
632 _mdb_init(void)
633 {
634 	return (&modinfo);
635 }
636