Merge commit 'b4bf0cf0458759c67920a031021a9d96cd683cfe'
[unleashed.git] / usr / src / cmd / mdb / common / modules / idm / idm.c
blobe6e4462a332a78228e8e8344e309f3c1d4c478e4
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
25 #include <mdb/mdb_modapi.h>
26 #include <mdb/mdb_ks.h>
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>
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>
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:
64 * target --> session --> connection --> task
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.
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().
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;
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.
119 uintptr_t idc_assoc_session;
120 } iscsi_dcmd_ctrl_t;
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;
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);
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);
219 #define PORTAL_STR_LEN (INET6_ADDRSTRLEN + 7)
222 * ::iscsi_tgt [-scatgpbSRv]
224 * iscsi_tgt - Print out information associated with an iscsit target instance
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
237 /*ARGSUSED*/
238 static int
239 iscsi_tgt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
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;
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);
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;
274 if (DCMD_HDRSPEC(flags))
275 idc.idc_header = 1;
278 * If no address was specified on the command line, we
279 * print out all tgtions
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);
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);
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);
300 return (DCMD_OK);
302 return (iscsi_tgt_impl(addr, &idc));
305 static int
306 iscsi_tpg(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
308 iscsi_dcmd_ctrl_t idc;
309 uintptr_t iscsit_global_addr, avl_addr;
310 GElf_Sym sym;
311 int rc_audit = 0;
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);
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;
327 * If no address was specified on the command line, we
328 * print out all tgtions
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);
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);
342 return (DCMD_OK);
344 return (iscsi_tpg_impl(addr, &idc));
348 * ::iscsi_tpgt [-pR]
350 * Print tpgt information.
351 * R Print reference count audit data
352 * p Print portal data
354 static int
355 iscsi_tpgt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
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;
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);
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;
376 * If no address was specified on the command line,
377 * print out all tpgts
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);
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);
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);
398 return (DCMD_OK);
400 return (iscsi_tpgt_impl(addr, &idc));
404 * ::iscsi_sess [-ablmtvcSRIT]
406 * iscsi_sess - Print out information associated with an iSCSI session
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
420 /*ARGSUSED*/
421 static int
422 iscsi_sess(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
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;
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);
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;
458 * If no address was specified on the command line, we
459 * print out all sessions
461 if (!(flags & DCMD_ADDRSPEC)) {
462 return (iscsi_walk_all_sess(&idc));
464 return (iscsi_sess_impl(addr, &idc));
470 * ::iscsi_conn [-abmtvSRIT]
472 * iscsi_conn - Print out information associated with an iSCSI connection
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
484 /*ARGSUSED*/
485 static int
486 iscsi_conn(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
488 iscsi_dcmd_ctrl_t idc;
489 int buffer = 0, task = 0, print_ip = 0;
490 int states = 0, rc_audit = 0, commands = 0;
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);
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;
517 * If no address was specified on the command line, we
518 * print out all connections
520 if (!(flags & DCMD_ADDRSPEC)) {
521 return (iscsi_walk_all_conn(&idc));
523 return (iscsi_conn_impl(addr, &idc));
528 * ::iscsi_svc [-vR]
530 * iscsi_svc - Print out information associated with an iSCSI svc
532 * R Print reference count audit data
533 * v Verbose output about the service
535 static int
536 iscsi_svc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
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;
544 bzero(&idc, sizeof (iscsi_dcmd_ctrl_t));
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);
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;
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);
563 idm_addr = (uintptr_t)sym.st_value;
564 svc_list_addr = idm_addr + offsetof(idm_global_t,
565 idm_tgt_svc_list);
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);
572 return (DCMD_OK);
574 return (iscsi_svc_impl(addr, &idc));
578 * ::iscsi_portal -R
580 * iscsi_portal - Print out information associated with an iSCSI portal
582 * R Print reference count audit data
584 static int
585 iscsi_portal(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
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;
594 bzero(&idc, sizeof (iscsi_dcmd_ctrl_t));
596 if (mdb_getopts(argc, argv,
597 'R', MDB_OPT_SETBITS, TRUE, &rc_audit,
598 NULL) != argc)
599 return (DCMD_USAGE);
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;
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);
613 iscsit_global_addr = (uintptr_t)sym.st_value;
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);
621 if (iscsi_tpg_impl((uintptr_t)iscsit_global.global_default_tpg,
622 &idc) != DCMD_OK) {
623 return (DCMD_ERR);
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);
634 return (DCMD_OK);
636 return (iscsi_portal_impl(addr, &idc));
641 * ::iscsi_cmd -S
643 * iscsi_cmd - Print out information associated with an iSCSI cmd
645 * S Print state audit data
647 static int
648 iscsi_cmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
650 iscsi_dcmd_ctrl_t idc;
651 iscsi_cmd_t cmd;
652 int states = 0;
654 bzero(&idc, sizeof (iscsi_dcmd_ctrl_t));
656 if (mdb_getopts(argc, argv,
657 'S', MDB_OPT_SETBITS, TRUE, &states,
658 NULL) != argc)
659 return (DCMD_USAGE);
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;
668 if (!(flags & DCMD_ADDRSPEC)) {
669 if (mdb_pwalk("iscsi_ini_hba", iscsi_ini_hba_walk_cb,
670 &idc, (uintptr_t)NULL) == -1) {
671 mdb_warn("iscsi cmd hba list walk failed");
672 return (DCMD_ERR);
674 } else {
675 if (mdb_vread(&cmd, sizeof (iscsi_cmd_t), addr) !=
676 sizeof (iscsi_cmd_t)) {
677 return (DCMD_ERR);
679 return (iscsi_print_ini_cmd(addr, &cmd, &idc));
681 return (DCMD_OK);
685 static int
686 iscsi_ini_hba_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc)
688 iscsi_hba_t ih;
690 if (mdb_vread(&ih, sizeof (ih), addr) != sizeof (ih)) {
691 mdb_warn("Invalid HBA\n");
692 return (DCMD_ERR);
695 if (idc->u.child.idc_hba) {
696 mdb_printf("iscsi_hba %p sessions: \n", addr);
699 if (mdb_pwalk("iscsi_ini_sess", iscsi_ini_sess_walk_cb, idc,
700 (uintptr_t)ih.hba_sess_list) == -1) {
701 mdb_warn("iscsi_sess_t walk failed");
702 return (DCMD_ERR);
704 return (DCMD_OK);
708 * ::iscsi_task [-bv]
710 * iscsi_task - Print out information associated with an iSCSI task
712 * b Print associated buffer information
713 * S Print recent state events and transitions
714 * R Print reference count audit data
715 * v Verbose output about the connection
717 /*ARGSUSED*/
718 static int
719 iscsi_task(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
721 iscsi_dcmd_ctrl_t idc;
722 int buffer = 0;
723 int states = 0, rc_audit = 0;
725 bzero(&idc, sizeof (idc));
726 if (mdb_getopts(argc, argv,
727 'b', MDB_OPT_SETBITS, TRUE, &buffer,
728 'S', MDB_OPT_SETBITS, TRUE, &states,
729 'R', MDB_OPT_SETBITS, TRUE, &rc_audit,
730 'v', MDB_OPT_SETBITS, TRUE, &idc.idc_verbose,
731 NULL) != argc)
732 return (DCMD_USAGE);
734 idc.u.child.idc_conn = 0;
735 idc.u.child.idc_task = 1;
736 idc.u.child.idc_buffer = buffer;
737 idc.u.child.idc_states = states;
738 idc.u.child.idc_rc_audit = rc_audit;
739 if (DCMD_HDRSPEC(flags))
740 idc.idc_header = 1;
743 * If no address was specified on the command line, we
744 * print out all connections
746 if (!(flags & DCMD_ADDRSPEC)) {
747 return (iscsi_walk_all_conn(&idc));
749 return (iscsi_task_impl(addr, &idc));
753 * ::iscsi_refcnt
755 * iscsi_refcnt - Dump an idm_refcnt_t structure
758 /*ARGSUSED*/
759 static int
760 iscsi_refcnt(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
762 if (!(flags & DCMD_ADDRSPEC)) {
763 return (DCMD_ERR);
765 return (iscsi_refcnt_impl(addr));
769 * ::iscsi_states
771 * iscsi_states - Dump events and state transitions recoreded in an
772 * idm_sm_audit_t structure
775 /*ARGSUSED*/
776 static int
777 iscsi_states(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
779 if (!(flags & DCMD_ADDRSPEC)) {
780 return (DCMD_ERR);
782 return (iscsi_sm_audit_impl(addr));
786 static int
787 iscsi_walk_all_sess(iscsi_dcmd_ctrl_t *idc)
789 uintptr_t iscsit_global_addr;
790 uintptr_t avl_addr;
791 uintptr_t list_addr;
792 GElf_Sym sym;
794 /* Initiator sessions */
795 if (idc->idc_ini) {
796 /* Always print hba info on this path */
797 idc->u.child.idc_hba = 1;
798 if (mdb_pwalk("iscsi_ini_hba", iscsi_ini_hba_walk_cb,
799 idc, (uintptr_t)NULL) == -1) {
800 mdb_warn("iscsi cmd hba list walk failed");
801 return (DCMD_ERR);
803 return (DCMD_OK);
806 /* Target sessions */
807 /* Walk discovery sessions */
808 if (mdb_lookup_by_name("iscsit_global", &sym) == -1) {
809 mdb_warn("failed to find symbol 'iscsit_global'");
810 return (DCMD_ERR);
812 iscsit_global_addr = (uintptr_t)sym.st_value;
813 avl_addr = iscsit_global_addr +
814 offsetof(iscsit_global_t, global_discovery_sessions);
815 if (mdb_pwalk("avl", iscsi_sess_walk_cb, idc, avl_addr) == -1) {
816 mdb_warn("avl walk failed for discovery sessions");
817 return (DCMD_ERR);
820 /* Walk targets printing all session info */
821 avl_addr = iscsit_global_addr +
822 offsetof(iscsit_global_t, global_target_list);
823 if (mdb_pwalk("avl", iscsi_tgt_walk_cb, idc, avl_addr) == -1) {
824 mdb_warn("avl walk failed for target/session tree");
825 return (DCMD_ERR);
828 /* Walk deleting targets printing all session info */
829 list_addr = iscsit_global_addr +
830 offsetof(iscsit_global_t, global_deleted_target_list);
831 if (mdb_pwalk("list", iscsi_tgt_walk_cb, idc, list_addr) == -1) {
832 mdb_warn("list walk failed for deleted target list");
833 return (DCMD_ERR);
836 return (DCMD_OK);
839 static int
840 iscsi_walk_all_conn(iscsi_dcmd_ctrl_t *idc)
842 uintptr_t idm_global_addr;
843 uintptr_t list_addr;
844 GElf_Sym sym;
846 /* Walk initiator connections */
847 if (mdb_lookup_by_name("idm", &sym) == -1) {
848 mdb_warn("failed to find symbol 'idm'");
849 return (DCMD_ERR);
851 idm_global_addr = (uintptr_t)sym.st_value;
852 /* Walk connection list associated with the initiator */
853 list_addr = idm_global_addr + offsetof(idm_global_t, idm_ini_conn_list);
854 if (mdb_pwalk("list", iscsi_conn_walk_cb, idc, list_addr) == -1) {
855 mdb_warn("list walk failed for initiator connections");
856 return (DCMD_ERR);
859 /* Walk connection list associated with the target */
860 list_addr = idm_global_addr + offsetof(idm_global_t, idm_tgt_conn_list);
861 if (mdb_pwalk("list", iscsi_conn_walk_cb, idc, list_addr) == -1) {
862 mdb_warn("list walk failed for target service instances");
863 return (DCMD_ERR);
866 return (DCMD_OK);
869 /*ARGSUSED*/
870 static int
871 iscsi_tpg_walk_cb(uintptr_t addr, const void *list_walker_data,
872 void *idc_void)
874 /* We don't particularly care about the list walker data */
875 iscsi_dcmd_ctrl_t *idc = idc_void;
876 int rc;
878 rc = iscsi_tpg_impl(addr, idc);
880 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR);
883 /*ARGSUSED*/
884 static int
885 iscsi_tgt_walk_cb(uintptr_t addr, const void *list_walker_data,
886 void *idc_void)
888 /* We don't particularly care about the list walker data */
889 iscsi_dcmd_ctrl_t *idc = idc_void;
890 int rc;
892 rc = iscsi_tgt_impl(addr, idc);
894 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR);
897 /*ARGSUSED*/
898 static int
899 iscsi_tpgt_walk_cb(uintptr_t addr, const void *list_walker_data,
900 void *idc_void)
902 /* We don't particularly care about the list walker data */
903 iscsi_dcmd_ctrl_t *idc = idc_void;
904 int rc;
906 rc = iscsi_tpgt_impl(addr, idc);
908 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR);
911 /*ARGSUSED*/
912 static int
913 iscsi_portal_walk_cb(uintptr_t addr, const void *list_walker_data,
914 void *idc_void)
916 /* We don't particularly care about the list walker data */
917 iscsi_dcmd_ctrl_t *idc = idc_void;
918 int rc;
920 rc = iscsi_portal_impl(addr, idc);
922 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR);
925 /*ARGSUSED*/
926 static int
927 iscsi_sess_walk_cb(uintptr_t addr, const void *list_walker_data,
928 void *idc_void)
930 /* We don't particularly care about the list walker data */
931 iscsi_dcmd_ctrl_t *idc = idc_void;
932 int rc;
934 rc = iscsi_sess_impl(addr, idc);
936 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR);
939 /*ARGSUSED*/
940 static int
941 iscsi_sess_conn_walk_cb(uintptr_t addr, const void *list_walker_data,
942 void *idc_void)
944 /* We don't particularly care about the list walker data */
945 iscsi_dcmd_ctrl_t *idc = idc_void;
946 iscsit_conn_t ict;
947 int rc;
950 * This function is different from iscsi_conn_walk_cb because
951 * we get an iscsit_conn_t instead of an idm_conn_t
953 * Read iscsit_conn_t, use to get idm_conn_t pointer
955 if (mdb_vread(&ict, sizeof (iscsit_conn_t), addr) !=
956 sizeof (iscsit_conn_t)) {
957 return (DCMD_ERR);
959 rc = iscsi_conn_impl((uintptr_t)ict.ict_ic, idc);
961 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR);
964 /*ARGSUSED*/
965 static int
966 iscsi_conn_walk_cb(uintptr_t addr, const void *list_walker_data,
967 void *idc_void)
969 /* We don't particularly care about the list walker data */
970 iscsi_dcmd_ctrl_t *idc = idc_void;
971 int rc;
973 rc = iscsi_conn_impl(addr, idc);
975 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR);
978 /*ARGSUSED*/
979 static int
980 iscsi_buffer_walk_cb(uintptr_t addr, const void *list_walker_data,
981 void *idc_void)
983 /* We don't particularly care about the list walker data */
984 iscsi_dcmd_ctrl_t *idc = idc_void;
985 int rc;
987 rc = iscsi_buffer_impl(addr, idc);
989 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR);
992 /*ARGSUSED*/
993 static int
994 iscsi_svc_walk_cb(uintptr_t addr, const void *list_walker_data,
995 void *idc_void)
997 iscsi_dcmd_ctrl_t *idc = idc_void;
998 int rc;
1000 rc = iscsi_svc_impl(addr, idc);
1002 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR);
1005 /*ARGSUSED*/
1006 static int
1007 iscsi_ini_hba_walk_cb(uintptr_t addr, const void *vhba, void *idc_void)
1010 iscsi_dcmd_ctrl_t *idc = idc_void;
1011 int rc;
1013 rc = iscsi_ini_hba_impl(addr, idc);
1015 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR);
1018 static int
1019 iscsi_ini_sess_walk_cb(uintptr_t addr, const void *vsess, void *idc_void)
1021 int rc;
1023 if (vsess == NULL) {
1024 return (WALK_ERR);
1027 rc = iscsi_print_ini_sess(addr, (iscsi_sess_t *)vsess,
1028 (iscsi_dcmd_ctrl_t *)idc_void);
1030 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR);
1033 /*ARGSUSED*/
1034 static int
1035 iscsi_ini_conn_walk_cb(uintptr_t addr, const void *vconn, void *idc_void)
1037 const iscsi_conn_t *ict = vconn;
1038 int rc;
1040 if (vconn == NULL) {
1041 return (WALK_ERR);
1045 * Look up the idm_conn_t in the iscsi_conn_t and call the general
1046 * connection handler.
1048 rc = iscsi_conn_impl((uintptr_t)ict->conn_ic,
1049 (iscsi_dcmd_ctrl_t *)idc_void);
1051 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR);
1054 static int
1055 iscsi_ini_lun_walk_cb(uintptr_t addr, const void *vlun, void *idc_void)
1057 int rc;
1059 if (vlun == NULL) {
1060 return (WALK_ERR);
1063 rc = iscsi_print_ini_lun(addr, (iscsi_lun_t *)vlun,
1064 (iscsi_dcmd_ctrl_t *)idc_void);
1066 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR);
1070 static int
1071 iscsi_tgt_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc)
1073 iscsit_tgt_t tgt;
1074 uintptr_t avl_addr, rc_addr, states_addr;
1075 char tgt_name[MAX_ISCSI_NODENAMELEN];
1076 int verbose, states, rc_audit;
1079 * Read iscsit_tgt_t
1081 if (mdb_vread(&tgt, sizeof (iscsit_tgt_t), addr) !=
1082 sizeof (iscsit_tgt_t)) {
1083 return (DCMD_ERR);
1087 * Read target name if available
1089 if ((tgt.target_name == NULL) ||
1090 (mdb_readstr(tgt_name, sizeof (tgt_name),
1091 (uintptr_t)tgt.target_name) == -1)) {
1092 strcpy(tgt_name, "N/A");
1096 * Brief output
1098 * iscsit_tgt_t pointer
1099 * iscsit_tgt_t.target_stmf_state
1100 * iscsit_tgt_t.target_sess_list.avl_numnodes (session count)
1101 * iscsit_tgt_t.target_name;
1104 verbose = idc->idc_verbose;
1105 states = idc->u.child.idc_states;
1106 rc_audit = idc->u.child.idc_rc_audit;
1108 /* For now we will ignore the verbose flag */
1109 if (idc->u.child.idc_tgt) {
1110 /* Print target data */
1111 if (idc->idc_header) {
1112 mdb_printf("%<u>%-19s %-4s %-8s%</u>\n",
1113 "iscsit_tgt_t", "Sess", "State");
1115 mdb_printf("%-19p %-4d %-8d\n", addr,
1116 tgt.target_sess_list.avl_numnodes,
1117 tgt.target_state);
1118 mdb_printf(" %s\n", tgt_name);
1120 /* Indent and disable verbose for any child structures */
1121 mdb_inc_indent(4);
1122 idc->idc_verbose = 0;
1126 * Print states if requested
1128 if (idc->u.child.idc_tgt && states) {
1129 states_addr = addr + offsetof(iscsit_tgt_t, target_state_audit);
1131 mdb_printf("State History(target_state_audit):\n");
1132 if (iscsi_sm_audit_impl(states_addr) != DCMD_OK)
1133 return (DCMD_ERR);
1134 idc->u.child.idc_states = 0;
1138 * Print refcnt audit data if requested
1140 if (idc->u.child.idc_tgt && rc_audit) {
1141 mdb_printf("Reference History(target_sess_refcnt):\n");
1142 rc_addr = addr +
1143 offsetof(iscsit_tgt_t, target_sess_refcnt);
1144 if (iscsi_refcnt_impl(rc_addr) != DCMD_OK)
1145 return (DCMD_ERR);
1147 mdb_printf("Reference History(target_refcnt):\n");
1148 rc_addr = addr +
1149 offsetof(iscsit_tgt_t, target_refcnt);
1151 if (iscsi_refcnt_impl(rc_addr) != DCMD_OK)
1152 return (DCMD_ERR);
1153 idc->u.child.idc_rc_audit = 0;
1156 /* Any child objects to walk? */
1157 if (idc->u.child.idc_tpgt || idc->u.child.idc_portal) {
1159 if (idc->u.child.idc_tgt) {
1160 idc->idc_header = 1;
1163 /* Walk TPGT tree */
1164 avl_addr = addr +
1165 offsetof(iscsit_tgt_t, target_tpgt_list);
1166 if (mdb_pwalk("avl", iscsi_tpgt_walk_cb, idc,
1167 avl_addr) == -1) {
1168 mdb_warn("target tpgt list walk failed");
1169 (void) mdb_dec_indent(4);
1170 return (DCMD_ERR);
1174 if (idc->u.child.idc_sess || idc->u.child.idc_conn ||
1175 idc->u.child.idc_task || idc->u.child.idc_buffer) {
1177 if (idc->u.child.idc_tgt || idc->u.child.idc_tpgt ||
1178 idc->u.child.idc_portal) {
1179 idc->idc_header = 1;
1182 /* Walk sess tree */
1183 avl_addr = addr + offsetof(iscsit_tgt_t, target_sess_list);
1184 if (mdb_pwalk("avl", iscsi_sess_walk_cb, idc,
1185 avl_addr) == -1) {
1186 mdb_warn("target sess list walk failed");
1187 (void) mdb_dec_indent(4);
1188 return (DCMD_ERR);
1192 /* If tgts were handled decrease indent and reset header */
1193 if (idc->u.child.idc_tgt) {
1194 idc->idc_header = 0;
1195 mdb_dec_indent(4);
1198 idc->idc_verbose = verbose;
1199 idc->u.child.idc_states = states;
1200 idc->u.child.idc_rc_audit = rc_audit;
1201 return (DCMD_OK);
1204 static int
1205 iscsi_tpgt_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc)
1207 iscsit_tpgt_t tpgt;
1208 iscsit_tpg_t tpg;
1209 uintptr_t avl_addr, tpg_addr, rc_addr;
1210 int rc_audit;
1213 * Read iscsit_tpgt_t
1215 if (mdb_vread(&tpgt, sizeof (iscsit_tpgt_t), addr) !=
1216 sizeof (iscsit_tpgt_t)) {
1217 return (DCMD_ERR);
1220 tpg_addr = (uintptr_t)tpgt.tpgt_tpg;
1223 * Read iscsit_tpg_t
1225 if (mdb_vread(&tpg, sizeof (iscsit_tpg_t), tpg_addr) !=
1226 sizeof (iscsit_tpg_t)) {
1227 return (DCMD_ERR);
1230 rc_audit = idc->u.child.idc_rc_audit;
1233 * Brief output
1235 * iscsit_tpgt_t pointer
1236 * iscsit_tpg_t pointer
1237 * iscsit_tpg_t.tpg_name
1238 * iscsit_tpgt_t.tpgt_tag;
1241 /* For now we will ignore the verbose flag */
1242 if (idc->u.child.idc_tpgt) {
1243 /* Print target data */
1244 if (idc->idc_header) {
1245 mdb_printf("%<u>%-?s %-?s %-18s %-6s%</u>\n",
1246 "iscsit_tpgt_t", "iscsit_tpg_t", "Name", "Tag");
1248 mdb_printf("%?p %?p %-18s 0x%04x\n", addr, tpgt.tpgt_tpg,
1249 tpg.tpg_name, tpgt.tpgt_tag);
1251 if (rc_audit) {
1252 (void) mdb_inc_indent(4);
1254 mdb_printf("Reference History(tpgt_refcnt):\n");
1255 rc_addr = addr + offsetof(iscsit_tpgt_t, tpgt_refcnt);
1256 if (iscsi_refcnt_impl(rc_addr) != DCMD_OK)
1257 return (DCMD_ERR);
1259 idc->u.child.idc_rc_audit = 0;
1260 (void) mdb_dec_indent(4);
1265 * Assume for now that anyone interested in TPGT wants to see the
1266 * portals as well. Enable idc_header for the portals.
1268 idc->idc_header = 1;
1269 (void) mdb_inc_indent(4);
1270 avl_addr = tpg_addr + offsetof(iscsit_tpg_t, tpg_portal_list);
1271 if (mdb_pwalk("avl", iscsi_portal_walk_cb, idc, avl_addr) == -1) {
1272 mdb_warn("portal list walk failed");
1273 (void) mdb_dec_indent(4);
1274 return (DCMD_ERR);
1276 (void) mdb_dec_indent(4);
1277 idc->idc_header = 0;
1279 idc->u.child.idc_rc_audit = rc_audit;
1280 return (DCMD_OK);
1283 static int
1284 iscsi_tpg_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc)
1286 iscsit_tpg_t tpg;
1287 uintptr_t avl_addr, rc_addr;
1288 int rc_audit = 0;
1290 rc_audit = idc->u.child.idc_rc_audit;
1293 * Read iscsit_tpg_t
1295 if (mdb_vread(&tpg, sizeof (iscsit_tpg_t), addr) !=
1296 sizeof (iscsit_tpg_t)) {
1297 return (DCMD_ERR);
1301 * Brief output
1303 * iscsit_tpgt_t pointer
1304 * iscsit_tpg_t pointer
1305 * iscsit_tpg_t.tpg_name
1306 * iscsit_tpgt_t.tpgt_tag;
1309 /* Print tpg data */
1310 if (idc->u.child.idc_tpg) {
1311 if (idc->idc_header) {
1312 mdb_printf("%<u>%-?s %-18s%</u>\n",
1313 "iscsit_tpg_t", "Name");
1315 mdb_printf("%?p %-18s\n", addr, tpg.tpg_name);
1317 (void) mdb_inc_indent(4);
1319 if (rc_audit) {
1320 mdb_printf("Reference History(tpg_refcnt):\n");
1321 rc_addr = addr + offsetof(iscsit_tpg_t, tpg_refcnt);
1322 if (iscsi_refcnt_impl(rc_addr) != DCMD_OK) {
1323 return (DCMD_ERR);
1325 idc->u.child.idc_rc_audit = 0;
1329 if (idc->u.child.idc_portal) {
1330 if (idc->u.child.idc_tpg) {
1331 idc->idc_header = 1;
1334 avl_addr = addr + offsetof(iscsit_tpg_t, tpg_portal_list);
1335 if (mdb_pwalk("avl", iscsi_portal_walk_cb, idc,
1336 avl_addr) == -1) {
1337 mdb_warn("portal list walk failed");
1338 if (idc->u.child.idc_tpg) {
1339 (void) mdb_dec_indent(4);
1341 return (DCMD_ERR);
1345 if (idc->u.child.idc_tpg) {
1346 (void) mdb_dec_indent(4);
1347 idc->idc_header = 0;
1350 idc->u.child.idc_rc_audit = rc_audit;
1351 return (DCMD_OK);
1354 static int
1355 iscsi_portal_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc)
1357 iscsit_portal_t portal;
1358 char portal_addr[PORTAL_STR_LEN];
1359 uintptr_t rc_addr;
1361 if (idc->u.child.idc_portal) {
1363 * Read iscsit_portal_t
1365 if (mdb_vread(&portal, sizeof (iscsit_portal_t), addr) !=
1366 sizeof (iscsit_portal_t)) {
1367 return (DCMD_ERR);
1370 /* Print portal data */
1371 if (idc->idc_header) {
1372 mdb_printf("%<u>%-?s %-?s %-30s%</u>\n",
1373 "iscsit_portal_t", "idm_svc_t", "IP:Port");
1374 idc->idc_header = 0;
1376 sa_to_str(&portal.portal_addr, portal_addr);
1377 mdb_printf("%?p %?p %s\n", addr, portal.portal_svc,
1378 portal.portal_default ? "(Default)" : portal_addr);
1380 if (idc->u.child.idc_rc_audit) {
1381 (void) mdb_inc_indent(4);
1382 mdb_printf("Reference History(portal_refcnt):\n");
1383 rc_addr = addr + offsetof(iscsit_portal_t,
1384 portal_refcnt);
1385 if (iscsi_refcnt_impl(rc_addr) != DCMD_OK) {
1386 return (DCMD_ERR);
1388 (void) mdb_dec_indent(4);
1392 return (DCMD_OK);
1395 static int
1396 iscsi_sess_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc)
1398 iscsit_sess_t ist;
1399 iscsi_sess_t ini_sess;
1400 uintptr_t list_addr, states_addr, rc_addr;
1401 char ini_name[80];
1402 char tgt_name[80];
1403 int verbose, states, rc_audit;
1405 if (idc->idc_ini) {
1406 if ((mdb_vread(&ini_sess, sizeof (iscsi_sess_t),
1407 (uintptr_t)addr)) != sizeof (iscsi_sess_t)) {
1408 mdb_warn("Failed to read initiator session\n");
1409 return (DCMD_ERR);
1411 if (iscsi_print_ini_sess(addr, &ini_sess, idc) != DCMD_OK) {
1412 return (DCMD_ERR);
1414 return (DCMD_OK);
1417 * Read iscsit_sess_t
1419 if (mdb_vread(&ist, sizeof (iscsit_sess_t), addr) !=
1420 sizeof (iscsit_sess_t)) {
1421 return (DCMD_ERR);
1425 * Brief output
1427 * iscsit_sess_t pointer
1428 * iscsit_sess_t.ist_state/iscsit_sess_t.ist_ffp_conn_count
1429 * iscsit_sess_t.ist_tsih
1430 * iscsit_sess_t.ist_initiator_name
1433 verbose = idc->idc_verbose;
1434 states = idc->u.child.idc_states;
1435 rc_audit = idc->u.child.idc_rc_audit;
1437 if (idc->u.child.idc_sess) {
1438 if (verbose) {
1440 * Read initiator name if available
1442 if ((ist.ist_initiator_name == NULL) ||
1443 (mdb_readstr(ini_name, sizeof (ini_name),
1444 (uintptr_t)ist.ist_initiator_name) == -1)) {
1445 strcpy(ini_name, "N/A");
1449 * Read target name if available
1451 if ((ist.ist_target_name == NULL) ||
1452 (mdb_readstr(tgt_name, sizeof (tgt_name),
1453 (uintptr_t)ist.ist_target_name) == -1)) {
1454 strcpy(tgt_name, "N/A");
1457 mdb_printf("Session %p\n", addr);
1458 mdb_printf("%16s: %d\n", "State",
1459 ist.ist_state);
1460 mdb_printf("%16s: %d\n", "Last State",
1461 ist.ist_last_state);
1462 mdb_printf("%16s: %d\n", "FFP Connections",
1463 ist.ist_ffp_conn_count);
1464 mdb_printf("%16s: %02x%02x%02x%02x%02x%02x\n", "ISID",
1465 ist.ist_isid[0], ist.ist_isid[1], ist.ist_isid[2],
1466 ist.ist_isid[3], ist.ist_isid[4], ist.ist_isid[5]);
1467 mdb_printf("%16s: 0x%04x\n", "TSIH",
1468 ist.ist_tsih);
1469 mdb_printf("%16s: %s\n", "Initiator IQN",
1470 ini_name);
1471 mdb_printf("%16s: %s\n", "Target IQN",
1472 tgt_name);
1473 mdb_printf("%16s: %08x\n", "ExpCmdSN",
1474 ist.ist_expcmdsn);
1475 mdb_printf("%16s: %08x\n", "MaxCmdSN",
1476 ist.ist_maxcmdsn);
1478 idc->idc_verbose = 0;
1479 } else {
1480 /* Print session data */
1481 if (idc->idc_header) {
1482 mdb_printf("%<u>%-?s %10s %-12s %-6s%</u>\n",
1483 "iscsit_sess_t", "State/Conn", "ISID",
1484 "TSIH");
1486 mdb_printf("%?p %4d/%-4d %02x%02x%02x%02x%02x%02x "
1487 "0x%04x\n", addr,
1488 ist.ist_state, ist.ist_ffp_conn_count,
1489 ist.ist_isid[0], ist.ist_isid[1], ist.ist_isid[2],
1490 ist.ist_isid[3], ist.ist_isid[4], ist.ist_isid[5],
1491 ist.ist_tsih);
1495 * Indent for any child structures
1497 (void) mdb_inc_indent(4);
1501 * Print states if requested
1503 if (idc->u.child.idc_sess && states) {
1504 states_addr = addr + offsetof(iscsit_sess_t, ist_state_audit);
1506 mdb_printf("State History(ist_state_audit):\n");
1507 if (iscsi_sm_audit_impl(states_addr) != DCMD_OK)
1508 return (DCMD_ERR);
1510 /* Don't print state history for child objects */
1511 idc->u.child.idc_states = 0;
1515 * Print refcnt audit data if requested
1517 if (idc->u.child.idc_sess && rc_audit) {
1518 mdb_printf("Reference History(ist_refcnt):\n");
1519 rc_addr = addr +
1520 offsetof(iscsit_sess_t, ist_refcnt);
1521 if (iscsi_refcnt_impl(rc_addr) != DCMD_OK)
1522 return (DCMD_ERR);
1524 /* Don't print audit data for child objects */
1525 idc->u.child.idc_rc_audit = 0;
1528 /* Any child objects to walk? */
1529 if (idc->u.child.idc_conn || idc->u.child.idc_task ||
1530 idc->u.child.idc_buffer) {
1532 * If a session has been printed enable headers for
1533 * any child structs.
1535 if (idc->u.child.idc_sess) {
1536 idc->idc_header = 1;
1539 /* Walk conn list */
1540 list_addr = addr + offsetof(iscsit_sess_t, ist_conn_list);
1541 if (mdb_pwalk("list", iscsi_sess_conn_walk_cb, idc,
1542 list_addr) == -1) {
1543 mdb_warn("session conn list walk failed");
1544 (void) mdb_dec_indent(4);
1545 return (DCMD_ERR);
1549 /* If a session was handled decrease indent and reset header. */
1550 if (idc->u.child.idc_sess) {
1551 idc->idc_header = 0;
1552 mdb_dec_indent(4);
1555 idc->idc_verbose = verbose;
1556 idc->u.child.idc_states = states;
1557 idc->u.child.idc_rc_audit = rc_audit;
1559 return (DCMD_OK);
1562 static int
1563 iscsi_print_ini_sess(uintptr_t addr, iscsi_sess_t *sess,
1564 iscsi_dcmd_ctrl_t *idc)
1567 int verbose, states;
1568 uintptr_t states_addr;
1570 verbose = idc->idc_verbose;
1571 states = idc->u.child.idc_states;
1574 if (idc->u.child.idc_sess) {
1575 if (!idc->idc_verbose) {
1576 if (idc->idc_header) {
1577 mdb_printf("%<u>%-?s %-4s %-8s%</u>\n",
1578 "iscsi_sess_t", "Type", "State");
1580 mdb_printf("%-19p %-4d %-8d\n", addr,
1581 sess->sess_type, sess->sess_state);
1582 } else {
1583 mdb_printf("Session %p\n", addr);
1584 mdb_printf("%22s: %d\n", "State",
1585 sess->sess_state);
1586 mdb_printf("%22s: %d\n", "Last State",
1587 sess->sess_prev_state);
1588 mdb_printf("%22s: %s\n", "Session Name",
1589 sess->sess_name);
1590 mdb_printf("%22s: %s\n", "Alias",
1591 sess->sess_alias);
1592 mdb_printf("%22s: %08x\n", "CmdSN",
1593 sess->sess_cmdsn);
1594 mdb_printf("%22s: %08x\n", "ExpCmdSN",
1595 sess->sess_expcmdsn);
1596 mdb_printf("%22s: %08x\n", "MaxCmdSN",
1597 sess->sess_maxcmdsn);
1598 mdb_printf("%22s: %p\n", "Pending Queue Head",
1599 sess->sess_queue_pending.head);
1600 mdb_printf("%22s: %p\n", "Completion Queue Head",
1601 sess->sess_queue_completion.head);
1602 mdb_printf("%22s: %p\n", "Connnection List Head",
1603 sess->sess_conn_list);
1605 idc->idc_verbose = 0;
1608 /* Indent for any child structures */
1609 mdb_inc_indent(4);
1611 if (idc->u.child.idc_states) {
1612 states_addr = (uintptr_t)addr +
1613 offsetof(iscsi_sess_t, sess_state_audit);
1615 mdb_printf("State History(sess_state_audit):\n");
1616 if (iscsi_sm_audit_impl(states_addr) != DCMD_OK) {
1617 (void) mdb_dec_indent(4);
1618 return (DCMD_ERR);
1620 idc->u.child.idc_states = 0;
1624 if (idc->u.child.idc_lun && sess->sess_lun_list) {
1625 if (idc->u.child.idc_sess) {
1626 idc->idc_header = 1;
1629 if (mdb_pwalk("iscsi_ini_lun", iscsi_ini_lun_walk_cb, idc,
1630 (uintptr_t)sess->sess_lun_list) == -1) {
1631 mdb_warn("iscsi_ini_lun walk failed");
1632 (void) mdb_dec_indent(4);
1633 return (DCMD_ERR);
1638 /* If requested print the cmds in the session queue */
1639 if (idc->u.child.idc_cmd) {
1641 /* If any other structs printed enable header */
1642 if (idc->u.child.idc_sess || idc->u.child.idc_lun) {
1643 idc->idc_header = 1;
1646 if (sess->sess_queue_pending.head) {
1647 if (mdb_pwalk("iscsi_ini_cmd", iscsi_ini_cmd_walk_cb,
1648 idc, (uintptr_t)sess->sess_queue_pending.head)
1649 == -1) {
1650 mdb_warn("list walk failed for iscsi cmds");
1653 if (sess->sess_queue_completion.head) {
1654 if (mdb_pwalk("iscsi_ini_cmd", iscsi_ini_cmd_walk_cb,
1655 idc, (uintptr_t)sess->sess_queue_completion.head)
1656 == -1) {
1657 mdb_warn("list walk failed for iscsi cmds");
1662 /* If connections or cmds requested walk the connections */
1663 if (idc->u.child.idc_conn || idc->u.child.idc_cmd) {
1665 * If idc_conn is not set don't enable header or the
1666 * commands may get extraneous headers.
1668 if (idc->u.child.idc_conn) {
1669 idc->idc_header = 1;
1671 if (mdb_pwalk("iscsi_ini_conn", iscsi_ini_conn_walk_cb, idc,
1672 (uintptr_t)sess->sess_conn_list) == -1) {
1673 mdb_warn("iscsi_ini_conn walk failed");
1674 return (DCMD_ERR);
1678 /* If sessions were handled decrease indent and reset header */
1679 if (idc->u.child.idc_sess) {
1680 idc->idc_header = 0;
1681 mdb_dec_indent(4);
1684 idc->u.child.idc_states = states;
1685 idc->idc_verbose = verbose;
1686 return (DCMD_OK);
1690 static int
1691 iscsi_conn_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc)
1693 uintptr_t idm_global_addr, states_addr, rc_addr;
1694 uintptr_t task_addr, task_ptr;
1695 GElf_Sym sym;
1696 idm_task_t idt;
1697 idm_conn_t ic;
1698 iscsit_conn_t ict;
1699 iscsi_conn_t ini_conn;
1700 char *conn_type;
1701 int task_idx;
1702 char laddr[PORTAL_STR_LEN];
1703 char raddr[PORTAL_STR_LEN];
1704 int verbose, states, rc_audit;
1707 * Get pointer to task table
1710 if (mdb_lookup_by_name("idm", &sym) == -1) {
1711 mdb_warn("failed to find symbol 'idm'");
1712 return (DCMD_ERR);
1715 idm_global_addr = (uintptr_t)sym.st_value;
1717 if (mdb_vread(&task_ptr, sizeof (uintptr_t),
1718 idm_global_addr + offsetof(idm_global_t, idm_taskid_table)) !=
1719 sizeof (uintptr_t)) {
1720 mdb_warn("Failed to read address of task table");
1721 return (DCMD_ERR);
1725 * Read idm_conn_t
1727 if (mdb_vread(&ic, sizeof (idm_conn_t), addr) != sizeof (idm_conn_t)) {
1728 return (DCMD_ERR);
1732 * If filter bits are set to only print targets or only initiators
1733 * skip entries of the other type.
1735 if (!(idc->idc_ini && idc->idc_tgt) &&
1736 ((idc->idc_ini && (ic.ic_conn_type != CONN_TYPE_INI)) ||
1737 (idc->idc_tgt && (ic.ic_conn_type != CONN_TYPE_TGT)))) {
1738 return (DCMD_OK);
1742 conn_type = (ic.ic_conn_type == CONN_TYPE_INI) ? "Ini" :
1743 (ic.ic_conn_type == CONN_TYPE_TGT) ? "Tgt" : "Unk";
1746 * Brief output
1748 * idm_conn_t pointer
1749 * idm_conn_t.ic_conn_type
1750 * idm_conn_t.ic_statet+idm_conn_t.ic_ffp
1753 verbose = idc->idc_verbose;
1754 states = idc->u.child.idc_states;
1755 rc_audit = idc->u.child.idc_rc_audit;
1758 * If targets(-T) and/or initiators (-I) are specifically requested,
1759 * fetch the iscsit_conn_t and/or iscsi_conn_t struct as a sanity
1760 * check and for use below.
1762 if (idc->idc_tgt && IDM_CONN_ISTGT(&ic)) {
1763 if (mdb_vread(&ict, sizeof (iscsit_conn_t),
1764 (uintptr_t)ic.ic_handle) !=
1765 sizeof (iscsit_conn_t)) {
1766 mdb_printf("Failed to read target connection "
1767 "handle data\n");
1768 return (DCMD_ERR);
1772 if (idc->idc_ini && IDM_CONN_ISINI(&ic)) {
1773 if (mdb_vread(&ini_conn, sizeof (iscsi_conn_t),
1774 (uintptr_t)ic.ic_handle) !=
1775 sizeof (iscsi_conn_t)) {
1776 mdb_printf("Failed to read initiator "
1777 "connection handle data\n");
1778 return (DCMD_ERR);
1782 if (idc->u.child.idc_conn) {
1783 if (idc->idc_verbose) {
1784 mdb_printf("IDM Conn %p\n", addr);
1785 if (ic.ic_conn_type == CONN_TYPE_TGT) {
1786 iscsi_print_iscsit_conn_data(&ic);
1787 } else {
1788 iscsi_print_ini_conn_data(&ic);
1790 idc->idc_verbose = 0;
1791 } else {
1792 /* Print connection data */
1793 if (idc->idc_header) {
1794 mdb_printf("%<u>%-?s %-6s %-10s %12s%</u>\n",
1795 "idm_conn_t", "Type", "Transport",
1796 "State/FFP");
1798 mdb_printf("%?p %-6s %-10s %6d/%-6d\n", addr, conn_type,
1799 (ic.ic_transport_type ==
1800 IDM_TRANSPORT_TYPE_ISER) ? "ISER_IB" :
1801 (ic.ic_transport_type ==
1802 IDM_TRANSPORT_TYPE_SOCKETS) ? "SOCKETS" :
1803 "N/A",
1804 ic.ic_state, ic.ic_ffp);
1805 if (idc->u.child.idc_print_ip) {
1806 sa_to_str(&ic.ic_laddr, laddr);
1807 sa_to_str(&ic.ic_raddr, raddr);
1808 mdb_printf(" L%s R%s\n",
1809 laddr, raddr);
1813 /* Indent for any child structs */
1814 mdb_inc_indent(4);
1818 * Print states if requested
1820 if (idc->u.child.idc_conn && states) {
1821 states_addr = addr + offsetof(idm_conn_t, ic_state_audit);
1823 mdb_printf("State History(ic_state_audit):\n");
1824 if (iscsi_sm_audit_impl(states_addr) != DCMD_OK)
1825 return (DCMD_ERR);
1828 * If targets are specifically requested show the
1829 * state audit for the target specific connection struct
1831 if (idc->idc_tgt && IDM_CONN_ISTGT(&ic)) {
1832 states_addr = (uintptr_t)ic.ic_handle +
1833 offsetof(iscsit_conn_t, ict_login_sm) +
1834 offsetof(iscsit_conn_login_t, icl_state_audit);
1836 mdb_printf("State History(icl_state_audit):\n");
1837 if (iscsi_sm_audit_impl(states_addr) != DCMD_OK) {
1838 return (DCMD_ERR);
1843 * If initiators are specifically requested show the
1844 * state audit for the initiator specific connection struct
1846 if (idc->idc_ini && IDM_CONN_ISINI(&ic)) {
1847 states_addr = (uintptr_t)ic.ic_handle +
1848 offsetof(iscsi_conn_t, conn_state_audit);
1850 mdb_printf("State History(iscsi_conn_t "
1851 "conn_state_audit):\n");
1852 if (iscsi_sm_audit_impl(states_addr) != DCMD_OK) {
1853 return (DCMD_ERR);
1857 /* Don't print state history for child objects */
1858 idc->u.child.idc_states = 0;
1862 * Print refcnt audit data for the connection struct if requested.
1864 if (idc->u.child.idc_conn && rc_audit) {
1865 mdb_printf("Reference History(ic_refcnt):\n");
1866 rc_addr = addr + offsetof(idm_conn_t, ic_refcnt);
1867 if (iscsi_refcnt_impl(rc_addr) != DCMD_OK)
1868 return (DCMD_ERR);
1871 * If targets are specifically requested show the
1872 * Refcounts for the target specific connection struct
1874 if (idc->idc_tgt && IDM_CONN_ISTGT(&ic)) {
1875 mdb_printf("Reference History(ict_refcnt):\n");
1876 rc_addr = (uintptr_t)ic.ic_handle +
1877 offsetof(iscsit_conn_t, ict_refcnt);
1878 if (iscsi_refcnt_impl(rc_addr) != DCMD_OK) {
1879 return (DCMD_ERR);
1882 mdb_printf("Reference History(ict_dispatch_refcnt):\n");
1883 rc_addr = (uintptr_t)ic.ic_handle +
1884 offsetof(iscsit_conn_t, ict_dispatch_refcnt);
1885 if (iscsi_refcnt_impl(rc_addr) != DCMD_OK) {
1886 return (DCMD_ERR);
1890 /* Don't print audit data for child objects */
1891 idc->u.child.idc_rc_audit = 0;
1894 task_idx = 0;
1896 if (idc->u.child.idc_task || idc->u.child.idc_buffer) {
1898 if (idc->u.child.idc_conn) {
1899 idc->idc_header = 1;
1902 while (task_idx < IDM_TASKIDS_MAX) {
1904 * Read the next idm_task_t
1906 if (mdb_vread(&task_addr, sizeof (uintptr_t),
1907 task_ptr) != sizeof (uintptr_t)) {
1908 mdb_warn("Failed to read task pointer");
1909 return (DCMD_ERR);
1912 if (task_addr == (uintptr_t)NULL) {
1913 task_ptr += sizeof (uintptr_t);
1914 task_idx++;
1915 continue;
1918 if (mdb_vread(&idt, sizeof (idm_task_t), task_addr)
1919 != sizeof (idm_task_t)) {
1920 mdb_warn("Failed to read task pointer");
1921 return (DCMD_ERR);
1924 if (((uintptr_t)idt.idt_ic == addr) &&
1925 (idt.idt_state != TASK_IDLE)) {
1926 if (iscsi_i_task_impl(&idt, task_addr, idc)
1927 == -1) {
1928 mdb_warn("Failed to walk connection "
1929 "task tree");
1930 return (DCMD_ERR);
1934 task_ptr += sizeof (uintptr_t);
1935 task_idx++;
1939 if (idc->idc_ini && IDM_CONN_ISINI(&ic) && idc->u.child.idc_cmd) {
1940 if (idc->u.child.idc_conn || idc->u.child.idc_task) {
1941 idc->idc_header = 1;
1943 if (ini_conn.conn_queue_active.head &&
1944 (mdb_pwalk("iscsi_ini_cmd", iscsi_ini_cmd_walk_cb, idc,
1945 (uintptr_t)ini_conn.conn_queue_active.head) == -1)) {
1946 mdb_warn("list walk failed for iscsi cmds");
1948 if (ini_conn.conn_queue_idm_aborting.head &&
1949 (mdb_pwalk("iscsi_ini_cmd", iscsi_ini_cmd_walk_cb, idc,
1950 (uintptr_t)ini_conn.conn_queue_idm_aborting.head) == -1)) {
1951 mdb_warn("list walk failed for iscsi cmds");
1956 * If connection information was handled unset header and
1957 * decrease indent
1959 if (idc->u.child.idc_conn) {
1960 idc->idc_header = 0;
1961 mdb_dec_indent(4);
1964 idc->idc_verbose = verbose;
1965 idc->u.child.idc_states = states;
1966 idc->u.child.idc_rc_audit = rc_audit;
1968 return (DCMD_OK);
1971 static int
1972 iscsi_svc_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc)
1974 idm_svc_t svc;
1975 iser_svc_t iser_svc;
1976 uintptr_t rc_addr;
1978 if (mdb_vread(&svc, sizeof (idm_svc_t), addr) !=
1979 sizeof (idm_svc_t)) {
1980 return (DCMD_ERR);
1983 if (idc->u.child.idc_svc) {
1984 if (idc->idc_verbose) {
1985 mdb_printf("Service %p\n", addr);
1986 mdb_printf("%20s: %d\n", "Port",
1987 svc.is_svc_req.sr_port);
1988 mdb_printf("%20s: %d\n", "Online",
1989 svc.is_online);
1990 mdb_printf("%20s: %p\n", "Socket Service",
1991 svc.is_so_svc);
1992 mdb_printf("%20s: %p\n", "iSER Service",
1993 svc.is_iser_svc);
1994 } else {
1995 if (idc->idc_header) {
1996 mdb_printf("%<u>%-?s %-8s %-8s%</u>\n",
1997 "idm_svc_t", "Port", "Online");
1998 idc->idc_header = 0;
2001 mdb_printf("%?p %-8d %-8d\n", addr,
2002 svc.is_svc_req.sr_port, svc.is_online);
2005 if (idc->u.child.idc_rc_audit) {
2006 (void) mdb_inc_indent(4);
2007 mdb_printf("Reference History(is_refcnt):\n");
2008 rc_addr = addr + offsetof(idm_svc_t, is_refcnt);
2009 if (iscsi_refcnt_impl(rc_addr) != DCMD_OK) {
2010 (void) mdb_dec_indent(4);
2011 return (DCMD_ERR);
2014 if (svc.is_iser_svc != NULL) {
2015 mdb_printf("Reference History"
2016 "(iser_svc is_refcnt):\n");
2018 /* Sanity check the iser svc struct */
2019 if (mdb_vread(&iser_svc, sizeof (iser_svc_t),
2020 (uintptr_t)svc.is_iser_svc) !=
2021 sizeof (iser_svc_t)) {
2022 return (DCMD_ERR);
2025 rc_addr = (uintptr_t)svc.is_iser_svc +
2026 offsetof(iser_svc_t, is_refcnt);
2028 if (iscsi_refcnt_impl(rc_addr) != DCMD_OK) {
2029 return (DCMD_ERR);
2032 (void) mdb_dec_indent(4);
2035 return (DCMD_OK);
2038 static void
2039 iscsi_print_iscsit_conn_data(idm_conn_t *ic)
2041 iscsit_conn_t ict;
2042 char *csg;
2043 char *nsg;
2045 iscsi_print_idm_conn_data(ic);
2047 if (mdb_vread(&ict, sizeof (iscsit_conn_t),
2048 (uintptr_t)ic->ic_handle) != sizeof (iscsit_conn_t)) {
2049 mdb_printf("**Failed to read conn private data\n");
2050 return;
2053 mdb_printf("%20s: %p\n", "iSCSIT TGT Conn",
2054 ic->ic_handle);
2056 if (ict.ict_login_sm.icl_login_state != ILS_LOGIN_DONE) {
2057 switch (ict.ict_login_sm.icl_login_csg) {
2058 case ISCSI_SECURITY_NEGOTIATION_STAGE:
2059 csg = "Security";
2060 break;
2061 case ISCSI_OP_PARMS_NEGOTIATION_STAGE:
2062 csg = "Operational";
2063 break;
2064 case ISCSI_FULL_FEATURE_PHASE:
2065 csg = "FFP";
2066 break;
2067 default:
2068 csg = "Unknown";
2070 switch (ict.ict_login_sm.icl_login_nsg) {
2071 case ISCSI_SECURITY_NEGOTIATION_STAGE:
2072 nsg = "Security";
2073 break;
2074 case ISCSI_OP_PARMS_NEGOTIATION_STAGE:
2075 nsg = "Operational";
2076 break;
2077 case ISCSI_FULL_FEATURE_PHASE:
2078 nsg = "FFP";
2079 break;
2080 default:
2081 nsg = "Unknown";
2083 mdb_printf("%20s: %d\n", "Login State",
2084 ict.ict_login_sm.icl_login_state);
2085 mdb_printf("%20s: %d\n", "Login Last State",
2086 ict.ict_login_sm.icl_login_last_state);
2087 mdb_printf("%20s: %s\n", "CSG", csg);
2088 mdb_printf("%20s: %s\n", "NSG", nsg);
2089 mdb_printf("%20s: %d\n", "Transit",
2090 ict.ict_login_sm.icl_login_transit >> 7);
2091 mdb_printf("%20s: %p\n", "Request nvlist",
2092 ict.ict_login_sm.icl_request_nvlist);
2093 mdb_printf("%20s: %p\n", "Response nvlist",
2094 ict.ict_login_sm.icl_response_nvlist);
2095 mdb_printf("%20s: %p\n", "Negotiated nvlist",
2096 ict.ict_login_sm.icl_negotiated_values);
2097 if (ict.ict_login_sm.icl_login_state == ILS_LOGIN_ERROR) {
2098 mdb_printf("%20s: 0x%02x\n", "Error Class",
2099 ict.ict_login_sm.icl_login_resp_err_class);
2100 mdb_printf("%20s: 0x%02x\n", "Error Detail",
2101 ict.ict_login_sm.icl_login_resp_err_detail);
2104 mdb_printf("%20s: 0x%04x\n", "CID", ict.ict_cid);
2105 mdb_printf("%20s: 0x%08x\n", "StatSN", ict.ict_statsn);
2108 static void
2109 iscsi_print_ini_conn_data(idm_conn_t *ic)
2111 iscsi_conn_t ini_conn;
2113 iscsi_print_idm_conn_data(ic);
2115 if (mdb_vread(&ini_conn, sizeof (iscsi_conn_t),
2116 (uintptr_t)ic->ic_handle) != sizeof (iscsi_conn_t)) {
2117 mdb_printf("Failed to read conn private data\n");
2118 return;
2121 mdb_printf("%20s: %p\n", "iSCSI Ini Conn",
2122 ic->ic_handle);
2123 mdb_printf("%20s: %p\n", "Parent Session",
2124 ini_conn.conn_sess);
2125 mdb_printf("%20s: %d\n", "Conn State",
2126 ini_conn.conn_state);
2127 mdb_printf("%20s: %d\n", "Last Conn State",
2128 ini_conn.conn_prev_state);
2130 mdb_printf("%20s: %d\n", "Login Stage",
2131 ini_conn.conn_current_stage);
2132 mdb_printf("%20s: %d\n", "Next Login Stage",
2133 ini_conn.conn_next_stage);
2135 mdb_printf("%20s: 0x%08x\n", "Expected StatSN",
2136 ini_conn.conn_expstatsn);
2137 mdb_printf("%20s: %p\n", "Active Queue Head",
2138 ini_conn.conn_queue_active.head);
2139 mdb_printf("%20s: %d\n", "Abort Queue Head",
2140 ini_conn.conn_queue_idm_aborting.head);
2143 static void
2144 iscsi_print_idm_conn_data(idm_conn_t *ic)
2146 char laddr[PORTAL_STR_LEN];
2147 char raddr[PORTAL_STR_LEN];
2149 sa_to_str(&ic->ic_laddr, laddr);
2150 sa_to_str(&ic->ic_raddr, raddr);
2152 mdb_printf("%20s: %s\n", "Conn Type",
2153 ((ic->ic_conn_type == CONN_TYPE_TGT) ? "Target" :
2154 ((ic->ic_conn_type == CONN_TYPE_INI) ? "Initiator" :
2155 "Unknown")));
2156 if (ic->ic_conn_type == CONN_TYPE_TGT) {
2157 mdb_printf("%20s: %p\n", "Svc. Binding",
2158 ic->ic_svc_binding);
2160 mdb_printf("%20s: %s\n", "Transport",
2161 (ic->ic_transport_type == IDM_TRANSPORT_TYPE_ISER) ? "ISER_IB" :
2162 (ic->ic_transport_type == IDM_TRANSPORT_TYPE_SOCKETS) ? "SOCKETS" :
2163 "N/A");
2165 mdb_printf("%20s: %s\n", "Local IP", laddr);
2166 mdb_printf("%20s: %s\n", "Remote IP", raddr);
2167 mdb_printf("%20s: %d\n", "State",
2168 ic->ic_state);
2169 mdb_printf("%20s: %d\n", "Last State",
2170 ic->ic_last_state);
2171 mdb_printf("%20s: %d %s\n", "Refcount",
2172 ic->ic_refcnt.ir_refcnt,
2173 (ic->ic_refcnt.ir_waiting == REF_NOWAIT) ? "" :
2174 ((ic->ic_refcnt.ir_waiting == REF_WAIT_SYNC) ? "REF_WAIT_SYNC" :
2175 ((ic->ic_refcnt.ir_waiting == REF_WAIT_ASYNC) ? "REF_WAIT_ASYNC" :
2176 "UNKNOWN")));
2179 static int
2180 iscsi_i_task_impl(idm_task_t *idt, uintptr_t addr, iscsi_dcmd_ctrl_t *idc)
2182 uintptr_t list_addr, rc_addr;
2183 idm_conn_type_t conn_type;
2184 int verbose, states, rc_audit;
2186 conn_type = idm_conn_type((uintptr_t)idt->idt_ic);
2188 verbose = idc->idc_verbose;
2189 states = idc->u.child.idc_states;
2190 rc_audit = idc->u.child.idc_rc_audit;
2192 if (idc->u.child.idc_task) {
2193 if (verbose) {
2194 mdb_printf("Task %p\n", addr);
2195 (void) mdb_inc_indent(2);
2196 if (conn_type == CONN_TYPE_TGT) {
2197 iscsi_print_iscsit_task_data(idt);
2199 (void) mdb_dec_indent(2);
2200 } else {
2201 /* Print task data */
2202 if (idc->idc_header) {
2203 mdb_printf(
2204 "%<u>%-?s %-16s %-4s %-8s %-8s%</u>\n",
2205 "Tasks:", "State", "Ref",
2206 (conn_type == CONN_TYPE_TGT ? "TTT" :
2207 (conn_type == CONN_TYPE_INI ? "ITT" :
2208 "TT")), "Handle");
2210 mdb_printf("%?p %-16s %04x %08x %08x\n", addr,
2211 idm_ts_name[idt->idt_state],
2212 idt->idt_refcnt.ir_refcnt,
2213 idt->idt_tt, idt->idt_client_handle);
2216 idc->idc_header = 0;
2217 idc->idc_verbose = 0;
2220 * Print states if requested
2222 #if 0
2223 if (states) {
2224 states_addr = addr + offsetof(idm_task_t, idt_state_audit);
2226 (void) mdb_inc_indent(4);
2227 mdb_printf("State History(idt_state_audit):\n");
2228 if (iscsi_sm_audit_impl(states_addr) != DCMD_OK)
2229 return (DCMD_ERR);
2231 /* Don't print state history for child objects */
2232 idc->u.child.idc_states = 0;
2233 (void) mdb_dec_indent(4);
2235 #endif
2238 * Print refcnt audit data if requested
2240 if (rc_audit) {
2241 (void) mdb_inc_indent(4);
2242 mdb_printf("Reference History(idt_refcnt):\n");
2243 rc_addr = addr +
2244 offsetof(idm_task_t, idt_refcnt);
2245 if (iscsi_refcnt_impl(rc_addr) != DCMD_OK)
2246 return (DCMD_ERR);
2248 /* Don't print audit data for child objects */
2249 idc->u.child.idc_rc_audit = 0;
2250 (void) mdb_dec_indent(4);
2255 * Buffers are leaf objects and always get headers so the
2256 * user can discern between in and out buffers.
2258 if (idc->u.child.idc_buffer) {
2259 /* Walk in buffer list */
2260 (void) mdb_inc_indent(2);
2261 mdb_printf("In buffers:\n");
2262 idc->idc_header = 1;
2263 (void) mdb_inc_indent(2);
2264 list_addr = addr + offsetof(idm_task_t, idt_inbufv);
2265 if (mdb_pwalk("list", iscsi_buffer_walk_cb, idc, list_addr) ==
2266 -1) {
2267 mdb_warn("list walk failed for task in buffers");
2268 (void) mdb_dec_indent(4);
2269 return (DCMD_ERR);
2271 (void) mdb_dec_indent(2);
2272 /* Walk out buffer list */
2273 mdb_printf("Out buffers:\n");
2274 idc->idc_header = 1;
2275 (void) mdb_inc_indent(2);
2276 list_addr = addr + offsetof(idm_task_t, idt_outbufv);
2277 if (mdb_pwalk("list", iscsi_buffer_walk_cb, idc, list_addr) ==
2278 -1) {
2279 mdb_warn("list walk failed for task out buffers\n");
2280 (void) mdb_dec_indent(2);
2281 return (DCMD_ERR);
2283 (void) mdb_dec_indent(4);
2286 idc->idc_verbose = verbose;
2287 idc->u.child.idc_states = states;
2288 idc->u.child.idc_rc_audit = rc_audit;
2290 return (DCMD_OK);
2293 static int
2294 iscsi_task_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc)
2296 idm_task_t idt;
2299 * Read idm_conn_t
2301 if (mdb_vread(&idt, sizeof (idm_task_t), addr) != sizeof (idm_task_t)) {
2302 return (DCMD_ERR);
2305 return (iscsi_i_task_impl(&idt, addr, idc));
2308 #define ISCSI_CDB_INDENT 16
2310 static void
2311 iscsi_print_iscsit_task_data(idm_task_t *idt)
2313 iscsit_task_t itask;
2314 boolean_t good_scsi_task = B_TRUE;
2315 scsi_task_t scsi_task;
2317 if (mdb_vread(&itask, sizeof (iscsit_task_t),
2318 (uintptr_t)idt->idt_private) != sizeof (iscsit_task_t)) {
2319 mdb_printf("**Failed to read idt_private data\n");
2320 return;
2323 if (mdb_vread(&scsi_task, sizeof (scsi_task_t),
2324 (uintptr_t)itask.it_stmf_task) != sizeof (scsi_task_t)) {
2325 good_scsi_task = B_FALSE;
2328 mdb_printf("%20s: %s(%d)\n", "State",
2329 idt->idt_state > TASK_MAX_STATE ?
2330 "UNKNOWN" : idm_ts_name[idt->idt_state],
2331 idt->idt_state);
2332 mdb_printf("%20s: %d/%d\n", "STMF abort/IDM aborted",
2333 itask.it_stmf_abort, itask.it_aborted);
2334 mdb_printf("%20s: %p/%p/%p%s\n",
2335 "iscsit/STMF/LU", idt->idt_private,
2336 itask.it_stmf_task, good_scsi_task ? scsi_task.task_lu_private : 0,
2337 good_scsi_task ? "" : "**");
2338 if (good_scsi_task) {
2339 mdb_printf("%20s: %08x/%08x\n", "ITT/TTT",
2340 itask.it_itt, itask.it_ttt);
2341 mdb_printf("%20s: %08x\n", "CmdSN",
2342 itask.it_cmdsn);
2343 mdb_printf("%20s: %02x %02x %02x %02x %02x %02x %02x %02x\n",
2344 "LU number",
2345 scsi_task.task_lun_no[0], scsi_task.task_lun_no[1],
2346 scsi_task.task_lun_no[2], scsi_task.task_lun_no[3],
2347 scsi_task.task_lun_no[4], scsi_task.task_lun_no[5],
2348 scsi_task.task_lun_no[6], scsi_task.task_lun_no[7]);
2349 mdb_printf(" CDB (%d bytes):\n",
2350 scsi_task.task_cdb_length);
2351 (void) mdb_inc_indent(ISCSI_CDB_INDENT);
2352 if (mdb_dumpptr((uintptr_t)scsi_task.task_cdb,
2353 scsi_task.task_cdb_length,
2354 MDB_DUMP_RELATIVE | MDB_DUMP_TRIM |
2355 MDB_DUMP_GROUP(1),
2356 (mdb_dumpptr_cb_t)mdb_vread, NULL)) {
2357 mdb_printf("** Invalid CDB addr (%p)\n",
2358 scsi_task.task_cdb);
2360 (void) mdb_dec_indent(ISCSI_CDB_INDENT);
2361 mdb_printf("%20s: %d/%d\n", "STMF cur/max bufs",
2362 scsi_task.task_cur_nbufs,
2363 scsi_task.task_max_nbufs);
2364 mdb_printf("%20s: 0x%08x/0x%08x/0x%08x\n", "Bytes Exp/Cmd/Done",
2365 scsi_task.task_expected_xfer_length,
2366 scsi_task.task_cmd_xfer_length,
2367 scsi_task.task_nbytes_transferred);
2368 mdb_printf("%20s: 0x%x/0x%x\n", "TX-ini start/done",
2369 idt->idt_tx_to_ini_start,
2370 idt->idt_tx_to_ini_done);
2371 mdb_printf("%20s: 0x%x/0x%x\n", "RX-ini start/done",
2372 idt->idt_rx_from_ini_start,
2373 idt->idt_rx_from_ini_done);
2377 static int
2378 iscsi_print_ini_lun(uintptr_t addr, const iscsi_lun_t *lun,
2379 iscsi_dcmd_ctrl_t *idc)
2382 if (idc->u.child.idc_lun) {
2383 if (idc->idc_header) {
2384 mdb_printf("%<u>%-?s %-5s %-10s%</u>\n",
2385 "iscsi_lun_t", "State", "Lun Number");
2386 idc->idc_header = 0;
2388 mdb_printf("%?p %-5d %-10d\n", addr,
2389 lun->lun_state, lun->lun_num);
2391 return (DCMD_OK);
2394 static int
2395 iscsi_print_ini_cmd(uintptr_t addr, const iscsi_cmd_t *cmd,
2396 iscsi_dcmd_ctrl_t *idc)
2399 uintptr_t states_addr;
2401 if (idc->idc_header) {
2402 mdb_printf("%<u>%-?s %-?s %4s %6s/%-6s %-?s%</u>\n",
2403 "iscsi_cmd_t", "idm_task_t", "Type",
2404 "State", "Prev", "iscsi_lun_t");
2405 idc->idc_header = 0;
2408 mdb_printf("%?p %?p %4d %6d/%-6d %?p\n",
2409 addr, cmd->cmd_itp, cmd->cmd_type, cmd->cmd_state,
2410 cmd->cmd_prev_state, cmd->cmd_lun);
2413 * Print states if requested
2415 if (idc->u.child.idc_states) {
2416 states_addr = addr + offsetof(iscsi_cmd_t, cmd_state_audit);
2418 (void) mdb_inc_indent(4);
2419 mdb_printf("State History(cmd_state_audit):\n");
2420 if (iscsi_sm_audit_impl(states_addr) != DCMD_OK)
2421 return (DCMD_ERR);
2422 idc->u.child.idc_states = 0;
2423 (void) mdb_dec_indent(4);
2425 return (DCMD_OK);
2428 static int
2429 iscsi_buffer_impl(uintptr_t addr, iscsi_dcmd_ctrl_t *idc)
2431 idm_buf_t idb;
2434 * Read idm_buf_t
2436 if (mdb_vread(&idb, sizeof (idm_buf_t), addr) != sizeof (idm_buf_t)) {
2437 return (DCMD_ERR);
2441 if (idc->idc_header) {
2442 mdb_printf("%<u>%-?s %?s/%-8s %8s %8s %8s%</u>\n",
2443 "idm_buf_t", "Mem Rgn", "Length",
2444 "Rel Off", "Xfer Len", "Exp. Off");
2445 idc->idc_header = 0;
2448 /* Print buffer data */
2449 mdb_printf("%?p %?p/%08x %8x %8x %08x\n", addr,
2450 idb.idb_buf, idb.idb_buflen,
2451 idb.idb_bufoffset, idb.idb_xfer_len,
2452 idb.idb_exp_offset);
2455 /* Buffers are leaf objects */
2457 return (DCMD_OK);
2460 static int
2461 iscsi_refcnt_impl(uintptr_t addr)
2463 idm_refcnt_t refcnt;
2464 refcnt_audit_buf_t *anb;
2465 int ctr;
2468 * Print refcnt info
2470 if (mdb_vread(&refcnt, sizeof (idm_refcnt_t), addr) !=
2471 sizeof (idm_refcnt_t)) {
2472 mdb_warn("read refcnt failed");
2473 return (DCMD_ERR);
2476 anb = &refcnt.ir_audit_buf;
2478 ctr = anb->anb_max_index + 1;
2479 anb->anb_index--;
2480 anb->anb_index &= anb->anb_max_index;
2482 while (ctr) {
2483 refcnt_audit_record_t *anr;
2485 anr = anb->anb_records + anb->anb_index;
2487 if (anr->anr_depth) {
2488 char c[MDB_SYM_NAMLEN];
2489 GElf_Sym sym;
2490 int i;
2492 mdb_printf("\nRefCnt: %u\t", anr->anr_refcnt);
2494 for (i = 0; i < anr->anr_depth; i++) {
2495 if (mdb_lookup_by_addr(anr->anr_stack[i],
2496 MDB_SYM_FUZZY, c, sizeof (c),
2497 &sym) == -1) {
2498 continue;
2500 mdb_printf("%s+0x%1x", c,
2501 anr->anr_stack[i] -
2502 (uintptr_t)sym.st_value);
2503 ++i;
2504 break;
2507 while (i < anr->anr_depth) {
2508 if (mdb_lookup_by_addr(anr->anr_stack[i],
2509 MDB_SYM_FUZZY, c, sizeof (c),
2510 &sym) == -1) {
2511 ++i;
2512 continue;
2514 mdb_printf("\n\t\t%s+0x%1x", c,
2515 anr->anr_stack[i] -
2516 (uintptr_t)sym.st_value);
2517 ++i;
2519 mdb_printf("\n");
2521 anb->anb_index--;
2522 anb->anb_index &= anb->anb_max_index;
2523 ctr--;
2526 return (DCMD_OK);
2529 static int
2530 iscsi_sm_audit_impl(uintptr_t addr)
2532 sm_audit_buf_t audit_buf;
2533 int ctr;
2534 const char *event_name;
2535 const char *state_name;
2536 const char *new_state_name;
2537 char ts_string[40];
2539 * Print refcnt info
2541 if (mdb_vread(&audit_buf, sizeof (sm_audit_buf_t), addr) !=
2542 sizeof (sm_audit_buf_t)) {
2543 mdb_warn("failed to read audit buf");
2544 return (DCMD_ERR);
2547 ctr = audit_buf.sab_max_index + 1;
2548 audit_buf.sab_index++;
2549 audit_buf.sab_index &= audit_buf.sab_max_index;
2551 while (ctr) {
2552 sm_audit_record_t *sar;
2554 sar = audit_buf.sab_records + audit_buf.sab_index;
2556 iscsi_format_timestamp(ts_string, 40, &sar->sar_timestamp);
2558 switch (sar->sar_type) {
2559 case SAR_STATE_EVENT:
2560 switch (sar->sar_sm_type) {
2561 case SAS_IDM_CONN:
2562 state_name =
2563 iscsi_idm_conn_state(sar->sar_state);
2564 event_name =
2565 iscsi_idm_conn_event(sar->sar_event);
2566 break;
2567 case SAS_ISCSIT_TGT:
2568 state_name =
2569 iscsi_iscsit_tgt_state(sar->sar_state);
2570 event_name =
2571 iscsi_iscsit_tgt_event(sar->sar_event);
2572 break;
2573 case SAS_ISCSIT_SESS:
2574 state_name =
2575 iscsi_iscsit_sess_state(sar->sar_state);
2576 event_name =
2577 iscsi_iscsit_sess_event(sar->sar_event);
2578 break;
2579 case SAS_ISCSIT_LOGIN:
2580 state_name =
2581 iscsi_iscsit_login_state(sar->sar_state);
2582 event_name =
2583 iscsi_iscsit_login_event(sar->sar_event);
2584 break;
2585 case SAS_ISCSI_CMD:
2586 state_name =
2587 iscsi_iscsi_cmd_state(sar->sar_state);
2588 event_name=
2589 iscsi_iscsi_cmd_event(sar->sar_event);
2590 break;
2591 case SAS_ISCSI_SESS:
2592 state_name =
2593 iscsi_iscsi_sess_state(sar->sar_state);
2594 event_name=
2595 iscsi_iscsi_sess_event(sar->sar_event);
2596 break;
2597 case SAS_ISCSI_CONN:
2598 state_name =
2599 iscsi_iscsi_conn_state(sar->sar_state);
2600 event_name=
2601 iscsi_iscsi_conn_event(sar->sar_event);
2602 break;
2603 default:
2604 state_name = event_name = "N/A";
2605 break;
2607 mdb_printf("%s|%s (%d)\n\t%9s %s (%d) %p\n",
2608 ts_string, state_name, sar->sar_state,
2609 "Event", event_name,
2610 sar->sar_event, sar->sar_event_info);
2612 break;
2613 case SAR_STATE_CHANGE:
2614 switch (sar->sar_sm_type) {
2615 case SAS_IDM_CONN:
2616 state_name =
2617 iscsi_idm_conn_state(sar->sar_state);
2618 new_state_name =
2619 iscsi_idm_conn_state(sar->sar_new_state);
2620 break;
2621 case SAS_IDM_TASK:
2622 state_name =
2623 iscsi_idm_task_state(sar->sar_state);
2624 new_state_name =
2625 iscsi_idm_task_state(sar->sar_new_state);
2626 break;
2627 case SAS_ISCSIT_TGT:
2628 state_name =
2629 iscsi_iscsit_tgt_state(sar->sar_state);
2630 new_state_name =
2631 iscsi_iscsit_tgt_state(sar->sar_new_state);
2632 break;
2633 case SAS_ISCSIT_SESS:
2634 state_name =
2635 iscsi_iscsit_sess_state(sar->sar_state);
2636 new_state_name =
2637 iscsi_iscsit_sess_state(sar->sar_new_state);
2638 break;
2639 case SAS_ISCSIT_LOGIN:
2640 state_name =
2641 iscsi_iscsit_login_state(sar->sar_state);
2642 new_state_name =
2643 iscsi_iscsit_login_state(
2644 sar->sar_new_state);
2645 break;
2646 case SAS_ISCSI_CMD:
2647 state_name =
2648 iscsi_iscsi_cmd_state(sar->sar_state);
2649 new_state_name=
2650 iscsi_iscsi_cmd_state(sar->sar_new_state);
2651 break;
2652 case SAS_ISCSI_SESS:
2653 state_name =
2654 iscsi_iscsi_sess_state(sar->sar_state);
2655 new_state_name=
2656 iscsi_iscsi_sess_state(sar->sar_new_state);
2657 break;
2658 case SAS_ISCSI_CONN:
2659 state_name =
2660 iscsi_iscsi_conn_state(sar->sar_state);
2661 new_state_name=
2662 iscsi_iscsi_conn_state(sar->sar_new_state);
2663 break;
2664 case SAS_ISCSI_LOGIN:
2665 state_name =
2666 iscsi_iscsi_login_state(sar->sar_state);
2667 new_state_name=
2668 iscsi_iscsi_login_state(sar->sar_new_state);
2669 break;
2670 default:
2671 state_name = new_state_name = "N/A";
2672 break;
2674 mdb_printf("%s|%s (%d)\n\t%9s %s (%d)\n",
2675 ts_string, state_name, sar->sar_state,
2676 "New State", new_state_name, sar->sar_new_state);
2678 break;
2679 default:
2680 break;
2683 audit_buf.sab_index++;
2684 audit_buf.sab_index &= audit_buf.sab_max_index;
2685 ctr--;
2688 return (DCMD_OK);
2691 static const char *
2692 iscsi_idm_conn_event(unsigned int event)
2694 return ((event < CE_MAX_EVENT) ? idm_ce_name[event] : "N/A");
2697 static const char *
2698 iscsi_iscsit_tgt_event(unsigned int event)
2700 return ((event < TE_MAX_EVENT) ? iscsit_te_name[event] : "N/A");
2703 static const char *
2704 iscsi_iscsit_sess_event(unsigned int event)
2706 return ((event < SE_MAX_EVENT) ? iscsit_se_name[event] : "N/A");
2709 static const char *
2710 iscsi_iscsit_login_event(unsigned int event)
2712 return ((event < ILE_MAX_EVENT) ? iscsit_ile_name[event] : "N/A");
2715 static const char *
2716 iscsi_iscsi_cmd_event(unsigned int event)
2718 return ((event < ISCSI_CMD_EVENT_MAX) ?
2719 iscsi_cmd_event_names[event] : "N/A");
2722 static const char *
2723 iscsi_iscsi_sess_event(unsigned int event)
2726 return ((event < ISCSI_SESS_EVENT_MAX) ?
2727 iscsi_sess_event_names[event] : "N/A");
2730 static const char *
2731 iscsi_idm_conn_state(unsigned int state)
2733 return ((state < CS_MAX_STATE) ? idm_cs_name[state] : "N/A");
2736 static const char *
2737 iscsi_iscsi_conn_event(unsigned int event)
2740 return ((event < CN_MAX) ? idm_cn_strings[event] : "N/A");
2743 /*ARGSUSED*/
2744 static const char *
2745 iscsi_idm_task_state(unsigned int state)
2747 return ("N/A");
2750 static const char *
2751 iscsi_iscsit_tgt_state(unsigned int state)
2753 return ((state < TS_MAX_STATE) ? iscsit_ts_name[state] : "N/A");
2756 static const char *
2757 iscsi_iscsit_sess_state(unsigned int state)
2759 return ((state < SS_MAX_STATE) ? iscsit_ss_name[state] : "N/A");
2762 static const char *
2763 iscsi_iscsit_login_state(unsigned int state)
2765 return ((state < ILS_MAX_STATE) ? iscsit_ils_name[state] : "N/A");
2768 static const char *
2769 iscsi_iscsi_cmd_state(unsigned int state)
2771 return ((state < ISCSI_CMD_STATE_MAX) ?
2772 iscsi_cmd_state_names[state] : "N/A");
2775 static const char *
2776 iscsi_iscsi_sess_state(unsigned int state)
2778 return ((state < ISCSI_SESS_STATE_MAX) ?
2779 iscsi_sess_state_names[state] : "N/A");
2782 static const char *
2783 iscsi_iscsi_conn_state(unsigned int state)
2785 return ((state < ISCSI_CONN_STATE_MAX) ? iscsi_ics_name[state] : "N/A");
2788 static const char *
2789 iscsi_iscsi_login_state(unsigned int state)
2791 return ((state < LOGIN_MAX) ? iscsi_login_state_names[state] : "N/A");
2796 * Retrieve connection type given a kernel address
2798 static idm_conn_type_t
2799 idm_conn_type(uintptr_t addr)
2801 idm_conn_type_t result = 0; /* Unknown */
2802 uintptr_t idm_conn_type_addr;
2804 idm_conn_type_addr = addr + offsetof(idm_conn_t, ic_conn_type);
2805 (void) mdb_vread(&result, sizeof (result), idm_conn_type_addr);
2807 return (result);
2811 * Convert a sockaddr to the string representation, suitable for
2812 * storing in an nvlist or printing out in a list.
2814 static int
2815 sa_to_str(struct sockaddr_storage *sa, char *buf)
2817 char pbuf[7];
2818 const char *bufp;
2819 struct sockaddr_in *sin;
2820 struct sockaddr_in6 *sin6;
2821 uint16_t port;
2823 if (!sa || !buf) {
2824 return (EINVAL);
2827 buf[0] = '\0';
2829 if (sa->ss_family == AF_INET) {
2830 sin = (struct sockaddr_in *)sa;
2831 bufp = iscsi_inet_ntop(AF_INET,
2832 (const void *)&(sin->sin_addr.s_addr),
2833 buf, PORTAL_STR_LEN);
2834 if (bufp == NULL) {
2835 return (-1);
2837 mdb_nhconvert(&port, &sin->sin_port, sizeof (uint16_t));
2838 } else if (sa->ss_family == AF_INET6) {
2839 strlcat(buf, "[", sizeof (buf));
2840 sin6 = (struct sockaddr_in6 *)sa;
2841 bufp = iscsi_inet_ntop(AF_INET6,
2842 (const void *)&sin6->sin6_addr.s6_addr,
2843 &buf[1], PORTAL_STR_LEN - 1);
2844 if (bufp == NULL) {
2845 return (-1);
2847 strlcat(buf, "]", PORTAL_STR_LEN);
2848 mdb_nhconvert(&port, &sin6->sin6_port, sizeof (uint16_t));
2849 } else {
2850 return (EINVAL);
2854 mdb_snprintf(pbuf, sizeof (pbuf), ":%u", port);
2855 strlcat(buf, pbuf, PORTAL_STR_LEN);
2857 return (0);
2861 static void
2862 iscsi_format_timestamp(char *ts_str, int strlen, timespec_t *ts)
2864 mdb_snprintf(ts_str, strlen, "%Y:%03d:%03d:%03d", ts->tv_sec,
2865 (ts->tv_nsec / 1000000) % 1000, (ts->tv_nsec / 1000) % 1000,
2866 ts->tv_nsec % 1000);
2870 * Help information for the iscsi_isns dcmd
2872 static void
2873 iscsi_isns_help(void)
2875 mdb_printf("iscsi_isns:\n");
2876 mdb_inc_indent(4);
2877 mdb_printf("-e: Print ESI information\n");
2878 mdb_printf("-p: Print portal information\n");
2879 mdb_printf("-s: Print iSNS server information\n");
2880 mdb_printf("-t: Print target information\n");
2881 mdb_printf("-v: Add verbosity to the other options' output\n");
2882 mdb_printf("-R: Add Refcount information to '-t' output\n");
2883 mdb_dec_indent(4);
2886 /* ARGSUSED */
2887 static int
2888 iscsi_isns_esi_cb(uintptr_t addr, const void *walker_data, void *data)
2890 isns_esi_tinfo_t tinfo;
2892 if (mdb_vread(&tinfo, sizeof (isns_esi_tinfo_t), addr) !=
2893 sizeof (isns_esi_tinfo_t)) {
2894 return (WALK_ERR);
2897 mdb_printf("ESI thread/thr did : 0x%p / %d\n", tinfo.esi_thread,
2898 tinfo.esi_thread_did);
2899 mdb_printf("ESI sonode : 0x%p\n", tinfo.esi_so);
2900 mdb_printf("ESI port : %d\n", tinfo.esi_port);
2901 mdb_printf("ESI thread running : %s\n",
2902 (tinfo.esi_thread_running) ? "Yes" : "No");
2904 return (WALK_NEXT);
2907 static int
2908 iscsi_isns_esi(iscsi_dcmd_ctrl_t *idc)
2910 GElf_Sym sym;
2911 uintptr_t addr;
2913 if (mdb_lookup_by_name("esi", &sym) == -1) {
2914 mdb_warn("failed to find symbol 'esi_list'");
2915 return (DCMD_ERR);
2917 addr = (uintptr_t)sym.st_value;
2919 idc->idc_header = 1;
2920 (void) iscsi_isns_esi_cb(addr, NULL, idc);
2922 return (0);
2925 /* ARGSUSED */
2926 static int
2927 iscsi_isns_portal_cb(uintptr_t addr, const void *walker_data, void *data)
2929 iscsi_dcmd_ctrl_t *idc = (iscsi_dcmd_ctrl_t *)data;
2930 isns_portal_t portal;
2931 char portal_addr[PORTAL_STR_LEN];
2932 struct sockaddr_storage *ss;
2933 char ts_string[40];
2935 if (mdb_vread(&portal, sizeof (isns_portal_t), addr) !=
2936 sizeof (isns_portal_t)) {
2937 return (WALK_ERR);
2940 ss = &portal.portal_addr;
2941 sa_to_str(ss, portal_addr);
2942 mdb_printf("Portal IP address ");
2944 if (ss->ss_family == AF_INET) {
2945 mdb_printf("(v4): %s", portal_addr);
2946 } else {
2947 mdb_printf("(v6): %s", portal_addr);
2950 if (portal.portal_default == B_TRUE) {
2951 mdb_printf(" (Default portal)\n");
2952 } else {
2953 mdb_printf("\n");
2955 if (portal.portal_iscsit != NULL) {
2956 mdb_printf("(Part of TPG: 0x%p)\n", portal.portal_iscsit);
2959 iscsi_format_timestamp(ts_string, 40, &portal.portal_esi_timestamp);
2960 mdb_printf("Portal ESI timestamp: %s\n\n", ts_string);
2962 if ((portal.portal_iscsit != NULL) && (idc->idc_verbose)) {
2963 mdb_inc_indent(4);
2964 iscsi_portal_impl((uintptr_t)portal.portal_iscsit, idc);
2965 mdb_dec_indent(4);
2969 return (WALK_NEXT);
2972 static int
2973 iscsi_isns_portals(iscsi_dcmd_ctrl_t *idc)
2975 GElf_Sym sym;
2976 uintptr_t portal_list;
2978 mdb_printf("All Active Portals:\n");
2980 if (mdb_lookup_by_name("isns_all_portals", &sym) == -1) {
2981 mdb_warn("failed to find symbol 'isns_all_portals'");
2982 return (DCMD_ERR);
2985 portal_list = (uintptr_t)sym.st_value;
2986 idc->idc_header = 1;
2988 if (mdb_pwalk("avl", iscsi_isns_portal_cb, idc, portal_list) == -1) {
2989 mdb_warn("avl walk failed for isns_all_portals");
2990 return (DCMD_ERR);
2992 mdb_printf("\nPortals from TPGs:\n");
2994 if (mdb_lookup_by_name("isns_tpg_portals", &sym) == -1) {
2995 mdb_warn("failed to find symbol 'isns_tpg_portals'");
2996 return (DCMD_ERR);
2999 portal_list = (uintptr_t)sym.st_value;
3000 idc->idc_header = 1;
3002 if (mdb_pwalk("avl", iscsi_isns_portal_cb, idc, portal_list) == -1) {
3003 mdb_warn("avl walk failed for isns_tpg_portals");
3004 return (DCMD_ERR);
3008 return (0);
3011 /* ARGSUSED */
3012 static int
3013 iscsi_isns_targets_cb(uintptr_t addr, const void *walker_data, void *data)
3015 iscsi_dcmd_ctrl_t *idc = (iscsi_dcmd_ctrl_t *)data;
3016 isns_target_t itarget;
3017 int rc = 0;
3018 int rc_audit = 0;
3019 uintptr_t rc_addr;
3021 if (mdb_vread(&itarget, sizeof (isns_target_t), addr) !=
3022 sizeof (isns_target_t)) {
3023 return (WALK_ERR);
3026 idc->idc_header = 1;
3027 rc_audit = idc->u.child.idc_rc_audit;
3029 mdb_printf("Target: %p\n", addr);
3030 mdb_inc_indent(4);
3031 mdb_printf("Registered: %s\n",
3032 (itarget.target_registered) ? "Yes" : "No");
3033 mdb_printf("Update needed: %s\n",
3034 (itarget.target_update_needed) ? "Yes" : "No");
3035 mdb_printf("Target Info: %p\n", itarget.target_info);
3037 /* Prevent target refcounts from showing through this path */
3038 idc->u.child.idc_rc_audit = 0;
3039 rc = iscsi_tgt_impl((uintptr_t)itarget.target, idc);
3041 idc->u.child.idc_rc_audit = rc_audit;
3042 if (idc->u.child.idc_rc_audit) {
3043 rc_addr = (uintptr_t)itarget.target_info +
3044 offsetof(isns_target_info_t, ti_refcnt);
3046 mdb_printf("Reference History(isns_target_info ti_refcnt):\n");
3047 if (iscsi_refcnt_impl(rc_addr) != 0) {
3048 return (WALK_ERR);
3052 mdb_dec_indent(4);
3054 if (rc == DCMD_OK) {
3055 return (WALK_NEXT);
3058 return (WALK_ERR);
3061 static int
3062 iscsi_isns_targets(iscsi_dcmd_ctrl_t *idc)
3064 GElf_Sym sym;
3065 uintptr_t isns_target_list;
3067 if (mdb_lookup_by_name("isns_target_list", &sym) == -1) {
3068 mdb_warn("failed to find symbol 'isns_target_list'");
3069 return (DCMD_ERR);
3072 isns_target_list = (uintptr_t)sym.st_value;
3073 idc->idc_header = 1;
3074 idc->u.child.idc_tgt = 1;
3076 if (mdb_pwalk("avl", iscsi_isns_targets_cb, idc,
3077 isns_target_list) == -1) {
3078 mdb_warn("avl walk failed for isns_target_list");
3079 return (DCMD_ERR);
3082 return (0);
3085 /* ARGSUSED */
3086 static int
3087 iscsi_isns_servers_cb(uintptr_t addr, const void *walker_data, void *data)
3089 iscsit_isns_svr_t server;
3090 char server_addr[PORTAL_STR_LEN];
3091 struct sockaddr_storage *ss;
3092 clock_t lbolt;
3093 iscsi_dcmd_ctrl_t *idc = (iscsi_dcmd_ctrl_t *)data;
3094 uintptr_t avl_addr;
3096 if (mdb_vread(&server, sizeof (iscsit_isns_svr_t), addr) !=
3097 sizeof (iscsit_isns_svr_t)) {
3098 return (WALK_ERR);
3101 if ((lbolt = (clock_t)mdb_get_lbolt()) == -1)
3102 return (WALK_ERR);
3104 mdb_printf("iSNS server %p:\n", addr);
3105 mdb_inc_indent(4);
3106 ss = &server.svr_sa;
3107 sa_to_str(ss, server_addr);
3109 mdb_printf("IP address ");
3110 if (ss->ss_family == AF_INET) {
3111 mdb_printf("(v4): %s\n", server_addr);
3112 } else {
3113 mdb_printf("(v6): %s\n", server_addr);
3116 mdb_printf("ESI Interval: %d seconds\n",
3117 server.svr_esi_interval);
3118 mdb_printf("Last message: %d seconds ago\n",
3119 ((lbolt - server.svr_last_msg) / 100));
3120 mdb_printf("Client registered: %s\n",
3121 (server.svr_registered) ? "Yes" : "No");
3122 mdb_printf("Retry Count: %d\n",
3123 server.svr_retry_count);
3124 mdb_printf("Targets Changes Pending: %s\n",
3125 (server.svr_targets_changed) ? "Yes" : "No");
3126 mdb_printf("Delete Pending: %s\n",
3127 (server.svr_delete_needed) ? "Yes" : "No");
3128 mdb_printf("Replace-All Needed: %s\n",
3129 (server.svr_reset_needed) ? "Yes" : "No");
3131 if (idc->idc_verbose) {
3132 idc->idc_header = 1;
3133 idc->u.child.idc_tgt = 1;
3135 mdb_inc_indent(2);
3136 avl_addr = addr + offsetof(iscsit_isns_svr_t,
3137 svr_target_list);
3138 if (mdb_pwalk("avl", iscsi_isns_targets_cb, idc,
3139 avl_addr) == -1) {
3140 mdb_warn("avl walk failed for svr_target_list");
3141 return (WALK_ERR);
3143 mdb_dec_indent(2);
3146 mdb_dec_indent(4);
3148 return (WALK_NEXT);
3151 static int
3152 iscsi_isns_servers(iscsi_dcmd_ctrl_t *idc)
3154 uintptr_t iscsit_global_addr;
3155 uintptr_t list_addr;
3156 GElf_Sym sym;
3158 if (mdb_lookup_by_name("iscsit_global", &sym) == -1) {
3159 mdb_warn("failed to find symbol 'iscsit_global'");
3160 return (DCMD_ERR);
3163 iscsit_global_addr = (uintptr_t)sym.st_value;
3164 idc->idc_header = 1;
3165 list_addr = iscsit_global_addr +
3166 offsetof(iscsit_global_t, global_isns_cfg.isns_svrs);
3168 if (mdb_pwalk("list", iscsi_isns_servers_cb, idc, list_addr) == -1) {
3169 mdb_warn("list walk failed for iSNS servers");
3170 return (DCMD_ERR);
3173 return (0);
3176 /* ARGSUSED */
3177 static int
3178 iscsi_isns(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
3180 iscsi_dcmd_ctrl_t idc;
3181 int portals = 0, esi = 0, targets = 0, verbose = 0, servers = 0;
3182 int rc_audit = 0;
3184 if (flags & DCMD_ADDRSPEC) {
3185 mdb_warn("iscsi_isns is only a global dcmd.");
3186 return (DCMD_ERR);
3189 bzero(&idc, sizeof (idc));
3190 if (mdb_getopts(argc, argv,
3191 'e', MDB_OPT_SETBITS, TRUE, &esi,
3192 'p', MDB_OPT_SETBITS, TRUE, &portals,
3193 's', MDB_OPT_SETBITS, TRUE, &servers,
3194 't', MDB_OPT_SETBITS, TRUE, &targets,
3195 'v', MDB_OPT_SETBITS, TRUE, &verbose,
3196 'R', MDB_OPT_SETBITS, TRUE, &rc_audit,
3197 NULL) != argc)
3198 return (DCMD_USAGE);
3200 if ((esi + portals + targets + servers) > 1) {
3201 mdb_printf("Only one of e, p, s, and t must be provided");
3202 return (DCMD_ERR);
3205 if ((esi | portals | targets | servers) == 0) {
3206 mdb_printf("Exactly one of e, p, s, or t must be provided");
3207 return (DCMD_ERR);
3210 idc.idc_verbose = verbose;
3211 idc.u.child.idc_rc_audit = rc_audit;
3213 if (esi) {
3214 return (iscsi_isns_esi(&idc));
3217 if (portals) {
3218 return (iscsi_isns_portals(&idc));
3221 if (servers) {
3222 return (iscsi_isns_servers(&idc));
3225 return (iscsi_isns_targets(&idc));
3228 static int
3229 iscsi_ini_sess_walk_init(mdb_walk_state_t *wsp)
3231 if (wsp->walk_addr == (uintptr_t)NULL) {
3232 mdb_warn("<iscsi_sess_t addr>::walk iscsi_ini_sess");
3233 return (WALK_ERR);
3236 wsp->walk_data = mdb_alloc(sizeof (iscsi_sess_t), UM_SLEEP|UM_GC);
3237 if (!wsp->walk_data) {
3238 mdb_warn("iscsi_ini_sess walk failed");
3239 return (WALK_ERR);
3242 return (WALK_NEXT);
3245 static int
3246 iscsi_ini_sess_step(mdb_walk_state_t *wsp)
3248 int status;
3250 if (wsp->walk_addr == (uintptr_t)NULL) {
3251 return (WALK_DONE);
3254 if (mdb_vread(wsp->walk_data, sizeof (iscsi_sess_t), wsp->walk_addr)
3255 != sizeof (iscsi_sess_t)) {
3256 mdb_warn("failed to read iscsi_sess_t at %p", wsp->walk_addr);
3257 return (WALK_DONE);
3260 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
3261 wsp->walk_cbdata);
3263 wsp->walk_addr =
3264 (uintptr_t)(((iscsi_sess_t *)wsp->walk_data)->sess_next);
3266 return (status);
3269 static int
3270 iscsi_ini_conn_walk_init(mdb_walk_state_t *wsp)
3272 if (wsp->walk_addr == (uintptr_t)NULL) {
3273 mdb_warn("<iscsi_conn_t addr>::walk iscsi_ini_conn");
3274 return (WALK_DONE);
3277 wsp->walk_data = mdb_alloc(sizeof (iscsi_conn_t), UM_SLEEP|UM_GC);
3278 if (!wsp->walk_data) {
3279 mdb_warn("iscsi_ini_conn walk failed");
3280 return (WALK_ERR);
3283 return (WALK_NEXT);
3286 static int
3287 iscsi_ini_conn_step(mdb_walk_state_t *wsp)
3289 int status;
3291 if (wsp->walk_addr == (uintptr_t)NULL) {
3292 return (WALK_DONE);
3295 if (mdb_vread(wsp->walk_data, sizeof (iscsi_conn_t), wsp->walk_addr)
3296 != sizeof (iscsi_conn_t)) {
3297 mdb_warn("failed to read iscsi_conn_t at %p", wsp->walk_addr);
3298 return (WALK_DONE);
3302 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
3303 wsp->walk_cbdata);
3305 wsp->walk_addr =
3306 (uintptr_t)(((iscsi_conn_t *)wsp->walk_data)->conn_next);
3308 return (status);
3311 static int
3312 iscsi_ini_lun_walk_init(mdb_walk_state_t *wsp)
3314 if (wsp->walk_addr == (uintptr_t)NULL) {
3315 mdb_warn("<iscsi_lun_t addr>::walk iscsi_ini_lun");
3316 return (WALK_DONE);
3319 wsp->walk_data = mdb_alloc(sizeof (iscsi_lun_t), UM_SLEEP|UM_GC);
3320 if (!wsp->walk_data) {
3321 return (WALK_ERR);
3324 return (WALK_NEXT);
3327 static int
3328 iscsi_ini_lun_step(mdb_walk_state_t *wsp)
3330 int status;
3332 if (wsp->walk_addr == (uintptr_t)NULL) {
3333 return (WALK_DONE);
3336 if (mdb_vread(wsp->walk_data, sizeof (iscsi_lun_t), wsp->walk_addr)
3337 != sizeof (iscsi_lun_t)) {
3338 mdb_warn("failed to read iscsi_lun_t at %p", wsp->walk_addr);
3339 return (WALK_DONE);
3342 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
3343 wsp->walk_cbdata);
3345 wsp->walk_addr =
3346 (uintptr_t)(((iscsi_lun_t *)wsp->walk_data)->lun_next);
3348 return (status);
3351 static int
3352 iscsi_ini_cmd_walk_init(mdb_walk_state_t *wsp)
3354 if (wsp->walk_addr == (uintptr_t)NULL) {
3355 mdb_warn("<iscsi_cmd_t addr>::walk iscsi_ini_cmd");
3356 return (WALK_DONE);
3359 wsp->walk_data = mdb_alloc(sizeof (iscsi_cmd_t), UM_SLEEP|UM_GC);
3360 if (!wsp->walk_data) {
3361 return (WALK_ERR);
3364 return (WALK_NEXT);
3367 static int
3368 iscsi_ini_cmd_step(mdb_walk_state_t *wsp)
3370 int status;
3372 if (wsp->walk_addr == (uintptr_t)NULL) {
3373 return (WALK_DONE);
3376 if (mdb_vread(wsp->walk_data, sizeof (iscsi_cmd_t), wsp->walk_addr)
3377 != sizeof (iscsi_cmd_t)) {
3378 mdb_warn("failed to read iscsi_cmd_t at %p", wsp->walk_addr);
3379 return (WALK_DONE);
3382 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
3383 wsp->walk_cbdata);
3385 wsp->walk_addr =
3386 (uintptr_t)(((iscsi_cmd_t *)wsp->walk_data)->cmd_next);
3388 return (status);
3391 static int
3392 iscsi_ini_cmd_walk_cb(uintptr_t addr, const void *vcmd, void *vidc)
3394 const iscsi_cmd_t *cmd = vcmd;
3395 iscsi_dcmd_ctrl_t *idc = vidc;
3396 int rc;
3398 if (cmd == NULL) {
3399 mdb_warn("list walk failed. Null cmd");
3400 return (WALK_ERR);
3403 rc = iscsi_print_ini_cmd(addr, cmd, idc);
3405 return ((rc == DCMD_OK) ? WALK_NEXT : WALK_ERR);
3408 static int
3409 iscsi_ini_hba_walk_init(mdb_walk_state_t *wsp)
3411 uintptr_t state_addr, array_addr;
3412 int array_size;
3413 struct i_ddi_soft_state *ss;
3414 idm_hba_walk_info_t *hwi;
3417 hwi = (idm_hba_walk_info_t *)mdb_zalloc(
3418 sizeof (idm_hba_walk_info_t), UM_SLEEP|UM_GC);
3420 if (!hwi) {
3421 mdb_warn("unable to allocate storage for iscsi_ini_hba walk");
3422 return (WALK_ERR);
3425 if (wsp->walk_addr != (uintptr_t)NULL) {
3426 mdb_warn("iscsi_ini_hba only supports global walk");
3427 return (WALK_ERR);
3428 } else {
3431 * Read in the array and setup the walk struct.
3433 if (mdb_readvar(&state_addr, "iscsi_state") == -1) {
3434 mdb_warn("state variable iscsi_state not found.\n");
3435 mdb_warn("Is the driver loaded ?\n");
3436 return (WALK_ERR);
3439 ss = (struct i_ddi_soft_state *)mdb_alloc(sizeof (*ss),
3440 UM_SLEEP|UM_GC);
3441 if (mdb_vread(ss, sizeof (*ss), state_addr) != sizeof (*ss)) {
3442 mdb_warn("Cannot read softstate struct "
3443 "(Invalid pointer?).\n");
3444 return (WALK_ERR);
3447 /* Where to get the data */
3448 array_size = ss->n_items * (sizeof (void *));
3449 array_addr = (uintptr_t)ss->array;
3451 /* Where to put the data */
3452 hwi->n_elements = ss->n_items;
3453 hwi->array = mdb_alloc(array_size, UM_SLEEP|UM_GC);
3454 if (!hwi->array) {
3455 mdb_warn("list walk failed");
3456 return (WALK_ERR);
3458 if (mdb_vread(hwi->array, array_size, array_addr) !=
3459 array_size) {
3460 mdb_warn("Corrupted softstate struct.\n");
3461 return (WALK_ERR);
3463 hwi->cur_element = 0;
3464 wsp->walk_data = hwi;
3467 return (WALK_NEXT);
3470 static int
3471 iscsi_ini_hba_step(mdb_walk_state_t *wsp)
3473 int status;
3474 idm_hba_walk_info_t *hwi = (idm_hba_walk_info_t *)wsp->walk_data;
3476 for (; hwi->cur_element < hwi->n_elements; hwi->cur_element++) {
3477 if (hwi->array[hwi->cur_element] != NULL) {
3478 break;
3481 if (hwi->cur_element >= hwi->n_elements) {
3482 return (WALK_DONE);
3485 hwi->data = (iscsi_hba_t *)mdb_alloc(sizeof (iscsi_hba_t),
3486 UM_SLEEP|UM_GC);
3487 if (mdb_vread(hwi->data, sizeof (iscsi_hba_t),
3488 (uintptr_t)hwi->array[hwi->cur_element]) != sizeof (iscsi_hba_t)) {
3489 mdb_warn("failed to read iscsi_sess_t at %p", wsp->walk_addr);
3490 return (WALK_DONE);
3494 status = wsp->walk_callback((uintptr_t)hwi->array[hwi->cur_element],
3495 hwi->data, wsp->walk_cbdata);
3497 /* Increment cur_element for next iteration */
3498 hwi->cur_element++;
3500 return (status);
3504 * iscsi_inet_ntop -- Convert an IPv4 or IPv6 address in binary form into
3505 * printable form, and return a pointer to that string. Caller should
3506 * provide a buffer of correct length to store string into.
3507 * Note: this routine is kernel version of inet_ntop. It has similar
3508 * format as iscsi_inet_ntop() defined in rfc2553. But it does not do
3509 * error handling operations exactly as rfc2553 defines. This function
3510 * is used by kernel inet directory routines only for debugging.
3511 * This iscsi_inet_ntop() function, does not return NULL if third argument
3512 * is NULL. The reason is simple that we don't want kernel to panic
3513 * as the output of this function is directly fed to ip<n>dbg macro.
3514 * Instead it uses a local buffer for destination address for
3515 * those calls which purposely pass NULL ptr for the destination
3516 * buffer. This function is thread-safe when the caller passes a non-
3517 * null buffer with the third argument.
3519 /* ARGSUSED */
3521 #define OK_16PTR(p) (!((uintptr_t)(p) & 0x1))
3522 #if defined(__x86)
3523 #define OK_32PTR(p) OK_16PTR(p)
3524 #else
3525 #define OK_32PTR(p) (!((uintptr_t)(p) & 0x3))
3526 #endif
3528 char *
3529 iscsi_inet_ntop(int af, const void *addr, char *buf, int addrlen)
3531 static char local_buf[PORTAL_STR_LEN];
3532 static char *err_buf1 = "<badaddr>";
3533 static char *err_buf2 = "<badfamily>";
3534 in6_addr_t *v6addr;
3535 uchar_t *v4addr;
3536 char *caddr;
3539 * We don't allow thread unsafe iscsi_inet_ntop calls, they
3540 * must pass a non-null buffer pointer. For DEBUG mode
3541 * we use the ASSERT() and for non-debug kernel it will
3542 * silently allow it for now. Someday we should remove
3543 * the static buffer from this function.
3546 ASSERT(buf != NULL);
3547 if (buf == NULL)
3548 buf = local_buf;
3549 buf[0] = '\0';
3551 /* Let user know politely not to send NULL or unaligned addr */
3552 if (addr == NULL || !(OK_32PTR(addr))) {
3553 return (err_buf1);
3557 #define UC(b) (((int)b) & 0xff)
3558 switch (af) {
3559 case AF_INET:
3560 ASSERT(addrlen >= INET_ADDRSTRLEN);
3561 v4addr = (uchar_t *)addr;
3562 (void) mdb_snprintf(buf, INET6_ADDRSTRLEN,
3563 "%03d.%03d.%03d.%03d",
3564 UC(v4addr[0]), UC(v4addr[1]), UC(v4addr[2]), UC(v4addr[3]));
3565 return (buf);
3567 case AF_INET6:
3568 ASSERT(addrlen >= INET6_ADDRSTRLEN);
3569 v6addr = (in6_addr_t *)addr;
3570 if (IN6_IS_ADDR_V4MAPPED(v6addr)) {
3571 caddr = (char *)addr;
3572 (void) mdb_snprintf(buf, INET6_ADDRSTRLEN,
3573 "::ffff:%d.%d.%d.%d",
3574 UC(caddr[12]), UC(caddr[13]),
3575 UC(caddr[14]), UC(caddr[15]));
3576 } else if (IN6_IS_ADDR_V4COMPAT(v6addr)) {
3577 caddr = (char *)addr;
3578 (void) mdb_snprintf(buf, INET6_ADDRSTRLEN,
3579 "::%d.%d.%d.%d",
3580 UC(caddr[12]), UC(caddr[13]), UC(caddr[14]),
3581 UC(caddr[15]));
3582 } else if (IN6_IS_ADDR_UNSPECIFIED(v6addr)) {
3583 (void) mdb_snprintf(buf, INET6_ADDRSTRLEN, "::");
3584 } else {
3585 convert2ascii(buf, v6addr);
3587 return (buf);
3589 default:
3590 return (err_buf2);
3592 #undef UC
3597 * v6 formats supported
3598 * General format xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx
3599 * The short hand notation :: is used for COMPAT addr
3600 * Other forms : fe80::xxxx:xxxx:xxxx:xxxx
3602 static void
3603 convert2ascii(char *buf, const in6_addr_t *addr)
3605 int hexdigits;
3606 int head_zero = 0;
3607 int tail_zero = 0;
3608 /* tempbuf must be big enough to hold ffff:\0 */
3609 char tempbuf[6];
3610 char *ptr;
3611 uint16_t out_addr_component;
3612 uint16_t *addr_component;
3613 size_t len;
3614 boolean_t first = B_FALSE;
3615 boolean_t med_zero = B_FALSE;
3616 boolean_t end_zero = B_FALSE;
3618 addr_component = (uint16_t *)addr;
3619 ptr = buf;
3621 /* First count if trailing zeroes higher in number */
3622 for (hexdigits = 0; hexdigits < 8; hexdigits++) {
3623 if (*addr_component == 0) {
3624 if (hexdigits < 4)
3625 head_zero++;
3626 else
3627 tail_zero++;
3629 addr_component++;
3631 addr_component = (uint16_t *)addr;
3632 if (tail_zero > head_zero && (head_zero + tail_zero) != 7)
3633 end_zero = B_TRUE;
3635 for (hexdigits = 0; hexdigits < 8; hexdigits++) {
3637 /* if entry is a 0 */
3639 if (*addr_component == 0) {
3640 if (!first && *(addr_component + 1) == 0) {
3641 if (end_zero && (hexdigits < 4)) {
3642 *ptr++ = '0';
3643 *ptr++ = ':';
3644 } else {
3646 * address starts with 0s ..
3647 * stick in leading ':' of pair
3649 if (hexdigits == 0)
3650 *ptr++ = ':';
3651 /* add another */
3652 *ptr++ = ':';
3653 first = B_TRUE;
3654 med_zero = B_TRUE;
3656 } else if (first && med_zero) {
3657 if (hexdigits == 7)
3658 *ptr++ = ':';
3659 addr_component++;
3660 continue;
3661 } else {
3662 *ptr++ = '0';
3663 *ptr++ = ':';
3665 addr_component++;
3666 continue;
3668 if (med_zero)
3669 med_zero = B_FALSE;
3671 tempbuf[0] = '\0';
3672 mdb_nhconvert(&out_addr_component, addr_component,
3673 sizeof (uint16_t));
3674 (void) mdb_snprintf(tempbuf, 6, "%x:", out_addr_component);
3675 len = strlen(tempbuf);
3676 bcopy(tempbuf, ptr, len);
3677 ptr = ptr + len;
3678 addr_component++;
3680 *--ptr = '\0';
3684 * MDB module linkage information:
3686 * We declare a list of structures describing our dcmds, a list of structures
3687 * describing our walkers and a function named _mdb_init to return a pointer
3688 * to our module information.
3690 static const mdb_dcmd_t dcmds[] = {
3691 { "iscsi_tgt", "[-agscptbSRv]",
3692 "iSCSI target information", iscsi_tgt },
3693 { "iscsi_tpgt", "[-R]",
3694 "iSCSI target portal group tag information", iscsi_tpgt },
3695 { "iscsi_tpg", "[-R]",
3696 "iSCSI target portal group information", iscsi_tpg },
3697 { "iscsi_sess", "[-ablmtvcSRIT]",
3698 "iSCSI session information", iscsi_sess },
3699 { "iscsi_conn", "[-abmtvSRIT]",
3700 "iSCSI connection information", iscsi_conn },
3701 { "iscsi_task", "[-bSRv]",
3702 "iSCSI task information", iscsi_task },
3703 { "iscsi_refcnt", "",
3704 "print audit informtion for idm_refcnt_t", iscsi_refcnt },
3705 { "iscsi_states", "",
3706 "dump events and state transitions recorded in an\t"
3707 "\t\tidm_sm_audit_t structure", iscsi_states },
3708 { "iscsi_isns", "[-epstvR]",
3709 "print iscsit iSNS information", iscsi_isns, iscsi_isns_help },
3710 { "iscsi_svc", "[-vR]",
3711 "iSCSI service information", iscsi_svc },
3712 { "iscsi_portal", "[-R]",
3713 "iSCSI portal information", iscsi_portal },
3714 { "iscsi_cmd", "[-S]",
3715 "iSCSI command information (initiator only)", iscsi_cmd },
3716 { NULL }
3720 * Basic walkers for the initiator linked lists
3722 static const mdb_walker_t walkers[] = {
3723 { "iscsi_ini_hba", "global walk of the initiator iscsi_hba_t "
3724 "list", iscsi_ini_hba_walk_init, iscsi_ini_hba_step, NULL},
3725 { "iscsi_ini_sess", "walk list of initiator iscsi_sess_t structures",
3726 iscsi_ini_sess_walk_init, iscsi_ini_sess_step, NULL },
3727 { "iscsi_ini_conn", "walk list of initiator iscsi_conn_t structures",
3728 iscsi_ini_conn_walk_init, iscsi_ini_conn_step, NULL },
3729 { "iscsi_ini_lun", "walk list of initiator iscsi_lun_t structures",
3730 iscsi_ini_lun_walk_init, iscsi_ini_lun_step, NULL },
3731 { "iscsi_ini_cmd", "walk list of initiator iscsi_cmd_t structures",
3732 iscsi_ini_cmd_walk_init, iscsi_ini_cmd_step, NULL },
3733 { NULL }
3736 static const mdb_modinfo_t modinfo = {
3737 MDB_API_VERSION, dcmds, walkers
3740 const mdb_modinfo_t *
3741 _mdb_init(void)
3743 return (&modinfo);