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.
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.
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]
22 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
25 #include <sys/dditypes.h>
26 #include <sys/mdb_modapi.h>
27 #include <sys/modctl.h>
28 #include <sys/sunddi.h>
32 #include <stmf_ioctl.h>
36 #include <scsi/generic/persist.h>
38 #define STMF_SBD_STR_MAX 2048
39 #define STMF_SBD_VERBOSE 0x00000001
41 #define ARRAY_SIZE(a) (sizeof (a) / sizeof (*a))
43 /* structure to pass arguments to mdb_walker callback function */
44 typedef struct stmf_sbd_cb_s
{
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 */
67 nhconvert_8bytes(const void *src
) {
69 mdb_nhconvert(&dest
, src
, 8);
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.
79 stmf_sbd_print_bit_flags(const char *flag_ary
[],
80 int total_bits
, uint32_t bits
) {
81 uint32_t curbit
= 0x01;
84 for (i
= 0; i
< total_bits
; i
++) {
86 mdb_printf("%s%s", (delim
) ? " | " : "", flag_ary
[i
]);
96 stmf_sbd_print_pgr_info(sbd_pgr_t
*pgr
)
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 */
105 static const char *pgr_type_desc
[] = {
107 "Write Exclusive", /* 0x1 */
109 "Exclusive Access", /* 0x3 */
111 "Write Exclusive, Registrants Only", /* 0x5 */
112 "Exclusive Access, Registrants Only", /* 0x6 */
113 "Write Exclusive, All Registrants", /* 0x7 */
114 "Exclusive Access, All Registrants" /* 0x8 */
117 mdb_printf("PGR flags: ");
118 stmf_sbd_print_bit_flags(pgr_flag_str
, ARRAY_SIZE(pgr_flag_str
),
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
);
127 mdb_printf("All Registrants\n");
129 mdb_printf("\t type : %d => %s\n",
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
);
135 mdb_printf("No reservations.\n");
140 print_scsi_devid_desc(uintptr_t addr
, uint16_t len
, char *spacer
)
142 scsi_devid_desc_t
*id
;
144 if (len
< sizeof (*id
)) {
145 mdb_warn("%sError: Devid Size = %d < sizeof(scsi_devid_desc_t)"
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
);
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
);
164 if (len
< sizeof (*id
) + id
->ident_length
- 1) {
165 mdb_printf("%s(Can not recognize ident data)\n", spacer
);
167 id
->ident
[id
->ident_length
] = '\0';
168 mdb_printf("%sIdent:\t\t%s\n", spacer
, id
->ident
);
175 * Decipher and print transport id which is pointed by addr variable.
178 print_transport_id(uintptr_t addr
, uint16_t tpd_len
, char *spacer
)
180 scsi_transport_id_t
*tpd
;
182 if (tpd_len
< sizeof (*tpd
)) {
183 mdb_warn("%sError: Transport ID Size = %d < "
184 "sizeof (scsi_transport_id_t)\n", spacer
, tpd_len
);
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
);
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
);
201 switch (tpd
->protocol_id
) {
202 case PROTOCOL_FIBRE_CHANNEL
:
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
));
209 case PROTOCOL_PARALLEL_SCSI
:
211 case PROTOCOL_IEEE_1394
:
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]));
222 mdb_printf("%sISCSI Name:\t%s\n", spacer
,
223 ((iscsi_transport_id_t
*)tpd
)->iscsi_name
);
232 mdb_free(tpd
, tpd_len
);
237 stmf_sbd_pgr_key_dcmd_help(void)
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"
245 " sbd_pgr_key_t if '-a' option is specified.\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");
254 * MDB WALKERS implementations
258 stmf_sbd_lu_walk_init(mdb_walk_state_t
*wsp
)
260 if (wsp
->walk_addr
== (uintptr_t)NULL
) {
261 if (mdb_readvar(&wsp
->walk_addr
, "sbd_lu_list") == -1) {
262 mdb_warn("failed to read sbd_lu_list\n");
270 stmf_sbd_lu_walk_step(mdb_walk_state_t
*wsp
)
272 uintptr_t addr
= wsp
->walk_addr
;
275 if (wsp
->walk_addr
== (uintptr_t)NULL
)
278 if (mdb_vread(&slu
, sizeof (sbd_lu_t
), addr
) == -1) {
279 mdb_warn("failed to read sbd_lu_t at %p\n", addr
);
282 wsp
->walk_addr
= (uintptr_t)slu
.sl_next
;
283 return (wsp
->walk_callback(addr
, &slu
, wsp
->walk_cbdata
));
287 stmf_sbd_getstr(uintptr_t addr
, char *str
) {
288 if ((addr
== (uintptr_t)NULL
) ||
289 (mdb_readstr(str
, STMF_SBD_STR_MAX
, addr
) == -1))
295 stmf_sbd_lu_cb(uintptr_t addr
, const sbd_lu_t
*slu
, stmf_sbd_cb_t
*cb_st
)
297 if (cb_st
->flag
& STMF_SBD_VERBOSE
) {
298 char str
[STMF_SBD_STR_MAX
];
300 mdb_printf("\nsbd_lu - %p\n", addr
);
302 /* sl_device_id contains 4 bytes hdr + 16 bytes(GUID) */
303 mdb_printf("\tsl_deviceid: %-?p GUID => %016llX%016llX\n",
304 slu
->sl_device_id
, nhconvert_8bytes(&slu
->sl_device_id
[4]),
305 nhconvert_8bytes(&slu
->sl_device_id
[12]));
306 mdb_printf("\tsl_name: %-?p %s\n", slu
->sl_name
,
307 stmf_sbd_getstr((uintptr_t)slu
->sl_name
, str
));
308 mdb_printf("\tsl_alias: %-?p %s\n", slu
->sl_alias
,
309 stmf_sbd_getstr((uintptr_t)slu
->sl_alias
, str
));
310 mdb_printf("\tsl_meta_filename: %-?p %s\n",
311 slu
->sl_meta_filename
,
312 stmf_sbd_getstr((uintptr_t)slu
->sl_meta_filename
, str
));
313 mdb_printf("\tsl_data_filename: %-?p %s\n",
314 slu
->sl_data_filename
,
315 stmf_sbd_getstr((uintptr_t)slu
->sl_data_filename
, str
));
316 mdb_printf("\tsl_mgmt_url: %-?p %s\n", slu
->sl_mgmt_url
,
317 stmf_sbd_getstr((uintptr_t)slu
->sl_mgmt_url
, str
));
318 mdb_printf("\tsl_zfs_meta: %-?p\n", slu
->sl_zfs_meta
);
319 mdb_printf("\tsl_it_list: %-?p\n", slu
->sl_it_list
);
320 mdb_printf("\tsl_pgr: %-?p\n", slu
->sl_pgr
);
322 mdb_printf("%p\n", addr
);
328 stmf_sbd_pgr_key_walk_init(mdb_walk_state_t
*wsp
)
330 if (wsp
->walk_addr
== (uintptr_t)NULL
) {
331 mdb_warn("<pgr_key_list addr>::walk stmf_sbd_pgr_key\n");
338 stmf_sbd_pgr_key_walk_step(mdb_walk_state_t
*wsp
)
340 uintptr_t addr
= wsp
->walk_addr
;
343 if (wsp
->walk_addr
== (uintptr_t)NULL
)
346 if (mdb_vread(&key
, sizeof (sbd_pgr_key_t
), addr
) == -1) {
347 mdb_warn("failed to read sbd_pgr_key_t at %p\n", addr
);
350 wsp
->walk_addr
= (uintptr_t)key
.pgr_key_next
;
351 return (wsp
->walk_callback(addr
, &key
, wsp
->walk_cbdata
));
355 stmf_sbd_pgr_key_cb(uintptr_t addr
, const sbd_pgr_key_t
*key
,
356 stmf_sbd_cb_t
*cb_st
)
358 static const char *key_flag_str
[] = {
359 "SBD_PGR_KEY_ALL_TG_PT", /* 0x01 */
360 "SBD_PGR_KEY_TPT_ID_FLAG" /* 0x02 */
363 if (cb_st
->flag
& STMF_SBD_VERBOSE
) {
364 mdb_printf("sbd_pgr_key - %p\n", addr
);
365 mdb_printf("\tRegistered key: 0x%016llx\n", key
->pgr_key
);
366 mdb_printf("\tKey Flags: ");
367 stmf_sbd_print_bit_flags(key_flag_str
, ARRAY_SIZE(key_flag_str
),
369 mdb_printf("\tpgr_key_it: %?-p\n", key
->pgr_key_it
);
370 mdb_printf("\tLocal Device ID: %?-p\n",
371 key
->pgr_key_lpt_id
);
372 print_scsi_devid_desc((uintptr_t)key
->pgr_key_lpt_id
,
373 key
->pgr_key_lpt_len
, " ");
374 mdb_printf("\tRemote Transport ID: %?-p\n",
375 key
->pgr_key_rpt_id
);
376 print_transport_id((uintptr_t)key
->pgr_key_rpt_id
,
377 key
->pgr_key_rpt_len
, " ");
379 mdb_printf("%p\n", addr
);
385 stmf_sbd_it_walk_init(mdb_walk_state_t
*wsp
)
387 if (wsp
->walk_addr
== (uintptr_t)NULL
) {
388 mdb_warn("<sbd_it_list addr>::walk stmf_sbd_pgr_key\n");
395 stmf_sbd_it_walk_step(mdb_walk_state_t
*wsp
)
397 uintptr_t addr
= wsp
->walk_addr
;
400 if (wsp
->walk_addr
== (uintptr_t)NULL
)
403 if (mdb_vread(&it
, sizeof (sbd_it_data_t
), addr
) == -1) {
404 mdb_warn("failed to read sbd_it_data_t at %p\n", addr
);
407 wsp
->walk_addr
= (uintptr_t)it
.sbd_it_next
;
408 return (wsp
->walk_callback(addr
, &it
, wsp
->walk_cbdata
));
412 stmf_sbd_it_cb(uintptr_t addr
, const sbd_it_data_t
*it
, stmf_sbd_cb_t
*cb_st
)
414 static const char *it_flag_str
[] = {
415 "SBD_IT_HAS_SCSI2_RESERVATION", /* 0x0001 */
416 "SBD_IT_PGR_REGISTERED", /* 0x0002 */
417 "SBD_IT_PGR_EXCLUSIVE_RSV_HOLDER", /* 0x0004 */
418 "SBD_IT_PGR_CHECK_FLAG" /* 0x0008 */
421 if (cb_st
->flag
& STMF_SBD_VERBOSE
) {
422 mdb_printf("SBD IT DATA - %p\n", addr
);
423 mdb_printf("\tSession ID: 0x%0-lx\n", it
->sbd_it_session_id
);
424 mdb_printf("\tIT Flags: ");
425 stmf_sbd_print_bit_flags(it_flag_str
, ARRAY_SIZE(it_flag_str
),
427 mdb_printf("\tPGR Key: %-p\n", it
->pgr_key_ptr
);
429 mdb_printf("%p\n", addr
);
435 * MDB DCMDS implementations.
439 stmf_sbd_lu(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
441 uint_t verbose
= FALSE
;
443 stmf_sbd_cb_t cb_st
= {0};
445 if (mdb_getopts(argc
, argv
, 'v', MDB_OPT_SETBITS
, TRUE
, &verbose
, NULL
)
449 cb_st
.flag
|= STMF_SBD_VERBOSE
;
451 if (flags
& DCMD_ADDRSPEC
) {
452 cb_st
.flag
|= STMF_SBD_VERBOSE
;
453 if (mdb_vread(&slu
, sizeof (sbd_lu_t
), addr
) == -1) {
454 mdb_warn("failed to read sbd_lu_t at %p\n", addr
);
457 if (stmf_sbd_lu_cb(addr
, &slu
, &cb_st
) == WALK_ERR
)
460 if (mdb_walk("stmf_sbd_lu", (mdb_walk_cb_t
)stmf_sbd_lu_cb
,
462 mdb_warn("failed to walk sbd_lu_list\n");
470 stmf_sbd_pgr_key(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
472 uint_t verbose
= FALSE
, keyonly
= FALSE
, pgrkeyaddr
= FALSE
;
476 stmf_sbd_cb_t cb_st
= {0};
478 if (!(flags
& DCMD_ADDRSPEC
))
481 if (mdb_getopts(argc
, argv
,
482 'a', MDB_OPT_SETBITS
, TRUE
, &pgrkeyaddr
,
483 'k', MDB_OPT_SETBITS
, TRUE
, &keyonly
,
484 'v', MDB_OPT_SETBITS
, TRUE
, &verbose
, NULL
) != argc
)
487 if (pgrkeyaddr
|| verbose
)
488 cb_st
.flag
|= STMF_SBD_VERBOSE
;
490 /* If address of pgr_key is given, just print that key and return */
492 if (mdb_vread(&key
, sizeof (sbd_pgr_key_t
), addr
) == -1) {
493 mdb_warn("failed to read sbd_pgr_key at %p\n", addr
);
496 if (stmf_sbd_pgr_key_cb(addr
, &key
, &cb_st
) == WALK_ERR
) {
501 if (mdb_vread(&slu
, sizeof (sbd_lu_t
), addr
) == -1) {
502 mdb_warn("failed to read sbd_lu at %p\n", addr
);
508 mdb_printf("\nLU:- %p\n", addr
);
510 /* Just a sanity check, not necessarily needed */
511 if (slu
.sl_pgr
== NULL
) {
513 mdb_warn("pgr structure not found for lun %p\n", addr
);
517 if (mdb_vread(&pgr
, sizeof (sbd_pgr_t
), (uintptr_t)slu
.sl_pgr
) == -1) {
518 mdb_warn("failed to read sbd_lu at %p\n", slu
.sl_pgr
);
523 stmf_sbd_print_pgr_info(&pgr
);
525 if (pgr
.pgr_keylist
== NULL
) {
527 mdb_printf("No registered pgr keys found\n");
531 mdb_printf("\nKeys\n");
534 if (mdb_pwalk("stmf_sbd_pgr_key", (mdb_walk_cb_t
)stmf_sbd_pgr_key_cb
,
535 &cb_st
, (uintptr_t)pgr
.pgr_keylist
) == -1) {
536 mdb_warn("failed to walk pgr_keylist\n");
544 stmf_remote_port(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
546 stmf_remote_port_t rpt
;
549 if (!(flags
& DCMD_ADDRSPEC
))
552 if (mdb_vread(&rpt
, sizeof (stmf_remote_port_t
), addr
) == -1) {
553 mdb_warn("failed to read stmf_remote_port_t at %p\n", addr
);
557 ret
= print_transport_id((uintptr_t)rpt
.rport_tptid
,
558 rpt
.rport_tptid_sz
, " ");
563 stmf_sbd_it(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
565 uint_t verbose
= FALSE
;
567 stmf_sbd_cb_t cb_st
= {0};
569 if (!(flags
& DCMD_ADDRSPEC
))
572 if (mdb_getopts(argc
, argv
,
573 'v', MDB_OPT_SETBITS
, TRUE
, &verbose
, NULL
) != argc
)
577 cb_st
.flag
|= STMF_SBD_VERBOSE
;
578 mdb_printf("\nLU:- %p\n", addr
);
581 /* If address of pgr_key is given, just print that key and return */
582 if (mdb_vread(&slu
, sizeof (sbd_lu_t
), addr
) == -1) {
583 mdb_warn("failed to read sbd_lu at %p\n", addr
);
587 /* Just a sanity check, not necessarily needed */
588 if (slu
.sl_it_list
== NULL
) {
590 mdb_printf("sbd_it_list is empty\n", addr
);
594 if (mdb_pwalk("stmf_sbd_it", (mdb_walk_cb_t
)stmf_sbd_it_cb
, &cb_st
,
595 (uintptr_t)slu
.sl_it_list
) == -1) {
596 mdb_warn("failed to walk sbd_lu_it_list\n");
603 * MDB dmcds and walkers definitions
606 static const mdb_dcmd_t dcmds
[] = {
607 { "stmf_sbd_lu", "?[-v]", "Print the list of sbd_lu_t",
609 { "stmf_sbd_it", ":[-v]", "Print the list of sbd_it_data for given lu",
611 { "stmf_sbd_pgr_key", ":[-kov]", "Print the list of pgr keys",
612 stmf_sbd_pgr_key
, stmf_sbd_pgr_key_dcmd_help
},
613 { "stmf_remote_port", ":", "decipher info in a stmf_remote_port",
614 stmf_remote_port
, NULL
},
618 static const mdb_walker_t walkers
[] = {
619 { "stmf_sbd_lu", "walk list of stmf_sbd_lu structures",
620 stmf_sbd_lu_walk_init
, stmf_sbd_lu_walk_step
, NULL
},
621 { "stmf_sbd_pgr_key", "walk the pgr keys of the given pgr key list",
622 stmf_sbd_pgr_key_walk_init
, stmf_sbd_pgr_key_walk_step
, NULL
},
623 { "stmf_sbd_it", "walk the sbd_it_data for the given it list",
624 stmf_sbd_it_walk_init
, stmf_sbd_it_walk_step
, NULL
},
628 static const mdb_modinfo_t modinfo
= {
629 MDB_API_VERSION
, dcmds
, walkers
632 const mdb_modinfo_t
*