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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/dditypes.h> 27 #include <sys/mdb_modapi.h> 28 #include <sys/modctl.h> 29 #include <sys/sunddi.h> 30 #include <sys/lpif.h> 31 #include <sys/stmf.h> 32 #include <sys/portif.h> 33 #include <stmf_impl.h> 34 #include <lun_map.h> 35 #include <stmf_state.h> 36 37 #include <sys/fct.h> 38 #include <fct_impl.h> 39 40 #include "cmd_options.h" 41 42 static int 43 stmf_ilport_walk_i(mdb_walk_state_t *wsp) 44 { 45 if (wsp->walk_addr == NULL) { 46 struct stmf_state state; 47 48 if (mdb_readsym(&state, sizeof (struct stmf_state), 49 "stmf_state") == -1) { 50 mdb_warn("failed to read stmf_state"); 51 return (WALK_ERR); 52 } 53 wsp->walk_addr = (uintptr_t)state.stmf_ilportlist; 54 } 55 56 wsp->walk_data = mdb_alloc(sizeof (stmf_i_local_port_t), UM_SLEEP); 57 return (WALK_NEXT); 58 } 59 60 static int 61 stmf_ilport_walk_s(mdb_walk_state_t *wsp) 62 { 63 int status = WALK_NEXT; 64 65 if (wsp->walk_addr == NULL) 66 return (WALK_DONE); 67 68 if (mdb_vread(wsp->walk_data, sizeof (struct stmf_i_local_port), 69 wsp->walk_addr) == -1) { 70 mdb_warn("failed to read stmf_i_local_port_t at %p", 71 wsp->walk_addr); 72 return (WALK_ERR); 73 } 74 75 if (wsp->walk_callback) 76 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 77 wsp->walk_cbdata); 78 79 wsp->walk_addr = (uintptr_t) 80 (((struct stmf_i_local_port *)wsp->walk_data)->ilport_next); 81 82 return (status); 83 } 84 85 static void 86 stmf_ilport_walk_f(mdb_walk_state_t *wsp) 87 { 88 mdb_free(wsp->walk_data, sizeof (struct stmf_i_local_port)); 89 } 90 91 static int 92 dump_ilport(struct stmf_i_local_port *ilportp, int verbose) 93 { 94 if (ilportp == NULL) 95 return (DCMD_OK); 96 97 mdb_printf("%p\n", ilportp); 98 99 if (verbose) { 100 /* here assume the alias is maximumly 1024 bytes */ 101 char alias[255]; 102 struct stmf_local_port lport; 103 struct stmf_i_local_port ilport; 104 105 if (mdb_vread(&ilport, sizeof (ilport), (uintptr_t)ilportp) 106 == -1) { 107 mdb_warn("failed to read stmf_i_local_port at %p", 108 ilportp); 109 return (DCMD_ERR); 110 } 111 112 memset(alias, 0, sizeof (alias)); 113 if (mdb_vread(&lport, sizeof (lport), 114 (uintptr_t)ilport.ilport_lport) == -1) { 115 mdb_warn("failed to read stmf_local_port at %p", 116 ilport.ilport_lport); 117 return (DCMD_ERR); 118 } 119 if (lport.lport_alias && mdb_vread(alias, sizeof (alias), 120 (uintptr_t)lport.lport_alias) == -1) { 121 mdb_warn("failed to read memory at %p", 122 lport.lport_alias); 123 return (DCMD_ERR); 124 } 125 126 mdb_printf(" lport: %p\n", ilport.ilport_lport); 127 if (lport.lport_alias) 128 mdb_printf(" port alias: %s\n", alias); 129 mdb_printf(" port provider: %p\n", lport.lport_pp); 130 } 131 132 return (DCMD_OK); 133 } 134 135 /*ARGSUSED*/ 136 static int 137 stmf_ilports(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 138 { 139 int i; 140 int verbose = 0; 141 mdb_walk_state_t ws = {NULL, }; 142 143 for (i = 0; i < argc; i++) { 144 char *ptr = (char *)argv[i].a_un.a_str; 145 146 if (ptr[0] == '-') 147 ptr++; 148 while (*ptr) { 149 if (*ptr == 'v') 150 verbose = 1; 151 ptr++; 152 } 153 } 154 155 if (stmf_ilport_walk_i(&ws) == WALK_ERR) 156 return (DCMD_ERR); 157 158 dump_ilport((stmf_i_local_port_t *)ws.walk_addr, verbose); 159 160 while (stmf_ilport_walk_s(&ws) == WALK_NEXT) 161 dump_ilport((stmf_i_local_port_t *)ws.walk_addr, verbose); 162 163 stmf_ilport_walk_f(&ws); 164 return (DCMD_OK); 165 } 166 167 struct stmf_i_local_port * 168 next_stmf_port(mdb_walk_state_t *wsp) 169 { 170 if (wsp->walk_addr == NULL) { 171 if (stmf_ilport_walk_i(wsp) == WALK_ERR) { 172 stmf_ilport_walk_f(wsp); 173 return (NULL); 174 } 175 if (wsp->walk_addr == NULL) 176 stmf_ilport_walk_f(wsp); 177 return ((struct stmf_i_local_port *)wsp->walk_addr); 178 } 179 180 if (stmf_ilport_walk_s(wsp) == WALK_ERR) { 181 stmf_ilport_walk_f(wsp); 182 return (NULL); 183 } 184 if (wsp->walk_addr == NULL) 185 stmf_ilport_walk_f(wsp); 186 return ((struct stmf_i_local_port *)wsp->walk_addr); 187 } 188 189 190 /*ARGSUSED*/ 191 static int 192 stmf_iss(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 193 { 194 struct stmf_i_local_port iport; 195 struct stmf_i_scsi_session *issp; 196 struct stmf_i_scsi_session iss; 197 int i; 198 int verbose = 0; 199 200 for (i = 0; i < argc; i++) { 201 char *ptr = (char *)argv[i].a_un.a_str; 202 203 if (ptr[0] == '-') 204 ptr++; 205 while (*ptr) { 206 if (*ptr == 'v') 207 verbose = 1; 208 ptr++; 209 } 210 } 211 212 if (addr == NULL) { 213 mdb_warn("address of stmf_i_local_port should be specified\n"); 214 return (DCMD_ERR); 215 } 216 217 /* 218 * Input should be stmf_i_local_port_t. 219 */ 220 if (mdb_vread(&iport, sizeof (struct stmf_i_local_port), addr) 221 != sizeof (struct stmf_i_local_port)) { 222 mdb_warn("Unable to read in stmf_i_local_port at %p\n", addr); 223 return (DCMD_ERR); 224 } 225 226 issp = iport.ilport_ss_list; 227 228 while (issp) { 229 if (mdb_vread(&iss, sizeof (iss), (uintptr_t)issp) == -1) { 230 mdb_warn("failed to read stmf_i_scsi_session_t at %p", 231 issp); 232 return (DCMD_ERR); 233 } 234 235 mdb_printf("%p\n", issp); 236 if (verbose) { 237 mdb_printf(" scsi session: %p\n", iss.iss_ss); 238 } 239 240 issp = iss.iss_next; 241 } 242 243 return (DCMD_OK); 244 } 245 246 /*ARGSUSED*/ 247 static int 248 stmf_ilus(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 249 { 250 struct stmf_state state; 251 struct stmf_i_lu ilu; 252 struct stmf_i_lu *ilup; 253 int i; 254 int verbose = 0; 255 256 for (i = 0; i < argc; i++) { 257 char *ptr = (char *)argv[i].a_un.a_str; 258 259 if (ptr[0] == '-') 260 ptr++; 261 while (*ptr) { 262 if (*ptr == 'v') 263 verbose = 1; 264 ptr++; 265 } 266 } 267 268 if (mdb_readsym(&state, sizeof (struct stmf_state), "stmf_state") 269 == -1) { 270 mdb_warn("failed to read stmf_state"); 271 return (DCMD_ERR); 272 } 273 274 ilup = state.stmf_ilulist; 275 while (ilup) { 276 if (mdb_vread(&ilu, sizeof (struct stmf_i_lu), (uintptr_t)ilup) 277 == -1) { 278 mdb_warn("failed to read stmf_i_lu_t at %p", ilup); 279 return (DCMD_ERR); 280 } 281 282 mdb_printf("%p\n", ilup); 283 if (verbose) { 284 mdb_printf(" lu: %p\n", ilu.ilu_lu); 285 286 /* XXX lu_alias? what is its size? */ 287 } 288 289 ilup = ilu.ilu_next; 290 } 291 292 return (DCMD_OK); 293 } 294 295 /*ARGSUSED*/ 296 static int 297 stmf_i_lu_providers(uintptr_t addr, uint_t flags, int argc, 298 const mdb_arg_t *argv) 299 { 300 struct stmf_state state; 301 struct stmf_i_lu_provider ilp; 302 struct stmf_i_lu_provider *ilpp; 303 int i; 304 int verbose = 0; 305 306 for (i = 0; i < argc; i++) { 307 char *ptr = (char *)argv[i].a_un.a_str; 308 309 if (ptr[0] == '-') 310 ptr++; 311 while (*ptr) { 312 if (*ptr == 'v') 313 verbose = 1; 314 ptr++; 315 } 316 } 317 318 if (mdb_readsym(&state, sizeof (struct stmf_state), "stmf_state") 319 == -1) { 320 mdb_warn("failed to read stmf_state"); 321 return (DCMD_ERR); 322 } 323 324 ilpp = state.stmf_ilplist; 325 while (ilpp) { 326 if (mdb_vread(&ilp, sizeof (stmf_i_lu_provider_t), 327 (uintptr_t)ilpp) == -1) { 328 mdb_warn("failed to read stmf_i_lu_provider_t at %p", 329 ilpp); 330 return (DCMD_ERR); 331 } 332 333 mdb_printf("%p\n", ilpp); 334 if (verbose) { 335 mdb_printf(" lu provider: %p\n", ilp.ilp_lp); 336 } 337 338 ilpp = ilp.ilp_next; 339 } 340 341 return (DCMD_OK); 342 } 343 344 /*ARGSUSED*/ 345 static int 346 stmf_i_port_providers(uintptr_t addr, uint_t flags, int argc, 347 const mdb_arg_t *argv) 348 { 349 struct stmf_state state; 350 struct stmf_i_port_provider ipp; 351 struct stmf_i_port_provider *ippp; 352 int i; 353 int verbose = 0; 354 355 for (i = 0; i < argc; i++) { 356 char *ptr = (char *)argv[i].a_un.a_str; 357 358 if (ptr[0] == '-') 359 ptr++; 360 while (*ptr) { 361 if (*ptr == 'v') 362 verbose = 1; 363 ptr++; 364 } 365 } 366 367 if (mdb_readsym(&state, sizeof (struct stmf_state), "stmf_state") 368 == -1) { 369 mdb_warn("failed to read stmf_state"); 370 return (DCMD_ERR); 371 } 372 373 ippp = state.stmf_ipplist; 374 while (ippp) { 375 if (mdb_vread(&ipp, sizeof (stmf_i_port_provider_t), 376 (uintptr_t)ippp) == -1) { 377 mdb_warn("failed to read stmf_i_port_provider_t at %p", 378 ippp); 379 return (DCMD_ERR); 380 } 381 382 mdb_printf("%p\n", ippp); 383 if (verbose) { 384 mdb_printf(" port provider: %p\n", ipp.ipp_pp); 385 } 386 387 ippp = ipp.ipp_next; 388 } 389 390 return (DCMD_OK); 391 } 392 393 int string2wwn(const char *s, uint8_t wwn[8]); 394 395 static uint16_t port_max_logins; 396 static int rp_index; 397 398 /* 399 * Cervert stmf_i_local_port to fct_i_local_port 400 */ 401 /*ARGSUSED*/ 402 static struct fct_i_local_port * 403 __ilport2iport(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 404 { 405 struct stmf_i_local_port iport; 406 struct stmf_local_port lport; 407 struct fct_local_port fport; 408 409 if (!(flags & DCMD_ADDRSPEC)) { 410 mdb_warn("stmf_i_local_port address should be specified"); 411 return (NULL); 412 } 413 414 /* 415 * Input should be stmf_i_local_port_t. 416 */ 417 if (mdb_vread(&iport, sizeof (struct stmf_i_local_port), addr) 418 != sizeof (struct stmf_i_local_port)) { 419 mdb_warn("Unable to read in stmf_i_local_port\n"); 420 return (NULL); 421 } 422 423 if (mdb_vread(&lport, sizeof (stmf_local_port_t), 424 (uintptr_t)iport.ilport_lport) != sizeof (stmf_local_port_t)) { 425 mdb_warn("Unable to read in stmf_local_port\n"); 426 return (NULL); 427 } 428 429 if (mdb_vread(&fport, sizeof (fct_local_port_t), 430 (uintptr_t)lport.lport_port_private) 431 != sizeof (fct_local_port_t)) { 432 mdb_warn("Unable to read in fct_local_port\n"); 433 return (NULL); 434 } 435 436 return (fport.port_fct_private); 437 } 438 439 static int 440 ilport2iport(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 441 { 442 struct fct_i_local_port *iportp; 443 int i; 444 int verbose = 0; 445 446 for (i = 0; i < argc; i++) { 447 char *ptr = (char *)argv[i].a_un.a_str; 448 449 if (ptr[0] == '-') 450 ptr++; 451 while (*ptr) { 452 if (*ptr == 'v') 453 verbose = 1; 454 ptr++; 455 } 456 } 457 458 459 iportp = __ilport2iport(addr, flags, argc, argv); 460 if (iportp) { 461 mdb_printf("%p\n", iportp); 462 if (verbose) { 463 struct fct_i_local_port iport; 464 /* is the alias always 16 bytes in size ? */ 465 char alias[16]; 466 467 memset(alias, 0, sizeof (alias)); 468 if (mdb_vread(&iport, sizeof (fct_i_local_port_t), 469 (uintptr_t)iportp) 470 != sizeof (fct_i_local_port_t)) { 471 mdb_warn("Unable to read in fct_i_local_port" 472 "at %p\n", iportp); 473 return (DCMD_ERR); 474 } 475 if (iport.iport_alias && 476 mdb_vread(alias, sizeof (alias), 477 (uintptr_t)iport.iport_alias) 478 != sizeof (alias)) { 479 mdb_warn("Unable to read in memory at %p", 480 iport.iport_alias); 481 return (DCMD_ERR); 482 } 483 mdb_printf(" port: %p\n", iport.iport_port); 484 if (iport.iport_alias) 485 mdb_printf(" alias: %s\n", alias); 486 } 487 } 488 return (DCMD_OK); 489 } 490 491 /* 492 * by wwn, we can only find one local port 493 */ 494 static struct stmf_i_local_port * 495 find_lport_by_wwn(uint8_t wwn[8]) 496 { 497 struct stmf_i_local_port *siport; 498 struct fct_i_local_port *fiport; 499 struct fct_i_local_port iport; 500 struct fct_local_port fport; 501 mdb_walk_state_t ws = {NULL, }; 502 503 while ((siport = next_stmf_port(&ws)) != NULL) { 504 fiport = __ilport2iport((uintptr_t)siport, DCMD_ADDRSPEC, 505 0, NULL); 506 if (fiport == NULL) 507 return (NULL); 508 509 if (mdb_vread(&iport, sizeof (fct_i_local_port_t), 510 (uintptr_t)fiport) 511 != sizeof (fct_i_local_port_t)) { 512 mdb_warn("Unable to read in fct_i_local_port\n"); 513 return (NULL); 514 } 515 if (mdb_vread(&fport, sizeof (fct_local_port_t), 516 (uintptr_t)iport.iport_port) 517 != sizeof (fct_local_port_t)) { 518 mdb_warn("Unable to read in fct_local_port\n"); 519 return (NULL); 520 } 521 522 #if 0 523 mdb_printf("pwwn=%02x%02x%02x%02x%02x%02x%02x%02x\n", 524 fport.port_pwwn[0], fport.port_pwwn[1], 525 fport.port_pwwn[2], fport.port_pwwn[3], 526 fport.port_pwwn[4], fport.port_pwwn[5], 527 fport.port_pwwn[6], fport.port_pwwn[7]); 528 #endif 529 if (memcmp(fport.port_pwwn, wwn, 8) == 0) { 530 return (siport); 531 } 532 } 533 534 return (NULL); 535 } 536 537 /*ARGSUSED*/ 538 static int 539 stmf_find_ilport(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 540 { 541 struct find_options *options; 542 struct stmf_i_local_port *siport; 543 544 options = parse_options(argc, argv); 545 /* need to free options manually ? */ 546 if (options == NULL || ! options->lpname_defined) { 547 mdb_printf("lpname=<wwn.12345678 or 12345678> " 548 "should be specified\n"); 549 return (DCMD_OK); 550 } 551 552 if ((siport = find_lport_by_wwn(options->lpname)) != NULL) 553 mdb_printf("%p\n", siport); 554 555 return (DCMD_OK); 556 } 557 558 static int 559 fct_irp_walk_i(mdb_walk_state_t *wsp) 560 { 561 struct fct_local_port port; 562 struct fct_i_local_port iport; 563 564 if (wsp->walk_addr == NULL) { 565 mdb_warn("Can not perform global walk"); 566 return (WALK_ERR); 567 } 568 569 /* 570 * Input should be fct_i_local_port_t. 571 */ 572 if (mdb_vread(&iport, sizeof (struct fct_i_local_port), wsp->walk_addr) 573 != sizeof (struct fct_i_local_port)) { 574 mdb_warn("Unable to read in fct_i_local_port\n"); 575 return (WALK_ERR); 576 } 577 578 if (mdb_vread(&port, sizeof (struct fct_local_port), 579 (uintptr_t)iport.iport_port) 580 != sizeof (struct fct_local_port)) { 581 mdb_warn("Unable to read in fct_local_port\n"); 582 return (WALK_ERR); 583 } 584 585 port_max_logins = port.port_max_logins; 586 rp_index = 0; 587 wsp->walk_addr = (uintptr_t)iport.iport_rp_slots; 588 589 return (WALK_NEXT); 590 } 591 592 static int 593 fct_irp_walk_s(mdb_walk_state_t *wsp) 594 { 595 int status = WALK_NEXT; 596 fct_i_remote_port_t *rp; 597 598 if (wsp->walk_addr == NULL) 599 return (WALK_DONE); 600 601 if (rp_index++ >= port_max_logins) 602 return (WALK_DONE); 603 604 if (mdb_vread(&rp, sizeof (fct_i_remote_port_t *), 605 wsp->walk_addr) == -1) { 606 mdb_warn("failed to read address of fct_i_remote_port_t at %p", 607 wsp->walk_addr); 608 return (WALK_DONE); 609 } 610 611 if (rp != NULL && wsp->walk_callback != NULL) 612 status = wsp->walk_callback((uintptr_t)rp, rp, 613 wsp->walk_cbdata); 614 615 wsp->walk_addr = (uintptr_t) 616 &(((fct_i_remote_port_t **)wsp->walk_addr)[1]); 617 618 return (status); 619 } 620 621 static void 622 fct_irp_walk_f(mdb_walk_state_t *wsp) 623 { 624 wsp->walk_addr = NULL; 625 } 626 627 /* 628 * to set remote_port 629 */ 630 /*ARGSUSED*/ 631 static int 632 walk_fct_irp_cb(uintptr_t p, const void * arg, void *cbdata) 633 { 634 *((uintptr_t *)cbdata) = p; 635 return (WALK_NEXT); 636 } 637 638 static int 639 fct_irps(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 640 { 641 static uint64_t cbdata = 0; 642 mdb_walk_state_t ws = {walk_fct_irp_cb, &cbdata, addr}; 643 fct_i_remote_port_t *irpp; 644 int i; 645 int verbose = 0; 646 647 for (i = 0; i < argc; i++) { 648 char *ptr = (char *)argv[i].a_un.a_str; 649 650 if (ptr[0] == '-') 651 ptr++; 652 while (*ptr) { 653 if (*ptr == 'v') 654 verbose = 1; 655 ptr++; 656 } 657 } 658 659 if (!(flags & DCMD_ADDRSPEC)) { 660 mdb_warn("fct_i_local_port_t address should be specified"); 661 return (DCMD_ERR); 662 } 663 664 fct_irp_walk_i(&ws); 665 while (fct_irp_walk_s(&ws) == WALK_NEXT) { 666 irpp = *((fct_i_remote_port_t **)ws.walk_cbdata); 667 668 if (irpp) { 669 *((fct_i_remote_port_t **)ws.walk_cbdata) = NULL; 670 671 mdb_printf("%p\n", irpp); 672 if (verbose) { 673 fct_i_remote_port_t irp; 674 675 if (mdb_vread(&irp, sizeof (irp), 676 (uintptr_t)irpp) != sizeof (irp)) { 677 mdb_warn("Unable to read in " 678 "fct_i_remote_port at %p\n", irpp); 679 return (DCMD_ERR); 680 } 681 mdb_printf(" remote port: %p\n", irp.irp_rp); 682 mdb_printf(" port id: %x\n", irp.irp_portid); 683 } 684 } 685 } 686 fct_irp_walk_f(&ws); 687 688 return (DCMD_OK); 689 } 690 691 static uintptr_t cur_iport_for_irp_loop = NULL; 692 693 static fct_i_remote_port_t * 694 next_rport(struct fct_i_local_port *iport) 695 { 696 static uint64_t cbdata = 0; 697 static mdb_walk_state_t ws = {walk_fct_irp_cb, &cbdata}; 698 int ret; 699 fct_i_remote_port_t *irp; 700 701 if (ws.walk_addr == NULL || cur_iport_for_irp_loop != 702 (uintptr_t)iport) { 703 *((fct_i_remote_port_t **)ws.walk_cbdata) = NULL; 704 cur_iport_for_irp_loop = (uintptr_t)iport; 705 ws.walk_addr = (uintptr_t)iport; 706 if (fct_irp_walk_i(&ws) == WALK_ERR) { 707 fct_irp_walk_f(&ws); 708 return (NULL); 709 } 710 if (ws.walk_addr == NULL) { 711 fct_irp_walk_f(&ws); 712 return (NULL); 713 } 714 } 715 716 while ((ret = fct_irp_walk_s(&ws)) == WALK_NEXT) { 717 if (*((fct_i_remote_port_t **)ws.walk_cbdata) != 0) { 718 irp = *((fct_i_remote_port_t **)ws.walk_cbdata); 719 *((fct_i_remote_port_t **)ws.walk_cbdata) = NULL; 720 return (irp); 721 } 722 } 723 fct_irp_walk_f(&ws); 724 725 /* 726 * If it is WALK_DONE, there may be one remote port there 727 */ 728 if (ret == WALK_DONE) { 729 irp = *((fct_i_remote_port_t **)ws.walk_cbdata); 730 *((fct_i_remote_port_t **)ws.walk_cbdata) = NULL; 731 return (irp); 732 } 733 return (NULL); 734 } 735 736 static struct stmf_i_local_port * 737 irp_to_ilport(struct fct_i_remote_port *irpp) 738 { 739 struct fct_i_remote_port irp; 740 struct fct_remote_port rp; 741 struct fct_local_port port; 742 struct stmf_local_port lport; 743 744 if (mdb_vread(&irp, sizeof (struct fct_i_remote_port), 745 (uintptr_t)irpp) 746 != sizeof (struct fct_i_remote_port)) { 747 mdb_warn("Unable to read in fct_i_remote_port\n"); 748 return (NULL); 749 } 750 if (mdb_vread(&rp, sizeof (struct fct_remote_port), 751 (uintptr_t)irp.irp_rp) 752 != sizeof (struct fct_remote_port)) { 753 mdb_warn("Unable to read in fct_remote_port\n"); 754 return (NULL); 755 } 756 757 if (mdb_vread(&port, sizeof (struct fct_local_port), 758 (uintptr_t)rp.rp_port) 759 != sizeof (struct fct_local_port)) { 760 mdb_warn("Unable to read in fct_local_port\n"); 761 return (NULL); 762 } 763 if (mdb_vread(&lport, sizeof (struct stmf_local_port), 764 (uintptr_t)port.port_lport) 765 != sizeof (struct stmf_local_port)) { 766 mdb_warn("Unable to read in stmf_local_port\n"); 767 return (NULL); 768 } 769 return (lport.lport_stmf_private); 770 } 771 772 /* 773 * by wwn, we may find more than one remote port, so we need to know its 774 * corresponding local port 775 */ 776 static struct fct_i_remote_port * 777 find_irp_by_wwn(struct stmf_i_local_port *siport, uint8_t wwn[8]) 778 { 779 struct fct_i_local_port *fiport; 780 fct_i_remote_port_t *irpp; 781 struct fct_i_remote_port irp; 782 struct fct_remote_port rp; 783 fct_i_remote_port_t *ret = NULL; 784 785 fiport = __ilport2iport((uintptr_t)siport, DCMD_ADDRSPEC, 0, NULL); 786 if (fiport == NULL) 787 return (NULL); 788 789 while ((irpp = next_rport(fiport)) != NULL) { 790 if (mdb_vread(&irp, sizeof (struct fct_i_remote_port), 791 (uintptr_t)irpp) 792 != sizeof (struct fct_i_remote_port)) { 793 mdb_warn("Unable to read in fct_i_remote_port\n"); 794 break; 795 } 796 if (mdb_vread(&rp, sizeof (struct fct_remote_port), 797 (uintptr_t)irp.irp_rp) 798 != sizeof (struct fct_remote_port)) { 799 mdb_warn("Unable to read in fct_remote_port\n"); 800 break; 801 } 802 803 if (memcmp(rp.rp_pwwn, wwn, 8) == 0) { 804 ret = irpp; 805 break; 806 } 807 } 808 cur_iport_for_irp_loop = NULL; 809 return (ret); 810 } 811 812 /*ARGSUSED*/ 813 static int 814 stmf_find_fct_irp(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 815 { 816 struct stmf_i_local_port *siport; 817 struct find_options *options; 818 fct_i_remote_port_t *irpp; 819 mdb_walk_state_t ws = {NULL, }; 820 821 options = parse_options(argc, argv); 822 /* need to free options manually ? */ 823 if (options == NULL || (options->rpname_defined == 0 && 824 options->rp_defined == 0)) { 825 mdb_printf("rpname=<wwn.12345678> or rp=<3000586778734>" 826 " should be specified\n"); 827 return (DCMD_OK); 828 } 829 if (options->rpname_defined && options->rp_defined) { 830 mdb_printf("rpname=<wwn.12345678> or rp=<3000586778734>" 831 " should be specified, but not both\n"); 832 return (DCMD_OK); 833 } 834 835 if (options->rp_defined) { 836 siport = irp_to_ilport(options->rp); 837 if (siport != NULL) 838 mdb_printf("stmf_i_local_port=%p," 839 " fct_i_remote_port=%p\n", 840 siport, options->rp); 841 return (DCMD_OK); 842 } 843 844 /* if options->rpname_defined */ 845 while ((siport = next_stmf_port(&ws)) != NULL) { 846 if ((irpp = find_irp_by_wwn(siport, options->rpname)) != NULL) 847 mdb_printf("stmf_i_local_port=%p, " 848 "fct_i_remote_port=%p\n", 849 siport, irpp); 850 } 851 852 return (DCMD_OK); 853 } 854 855 typedef void (*cmd_filter_t) (struct fct_i_cmd *, 856 struct find_options *, void *); 857 858 /*ARGSUSED*/ 859 static void 860 print_tasks(struct fct_i_cmd *icmdp, struct find_options *options, void *arg) 861 { 862 struct fct_i_cmd icmd; 863 struct fct_cmd cmd; 864 865 if (mdb_vread(&icmd, sizeof (struct fct_i_cmd), 866 (uintptr_t)icmdp) != sizeof (struct fct_i_cmd)) { 867 mdb_warn("Unable to read in fct_i_cmd\n"); 868 return; 869 } 870 if (mdb_vread(&cmd, sizeof (struct fct_cmd), 871 (uintptr_t)icmd.icmd_cmd) != sizeof (struct fct_cmd)) { 872 mdb_warn("Unable to read in fct_cmd\n"); 873 return; 874 } 875 876 if (cmd.cmd_type == FCT_CMD_FCP_XCHG) { 877 struct scsi_task task; 878 int colon_printed = 0; 879 880 if (mdb_vread(&task, sizeof (struct scsi_task), 881 (uintptr_t)cmd.cmd_specific) 882 != sizeof (struct scsi_task)) { 883 mdb_warn("Unable to read in scsi_task\n"); 884 return; 885 } 886 887 mdb_printf("%p", cmd.cmd_specific); 888 if (options->show_task_flags) { 889 mdb_printf(":"); 890 colon_printed = 1; 891 mdb_printf(" task_flags=%x", task.task_flags); 892 } 893 894 if (options->show_lport) { 895 if (colon_printed == 0) { 896 mdb_printf(":"); 897 colon_printed = 1; 898 } 899 mdb_printf(" lport=%p", task.task_lport); 900 } 901 mdb_printf("\n"); 902 } 903 } 904 905 static void 906 print_tasks_on_rp(struct fct_i_cmd *icmdp, struct find_options *options, 907 void *arg) 908 { 909 struct fct_i_cmd icmd; 910 struct fct_cmd cmd; 911 fct_i_remote_port_t irp; 912 913 if (mdb_vread(&icmd, sizeof (struct fct_i_cmd), 914 (uintptr_t)icmdp) != sizeof (struct fct_i_cmd)) { 915 mdb_warn("Unable to read in fct_i_cmd\n"); 916 return; 917 } 918 if (mdb_vread(&cmd, sizeof (struct fct_cmd), 919 (uintptr_t)icmd.icmd_cmd) != sizeof (struct fct_cmd)) { 920 mdb_warn("Unable to read in fct_cmd\n"); 921 return; 922 } 923 924 /* arg is a pointer to fct_i_remote_port */ 925 if (mdb_vread(&irp, sizeof (struct fct_i_remote_port), 926 (uintptr_t)arg) != sizeof (struct fct_i_remote_port)) { 927 mdb_warn("Unable to read in fct_i_remote_port\n"); 928 return; 929 } 930 931 if (cmd.cmd_type == FCT_CMD_FCP_XCHG && cmd.cmd_rp == irp.irp_rp) { 932 struct scsi_task task; 933 int colon_printed = 0; 934 935 if (mdb_vread(&task, sizeof (struct scsi_task), 936 (uintptr_t)cmd.cmd_specific) 937 != sizeof (struct scsi_task)) { 938 mdb_warn("Unable to read in scsi_task\n"); 939 return; 940 } 941 942 mdb_printf("%p", cmd.cmd_specific); 943 if (options->show_task_flags) { 944 mdb_printf(":"); 945 colon_printed = 1; 946 mdb_printf(" task_flags=%x", task.task_flags); 947 } 948 949 if (options->show_lport) { 950 if (colon_printed == 0) { 951 mdb_printf(":"); 952 colon_printed = 1; 953 } 954 mdb_printf(" lport=%p", task.task_lport); 955 } 956 mdb_printf("\n"); 957 } 958 } 959 960 /*ARGSUSED*/ 961 static void 962 print_all_cmds(struct fct_i_cmd *icmd, struct find_options *options, void *arg) 963 { 964 mdb_printf("%p\n", icmd); 965 } 966 967 /* 968 * find outstanding cmds (fct_i_cmd) on local port 969 */ 970 static int 971 outstanding_cmds_on_lport(struct stmf_i_local_port *siport, cmd_filter_t filter, 972 struct find_options *options, void *arg) 973 { 974 struct fct_i_local_port *iportp; 975 struct fct_i_local_port iport; 976 struct fct_local_port port; 977 struct fct_cmd_slot *slotp; 978 struct fct_cmd_slot slot; 979 int i; 980 981 iportp = __ilport2iport((uintptr_t)siport, DCMD_ADDRSPEC, 0, NULL); 982 if (iportp == NULL) 983 return (DCMD_ERR); 984 985 if (mdb_vread(&iport, sizeof (struct fct_i_local_port), 986 (uintptr_t)iportp) != sizeof (struct fct_i_local_port)) { 987 mdb_warn("Unable to read in fct_i_local_port\n"); 988 return (DCMD_ERR); 989 } 990 if (mdb_vread(&port, sizeof (struct fct_local_port), 991 (uintptr_t)iport.iport_port) != sizeof (struct fct_local_port)) { 992 mdb_warn("Unable to read in fct_local_port\n"); 993 return (DCMD_ERR); 994 } 995 996 slotp = iport.iport_cmd_slots; 997 for (i = 0; i < port.port_max_xchges; i++) { 998 if (mdb_vread(&slot, sizeof (struct fct_cmd_slot), 999 (uintptr_t)slotp) != sizeof (struct fct_cmd_slot)) { 1000 mdb_warn("Unable to read in fct_cmd_slot\n"); 1001 return (DCMD_ERR); 1002 } 1003 if (slot.slot_cmd != NULL) { 1004 if (filter == NULL) 1005 mdb_printf("%p\n", slot.slot_cmd); 1006 else 1007 filter(slot.slot_cmd, options, arg); 1008 } 1009 slotp ++; 1010 } 1011 1012 return (DCMD_OK); 1013 } 1014 1015 /*ARGSUSED*/ 1016 static int 1017 stmf_find_tasks(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1018 { 1019 struct find_options *options; 1020 struct stmf_i_local_port *siport; 1021 1022 options = parse_options(argc, argv); 1023 if (options == NULL || 1024 (options->lpname_defined == 0 && options->rpname_defined == 0)) { 1025 mdb_printf("lpname=<wwn.12345678> or rpname=<wwn.12345678>" 1026 " should be specified\n"); 1027 return (DCMD_OK); 1028 } 1029 1030 if (options->lpname_defined) { 1031 siport = find_lport_by_wwn(options->lpname); 1032 if (siport == NULL) 1033 return (DCMD_ERR); 1034 1035 outstanding_cmds_on_lport(siport, print_tasks, options, NULL); 1036 return (DCMD_OK); 1037 } 1038 1039 if (options->rpname_defined) { 1040 mdb_walk_state_t ws = {NULL, }; 1041 fct_i_remote_port_t *irpp; 1042 1043 while ((siport = next_stmf_port(&ws)) != NULL) { 1044 if ((irpp = find_irp_by_wwn(siport, options->rpname)) 1045 != NULL) { 1046 outstanding_cmds_on_lport(siport, 1047 print_tasks_on_rp, options, irpp); 1048 } 1049 } 1050 } 1051 1052 return (DCMD_OK); 1053 } 1054 1055 /*ARGSUSED*/ 1056 static int 1057 fct_find_cmds(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1058 { 1059 struct find_options *options; 1060 struct stmf_i_local_port *siport; 1061 1062 options = parse_options(argc, argv); 1063 if (options == NULL || options->lpname_defined == 0) { 1064 mdb_printf("lpname=<wwn.12345678> should be specified\n"); 1065 return (DCMD_OK); 1066 } 1067 1068 siport = find_lport_by_wwn(options->lpname); 1069 if (siport == NULL) 1070 return (DCMD_ERR); 1071 1072 outstanding_cmds_on_lport(siport, print_all_cmds, options, NULL); 1073 return (DCMD_OK); 1074 } 1075 1076 static int 1077 fct_icmds(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1078 { 1079 struct fct_i_local_port iport; 1080 struct fct_i_cmd icmd; 1081 struct fct_i_cmd *icmdp; 1082 int i; 1083 int verbose = 0; 1084 1085 for (i = 0; i < argc; i++) { 1086 char *ptr = (char *)argv[i].a_un.a_str; 1087 1088 if (ptr[0] == '-') 1089 ptr++; 1090 while (*ptr) { 1091 if (*ptr == 'v') 1092 verbose = 1; 1093 ptr++; 1094 } 1095 } 1096 1097 if (!(flags & DCMD_ADDRSPEC)) { 1098 mdb_warn("fct_i_local_port_t address should be specified"); 1099 return (DCMD_ERR); 1100 } 1101 1102 if (mdb_vread(&iport, sizeof (struct fct_i_local_port), addr) 1103 != sizeof (struct fct_i_local_port)) { 1104 mdb_warn("Unable to read in fct_i_local_port at %p\n", addr); 1105 return (DCMD_ERR); 1106 } 1107 1108 icmdp = iport.iport_cached_cmdlist; 1109 while (icmdp) { 1110 if (mdb_vread(&icmd, sizeof (struct fct_i_cmd), 1111 (uintptr_t)icmdp) == -1) { 1112 mdb_warn("failed to read fct_i_cmd at %p", icmdp); 1113 return (DCMD_ERR); 1114 } 1115 1116 mdb_printf("%p\n", icmdp); 1117 if (verbose) { 1118 mdb_printf(" fct cmd: %p\n", icmd.icmd_cmd); 1119 } 1120 1121 icmdp = icmd.icmd_next; 1122 } 1123 1124 return (DCMD_OK); 1125 } 1126 1127 struct find_options * 1128 parse_options(int argc, const mdb_arg_t *argv) 1129 { 1130 int i; 1131 struct find_options *options; 1132 int len; 1133 char *ptr; 1134 int ret; 1135 1136 if (argc == 0) 1137 return (NULL); 1138 options = mdb_zalloc(sizeof (struct find_options), UM_SLEEP); 1139 for (i = 0; i < argc; i++) { 1140 switch (argv[i].a_type) { 1141 case MDB_TYPE_STRING: 1142 break; 1143 case MDB_TYPE_IMMEDIATE: 1144 case MDB_TYPE_CHAR: 1145 mdb_printf("unknown type\n"); 1146 } 1147 if ((ptr = strchr(argv[i].a_un.a_str, '=')) == NULL) { 1148 mdb_printf("invalid argument: %s\n", 1149 argv[i].a_un.a_str); 1150 goto out; 1151 } 1152 len = ptr - argv[i].a_un.a_str; 1153 ptr++; /* point to value now */ 1154 1155 if (len == strlen("lpname") && 1156 strncmp(argv[i].a_un.a_str, "lpname", len) == 0) { 1157 if (strstr(ptr, "wwn.") == ptr) 1158 ptr += 4; 1159 ret = string2wwn(ptr, options->lpname); 1160 if (ret == -1) 1161 goto out; 1162 #if 0 1163 mdb_printf("wwn=%02x%02x%02x%02x%02x%02x%02x%02x\n", 1164 wwn[0], wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]); 1165 #endif 1166 options->lpname_defined = 1; 1167 1168 } else if (len == strlen("rp") && 1169 strncmp(argv[i].a_un.a_str, "rp", len) == 0) { 1170 options->rp_defined = 1; 1171 options->rp = 1172 (void *)(unsigned long)mdb_strtoull(ptr); 1173 1174 } else if (len == strlen("rpname") && 1175 strncmp(argv[i].a_un.a_str, "rpname", len) == 0) { 1176 if (strstr(ptr, "wwn.") == ptr) 1177 ptr += 4; 1178 ret = string2wwn(ptr, options->rpname); 1179 if (ret == -1) 1180 goto out; 1181 options->rpname_defined = 1; 1182 1183 } else if (len == strlen("show") && 1184 strncmp(argv[i].a_un.a_str, "show", len) == 0) { 1185 char *s; 1186 int l; 1187 1188 for (;;) { 1189 s = strchr(ptr, ','); 1190 if (s) 1191 l = s - ptr; 1192 else 1193 l = strlen(ptr); 1194 if (l == strlen("task_flags") && 1195 strncmp(ptr, "task_flags", l) == 0) 1196 options->show_task_flags = 1; 1197 else if (l == strlen("lport") && 1198 strncmp(ptr, "lport", l) == 0) 1199 options->show_lport = 1; 1200 else { 1201 mdb_printf("unknown shower: %s\n", 1202 ptr); 1203 goto out; 1204 } 1205 if (s == NULL) 1206 break; 1207 ptr = s + 1; 1208 } 1209 } else { 1210 mdb_printf("unknown argument: %s\n", 1211 argv[i].a_un.a_str); 1212 goto out; 1213 } 1214 } 1215 1216 return (options); 1217 out: 1218 mdb_free(options, sizeof (struct find_options)); 1219 return (NULL); 1220 } 1221 1222 int 1223 string2wwn(const char *s, uint8_t wwn[8]) 1224 { 1225 int i; 1226 char tmp[17]; 1227 char *p; 1228 1229 if (strlen(s) > 16) { 1230 mdb_printf("invalid wwn %s\n", s); 1231 return (-1); 1232 } 1233 1234 strcpy(tmp, s); 1235 p = tmp + strlen(tmp) - 2; 1236 memset(wwn, 0, 8); 1237 /* figure out wwn from the tail to beginning */ 1238 for (i = 7; i >= 0 && p >= tmp; i--, p -= 2) { 1239 wwn[i] = mdb_strtoull(p); 1240 *p = 0; 1241 } 1242 return (0); 1243 } 1244 1245 void 1246 fct_find_cmds_help(void) 1247 { 1248 mdb_printf( 1249 "Find all cached fct_i_cmd_t for a local port. If a local port \n" 1250 "name is specified, find all pending cmds for it and print the \n" 1251 "address. Example:\n" 1252 " fct_find_cmds lpname=<wwn.12345678 or 12345678>\n"); 1253 } 1254 void 1255 stmf_find_ilport_help(void) 1256 { 1257 mdb_printf( 1258 "Find the fct_i_local_port if local port name is " 1259 "specified. Example:\n" 1260 " stmf_find_ilport lpname=<wwn.12345678 or 12345678>\n"); 1261 } 1262 void 1263 stmf_find_fct_irp_help(void) 1264 { 1265 mdb_printf( 1266 "If a remote port name or stmf_i_remote_port_t address is\n" 1267 "specified, loop through all local ports, to which this remote \n" 1268 "port has logged in, print address for stmf_i_local_port_t and \n" 1269 "stmf_i_remote_port. Example:\n" 1270 " stmf_find_fct_irp rpname=<wwn.12345678 or 12345678>\n" 1271 " stmf_find_fct_irp rp=<3000586778734>\n"); 1272 } 1273 void 1274 stmf_find_tasks_help(void) 1275 { 1276 mdb_printf( 1277 "Find all pending scsi_task_t for a given local port and/or\n" 1278 "remote port. Various different fields for each task are printed\n" 1279 "depending on what is requested. Example:\n" 1280 " stmf_find_tasks rpname=<wwn.12345678 or 12345678>\n" 1281 " stmf_find_tasks lpname=<wwn.12345678 or 12345678> " 1282 "show=task_flags,lport\n"); 1283 } 1284 1285 static const mdb_dcmd_t dcmds[] = { 1286 { "stmf_ilports", "[-v]", 1287 "Print a list of stmf_i_local_port", stmf_ilports }, 1288 { "ilport2iport", "?[-v]", 1289 "Convert stmf_i_local_port to corresponding fct_i_local_port", 1290 ilport2iport }, 1291 { "stmf_iss", "?[-v]", 1292 "List all active sessions for a given local port", 1293 stmf_iss }, 1294 { "stmf_ilus", "[-v]", "Print a list of stmf_i_lu", stmf_ilus }, 1295 { "stmf_i_lu_providers", "[-v]", 1296 "Print a list of stmf_i_lu_provider", stmf_i_lu_providers }, 1297 { "stmf_i_port_providers", "[-v]", 1298 "Print a list of stmf_i_port_provider", stmf_i_port_providers }, 1299 { "fct_irps", "?[-v]", 1300 "Print all fct_i_remote_port for a given fct_i_local_port", 1301 fct_irps }, 1302 { "fct_icmds", "?[-v]", 1303 "Print all cached fct_i_cmd_t on fct_i_local_port", 1304 fct_icmds }, 1305 { "fct_find_cmds", "lpname", 1306 "Find all fct_i_cmd_t for a given local port", 1307 fct_find_cmds, fct_find_cmds_help}, 1308 { "stmf_find_ilport", "lpname", 1309 "Find local port information based on its wwn", 1310 stmf_find_ilport, stmf_find_ilport_help}, 1311 { "stmf_find_fct_irp", "rpname|rp", 1312 "Print fct remote port information based on its wwn", 1313 stmf_find_fct_irp, stmf_find_fct_irp_help}, 1314 { "stmf_find_tasks", "lpname|rpname [show]", 1315 "Find all pending task for a local port or remote port", 1316 stmf_find_tasks, stmf_find_tasks_help}, 1317 { NULL } 1318 }; 1319 1320 static const mdb_walker_t walkers[] = { 1321 { NULL } 1322 }; 1323 1324 static const mdb_modinfo_t modinfo = { 1325 MDB_API_VERSION, dcmds, walkers 1326 }; 1327 1328 const mdb_modinfo_t * 1329 _mdb_init(void) 1330 { 1331 return (&modinfo); 1332 } 1333