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 2009 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 /* 1128 * Walker to list the addresses of all the active STMF scsi tasks (scsi_task_t), 1129 * given a stmf_worker address 1130 * 1131 * To list all the active STMF scsi tasks, use 1132 * "::walk stmf_worker |::walk stmf_scsi_task" 1133 * To list the active tasks of a particular worker, use 1134 * <stmf_worker addr>::walk stmf_scsi_task 1135 */ 1136 static int 1137 stmf_scsi_task_walk_init(mdb_walk_state_t *wsp) 1138 { 1139 stmf_worker_t worker; 1140 1141 /* 1142 * Input should be a stmf_worker, so read it to get the 1143 * worker_task_head to get the start of the task list 1144 */ 1145 if (wsp->walk_addr == NULL) { 1146 mdb_warn("<worker addr>::walk stmf_scsi_task\n"); 1147 return (WALK_ERR); 1148 } 1149 1150 if (mdb_vread(&worker, sizeof (stmf_worker_t), wsp->walk_addr) != 1151 sizeof (stmf_worker_t)) { 1152 mdb_warn("failed to read in the task address\n"); 1153 return (WALK_ERR); 1154 } 1155 1156 wsp->walk_addr = (uintptr_t)(worker.worker_task_head); 1157 wsp->walk_data = mdb_alloc(sizeof (scsi_task_t), UM_SLEEP); 1158 1159 return (WALK_NEXT); 1160 } 1161 1162 static int 1163 stmf_scsi_task_walk_step(mdb_walk_state_t *wsp) 1164 { 1165 stmf_i_scsi_task_t itask; 1166 int status; 1167 1168 if (wsp->walk_addr == NULL) { 1169 return (WALK_DONE); 1170 } 1171 1172 /* Save the stmf_i_scsi_task for use later to get the next entry */ 1173 if (mdb_vread(&itask, sizeof (stmf_i_scsi_task_t), 1174 wsp->walk_addr) != sizeof (stmf_i_scsi_task_t)) { 1175 mdb_warn("failed to read stmf_i_scsi_task at %p", 1176 wsp->walk_addr); 1177 return (WALK_DONE); 1178 } 1179 1180 wsp->walk_addr = (uintptr_t)itask.itask_task; 1181 1182 if (mdb_vread(wsp->walk_data, sizeof (scsi_task_t), 1183 wsp->walk_addr) != sizeof (scsi_task_t)) { 1184 mdb_warn("failed to read scsi_task_t at %p", wsp->walk_addr); 1185 return (DCMD_ERR); 1186 } 1187 1188 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 1189 wsp->walk_cbdata); 1190 1191 wsp->walk_addr = (uintptr_t)(itask.itask_worker_next); 1192 1193 return (status); 1194 } 1195 1196 static void 1197 stmf_scsi_task_walk_fini(mdb_walk_state_t *wsp) 1198 { 1199 mdb_free(wsp->walk_data, sizeof (scsi_task_t)); 1200 } 1201 1202 /*ARGSUSED*/ 1203 static int 1204 stmf_scsi_task(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1205 { 1206 stmf_worker_t worker; 1207 stmf_i_scsi_task_t itask; 1208 scsi_task_t *task_addr, task; 1209 1210 /* 1211 * A stmf_worker address is given to the left of ::stmf_scsi_task 1212 * i.e. display the scsi_task for the given worker 1213 */ 1214 if (!(flags & DCMD_ADDRSPEC)) { 1215 if (mdb_walk_dcmd("stmf_worker", "stmf_scsi_task", argc, 1216 argv) == -1) { 1217 mdb_warn("Failed to walk the stmf_scsi_task entries"); 1218 return (DCMD_ERR); 1219 } 1220 return (DCMD_OK); 1221 } 1222 1223 if (DCMD_HDRSPEC(flags) && (!(flags & DCMD_PIPE_OUT))) { 1224 mdb_printf("%<u>%-19s %-10s %-19s%</u>\n", 1225 "scsi_task_t", "Flags", "LPort"); 1226 } 1227 1228 if (mdb_vread(&worker, sizeof (stmf_worker_t), 1229 addr) != sizeof (stmf_worker_t)) { 1230 mdb_warn("failed to read in the worker address"); 1231 return (DCMD_ERR); 1232 } 1233 1234 /* Read the scsi_task */ 1235 if (worker.worker_task_head == NULL) { 1236 return (DCMD_OK); 1237 } 1238 1239 if (mdb_vread(&itask, sizeof (stmf_i_scsi_task_t), 1240 (uintptr_t)worker.worker_task_head) == -1) { 1241 mdb_warn("failed to read stmf_i_scsi_task_t at %p", 1242 worker.worker_task_head); 1243 return (DCMD_ERR); 1244 } 1245 1246 task_addr = itask.itask_task; 1247 1248 if (mdb_vread(&task, sizeof (scsi_task_t), 1249 (uintptr_t)task_addr) != sizeof (scsi_task_t)) { 1250 mdb_warn("failed to read scsi_task_t at %p", task_addr); 1251 return (DCMD_ERR); 1252 } 1253 1254 if ((flags & DCMD_PIPE_OUT)) { 1255 mdb_printf("%p\n", task_addr); 1256 } else { 1257 /* pretty print */ 1258 mdb_printf("%-19p %-10x %-19p\n", 1259 task_addr, task.task_flags, task.task_lport); 1260 } 1261 1262 return (DCMD_OK); 1263 } 1264 1265 /* 1266 * Walker to list the addresses of all the stmf_worker in the queue 1267 */ 1268 typedef struct stmf_worker_walk_data { 1269 int worker_current; 1270 int worker_count; 1271 } stmf_worker_walk_data_t; 1272 1273 /* stmf_workers_state definition from stmf.c (static) */ 1274 enum { 1275 STMF_WORKERS_DISABLED = 0, 1276 STMF_WORKERS_ENABLING, 1277 STMF_WORKERS_ENABLED 1278 } stmf_workers_state; 1279 1280 /* 1281 * Initialize the stmf_worker_t walker by either using the given starting 1282 * address, or reading the value of the kernel's global stmf_workers pointer. 1283 */ 1284 /*ARGSUSED*/ 1285 static int 1286 stmf_worker_walk_init(mdb_walk_state_t *wsp) 1287 { 1288 int worker_state; 1289 int nworkers; 1290 stmf_worker_t *worker; 1291 stmf_worker_walk_data_t *walk_data; 1292 1293 if (mdb_readvar(&worker_state, "stmf_workers_state") == -1) { 1294 mdb_warn("failed to read stmf_workers_state"); 1295 return (WALK_ERR); 1296 } 1297 if (worker_state != STMF_WORKERS_ENABLED) { 1298 mdb_warn("stmf_workers_state not initialized"); 1299 return (WALK_ERR); 1300 } 1301 1302 /* 1303 * Look up the stmf_nworkers_accepting_cmds to 1304 * determine number of entries in the worker queue 1305 */ 1306 if (mdb_readvar(&nworkers, "stmf_nworkers_accepting_cmds") == -1) { 1307 mdb_warn("failed to read stmf_nworkers_accepting_cmds"); 1308 return (WALK_ERR); 1309 } 1310 1311 if (mdb_readvar(&worker, "stmf_workers") == -1) { 1312 mdb_warn("failed to read stmf_workers"); 1313 return (WALK_ERR); 1314 } 1315 1316 walk_data = mdb_alloc(sizeof (stmf_worker_walk_data_t), UM_SLEEP); 1317 walk_data->worker_current = 0; 1318 walk_data->worker_count = nworkers; 1319 1320 wsp->walk_addr = (uintptr_t)worker; 1321 wsp->walk_data = walk_data; 1322 1323 return (WALK_NEXT); 1324 } 1325 1326 static int 1327 stmf_worker_walk_step(mdb_walk_state_t *wsp) 1328 { 1329 stmf_worker_walk_data_t *walk_data = wsp->walk_data; 1330 int status; 1331 1332 if (wsp->walk_addr == NULL) { 1333 return (WALK_DONE); 1334 } 1335 1336 if (walk_data->worker_current >= walk_data->worker_count) { 1337 return (WALK_DONE); 1338 } 1339 1340 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 1341 wsp->walk_cbdata); 1342 1343 walk_data->worker_current++; 1344 wsp->walk_addr += sizeof (stmf_worker_t); 1345 1346 return (status); 1347 } 1348 1349 static void 1350 stmf_worker_walk_fini(mdb_walk_state_t *wsp) 1351 { 1352 mdb_free(wsp->walk_data, sizeof (stmf_worker_walk_data_t)); 1353 } 1354 1355 int 1356 stmf_worker(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 1357 { 1358 stmf_worker_t worker; 1359 1360 if (!(flags & DCMD_ADDRSPEC)) { 1361 if (mdb_walk_dcmd("stmf_worker", "stmf_worker", argc, 1362 argv) == -1) { 1363 mdb_warn("Failed to walk the stmf_worker entries"); 1364 return (DCMD_ERR); 1365 } 1366 return (DCMD_OK); 1367 } 1368 1369 if (mdb_vread(&worker, sizeof (stmf_worker_t), 1370 addr) != sizeof (stmf_worker_t)) { 1371 mdb_warn("failed to read stmf_worker at %p", addr); 1372 return (DCMD_ERR); 1373 } 1374 1375 if (flags & DCMD_PIPE_OUT) { 1376 mdb_printf("%-19p\n", addr); 1377 } else { 1378 /* pretty print */ 1379 if (DCMD_HDRSPEC(flags)) { 1380 mdb_printf("%<u>%-19s %-10s %-10s %-10s%</u>\n", 1381 "stmf_worker_t", "State", "Ref_Count", "Tasks"); 1382 } 1383 1384 mdb_printf("%-19p %-10s %-10d %-5d%\n", addr, 1385 (worker.worker_flags == STMF_WORKER_STARTED) ? "STARTED" : 1386 (worker.worker_flags == STMF_WORKER_ACTIVE) ? 1387 "ACTIVE" : "TERMINATED", 1388 worker.worker_ref_count, 1389 worker.worker_queue_depth); 1390 } 1391 1392 return (DCMD_OK); 1393 } 1394 1395 struct find_options * 1396 parse_options(int argc, const mdb_arg_t *argv) 1397 { 1398 int i; 1399 struct find_options *options; 1400 int len; 1401 char *ptr; 1402 int ret; 1403 1404 if (argc == 0) 1405 return (NULL); 1406 options = mdb_zalloc(sizeof (struct find_options), UM_SLEEP); 1407 for (i = 0; i < argc; i++) { 1408 switch (argv[i].a_type) { 1409 case MDB_TYPE_STRING: 1410 break; 1411 case MDB_TYPE_IMMEDIATE: 1412 case MDB_TYPE_CHAR: 1413 mdb_printf("unknown type\n"); 1414 } 1415 if ((ptr = strchr(argv[i].a_un.a_str, '=')) == NULL) { 1416 mdb_printf("invalid argument: %s\n", 1417 argv[i].a_un.a_str); 1418 goto out; 1419 } 1420 len = ptr - argv[i].a_un.a_str; 1421 ptr++; /* point to value now */ 1422 1423 if (len == strlen("lpname") && 1424 strncmp(argv[i].a_un.a_str, "lpname", len) == 0) { 1425 if (strstr(ptr, "wwn.") == ptr) 1426 ptr += 4; 1427 ret = string2wwn(ptr, options->lpname); 1428 if (ret == -1) 1429 goto out; 1430 #if 0 1431 mdb_printf("wwn=%02x%02x%02x%02x%02x%02x%02x%02x\n", 1432 wwn[0], wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]); 1433 #endif 1434 options->lpname_defined = 1; 1435 1436 } else if (len == strlen("rp") && 1437 strncmp(argv[i].a_un.a_str, "rp", len) == 0) { 1438 options->rp_defined = 1; 1439 options->rp = 1440 (void *)(unsigned long)mdb_strtoull(ptr); 1441 1442 } else if (len == strlen("rpname") && 1443 strncmp(argv[i].a_un.a_str, "rpname", len) == 0) { 1444 if (strstr(ptr, "wwn.") == ptr) 1445 ptr += 4; 1446 ret = string2wwn(ptr, options->rpname); 1447 if (ret == -1) 1448 goto out; 1449 options->rpname_defined = 1; 1450 1451 } else if (len == strlen("show") && 1452 strncmp(argv[i].a_un.a_str, "show", len) == 0) { 1453 char *s; 1454 int l; 1455 1456 for (;;) { 1457 s = strchr(ptr, ','); 1458 if (s) 1459 l = s - ptr; 1460 else 1461 l = strlen(ptr); 1462 if (l == strlen("task_flags") && 1463 strncmp(ptr, "task_flags", l) == 0) 1464 options->show_task_flags = 1; 1465 else if (l == strlen("lport") && 1466 strncmp(ptr, "lport", l) == 0) 1467 options->show_lport = 1; 1468 else { 1469 mdb_printf("unknown shower: %s\n", 1470 ptr); 1471 goto out; 1472 } 1473 if (s == NULL) 1474 break; 1475 ptr = s + 1; 1476 } 1477 } else { 1478 mdb_printf("unknown argument: %s\n", 1479 argv[i].a_un.a_str); 1480 goto out; 1481 } 1482 } 1483 1484 return (options); 1485 out: 1486 mdb_free(options, sizeof (struct find_options)); 1487 return (NULL); 1488 } 1489 1490 int 1491 string2wwn(const char *s, uint8_t wwn[8]) 1492 { 1493 int i; 1494 char tmp[17]; 1495 char *p; 1496 1497 if (strlen(s) > 16) { 1498 mdb_printf("invalid wwn %s\n", s); 1499 return (-1); 1500 } 1501 1502 strcpy(tmp, s); 1503 p = tmp + strlen(tmp) - 2; 1504 memset(wwn, 0, 8); 1505 /* figure out wwn from the tail to beginning */ 1506 for (i = 7; i >= 0 && p >= tmp; i--, p -= 2) { 1507 wwn[i] = mdb_strtoull(p); 1508 *p = 0; 1509 } 1510 return (0); 1511 } 1512 1513 void 1514 fct_find_cmds_help(void) 1515 { 1516 mdb_printf( 1517 "Find all cached fct_i_cmd_t for a local port. If a local port \n" 1518 "name is specified, find all pending cmds for it and print the \n" 1519 "address. Example:\n" 1520 " fct_find_cmds lpname=<wwn.12345678 or 12345678>\n"); 1521 } 1522 void 1523 stmf_find_ilport_help(void) 1524 { 1525 mdb_printf( 1526 "Find the fct_i_local_port if local port name is " 1527 "specified. Example:\n" 1528 " stmf_find_ilport lpname=<wwn.12345678 or 12345678>\n"); 1529 } 1530 void 1531 stmf_find_fct_irp_help(void) 1532 { 1533 mdb_printf( 1534 "If a remote port name or stmf_i_remote_port_t address is\n" 1535 "specified, loop through all local ports, to which this remote \n" 1536 "port has logged in, print address for stmf_i_local_port_t and \n" 1537 "stmf_i_remote_port. Example:\n" 1538 " stmf_find_fct_irp rpname=<wwn.12345678 or 12345678>\n" 1539 " stmf_find_fct_irp rp=<3000586778734>\n"); 1540 } 1541 1542 void 1543 stmf_find_tasks_help(void) 1544 { 1545 mdb_printf( 1546 "Find all pending scsi_task_t for a given local port and/or\n" 1547 "remote port. Various different fields for each task are printed\n" 1548 "depending on what is requested. Example:\n" 1549 " stmf_find_tasks rpname=<wwn.12345678 or 12345678>\n" 1550 " stmf_find_tasks lpname=<wwn.12345678 or 12345678> " 1551 "show=task_flags,lport\n"); 1552 } 1553 1554 void 1555 stmf_scsi_task_help(void) 1556 { 1557 mdb_printf( 1558 "List all active scsi_task_t on a given stmf_worker_t. Example\n" 1559 " addr::stmf_scsi_task\n"); 1560 } 1561 1562 static const mdb_dcmd_t dcmds[] = { 1563 { "stmf_ilports", "[-v]", 1564 "Print a list of stmf_i_local_port", stmf_ilports }, 1565 { "ilport2iport", "?[-v]", 1566 "Convert stmf_i_local_port to corresponding fct_i_local_port", 1567 ilport2iport }, 1568 { "stmf_iss", "?[-v]", 1569 "List all active sessions for a given local port", 1570 stmf_iss }, 1571 { "stmf_ilus", "[-v]", "Print a list of stmf_i_lu", stmf_ilus }, 1572 { "stmf_i_lu_providers", "[-v]", 1573 "Print a list of stmf_i_lu_provider", stmf_i_lu_providers }, 1574 { "stmf_i_port_providers", "[-v]", 1575 "Print a list of stmf_i_port_provider", stmf_i_port_providers }, 1576 { "fct_irps", "?[-v]", 1577 "Print all fct_i_remote_port for a given fct_i_local_port", 1578 fct_irps }, 1579 { "fct_icmds", "?[-v]", 1580 "Print all cached fct_i_cmd_t on fct_i_local_port", 1581 fct_icmds }, 1582 { "fct_find_cmds", "lpname", 1583 "Find all fct_i_cmd_t for a given local port", 1584 fct_find_cmds, fct_find_cmds_help}, 1585 { "stmf_find_ilport", "lpname", 1586 "Find local port information based on its wwn", 1587 stmf_find_ilport, stmf_find_ilport_help}, 1588 { "stmf_find_fct_irp", "rpname|rp", 1589 "Print fct remote port information based on its wwn", 1590 stmf_find_fct_irp, stmf_find_fct_irp_help}, 1591 { "stmf_find_tasks", "lpname|rpname [show]", 1592 "Find all pending task for a local port or remote port", 1593 stmf_find_tasks, stmf_find_tasks_help}, 1594 { "stmf_worker", "?", "List all the stmf_worker entries", stmf_worker}, 1595 { "stmf_scsi_task", ":", 1596 "List all the active STMF SCSI tasks per worker", stmf_scsi_task, 1597 stmf_scsi_task_help}, 1598 { NULL } 1599 }; 1600 1601 static const mdb_walker_t walkers[] = { 1602 { "stmf_worker", "Walk STMF worker queue", stmf_worker_walk_init, 1603 stmf_worker_walk_step, stmf_worker_walk_fini}, 1604 { "stmf_scsi_task", "Walk active STMF SCSI tasks per worker", 1605 stmf_scsi_task_walk_init, 1606 stmf_scsi_task_walk_step, stmf_scsi_task_walk_fini }, 1607 { NULL } 1608 }; 1609 1610 static const mdb_modinfo_t modinfo = { 1611 MDB_API_VERSION, dcmds, walkers 1612 }; 1613 1614 const mdb_modinfo_t * 1615 _mdb_init(void) 1616 { 1617 return (&modinfo); 1618 } 1619