Print this page
NEX-2787 Multiple comstar / fibre channel / qlt threads stuck waiting on locks with a spinning interrupt thread
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Approved by: Jean McCormack <jean.mccormack@nexenta.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/cmd/mdb/common/modules/stmf/stmf.c
+++ new/usr/src/cmd/mdb/common/modules/stmf/stmf.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
|
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 + * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
23 24 * Use is subject to license terms.
24 25 */
25 26
26 27 #include <sys/dditypes.h>
27 28 #include <sys/mdb_modapi.h>
28 29 #include <sys/modctl.h>
29 30 #include <sys/sunddi.h>
30 31 #include <sys/lpif.h>
31 32 #include <sys/stmf.h>
32 33 #include <sys/portif.h>
34 +#include <sys/list.h>
33 35 #include <stmf_impl.h>
34 36 #include <lun_map.h>
35 37 #include <stmf_state.h>
36 38
37 39 #include <sys/fct.h>
38 40 #include <fct_impl.h>
39 41
40 42 #include "cmd_options.h"
41 43
42 44 static int
43 45 stmf_ilport_walk_i(mdb_walk_state_t *wsp)
44 46 {
45 47 if (wsp->walk_addr == NULL) {
46 48 struct stmf_state state;
47 49
48 50 if (mdb_readsym(&state, sizeof (struct stmf_state),
49 51 "stmf_state") == -1) {
50 52 mdb_warn("failed to read stmf_state");
51 53 return (WALK_ERR);
52 54 }
53 55 wsp->walk_addr = (uintptr_t)state.stmf_ilportlist;
54 56 }
55 57
56 58 wsp->walk_data = mdb_alloc(sizeof (stmf_i_local_port_t), UM_SLEEP);
57 59 return (WALK_NEXT);
58 60 }
59 61
60 62 static int
61 63 stmf_ilport_walk_s(mdb_walk_state_t *wsp)
62 64 {
63 65 int status = WALK_NEXT;
64 66
65 67 if (wsp->walk_addr == NULL)
66 68 return (WALK_DONE);
67 69
68 70 if (mdb_vread(wsp->walk_data, sizeof (struct stmf_i_local_port),
69 71 wsp->walk_addr) == -1) {
70 72 mdb_warn("failed to read stmf_i_local_port_t at %p",
71 73 wsp->walk_addr);
72 74 return (WALK_ERR);
73 75 }
74 76
75 77 if (wsp->walk_callback)
76 78 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
77 79 wsp->walk_cbdata);
78 80
79 81 wsp->walk_addr = (uintptr_t)
80 82 (((struct stmf_i_local_port *)wsp->walk_data)->ilport_next);
81 83
82 84 return (status);
83 85 }
84 86
85 87 static void
86 88 stmf_ilport_walk_f(mdb_walk_state_t *wsp)
87 89 {
88 90 mdb_free(wsp->walk_data, sizeof (struct stmf_i_local_port));
89 91 }
90 92
91 93 static int
92 94 dump_ilport(struct stmf_i_local_port *ilportp, int verbose)
93 95 {
94 96 if (ilportp == NULL)
95 97 return (DCMD_OK);
96 98
97 99 mdb_printf("%p\n", ilportp);
98 100
99 101 if (verbose) {
100 102 /* here assume the alias is maximumly 1024 bytes */
101 103 char alias[255];
102 104 struct stmf_local_port lport;
103 105 struct stmf_i_local_port ilport;
104 106
105 107 if (mdb_vread(&ilport, sizeof (ilport), (uintptr_t)ilportp)
106 108 == -1) {
107 109 mdb_warn("failed to read stmf_i_local_port at %p",
108 110 ilportp);
109 111 return (DCMD_ERR);
110 112 }
111 113
112 114 memset(alias, 0, sizeof (alias));
113 115 if (mdb_vread(&lport, sizeof (lport),
114 116 (uintptr_t)ilport.ilport_lport) == -1) {
115 117 mdb_warn("failed to read stmf_local_port at %p",
116 118 ilport.ilport_lport);
117 119 return (DCMD_ERR);
118 120 }
119 121 if (lport.lport_alias && mdb_vread(alias, sizeof (alias),
120 122 (uintptr_t)lport.lport_alias) == -1) {
121 123 mdb_warn("failed to read memory at %p",
122 124 lport.lport_alias);
123 125 return (DCMD_ERR);
124 126 }
125 127
126 128 mdb_printf(" lport: %p\n", ilport.ilport_lport);
127 129 if (lport.lport_alias)
128 130 mdb_printf(" port alias: %s\n", alias);
129 131 mdb_printf(" port provider: %p\n", lport.lport_pp);
130 132 }
131 133
132 134 return (DCMD_OK);
133 135 }
134 136
135 137 /*ARGSUSED*/
136 138 static int
137 139 stmf_ilports(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
138 140 {
139 141 int i;
140 142 int verbose = 0;
141 143 mdb_walk_state_t ws = {NULL, };
142 144
143 145 for (i = 0; i < argc; i++) {
144 146 char *ptr = (char *)argv[i].a_un.a_str;
145 147
146 148 if (ptr[0] == '-')
147 149 ptr++;
148 150 while (*ptr) {
149 151 if (*ptr == 'v')
150 152 verbose = 1;
151 153 ptr++;
152 154 }
153 155 }
154 156
155 157 if (stmf_ilport_walk_i(&ws) == WALK_ERR)
156 158 return (DCMD_ERR);
157 159
158 160 dump_ilport((stmf_i_local_port_t *)ws.walk_addr, verbose);
159 161
160 162 while (stmf_ilport_walk_s(&ws) == WALK_NEXT)
161 163 dump_ilport((stmf_i_local_port_t *)ws.walk_addr, verbose);
162 164
163 165 stmf_ilport_walk_f(&ws);
164 166 return (DCMD_OK);
165 167 }
166 168
167 169 struct stmf_i_local_port *
168 170 next_stmf_port(mdb_walk_state_t *wsp)
169 171 {
170 172 if (wsp->walk_addr == NULL) {
171 173 if (stmf_ilport_walk_i(wsp) == WALK_ERR) {
172 174 stmf_ilport_walk_f(wsp);
173 175 return (NULL);
174 176 }
175 177 if (wsp->walk_addr == NULL)
176 178 stmf_ilport_walk_f(wsp);
177 179 return ((struct stmf_i_local_port *)wsp->walk_addr);
178 180 }
179 181
180 182 if (stmf_ilport_walk_s(wsp) == WALK_ERR) {
181 183 stmf_ilport_walk_f(wsp);
182 184 return (NULL);
183 185 }
184 186 if (wsp->walk_addr == NULL)
185 187 stmf_ilport_walk_f(wsp);
186 188 return ((struct stmf_i_local_port *)wsp->walk_addr);
187 189 }
188 190
189 191
190 192 /*ARGSUSED*/
191 193 static int
192 194 stmf_iss(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
193 195 {
194 196 struct stmf_i_local_port iport;
195 197 struct stmf_i_scsi_session *issp;
196 198 struct stmf_i_scsi_session iss;
197 199 int i;
198 200 int verbose = 0;
199 201
200 202 for (i = 0; i < argc; i++) {
201 203 char *ptr = (char *)argv[i].a_un.a_str;
202 204
203 205 if (ptr[0] == '-')
204 206 ptr++;
205 207 while (*ptr) {
206 208 if (*ptr == 'v')
207 209 verbose = 1;
208 210 ptr++;
209 211 }
210 212 }
211 213
212 214 if (addr == NULL) {
213 215 mdb_warn("address of stmf_i_local_port should be specified\n");
214 216 return (DCMD_ERR);
215 217 }
216 218
217 219 /*
218 220 * Input should be stmf_i_local_port_t.
219 221 */
220 222 if (mdb_vread(&iport, sizeof (struct stmf_i_local_port), addr)
221 223 != sizeof (struct stmf_i_local_port)) {
222 224 mdb_warn("Unable to read in stmf_i_local_port at %p\n", addr);
223 225 return (DCMD_ERR);
224 226 }
225 227
226 228 issp = iport.ilport_ss_list;
227 229
228 230 while (issp) {
229 231 if (mdb_vread(&iss, sizeof (iss), (uintptr_t)issp) == -1) {
230 232 mdb_warn("failed to read stmf_i_scsi_session_t at %p",
231 233 issp);
232 234 return (DCMD_ERR);
233 235 }
234 236
235 237 mdb_printf("%p\n", issp);
236 238 if (verbose) {
237 239 mdb_printf(" scsi session: %p\n", iss.iss_ss);
238 240 }
239 241
240 242 issp = iss.iss_next;
241 243 }
242 244
243 245 return (DCMD_OK);
244 246 }
245 247
246 248 /*ARGSUSED*/
247 249 static int
248 250 stmf_ilus(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
249 251 {
250 252 struct stmf_state state;
251 253 struct stmf_i_lu ilu;
252 254 struct stmf_i_lu *ilup;
253 255 int i;
254 256 int verbose = 0;
255 257
256 258 for (i = 0; i < argc; i++) {
257 259 char *ptr = (char *)argv[i].a_un.a_str;
258 260
259 261 if (ptr[0] == '-')
260 262 ptr++;
261 263 while (*ptr) {
262 264 if (*ptr == 'v')
263 265 verbose = 1;
264 266 ptr++;
265 267 }
266 268 }
267 269
268 270 if (mdb_readsym(&state, sizeof (struct stmf_state), "stmf_state")
269 271 == -1) {
270 272 mdb_warn("failed to read stmf_state");
271 273 return (DCMD_ERR);
272 274 }
273 275
274 276 ilup = state.stmf_ilulist;
275 277 while (ilup) {
276 278 if (mdb_vread(&ilu, sizeof (struct stmf_i_lu), (uintptr_t)ilup)
277 279 == -1) {
278 280 mdb_warn("failed to read stmf_i_lu_t at %p", ilup);
279 281 return (DCMD_ERR);
280 282 }
281 283
282 284 mdb_printf("%p\n", ilup);
283 285 if (verbose) {
284 286 mdb_printf(" lu: %p\n", ilu.ilu_lu);
285 287
286 288 /* XXX lu_alias? what is its size? */
287 289 }
288 290
289 291 ilup = ilu.ilu_next;
290 292 }
291 293
292 294 return (DCMD_OK);
293 295 }
294 296
295 297 /*ARGSUSED*/
296 298 static int
297 299 stmf_i_lu_providers(uintptr_t addr, uint_t flags, int argc,
298 300 const mdb_arg_t *argv)
299 301 {
300 302 struct stmf_state state;
301 303 struct stmf_i_lu_provider ilp;
302 304 struct stmf_i_lu_provider *ilpp;
303 305 int i;
304 306 int verbose = 0;
305 307
306 308 for (i = 0; i < argc; i++) {
307 309 char *ptr = (char *)argv[i].a_un.a_str;
308 310
309 311 if (ptr[0] == '-')
310 312 ptr++;
311 313 while (*ptr) {
312 314 if (*ptr == 'v')
313 315 verbose = 1;
314 316 ptr++;
315 317 }
316 318 }
317 319
318 320 if (mdb_readsym(&state, sizeof (struct stmf_state), "stmf_state")
319 321 == -1) {
320 322 mdb_warn("failed to read stmf_state");
321 323 return (DCMD_ERR);
322 324 }
323 325
324 326 ilpp = state.stmf_ilplist;
325 327 while (ilpp) {
326 328 if (mdb_vread(&ilp, sizeof (stmf_i_lu_provider_t),
327 329 (uintptr_t)ilpp) == -1) {
328 330 mdb_warn("failed to read stmf_i_lu_provider_t at %p",
329 331 ilpp);
330 332 return (DCMD_ERR);
331 333 }
332 334
333 335 mdb_printf("%p\n", ilpp);
334 336 if (verbose) {
335 337 mdb_printf(" lu provider: %p\n", ilp.ilp_lp);
336 338 }
337 339
338 340 ilpp = ilp.ilp_next;
339 341 }
340 342
341 343 return (DCMD_OK);
342 344 }
343 345
344 346 /*ARGSUSED*/
345 347 static int
346 348 stmf_i_port_providers(uintptr_t addr, uint_t flags, int argc,
347 349 const mdb_arg_t *argv)
348 350 {
349 351 struct stmf_state state;
350 352 struct stmf_i_port_provider ipp;
351 353 struct stmf_i_port_provider *ippp;
352 354 int i;
353 355 int verbose = 0;
354 356
355 357 for (i = 0; i < argc; i++) {
356 358 char *ptr = (char *)argv[i].a_un.a_str;
357 359
358 360 if (ptr[0] == '-')
359 361 ptr++;
360 362 while (*ptr) {
361 363 if (*ptr == 'v')
362 364 verbose = 1;
363 365 ptr++;
364 366 }
365 367 }
366 368
367 369 if (mdb_readsym(&state, sizeof (struct stmf_state), "stmf_state")
368 370 == -1) {
369 371 mdb_warn("failed to read stmf_state");
370 372 return (DCMD_ERR);
371 373 }
372 374
373 375 ippp = state.stmf_ipplist;
374 376 while (ippp) {
375 377 if (mdb_vread(&ipp, sizeof (stmf_i_port_provider_t),
376 378 (uintptr_t)ippp) == -1) {
377 379 mdb_warn("failed to read stmf_i_port_provider_t at %p",
378 380 ippp);
379 381 return (DCMD_ERR);
380 382 }
381 383
382 384 mdb_printf("%p\n", ippp);
383 385 if (verbose) {
384 386 mdb_printf(" port provider: %p\n", ipp.ipp_pp);
385 387 }
386 388
387 389 ippp = ipp.ipp_next;
388 390 }
389 391
390 392 return (DCMD_OK);
391 393 }
392 394
393 395 int string2wwn(const char *s, uint8_t wwn[8]);
394 396
395 397 static uint16_t port_max_logins;
396 398 static int rp_index;
397 399
398 400 /*
399 401 * Cervert stmf_i_local_port to fct_i_local_port
400 402 */
401 403 /*ARGSUSED*/
402 404 static struct fct_i_local_port *
403 405 __ilport2iport(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
404 406 {
405 407 struct stmf_i_local_port iport;
406 408 struct stmf_local_port lport;
407 409 struct fct_local_port fport;
408 410
409 411 if (!(flags & DCMD_ADDRSPEC)) {
410 412 mdb_warn("stmf_i_local_port address should be specified");
411 413 return (NULL);
412 414 }
413 415
414 416 /*
415 417 * Input should be stmf_i_local_port_t.
416 418 */
417 419 if (mdb_vread(&iport, sizeof (struct stmf_i_local_port), addr)
418 420 != sizeof (struct stmf_i_local_port)) {
419 421 mdb_warn("Unable to read in stmf_i_local_port\n");
420 422 return (NULL);
421 423 }
422 424
423 425 if (mdb_vread(&lport, sizeof (stmf_local_port_t),
424 426 (uintptr_t)iport.ilport_lport) != sizeof (stmf_local_port_t)) {
425 427 mdb_warn("Unable to read in stmf_local_port\n");
426 428 return (NULL);
427 429 }
428 430
429 431 if (mdb_vread(&fport, sizeof (fct_local_port_t),
430 432 (uintptr_t)lport.lport_port_private)
431 433 != sizeof (fct_local_port_t)) {
432 434 mdb_warn("Unable to read in fct_local_port\n");
433 435 return (NULL);
434 436 }
435 437
436 438 return (fport.port_fct_private);
437 439 }
438 440
439 441 static int
440 442 ilport2iport(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
441 443 {
442 444 struct fct_i_local_port *iportp;
443 445 int i;
444 446 int verbose = 0;
445 447
446 448 for (i = 0; i < argc; i++) {
447 449 char *ptr = (char *)argv[i].a_un.a_str;
448 450
449 451 if (ptr[0] == '-')
450 452 ptr++;
451 453 while (*ptr) {
452 454 if (*ptr == 'v')
453 455 verbose = 1;
454 456 ptr++;
455 457 }
456 458 }
457 459
458 460
459 461 iportp = __ilport2iport(addr, flags, argc, argv);
460 462 if (iportp) {
461 463 mdb_printf("%p\n", iportp);
462 464 if (verbose) {
463 465 struct fct_i_local_port iport;
464 466 /* is the alias always 16 bytes in size ? */
465 467 char alias[16];
466 468
467 469 memset(alias, 0, sizeof (alias));
468 470 if (mdb_vread(&iport, sizeof (fct_i_local_port_t),
469 471 (uintptr_t)iportp)
470 472 != sizeof (fct_i_local_port_t)) {
471 473 mdb_warn("Unable to read in fct_i_local_port"
472 474 "at %p\n", iportp);
473 475 return (DCMD_ERR);
474 476 }
475 477 if (iport.iport_alias &&
476 478 mdb_vread(alias, sizeof (alias),
477 479 (uintptr_t)iport.iport_alias)
478 480 != sizeof (alias)) {
479 481 mdb_warn("Unable to read in memory at %p",
480 482 iport.iport_alias);
481 483 return (DCMD_ERR);
482 484 }
483 485 mdb_printf(" port: %p\n", iport.iport_port);
484 486 if (iport.iport_alias)
485 487 mdb_printf(" alias: %s\n", alias);
486 488 }
487 489 }
488 490 return (DCMD_OK);
489 491 }
490 492
491 493 /*
492 494 * by wwn, we can only find one local port
493 495 */
494 496 static struct stmf_i_local_port *
495 497 find_lport_by_wwn(uint8_t wwn[8])
496 498 {
497 499 struct stmf_i_local_port *siport;
498 500 struct fct_i_local_port *fiport;
499 501 struct fct_i_local_port iport;
500 502 struct fct_local_port fport;
501 503 mdb_walk_state_t ws = {NULL, };
502 504
503 505 while ((siport = next_stmf_port(&ws)) != NULL) {
504 506 fiport = __ilport2iport((uintptr_t)siport, DCMD_ADDRSPEC,
505 507 0, NULL);
506 508 if (fiport == NULL)
507 509 return (NULL);
508 510
509 511 if (mdb_vread(&iport, sizeof (fct_i_local_port_t),
510 512 (uintptr_t)fiport)
511 513 != sizeof (fct_i_local_port_t)) {
512 514 mdb_warn("Unable to read in fct_i_local_port\n");
513 515 return (NULL);
514 516 }
515 517 if (mdb_vread(&fport, sizeof (fct_local_port_t),
516 518 (uintptr_t)iport.iport_port)
517 519 != sizeof (fct_local_port_t)) {
518 520 mdb_warn("Unable to read in fct_local_port\n");
519 521 return (NULL);
520 522 }
521 523
522 524 #if 0
523 525 mdb_printf("pwwn=%02x%02x%02x%02x%02x%02x%02x%02x\n",
524 526 fport.port_pwwn[0], fport.port_pwwn[1],
525 527 fport.port_pwwn[2], fport.port_pwwn[3],
526 528 fport.port_pwwn[4], fport.port_pwwn[5],
527 529 fport.port_pwwn[6], fport.port_pwwn[7]);
528 530 #endif
529 531 if (memcmp(fport.port_pwwn, wwn, 8) == 0) {
530 532 return (siport);
531 533 }
532 534 }
533 535
534 536 return (NULL);
535 537 }
536 538
537 539 /*ARGSUSED*/
538 540 static int
539 541 stmf_find_ilport(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
540 542 {
541 543 struct find_options *options;
542 544 struct stmf_i_local_port *siport;
543 545
544 546 options = parse_options(argc, argv);
545 547 /* need to free options manually ? */
546 548 if (options == NULL || ! options->lpname_defined) {
547 549 mdb_printf("lpname=<wwn.12345678 or 12345678> "
548 550 "should be specified\n");
549 551 return (DCMD_OK);
550 552 }
551 553
552 554 if ((siport = find_lport_by_wwn(options->lpname)) != NULL)
553 555 mdb_printf("%p\n", siport);
554 556
555 557 return (DCMD_OK);
556 558 }
557 559
558 560 static int
559 561 fct_irp_walk_i(mdb_walk_state_t *wsp)
560 562 {
561 563 struct fct_local_port port;
562 564 struct fct_i_local_port iport;
563 565
564 566 if (wsp->walk_addr == NULL) {
565 567 mdb_warn("Can not perform global walk");
566 568 return (WALK_ERR);
567 569 }
568 570
569 571 /*
570 572 * Input should be fct_i_local_port_t.
571 573 */
572 574 if (mdb_vread(&iport, sizeof (struct fct_i_local_port), wsp->walk_addr)
573 575 != sizeof (struct fct_i_local_port)) {
574 576 mdb_warn("Unable to read in fct_i_local_port\n");
575 577 return (WALK_ERR);
576 578 }
577 579
578 580 if (mdb_vread(&port, sizeof (struct fct_local_port),
579 581 (uintptr_t)iport.iport_port)
580 582 != sizeof (struct fct_local_port)) {
581 583 mdb_warn("Unable to read in fct_local_port\n");
582 584 return (WALK_ERR);
583 585 }
584 586
585 587 port_max_logins = port.port_max_logins;
586 588 rp_index = 0;
587 589 wsp->walk_addr = (uintptr_t)iport.iport_rp_slots;
588 590
589 591 return (WALK_NEXT);
590 592 }
591 593
592 594 static int
593 595 fct_irp_walk_s(mdb_walk_state_t *wsp)
594 596 {
595 597 int status = WALK_NEXT;
596 598 fct_i_remote_port_t *rp;
597 599
598 600 if (wsp->walk_addr == NULL)
599 601 return (WALK_DONE);
600 602
601 603 if (rp_index++ >= port_max_logins)
602 604 return (WALK_DONE);
603 605
604 606 if (mdb_vread(&rp, sizeof (fct_i_remote_port_t *),
605 607 wsp->walk_addr) == -1) {
606 608 mdb_warn("failed to read address of fct_i_remote_port_t at %p",
607 609 wsp->walk_addr);
608 610 return (WALK_DONE);
609 611 }
610 612
611 613 if (rp != NULL && wsp->walk_callback != NULL)
612 614 status = wsp->walk_callback((uintptr_t)rp, rp,
613 615 wsp->walk_cbdata);
614 616
615 617 wsp->walk_addr = (uintptr_t)
616 618 &(((fct_i_remote_port_t **)wsp->walk_addr)[1]);
617 619
618 620 return (status);
619 621 }
620 622
621 623 static void
622 624 fct_irp_walk_f(mdb_walk_state_t *wsp)
623 625 {
624 626 wsp->walk_addr = NULL;
625 627 }
626 628
627 629 /*
628 630 * to set remote_port
629 631 */
630 632 /*ARGSUSED*/
631 633 static int
632 634 walk_fct_irp_cb(uintptr_t p, const void * arg, void *cbdata)
633 635 {
634 636 *((uintptr_t *)cbdata) = p;
635 637 return (WALK_NEXT);
636 638 }
637 639
638 640 static int
639 641 fct_irps(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
640 642 {
641 643 static uint64_t cbdata = 0;
642 644 mdb_walk_state_t ws = {walk_fct_irp_cb, &cbdata, addr};
643 645 fct_i_remote_port_t *irpp;
644 646 int i;
645 647 int verbose = 0;
646 648
647 649 for (i = 0; i < argc; i++) {
648 650 char *ptr = (char *)argv[i].a_un.a_str;
649 651
650 652 if (ptr[0] == '-')
651 653 ptr++;
652 654 while (*ptr) {
653 655 if (*ptr == 'v')
654 656 verbose = 1;
655 657 ptr++;
656 658 }
657 659 }
658 660
659 661 if (!(flags & DCMD_ADDRSPEC)) {
660 662 mdb_warn("fct_i_local_port_t address should be specified");
661 663 return (DCMD_ERR);
662 664 }
663 665
664 666 fct_irp_walk_i(&ws);
665 667 while (fct_irp_walk_s(&ws) == WALK_NEXT) {
666 668 irpp = *((fct_i_remote_port_t **)ws.walk_cbdata);
667 669
668 670 if (irpp) {
669 671 *((fct_i_remote_port_t **)ws.walk_cbdata) = NULL;
670 672
671 673 mdb_printf("%p\n", irpp);
672 674 if (verbose) {
673 675 fct_i_remote_port_t irp;
674 676
675 677 if (mdb_vread(&irp, sizeof (irp),
676 678 (uintptr_t)irpp) != sizeof (irp)) {
677 679 mdb_warn("Unable to read in "
678 680 "fct_i_remote_port at %p\n", irpp);
679 681 return (DCMD_ERR);
680 682 }
681 683 mdb_printf(" remote port: %p\n", irp.irp_rp);
682 684 mdb_printf(" port id: %x\n", irp.irp_portid);
683 685 }
684 686 }
685 687 }
686 688 fct_irp_walk_f(&ws);
687 689
688 690 return (DCMD_OK);
689 691 }
690 692
691 693 static uintptr_t cur_iport_for_irp_loop = NULL;
692 694
693 695 static fct_i_remote_port_t *
694 696 next_rport(struct fct_i_local_port *iport)
695 697 {
696 698 static uint64_t cbdata = 0;
697 699 static mdb_walk_state_t ws = {walk_fct_irp_cb, &cbdata};
698 700 int ret;
699 701 fct_i_remote_port_t *irp;
700 702
701 703 if (ws.walk_addr == NULL || cur_iport_for_irp_loop !=
702 704 (uintptr_t)iport) {
703 705 *((fct_i_remote_port_t **)ws.walk_cbdata) = NULL;
704 706 cur_iport_for_irp_loop = (uintptr_t)iport;
705 707 ws.walk_addr = (uintptr_t)iport;
706 708 if (fct_irp_walk_i(&ws) == WALK_ERR) {
707 709 fct_irp_walk_f(&ws);
708 710 return (NULL);
709 711 }
710 712 if (ws.walk_addr == NULL) {
711 713 fct_irp_walk_f(&ws);
712 714 return (NULL);
713 715 }
714 716 }
715 717
716 718 while ((ret = fct_irp_walk_s(&ws)) == WALK_NEXT) {
717 719 if (*((fct_i_remote_port_t **)ws.walk_cbdata) != 0) {
718 720 irp = *((fct_i_remote_port_t **)ws.walk_cbdata);
719 721 *((fct_i_remote_port_t **)ws.walk_cbdata) = NULL;
720 722 return (irp);
721 723 }
722 724 }
723 725 fct_irp_walk_f(&ws);
724 726
725 727 /*
726 728 * If it is WALK_DONE, there may be one remote port there
727 729 */
728 730 if (ret == WALK_DONE) {
729 731 irp = *((fct_i_remote_port_t **)ws.walk_cbdata);
730 732 *((fct_i_remote_port_t **)ws.walk_cbdata) = NULL;
731 733 return (irp);
732 734 }
733 735 return (NULL);
734 736 }
735 737
736 738 static struct stmf_i_local_port *
737 739 irp_to_ilport(struct fct_i_remote_port *irpp)
738 740 {
739 741 struct fct_i_remote_port irp;
740 742 struct fct_remote_port rp;
741 743 struct fct_local_port port;
742 744 struct stmf_local_port lport;
743 745
744 746 if (mdb_vread(&irp, sizeof (struct fct_i_remote_port),
745 747 (uintptr_t)irpp)
746 748 != sizeof (struct fct_i_remote_port)) {
747 749 mdb_warn("Unable to read in fct_i_remote_port\n");
748 750 return (NULL);
749 751 }
750 752 if (mdb_vread(&rp, sizeof (struct fct_remote_port),
751 753 (uintptr_t)irp.irp_rp)
752 754 != sizeof (struct fct_remote_port)) {
753 755 mdb_warn("Unable to read in fct_remote_port\n");
754 756 return (NULL);
755 757 }
756 758
757 759 if (mdb_vread(&port, sizeof (struct fct_local_port),
758 760 (uintptr_t)rp.rp_port)
759 761 != sizeof (struct fct_local_port)) {
760 762 mdb_warn("Unable to read in fct_local_port\n");
761 763 return (NULL);
762 764 }
763 765 if (mdb_vread(&lport, sizeof (struct stmf_local_port),
764 766 (uintptr_t)port.port_lport)
765 767 != sizeof (struct stmf_local_port)) {
766 768 mdb_warn("Unable to read in stmf_local_port\n");
767 769 return (NULL);
768 770 }
769 771 return (lport.lport_stmf_private);
770 772 }
771 773
772 774 /*
773 775 * by wwn, we may find more than one remote port, so we need to know its
774 776 * corresponding local port
775 777 */
776 778 static struct fct_i_remote_port *
777 779 find_irp_by_wwn(struct stmf_i_local_port *siport, uint8_t wwn[8])
778 780 {
779 781 struct fct_i_local_port *fiport;
780 782 fct_i_remote_port_t *irpp;
781 783 struct fct_i_remote_port irp;
782 784 struct fct_remote_port rp;
783 785 fct_i_remote_port_t *ret = NULL;
784 786
785 787 fiport = __ilport2iport((uintptr_t)siport, DCMD_ADDRSPEC, 0, NULL);
786 788 if (fiport == NULL)
787 789 return (NULL);
788 790
789 791 while ((irpp = next_rport(fiport)) != NULL) {
790 792 if (mdb_vread(&irp, sizeof (struct fct_i_remote_port),
791 793 (uintptr_t)irpp)
792 794 != sizeof (struct fct_i_remote_port)) {
793 795 mdb_warn("Unable to read in fct_i_remote_port\n");
794 796 break;
795 797 }
796 798 if (mdb_vread(&rp, sizeof (struct fct_remote_port),
797 799 (uintptr_t)irp.irp_rp)
798 800 != sizeof (struct fct_remote_port)) {
799 801 mdb_warn("Unable to read in fct_remote_port\n");
800 802 break;
801 803 }
802 804
803 805 if (memcmp(rp.rp_pwwn, wwn, 8) == 0) {
804 806 ret = irpp;
805 807 break;
806 808 }
807 809 }
808 810 cur_iport_for_irp_loop = NULL;
809 811 return (ret);
810 812 }
811 813
812 814 /*ARGSUSED*/
813 815 static int
814 816 stmf_find_fct_irp(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
815 817 {
816 818 struct stmf_i_local_port *siport;
817 819 struct find_options *options;
818 820 fct_i_remote_port_t *irpp;
819 821 mdb_walk_state_t ws = {NULL, };
820 822
821 823 options = parse_options(argc, argv);
822 824 /* need to free options manually ? */
823 825 if (options == NULL || (options->rpname_defined == 0 &&
824 826 options->rp_defined == 0)) {
825 827 mdb_printf("rpname=<wwn.12345678> or rp=<3000586778734>"
826 828 " should be specified\n");
827 829 return (DCMD_OK);
828 830 }
829 831 if (options->rpname_defined && options->rp_defined) {
830 832 mdb_printf("rpname=<wwn.12345678> or rp=<3000586778734>"
831 833 " should be specified, but not both\n");
832 834 return (DCMD_OK);
833 835 }
834 836
835 837 if (options->rp_defined) {
836 838 siport = irp_to_ilport(options->rp);
837 839 if (siport != NULL)
838 840 mdb_printf("stmf_i_local_port=%p,"
839 841 " fct_i_remote_port=%p\n",
840 842 siport, options->rp);
841 843 return (DCMD_OK);
842 844 }
843 845
844 846 /* if options->rpname_defined */
845 847 while ((siport = next_stmf_port(&ws)) != NULL) {
846 848 if ((irpp = find_irp_by_wwn(siport, options->rpname)) != NULL)
847 849 mdb_printf("stmf_i_local_port=%p, "
848 850 "fct_i_remote_port=%p\n",
849 851 siport, irpp);
850 852 }
851 853
852 854 return (DCMD_OK);
853 855 }
854 856
855 857 typedef void (*cmd_filter_t) (struct fct_i_cmd *,
856 858 struct find_options *, void *);
857 859
858 860 /*ARGSUSED*/
859 861 static void
860 862 print_tasks(struct fct_i_cmd *icmdp, struct find_options *options, void *arg)
861 863 {
862 864 struct fct_i_cmd icmd;
863 865 struct fct_cmd cmd;
864 866
865 867 if (mdb_vread(&icmd, sizeof (struct fct_i_cmd),
866 868 (uintptr_t)icmdp) != sizeof (struct fct_i_cmd)) {
867 869 mdb_warn("Unable to read in fct_i_cmd\n");
868 870 return;
869 871 }
870 872 if (mdb_vread(&cmd, sizeof (struct fct_cmd),
871 873 (uintptr_t)icmd.icmd_cmd) != sizeof (struct fct_cmd)) {
872 874 mdb_warn("Unable to read in fct_cmd\n");
873 875 return;
874 876 }
875 877
876 878 if (cmd.cmd_type == FCT_CMD_FCP_XCHG) {
877 879 struct scsi_task task;
878 880 int colon_printed = 0;
879 881
880 882 if (mdb_vread(&task, sizeof (struct scsi_task),
881 883 (uintptr_t)cmd.cmd_specific)
882 884 != sizeof (struct scsi_task)) {
883 885 mdb_warn("Unable to read in scsi_task\n");
884 886 return;
885 887 }
886 888
887 889 mdb_printf("%p", cmd.cmd_specific);
888 890 if (options->show_task_flags) {
889 891 mdb_printf(":");
890 892 colon_printed = 1;
891 893 mdb_printf(" task_flags=%x", task.task_flags);
892 894 }
893 895
894 896 if (options->show_lport) {
895 897 if (colon_printed == 0) {
896 898 mdb_printf(":");
897 899 colon_printed = 1;
898 900 }
899 901 mdb_printf(" lport=%p", task.task_lport);
900 902 }
901 903 mdb_printf("\n");
902 904 }
903 905 }
904 906
905 907 static void
906 908 print_tasks_on_rp(struct fct_i_cmd *icmdp, struct find_options *options,
907 909 void *arg)
908 910 {
909 911 struct fct_i_cmd icmd;
910 912 struct fct_cmd cmd;
911 913 fct_i_remote_port_t irp;
912 914
913 915 if (mdb_vread(&icmd, sizeof (struct fct_i_cmd),
914 916 (uintptr_t)icmdp) != sizeof (struct fct_i_cmd)) {
915 917 mdb_warn("Unable to read in fct_i_cmd\n");
916 918 return;
917 919 }
918 920 if (mdb_vread(&cmd, sizeof (struct fct_cmd),
919 921 (uintptr_t)icmd.icmd_cmd) != sizeof (struct fct_cmd)) {
920 922 mdb_warn("Unable to read in fct_cmd\n");
921 923 return;
922 924 }
923 925
924 926 /* arg is a pointer to fct_i_remote_port */
925 927 if (mdb_vread(&irp, sizeof (struct fct_i_remote_port),
926 928 (uintptr_t)arg) != sizeof (struct fct_i_remote_port)) {
927 929 mdb_warn("Unable to read in fct_i_remote_port\n");
928 930 return;
929 931 }
930 932
931 933 if (cmd.cmd_type == FCT_CMD_FCP_XCHG && cmd.cmd_rp == irp.irp_rp) {
932 934 struct scsi_task task;
933 935 int colon_printed = 0;
934 936
935 937 if (mdb_vread(&task, sizeof (struct scsi_task),
936 938 (uintptr_t)cmd.cmd_specific)
937 939 != sizeof (struct scsi_task)) {
938 940 mdb_warn("Unable to read in scsi_task\n");
939 941 return;
940 942 }
941 943
942 944 mdb_printf("%p", cmd.cmd_specific);
943 945 if (options->show_task_flags) {
944 946 mdb_printf(":");
945 947 colon_printed = 1;
946 948 mdb_printf(" task_flags=%x", task.task_flags);
947 949 }
948 950
949 951 if (options->show_lport) {
950 952 if (colon_printed == 0) {
951 953 mdb_printf(":");
952 954 colon_printed = 1;
953 955 }
954 956 mdb_printf(" lport=%p", task.task_lport);
955 957 }
956 958 mdb_printf("\n");
957 959 }
958 960 }
959 961
960 962 /*ARGSUSED*/
961 963 static void
962 964 print_all_cmds(struct fct_i_cmd *icmd, struct find_options *options, void *arg)
963 965 {
964 966 mdb_printf("%p\n", icmd);
965 967 }
966 968
967 969 /*
968 970 * find outstanding cmds (fct_i_cmd) on local port
969 971 */
970 972 static int
971 973 outstanding_cmds_on_lport(struct stmf_i_local_port *siport, cmd_filter_t filter,
972 974 struct find_options *options, void *arg)
973 975 {
974 976 struct fct_i_local_port *iportp;
975 977 struct fct_i_local_port iport;
976 978 struct fct_local_port port;
977 979 struct fct_cmd_slot *slotp;
978 980 struct fct_cmd_slot slot;
979 981 int i;
980 982
981 983 iportp = __ilport2iport((uintptr_t)siport, DCMD_ADDRSPEC, 0, NULL);
982 984 if (iportp == NULL)
983 985 return (DCMD_ERR);
984 986
985 987 if (mdb_vread(&iport, sizeof (struct fct_i_local_port),
986 988 (uintptr_t)iportp) != sizeof (struct fct_i_local_port)) {
987 989 mdb_warn("Unable to read in fct_i_local_port\n");
988 990 return (DCMD_ERR);
989 991 }
990 992 if (mdb_vread(&port, sizeof (struct fct_local_port),
991 993 (uintptr_t)iport.iport_port) != sizeof (struct fct_local_port)) {
992 994 mdb_warn("Unable to read in fct_local_port\n");
993 995 return (DCMD_ERR);
994 996 }
995 997
996 998 slotp = iport.iport_cmd_slots;
997 999 for (i = 0; i < port.port_max_xchges; i++) {
998 1000 if (mdb_vread(&slot, sizeof (struct fct_cmd_slot),
999 1001 (uintptr_t)slotp) != sizeof (struct fct_cmd_slot)) {
1000 1002 mdb_warn("Unable to read in fct_cmd_slot\n");
1001 1003 return (DCMD_ERR);
1002 1004 }
1003 1005 if (slot.slot_cmd != NULL) {
1004 1006 if (filter == NULL)
1005 1007 mdb_printf("%p\n", slot.slot_cmd);
1006 1008 else
1007 1009 filter(slot.slot_cmd, options, arg);
1008 1010 }
1009 1011 slotp ++;
1010 1012 }
1011 1013
1012 1014 return (DCMD_OK);
1013 1015 }
1014 1016
1015 1017 /*ARGSUSED*/
1016 1018 static int
1017 1019 stmf_find_tasks(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1018 1020 {
1019 1021 struct find_options *options;
1020 1022 struct stmf_i_local_port *siport;
1021 1023
1022 1024 options = parse_options(argc, argv);
1023 1025 if (options == NULL ||
1024 1026 (options->lpname_defined == 0 && options->rpname_defined == 0)) {
1025 1027 mdb_printf("lpname=<wwn.12345678> or rpname=<wwn.12345678>"
1026 1028 " should be specified\n");
1027 1029 return (DCMD_OK);
1028 1030 }
1029 1031
1030 1032 if (options->lpname_defined) {
1031 1033 siport = find_lport_by_wwn(options->lpname);
1032 1034 if (siport == NULL)
1033 1035 return (DCMD_ERR);
1034 1036
1035 1037 outstanding_cmds_on_lport(siport, print_tasks, options, NULL);
1036 1038 return (DCMD_OK);
1037 1039 }
1038 1040
1039 1041 if (options->rpname_defined) {
1040 1042 mdb_walk_state_t ws = {NULL, };
1041 1043 fct_i_remote_port_t *irpp;
1042 1044
1043 1045 while ((siport = next_stmf_port(&ws)) != NULL) {
1044 1046 if ((irpp = find_irp_by_wwn(siport, options->rpname))
1045 1047 != NULL) {
1046 1048 outstanding_cmds_on_lport(siport,
1047 1049 print_tasks_on_rp, options, irpp);
1048 1050 }
1049 1051 }
1050 1052 }
1051 1053
1052 1054 return (DCMD_OK);
1053 1055 }
1054 1056
1055 1057 /*ARGSUSED*/
1056 1058 static int
1057 1059 fct_find_cmds(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1058 1060 {
1059 1061 struct find_options *options;
1060 1062 struct stmf_i_local_port *siport;
1061 1063
1062 1064 options = parse_options(argc, argv);
1063 1065 if (options == NULL || options->lpname_defined == 0) {
1064 1066 mdb_printf("lpname=<wwn.12345678> should be specified\n");
1065 1067 return (DCMD_OK);
1066 1068 }
1067 1069
1068 1070 siport = find_lport_by_wwn(options->lpname);
1069 1071 if (siport == NULL)
1070 1072 return (DCMD_ERR);
1071 1073
1072 1074 outstanding_cmds_on_lport(siport, print_all_cmds, options, NULL);
1073 1075 return (DCMD_OK);
1074 1076 }
1075 1077
1076 1078 static int
1077 1079 fct_icmds(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1078 1080 {
1079 1081 struct fct_i_local_port iport;
1080 1082 struct fct_i_cmd icmd;
1081 1083 struct fct_i_cmd *icmdp;
1082 1084 int i;
1083 1085 int verbose = 0;
1084 1086
1085 1087 for (i = 0; i < argc; i++) {
1086 1088 char *ptr = (char *)argv[i].a_un.a_str;
1087 1089
1088 1090 if (ptr[0] == '-')
1089 1091 ptr++;
1090 1092 while (*ptr) {
1091 1093 if (*ptr == 'v')
1092 1094 verbose = 1;
1093 1095 ptr++;
1094 1096 }
1095 1097 }
1096 1098
1097 1099 if (!(flags & DCMD_ADDRSPEC)) {
|
↓ open down ↓ |
1055 lines elided |
↑ open up ↑ |
1098 1100 mdb_warn("fct_i_local_port_t address should be specified");
1099 1101 return (DCMD_ERR);
1100 1102 }
1101 1103
1102 1104 if (mdb_vread(&iport, sizeof (struct fct_i_local_port), addr)
1103 1105 != sizeof (struct fct_i_local_port)) {
1104 1106 mdb_warn("Unable to read in fct_i_local_port at %p\n", addr);
1105 1107 return (DCMD_ERR);
1106 1108 }
1107 1109
1108 - icmdp = iport.iport_cached_cmdlist;
1110 + icmdp = list_head(&iport.iport_cached_cmdlist);
1109 1111 while (icmdp) {
1112 +
1110 1113 if (mdb_vread(&icmd, sizeof (struct fct_i_cmd),
1111 1114 (uintptr_t)icmdp) == -1) {
1112 1115 mdb_warn("failed to read fct_i_cmd at %p", icmdp);
1113 1116 return (DCMD_ERR);
1114 1117 }
1115 1118
1116 1119 mdb_printf("%p\n", icmdp);
1117 1120 if (verbose) {
1118 1121 mdb_printf(" fct cmd: %p\n", icmd.icmd_cmd);
1119 1122 }
1120 1123
1121 - icmdp = icmd.icmd_next;
1124 + icmdp = list_next(&iport.iport_cached_cmdlist, icmdp);
1122 1125 }
1123 1126
1124 1127 return (DCMD_OK);
1125 1128 }
1126 1129
1127 1130 /*
1128 1131 * Walker to list the addresses of all the active STMF scsi tasks (scsi_task_t),
1129 1132 * given a stmf_worker address
1130 1133 *
1131 1134 * To list all the active STMF scsi tasks, use
1132 1135 * "::walk stmf_worker |::walk stmf_scsi_task"
1133 1136 * To list the active tasks of a particular worker, use
1134 1137 * <stmf_worker addr>::walk stmf_scsi_task
1135 1138 */
1136 1139 static int
1137 1140 stmf_scsi_task_walk_init(mdb_walk_state_t *wsp)
1138 1141 {
1139 1142 stmf_worker_t worker;
1140 1143
1141 1144 /*
1142 1145 * Input should be a stmf_worker, so read it to get the
1143 1146 * worker_task_head to get the start of the task list
1144 1147 */
1145 1148 if (wsp->walk_addr == NULL) {
1146 1149 mdb_warn("<worker addr>::walk stmf_scsi_task\n");
1147 1150 return (WALK_ERR);
1148 1151 }
1149 1152
1150 1153 if (mdb_vread(&worker, sizeof (stmf_worker_t), wsp->walk_addr) !=
1151 1154 sizeof (stmf_worker_t)) {
1152 1155 mdb_warn("failed to read in the task address\n");
1153 1156 return (WALK_ERR);
1154 1157 }
1155 1158
1156 1159 wsp->walk_addr = (uintptr_t)(worker.worker_task_head);
1157 1160 wsp->walk_data = mdb_alloc(sizeof (scsi_task_t), UM_SLEEP);
1158 1161
1159 1162 return (WALK_NEXT);
1160 1163 }
1161 1164
1162 1165 static int
1163 1166 stmf_scsi_task_walk_step(mdb_walk_state_t *wsp)
1164 1167 {
1165 1168 stmf_i_scsi_task_t itask;
1166 1169 int status;
1167 1170
1168 1171 if (wsp->walk_addr == NULL) {
1169 1172 return (WALK_DONE);
1170 1173 }
1171 1174
1172 1175 /* Save the stmf_i_scsi_task for use later to get the next entry */
1173 1176 if (mdb_vread(&itask, sizeof (stmf_i_scsi_task_t),
1174 1177 wsp->walk_addr) != sizeof (stmf_i_scsi_task_t)) {
1175 1178 mdb_warn("failed to read stmf_i_scsi_task at %p",
1176 1179 wsp->walk_addr);
1177 1180 return (WALK_DONE);
1178 1181 }
1179 1182
1180 1183 wsp->walk_addr = (uintptr_t)itask.itask_task;
1181 1184
1182 1185 if (mdb_vread(wsp->walk_data, sizeof (scsi_task_t),
1183 1186 wsp->walk_addr) != sizeof (scsi_task_t)) {
1184 1187 mdb_warn("failed to read scsi_task_t at %p", wsp->walk_addr);
1185 1188 return (DCMD_ERR);
1186 1189 }
1187 1190
1188 1191 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
1189 1192 wsp->walk_cbdata);
1190 1193
1191 1194 wsp->walk_addr = (uintptr_t)(itask.itask_worker_next);
1192 1195
1193 1196 return (status);
1194 1197 }
1195 1198
1196 1199 static void
1197 1200 stmf_scsi_task_walk_fini(mdb_walk_state_t *wsp)
1198 1201 {
1199 1202 mdb_free(wsp->walk_data, sizeof (scsi_task_t));
1200 1203 }
1201 1204
1202 1205 /*ARGSUSED*/
1203 1206 static int
1204 1207 stmf_scsi_task(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1205 1208 {
1206 1209 stmf_worker_t worker;
1207 1210 stmf_i_scsi_task_t itask;
1208 1211 scsi_task_t *task_addr, task;
1209 1212
1210 1213 /*
1211 1214 * A stmf_worker address is given to the left of ::stmf_scsi_task
1212 1215 * i.e. display the scsi_task for the given worker
1213 1216 */
1214 1217 if (!(flags & DCMD_ADDRSPEC)) {
1215 1218 if (mdb_walk_dcmd("stmf_worker", "stmf_scsi_task", argc,
1216 1219 argv) == -1) {
1217 1220 mdb_warn("Failed to walk the stmf_scsi_task entries");
1218 1221 return (DCMD_ERR);
1219 1222 }
1220 1223 return (DCMD_OK);
1221 1224 }
1222 1225
1223 1226 if (DCMD_HDRSPEC(flags) && (!(flags & DCMD_PIPE_OUT))) {
1224 1227 mdb_printf("%<u>%-19s %-10s %-19s%</u>\n",
1225 1228 "scsi_task_t", "Flags", "LPort");
1226 1229 }
1227 1230
1228 1231 if (mdb_vread(&worker, sizeof (stmf_worker_t),
1229 1232 addr) != sizeof (stmf_worker_t)) {
1230 1233 mdb_warn("failed to read in the worker address");
1231 1234 return (DCMD_ERR);
1232 1235 }
1233 1236
1234 1237 /* Read the scsi_task */
1235 1238 if (worker.worker_task_head == NULL) {
1236 1239 return (DCMD_OK);
1237 1240 }
1238 1241
1239 1242 if (mdb_vread(&itask, sizeof (stmf_i_scsi_task_t),
1240 1243 (uintptr_t)worker.worker_task_head) == -1) {
1241 1244 mdb_warn("failed to read stmf_i_scsi_task_t at %p",
1242 1245 worker.worker_task_head);
1243 1246 return (DCMD_ERR);
1244 1247 }
1245 1248
1246 1249 task_addr = itask.itask_task;
1247 1250
1248 1251 if (mdb_vread(&task, sizeof (scsi_task_t),
1249 1252 (uintptr_t)task_addr) != sizeof (scsi_task_t)) {
1250 1253 mdb_warn("failed to read scsi_task_t at %p", task_addr);
1251 1254 return (DCMD_ERR);
1252 1255 }
1253 1256
1254 1257 if ((flags & DCMD_PIPE_OUT)) {
1255 1258 mdb_printf("%p\n", task_addr);
1256 1259 } else {
1257 1260 /* pretty print */
1258 1261 mdb_printf("%-19p %-10x %-19p\n",
1259 1262 task_addr, task.task_flags, task.task_lport);
1260 1263 }
1261 1264
1262 1265 return (DCMD_OK);
1263 1266 }
1264 1267
1265 1268 /*
1266 1269 * Walker to list the addresses of all the stmf_worker in the queue
1267 1270 */
1268 1271 typedef struct stmf_worker_walk_data {
1269 1272 int worker_current;
1270 1273 int worker_count;
1271 1274 } stmf_worker_walk_data_t;
1272 1275
1273 1276 /* stmf_workers_state definition from stmf.c (static) */
1274 1277 enum {
1275 1278 STMF_WORKERS_DISABLED = 0,
1276 1279 STMF_WORKERS_ENABLING,
1277 1280 STMF_WORKERS_ENABLED
1278 1281 } stmf_workers_state;
1279 1282
1280 1283 /*
1281 1284 * Initialize the stmf_worker_t walker by either using the given starting
1282 1285 * address, or reading the value of the kernel's global stmf_workers pointer.
1283 1286 */
1284 1287 /*ARGSUSED*/
1285 1288 static int
1286 1289 stmf_worker_walk_init(mdb_walk_state_t *wsp)
1287 1290 {
1288 1291 int worker_state;
1289 1292 int nworkers;
1290 1293 stmf_worker_t *worker;
1291 1294 stmf_worker_walk_data_t *walk_data;
1292 1295
1293 1296 if (mdb_readvar(&worker_state, "stmf_workers_state") == -1) {
1294 1297 mdb_warn("failed to read stmf_workers_state");
1295 1298 return (WALK_ERR);
1296 1299 }
1297 1300 if (worker_state != STMF_WORKERS_ENABLED) {
1298 1301 mdb_warn("stmf_workers_state not initialized");
1299 1302 return (WALK_ERR);
1300 1303 }
1301 1304
1302 1305 /*
1303 1306 * Look up the stmf_nworkers_accepting_cmds to
1304 1307 * determine number of entries in the worker queue
1305 1308 */
1306 1309 if (mdb_readvar(&nworkers, "stmf_nworkers_accepting_cmds") == -1) {
1307 1310 mdb_warn("failed to read stmf_nworkers_accepting_cmds");
1308 1311 return (WALK_ERR);
1309 1312 }
1310 1313
1311 1314 if (mdb_readvar(&worker, "stmf_workers") == -1) {
1312 1315 mdb_warn("failed to read stmf_workers");
1313 1316 return (WALK_ERR);
1314 1317 }
1315 1318
1316 1319 walk_data = mdb_alloc(sizeof (stmf_worker_walk_data_t), UM_SLEEP);
1317 1320 walk_data->worker_current = 0;
1318 1321 walk_data->worker_count = nworkers;
1319 1322
1320 1323 wsp->walk_addr = (uintptr_t)worker;
1321 1324 wsp->walk_data = walk_data;
1322 1325
1323 1326 return (WALK_NEXT);
1324 1327 }
1325 1328
1326 1329 static int
1327 1330 stmf_worker_walk_step(mdb_walk_state_t *wsp)
1328 1331 {
1329 1332 stmf_worker_walk_data_t *walk_data = wsp->walk_data;
1330 1333 int status;
1331 1334
1332 1335 if (wsp->walk_addr == NULL) {
1333 1336 return (WALK_DONE);
1334 1337 }
1335 1338
1336 1339 if (walk_data->worker_current >= walk_data->worker_count) {
1337 1340 return (WALK_DONE);
1338 1341 }
1339 1342
1340 1343 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
1341 1344 wsp->walk_cbdata);
1342 1345
1343 1346 walk_data->worker_current++;
1344 1347 wsp->walk_addr += sizeof (stmf_worker_t);
1345 1348
1346 1349 return (status);
1347 1350 }
1348 1351
1349 1352 static void
1350 1353 stmf_worker_walk_fini(mdb_walk_state_t *wsp)
1351 1354 {
1352 1355 mdb_free(wsp->walk_data, sizeof (stmf_worker_walk_data_t));
1353 1356 }
1354 1357
1355 1358 int
1356 1359 stmf_worker(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
1357 1360 {
1358 1361 stmf_worker_t worker;
1359 1362
1360 1363 if (!(flags & DCMD_ADDRSPEC)) {
1361 1364 if (mdb_walk_dcmd("stmf_worker", "stmf_worker", argc,
1362 1365 argv) == -1) {
1363 1366 mdb_warn("Failed to walk the stmf_worker entries");
1364 1367 return (DCMD_ERR);
1365 1368 }
1366 1369 return (DCMD_OK);
1367 1370 }
1368 1371
1369 1372 if (mdb_vread(&worker, sizeof (stmf_worker_t),
1370 1373 addr) != sizeof (stmf_worker_t)) {
1371 1374 mdb_warn("failed to read stmf_worker at %p", addr);
1372 1375 return (DCMD_ERR);
1373 1376 }
1374 1377
1375 1378 if (flags & DCMD_PIPE_OUT) {
1376 1379 mdb_printf("%-19p\n", addr);
1377 1380 } else {
1378 1381 /* pretty print */
1379 1382 if (DCMD_HDRSPEC(flags)) {
1380 1383 mdb_printf("%<u>%-19s %-10s %-10s %-10s%</u>\n",
1381 1384 "stmf_worker_t", "State", "Ref_Count", "Tasks");
1382 1385 }
1383 1386
1384 1387 mdb_printf("%-19p %-10s %-10d %-5d%\n", addr,
1385 1388 (worker.worker_flags == STMF_WORKER_STARTED) ? "STARTED" :
1386 1389 (worker.worker_flags & STMF_WORKER_ACTIVE) ?
1387 1390 "ACTIVE" : "TERMINATED",
1388 1391 worker.worker_ref_count,
1389 1392 worker.worker_queue_depth);
1390 1393 }
1391 1394
1392 1395 return (DCMD_OK);
1393 1396 }
1394 1397
1395 1398 struct find_options *
1396 1399 parse_options(int argc, const mdb_arg_t *argv)
1397 1400 {
1398 1401 int i;
1399 1402 struct find_options *options;
1400 1403 int len;
1401 1404 char *ptr;
1402 1405 int ret;
1403 1406
1404 1407 if (argc == 0)
1405 1408 return (NULL);
1406 1409 options = mdb_zalloc(sizeof (struct find_options), UM_SLEEP);
1407 1410 for (i = 0; i < argc; i++) {
1408 1411 switch (argv[i].a_type) {
1409 1412 case MDB_TYPE_STRING:
1410 1413 break;
1411 1414 case MDB_TYPE_IMMEDIATE:
1412 1415 case MDB_TYPE_CHAR:
1413 1416 mdb_printf("unknown type\n");
1414 1417 }
1415 1418 if ((ptr = strchr(argv[i].a_un.a_str, '=')) == NULL) {
1416 1419 mdb_printf("invalid argument: %s\n",
1417 1420 argv[i].a_un.a_str);
1418 1421 goto out;
1419 1422 }
1420 1423 len = ptr - argv[i].a_un.a_str;
1421 1424 ptr++; /* point to value now */
1422 1425
1423 1426 if (len == strlen("lpname") &&
1424 1427 strncmp(argv[i].a_un.a_str, "lpname", len) == 0) {
1425 1428 if (strstr(ptr, "wwn.") == ptr)
1426 1429 ptr += 4;
1427 1430 ret = string2wwn(ptr, options->lpname);
1428 1431 if (ret == -1)
1429 1432 goto out;
1430 1433 #if 0
1431 1434 mdb_printf("wwn=%02x%02x%02x%02x%02x%02x%02x%02x\n",
1432 1435 wwn[0], wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]);
1433 1436 #endif
1434 1437 options->lpname_defined = 1;
1435 1438
1436 1439 } else if (len == strlen("rp") &&
1437 1440 strncmp(argv[i].a_un.a_str, "rp", len) == 0) {
1438 1441 options->rp_defined = 1;
1439 1442 options->rp =
1440 1443 (void *)(unsigned long)mdb_strtoull(ptr);
1441 1444
1442 1445 } else if (len == strlen("rpname") &&
1443 1446 strncmp(argv[i].a_un.a_str, "rpname", len) == 0) {
1444 1447 if (strstr(ptr, "wwn.") == ptr)
1445 1448 ptr += 4;
1446 1449 ret = string2wwn(ptr, options->rpname);
1447 1450 if (ret == -1)
1448 1451 goto out;
1449 1452 options->rpname_defined = 1;
1450 1453
1451 1454 } else if (len == strlen("show") &&
1452 1455 strncmp(argv[i].a_un.a_str, "show", len) == 0) {
1453 1456 char *s;
1454 1457 int l;
1455 1458
1456 1459 for (;;) {
1457 1460 s = strchr(ptr, ',');
1458 1461 if (s)
1459 1462 l = s - ptr;
1460 1463 else
1461 1464 l = strlen(ptr);
1462 1465 if (l == strlen("task_flags") &&
1463 1466 strncmp(ptr, "task_flags", l) == 0)
1464 1467 options->show_task_flags = 1;
1465 1468 else if (l == strlen("lport") &&
1466 1469 strncmp(ptr, "lport", l) == 0)
1467 1470 options->show_lport = 1;
1468 1471 else {
1469 1472 mdb_printf("unknown shower: %s\n",
1470 1473 ptr);
1471 1474 goto out;
1472 1475 }
1473 1476 if (s == NULL)
1474 1477 break;
1475 1478 ptr = s + 1;
1476 1479 }
1477 1480 } else {
1478 1481 mdb_printf("unknown argument: %s\n",
1479 1482 argv[i].a_un.a_str);
1480 1483 goto out;
1481 1484 }
1482 1485 }
1483 1486
1484 1487 return (options);
1485 1488 out:
1486 1489 mdb_free(options, sizeof (struct find_options));
1487 1490 return (NULL);
1488 1491 }
1489 1492
1490 1493 int
1491 1494 string2wwn(const char *s, uint8_t wwn[8])
1492 1495 {
1493 1496 int i;
1494 1497 char tmp[17];
1495 1498 char *p;
1496 1499
1497 1500 if (strlen(s) > 16) {
1498 1501 mdb_printf("invalid wwn %s\n", s);
1499 1502 return (-1);
1500 1503 }
1501 1504
1502 1505 strcpy(tmp, s);
1503 1506 p = tmp + strlen(tmp) - 2;
1504 1507 memset(wwn, 0, 8);
1505 1508 /* figure out wwn from the tail to beginning */
1506 1509 for (i = 7; i >= 0 && p >= tmp; i--, p -= 2) {
1507 1510 wwn[i] = mdb_strtoull(p);
1508 1511 *p = 0;
1509 1512 }
1510 1513 return (0);
1511 1514 }
1512 1515
1513 1516 void
1514 1517 fct_find_cmds_help(void)
1515 1518 {
1516 1519 mdb_printf(
1517 1520 "Find all cached fct_i_cmd_t for a local port. If a local port \n"
1518 1521 "name is specified, find all pending cmds for it and print the \n"
1519 1522 "address. Example:\n"
1520 1523 " fct_find_cmds lpname=<wwn.12345678 or 12345678>\n");
1521 1524 }
1522 1525 void
1523 1526 stmf_find_ilport_help(void)
1524 1527 {
1525 1528 mdb_printf(
1526 1529 "Find the fct_i_local_port if local port name is "
1527 1530 "specified. Example:\n"
1528 1531 " stmf_find_ilport lpname=<wwn.12345678 or 12345678>\n");
1529 1532 }
1530 1533 void
1531 1534 stmf_find_fct_irp_help(void)
1532 1535 {
1533 1536 mdb_printf(
1534 1537 "If a remote port name or stmf_i_remote_port_t address is\n"
1535 1538 "specified, loop through all local ports, to which this remote \n"
1536 1539 "port has logged in, print address for stmf_i_local_port_t and \n"
1537 1540 "stmf_i_remote_port. Example:\n"
1538 1541 " stmf_find_fct_irp rpname=<wwn.12345678 or 12345678>\n"
1539 1542 " stmf_find_fct_irp rp=<3000586778734>\n");
1540 1543 }
1541 1544
1542 1545 void
1543 1546 stmf_find_tasks_help(void)
1544 1547 {
1545 1548 mdb_printf(
1546 1549 "Find all pending scsi_task_t for a given local port and/or\n"
1547 1550 "remote port. Various different fields for each task are printed\n"
1548 1551 "depending on what is requested. Example:\n"
1549 1552 " stmf_find_tasks rpname=<wwn.12345678 or 12345678>\n"
1550 1553 " stmf_find_tasks lpname=<wwn.12345678 or 12345678> "
1551 1554 "show=task_flags,lport\n");
1552 1555 }
1553 1556
1554 1557 void
1555 1558 stmf_scsi_task_help(void)
1556 1559 {
1557 1560 mdb_printf(
1558 1561 "List all active scsi_task_t on a given stmf_worker_t. Example\n"
1559 1562 " addr::stmf_scsi_task\n");
1560 1563 }
1561 1564
1562 1565 static const mdb_dcmd_t dcmds[] = {
1563 1566 { "stmf_ilports", "[-v]",
1564 1567 "Print a list of stmf_i_local_port", stmf_ilports },
1565 1568 { "ilport2iport", "?[-v]",
1566 1569 "Convert stmf_i_local_port to corresponding fct_i_local_port",
1567 1570 ilport2iport },
1568 1571 { "stmf_iss", "?[-v]",
1569 1572 "List all active sessions for a given local port",
1570 1573 stmf_iss },
1571 1574 { "stmf_ilus", "[-v]", "Print a list of stmf_i_lu", stmf_ilus },
1572 1575 { "stmf_i_lu_providers", "[-v]",
1573 1576 "Print a list of stmf_i_lu_provider", stmf_i_lu_providers },
1574 1577 { "stmf_i_port_providers", "[-v]",
1575 1578 "Print a list of stmf_i_port_provider", stmf_i_port_providers },
1576 1579 { "fct_irps", "?[-v]",
1577 1580 "Print all fct_i_remote_port for a given fct_i_local_port",
1578 1581 fct_irps },
1579 1582 { "fct_icmds", "?[-v]",
1580 1583 "Print all cached fct_i_cmd_t on fct_i_local_port",
1581 1584 fct_icmds },
1582 1585 { "fct_find_cmds", "lpname",
1583 1586 "Find all fct_i_cmd_t for a given local port",
1584 1587 fct_find_cmds, fct_find_cmds_help},
1585 1588 { "stmf_find_ilport", "lpname",
1586 1589 "Find local port information based on its wwn",
1587 1590 stmf_find_ilport, stmf_find_ilport_help},
1588 1591 { "stmf_find_fct_irp", "rpname|rp",
1589 1592 "Print fct remote port information based on its wwn",
1590 1593 stmf_find_fct_irp, stmf_find_fct_irp_help},
1591 1594 { "stmf_find_tasks", "lpname|rpname [show]",
1592 1595 "Find all pending task for a local port or remote port",
1593 1596 stmf_find_tasks, stmf_find_tasks_help},
1594 1597 { "stmf_worker", "?", "List all the stmf_worker entries", stmf_worker},
1595 1598 { "stmf_scsi_task", ":",
1596 1599 "List all the active STMF SCSI tasks per worker", stmf_scsi_task,
1597 1600 stmf_scsi_task_help},
1598 1601 { NULL }
1599 1602 };
1600 1603
1601 1604 static const mdb_walker_t walkers[] = {
1602 1605 { "stmf_worker", "Walk STMF worker queue", stmf_worker_walk_init,
1603 1606 stmf_worker_walk_step, stmf_worker_walk_fini},
1604 1607 { "stmf_scsi_task", "Walk active STMF SCSI tasks per worker",
1605 1608 stmf_scsi_task_walk_init,
1606 1609 stmf_scsi_task_walk_step, stmf_scsi_task_walk_fini },
1607 1610 { NULL }
1608 1611 };
1609 1612
1610 1613 static const mdb_modinfo_t modinfo = {
1611 1614 MDB_API_VERSION, dcmds, walkers
1612 1615 };
1613 1616
1614 1617 const mdb_modinfo_t *
1615 1618 _mdb_init(void)
1616 1619 {
1617 1620 return (&modinfo);
1618 1621 }
|
↓ open down ↓ |
487 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX