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_FLAG_ARY_SZ 32 39 #define STMF_SBD_STR_MAX 2048 40 #define STMF_SBD_VERBOSE 0x00000001 41 42 /* structure to pass arguments to mdb_walker callback function */ 43 typedef struct stmf_sbd_cb_s { 44 uint32_t flag; 45 } stmf_sbd_cb_t; 46 47 char stmf_protocol_str [9][STMF_SBD_FLAG_ARY_SZ] = { 48 "FIBRE_CHANNEL", /* PROTOCOL_FIBRE_CHANNEL 0 */ 49 "PARALLEL_SCSI", /* PROTOCOL_PARALLEL_SCSI 1 */ 50 "SSA", /* PROTOCOL_SSA 2 */ 51 "IEEE_1394", /* PROTOCOL_IEEE_1394 3 */ 52 "SRP", /* PROTOCOL_SRP 4 */ 53 "iSCSI", /* PROTOCOL_iSCSI 5 */ 54 "SAS", /* PROTOCOL_SAS 6 */ 55 "ADT", /* PROTOCOL_ADT 7 */ 56 "ATAPI", /* PROTOCOL_ATAPI 8 */ 57 }; 58 59 /* 60 * Support functions. 61 */ 62 63 /* 64 * Variable 'bits' is a collection of flags for which a corresponding 65 * description string is available at flag_ary. 66 * So flag_ary should be an ary of strings with total_bits + 1 strings. 67 */ 68 static void 69 stmf_sbd_print_bit_flags(char flag_ary[][STMF_SBD_FLAG_ARY_SZ], 70 int total_bits, uint32_t bits) { 71 uint32_t curbit = 0x01; 72 int i, delim = 0; 73 74 for (i = 0; i < total_bits; i++) { 75 if (bits & curbit) { 76 mdb_printf("%s%s", (delim) ? " | " : "", flag_ary[i]); 77 delim = 1; 78 } 79 curbit <<= 1; 80 } 81 mdb_printf("\n"); 82 } 83 84 85 static void 86 stmf_sbd_print_pgr_info(sbd_pgr_t *pgr) 87 { 88 char pgr_flag_str [5][STMF_SBD_FLAG_ARY_SZ] = { 89 "SBD_PGR_APTPL", /* 0x01 */ 90 "SBD_PGR_RSVD_ONE", /* 0x02 */ 91 "SBD_PGR_RSVD_ALL_REGISTRANTS", /* 0x04 */ 92 "SBD_PGR_ALL_KEYS_HAS_IT" /* 0x08 */ 93 }; 94 char pgr_type_desc[9][48] = {"ILLEGAL", 95 "Write Exclusive", /* 0x1 */ 96 "ILLEGAL", 97 "Exclusive Access", /* 0x3 */ 98 "Write Exclusive, Registrants Only", /* 0x5 */ 99 "Exclusive Access, Registrants Only", /* 0x6 */ 100 "Write Exclusive, All Registrants", /* 0x7 */ 101 "Exclusive Access, All Registrants" /* 0x8 */ 102 }; 103 char *type_str = pgr_type_desc[0]; 104 105 106 mdb_printf("PGR flags: "); 107 stmf_sbd_print_bit_flags(pgr_flag_str, 4, pgr->pgr_flags); 108 if (pgr->pgr_rsvholder || pgr->pgr_flags & 109 SBD_PGR_RSVD_ALL_REGISTRANTS) { 110 mdb_printf("Reservation Details \n"); 111 mdb_printf("\tReservation holder: "); 112 if (pgr->pgr_rsvholder) 113 mdb_printf("%p\n", pgr->pgr_rsvholder); 114 else 115 mdb_printf("All Registrants\n"); 116 if (pgr->pgr_rsv_type < 8) 117 type_str = pgr_type_desc[pgr->pgr_rsv_type]; 118 mdb_printf("\t type : %d => %s\n", 119 pgr->pgr_rsv_type, type_str); 120 mdb_printf("\t scope : %d\n", pgr->pgr_rsv_scope); 121 } else { 122 mdb_printf("No reservations.\n"); 123 } 124 } 125 126 void 127 print_scsi_devid_desc(uintptr_t addr, uint16_t len, char *s) 128 { 129 scsi_devid_desc_t *id; 130 131 id = mdb_zalloc(len, UM_SLEEP); 132 if (mdb_vread(id, len, addr) == -1) { 133 mdb_warn("failed to read scsi_devid_desc at %p\n", addr); 134 mdb_free(id, len); 135 return; 136 } 137 138 mdb_printf("%sTotal length:\t%d\n", s, len); 139 mdb_printf("%sProtocol:\t%d => %-16s\n", s, id->protocol_id, 140 (id->protocol_id < 8) ? stmf_protocol_str[id->protocol_id] : ""); 141 mdb_printf("%sCode Set:\t%d\n", s, id->code_set); 142 mdb_printf("%sIdent Length:\t%d\n", s, id->ident_length); 143 144 if (len > id->ident_length + 3) { 145 id->ident[id->ident_length] = '\0'; 146 mdb_printf("%sIdent:\t%s\n", s, id->ident); 147 } else { 148 mdb_printf("%s(Can not recognize ident data)\n", s); 149 } 150 mdb_free(id, len); 151 mdb_printf("\n"); 152 } 153 154 void 155 stmf_sbd_pgr_key_dcmd_help(void) 156 { 157 mdb_printf( 158 "Prints info about pgr keys and reservations on the given lun.\n\n" 159 "Usage: <addr>::stmf_sbd_pgr_key [-akv]\n" 160 " where <addr> represent the address of\n" 161 " sbd_lu_t by default\n" 162 " or\n" 163 " sbd_pgr_key_t if '-a' option is specified.\n" 164 "Options:\n" 165 " -a if specified, <addr> represents address of sbd_pgr_key_t\n" 166 " -k if specified, only prints key information\n" 167 " -v verbose output\n"); 168 } 169 170 171 /* 172 * MDB WALKERS implementations 173 */ 174 175 static int 176 stmf_sbd_lu_walk_init(mdb_walk_state_t *wsp) 177 { 178 if (wsp->walk_addr == NULL) { 179 if (mdb_readvar(&wsp->walk_addr, "sbd_lu_list") == -1) { 180 mdb_warn("failed to read sbd_lu_list\n"); 181 return (WALK_ERR); 182 } 183 } 184 return (WALK_NEXT); 185 } 186 187 static int 188 stmf_sbd_lu_walk_step(mdb_walk_state_t *wsp) 189 { 190 uintptr_t addr = wsp->walk_addr; 191 sbd_lu_t slu; 192 193 if (wsp->walk_addr == NULL) 194 return (WALK_DONE); 195 196 if (mdb_vread(&slu, sizeof (sbd_lu_t), addr) == -1) { 197 mdb_warn("failed to read sbd_lu_t at %p\n", addr); 198 return (WALK_ERR); 199 } 200 wsp->walk_addr = (uintptr_t)slu.sl_next; 201 return (wsp->walk_callback(addr, &slu, wsp->walk_cbdata)); 202 } 203 204 char * 205 stmf_sbd_getstr(uintptr_t addr, char *str) { 206 if ((addr == 0) || (mdb_readstr(str, STMF_SBD_STR_MAX, addr) == -1)) 207 str = NULL; 208 return (str); 209 } 210 211 static int 212 stmf_sbd_lu_cb(uintptr_t addr, const sbd_lu_t *slu, stmf_sbd_cb_t *cb_st) 213 { 214 if (cb_st->flag & STMF_SBD_VERBOSE) { 215 char str[STMF_SBD_STR_MAX]; 216 217 mdb_printf("sbd_lu - %p\n", addr); 218 mdb_printf("\tsl_name: %-?p %s\n", slu->sl_name, 219 stmf_sbd_getstr((uintptr_t)slu->sl_name, str)); 220 mdb_printf("\tsl_alias: %-?p %s\n", slu->sl_alias, 221 stmf_sbd_getstr((uintptr_t)slu->sl_alias, str)); 222 mdb_printf("\tsl_meta_filename: %-?p %s\n", 223 slu->sl_meta_filename, 224 stmf_sbd_getstr((uintptr_t)slu->sl_meta_filename, str)); 225 mdb_printf("\tsl_data_filename: %-?p %s\n", 226 slu->sl_data_filename, 227 stmf_sbd_getstr((uintptr_t)slu->sl_data_filename, str)); 228 mdb_printf("\tsl_mgmt_url: %-?p %s\n", slu->sl_mgmt_url, 229 stmf_sbd_getstr((uintptr_t)slu->sl_mgmt_url, str)); 230 mdb_printf("\tsl_zfs_meta: %-?p\n", slu->sl_zfs_meta); 231 mdb_printf("\tsl_it_list: %-?p\n", slu->sl_it_list); 232 mdb_printf("\tsl_pgr: %-?p\n", slu->sl_pgr); 233 mdb_printf("\n"); 234 } else { 235 mdb_printf("%p\n", addr); 236 } 237 return (WALK_NEXT); 238 } 239 240 static int 241 stmf_sbd_pgr_key_walk_init(mdb_walk_state_t *wsp) 242 { 243 if (wsp->walk_addr == NULL) { 244 mdb_warn("<pgr_key_list addr>::walk stmf_sbd_pgr_key\n"); 245 return (WALK_ERR); 246 } 247 return (WALK_NEXT); 248 } 249 250 static int 251 stmf_sbd_pgr_key_walk_step(mdb_walk_state_t *wsp) 252 { 253 uintptr_t addr = wsp->walk_addr; 254 sbd_pgr_key_t key; 255 256 if (wsp->walk_addr == NULL) 257 return (WALK_DONE); 258 259 if (mdb_vread(&key, sizeof (sbd_pgr_key_t), addr) == -1) { 260 mdb_warn("failed to read sbd_pgr_key_t at %p\n", addr); 261 return (WALK_ERR); 262 } 263 wsp->walk_addr = (uintptr_t)key.pgr_key_next; 264 return (wsp->walk_callback(addr, &key, wsp->walk_cbdata)); 265 } 266 267 static int 268 stmf_sbd_pgr_key_cb(uintptr_t addr, const sbd_pgr_key_t *key, 269 stmf_sbd_cb_t *cb_st) 270 { 271 char key_flag_str [5][STMF_SBD_FLAG_ARY_SZ] = { 272 "SBD_PGR_KEY_ALL_TG_PT", /* 0x01 */ 273 "SBD_PGR_KEY_TPT_ID_FLAG", /* 0x02 */ 274 }; 275 276 if (cb_st->flag & STMF_SBD_VERBOSE) { 277 mdb_printf("sbd_pgr_key - %p\n", addr); 278 mdb_printf("\tRegistered key: 0x%llx\n", key->pgr_key); 279 mdb_printf("\tKey Flags: "); 280 stmf_sbd_print_bit_flags(key_flag_str, 2, key->pgr_key_flags); 281 mdb_printf("\tpgr_key_it: %?-p\n", key->pgr_key_it); 282 mdb_printf("\tLocal Device ID: %?-p\n", 283 key->pgr_key_lpt_id); 284 print_scsi_devid_desc((uintptr_t)key->pgr_key_lpt_id, 285 key->pgr_key_lpt_len, " "); 286 mdb_printf("\tRemote scsi devid desc: %?-p\n", 287 key->pgr_key_rpt_id); 288 print_scsi_devid_desc((uintptr_t)key->pgr_key_rpt_id, 289 key->pgr_key_rpt_len, " "); 290 } else { 291 mdb_printf("%p\n", addr); 292 } 293 return (WALK_NEXT); 294 } 295 296 static int 297 stmf_sbd_it_walk_init(mdb_walk_state_t *wsp) 298 { 299 if (wsp->walk_addr == NULL) { 300 mdb_warn("<sbd_it_list addr>::walk stmf_sbd_pgr_key\n"); 301 return (WALK_ERR); 302 } 303 return (WALK_NEXT); 304 } 305 306 static int 307 stmf_sbd_it_walk_step(mdb_walk_state_t *wsp) 308 { 309 uintptr_t addr = wsp->walk_addr; 310 sbd_it_data_t it; 311 312 if (wsp->walk_addr == NULL) 313 return (WALK_DONE); 314 315 if (mdb_vread(&it, sizeof (sbd_it_data_t), addr) == -1) { 316 mdb_warn("failed to read sbd_it_data_t at %p\n", addr); 317 return (WALK_ERR); 318 } 319 wsp->walk_addr = (uintptr_t)it.sbd_it_next; 320 return (wsp->walk_callback(addr, &it, wsp->walk_cbdata)); 321 } 322 323 static int 324 stmf_sbd_it_cb(uintptr_t addr, const sbd_it_data_t *it, stmf_sbd_cb_t *cb_st) 325 { 326 char it_flag_str [5][STMF_SBD_FLAG_ARY_SZ] = { 327 "SBD_IT_HAS_SCSI2_RESERVATION", /* 0x0001 */ 328 "SBD_IT_PGR_REGISTERED", /* 0x0002 */ 329 "SBD_IT_PGR_EXCLUSIVE_RSV_HOLDER", /* 0x0004 */ 330 "SBD_IT_PGR_CHECK_FLAG", /* 0x0008 */ 331 }; 332 333 if (cb_st->flag & STMF_SBD_VERBOSE) { 334 mdb_printf("SBD IT DATA - %p\n", addr); 335 mdb_printf("\tSession ID: 0x%0-lx\n", it->sbd_it_session_id); 336 mdb_printf("\tIT Flags: "); 337 stmf_sbd_print_bit_flags(it_flag_str, 4, it->sbd_it_flags); 338 mdb_printf("\tPGR Key: %-p\n", it->pgr_key_ptr); 339 mdb_printf("\n"); 340 } else { 341 mdb_printf("%p\n", addr); 342 } 343 return (WALK_NEXT); 344 } 345 346 /* 347 * MDB DCMDS implementations. 348 */ 349 350 int 351 stmf_sbd_lu(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 352 { 353 uint_t verbose = FALSE; 354 sbd_lu_t slu; 355 stmf_sbd_cb_t cb_st = {0}; 356 357 if (mdb_getopts(argc, argv, 'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL) 358 != argc) 359 return (DCMD_USAGE); 360 if (verbose) 361 cb_st.flag |= STMF_SBD_VERBOSE; 362 363 if (flags & DCMD_ADDRSPEC) { 364 cb_st.flag |= STMF_SBD_VERBOSE; 365 if (mdb_vread(&slu, sizeof (sbd_lu_t), addr) == -1) { 366 mdb_warn("failed to read sbd_lu_t at %p\n", addr); 367 return (DCMD_ERR); 368 } 369 if (stmf_sbd_lu_cb(addr, &slu, &cb_st) == WALK_ERR) 370 return (DCMD_ERR); 371 } else { 372 if (mdb_walk("stmf_sbd_lu", (mdb_walk_cb_t)stmf_sbd_lu_cb, 373 &cb_st) == -1) { 374 mdb_warn("failed to walk sbd_lu_list\n"); 375 return (DCMD_ERR); 376 } 377 } 378 return (DCMD_OK); 379 } 380 381 static int 382 stmf_sbd_pgr_key(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 383 { 384 uint_t verbose = FALSE, keyonly = FALSE, pgrkeyaddr = FALSE; 385 sbd_lu_t slu; 386 sbd_pgr_t pgr; 387 sbd_pgr_key_t key; 388 stmf_sbd_cb_t cb_st = {0}; 389 390 if (!(flags & DCMD_ADDRSPEC)) 391 return (DCMD_USAGE); 392 393 if (mdb_getopts(argc, argv, 394 'a', MDB_OPT_SETBITS, TRUE, &pgrkeyaddr, 395 'k', MDB_OPT_SETBITS, TRUE, &keyonly, 396 'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL) != argc) 397 return (DCMD_USAGE); 398 399 if (pgrkeyaddr || verbose) 400 cb_st.flag |= STMF_SBD_VERBOSE; 401 402 /* If address of pgr_key is given, just print that key and return */ 403 if (pgrkeyaddr) { 404 if (mdb_vread(&key, sizeof (sbd_pgr_key_t), addr) == -1) { 405 mdb_warn("failed to read sbd_pgr_key at %p\n", addr); 406 return (DCMD_ERR); 407 } 408 if (stmf_sbd_pgr_key_cb(addr, &key, &cb_st) == WALK_ERR) { 409 return (DCMD_ERR); 410 } 411 return (DCMD_OK); 412 } else { 413 if (mdb_vread(&slu, sizeof (sbd_lu_t), addr) == -1) { 414 mdb_warn("failed to read sbd_lu at %p\n", addr); 415 return (DCMD_ERR); 416 } 417 } 418 419 if (verbose) { 420 mdb_printf("\nLU:- %p\n", addr); 421 } 422 /* Just a sanity check, not necessarily needed */ 423 if (slu.sl_pgr == NULL) { 424 if (verbose) 425 mdb_warn("pgr structure not found for lun %p\n", addr); 426 return (DCMD_OK); 427 } 428 429 if (mdb_vread(&pgr, sizeof (sbd_pgr_t), (uintptr_t)slu.sl_pgr) == -1) { 430 mdb_warn("failed to read sbd_lu at %p\n", slu.sl_pgr); 431 return (DCMD_ERR); 432 } 433 434 if (!keyonly) 435 stmf_sbd_print_pgr_info(&pgr); 436 437 if (pgr.pgr_keylist == NULL) { 438 if (verbose) 439 mdb_printf("No registered pgr keys found\n"); 440 return (DCMD_OK); 441 } else { 442 if (!keyonly) 443 mdb_printf("\nKeys\n"); 444 } 445 446 if (mdb_pwalk("stmf_sbd_pgr_key", (mdb_walk_cb_t)stmf_sbd_pgr_key_cb, 447 &cb_st, (uintptr_t)pgr.pgr_keylist) == -1) { 448 mdb_warn("failed to walk pgr_keylist\n"); 449 return (DCMD_ERR); 450 } 451 return (DCMD_OK); 452 } 453 454 static int 455 stmf_sbd_it(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 456 { 457 uint_t verbose = FALSE; 458 sbd_lu_t slu; 459 stmf_sbd_cb_t cb_st = {0}; 460 461 if (!(flags & DCMD_ADDRSPEC)) 462 return (DCMD_USAGE); 463 464 if (mdb_getopts(argc, argv, 465 'v', MDB_OPT_SETBITS, TRUE, &verbose, NULL) != argc) 466 return (DCMD_USAGE); 467 468 if (verbose) { 469 cb_st.flag |= STMF_SBD_VERBOSE; 470 mdb_printf("LU:- %p\n", addr); 471 } 472 473 /* If address of pgr_key is given, just print that key and return */ 474 if (mdb_vread(&slu, sizeof (sbd_lu_t), addr) == -1) { 475 mdb_warn("failed to read sbd_lu at %p\n", addr); 476 return (DCMD_ERR); 477 } 478 479 /* Just a sanity check, not necessarily needed */ 480 if (slu.sl_it_list == NULL) { 481 if (verbose) 482 mdb_warn("sbd_it_list is empty%p\n", addr); 483 return (DCMD_OK); 484 } 485 486 if (mdb_pwalk("stmf_sbd_it", (mdb_walk_cb_t)stmf_sbd_it_cb, &cb_st, 487 (uintptr_t)slu.sl_it_list) == -1) { 488 mdb_warn("failed to walk sbd_lu_it_list\n"); 489 return (DCMD_ERR); 490 } 491 return (DCMD_OK); 492 } 493 494 /* 495 * MDB dmcds and walkers definitions 496 */ 497 498 static const mdb_dcmd_t dcmds[] = { 499 { "stmf_sbd_lu", "?[-v]", "Print the list of sbd_lu_t", 500 stmf_sbd_lu, NULL }, 501 { "stmf_sbd_it", ":[-v]", "Print the list of sbd_it_data for given lu", 502 stmf_sbd_it, NULL }, 503 { "stmf_sbd_pgr_key", ":[-kov]", "Print the list of pgr keys", 504 stmf_sbd_pgr_key, stmf_sbd_pgr_key_dcmd_help }, 505 { NULL } 506 }; 507 508 static const mdb_walker_t walkers[] = { 509 { "stmf_sbd_lu", "walk list of stmf_sbd_lu structures", 510 stmf_sbd_lu_walk_init, stmf_sbd_lu_walk_step, NULL }, 511 { "stmf_sbd_pgr_key", "walk the pgr keys of the given pgr key list", 512 stmf_sbd_pgr_key_walk_init, stmf_sbd_pgr_key_walk_step, NULL }, 513 { "stmf_sbd_it", "walk the sbd_it_data for the given it list", 514 stmf_sbd_it_walk_init, stmf_sbd_it_walk_step, NULL }, 515 { NULL } 516 }; 517 518 static const mdb_modinfo_t modinfo = { 519 MDB_API_VERSION, dcmds, walkers 520 }; 521 522 const mdb_modinfo_t * 523 _mdb_init(void) 524 { 525 return (&modinfo); 526 } 527