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