1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 #include <mdb/mdb_modapi.h>
26 #include <mdb/mdb_ks.h>
27
28 #include <sys/cpuvar.h>
29 #include <sys/conf.h>
30 #include <sys/file.h>
31 #include <sys/types.h>
32 #include <sys/taskq.h>
33 #include <sys/sysmacros.h>
34 #include <sys/socket.h> /* networking stuff */
35 #include <sys/strsubr.h> /* networking stuff */
36 #include <sys/nvpair.h>
37 #include <sys/sunldi.h>
38 #include <sys/stmf.h>
39 #include <sys/stmf_ioctl.h>
40 #include <sys/portif.h>
41
42 #define IDM_CONN_SM_STRINGS
43 #define IDM_TASK_SM_STRINGS
44 #define ISCSIT_TGT_SM_STRINGS
45 #define ISCSIT_SESS_SM_STRINGS
46 #define ISCSIT_LOGIN_SM_STRINGS
47 #define ISCSI_SESS_SM_STRINGS
48 #define ISCSI_CMD_SM_STRINGS
49 #define ISCSI_ICS_NAMES
50 #define ISCSI_LOGIN_STATE_NAMES
51 #define IDM_CN_NOTIFY_STRINGS
52 #include <sys/idm/idm.h>
53 #include <iscsi.h>
54 #include <iscsit.h>
55 #include <iscsit_isns.h>
56 #include <sys/ib/clients/iser/iser.h>
57
58 /*
59 * We want to be able to print multiple levels of object hierarchy with a
60 * single dcmd information, and preferably also exclude intermediate
61 * levels if desired. For example some of the target objects have the
62 * following relationship:
63 *
64 * target --> session --> connection --> task
65 *
66 * The session dcmd should allow the printing of all associated tasks for the
67 * sessions without printing all the associated connections. To accomplish
68 * this the following structure contains a bit for each object type. Dcmds
69 * should invoke the functions for child objects if any bits are set
70 * in iscsi_dcmd_ctrl_t but the functions for the child object should only
71 * print data if their associated bit is set. Each object type should print
72 * a header for its first occurrence or if it is being printed as a child
73 * object for the first occurrence under each parent. For the model to follow
74 * see how idc->idc_header is handled in iscsi_sess_impl.
75 *
76 * Each dcmd should provide an external interface with the standard MDB API
77 * and an internal interface that accepts iscsi_dcmd_ctrl_t. To display
78 * child objects the dcmd calls the internal interface for the child object
79 * directly. Dcmds invoked from the command line will, of course, call the
80 * external interface. See iscsi_conn() and iscsi_conn_impl().
81 */
82
83 typedef struct {
84 union {
85 uint32_t idc_children;
86 struct {
87 uint32_t idc_tgt:1,
88 idc_tpg:1,
89 idc_tpgt:1,
90 idc_portal:1,
91 idc_sess:1,
92 idc_conn:1,
93 idc_svc:1,
94 idc_print_ip:1,
95 idc_task:1,
96 idc_buffer:1,
97 idc_states:1,
98 idc_rc_audit:1,
99 idc_lun:1,
100 idc_hba:1,
101 idc_cmd:1;
102 } child;
103 } u;
104 boolean_t idc_ini;
105 boolean_t idc_tgt;
106 boolean_t idc_verbose;
107 boolean_t idc_header;
108 /*
109 * Our connection dcmd code works off the global connection lists
110 * in IDM since we want to know about connections even when they
111 * have not progressed to the point that they have an associated
112 * session. If we use "::iscsi_sess [-c]" then we only want to
113 * see connections associated with particular session. To avoid
114 * writing a separate set of code to print session-specific connection
115 * the session code should set the sessions kernel address in the
116 * following field. The connection code will then only print
117 * connections that match.
118 */
119 uintptr_t idc_assoc_session;
120 } iscsi_dcmd_ctrl_t;
121
122 typedef struct idm_hba_walk_info {
123 void **array;
124 int n_elements;
125 int cur_element;
126 void *data;
127 } idm_hba_walk_info_t;
128
129 static int iscsi_walk_all_sess(iscsi_dcmd_ctrl_t *idc);
130 static int iscsi_walk_all_conn(iscsi_dcmd_ctrl_t *idc);
131 static int iscsi_tgt_walk_cb(uintptr_t addr, const void *list_walker_data,
132 void *idc_void);
133 static int iscsi_tpgt_walk_cb(uintptr_t addr, const void *list_walker_data,
134 void *idc_void);
135 static int iscsi_tpg_walk_cb(uintptr_t addr, const void *list_walker_data,
136 void *idc_void);
137 static int iscsi_portal_walk_cb(uintptr_t addr, const void *list_walker_data,
138 void *idc_void);
139 static int iscsi_sess_walk_cb(uintptr_t addr, const void *list_walker_data,
140 void *idc_void);
141 static int iscsi_conn_walk_cb(uintptr_t addr, const void *list_walker_data,
142 void *idc_void);
143 static int iscsi_buffer_walk_cb(uintptr_t addr, const void *list_walker_data,
144 void *idc_void);
145 static int iscsi_svc_walk_cb(uintptr_t addr, const void *list_walker_data,
146 void *idc_void);
147 static int iscsi_ini_hba_walk_cb(uintptr_t addr, const void *vhba,
148 void *idc_void);
149 static int iscsi_ini_sess_walk_cb(uintptr_t addr, const void *vsess,
150 void *idc);
151 static int iscsi_ini_conn_walk_cb(uintptr_t addr, const void *vconn,
152 void *idc_void);
153 static int iscsi_ini_lun_walk_cb(uintptr_t addr, const void *vlun,
154 void *idc_void);
155 static int iscsi_ini_cmd_walk_cb(uintptr_t addr, const void *vcmd,
156 void *idc);
157 static int iscsi_tgt_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc);
158 static int iscsi_tpgt_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc);
159 static int iscsi_tpg_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc);
160 static int iscsi_portal_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc);
161 static int iscsi_sess_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc);
162 static int iscsi_conn_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc);
163 static void iscsi_print_iscsit_conn_data(idm_conn_t *ict);
164 static void iscsi_print_ini_conn_data(idm_conn_t *ict);
165 static void iscsi_print_idm_conn_data(idm_conn_t *ict);
166 static int iscsi_task_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc);
167 static void iscsi_print_iscsit_task_data(idm_task_t *idt);
168 static int iscsi_buffer_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc);
169 static idm_conn_type_t idm_conn_type(uintptr_t addr);
170 static int iscsi_i_task_impl(idm_task_t *idt, uintptr_t addr,
171 iscsi_dcmd_ctrl_t *idc);
172 static int iscsi_refcnt_impl(uintptr_t addr);
173 static int iscsi_sm_audit_impl(uintptr_t addr);
174 static int iscsi_isns(uintptr_t addr, uint_t flags, int argc,
175 const mdb_arg_t *argv);
176 static int iscsi_svc_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc);
177 static int iscsi_ini_hba_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc);
178 static int iscsi_print_ini_sess(uintptr_t addr, iscsi_sess_t *sess,
179 iscsi_dcmd_ctrl_t *idc);
180 static int iscsi_print_ini_lun(uintptr_t addr, const iscsi_lun_t *lun,
181 iscsi_dcmd_ctrl_t *idc);
182 static int iscsi_print_ini_cmd(uintptr_t addr, const iscsi_cmd_t *cmd,
183 iscsi_dcmd_ctrl_t *idc);
184 static int iscsi_ini_sess_walk_init(mdb_walk_state_t *wsp);
185 static int iscsi_ini_sess_step(mdb_walk_state_t *wsp);
186 static int iscsi_ini_conn_walk_init(mdb_walk_state_t *wsp);
187 static int iscsi_ini_conn_step(mdb_walk_state_t *wsp);
188 static int iscsi_ini_lun_walk_init(mdb_walk_state_t *wsp);
189 static int iscsi_ini_lun_step(mdb_walk_state_t *wsp);
190 static int iscsi_ini_cmd_walk_init(mdb_walk_state_t *wsp);
191 static int iscsi_ini_cmd_step(mdb_walk_state_t *wsp);
192 static const char *iscsi_idm_conn_event(unsigned int event);
193 static const char *iscsi_iscsit_tgt_event(unsigned int event);
194 static const char *iscsi_iscsit_sess_event(unsigned int event);
195 static const char *iscsi_iscsit_login_event(unsigned int event);
196 static const char *iscsi_iscsi_cmd_event(unsigned int event);
197 static const char *iscsi_iscsi_sess_event(unsigned int event);
198 static const char *iscsi_idm_conn_state(unsigned int state);
199 static const char *iscsi_idm_task_state(unsigned int state);
200 static const char *iscsi_iscsit_tgt_state(unsigned int state);
201 static const char *iscsi_iscsit_sess_state(unsigned int state);
202 static const char *iscsi_iscsit_login_state(unsigned int state);
203 static const char *iscsi_iscsi_cmd_state(unsigned int state);
204 static const char *iscsi_iscsi_sess_state(unsigned int state);
205 static const char *iscsi_iscsi_conn_state(unsigned int state);
206 static const char *iscsi_iscsi_conn_event(unsigned int event);
207 static const char *iscsi_iscsi_login_state(unsigned int state);
208
209 static void iscsi_format_timestamp(char *ts_str, int strlen,
210 timespec_t *ts);
211 static char *iscsi_inet_ntop(int af, const void *addr, char *buf, int addrlen);
212 static void convert2ascii(char *, const in6_addr_t *);
213 static int sa_to_str(struct sockaddr_storage *sa, char *addr);
214 static int iscsi_isns_esi_cb(uintptr_t addr, const void *walker_data,
215 void *data);
216 static int iscsi_isns_portal_cb(uintptr_t addr, const void *walker_data,
217 void *data);
218
219 #define PORTAL_STR_LEN (INET6_ADDRSTRLEN + 7)
220
221 /*
222 * ::iscsi_tgt [-scatgpbSRv]
223 *
224 * iscsi_tgt - Print out information associated with an iscsit target instance
225 *
226 * s Print associated session information
227 * c Print associated connection information
228 * a Print IP addresses with connection information
229 * t Print associated task information
230 * g Print associated TPG information
231 * p Print portals with TPG information
232 * b Print associated buffer information
233 * S Print recent state events and transitions
234 * R Print reference count audit data
235 * v Verbose output about the connection
236 */
237 /*ARGSUSED*/
238 static int
iscsi_tgt(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)239 iscsi_tgt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
240 {
241 iscsi_dcmd_ctrl_t idc;
242 int buffer = 0, task = 0, print_ip = 0;
243 int tpgt = 0, conn = 0, sess = 0, portal = 0;
244 int states = 0, rc_audit = 0;
245 uintptr_t iscsit_global_addr, avl_addr, list_addr;
246 GElf_Sym sym;
247
248 bzero(&idc, sizeof (idc));
249 if (mdb_getopts(argc, argv,
250 'a', MDB_OPT_SETBITS, TRUE, &print_ip,
251 'g', MDB_OPT_SETBITS, TRUE, &tpgt,
252 's', MDB_OPT_SETBITS, TRUE, &sess,
253 'c', MDB_OPT_SETBITS, TRUE, &conn,
254 't', MDB_OPT_SETBITS, TRUE, &task,
255 'b', MDB_OPT_SETBITS, TRUE, &buffer,
256 'p', MDB_OPT_SETBITS, TRUE, &portal,
257 'S', MDB_OPT_SETBITS, TRUE, &states,
258 'R', MDB_OPT_SETBITS, TRUE, &rc_audit,
259 'v', MDB_OPT_SETBITS, TRUE, &idc.idc_verbose,
260 NULL) != argc)
261 return (DCMD_USAGE);
262
263 idc.u.child.idc_tgt = 1;
264 idc.u.child.idc_print_ip = print_ip;
265 idc.u.child.idc_tpgt = tpgt;
266 idc.u.child.idc_portal = portal;
267 idc.u.child.idc_sess = sess;
268 idc.u.child.idc_conn = conn;
269 idc.u.child.idc_task = task;
270 idc.u.child.idc_buffer = buffer;
271 idc.u.child.idc_states = states;
272 idc.u.child.idc_rc_audit = rc_audit;
273
274 if (DCMD_HDRSPEC(flags))
275 idc.idc_header = 1;
276
277 /*
278 * If no address was specified on the command line, we
279 * print out all tgtions
280 */
281 if (!(flags & DCMD_ADDRSPEC)) {
282 if (mdb_lookup_by_name("iscsit_global", &sym) == -1) {
283 mdb_warn("failed to find symbol 'iscsit_global'");
284 return (DCMD_ERR);
285 }
286 iscsit_global_addr = (uintptr_t)sym.st_value;
287 avl_addr = iscsit_global_addr +
288 offsetof(iscsit_global_t, global_target_list);
289 if (mdb_pwalk("avl", iscsi_tgt_walk_cb, &idc, avl_addr) == -1) {
290 mdb_warn("avl walk failed for global target tree");
291 return (DCMD_ERR);
292 }
293 list_addr = iscsit_global_addr +
294 offsetof(iscsit_global_t, global_deleted_target_list);
295 if (mdb_pwalk("list", iscsi_tgt_walk_cb,
296 &idc, list_addr) == -1) {
297 mdb_warn("list walk failed for deleted target list");
298 return (DCMD_ERR);
299 }
300 return (DCMD_OK);
301 }
302 return (iscsi_tgt_impl(addr, &idc));
303 }
304
305 static int
iscsi_tpg(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)306 iscsi_tpg(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
307 {
308 iscsi_dcmd_ctrl_t idc;
309 uintptr_t iscsit_global_addr, avl_addr;
310 GElf_Sym sym;
311 int rc_audit = 0;
312
313 bzero(&idc, sizeof (idc));
314 if (mdb_getopts(argc, argv,
315 'R', MDB_OPT_SETBITS, TRUE, &rc_audit,
316 NULL) != argc)
317 return (DCMD_USAGE);
318
319 /* Always print tpgs and portals */
320 idc.u.child.idc_tpg = 1;
321 idc.u.child.idc_portal = 1;
322 idc.u.child.idc_rc_audit = rc_audit;
323 if (DCMD_HDRSPEC(flags))
324 idc.idc_header = 1;
325
326 /*
327 * If no address was specified on the command line, we
328 * print out all tgtions
329 */
330 if (!(flags & DCMD_ADDRSPEC)) {
331 if (mdb_lookup_by_name("iscsit_global", &sym) == -1) {
332 mdb_warn("failed to find symbol 'iscsit_global'");
333 return (DCMD_ERR);
334 }
335 iscsit_global_addr = (uintptr_t)sym.st_value;
336 avl_addr = iscsit_global_addr +
337 offsetof(iscsit_global_t, global_tpg_list);
338 if (mdb_pwalk("avl", iscsi_tpg_walk_cb, &idc, avl_addr) == -1) {
339 mdb_warn("avl walk failed for global target tree");
340 return (DCMD_ERR);
341 }
342 return (DCMD_OK);
343 }
344 return (iscsi_tpg_impl(addr, &idc));
345 }
346
347 /*
348 * ::iscsi_tpgt [-pR]
349 *
350 * Print tpgt information.
351 * R Print reference count audit data
352 * p Print portal data
353 */
354 static int
iscsi_tpgt(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)355 iscsi_tpgt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
356 {
357 iscsi_dcmd_ctrl_t idc;
358 uintptr_t iscsit_global_addr, avl_addr, list_addr;
359 GElf_Sym sym;
360 int rc_audit = 0, portal = 0;
361
362 bzero(&idc, sizeof (idc));
363 if (mdb_getopts(argc, argv,
364 'p', MDB_OPT_SETBITS, TRUE, &portal,
365 'R', MDB_OPT_SETBITS, TRUE, &rc_audit,
366 NULL) != argc)
367 return (DCMD_USAGE);
368
369 idc.u.child.idc_tpgt = 1;
370 idc.u.child.idc_portal = portal;
371 idc.u.child.idc_rc_audit = rc_audit;
372 if (DCMD_HDRSPEC(flags))
373 idc.idc_header = 1;
374
375 /*
376 * If no address was specified on the command line,
377 * print out all tpgts
378 */
379 if (!(flags & DCMD_ADDRSPEC)) {
380 if (mdb_lookup_by_name("iscsit_global", &sym) == -1) {
381 mdb_warn("failed to find symbol 'iscsit_global'");
382 return (DCMD_ERR);
383 }
384 iscsit_global_addr = (uintptr_t)sym.st_value;
385 avl_addr = iscsit_global_addr +
386 offsetof(iscsit_global_t, global_target_list);
387 if (mdb_pwalk("avl", iscsi_tgt_walk_cb, &idc, avl_addr) == -1) {
388 mdb_warn("avl walk failed for global target tree");
389 return (DCMD_ERR);
390 }
391 list_addr = iscsit_global_addr +
392 offsetof(iscsit_global_t, global_deleted_target_list);
393 if (mdb_pwalk("list", iscsi_tgt_walk_cb,
394 &idc, list_addr) == -1) {
395 mdb_warn("list walk failed for deleted target list");
396 return (DCMD_ERR);
397 }
398 return (DCMD_OK);
399 }
400 return (iscsi_tpgt_impl(addr, &idc));
401 }
402
403 /*
404 * ::iscsi_sess [-ablmtvcSRIT]
405 *
406 * iscsi_sess - Print out information associated with an iSCSI session
407 *
408 * I Print only initiator sessions
409 * T Print only target sessions
410 * c Print associated connection information
411 * a Print IP addresses with connection information
412 * t Print associated task information
413 * l Print associated lun information (with -I)
414 * m Print associated initiator command information (with -I)
415 * b Print associated buffer information
416 * S Print recent state events and transitions
417 * R Print reference count audit data
418 * v Verbose output about the connection
419 */
420 /*ARGSUSED*/
421 static int
iscsi_sess(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)422 iscsi_sess(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
423 {
424 iscsi_dcmd_ctrl_t idc;
425 int buffer = 0, task = 0, conn = 0, print_ip = 0;
426 int states = 0, rc_audit = 0, commands = 0;
427 int luns = 0;
428
429 bzero(&idc, sizeof (idc));
430 if (mdb_getopts(argc, argv,
431 'I', MDB_OPT_SETBITS, TRUE, &idc.idc_ini,
432 'T', MDB_OPT_SETBITS, TRUE, &idc.idc_tgt,
433 'a', MDB_OPT_SETBITS, TRUE, &print_ip,
434 'c', MDB_OPT_SETBITS, TRUE, &conn,
435 't', MDB_OPT_SETBITS, TRUE, &task,
436 'l', MDB_OPT_SETBITS, TRUE, &luns,
437 'm', MDB_OPT_SETBITS, TRUE, &commands,
438 'b', MDB_OPT_SETBITS, TRUE, &buffer,
439 'S', MDB_OPT_SETBITS, TRUE, &states,
440 'R', MDB_OPT_SETBITS, TRUE, &rc_audit,
441 'v', MDB_OPT_SETBITS, TRUE, &idc.idc_verbose,
442 NULL) != argc)
443 return (DCMD_USAGE);
444
445 idc.u.child.idc_sess = 1;
446 idc.u.child.idc_print_ip = print_ip;
447 idc.u.child.idc_conn = conn;
448 idc.u.child.idc_task = task;
449 idc.u.child.idc_cmd = commands;
450 idc.u.child.idc_lun = luns;
451 idc.u.child.idc_buffer = buffer;
452 idc.u.child.idc_states = states;
453 idc.u.child.idc_rc_audit = rc_audit;
454 if (DCMD_HDRSPEC(flags))
455 idc.idc_header = 1;
456
457 /*
458 * If no address was specified on the command line, we
459 * print out all sessions
460 */
461 if (!(flags & DCMD_ADDRSPEC)) {
462 return (iscsi_walk_all_sess(&idc));
463 }
464 return (iscsi_sess_impl(addr, &idc));
465 }
466
467
468
469 /*
470 * ::iscsi_conn [-abmtvSRIT]
471 *
472 * iscsi_conn - Print out information associated with an iSCSI connection
473 *
474 * I Print only initiator connections
475 * T Print only target connections
476 * a Print IP addresses with connection information
477 * t Print associated task information
478 * b Print associated buffer information
479 * m Print associated initiator commands (with -I)
480 * S Print recent state events and transitions
481 * R Print reference count audit data
482 * v Verbose output about the connection
483 */
484 /*ARGSUSED*/
485 static int
iscsi_conn(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)486 iscsi_conn(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
487 {
488 iscsi_dcmd_ctrl_t idc;
489 int buffer = 0, task = 0, print_ip = 0;
490 int states = 0, rc_audit = 0, commands = 0;
491
492 bzero(&idc, sizeof (idc));
493 if (mdb_getopts(argc, argv,
494 'I', MDB_OPT_SETBITS, TRUE, &idc.idc_ini,
495 'T', MDB_OPT_SETBITS, TRUE, &idc.idc_tgt,
496 'a', MDB_OPT_SETBITS, TRUE, &print_ip,
497 't', MDB_OPT_SETBITS, TRUE, &task,
498 'b', MDB_OPT_SETBITS, TRUE, &buffer,
499 'm', MDB_OPT_SETBITS, TRUE, &commands,
500 'S', MDB_OPT_SETBITS, TRUE, &states,
501 'R', MDB_OPT_SETBITS, TRUE, &rc_audit,
502 'v', MDB_OPT_SETBITS, TRUE, &idc.idc_verbose,
503 NULL) != argc)
504 return (DCMD_USAGE);
505
506 idc.u.child.idc_conn = 1;
507 idc.u.child.idc_print_ip = print_ip;
508 idc.u.child.idc_task = task;
509 idc.u.child.idc_buffer = buffer;
510 idc.u.child.idc_cmd = commands;
511 idc.u.child.idc_states = states;
512 idc.u.child.idc_rc_audit = rc_audit;
513 if (DCMD_HDRSPEC(flags))
514 idc.idc_header = 1;
515
516 /*
517 * If no address was specified on the command line, we
518 * print out all connections
519 */
520 if (!(flags & DCMD_ADDRSPEC)) {
521 return (iscsi_walk_all_conn(&idc));
522 }
523 return (iscsi_conn_impl(addr, &idc));
524 }
525
526
527 /*
528 * ::iscsi_svc [-vR]
529 *
530 * iscsi_svc - Print out information associated with an iSCSI svc
531 *
532 * R Print reference count audit data
533 * v Verbose output about the service
534 */
535 static int
iscsi_svc(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)536 iscsi_svc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
537 {
538 iscsi_dcmd_ctrl_t idc;
539 GElf_Sym sym;
540 uintptr_t idm_addr;
541 uintptr_t svc_list_addr;
542 int rc_audit = 0;
543
544 bzero(&idc, sizeof (iscsi_dcmd_ctrl_t));
545
546 if (mdb_getopts(argc, argv,
547 'R', MDB_OPT_SETBITS, TRUE, &rc_audit,
548 'v', MDB_OPT_SETBITS, TRUE, &idc.idc_verbose,
549 NULL) != argc)
550 return (DCMD_USAGE);
551
552 idc.u.child.idc_svc = 1;
553 idc.u.child.idc_rc_audit = rc_audit;
554 if (DCMD_HDRSPEC(flags)) {
555 idc.idc_header = 1;
556 }
557
558 if (!(flags & DCMD_ADDRSPEC)) {
559 if (mdb_lookup_by_name("idm", &sym) == -1) {
560 mdb_warn("failed to find symbol 'idm'");
561 return (DCMD_ERR);
562 }
563 idm_addr = (uintptr_t)sym.st_value;
564 svc_list_addr = idm_addr + offsetof(idm_global_t,
565 idm_tgt_svc_list);
566
567 if (mdb_pwalk("list", iscsi_svc_walk_cb, &idc,
568 svc_list_addr) == -1) {
569 mdb_warn("list walk failed for idm services");
570 return (DCMD_ERR);
571 }
572 return (DCMD_OK);
573 }
574 return (iscsi_svc_impl(addr, &idc));
575 }
576
577 /*
578 * ::iscsi_portal -R
579 *
580 * iscsi_portal - Print out information associated with an iSCSI portal
581 *
582 * R Print reference count audit data
583 */
584 static int
iscsi_portal(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)585 iscsi_portal(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
586 {
587 iscsi_dcmd_ctrl_t idc;
588 GElf_Sym sym;
589 iscsit_global_t iscsit_global;
590 uintptr_t iscsit_global_addr;
591 uintptr_t tpg_avl_addr;
592 int rc_audit = 0;
593
594 bzero(&idc, sizeof (iscsi_dcmd_ctrl_t));
595
596 if (mdb_getopts(argc, argv,
597 'R', MDB_OPT_SETBITS, TRUE, &rc_audit,
598 NULL) != argc)
599 return (DCMD_USAGE);
600
601 idc.u.child.idc_rc_audit = rc_audit;
602 idc.u.child.idc_portal = 1;
603 if (DCMD_HDRSPEC(flags)) {
604 idc.idc_header = 1;
605 }
606
607 if (!(flags & DCMD_ADDRSPEC)) {
608 if (mdb_lookup_by_name("iscsit_global", &sym) == -1) {
609 mdb_warn("failed to find symbol 'iscsit_global'");
610 return (DCMD_ERR);
611 }
612
613 iscsit_global_addr = (uintptr_t)sym.st_value;
614
615 /* get and print the global default tpg */
616 if (mdb_vread(&iscsit_global, sizeof (iscsit_global_t),
617 iscsit_global_addr) != sizeof (iscsit_global_t)) {
618 mdb_warn("failed to read iscsit_global_t");
619 return (DCMD_ERR);
620 }
621 if (iscsi_tpg_impl((uintptr_t)iscsit_global.global_default_tpg,
622 &idc) != DCMD_OK) {
623 return (DCMD_ERR);
624 }
625
626 /* Walk the tpgs for the rest of the portals */
627 tpg_avl_addr = iscsit_global_addr + offsetof(iscsit_global_t,
628 global_tpg_list);
629 if (mdb_pwalk("avl", iscsi_tpg_walk_cb, &idc,
630 tpg_avl_addr) == -1) {
631 mdb_warn("list walk failed for global tpg tree");
632 return (DCMD_ERR);
633 }
634 return (DCMD_OK);
635 }
636 return (iscsi_portal_impl(addr, &idc));
637 }
638
639
640 /*
641 * ::iscsi_cmd -S
642 *
643 * iscsi_cmd - Print out information associated with an iSCSI cmd
644 *
645 * S Print state audit data
646 */
647 static int
iscsi_cmd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)648 iscsi_cmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
649 {
650 iscsi_dcmd_ctrl_t idc;
651 iscsi_cmd_t cmd;
652 int states = 0;
653
654 bzero(&idc, sizeof (iscsi_dcmd_ctrl_t));
655
656 if (mdb_getopts(argc, argv,
657 'S', MDB_OPT_SETBITS, TRUE, &states,
658 NULL) != argc)
659 return (DCMD_USAGE);
660
661 idc.u.child.idc_states = states;
662 idc.u.child.idc_cmd = 1;
663 idc.idc_ini = 1;
664 if (DCMD_HDRSPEC(flags)) {
665 idc.idc_header = 1;
666 }
667
668 if (!(flags & DCMD_ADDRSPEC)) {
669 if (mdb_pwalk("iscsi_ini_hba", iscsi_ini_hba_walk_cb,
670 &idc, 0) == -1) {
671 mdb_warn("iscsi cmd hba list walk failed");
672 return (DCMD_ERR);
673 }
674 } else {
675 if (mdb_vread(&cmd, sizeof (iscsi_cmd_t), addr) !=
676 sizeof (iscsi_cmd_t)) {
677 return (DCMD_ERR);
678 }
679 return (iscsi_print_ini_cmd(addr, &cmd, &idc));
680 }
681 return (DCMD_OK);
682 }
683
684
685 static int
iscsi_ini_hba_impl(uintptr_t addr,iscsi_dcmd_ctrl_t * idc)686 iscsi_ini_hba_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc)
687 {
688 iscsi_hba_t ih;
689
690 if (mdb_vread(&ih, sizeof (ih), addr) != sizeof (ih)) {
691 mdb_warn("Invalid HBA\n");
692 return (DCMD_ERR);
693 }
694
695 if (idc->u.child.idc_hba) {
696 mdb_printf("iscsi_hba %p sessions: \n", addr);
697 }
698
699 if (mdb_pwalk("iscsi_ini_sess", iscsi_ini_sess_walk_cb, idc,
700 (uintptr_t)ih.hba_sess_list) == -1) {
701 mdb_warn("iscsi_sess_t walk failed");
702 return (DCMD_ERR);
703 }
704 return (DCMD_OK);
705 }
706
707 /*
708 * ::iscsi_task [-bv]
709 *
710 * iscsi_task - Print out information associated with an iSCSI task
711 *
712 * b Print associated buffer information
713 * S Print recent state events and transitions
714 * R Print reference count audit data
715 * v Verbose output about the connection
716 */
717 /*ARGSUSED*/
718 static int
iscsi_task(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)719 iscsi_task(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
720 {
721 iscsi_dcmd_ctrl_t idc;
722 int buffer = 0;
723 int states = 0, rc_audit = 0;
724
725 bzero(&idc, sizeof (idc));
726 if (mdb_getopts(argc, argv,
727 'b', MDB_OPT_SETBITS, TRUE, &buffer,
728 'S', MDB_OPT_SETBITS, TRUE, &states,
729 'R', MDB_OPT_SETBITS, TRUE, &rc_audit,
730 'v', MDB_OPT_SETBITS, TRUE, &idc.idc_verbose,
731 NULL) != argc)
732 return (DCMD_USAGE);
733
734 idc.u.child.idc_conn = 0;
735 idc.u.child.idc_task = 1;
736 idc.u.child.idc_buffer = buffer;
737 idc.u.child.idc_states = states;
738 idc.u.child.idc_rc_audit = rc_audit;
739 if (DCMD_HDRSPEC(flags))
740 idc.idc_header = 1;
741
742 /*
743 * If no address was specified on the command line, we
744 * print out all connections
745 */
746 if (!(flags & DCMD_ADDRSPEC)) {
747 return (iscsi_walk_all_conn(&idc));
748 }
749 return (iscsi_task_impl(addr, &idc));
750 }
751
752 /*
753 * ::iscsi_refcnt
754 *
755 * iscsi_refcnt - Dump an idm_refcnt_t structure
756 *
757 */
758 /*ARGSUSED*/
759 static int
iscsi_refcnt(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)760 iscsi_refcnt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
761 {
762 if (!(flags & DCMD_ADDRSPEC)) {
763 return (DCMD_ERR);
764 }
765 return (iscsi_refcnt_impl(addr));
766 }
767
768 /*
769 * ::iscsi_states
770 *
771 * iscsi_states - Dump events and state transitions recoreded in an
772 * idm_sm_audit_t structure
773 *
774 */
775 /*ARGSUSED*/
776 static int
iscsi_states(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)777 iscsi_states(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
778 {
779 if (!(flags & DCMD_ADDRSPEC)) {
780 return (DCMD_ERR);
781 }
782 return (iscsi_sm_audit_impl(addr));
783 }
784
785
786 static int
iscsi_walk_all_sess(iscsi_dcmd_ctrl_t * idc)787 iscsi_walk_all_sess(iscsi_dcmd_ctrl_t *idc)
788 {
789 uintptr_t iscsit_global_addr;
790 uintptr_t avl_addr;
791 uintptr_t list_addr;
792 GElf_Sym sym;
793
794 /* Initiator sessions */
795 if (idc->idc_ini) {
796 /* Always print hba info on this path */
797 idc->u.child.idc_hba = 1;
798 if (mdb_pwalk("iscsi_ini_hba", iscsi_ini_hba_walk_cb,
799 idc, 0) == -1) {
800 mdb_warn("iscsi cmd hba list walk failed");
801 return (DCMD_ERR);
802 }
803 return (DCMD_OK);
804 }
805
806 /* Target sessions */
807 /* Walk discovery sessions */
808 if (mdb_lookup_by_name("iscsit_global", &sym) == -1) {
809 mdb_warn("failed to find symbol 'iscsit_global'");
810 return (DCMD_ERR);
811 }
812 iscsit_global_addr = (uintptr_t)sym.st_value;
813 avl_addr = iscsit_global_addr +
814 offsetof(iscsit_global_t, global_discovery_sessions);
815 if (mdb_pwalk("avl", iscsi_sess_walk_cb, idc, avl_addr) == -1) {
816 mdb_warn("avl walk failed for discovery sessions");
817 return (DCMD_ERR);
818 }
819
820 /* Walk targets printing all session info */
821 avl_addr = iscsit_global_addr +
822 offsetof(iscsit_global_t, global_target_list);
823 if (mdb_pwalk("avl", iscsi_tgt_walk_cb, idc, avl_addr) == -1) {
824 mdb_warn("avl walk failed for target/session tree");
825 return (DCMD_ERR);
826 }
827
828 /* Walk deleting targets printing all session info */
829 list_addr = iscsit_global_addr +
830 offsetof(iscsit_global_t, global_deleted_target_list);
831 if (mdb_pwalk("list", iscsi_tgt_walk_cb, idc, list_addr) == -1) {
832 mdb_warn("list walk failed for deleted target list");
833 return (DCMD_ERR);
834 }
835
836 return (DCMD_OK);
837 }
838
839 static int
iscsi_walk_all_conn(iscsi_dcmd_ctrl_t * idc)840 iscsi_walk_all_conn(iscsi_dcmd_ctrl_t *idc)
841 {
842 uintptr_t idm_global_addr;
843 uintptr_t list_addr;
844 GElf_Sym sym;
845
846 /* Walk initiator connections */
847 if (mdb_lookup_by_name("idm", &sym) == -1) {
848 mdb_warn("failed to find symbol 'idm'");
849 return (DCMD_ERR);
850 }
851 idm_global_addr = (uintptr_t)sym.st_value;
852 /* Walk connection list associated with the initiator */
853 list_addr = idm_global_addr + offsetof(idm_global_t, idm_ini_conn_list);
854 if (mdb_pwalk("list", iscsi_conn_walk_cb, idc, list_addr) == -1) {
855 mdb_warn("list walk failed for initiator connections");
856 return (DCMD_ERR);
857 }
858
859 /* Walk connection list associated with the target */
860 list_addr = idm_global_addr + offsetof(idm_global_t, idm_tgt_conn_list);
861 if (mdb_pwalk("list", iscsi_conn_walk_cb, idc, list_addr) == -1) {
862 mdb_warn("list walk failed for target service instances");
863 return (DCMD_ERR);
864 }
865
866 return (DCMD_OK);
867 }
868
869 /*ARGSUSED*/
870 static int
iscsi_tpg_walk_cb(uintptr_t addr,const void * list_walker_data,void * idc_void)871 iscsi_tpg_walk_cb(uintptr_t addr, const void *list_walker_data,
872 void *idc_void)
873 {
874 /* We don't particularly care about the list walker data */
875 iscsi_dcmd_ctrl_t *idc = idc_void;
876 int rc;
877
878 rc = iscsi_tpg_impl(addr, idc);
879
880 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR);
881 }
882
883 /*ARGSUSED*/
884 static int
iscsi_tgt_walk_cb(uintptr_t addr,const void * list_walker_data,void * idc_void)885 iscsi_tgt_walk_cb(uintptr_t addr, const void *list_walker_data,
886 void *idc_void)
887 {
888 /* We don't particularly care about the list walker data */
889 iscsi_dcmd_ctrl_t *idc = idc_void;
890 int rc;
891
892 rc = iscsi_tgt_impl(addr, idc);
893
894 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR);
895 }
896
897 /*ARGSUSED*/
898 static int
iscsi_tpgt_walk_cb(uintptr_t addr,const void * list_walker_data,void * idc_void)899 iscsi_tpgt_walk_cb(uintptr_t addr, const void *list_walker_data,
900 void *idc_void)
901 {
902 /* We don't particularly care about the list walker data */
903 iscsi_dcmd_ctrl_t *idc = idc_void;
904 int rc;
905
906 rc = iscsi_tpgt_impl(addr, idc);
907
908 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR);
909 }
910
911 /*ARGSUSED*/
912 static int
iscsi_portal_walk_cb(uintptr_t addr,const void * list_walker_data,void * idc_void)913 iscsi_portal_walk_cb(uintptr_t addr, const void *list_walker_data,
914 void *idc_void)
915 {
916 /* We don't particularly care about the list walker data */
917 iscsi_dcmd_ctrl_t *idc = idc_void;
918 int rc;
919
920 rc = iscsi_portal_impl(addr, idc);
921
922 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR);
923 }
924
925 /*ARGSUSED*/
926 static int
iscsi_sess_walk_cb(uintptr_t addr,const void * list_walker_data,void * idc_void)927 iscsi_sess_walk_cb(uintptr_t addr, const void *list_walker_data,
928 void *idc_void)
929 {
930 /* We don't particularly care about the list walker data */
931 iscsi_dcmd_ctrl_t *idc = idc_void;
932 int rc;
933
934 rc = iscsi_sess_impl(addr, idc);
935
936 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR);
937 }
938
939 /*ARGSUSED*/
940 static int
iscsi_sess_conn_walk_cb(uintptr_t addr,const void * list_walker_data,void * idc_void)941 iscsi_sess_conn_walk_cb(uintptr_t addr, const void *list_walker_data,
942 void *idc_void)
943 {
944 /* We don't particularly care about the list walker data */
945 iscsi_dcmd_ctrl_t *idc = idc_void;
946 iscsit_conn_t ict;
947 int rc;
948
949 /*
950 * This function is different from iscsi_conn_walk_cb because
951 * we get an iscsit_conn_t instead of an idm_conn_t
952 *
953 * Read iscsit_conn_t, use to get idm_conn_t pointer
954 */
955 if (mdb_vread(&ict, sizeof (iscsit_conn_t), addr) !=
956 sizeof (iscsit_conn_t)) {
957 return (DCMD_ERR);
958 }
959 rc = iscsi_conn_impl((uintptr_t)ict.ict_ic, idc);
960
961 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR);
962 }
963
964 /*ARGSUSED*/
965 static int
iscsi_conn_walk_cb(uintptr_t addr,const void * list_walker_data,void * idc_void)966 iscsi_conn_walk_cb(uintptr_t addr, const void *list_walker_data,
967 void *idc_void)
968 {
969 /* We don't particularly care about the list walker data */
970 iscsi_dcmd_ctrl_t *idc = idc_void;
971 int rc;
972
973 rc = iscsi_conn_impl(addr, idc);
974
975 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR);
976 }
977
978 /*ARGSUSED*/
979 static int
iscsi_buffer_walk_cb(uintptr_t addr,const void * list_walker_data,void * idc_void)980 iscsi_buffer_walk_cb(uintptr_t addr, const void *list_walker_data,
981 void *idc_void)
982 {
983 /* We don't particularly care about the list walker data */
984 iscsi_dcmd_ctrl_t *idc = idc_void;
985 int rc;
986
987 rc = iscsi_buffer_impl(addr, idc);
988
989 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR);
990 }
991
992 /*ARGSUSED*/
993 static int
iscsi_svc_walk_cb(uintptr_t addr,const void * list_walker_data,void * idc_void)994 iscsi_svc_walk_cb(uintptr_t addr, const void *list_walker_data,
995 void *idc_void)
996 {
997 iscsi_dcmd_ctrl_t *idc = idc_void;
998 int rc;
999
1000 rc = iscsi_svc_impl(addr, idc);
1001
1002 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR);
1003 }
1004
1005 /*ARGSUSED*/
1006 static int
iscsi_ini_hba_walk_cb(uintptr_t addr,const void * vhba,void * idc_void)1007 iscsi_ini_hba_walk_cb(uintptr_t addr, const void *vhba, void *idc_void)
1008 {
1009
1010 iscsi_dcmd_ctrl_t *idc = idc_void;
1011 int rc;
1012
1013 rc = iscsi_ini_hba_impl(addr, idc);
1014
1015 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR);
1016 }
1017
1018 static int
iscsi_ini_sess_walk_cb(uintptr_t addr,const void * vsess,void * idc_void)1019 iscsi_ini_sess_walk_cb(uintptr_t addr, const void *vsess, void *idc_void)
1020 {
1021 int rc;
1022
1023 if (vsess == NULL) {
1024 return (WALK_ERR);
1025 }
1026
1027 rc = iscsi_print_ini_sess(addr, (iscsi_sess_t *)vsess,
1028 (iscsi_dcmd_ctrl_t *)idc_void);
1029
1030 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR);
1031 }
1032
1033 /*ARGSUSED*/
1034 static int
iscsi_ini_conn_walk_cb(uintptr_t addr,const void * vconn,void * idc_void)1035 iscsi_ini_conn_walk_cb(uintptr_t addr, const void *vconn, void *idc_void)
1036 {
1037 const iscsi_conn_t *ict = vconn;
1038 int rc;
1039
1040 if (vconn == NULL) {
1041 return (WALK_ERR);
1042 }
1043
1044 /*
1045 * Look up the idm_conn_t in the iscsi_conn_t and call the general
1046 * connection handler.
1047 */
1048 rc = iscsi_conn_impl((uintptr_t)ict->conn_ic,
1049 (iscsi_dcmd_ctrl_t *)idc_void);
1050
1051 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR);
1052 }
1053
1054 static int
iscsi_ini_lun_walk_cb(uintptr_t addr,const void * vlun,void * idc_void)1055 iscsi_ini_lun_walk_cb(uintptr_t addr, const void *vlun, void *idc_void)
1056 {
1057 int rc;
1058
1059 if (vlun == NULL) {
1060 return (WALK_ERR);
1061 }
1062
1063 rc = iscsi_print_ini_lun(addr, (iscsi_lun_t *)vlun,
1064 (iscsi_dcmd_ctrl_t *)idc_void);
1065
1066 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR);
1067 }
1068
1069
1070 static int
iscsi_tgt_impl(uintptr_t addr,iscsi_dcmd_ctrl_t * idc)1071 iscsi_tgt_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc)
1072 {
1073 iscsit_tgt_t tgt;
1074 uintptr_t avl_addr, rc_addr, states_addr;
1075 char tgt_name[MAX_ISCSI_NODENAMELEN];
1076 int verbose, states, rc_audit;
1077
1078 /*
1079 * Read iscsit_tgt_t
1080 */
1081 if (mdb_vread(&tgt, sizeof (iscsit_tgt_t), addr) !=
1082 sizeof (iscsit_tgt_t)) {
1083 return (DCMD_ERR);
1084 }
1085
1086 /*
1087 * Read target name if available
1088 */
1089 if ((tgt.target_name == NULL) ||
1090 (mdb_readstr(tgt_name, sizeof (tgt_name),
1091 (uintptr_t)tgt.target_name) == -1)) {
1092 strcpy(tgt_name, "N/A");
1093 }
1094
1095 /*
1096 * Brief output
1097 *
1098 * iscsit_tgt_t pointer
1099 * iscsit_tgt_t.target_stmf_state
1100 * iscsit_tgt_t.target_sess_list.avl_numnodes (session count)
1101 * iscsit_tgt_t.target_name;
1102 */
1103
1104 verbose = idc->idc_verbose;
1105 states = idc->u.child.idc_states;
1106 rc_audit = idc->u.child.idc_rc_audit;
1107
1108 /* For now we will ignore the verbose flag */
1109 if (idc->u.child.idc_tgt) {
1110 /* Print target data */
1111 if (idc->idc_header) {
1112 mdb_printf("%<u>%-19s %-4s %-8s%</u>\n",
1113 "iscsit_tgt_t", "Sess", "State");
1114 }
1115 mdb_printf("%-19p %-4d %-8d\n", addr,
1116 tgt.target_sess_list.avl_numnodes,
1117 tgt.target_state);
1118 mdb_printf(" %s\n", tgt_name);
1119
1120 /* Indent and disable verbose for any child structures */
1121 mdb_inc_indent(4);
1122 idc->idc_verbose = 0;
1123 }
1124
1125 /*
1126 * Print states if requested
1127 */
1128 if (idc->u.child.idc_tgt && states) {
1129 states_addr = addr + offsetof(iscsit_tgt_t, target_state_audit);
1130
1131 mdb_printf("State History(target_state_audit):\n");
1132 if (iscsi_sm_audit_impl(states_addr) != DCMD_OK)
1133 return (DCMD_ERR);
1134 idc->u.child.idc_states = 0;
1135 }
1136
1137 /*
1138 * Print refcnt audit data if requested
1139 */
1140 if (idc->u.child.idc_tgt && rc_audit) {
1141 mdb_printf("Reference History(target_sess_refcnt):\n");
1142 rc_addr = addr +
1143 offsetof(iscsit_tgt_t, target_sess_refcnt);
1144 if (iscsi_refcnt_impl(rc_addr) != DCMD_OK)
1145 return (DCMD_ERR);
1146
1147 mdb_printf("Reference History(target_refcnt):\n");
1148 rc_addr = addr +
1149 offsetof(iscsit_tgt_t, target_refcnt);
1150
1151 if (iscsi_refcnt_impl(rc_addr) != DCMD_OK)
1152 return (DCMD_ERR);
1153 idc->u.child.idc_rc_audit = 0;
1154 }
1155
1156 /* Any child objects to walk? */
1157 if (idc->u.child.idc_tpgt || idc->u.child.idc_portal) {
1158
1159 if (idc->u.child.idc_tgt) {
1160 idc->idc_header = 1;
1161 }
1162
1163 /* Walk TPGT tree */
1164 avl_addr = addr +
1165 offsetof(iscsit_tgt_t, target_tpgt_list);
1166 if (mdb_pwalk("avl", iscsi_tpgt_walk_cb, idc,
1167 avl_addr) == -1) {
1168 mdb_warn("target tpgt list walk failed");
1169 (void) mdb_dec_indent(4);
1170 return (DCMD_ERR);
1171 }
1172 }
1173
1174 if (idc->u.child.idc_sess || idc->u.child.idc_conn ||
1175 idc->u.child.idc_task || idc->u.child.idc_buffer) {
1176
1177 if (idc->u.child.idc_tgt || idc->u.child.idc_tpgt ||
1178 idc->u.child.idc_portal) {
1179 idc->idc_header = 1;
1180 }
1181
1182 /* Walk sess tree */
1183 avl_addr = addr + offsetof(iscsit_tgt_t, target_sess_list);
1184 if (mdb_pwalk("avl", iscsi_sess_walk_cb, idc,
1185 avl_addr) == -1) {
1186 mdb_warn("target sess list walk failed");
1187 (void) mdb_dec_indent(4);
1188 return (DCMD_ERR);
1189 }
1190 }
1191
1192 /* If tgts were handled decrease indent and reset header */
1193 if (idc->u.child.idc_tgt) {
1194 idc->idc_header = 0;
1195 mdb_dec_indent(4);
1196 }
1197
1198 idc->idc_verbose = verbose;
1199 idc->u.child.idc_states = states;
1200 idc->u.child.idc_rc_audit = rc_audit;
1201 return (DCMD_OK);
1202 }
1203
1204 static int
iscsi_tpgt_impl(uintptr_t addr,iscsi_dcmd_ctrl_t * idc)1205 iscsi_tpgt_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc)
1206 {
1207 iscsit_tpgt_t tpgt;
1208 iscsit_tpg_t tpg;
1209 uintptr_t avl_addr, tpg_addr, rc_addr;
1210 int rc_audit;
1211
1212 /*
1213 * Read iscsit_tpgt_t
1214 */
1215 if (mdb_vread(&tpgt, sizeof (iscsit_tpgt_t), addr) !=
1216 sizeof (iscsit_tpgt_t)) {
1217 return (DCMD_ERR);
1218 }
1219
1220 tpg_addr = (uintptr_t)tpgt.tpgt_tpg;
1221
1222 /*
1223 * Read iscsit_tpg_t
1224 */
1225 if (mdb_vread(&tpg, sizeof (iscsit_tpg_t), tpg_addr) !=
1226 sizeof (iscsit_tpg_t)) {
1227 return (DCMD_ERR);
1228 }
1229
1230 rc_audit = idc->u.child.idc_rc_audit;
1231
1232 /*
1233 * Brief output
1234 *
1235 * iscsit_tpgt_t pointer
1236 * iscsit_tpg_t pointer
1237 * iscsit_tpg_t.tpg_name
1238 * iscsit_tpgt_t.tpgt_tag;
1239 */
1240
1241 /* For now we will ignore the verbose flag */
1242 if (idc->u.child.idc_tpgt) {
1243 /* Print target data */
1244 if (idc->idc_header) {
1245 mdb_printf("%<u>%-?s %-?s %-18s %-6s%</u>\n",
1246 "iscsit_tpgt_t", "iscsit_tpg_t", "Name", "Tag");
1247 }
1248 mdb_printf("%?p %?p %-18s 0x%04x\n", addr, tpgt.tpgt_tpg,
1249 tpg.tpg_name, tpgt.tpgt_tag);
1250
1251 if (rc_audit) {
1252 (void) mdb_inc_indent(4);
1253
1254 mdb_printf("Reference History(tpgt_refcnt):\n");
1255 rc_addr = addr + offsetof(iscsit_tpgt_t, tpgt_refcnt);
1256 if (iscsi_refcnt_impl(rc_addr) != DCMD_OK)
1257 return (DCMD_ERR);
1258
1259 idc->u.child.idc_rc_audit = 0;
1260 (void) mdb_dec_indent(4);
1261 }
1262 }
1263
1264 /*
1265 * Assume for now that anyone interested in TPGT wants to see the
1266 * portals as well. Enable idc_header for the portals.
1267 */
1268 idc->idc_header = 1;
1269 (void) mdb_inc_indent(4);
1270 avl_addr = tpg_addr + offsetof(iscsit_tpg_t, tpg_portal_list);
1271 if (mdb_pwalk("avl", iscsi_portal_walk_cb, idc, avl_addr) == -1) {
1272 mdb_warn("portal list walk failed");
1273 (void) mdb_dec_indent(4);
1274 return (DCMD_ERR);
1275 }
1276 (void) mdb_dec_indent(4);
1277 idc->idc_header = 0;
1278
1279 idc->u.child.idc_rc_audit = rc_audit;
1280 return (DCMD_OK);
1281 }
1282
1283 static int
iscsi_tpg_impl(uintptr_t addr,iscsi_dcmd_ctrl_t * idc)1284 iscsi_tpg_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc)
1285 {
1286 iscsit_tpg_t tpg;
1287 uintptr_t avl_addr, rc_addr;
1288 int rc_audit = 0;
1289
1290 rc_audit = idc->u.child.idc_rc_audit;
1291
1292 /*
1293 * Read iscsit_tpg_t
1294 */
1295 if (mdb_vread(&tpg, sizeof (iscsit_tpg_t), addr) !=
1296 sizeof (iscsit_tpg_t)) {
1297 return (DCMD_ERR);
1298 }
1299
1300 /*
1301 * Brief output
1302 *
1303 * iscsit_tpgt_t pointer
1304 * iscsit_tpg_t pointer
1305 * iscsit_tpg_t.tpg_name
1306 * iscsit_tpgt_t.tpgt_tag;
1307 */
1308
1309 /* Print tpg data */
1310 if (idc->u.child.idc_tpg) {
1311 if (idc->idc_header) {
1312 mdb_printf("%<u>%-?s %-18s%</u>\n",
1313 "iscsit_tpg_t", "Name");
1314 }
1315 mdb_printf("%?p %-18s\n", addr, tpg.tpg_name);
1316
1317 (void) mdb_inc_indent(4);
1318
1319 if (rc_audit) {
1320 mdb_printf("Reference History(tpg_refcnt):\n");
1321 rc_addr = addr + offsetof(iscsit_tpg_t, tpg_refcnt);
1322 if (iscsi_refcnt_impl(rc_addr) != DCMD_OK) {
1323 return (DCMD_ERR);
1324 }
1325 idc->u.child.idc_rc_audit = 0;
1326 }
1327 }
1328
1329 if (idc->u.child.idc_portal) {
1330 if (idc->u.child.idc_tpg) {
1331 idc->idc_header = 1;
1332 }
1333
1334 avl_addr = addr + offsetof(iscsit_tpg_t, tpg_portal_list);
1335 if (mdb_pwalk("avl", iscsi_portal_walk_cb, idc,
1336 avl_addr) == -1) {
1337 mdb_warn("portal list walk failed");
1338 if (idc->u.child.idc_tpg) {
1339 (void) mdb_dec_indent(4);
1340 }
1341 return (DCMD_ERR);
1342 }
1343 }
1344
1345 if (idc->u.child.idc_tpg) {
1346 (void) mdb_dec_indent(4);
1347 idc->idc_header = 0;
1348 }
1349
1350 idc->u.child.idc_rc_audit = rc_audit;
1351 return (DCMD_OK);
1352 }
1353
1354 static int
iscsi_portal_impl(uintptr_t addr,iscsi_dcmd_ctrl_t * idc)1355 iscsi_portal_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc)
1356 {
1357 iscsit_portal_t portal;
1358 char portal_addr[PORTAL_STR_LEN];
1359 uintptr_t rc_addr;
1360
1361 if (idc->u.child.idc_portal) {
1362 /*
1363 * Read iscsit_portal_t
1364 */
1365 if (mdb_vread(&portal, sizeof (iscsit_portal_t), addr) !=
1366 sizeof (iscsit_portal_t)) {
1367 return (DCMD_ERR);
1368 }
1369
1370 /* Print portal data */
1371 if (idc->idc_header) {
1372 mdb_printf("%<u>%-?s %-?s %-30s%</u>\n",
1373 "iscsit_portal_t", "idm_svc_t", "IP:Port");
1374 idc->idc_header = 0;
1375 }
1376 sa_to_str(&portal.portal_addr, portal_addr);
1377 mdb_printf("%?p %?p %s\n", addr, portal.portal_svc,
1378 portal.portal_default ? "(Default)" : portal_addr);
1379
1380 if (idc->u.child.idc_rc_audit) {
1381 (void) mdb_inc_indent(4);
1382 mdb_printf("Reference History(portal_refcnt):\n");
1383 rc_addr = addr + offsetof(iscsit_portal_t,
1384 portal_refcnt);
1385 if (iscsi_refcnt_impl(rc_addr) != DCMD_OK) {
1386 return (DCMD_ERR);
1387 }
1388 (void) mdb_dec_indent(4);
1389 }
1390 }
1391
1392 return (DCMD_OK);
1393 }
1394
1395 static int
iscsi_sess_impl(uintptr_t addr,iscsi_dcmd_ctrl_t * idc)1396 iscsi_sess_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc)
1397 {
1398 iscsit_sess_t ist;
1399 iscsi_sess_t ini_sess;
1400 uintptr_t list_addr, states_addr, rc_addr;
1401 char ini_name[80];
1402 char tgt_name[80];
1403 int verbose, states, rc_audit;
1404
1405 if (idc->idc_ini) {
1406 if ((mdb_vread(&ini_sess, sizeof (iscsi_sess_t),
1407 (uintptr_t)addr)) != sizeof (iscsi_sess_t)) {
1408 mdb_warn("Failed to read initiator session\n");
1409 return (DCMD_ERR);
1410 }
1411 if (iscsi_print_ini_sess(addr, &ini_sess, idc) != DCMD_OK) {
1412 return (DCMD_ERR);
1413 }
1414 return (DCMD_OK);
1415 }
1416 /*
1417 * Read iscsit_sess_t
1418 */
1419 if (mdb_vread(&ist, sizeof (iscsit_sess_t), addr) !=
1420 sizeof (iscsit_sess_t)) {
1421 return (DCMD_ERR);
1422 }
1423
1424 /*
1425 * Brief output
1426 *
1427 * iscsit_sess_t pointer
1428 * iscsit_sess_t.ist_state/iscsit_sess_t.ist_ffp_conn_count
1429 * iscsit_sess_t.ist_tsih
1430 * iscsit_sess_t.ist_initiator_name
1431 */
1432
1433 verbose = idc->idc_verbose;
1434 states = idc->u.child.idc_states;
1435 rc_audit = idc->u.child.idc_rc_audit;
1436
1437 if (idc->u.child.idc_sess) {
1438 if (verbose) {
1439 /*
1440 * Read initiator name if available
1441 */
1442 if ((ist.ist_initiator_name == NULL) ||
1443 (mdb_readstr(ini_name, sizeof (ini_name),
1444 (uintptr_t)ist.ist_initiator_name) == -1)) {
1445 strcpy(ini_name, "N/A");
1446 }
1447
1448 /*
1449 * Read target name if available
1450 */
1451 if ((ist.ist_target_name == NULL) ||
1452 (mdb_readstr(tgt_name, sizeof (tgt_name),
1453 (uintptr_t)ist.ist_target_name) == -1)) {
1454 strcpy(tgt_name, "N/A");
1455 }
1456
1457 mdb_printf("Session %p\n", addr);
1458 mdb_printf("%16s: %d\n", "State",
1459 ist.ist_state);
1460 mdb_printf("%16s: %d\n", "Last State",
1461 ist.ist_last_state);
1462 mdb_printf("%16s: %d\n", "FFP Connections",
1463 ist.ist_ffp_conn_count);
1464 mdb_printf("%16s: %02x%02x%02x%02x%02x%02x\n", "ISID",
1465 ist.ist_isid[0], ist.ist_isid[1], ist.ist_isid[2],
1466 ist.ist_isid[3], ist.ist_isid[4], ist.ist_isid[5]);
1467 mdb_printf("%16s: 0x%04x\n", "TSIH",
1468 ist.ist_tsih);
1469 mdb_printf("%16s: %s\n", "Initiator IQN",
1470 ini_name);
1471 mdb_printf("%16s: %s\n", "Target IQN",
1472 tgt_name);
1473 mdb_printf("%16s: %08x\n", "ExpCmdSN",
1474 ist.ist_expcmdsn);
1475 mdb_printf("%16s: %08x\n", "MaxCmdSN",
1476 ist.ist_maxcmdsn);
1477
1478 idc->idc_verbose = 0;
1479 } else {
1480 /* Print session data */
1481 if (idc->idc_header) {
1482 mdb_printf("%<u>%-?s %10s %-12s %-6s%</u>\n",
1483 "iscsit_sess_t", "State/Conn", "ISID",
1484 "TSIH");
1485 }
1486 mdb_printf("%?p %4d/%-4d %02x%02x%02x%02x%02x%02x "
1487 "0x%04x\n", addr,
1488 ist.ist_state, ist.ist_ffp_conn_count,
1489 ist.ist_isid[0], ist.ist_isid[1], ist.ist_isid[2],
1490 ist.ist_isid[3], ist.ist_isid[4], ist.ist_isid[5],
1491 ist.ist_tsih);
1492 }
1493
1494 /*
1495 * Indent for any child structures
1496 */
1497 (void) mdb_inc_indent(4);
1498 }
1499
1500 /*
1501 * Print states if requested
1502 */
1503 if (idc->u.child.idc_sess && states) {
1504 states_addr = addr + offsetof(iscsit_sess_t, ist_state_audit);
1505
1506 mdb_printf("State History(ist_state_audit):\n");
1507 if (iscsi_sm_audit_impl(states_addr) != DCMD_OK)
1508 return (DCMD_ERR);
1509
1510 /* Don't print state history for child objects */
1511 idc->u.child.idc_states = 0;
1512 }
1513
1514 /*
1515 * Print refcnt audit data if requested
1516 */
1517 if (idc->u.child.idc_sess && rc_audit) {
1518 mdb_printf("Reference History(ist_refcnt):\n");
1519 rc_addr = addr +
1520 offsetof(iscsit_sess_t, ist_refcnt);
1521 if (iscsi_refcnt_impl(rc_addr) != DCMD_OK)
1522 return (DCMD_ERR);
1523
1524 /* Don't print audit data for child objects */
1525 idc->u.child.idc_rc_audit = 0;
1526 }
1527
1528 /* Any child objects to walk? */
1529 if (idc->u.child.idc_conn || idc->u.child.idc_task ||
1530 idc->u.child.idc_buffer) {
1531 /*
1532 * If a session has been printed enable headers for
1533 * any child structs.
1534 */
1535 if (idc->u.child.idc_sess) {
1536 idc->idc_header = 1;
1537 }
1538
1539 /* Walk conn list */
1540 list_addr = addr + offsetof(iscsit_sess_t, ist_conn_list);
1541 if (mdb_pwalk("list", iscsi_sess_conn_walk_cb, idc,
1542 list_addr) == -1) {
1543 mdb_warn("session conn list walk failed");
1544 (void) mdb_dec_indent(4);
1545 return (DCMD_ERR);
1546 }
1547 }
1548
1549 /* If a session was handled decrease indent and reset header. */
1550 if (idc->u.child.idc_sess) {
1551 idc->idc_header = 0;
1552 mdb_dec_indent(4);
1553 }
1554
1555 idc->idc_verbose = verbose;
1556 idc->u.child.idc_states = states;
1557 idc->u.child.idc_rc_audit = rc_audit;
1558
1559 return (DCMD_OK);
1560 }
1561
1562 static int
iscsi_print_ini_sess(uintptr_t addr,iscsi_sess_t * sess,iscsi_dcmd_ctrl_t * idc)1563 iscsi_print_ini_sess(uintptr_t addr, iscsi_sess_t *sess,
1564 iscsi_dcmd_ctrl_t *idc)
1565 {
1566
1567 int verbose, states;
1568 uintptr_t states_addr;
1569
1570 verbose = idc->idc_verbose;
1571 states = idc->u.child.idc_states;
1572
1573
1574 if (idc->u.child.idc_sess) {
1575 if (!idc->idc_verbose) {
1576 if (idc->idc_header) {
1577 mdb_printf("%<u>%-?s %-4s %-8s%</u>\n",
1578 "iscsi_sess_t", "Type", "State");
1579 }
1580 mdb_printf("%-19p %-4d %-8d\n", addr,
1581 sess->sess_type, sess->sess_state);
1582 } else {
1583 mdb_printf("Session %p\n", addr);
1584 mdb_printf("%22s: %d\n", "State",
1585 sess->sess_state);
1586 mdb_printf("%22s: %d\n", "Last State",
1587 sess->sess_prev_state);
1588 mdb_printf("%22s: %s\n", "Session Name",
1589 sess->sess_name);
1590 mdb_printf("%22s: %s\n", "Alias",
1591 sess->sess_alias);
1592 mdb_printf("%22s: %08x\n", "CmdSN",
1593 sess->sess_cmdsn);
1594 mdb_printf("%22s: %08x\n", "ExpCmdSN",
1595 sess->sess_expcmdsn);
1596 mdb_printf("%22s: %08x\n", "MaxCmdSN",
1597 sess->sess_maxcmdsn);
1598 mdb_printf("%22s: %p\n", "Pending Queue Head",
1599 sess->sess_queue_pending.head);
1600 mdb_printf("%22s: %p\n", "Completion Queue Head",
1601 sess->sess_queue_completion.head);
1602 mdb_printf("%22s: %p\n", "Connnection List Head",
1603 sess->sess_conn_list);
1604
1605 idc->idc_verbose = 0;
1606 }
1607
1608 /* Indent for any child structures */
1609 mdb_inc_indent(4);
1610
1611 if (idc->u.child.idc_states) {
1612 states_addr = (uintptr_t)addr +
1613 offsetof(iscsi_sess_t, sess_state_audit);
1614
1615 mdb_printf("State History(sess_state_audit):\n");
1616 if (iscsi_sm_audit_impl(states_addr) != DCMD_OK) {
1617 (void) mdb_dec_indent(4);
1618 return (DCMD_ERR);
1619 }
1620 idc->u.child.idc_states = 0;
1621 }
1622 }
1623
1624 if (idc->u.child.idc_lun && sess->sess_lun_list) {
1625 if (idc->u.child.idc_sess) {
1626 idc->idc_header = 1;
1627 }
1628
1629 if (mdb_pwalk("iscsi_ini_lun", iscsi_ini_lun_walk_cb, idc,
1630 (uintptr_t)sess->sess_lun_list) == -1) {
1631 mdb_warn("iscsi_ini_lun walk failed");
1632 (void) mdb_dec_indent(4);
1633 return (DCMD_ERR);
1634 }
1635 }
1636
1637
1638 /* If requested print the cmds in the session queue */
1639 if (idc->u.child.idc_cmd) {
1640
1641 /* If any other structs printed enable header */
1642 if (idc->u.child.idc_sess || idc->u.child.idc_lun) {
1643 idc->idc_header = 1;
1644 }
1645
1646 if (sess->sess_queue_pending.head) {
1647 if (mdb_pwalk("iscsi_ini_cmd", iscsi_ini_cmd_walk_cb,
1648 idc, (uintptr_t)sess->sess_queue_pending.head)
1649 == -1) {
1650 mdb_warn("list walk failed for iscsi cmds");
1651 }
1652 }
1653 if (sess->sess_queue_completion.head) {
1654 if (mdb_pwalk("iscsi_ini_cmd", iscsi_ini_cmd_walk_cb,
1655 idc, (uintptr_t)sess->sess_queue_completion.head)
1656 == -1) {
1657 mdb_warn("list walk failed for iscsi cmds");
1658 }
1659 }
1660 }
1661
1662 /* If connections or cmds requested walk the connections */
1663 if (idc->u.child.idc_conn || idc->u.child.idc_cmd) {
1664 /*
1665 * If idc_conn is not set don't enable header or the
1666 * commands may get extraneous headers.
1667 */
1668 if (idc->u.child.idc_conn) {
1669 idc->idc_header = 1;
1670 }
1671 if (mdb_pwalk("iscsi_ini_conn", iscsi_ini_conn_walk_cb, idc,
1672 (uintptr_t)sess->sess_conn_list) == -1) {
1673 mdb_warn("iscsi_ini_conn walk failed");
1674 return (DCMD_ERR);
1675 }
1676 }
1677
1678 /* If sessions were handled decrease indent and reset header */
1679 if (idc->u.child.idc_sess) {
1680 idc->idc_header = 0;
1681 mdb_dec_indent(4);
1682 }
1683
1684 idc->u.child.idc_states = states;
1685 idc->idc_verbose = verbose;
1686 return (DCMD_OK);
1687 }
1688
1689
1690 static int
iscsi_conn_impl(uintptr_t addr,iscsi_dcmd_ctrl_t * idc)1691 iscsi_conn_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc)
1692 {
1693 uintptr_t idm_global_addr, states_addr, rc_addr;
1694 uintptr_t task_addr, task_ptr;
1695 GElf_Sym sym;
1696 idm_task_t idt;
1697 idm_conn_t ic;
1698 iscsit_conn_t ict;
1699 iscsi_conn_t ini_conn;
1700 char *conn_type;
1701 int task_idx;
1702 char laddr[PORTAL_STR_LEN];
1703 char raddr[PORTAL_STR_LEN];
1704 int verbose, states, rc_audit;
1705
1706 /*
1707 * Get pointer to task table
1708 */
1709
1710 if (mdb_lookup_by_name("idm", &sym) == -1) {
1711 mdb_warn("failed to find symbol 'idm'");
1712 return (DCMD_ERR);
1713 }
1714
1715 idm_global_addr = (uintptr_t)sym.st_value;
1716
1717 if (mdb_vread(&task_ptr, sizeof (uintptr_t),
1718 idm_global_addr + offsetof(idm_global_t, idm_taskid_table)) !=
1719 sizeof (uintptr_t)) {
1720 mdb_warn("Failed to read address of task table");
1721 return (DCMD_ERR);
1722 }
1723
1724 /*
1725 * Read idm_conn_t
1726 */
1727 if (mdb_vread(&ic, sizeof (idm_conn_t), addr) != sizeof (idm_conn_t)) {
1728 return (DCMD_ERR);
1729 }
1730
1731 /*
1732 * If filter bits are set to only print targets or only initiators
1733 * skip entries of the other type.
1734 */
1735 if (!(idc->idc_ini && idc->idc_tgt) &&
1736 ((idc->idc_ini && (ic.ic_conn_type != CONN_TYPE_INI)) ||
1737 (idc->idc_tgt && (ic.ic_conn_type != CONN_TYPE_TGT)))) {
1738 return (DCMD_OK);
1739 }
1740
1741
1742 conn_type = (ic.ic_conn_type == CONN_TYPE_INI) ? "Ini" :
1743 (ic.ic_conn_type == CONN_TYPE_TGT) ? "Tgt" : "Unk";
1744
1745 /*
1746 * Brief output
1747 *
1748 * idm_conn_t pointer
1749 * idm_conn_t.ic_conn_type
1750 * idm_conn_t.ic_statet+idm_conn_t.ic_ffp
1751 */
1752
1753 verbose = idc->idc_verbose;
1754 states = idc->u.child.idc_states;
1755 rc_audit = idc->u.child.idc_rc_audit;
1756
1757 /*
1758 * If targets(-T) and/or initiators (-I) are specifically requested,
1759 * fetch the iscsit_conn_t and/or iscsi_conn_t struct as a sanity
1760 * check and for use below.
1761 */
1762 if (idc->idc_tgt && IDM_CONN_ISTGT(&ic)) {
1763 if (mdb_vread(&ict, sizeof (iscsit_conn_t),
1764 (uintptr_t)ic.ic_handle) !=
1765 sizeof (iscsit_conn_t)) {
1766 mdb_printf("Failed to read target connection "
1767 "handle data\n");
1768 return (DCMD_ERR);
1769 }
1770 }
1771
1772 if (idc->idc_ini && IDM_CONN_ISINI(&ic)) {
1773 if (mdb_vread(&ini_conn, sizeof (iscsi_conn_t),
1774 (uintptr_t)ic.ic_handle) !=
1775 sizeof (iscsi_conn_t)) {
1776 mdb_printf("Failed to read initiator "
1777 "connection handle data\n");
1778 return (DCMD_ERR);
1779 }
1780 }
1781
1782 if (idc->u.child.idc_conn) {
1783 if (idc->idc_verbose) {
1784 mdb_printf("IDM Conn %p\n", addr);
1785 if (ic.ic_conn_type == CONN_TYPE_TGT) {
1786 iscsi_print_iscsit_conn_data(&ic);
1787 } else {
1788 iscsi_print_ini_conn_data(&ic);
1789 }
1790 idc->idc_verbose = 0;
1791 } else {
1792 /* Print connection data */
1793 if (idc->idc_header) {
1794 mdb_printf("%<u>%-?s %-6s %-10s %12s%</u>\n",
1795 "idm_conn_t", "Type", "Transport",
1796 "State/FFP");
1797 }
1798 mdb_printf("%?p %-6s %-10s %6d/%-6d\n", addr, conn_type,
1799 (ic.ic_transport_type ==
1800 IDM_TRANSPORT_TYPE_ISER) ? "ISER_IB" :
1801 (ic.ic_transport_type ==
1802 IDM_TRANSPORT_TYPE_SOCKETS) ? "SOCKETS" :
1803 "N/A",
1804 ic.ic_state, ic.ic_ffp);
1805 if (idc->u.child.idc_print_ip) {
1806 sa_to_str(&ic.ic_laddr, laddr);
1807 sa_to_str(&ic.ic_raddr, raddr);
1808 mdb_printf(" L%s R%s\n",
1809 laddr, raddr);
1810 }
1811 }
1812
1813 /* Indent for any child structs */
1814 mdb_inc_indent(4);
1815 }
1816
1817 /*
1818 * Print states if requested
1819 */
1820 if (idc->u.child.idc_conn && states) {
1821 states_addr = addr + offsetof(idm_conn_t, ic_state_audit);
1822
1823 mdb_printf("State History(ic_state_audit):\n");
1824 if (iscsi_sm_audit_impl(states_addr) != DCMD_OK)
1825 return (DCMD_ERR);
1826
1827 /*
1828 * If targets are specifically requested show the
1829 * state audit for the target specific connection struct
1830 */
1831 if (idc->idc_tgt && IDM_CONN_ISTGT(&ic)) {
1832 states_addr = (uintptr_t)ic.ic_handle +
1833 offsetof(iscsit_conn_t, ict_login_sm) +
1834 offsetof(iscsit_conn_login_t, icl_state_audit);
1835
1836 mdb_printf("State History(icl_state_audit):\n");
1837 if (iscsi_sm_audit_impl(states_addr) != DCMD_OK) {
1838 return (DCMD_ERR);
1839 }
1840 }
1841
1842 /*
1843 * If initiators are specifically requested show the
1844 * state audit for the initiator specific connection struct
1845 */
1846 if (idc->idc_ini && IDM_CONN_ISINI(&ic)) {
1847 states_addr = (uintptr_t)ic.ic_handle +
1848 offsetof(iscsi_conn_t, conn_state_audit);
1849
1850 mdb_printf("State History(iscsi_conn_t "
1851 "conn_state_audit):\n");
1852 if (iscsi_sm_audit_impl(states_addr) != DCMD_OK) {
1853 return (DCMD_ERR);
1854 }
1855 }
1856
1857 /* Don't print state history for child objects */
1858 idc->u.child.idc_states = 0;
1859 }
1860
1861 /*
1862 * Print refcnt audit data for the connection struct if requested.
1863 */
1864 if (idc->u.child.idc_conn && rc_audit) {
1865 mdb_printf("Reference History(ic_refcnt):\n");
1866 rc_addr = addr + offsetof(idm_conn_t, ic_refcnt);
1867 if (iscsi_refcnt_impl(rc_addr) != DCMD_OK)
1868 return (DCMD_ERR);
1869
1870 /*
1871 * If targets are specifically requested show the
1872 * Refcounts for the target specific connection struct
1873 */
1874 if (idc->idc_tgt && IDM_CONN_ISTGT(&ic)) {
1875 mdb_printf("Reference History(ict_refcnt):\n");
1876 rc_addr = (uintptr_t)ic.ic_handle +
1877 offsetof(iscsit_conn_t, ict_refcnt);
1878 if (iscsi_refcnt_impl(rc_addr) != DCMD_OK) {
1879 return (DCMD_ERR);
1880 }
1881
1882 mdb_printf("Reference History(ict_dispatch_refcnt):\n");
1883 rc_addr = (uintptr_t)ic.ic_handle +
1884 offsetof(iscsit_conn_t, ict_dispatch_refcnt);
1885 if (iscsi_refcnt_impl(rc_addr) != DCMD_OK) {
1886 return (DCMD_ERR);
1887 }
1888 }
1889
1890 /* Don't print audit data for child objects */
1891 idc->u.child.idc_rc_audit = 0;
1892 }
1893
1894 task_idx = 0;
1895
1896 if (idc->u.child.idc_task || idc->u.child.idc_buffer) {
1897
1898 if (idc->u.child.idc_conn) {
1899 idc->idc_header = 1;
1900 }
1901
1902 while (task_idx < IDM_TASKIDS_MAX) {
1903 /*
1904 * Read the next idm_task_t
1905 */
1906 if (mdb_vread(&task_addr, sizeof (uintptr_t),
1907 task_ptr) != sizeof (uintptr_t)) {
1908 mdb_warn("Failed to read task pointer");
1909 return (DCMD_ERR);
1910 }
1911
1912 if (task_addr == 0) {
1913 task_ptr += sizeof (uintptr_t);
1914 task_idx++;
1915 continue;
1916 }
1917
1918 if (mdb_vread(&idt, sizeof (idm_task_t), task_addr)
1919 != sizeof (idm_task_t)) {
1920 mdb_warn("Failed to read task pointer");
1921 return (DCMD_ERR);
1922 }
1923
1924 if (((uintptr_t)idt.idt_ic == addr) &&
1925 (idt.idt_state != TASK_IDLE)) {
1926 if (iscsi_i_task_impl(&idt, task_addr, idc)
1927 == -1) {
1928 mdb_warn("Failed to walk connection "
1929 "task tree");
1930 return (DCMD_ERR);
1931 }
1932 }
1933
1934 task_ptr += sizeof (uintptr_t);
1935 task_idx++;
1936 }
1937 }
1938
1939 if (idc->idc_ini && IDM_CONN_ISINI(&ic) && idc->u.child.idc_cmd) {
1940 if (idc->u.child.idc_conn || idc->u.child.idc_task) {
1941 idc->idc_header = 1;
1942 }
1943 if (ini_conn.conn_queue_active.head &&
1944 (mdb_pwalk("iscsi_ini_cmd", iscsi_ini_cmd_walk_cb, idc,
1945 (uintptr_t)ini_conn.conn_queue_active.head) == -1)) {
1946 mdb_warn("list walk failed for iscsi cmds");
1947 }
1948 if (ini_conn.conn_queue_idm_aborting.head &&
1949 (mdb_pwalk("iscsi_ini_cmd", iscsi_ini_cmd_walk_cb, idc,
1950 (uintptr_t)ini_conn.conn_queue_idm_aborting.head) == -1)) {
1951 mdb_warn("list walk failed for iscsi cmds");
1952 }
1953 }
1954
1955 /*
1956 * If connection information was handled unset header and
1957 * decrease indent
1958 */
1959 if (idc->u.child.idc_conn) {
1960 idc->idc_header = 0;
1961 mdb_dec_indent(4);
1962 }
1963
1964 idc->idc_verbose = verbose;
1965 idc->u.child.idc_states = states;
1966 idc->u.child.idc_rc_audit = rc_audit;
1967
1968 return (DCMD_OK);
1969 }
1970
1971 static int
iscsi_svc_impl(uintptr_t addr,iscsi_dcmd_ctrl_t * idc)1972 iscsi_svc_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc)
1973 {
1974 idm_svc_t svc;
1975 iser_svc_t iser_svc;
1976 uintptr_t rc_addr;
1977
1978 if (mdb_vread(&svc, sizeof (idm_svc_t), addr) !=
1979 sizeof (idm_svc_t)) {
1980 return (DCMD_ERR);
1981 }
1982
1983 if (idc->u.child.idc_svc) {
1984 if (idc->idc_verbose) {
1985 mdb_printf("Service %p\n", addr);
1986 mdb_printf("%20s: %d\n", "Port",
1987 svc.is_svc_req.sr_port);
1988 mdb_printf("%20s: %d\n", "Online",
1989 svc.is_online);
1990 mdb_printf("%20s: %p\n", "Socket Service",
1991 svc.is_so_svc);
1992 mdb_printf("%20s: %p\n", "iSER Service",
1993 svc.is_iser_svc);
1994 } else {
1995 if (idc->idc_header) {
1996 mdb_printf("%<u>%-?s %-8s %-8s%</u>\n",
1997 "idm_svc_t", "Port", "Online");
1998 idc->idc_header = 0;
1999 }
2000
2001 mdb_printf("%?p %-8d %-8d\n", addr,
2002 svc.is_svc_req.sr_port, svc.is_online);
2003 }
2004
2005 if (idc->u.child.idc_rc_audit) {
2006 (void) mdb_inc_indent(4);
2007 mdb_printf("Reference History(is_refcnt):\n");
2008 rc_addr = addr + offsetof(idm_svc_t, is_refcnt);
2009 if (iscsi_refcnt_impl(rc_addr) != DCMD_OK) {
2010 (void) mdb_dec_indent(4);
2011 return (DCMD_ERR);
2012 }
2013
2014 if (svc.is_iser_svc != NULL) {
2015 mdb_printf("Reference History"
2016 "(iser_svc is_refcnt):\n");
2017
2018 /* Sanity check the iser svc struct */
2019 if (mdb_vread(&iser_svc, sizeof (iser_svc_t),
2020 (uintptr_t)svc.is_iser_svc) !=
2021 sizeof (iser_svc_t)) {
2022 return (DCMD_ERR);
2023 }
2024
2025 rc_addr = (uintptr_t)svc.is_iser_svc +
2026 offsetof(iser_svc_t, is_refcnt);
2027
2028 if (iscsi_refcnt_impl(rc_addr) != DCMD_OK) {
2029 return (DCMD_ERR);
2030 }
2031 }
2032 (void) mdb_dec_indent(4);
2033 }
2034 }
2035 return (DCMD_OK);
2036 }
2037
2038 static void
iscsi_print_iscsit_conn_data(idm_conn_t * ic)2039 iscsi_print_iscsit_conn_data(idm_conn_t *ic)
2040 {
2041 iscsit_conn_t ict;
2042 char *csg;
2043 char *nsg;
2044
2045 iscsi_print_idm_conn_data(ic);
2046
2047 if (mdb_vread(&ict, sizeof (iscsit_conn_t),
2048 (uintptr_t)ic->ic_handle) != sizeof (iscsit_conn_t)) {
2049 mdb_printf("**Failed to read conn private data\n");
2050 return;
2051 }
2052
2053 mdb_printf("%20s: %p\n", "iSCSIT TGT Conn",
2054 ic->ic_handle);
2055
2056 if (ict.ict_login_sm.icl_login_state != ILS_LOGIN_DONE) {
2057 switch (ict.ict_login_sm.icl_login_csg) {
2058 case ISCSI_SECURITY_NEGOTIATION_STAGE:
2059 csg = "Security";
2060 break;
2061 case ISCSI_OP_PARMS_NEGOTIATION_STAGE:
2062 csg = "Operational";
2063 break;
2064 case ISCSI_FULL_FEATURE_PHASE:
2065 csg = "FFP";
2066 break;
2067 default:
2068 csg = "Unknown";
2069 }
2070 switch (ict.ict_login_sm.icl_login_nsg) {
2071 case ISCSI_SECURITY_NEGOTIATION_STAGE:
2072 nsg = "Security";
2073 break;
2074 case ISCSI_OP_PARMS_NEGOTIATION_STAGE:
2075 nsg = "Operational";
2076 break;
2077 case ISCSI_FULL_FEATURE_PHASE:
2078 nsg = "FFP";
2079 break;
2080 default:
2081 nsg = "Unknown";
2082 }
2083 mdb_printf("%20s: %d\n", "Login State",
2084 ict.ict_login_sm.icl_login_state);
2085 mdb_printf("%20s: %d\n", "Login Last State",
2086 ict.ict_login_sm.icl_login_last_state);
2087 mdb_printf("%20s: %s\n", "CSG", csg);
2088 mdb_printf("%20s: %s\n", "NSG", nsg);
2089 mdb_printf("%20s: %d\n", "Transit",
2090 ict.ict_login_sm.icl_login_transit >> 7);
2091 mdb_printf("%20s: %p\n", "Request nvlist",
2092 ict.ict_login_sm.icl_request_nvlist);
2093 mdb_printf("%20s: %p\n", "Response nvlist",
2094 ict.ict_login_sm.icl_response_nvlist);
2095 mdb_printf("%20s: %p\n", "Negotiated nvlist",
2096 ict.ict_login_sm.icl_negotiated_values);
2097 if (ict.ict_login_sm.icl_login_state == ILS_LOGIN_ERROR) {
2098 mdb_printf("%20s: 0x%02x\n", "Error Class",
2099 ict.ict_login_sm.icl_login_resp_err_class);
2100 mdb_printf("%20s: 0x%02x\n", "Error Detail",
2101 ict.ict_login_sm.icl_login_resp_err_detail);
2102 }
2103 }
2104 mdb_printf("%20s: 0x%04x\n", "CID", ict.ict_cid);
2105 mdb_printf("%20s: 0x%08x\n", "StatSN", ict.ict_statsn);
2106 }
2107
2108 static void
iscsi_print_ini_conn_data(idm_conn_t * ic)2109 iscsi_print_ini_conn_data(idm_conn_t *ic)
2110 {
2111 iscsi_conn_t ini_conn;
2112
2113 iscsi_print_idm_conn_data(ic);
2114
2115 if (mdb_vread(&ini_conn, sizeof (iscsi_conn_t),
2116 (uintptr_t)ic->ic_handle) != sizeof (iscsi_conn_t)) {
2117 mdb_printf("Failed to read conn private data\n");
2118 return;
2119 }
2120
2121 mdb_printf("%20s: %p\n", "iSCSI Ini Conn",
2122 ic->ic_handle);
2123 mdb_printf("%20s: %p\n", "Parent Session",
2124 ini_conn.conn_sess);
2125 mdb_printf("%20s: %d\n", "Conn State",
2126 ini_conn.conn_state);
2127 mdb_printf("%20s: %d\n", "Last Conn State",
2128 ini_conn.conn_prev_state);
2129
2130 mdb_printf("%20s: %d\n", "Login Stage",
2131 ini_conn.conn_current_stage);
2132 mdb_printf("%20s: %d\n", "Next Login Stage",
2133 ini_conn.conn_next_stage);
2134
2135 mdb_printf("%20s: 0x%08x\n", "Expected StatSN",
2136 ini_conn.conn_expstatsn);
2137 mdb_printf("%20s: %p\n", "Active Queue Head",
2138 ini_conn.conn_queue_active.head);
2139 mdb_printf("%20s: %d\n", "Abort Queue Head",
2140 ini_conn.conn_queue_idm_aborting.head);
2141 }
2142
2143 static void
iscsi_print_idm_conn_data(idm_conn_t * ic)2144 iscsi_print_idm_conn_data(idm_conn_t *ic)
2145 {
2146 char laddr[PORTAL_STR_LEN];
2147 char raddr[PORTAL_STR_LEN];
2148
2149 sa_to_str(&ic->ic_laddr, laddr);
2150 sa_to_str(&ic->ic_raddr, raddr);
2151
2152 mdb_printf("%20s: %s\n", "Conn Type",
2153 ((ic->ic_conn_type == CONN_TYPE_TGT) ? "Target" :
2154 ((ic->ic_conn_type == CONN_TYPE_INI) ? "Initiator" :
2155 "Unknown")));
2156 if (ic->ic_conn_type == CONN_TYPE_TGT) {
2157 mdb_printf("%20s: %p\n", "Svc. Binding",
2158 ic->ic_svc_binding);
2159 }
2160 mdb_printf("%20s: %s\n", "Transport",
2161 (ic->ic_transport_type == IDM_TRANSPORT_TYPE_ISER) ? "ISER_IB" :
2162 (ic->ic_transport_type == IDM_TRANSPORT_TYPE_SOCKETS) ? "SOCKETS" :
2163 "N/A");
2164
2165 mdb_printf("%20s: %s\n", "Local IP", laddr);
2166 mdb_printf("%20s: %s\n", "Remote IP", raddr);
2167 mdb_printf("%20s: %d\n", "State",
2168 ic->ic_state);
2169 mdb_printf("%20s: %d\n", "Last State",
2170 ic->ic_last_state);
2171 mdb_printf("%20s: %d %s\n", "Refcount",
2172 ic->ic_refcnt.ir_refcnt,
2173 (ic->ic_refcnt.ir_waiting == REF_NOWAIT) ? "" :
2174 ((ic->ic_refcnt.ir_waiting == REF_WAIT_SYNC) ? "REF_WAIT_SYNC" :
2175 ((ic->ic_refcnt.ir_waiting == REF_WAIT_ASYNC) ? "REF_WAIT_ASYNC" :
2176 "UNKNOWN")));
2177 }
2178
2179 static int
iscsi_i_task_impl(idm_task_t * idt,uintptr_t addr,iscsi_dcmd_ctrl_t * idc)2180 iscsi_i_task_impl(idm_task_t *idt, uintptr_t addr, iscsi_dcmd_ctrl_t *idc)
2181 {
2182 uintptr_t list_addr, rc_addr;
2183 idm_conn_type_t conn_type;
2184 int verbose, states, rc_audit;
2185
2186 conn_type = idm_conn_type((uintptr_t)idt->idt_ic);
2187
2188 verbose = idc->idc_verbose;
2189 states = idc->u.child.idc_states;
2190 rc_audit = idc->u.child.idc_rc_audit;
2191
2192 if (idc->u.child.idc_task) {
2193 if (verbose) {
2194 mdb_printf("Task %p\n", addr);
2195 (void) mdb_inc_indent(2);
2196 if (conn_type == CONN_TYPE_TGT) {
2197 iscsi_print_iscsit_task_data(idt);
2198 }
2199 (void) mdb_dec_indent(2);
2200 } else {
2201 /* Print task data */
2202 if (idc->idc_header) {
2203 mdb_printf(
2204 "%<u>%-?s %-16s %-4s %-8s %-8s%</u>\n",
2205 "Tasks:", "State", "Ref",
2206 (conn_type == CONN_TYPE_TGT ? "TTT" :
2207 (conn_type == CONN_TYPE_INI ? "ITT" :
2208 "TT")), "Handle");
2209 }
2210 mdb_printf("%?p %-16s %04x %08x %08x\n", addr,
2211 idm_ts_name[idt->idt_state],
2212 idt->idt_refcnt.ir_refcnt,
2213 idt->idt_tt, idt->idt_client_handle);
2214 }
2215 }
2216 idc->idc_header = 0;
2217 idc->idc_verbose = 0;
2218
2219 /*
2220 * Print states if requested
2221 */
2222 #if 0
2223 if (states) {
2224 states_addr = addr + offsetof(idm_task_t, idt_state_audit);
2225
2226 (void) mdb_inc_indent(4);
2227 mdb_printf("State History(idt_state_audit):\n");
2228 if (iscsi_sm_audit_impl(states_addr) != DCMD_OK)
2229 return (DCMD_ERR);
2230
2231 /* Don't print state history for child objects */
2232 idc->u.child.idc_states = 0;
2233 (void) mdb_dec_indent(4);
2234 }
2235 #endif
2236
2237 /*
2238 * Print refcnt audit data if requested
2239 */
2240 if (rc_audit) {
2241 (void) mdb_inc_indent(4);
2242 mdb_printf("Reference History(idt_refcnt):\n");
2243 rc_addr = addr +
2244 offsetof(idm_task_t, idt_refcnt);
2245 if (iscsi_refcnt_impl(rc_addr) != DCMD_OK)
2246 return (DCMD_ERR);
2247
2248 /* Don't print audit data for child objects */
2249 idc->u.child.idc_rc_audit = 0;
2250 (void) mdb_dec_indent(4);
2251 }
2252
2253
2254 /*
2255 * Buffers are leaf objects and always get headers so the
2256 * user can discern between in and out buffers.
2257 */
2258 if (idc->u.child.idc_buffer) {
2259 /* Walk in buffer list */
2260 (void) mdb_inc_indent(2);
2261 mdb_printf("In buffers:\n");
2262 idc->idc_header = 1;
2263 (void) mdb_inc_indent(2);
2264 list_addr = addr + offsetof(idm_task_t, idt_inbufv);
2265 if (mdb_pwalk("list", iscsi_buffer_walk_cb, idc, list_addr) ==
2266 -1) {
2267 mdb_warn("list walk failed for task in buffers");
2268 (void) mdb_dec_indent(4);
2269 return (DCMD_ERR);
2270 }
2271 (void) mdb_dec_indent(2);
2272 /* Walk out buffer list */
2273 mdb_printf("Out buffers:\n");
2274 idc->idc_header = 1;
2275 (void) mdb_inc_indent(2);
2276 list_addr = addr + offsetof(idm_task_t, idt_outbufv);
2277 if (mdb_pwalk("list", iscsi_buffer_walk_cb, idc, list_addr) ==
2278 -1) {
2279 mdb_warn("list walk failed for task out buffers\n");
2280 (void) mdb_dec_indent(2);
2281 return (DCMD_ERR);
2282 }
2283 (void) mdb_dec_indent(4);
2284 }
2285
2286 idc->idc_verbose = verbose;
2287 idc->u.child.idc_states = states;
2288 idc->u.child.idc_rc_audit = rc_audit;
2289
2290 return (DCMD_OK);
2291 }
2292
2293 static int
iscsi_task_impl(uintptr_t addr,iscsi_dcmd_ctrl_t * idc)2294 iscsi_task_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc)
2295 {
2296 idm_task_t idt;
2297
2298 /*
2299 * Read idm_conn_t
2300 */
2301 if (mdb_vread(&idt, sizeof (idm_task_t), addr) != sizeof (idm_task_t)) {
2302 return (DCMD_ERR);
2303 }
2304
2305 return (iscsi_i_task_impl(&idt, addr, idc));
2306 }
2307
2308 #define ISCSI_CDB_INDENT 16
2309
2310 static void
iscsi_print_iscsit_task_data(idm_task_t * idt)2311 iscsi_print_iscsit_task_data(idm_task_t *idt)
2312 {
2313 iscsit_task_t itask;
2314 boolean_t good_scsi_task = B_TRUE;
2315 scsi_task_t scsi_task;
2316
2317 if (mdb_vread(&itask, sizeof (iscsit_task_t),
2318 (uintptr_t)idt->idt_private) != sizeof (iscsit_task_t)) {
2319 mdb_printf("**Failed to read idt_private data\n");
2320 return;
2321 }
2322
2323 if (mdb_vread(&scsi_task, sizeof (scsi_task_t),
2324 (uintptr_t)itask.it_stmf_task) != sizeof (scsi_task_t)) {
2325 good_scsi_task = B_FALSE;
2326 }
2327
2328 mdb_printf("%20s: %s(%d)\n", "State",
2329 idt->idt_state > TASK_MAX_STATE ?
2330 "UNKNOWN" : idm_ts_name[idt->idt_state],
2331 idt->idt_state);
2332 mdb_printf("%20s: %d/%d\n", "STMF abort/IDM aborted",
2333 itask.it_stmf_abort, itask.it_aborted);
2334 mdb_printf("%20s: %p/%p/%p%s\n",
2335 "iscsit/STMF/LU", idt->idt_private,
2336 itask.it_stmf_task, good_scsi_task ? scsi_task.task_lu_private : 0,
2337 good_scsi_task ? "" : "**");
2338 if (good_scsi_task) {
2339 mdb_printf("%20s: %08x/%08x\n", "ITT/TTT",
2340 itask.it_itt, itask.it_ttt);
2341 mdb_printf("%20s: %08x\n", "CmdSN",
2342 itask.it_cmdsn);
2343 mdb_printf("%20s: %02x %02x %02x %02x %02x %02x %02x %02x\n",
2344 "LU number",
2345 scsi_task.task_lun_no[0], scsi_task.task_lun_no[1],
2346 scsi_task.task_lun_no[2], scsi_task.task_lun_no[3],
2347 scsi_task.task_lun_no[4], scsi_task.task_lun_no[5],
2348 scsi_task.task_lun_no[6], scsi_task.task_lun_no[7]);
2349 mdb_printf(" CDB (%d bytes):\n",
2350 scsi_task.task_cdb_length);
2351 (void) mdb_inc_indent(ISCSI_CDB_INDENT);
2352 if (mdb_dumpptr((uintptr_t)scsi_task.task_cdb,
2353 scsi_task.task_cdb_length,
2354 MDB_DUMP_RELATIVE | MDB_DUMP_TRIM |
2355 MDB_DUMP_GROUP(1), NULL, NULL)) {
2356 mdb_printf("** Invalid CDB addr (%p)\n",
2357 scsi_task.task_cdb);
2358 }
2359 (void) mdb_dec_indent(ISCSI_CDB_INDENT);
2360 mdb_printf("%20s: %d/%d\n", "STMF cur/max bufs",
2361 scsi_task.task_cur_nbufs,
2362 scsi_task.task_max_nbufs);
2363 mdb_printf("%20s: 0x%08x/0x%08x/0x%08x\n", "Bytes Exp/Cmd/Done",
2364 scsi_task.task_expected_xfer_length,
2365 scsi_task.task_cmd_xfer_length,
2366 scsi_task.task_nbytes_transferred);
2367 mdb_printf("%20s: 0x%x/0x%x\n", "TX-ini start/done",
2368 idt->idt_tx_to_ini_start,
2369 idt->idt_tx_to_ini_done);
2370 mdb_printf("%20s: 0x%x/0x%x\n", "RX-ini start/done",
2371 idt->idt_rx_from_ini_start,
2372 idt->idt_rx_from_ini_done);
2373 }
2374 }
2375
2376 static int
iscsi_print_ini_lun(uintptr_t addr,const iscsi_lun_t * lun,iscsi_dcmd_ctrl_t * idc)2377 iscsi_print_ini_lun(uintptr_t addr, const iscsi_lun_t *lun,
2378 iscsi_dcmd_ctrl_t *idc)
2379 {
2380
2381 if (idc->u.child.idc_lun) {
2382 if (idc->idc_header) {
2383 mdb_printf("%<u>%-?s %-5s %-10s%</u>\n",
2384 "iscsi_lun_t", "State", "Lun Number");
2385 idc->idc_header = 0;
2386 }
2387 mdb_printf("%?p %-5d %-10d\n", addr,
2388 lun->lun_state, lun->lun_num);
2389 }
2390 return (DCMD_OK);
2391 }
2392
2393 static int
iscsi_print_ini_cmd(uintptr_t addr,const iscsi_cmd_t * cmd,iscsi_dcmd_ctrl_t * idc)2394 iscsi_print_ini_cmd(uintptr_t addr, const iscsi_cmd_t *cmd,
2395 iscsi_dcmd_ctrl_t *idc)
2396 {
2397
2398 uintptr_t states_addr;
2399
2400 if (idc->idc_header) {
2401 mdb_printf("%<u>%-?s %-?s %4s %6s/%-6s %-?s%</u>\n",
2402 "iscsi_cmd_t", "idm_task_t", "Type",
2403 "State", "Prev", "iscsi_lun_t");
2404 idc->idc_header = 0;
2405 }
2406
2407 mdb_printf("%?p %?p %4d %6d/%-6d %?p\n",
2408 addr, cmd->cmd_itp, cmd->cmd_type, cmd->cmd_state,
2409 cmd->cmd_prev_state, cmd->cmd_lun);
2410
2411 /*
2412 * Print states if requested
2413 */
2414 if (idc->u.child.idc_states) {
2415 states_addr = addr + offsetof(iscsi_cmd_t, cmd_state_audit);
2416
2417 (void) mdb_inc_indent(4);
2418 mdb_printf("State History(cmd_state_audit):\n");
2419 if (iscsi_sm_audit_impl(states_addr) != DCMD_OK)
2420 return (DCMD_ERR);
2421 idc->u.child.idc_states = 0;
2422 (void) mdb_dec_indent(4);
2423 }
2424 return (DCMD_OK);
2425 }
2426
2427 static int
iscsi_buffer_impl(uintptr_t addr,iscsi_dcmd_ctrl_t * idc)2428 iscsi_buffer_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc)
2429 {
2430 idm_buf_t idb;
2431
2432 /*
2433 * Read idm_buf_t
2434 */
2435 if (mdb_vread(&idb, sizeof (idm_buf_t), addr) != sizeof (idm_buf_t)) {
2436 return (DCMD_ERR);
2437 }
2438
2439
2440 if (idc->idc_header) {
2441 mdb_printf("%<u>%-?s %?s/%-8s %8s %8s %8s%</u>\n",
2442 "idm_buf_t", "Mem Rgn", "Length",
2443 "Rel Off", "Xfer Len", "Exp. Off");
2444 idc->idc_header = 0;
2445 }
2446
2447 /* Print buffer data */
2448 mdb_printf("%?p %?p/%08x %8x %8x %08x\n", addr,
2449 idb.idb_buf, idb.idb_buflen,
2450 idb.idb_bufoffset, idb.idb_xfer_len,
2451 idb.idb_exp_offset);
2452
2453
2454 /* Buffers are leaf objects */
2455
2456 return (DCMD_OK);
2457 }
2458
2459 static int
iscsi_refcnt_impl(uintptr_t addr)2460 iscsi_refcnt_impl(uintptr_t addr)
2461 {
2462 idm_refcnt_t refcnt;
2463 refcnt_audit_buf_t *anb;
2464 int ctr;
2465
2466 /*
2467 * Print refcnt info
2468 */
2469 if (mdb_vread(&refcnt, sizeof (idm_refcnt_t), addr) !=
2470 sizeof (idm_refcnt_t)) {
2471 mdb_warn("read refcnt failed");
2472 return (DCMD_ERR);
2473 }
2474
2475 anb = &refcnt.ir_audit_buf;
2476
2477 ctr = anb->anb_max_index + 1;
2478 anb->anb_index--;
2479 anb->anb_index &= anb->anb_max_index;
2480
2481 while (ctr) {
2482 refcnt_audit_record_t *anr;
2483
2484 anr = anb->anb_records + anb->anb_index;
2485
2486 if (anr->anr_depth) {
2487 char c[MDB_SYM_NAMLEN];
2488 GElf_Sym sym;
2489 int i;
2490
2491 mdb_printf("\nRefCnt: %u\t", anr->anr_refcnt);
2492
2493 for (i = 0; i < anr->anr_depth; i++) {
2494 if (mdb_lookup_by_addr(anr->anr_stack[i],
2495 MDB_SYM_FUZZY, c, sizeof (c),
2496 &sym) == -1) {
2497 continue;
2498 }
2499 mdb_printf("%s+0x%1x", c,
2500 anr->anr_stack[i] -
2501 (uintptr_t)sym.st_value);
2502 ++i;
2503 break;
2504 }
2505
2506 while (i < anr->anr_depth) {
2507 if (mdb_lookup_by_addr(anr->anr_stack[i],
2508 MDB_SYM_FUZZY, c, sizeof (c),
2509 &sym) == -1) {
2510 ++i;
2511 continue;
2512 }
2513 mdb_printf("\n\t\t%s+0x%1x", c,
2514 anr->anr_stack[i] -
2515 (uintptr_t)sym.st_value);
2516 ++i;
2517 }
2518 mdb_printf("\n");
2519 }
2520 anb->anb_index--;
2521 anb->anb_index &= anb->anb_max_index;
2522 ctr--;
2523 }
2524
2525 return (DCMD_OK);
2526 }
2527
2528 static int
iscsi_sm_audit_impl(uintptr_t addr)2529 iscsi_sm_audit_impl(uintptr_t addr)
2530 {
2531 sm_audit_buf_t audit_buf;
2532 int ctr;
2533 const char *event_name;
2534 const char *state_name;
2535 const char *new_state_name;
2536 char ts_string[40];
2537 /*
2538 * Print refcnt info
2539 */
2540 if (mdb_vread(&audit_buf, sizeof (sm_audit_buf_t), addr) !=
2541 sizeof (sm_audit_buf_t)) {
2542 mdb_warn("failed to read audit buf");
2543 return (DCMD_ERR);
2544 }
2545
2546 ctr = audit_buf.sab_max_index + 1;
2547 audit_buf.sab_index++;
2548 audit_buf.sab_index &= audit_buf.sab_max_index;
2549
2550 while (ctr) {
2551 sm_audit_record_t *sar;
2552
2553 sar = audit_buf.sab_records + audit_buf.sab_index;
2554
2555 iscsi_format_timestamp(ts_string, 40, &sar->sar_timestamp);
2556
2557 switch (sar->sar_type) {
2558 case SAR_STATE_EVENT:
2559 switch (sar->sar_sm_type) {
2560 case SAS_IDM_CONN:
2561 state_name =
2562 iscsi_idm_conn_state(sar->sar_state);
2563 event_name =
2564 iscsi_idm_conn_event(sar->sar_event);
2565 break;
2566 case SAS_ISCSIT_TGT:
2567 state_name =
2568 iscsi_iscsit_tgt_state(sar->sar_state);
2569 event_name =
2570 iscsi_iscsit_tgt_event(sar->sar_event);
2571 break;
2572 case SAS_ISCSIT_SESS:
2573 state_name =
2574 iscsi_iscsit_sess_state(sar->sar_state);
2575 event_name =
2576 iscsi_iscsit_sess_event(sar->sar_event);
2577 break;
2578 case SAS_ISCSIT_LOGIN:
2579 state_name =
2580 iscsi_iscsit_login_state(sar->sar_state);
2581 event_name =
2582 iscsi_iscsit_login_event(sar->sar_event);
2583 break;
2584 case SAS_ISCSI_CMD:
2585 state_name =
2586 iscsi_iscsi_cmd_state(sar->sar_state);
2587 event_name=
2588 iscsi_iscsi_cmd_event(sar->sar_event);
2589 break;
2590 case SAS_ISCSI_SESS:
2591 state_name =
2592 iscsi_iscsi_sess_state(sar->sar_state);
2593 event_name=
2594 iscsi_iscsi_sess_event(sar->sar_event);
2595 break;
2596 case SAS_ISCSI_CONN:
2597 state_name =
2598 iscsi_iscsi_conn_state(sar->sar_state);
2599 event_name=
2600 iscsi_iscsi_conn_event(sar->sar_event);
2601 break;
2602 default:
2603 state_name = event_name = "N/A";
2604 break;
2605 }
2606 mdb_printf("%s|%s (%d)\n\t%9s %s (%d) %p\n",
2607 ts_string, state_name, sar->sar_state,
2608 "Event", event_name,
2609 sar->sar_event, sar->sar_event_info);
2610
2611 break;
2612 case SAR_STATE_CHANGE:
2613 switch (sar->sar_sm_type) {
2614 case SAS_IDM_CONN:
2615 state_name =
2616 iscsi_idm_conn_state(sar->sar_state);
2617 new_state_name =
2618 iscsi_idm_conn_state(sar->sar_new_state);
2619 break;
2620 case SAS_IDM_TASK:
2621 state_name =
2622 iscsi_idm_task_state(sar->sar_state);
2623 new_state_name =
2624 iscsi_idm_task_state(sar->sar_new_state);
2625 break;
2626 case SAS_ISCSIT_TGT:
2627 state_name =
2628 iscsi_iscsit_tgt_state(sar->sar_state);
2629 new_state_name =
2630 iscsi_iscsit_tgt_state(sar->sar_new_state);
2631 break;
2632 case SAS_ISCSIT_SESS:
2633 state_name =
2634 iscsi_iscsit_sess_state(sar->sar_state);
2635 new_state_name =
2636 iscsi_iscsit_sess_state(sar->sar_new_state);
2637 break;
2638 case SAS_ISCSIT_LOGIN:
2639 state_name =
2640 iscsi_iscsit_login_state(sar->sar_state);
2641 new_state_name =
2642 iscsi_iscsit_login_state(
2643 sar->sar_new_state);
2644 break;
2645 case SAS_ISCSI_CMD:
2646 state_name =
2647 iscsi_iscsi_cmd_state(sar->sar_state);
2648 new_state_name=
2649 iscsi_iscsi_cmd_state(sar->sar_new_state);
2650 break;
2651 case SAS_ISCSI_SESS:
2652 state_name =
2653 iscsi_iscsi_sess_state(sar->sar_state);
2654 new_state_name=
2655 iscsi_iscsi_sess_state(sar->sar_new_state);
2656 break;
2657 case SAS_ISCSI_CONN:
2658 state_name =
2659 iscsi_iscsi_conn_state(sar->sar_state);
2660 new_state_name=
2661 iscsi_iscsi_conn_state(sar->sar_new_state);
2662 break;
2663 case SAS_ISCSI_LOGIN:
2664 state_name =
2665 iscsi_iscsi_login_state(sar->sar_state);
2666 new_state_name=
2667 iscsi_iscsi_login_state(sar->sar_new_state);
2668 break;
2669 default:
2670 state_name = new_state_name = "N/A";
2671 break;
2672 }
2673 mdb_printf("%s|%s (%d)\n\t%9s %s (%d)\n",
2674 ts_string, state_name, sar->sar_state,
2675 "New State", new_state_name, sar->sar_new_state);
2676
2677 break;
2678 default:
2679 break;
2680 }
2681
2682 audit_buf.sab_index++;
2683 audit_buf.sab_index &= audit_buf.sab_max_index;
2684 ctr--;
2685 }
2686
2687 return (DCMD_OK);
2688 }
2689
2690 static const char *
iscsi_idm_conn_event(unsigned int event)2691 iscsi_idm_conn_event(unsigned int event)
2692 {
2693 return ((event < CE_MAX_EVENT) ? idm_ce_name[event] : "N/A");
2694 }
2695
2696 static const char *
iscsi_iscsit_tgt_event(unsigned int event)2697 iscsi_iscsit_tgt_event(unsigned int event)
2698 {
2699 return ((event < TE_MAX_EVENT) ? iscsit_te_name[event] : "N/A");
2700 }
2701
2702 static const char *
iscsi_iscsit_sess_event(unsigned int event)2703 iscsi_iscsit_sess_event(unsigned int event)
2704 {
2705 return ((event < SE_MAX_EVENT) ? iscsit_se_name[event] : "N/A");
2706 }
2707
2708 static const char *
iscsi_iscsit_login_event(unsigned int event)2709 iscsi_iscsit_login_event(unsigned int event)
2710 {
2711 return ((event < ILE_MAX_EVENT) ? iscsit_ile_name[event] : "N/A");
2712 }
2713
2714 static const char *
iscsi_iscsi_cmd_event(unsigned int event)2715 iscsi_iscsi_cmd_event(unsigned int event)
2716 {
2717 return ((event < ISCSI_CMD_EVENT_MAX) ?
2718 iscsi_cmd_event_names[event] : "N/A");
2719 }
2720
2721 static const char *
iscsi_iscsi_sess_event(unsigned int event)2722 iscsi_iscsi_sess_event(unsigned int event)
2723 {
2724
2725 return ((event < ISCSI_SESS_EVENT_MAX) ?
2726 iscsi_sess_event_names[event] : "N/A");
2727 }
2728
2729 static const char *
iscsi_idm_conn_state(unsigned int state)2730 iscsi_idm_conn_state(unsigned int state)
2731 {
2732 return ((state < CS_MAX_STATE) ? idm_cs_name[state] : "N/A");
2733 }
2734
2735 static const char *
iscsi_iscsi_conn_event(unsigned int event)2736 iscsi_iscsi_conn_event(unsigned int event)
2737 {
2738
2739 return ((event < CN_MAX) ? idm_cn_strings[event] : "N/A");
2740 }
2741
2742 /*ARGSUSED*/
2743 static const char *
iscsi_idm_task_state(unsigned int state)2744 iscsi_idm_task_state(unsigned int state)
2745 {
2746 return ("N/A");
2747 }
2748
2749 static const char *
iscsi_iscsit_tgt_state(unsigned int state)2750 iscsi_iscsit_tgt_state(unsigned int state)
2751 {
2752 return ((state < TS_MAX_STATE) ? iscsit_ts_name[state] : "N/A");
2753 }
2754
2755 static const char *
iscsi_iscsit_sess_state(unsigned int state)2756 iscsi_iscsit_sess_state(unsigned int state)
2757 {
2758 return ((state < SS_MAX_STATE) ? iscsit_ss_name[state] : "N/A");
2759 }
2760
2761 static const char *
iscsi_iscsit_login_state(unsigned int state)2762 iscsi_iscsit_login_state(unsigned int state)
2763 {
2764 return ((state < ILS_MAX_STATE) ? iscsit_ils_name[state] : "N/A");
2765 }
2766
2767 static const char *
iscsi_iscsi_cmd_state(unsigned int state)2768 iscsi_iscsi_cmd_state(unsigned int state)
2769 {
2770 return ((state < ISCSI_CMD_STATE_MAX) ?
2771 iscsi_cmd_state_names[state] : "N/A");
2772 }
2773
2774 static const char *
iscsi_iscsi_sess_state(unsigned int state)2775 iscsi_iscsi_sess_state(unsigned int state)
2776 {
2777 return ((state < ISCSI_SESS_STATE_MAX) ?
2778 iscsi_sess_state_names[state] : "N/A");
2779 }
2780
2781 static const char *
iscsi_iscsi_conn_state(unsigned int state)2782 iscsi_iscsi_conn_state(unsigned int state)
2783 {
2784 return ((state < ISCSI_CONN_STATE_MAX) ? iscsi_ics_name[state] : "N/A");
2785 }
2786
2787 static const char *
iscsi_iscsi_login_state(unsigned int state)2788 iscsi_iscsi_login_state(unsigned int state)
2789 {
2790 return ((state < LOGIN_MAX) ? iscsi_login_state_names[state] : "N/A");
2791 }
2792
2793
2794 /*
2795 * Retrieve connection type given a kernel address
2796 */
2797 static idm_conn_type_t
idm_conn_type(uintptr_t addr)2798 idm_conn_type(uintptr_t addr)
2799 {
2800 idm_conn_type_t result = 0; /* Unknown */
2801 uintptr_t idm_conn_type_addr;
2802
2803 idm_conn_type_addr = addr + offsetof(idm_conn_t, ic_conn_type);
2804 (void) mdb_vread(&result, sizeof (result), idm_conn_type_addr);
2805
2806 return (result);
2807 }
2808
2809 /*
2810 * Convert a sockaddr to the string representation, suitable for
2811 * storing in an nvlist or printing out in a list.
2812 */
2813 static int
sa_to_str(struct sockaddr_storage * sa,char * buf)2814 sa_to_str(struct sockaddr_storage *sa, char *buf)
2815 {
2816 char pbuf[7];
2817 const char *bufp;
2818 struct sockaddr_in *sin;
2819 struct sockaddr_in6 *sin6;
2820 uint16_t port;
2821
2822 if (!sa || !buf) {
2823 return (EINVAL);
2824 }
2825
2826 buf[0] = '\0';
2827
2828 if (sa->ss_family == AF_INET) {
2829 sin = (struct sockaddr_in *)sa;
2830 bufp = iscsi_inet_ntop(AF_INET,
2831 (const void *)&(sin->sin_addr.s_addr),
2832 buf, PORTAL_STR_LEN);
2833 if (bufp == NULL) {
2834 return (-1);
2835 }
2836 mdb_nhconvert(&port, &sin->sin_port, sizeof (uint16_t));
2837 } else if (sa->ss_family == AF_INET6) {
2838 strlcat(buf, "[", sizeof (buf));
2839 sin6 = (struct sockaddr_in6 *)sa;
2840 bufp = iscsi_inet_ntop(AF_INET6,
2841 (const void *)&sin6->sin6_addr.s6_addr,
2842 &buf[1], PORTAL_STR_LEN - 1);
2843 if (bufp == NULL) {
2844 return (-1);
2845 }
2846 strlcat(buf, "]", PORTAL_STR_LEN);
2847 mdb_nhconvert(&port, &sin6->sin6_port, sizeof (uint16_t));
2848 } else {
2849 return (EINVAL);
2850 }
2851
2852
2853 mdb_snprintf(pbuf, sizeof (pbuf), ":%u", port);
2854 strlcat(buf, pbuf, PORTAL_STR_LEN);
2855
2856 return (0);
2857 }
2858
2859
2860 static void
iscsi_format_timestamp(char * ts_str,int strlen,timespec_t * ts)2861 iscsi_format_timestamp(char *ts_str, int strlen, timespec_t *ts)
2862 {
2863 mdb_snprintf(ts_str, strlen, "%Y:%03d:%03d:%03d", ts->tv_sec,
2864 (ts->tv_nsec / 1000000) % 1000, (ts->tv_nsec / 1000) % 1000,
2865 ts->tv_nsec % 1000);
2866 }
2867
2868 /*
2869 * Help information for the iscsi_isns dcmd
2870 */
2871 static void
iscsi_isns_help(void)2872 iscsi_isns_help(void)
2873 {
2874 mdb_printf("iscsi_isns:\n");
2875 mdb_inc_indent(4);
2876 mdb_printf("-e: Print ESI information\n");
2877 mdb_printf("-p: Print portal information\n");
2878 mdb_printf("-s: Print iSNS server information\n");
2879 mdb_printf("-t: Print target information\n");
2880 mdb_printf("-v: Add verbosity to the other options' output\n");
2881 mdb_printf("-R: Add Refcount information to '-t' output\n");
2882 mdb_dec_indent(4);
2883 }
2884
2885 /* ARGSUSED */
2886 static int
iscsi_isns_esi_cb(uintptr_t addr,const void * walker_data,void * data)2887 iscsi_isns_esi_cb(uintptr_t addr, const void *walker_data, void *data)
2888 {
2889 isns_esi_tinfo_t tinfo;
2890
2891 if (mdb_vread(&tinfo, sizeof (isns_esi_tinfo_t), addr) !=
2892 sizeof (isns_esi_tinfo_t)) {
2893 return (WALK_ERR);
2894 }
2895
2896 mdb_printf("ESI thread/thr did : 0x%p / %d\n", tinfo.esi_thread,
2897 tinfo.esi_thread_did);
2898 mdb_printf("ESI sonode : 0x%p\n", tinfo.esi_so);
2899 mdb_printf("ESI port : %d\n", tinfo.esi_port);
2900 mdb_printf("ESI thread running : %s\n",
2901 (tinfo.esi_thread_running) ? "Yes" : "No");
2902
2903 return (WALK_NEXT);
2904 }
2905
2906 static int
iscsi_isns_esi(iscsi_dcmd_ctrl_t * idc)2907 iscsi_isns_esi(iscsi_dcmd_ctrl_t *idc)
2908 {
2909 GElf_Sym sym;
2910 uintptr_t addr;
2911
2912 if (mdb_lookup_by_name("esi", &sym) == -1) {
2913 mdb_warn("failed to find symbol 'esi_list'");
2914 return (DCMD_ERR);
2915 }
2916 addr = (uintptr_t)sym.st_value;
2917
2918 idc->idc_header = 1;
2919 (void) iscsi_isns_esi_cb(addr, NULL, idc);
2920
2921 return (0);
2922 }
2923
2924 /* ARGSUSED */
2925 static int
iscsi_isns_portal_cb(uintptr_t addr,const void * walker_data,void * data)2926 iscsi_isns_portal_cb(uintptr_t addr, const void *walker_data, void *data)
2927 {
2928 iscsi_dcmd_ctrl_t *idc = (iscsi_dcmd_ctrl_t *)data;
2929 isns_portal_t portal;
2930 char portal_addr[PORTAL_STR_LEN];
2931 struct sockaddr_storage *ss;
2932 char ts_string[40];
2933
2934 if (mdb_vread(&portal, sizeof (isns_portal_t), addr) !=
2935 sizeof (isns_portal_t)) {
2936 return (WALK_ERR);
2937 }
2938
2939 ss = &portal.portal_addr;
2940 sa_to_str(ss, portal_addr);
2941 mdb_printf("Portal IP address ");
2942
2943 if (ss->ss_family == AF_INET) {
2944 mdb_printf("(v4): %s", portal_addr);
2945 } else {
2946 mdb_printf("(v6): %s", portal_addr);
2947 }
2948
2949 if (portal.portal_default == B_TRUE) {
2950 mdb_printf(" (Default portal)\n");
2951 } else {
2952 mdb_printf("\n");
2953 }
2954 if (portal.portal_iscsit != NULL) {
2955 mdb_printf("(Part of TPG: 0x%p)\n", portal.portal_iscsit);
2956 }
2957
2958 iscsi_format_timestamp(ts_string, 40, &portal.portal_esi_timestamp);
2959 mdb_printf("Portal ESI timestamp: %s\n\n", ts_string);
2960
2961 if ((portal.portal_iscsit != NULL) && (idc->idc_verbose)) {
2962 mdb_inc_indent(4);
2963 iscsi_portal_impl((uintptr_t)portal.portal_iscsit, idc);
2964 mdb_dec_indent(4);
2965 }
2966
2967
2968 return (WALK_NEXT);
2969 }
2970
2971 static int
iscsi_isns_portals(iscsi_dcmd_ctrl_t * idc)2972 iscsi_isns_portals(iscsi_dcmd_ctrl_t *idc)
2973 {
2974 GElf_Sym sym;
2975 uintptr_t portal_list;
2976
2977 mdb_printf("All Active Portals:\n");
2978
2979 if (mdb_lookup_by_name("isns_all_portals", &sym) == -1) {
2980 mdb_warn("failed to find symbol 'isns_all_portals'");
2981 return (DCMD_ERR);
2982 }
2983
2984 portal_list = (uintptr_t)sym.st_value;
2985 idc->idc_header = 1;
2986
2987 if (mdb_pwalk("avl", iscsi_isns_portal_cb, idc, portal_list) == -1) {
2988 mdb_warn("avl walk failed for isns_all_portals");
2989 return (DCMD_ERR);
2990 }
2991 mdb_printf("\nPortals from TPGs:\n");
2992
2993 if (mdb_lookup_by_name("isns_tpg_portals", &sym) == -1) {
2994 mdb_warn("failed to find symbol 'isns_tpg_portals'");
2995 return (DCMD_ERR);
2996 }
2997
2998 portal_list = (uintptr_t)sym.st_value;
2999 idc->idc_header = 1;
3000
3001 if (mdb_pwalk("avl", iscsi_isns_portal_cb, idc, portal_list) == -1) {
3002 mdb_warn("avl walk failed for isns_tpg_portals");
3003 return (DCMD_ERR);
3004 }
3005
3006
3007 return (0);
3008 }
3009
3010 /* ARGSUSED */
3011 static int
iscsi_isns_targets_cb(uintptr_t addr,const void * walker_data,void * data)3012 iscsi_isns_targets_cb(uintptr_t addr, const void *walker_data, void *data)
3013 {
3014 iscsi_dcmd_ctrl_t *idc = (iscsi_dcmd_ctrl_t *)data;
3015 isns_target_t itarget;
3016 int rc = 0;
3017 int rc_audit = 0;
3018 uintptr_t rc_addr;
3019
3020 if (mdb_vread(&itarget, sizeof (isns_target_t), addr) !=
3021 sizeof (isns_target_t)) {
3022 return (WALK_ERR);
3023 }
3024
3025 idc->idc_header = 1;
3026 rc_audit = idc->u.child.idc_rc_audit;
3027
3028 mdb_printf("Target: %p\n", addr);
3029 mdb_inc_indent(4);
3030 mdb_printf("Registered: %s\n",
3031 (itarget.target_registered) ? "Yes" : "No");
3032 mdb_printf("Update needed: %s\n",
3033 (itarget.target_update_needed) ? "Yes" : "No");
3034 mdb_printf("Target Info: %p\n", itarget.target_info);
3035
3036 /* Prevent target refcounts from showing through this path */
3037 idc->u.child.idc_rc_audit = 0;
3038 rc = iscsi_tgt_impl((uintptr_t)itarget.target, idc);
3039
3040 idc->u.child.idc_rc_audit = rc_audit;
3041 if (idc->u.child.idc_rc_audit) {
3042 rc_addr = (uintptr_t)itarget.target_info +
3043 offsetof(isns_target_info_t, ti_refcnt);
3044
3045 mdb_printf("Reference History(isns_target_info ti_refcnt):\n");
3046 if (iscsi_refcnt_impl(rc_addr) != 0) {
3047 return (WALK_ERR);
3048 }
3049 }
3050
3051 mdb_dec_indent(4);
3052
3053 if (rc == DCMD_OK) {
3054 return (WALK_NEXT);
3055 }
3056
3057 return (WALK_ERR);
3058 }
3059
3060 static int
iscsi_isns_targets(iscsi_dcmd_ctrl_t * idc)3061 iscsi_isns_targets(iscsi_dcmd_ctrl_t *idc)
3062 {
3063 GElf_Sym sym;
3064 uintptr_t isns_target_list;
3065
3066 if (mdb_lookup_by_name("isns_target_list", &sym) == -1) {
3067 mdb_warn("failed to find symbol 'isns_target_list'");
3068 return (DCMD_ERR);
3069 }
3070
3071 isns_target_list = (uintptr_t)sym.st_value;
3072 idc->idc_header = 1;
3073 idc->u.child.idc_tgt = 1;
3074
3075 if (mdb_pwalk("avl", iscsi_isns_targets_cb, idc,
3076 isns_target_list) == -1) {
3077 mdb_warn("avl walk failed for isns_target_list");
3078 return (DCMD_ERR);
3079 }
3080
3081 return (0);
3082 }
3083
3084 /* ARGSUSED */
3085 static int
iscsi_isns_servers_cb(uintptr_t addr,const void * walker_data,void * data)3086 iscsi_isns_servers_cb(uintptr_t addr, const void *walker_data, void *data)
3087 {
3088 iscsit_isns_svr_t server;
3089 char server_addr[PORTAL_STR_LEN];
3090 struct sockaddr_storage *ss;
3091 clock_t lbolt;
3092 iscsi_dcmd_ctrl_t *idc = (iscsi_dcmd_ctrl_t *)data;
3093 uintptr_t avl_addr;
3094
3095 if (mdb_vread(&server, sizeof (iscsit_isns_svr_t), addr) !=
3096 sizeof (iscsit_isns_svr_t)) {
3097 return (WALK_ERR);
3098 }
3099
3100 if ((lbolt = (clock_t)mdb_get_lbolt()) == -1)
3101 return (WALK_ERR);
3102
3103 mdb_printf("iSNS server %p:\n", addr);
3104 mdb_inc_indent(4);
3105 ss = &server.svr_sa;
3106 sa_to_str(ss, server_addr);
3107
3108 mdb_printf("IP address ");
3109 if (ss->ss_family == AF_INET) {
3110 mdb_printf("(v4): %s\n", server_addr);
3111 } else {
3112 mdb_printf("(v6): %s\n", server_addr);
3113 }
3114
3115 mdb_printf("ESI Interval: %d seconds\n",
3116 server.svr_esi_interval);
3117 mdb_printf("Last message: %d seconds ago\n",
3118 ((lbolt - server.svr_last_msg) / 100));
3119 mdb_printf("Client registered: %s\n",
3120 (server.svr_registered) ? "Yes" : "No");
3121 mdb_printf("Retry Count: %d\n",
3122 server.svr_retry_count);
3123 mdb_printf("Targets Changes Pending: %s\n",
3124 (server.svr_targets_changed) ? "Yes" : "No");
3125 mdb_printf("Delete Pending: %s\n",
3126 (server.svr_delete_needed) ? "Yes" : "No");
3127 mdb_printf("Replace-All Needed: %s\n",
3128 (server.svr_reset_needed) ? "Yes" : "No");
3129
3130 if (idc->idc_verbose) {
3131 idc->idc_header = 1;
3132 idc->u.child.idc_tgt = 1;
3133
3134 mdb_inc_indent(2);
3135 avl_addr = addr + offsetof(iscsit_isns_svr_t,
3136 svr_target_list);
3137 if (mdb_pwalk("avl", iscsi_isns_targets_cb, idc,
3138 avl_addr) == -1) {
3139 mdb_warn("avl walk failed for svr_target_list");
3140 return (WALK_ERR);
3141 }
3142 mdb_dec_indent(2);
3143 }
3144
3145 mdb_dec_indent(4);
3146
3147 return (WALK_NEXT);
3148 }
3149
3150 static int
iscsi_isns_servers(iscsi_dcmd_ctrl_t * idc)3151 iscsi_isns_servers(iscsi_dcmd_ctrl_t *idc)
3152 {
3153 uintptr_t iscsit_global_addr;
3154 uintptr_t list_addr;
3155 GElf_Sym sym;
3156
3157 if (mdb_lookup_by_name("iscsit_global", &sym) == -1) {
3158 mdb_warn("failed to find symbol 'iscsit_global'");
3159 return (DCMD_ERR);
3160 }
3161
3162 iscsit_global_addr = (uintptr_t)sym.st_value;
3163 idc->idc_header = 1;
3164 list_addr = iscsit_global_addr +
3165 offsetof(iscsit_global_t, global_isns_cfg.isns_svrs);
3166
3167 if (mdb_pwalk("list", iscsi_isns_servers_cb, idc, list_addr) == -1) {
3168 mdb_warn("list walk failed for iSNS servers");
3169 return (DCMD_ERR);
3170 }
3171
3172 return (0);
3173 }
3174
3175 /* ARGSUSED */
3176 static int
iscsi_isns(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)3177 iscsi_isns(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
3178 {
3179 iscsi_dcmd_ctrl_t idc;
3180 int portals = 0, esi = 0, targets = 0, verbose = 0, servers = 0;
3181 int rc_audit = 0;
3182
3183 if (flags & DCMD_ADDRSPEC) {
3184 mdb_warn("iscsi_isns is only a global dcmd.");
3185 return (DCMD_ERR);
3186 }
3187
3188 bzero(&idc, sizeof (idc));
3189 if (mdb_getopts(argc, argv,
3190 'e', MDB_OPT_SETBITS, TRUE, &esi,
3191 'p', MDB_OPT_SETBITS, TRUE, &portals,
3192 's', MDB_OPT_SETBITS, TRUE, &servers,
3193 't', MDB_OPT_SETBITS, TRUE, &targets,
3194 'v', MDB_OPT_SETBITS, TRUE, &verbose,
3195 'R', MDB_OPT_SETBITS, TRUE, &rc_audit,
3196 NULL) != argc)
3197 return (DCMD_USAGE);
3198
3199 if ((esi + portals + targets + servers) > 1) {
3200 mdb_printf("Only one of e, p, s, and t must be provided");
3201 return (DCMD_ERR);
3202 }
3203
3204 if ((esi | portals | targets | servers) == 0) {
3205 mdb_printf("Exactly one of e, p, s, or t must be provided");
3206 return (DCMD_ERR);
3207 }
3208
3209 idc.idc_verbose = verbose;
3210 idc.u.child.idc_rc_audit = rc_audit;
3211
3212 if (esi) {
3213 return (iscsi_isns_esi(&idc));
3214 }
3215
3216 if (portals) {
3217 return (iscsi_isns_portals(&idc));
3218 }
3219
3220 if (servers) {
3221 return (iscsi_isns_servers(&idc));
3222 }
3223
3224 return (iscsi_isns_targets(&idc));
3225 }
3226
3227 static int
iscsi_ini_sess_walk_init(mdb_walk_state_t * wsp)3228 iscsi_ini_sess_walk_init(mdb_walk_state_t *wsp)
3229 {
3230 if (wsp->walk_addr == 0) {
3231 mdb_warn("<iscsi_sess_t addr>::walk iscsi_ini_sess");
3232 return (WALK_ERR);
3233 }
3234
3235 wsp->walk_data = mdb_alloc(sizeof (iscsi_sess_t), UM_SLEEP|UM_GC);
3236 if (!wsp->walk_data) {
3237 mdb_warn("iscsi_ini_sess walk failed");
3238 return (WALK_ERR);
3239 }
3240
3241 return (WALK_NEXT);
3242 }
3243
3244 static int
iscsi_ini_sess_step(mdb_walk_state_t * wsp)3245 iscsi_ini_sess_step(mdb_walk_state_t *wsp)
3246 {
3247 int status;
3248
3249 if (wsp->walk_addr == 0) {
3250 return (WALK_DONE);
3251 }
3252
3253 if (mdb_vread(wsp->walk_data, sizeof (iscsi_sess_t), wsp->walk_addr)
3254 != sizeof (iscsi_sess_t)) {
3255 mdb_warn("failed to read iscsi_sess_t at %p", wsp->walk_addr);
3256 return (WALK_DONE);
3257 }
3258
3259 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
3260 wsp->walk_cbdata);
3261
3262 wsp->walk_addr =
3263 (uintptr_t)(((iscsi_sess_t *)wsp->walk_data)->sess_next);
3264
3265 return (status);
3266 }
3267
3268 static int
iscsi_ini_conn_walk_init(mdb_walk_state_t * wsp)3269 iscsi_ini_conn_walk_init(mdb_walk_state_t *wsp)
3270 {
3271 if (wsp->walk_addr == 0) {
3272 mdb_warn("<iscsi_conn_t addr>::walk iscsi_ini_conn");
3273 return (WALK_DONE);
3274 }
3275
3276 wsp->walk_data = mdb_alloc(sizeof (iscsi_conn_t), UM_SLEEP|UM_GC);
3277 if (!wsp->walk_data) {
3278 mdb_warn("iscsi_ini_conn walk failed");
3279 return (WALK_ERR);
3280 }
3281
3282 return (WALK_NEXT);
3283 }
3284
3285 static int
iscsi_ini_conn_step(mdb_walk_state_t * wsp)3286 iscsi_ini_conn_step(mdb_walk_state_t *wsp)
3287 {
3288 int status;
3289
3290 if (wsp->walk_addr == 0) {
3291 return (WALK_DONE);
3292 }
3293
3294 if (mdb_vread(wsp->walk_data, sizeof (iscsi_conn_t), wsp->walk_addr)
3295 != sizeof (iscsi_conn_t)) {
3296 mdb_warn("failed to read iscsi_conn_t at %p", wsp->walk_addr);
3297 return (WALK_DONE);
3298 }
3299
3300
3301 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
3302 wsp->walk_cbdata);
3303
3304 wsp->walk_addr =
3305 (uintptr_t)(((iscsi_conn_t *)wsp->walk_data)->conn_next);
3306
3307 return (status);
3308 }
3309
3310 static int
iscsi_ini_lun_walk_init(mdb_walk_state_t * wsp)3311 iscsi_ini_lun_walk_init(mdb_walk_state_t *wsp)
3312 {
3313 if (wsp->walk_addr == 0) {
3314 mdb_warn("<iscsi_lun_t addr>::walk iscsi_ini_lun");
3315 return (WALK_DONE);
3316 }
3317
3318 wsp->walk_data = mdb_alloc(sizeof (iscsi_lun_t), UM_SLEEP|UM_GC);
3319 if (!wsp->walk_data) {
3320 return (WALK_ERR);
3321 }
3322
3323 return (WALK_NEXT);
3324 }
3325
3326 static int
iscsi_ini_lun_step(mdb_walk_state_t * wsp)3327 iscsi_ini_lun_step(mdb_walk_state_t *wsp)
3328 {
3329 int status;
3330
3331 if (wsp->walk_addr == 0) {
3332 return (WALK_DONE);
3333 }
3334
3335 if (mdb_vread(wsp->walk_data, sizeof (iscsi_lun_t), wsp->walk_addr)
3336 != sizeof (iscsi_lun_t)) {
3337 mdb_warn("failed to read iscsi_lun_t at %p", wsp->walk_addr);
3338 return (WALK_DONE);
3339 }
3340
3341 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
3342 wsp->walk_cbdata);
3343
3344 wsp->walk_addr =
3345 (uintptr_t)(((iscsi_lun_t *)wsp->walk_data)->lun_next);
3346
3347 return (status);
3348 }
3349
3350 static int
iscsi_ini_cmd_walk_init(mdb_walk_state_t * wsp)3351 iscsi_ini_cmd_walk_init(mdb_walk_state_t *wsp)
3352 {
3353 if (wsp->walk_addr == 0) {
3354 mdb_warn("<iscsi_cmd_t addr>::walk iscsi_ini_cmd");
3355 return (WALK_DONE);
3356 }
3357
3358 wsp->walk_data = mdb_alloc(sizeof (iscsi_cmd_t), UM_SLEEP|UM_GC);
3359 if (!wsp->walk_data) {
3360 return (WALK_ERR);
3361 }
3362
3363 return (WALK_NEXT);
3364 }
3365
3366 static int
iscsi_ini_cmd_step(mdb_walk_state_t * wsp)3367 iscsi_ini_cmd_step(mdb_walk_state_t *wsp)
3368 {
3369 int status;
3370
3371 if (wsp->walk_addr == 0) {
3372 return (WALK_DONE);
3373 }
3374
3375 if (mdb_vread(wsp->walk_data, sizeof (iscsi_cmd_t), wsp->walk_addr)
3376 != sizeof (iscsi_cmd_t)) {
3377 mdb_warn("failed to read iscsi_cmd_t at %p", wsp->walk_addr);
3378 return (WALK_DONE);
3379 }
3380
3381 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
3382 wsp->walk_cbdata);
3383
3384 wsp->walk_addr =
3385 (uintptr_t)(((iscsi_cmd_t *)wsp->walk_data)->cmd_next);
3386
3387 return (status);
3388 }
3389
3390 static int
iscsi_ini_cmd_walk_cb(uintptr_t addr,const void * vcmd,void * vidc)3391 iscsi_ini_cmd_walk_cb(uintptr_t addr, const void *vcmd, void *vidc)
3392 {
3393 const iscsi_cmd_t *cmd = vcmd;
3394 iscsi_dcmd_ctrl_t *idc = vidc;
3395 int rc;
3396
3397 if (cmd == NULL) {
3398 mdb_warn("list walk failed. Null cmd");
3399 return (WALK_ERR);
3400 }
3401
3402 rc = iscsi_print_ini_cmd(addr, cmd, idc);
3403
3404 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR);
3405 }
3406
3407 static int
iscsi_ini_hba_walk_init(mdb_walk_state_t * wsp)3408 iscsi_ini_hba_walk_init(mdb_walk_state_t *wsp)
3409 {
3410 uintptr_t state_addr, array_addr;
3411 int array_size;
3412 struct i_ddi_soft_state *ss;
3413 idm_hba_walk_info_t *hwi;
3414
3415
3416 hwi = (idm_hba_walk_info_t *)mdb_zalloc(
3417 sizeof (idm_hba_walk_info_t), UM_SLEEP|UM_GC);
3418
3419 if (!hwi) {
3420 mdb_warn("unable to allocate storage for iscsi_ini_hba walk");
3421 return (WALK_ERR);
3422 }
3423
3424 if (wsp->walk_addr != 0) {
3425 mdb_warn("iscsi_ini_hba only supports global walk");
3426 return (WALK_ERR);
3427 } else {
3428
3429 /*
3430 * Read in the array and setup the walk struct.
3431 */
3432 if (mdb_readvar(&state_addr, "iscsi_state") == -1) {
3433 mdb_warn("state variable iscsi_state not found.\n");
3434 mdb_warn("Is the driver loaded ?\n");
3435 return (WALK_ERR);
3436 }
3437
3438 ss = (struct i_ddi_soft_state *)mdb_alloc(sizeof (*ss),
3439 UM_SLEEP|UM_GC);
3440 if (mdb_vread(ss, sizeof (*ss), state_addr) != sizeof (*ss)) {
3441 mdb_warn("Cannot read softstate struct "
3442 "(Invalid pointer?).\n");
3443 return (WALK_ERR);
3444 }
3445
3446 /* Where to get the data */
3447 array_size = ss->n_items * (sizeof (void *));
3448 array_addr = (uintptr_t)ss->array;
3449
3450 /* Where to put the data */
3451 hwi->n_elements = ss->n_items;
3452 hwi->array = mdb_alloc(array_size, UM_SLEEP|UM_GC);
3453 if (!hwi->array) {
3454 mdb_warn("list walk failed");
3455 return (WALK_ERR);
3456 }
3457 if (mdb_vread(hwi->array, array_size, array_addr) !=
3458 array_size) {
3459 mdb_warn("Corrupted softstate struct.\n");
3460 return (WALK_ERR);
3461 }
3462 hwi->cur_element = 0;
3463 wsp->walk_data = hwi;
3464 }
3465
3466 return (WALK_NEXT);
3467 }
3468
3469 static int
iscsi_ini_hba_step(mdb_walk_state_t * wsp)3470 iscsi_ini_hba_step(mdb_walk_state_t *wsp)
3471 {
3472 int status;
3473 idm_hba_walk_info_t *hwi = (idm_hba_walk_info_t *)wsp->walk_data;
3474
3475 for (; hwi->cur_element < hwi->n_elements; hwi->cur_element++) {
3476 if (hwi->array[hwi->cur_element] != NULL) {
3477 break;
3478 }
3479 }
3480 if (hwi->cur_element >= hwi->n_elements) {
3481 return (WALK_DONE);
3482 }
3483
3484 hwi->data = (iscsi_hba_t *)mdb_alloc(sizeof (iscsi_hba_t),
3485 UM_SLEEP|UM_GC);
3486 if (mdb_vread(hwi->data, sizeof (iscsi_hba_t),
3487 (uintptr_t)hwi->array[hwi->cur_element]) != sizeof (iscsi_hba_t)) {
3488 mdb_warn("failed to read iscsi_sess_t at %p", wsp->walk_addr);
3489 return (WALK_DONE);
3490 }
3491
3492
3493 status = wsp->walk_callback((uintptr_t)hwi->array[hwi->cur_element],
3494 hwi->data, wsp->walk_cbdata);
3495
3496 /* Increment cur_element for next iteration */
3497 hwi->cur_element++;
3498
3499 return (status);
3500 }
3501
3502 /*
3503 * iscsi_inet_ntop -- Convert an IPv4 or IPv6 address in binary form into
3504 * printable form, and return a pointer to that string. Caller should
3505 * provide a buffer of correct length to store string into.
3506 * Note: this routine is kernel version of inet_ntop. It has similar
3507 * format as iscsi_inet_ntop() defined in rfc2553. But it does not do
3508 * error handling operations exactly as rfc2553 defines. This function
3509 * is used by kernel inet directory routines only for debugging.
3510 * This iscsi_inet_ntop() function, does not return NULL if third argument
3511 * is NULL. The reason is simple that we don't want kernel to panic
3512 * as the output of this function is directly fed to ip<n>dbg macro.
3513 * Instead it uses a local buffer for destination address for
3514 * those calls which purposely pass NULL ptr for the destination
3515 * buffer. This function is thread-safe when the caller passes a non-
3516 * null buffer with the third argument.
3517 */
3518 /* ARGSUSED */
3519
3520 #define OK_16PTR(p) (!((uintptr_t)(p) & 0x1))
3521 #if defined(__x86)
3522 #define OK_32PTR(p) OK_16PTR(p)
3523 #else
3524 #define OK_32PTR(p) (!((uintptr_t)(p) & 0x3))
3525 #endif
3526
3527 char *
iscsi_inet_ntop(int af,const void * addr,char * buf,int addrlen)3528 iscsi_inet_ntop(int af, const void *addr, char *buf, int addrlen)
3529 {
3530 static char local_buf[PORTAL_STR_LEN];
3531 static char *err_buf1 = "<badaddr>";
3532 static char *err_buf2 = "<badfamily>";
3533 in6_addr_t *v6addr;
3534 uchar_t *v4addr;
3535 char *caddr;
3536
3537 /*
3538 * We don't allow thread unsafe iscsi_inet_ntop calls, they
3539 * must pass a non-null buffer pointer. For DEBUG mode
3540 * we use the ASSERT() and for non-debug kernel it will
3541 * silently allow it for now. Someday we should remove
3542 * the static buffer from this function.
3543 */
3544
3545 ASSERT(buf != NULL);
3546 if (buf == NULL)
3547 buf = local_buf;
3548 buf[0] = '\0';
3549
3550 /* Let user know politely not to send NULL or unaligned addr */
3551 if (addr == NULL || !(OK_32PTR(addr))) {
3552 return (err_buf1);
3553 }
3554
3555
3556 #define UC(b) (((int)b) & 0xff)
3557 switch (af) {
3558 case AF_INET:
3559 ASSERT(addrlen >= INET_ADDRSTRLEN);
3560 v4addr = (uchar_t *)addr;
3561 (void) mdb_snprintf(buf, INET6_ADDRSTRLEN,
3562 "%03d.%03d.%03d.%03d",
3563 UC(v4addr[0]), UC(v4addr[1]), UC(v4addr[2]), UC(v4addr[3]));
3564 return (buf);
3565
3566 case AF_INET6:
3567 ASSERT(addrlen >= INET6_ADDRSTRLEN);
3568 v6addr = (in6_addr_t *)addr;
3569 if (IN6_IS_ADDR_V4MAPPED(v6addr)) {
3570 caddr = (char *)addr;
3571 (void) mdb_snprintf(buf, INET6_ADDRSTRLEN,
3572 "::ffff:%d.%d.%d.%d",
3573 UC(caddr[12]), UC(caddr[13]),
3574 UC(caddr[14]), UC(caddr[15]));
3575 } else if (IN6_IS_ADDR_V4COMPAT(v6addr)) {
3576 caddr = (char *)addr;
3577 (void) mdb_snprintf(buf, INET6_ADDRSTRLEN,
3578 "::%d.%d.%d.%d",
3579 UC(caddr[12]), UC(caddr[13]), UC(caddr[14]),
3580 UC(caddr[15]));
3581 } else if (IN6_IS_ADDR_UNSPECIFIED(v6addr)) {
3582 (void) mdb_snprintf(buf, INET6_ADDRSTRLEN, "::");
3583 } else {
3584 convert2ascii(buf, v6addr);
3585 }
3586 return (buf);
3587
3588 default:
3589 return (err_buf2);
3590 }
3591 #undef UC
3592 }
3593
3594 /*
3595 *
3596 * v6 formats supported
3597 * General format xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx
3598 * The short hand notation :: is used for COMPAT addr
3599 * Other forms : fe80::xxxx:xxxx:xxxx:xxxx
3600 */
3601 static void
convert2ascii(char * buf,const in6_addr_t * addr)3602 convert2ascii(char *buf, const in6_addr_t *addr)
3603 {
3604 int hexdigits;
3605 int head_zero = 0;
3606 int tail_zero = 0;
3607 /* tempbuf must be big enough to hold ffff:\0 */
3608 char tempbuf[6];
3609 char *ptr;
3610 uint16_t out_addr_component;
3611 uint16_t *addr_component;
3612 size_t len;
3613 boolean_t first = B_FALSE;
3614 boolean_t med_zero = B_FALSE;
3615 boolean_t end_zero = B_FALSE;
3616
3617 addr_component = (uint16_t *)addr;
3618 ptr = buf;
3619
3620 /* First count if trailing zeroes higher in number */
3621 for (hexdigits = 0; hexdigits < 8; hexdigits++) {
3622 if (*addr_component == 0) {
3623 if (hexdigits < 4)
3624 head_zero++;
3625 else
3626 tail_zero++;
3627 }
3628 addr_component++;
3629 }
3630 addr_component = (uint16_t *)addr;
3631 if (tail_zero > head_zero && (head_zero + tail_zero) != 7)
3632 end_zero = B_TRUE;
3633
3634 for (hexdigits = 0; hexdigits < 8; hexdigits++) {
3635
3636 /* if entry is a 0 */
3637
3638 if (*addr_component == 0) {
3639 if (!first && *(addr_component + 1) == 0) {
3640 if (end_zero && (hexdigits < 4)) {
3641 *ptr++ = '0';
3642 *ptr++ = ':';
3643 } else {
3644 /*
3645 * address starts with 0s ..
3646 * stick in leading ':' of pair
3647 */
3648 if (hexdigits == 0)
3649 *ptr++ = ':';
3650 /* add another */
3651 *ptr++ = ':';
3652 first = B_TRUE;
3653 med_zero = B_TRUE;
3654 }
3655 } else if (first && med_zero) {
3656 if (hexdigits == 7)
3657 *ptr++ = ':';
3658 addr_component++;
3659 continue;
3660 } else {
3661 *ptr++ = '0';
3662 *ptr++ = ':';
3663 }
3664 addr_component++;
3665 continue;
3666 }
3667 if (med_zero)
3668 med_zero = B_FALSE;
3669
3670 tempbuf[0] = '\0';
3671 mdb_nhconvert(&out_addr_component, addr_component,
3672 sizeof (uint16_t));
3673 (void) mdb_snprintf(tempbuf, 6, "%x:", out_addr_component);
3674 len = strlen(tempbuf);
3675 bcopy(tempbuf, ptr, len);
3676 ptr = ptr + len;
3677 addr_component++;
3678 }
3679 *--ptr = '\0';
3680 }
3681
3682 /*
3683 * MDB module linkage information:
3684 *
3685 * We declare a list of structures describing our dcmds, a list of structures
3686 * describing our walkers and a function named _mdb_init to return a pointer
3687 * to our module information.
3688 */
3689 static const mdb_dcmd_t dcmds[] = {
3690 { "iscsi_tgt", "[-agscptbSRv]",
3691 "iSCSI target information", iscsi_tgt },
3692 { "iscsi_tpgt", "[-R]",
3693 "iSCSI target portal group tag information", iscsi_tpgt },
3694 { "iscsi_tpg", "[-R]",
3695 "iSCSI target portal group information", iscsi_tpg },
3696 { "iscsi_sess", "[-ablmtvcSRIT]",
3697 "iSCSI session information", iscsi_sess },
3698 { "iscsi_conn", "[-abmtvSRIT]",
3699 "iSCSI connection information", iscsi_conn },
3700 { "iscsi_task", "[-bSRv]",
3701 "iSCSI task information", iscsi_task },
3702 { "iscsi_refcnt", "",
3703 "print audit informtion for idm_refcnt_t", iscsi_refcnt },
3704 { "iscsi_states", "",
3705 "dump events and state transitions recorded in an\t"
3706 "\t\tidm_sm_audit_t structure", iscsi_states },
3707 { "iscsi_isns", "[-epstvR]",
3708 "print iscsit iSNS information", iscsi_isns, iscsi_isns_help },
3709 { "iscsi_svc", "[-vR]",
3710 "iSCSI service information", iscsi_svc },
3711 { "iscsi_portal", "[-R]",
3712 "iSCSI portal information", iscsi_portal },
3713 { "iscsi_cmd", "[-S]",
3714 "iSCSI command information (initiator only)", iscsi_cmd },
3715 { NULL }
3716 };
3717
3718 /*
3719 * Basic walkers for the initiator linked lists
3720 */
3721 static const mdb_walker_t walkers[] = {
3722 { "iscsi_ini_hba", "global walk of the initiator iscsi_hba_t "
3723 "list", iscsi_ini_hba_walk_init, iscsi_ini_hba_step, NULL},
3724 { "iscsi_ini_sess", "walk list of initiator iscsi_sess_t structures",
3725 iscsi_ini_sess_walk_init, iscsi_ini_sess_step, NULL },
3726 { "iscsi_ini_conn", "walk list of initiator iscsi_conn_t structures",
3727 iscsi_ini_conn_walk_init, iscsi_ini_conn_step, NULL },
3728 { "iscsi_ini_lun", "walk list of initiator iscsi_lun_t structures",
3729 iscsi_ini_lun_walk_init, iscsi_ini_lun_step, NULL },
3730 { "iscsi_ini_cmd", "walk list of initiator iscsi_cmd_t structures",
3731 iscsi_ini_cmd_walk_init, iscsi_ini_cmd_step, NULL },
3732 { NULL }
3733 };
3734
3735 static const mdb_modinfo_t modinfo = {
3736 MDB_API_VERSION, dcmds, walkers
3737 };
3738
3739 const mdb_modinfo_t *
_mdb_init(void)3740 _mdb_init(void)
3741 {
3742 return (&modinfo);
3743 }
3744