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
stmf_ilport_walk_i(mdb_walk_state_t * wsp)43 stmf_ilport_walk_i(mdb_walk_state_t *wsp)
44 {
45 if (wsp->walk_addr == 0) {
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
stmf_ilport_walk_s(mdb_walk_state_t * wsp)61 stmf_ilport_walk_s(mdb_walk_state_t *wsp)
62 {
63 int status = WALK_NEXT;
64
65 if (wsp->walk_addr == 0)
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
stmf_ilport_walk_f(mdb_walk_state_t * wsp)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
dump_ilport(struct stmf_i_local_port * ilportp,int verbose)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
stmf_ilports(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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 *
next_stmf_port(mdb_walk_state_t * wsp)168 next_stmf_port(mdb_walk_state_t *wsp)
169 {
170 if (wsp->walk_addr == 0) {
171 if (stmf_ilport_walk_i(wsp) == WALK_ERR) {
172 stmf_ilport_walk_f(wsp);
173 return (NULL);
174 }
175 if (wsp->walk_addr == 0)
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 == 0)
185 stmf_ilport_walk_f(wsp);
186 return ((struct stmf_i_local_port *)wsp->walk_addr);
187 }
188
189
190 /*ARGSUSED*/
191 static int
stmf_iss(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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 == 0) {
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
stmf_ilus(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
stmf_i_lu_providers(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
stmf_i_port_providers(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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 *
__ilport2iport(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
ilport2iport(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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 *
find_lport_by_wwn(uint8_t wwn[8])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
stmf_find_ilport(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
fct_irp_walk_i(mdb_walk_state_t * wsp)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 == 0) {
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
fct_irp_walk_s(mdb_walk_state_t * wsp)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 == 0)
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
fct_irp_walk_f(mdb_walk_state_t * wsp)622 fct_irp_walk_f(mdb_walk_state_t *wsp)
623 {
624 wsp->walk_addr = 0;
625 }
626
627 /*
628 * to set remote_port
629 */
630 /*ARGSUSED*/
631 static int
walk_fct_irp_cb(uintptr_t p,const void * arg,void * cbdata)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
fct_irps(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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 = 0;
692
693 static fct_i_remote_port_t *
next_rport(struct fct_i_local_port * iport)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 == 0 || 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 == 0) {
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 *
irp_to_ilport(struct fct_i_remote_port * irpp)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 *
find_irp_by_wwn(struct stmf_i_local_port * siport,uint8_t wwn[8])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 = 0;
809 return (ret);
810 }
811
812 /*ARGSUSED*/
813 static int
stmf_find_fct_irp(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
print_tasks(struct fct_i_cmd * icmdp,struct find_options * options,void * arg)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
print_tasks_on_rp(struct fct_i_cmd * icmdp,struct find_options * options,void * arg)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
print_all_cmds(struct fct_i_cmd * icmd,struct find_options * options,void * arg)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
outstanding_cmds_on_lport(struct stmf_i_local_port * siport,cmd_filter_t filter,struct find_options * options,void * arg)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
stmf_find_tasks(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
fct_find_cmds(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
fct_icmds(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
stmf_scsi_task_walk_init(mdb_walk_state_t * wsp)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 == 0) {
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
stmf_scsi_task_walk_step(mdb_walk_state_t * wsp)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 == 0) {
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
stmf_scsi_task_walk_fini(mdb_walk_state_t * wsp)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
stmf_scsi_task(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
stmf_worker_walk_init(mdb_walk_state_t * wsp)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
stmf_worker_walk_step(mdb_walk_state_t * wsp)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 == 0) {
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
stmf_worker_walk_fini(mdb_walk_state_t * wsp)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
stmf_worker(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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 *
parse_options(int argc,const mdb_arg_t * argv)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
string2wwn(const char * s,uint8_t wwn[8])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
fct_find_cmds_help(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
stmf_find_ilport_help(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
stmf_find_fct_irp_help(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
stmf_find_tasks_help(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
stmf_scsi_task_help(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 *
_mdb_init(void)1615 _mdb_init(void)
1616 {
1617 return (&modinfo);
1618 }
1619