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]
22 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
26 #include <sys/cpuvar.h>
27 #include <sys/types.h>
31 #include <sys/sunddi.h>
32 #include <sys/modctl.h>
33 #include <sys/sysmacros.h>
34 #include <sys/scsi/generic/persist.h>
36 #include <sys/socket.h>
37 #include <sys/strsubr.h>
42 #include <sys/stmf_ioctl.h>
43 #include <sys/portif.h>
44 #include <sys/idm/idm.h>
46 #define ISCSIT_SESS_SM_STRINGS
50 list_node_t se_ctx_node
;
51 iscsit_session_event_t se_ctx_event
;
52 iscsit_conn_t
*se_event_data
;
56 sess_sm_event_locked(iscsit_sess_t
*ist
, iscsit_session_event_t event
,
60 sess_sm_event_dispatch(iscsit_sess_t
*ist
, sess_event_ctx_t
*ctx
);
63 sess_sm_q1_free(iscsit_sess_t
*ist
, sess_event_ctx_t
*ctx
);
66 sess_sm_q2_active(iscsit_sess_t
*ist
, sess_event_ctx_t
*ctx
);
69 sess_sm_q3_logged_in(iscsit_sess_t
*ist
, sess_event_ctx_t
*ctx
);
72 sess_sm_q4_failed(iscsit_sess_t
*ist
, sess_event_ctx_t
*ctx
);
75 sess_sm_q5_continue(iscsit_sess_t
*ist
, sess_event_ctx_t
*ctx
);
78 sess_sm_q6_done(iscsit_sess_t
*ist
, sess_event_ctx_t
*ctx
);
81 sess_sm_q7_error(iscsit_sess_t
*ist
, sess_event_ctx_t
*ctx
);
84 sess_sm_new_state(iscsit_sess_t
*ist
, sess_event_ctx_t
*ctx
,
85 iscsit_session_state_t new_state
);
88 iscsit_task_itt_compare(const void *void_task1
, const void *void_task2
);
91 iscsit_tsih_alloc(void)
95 result
= (uintptr_t)vmem_alloc(iscsit_global
.global_tsih_pool
,
96 1, VM_NOSLEEP
| VM_NEXTFIT
);
98 /* ISCSI_UNSPEC_TSIH (0) indicates failure */
99 if (result
> ISCSI_MAX_TSIH
) {
100 vmem_free(iscsit_global
.global_tsih_pool
, (void *)result
, 1);
101 result
= ISCSI_UNSPEC_TSIH
;
104 return ((uint16_t)result
);
108 iscsit_tsih_free(uint16_t tsih
)
110 vmem_free(iscsit_global
.global_tsih_pool
, (void *)(uintptr_t)tsih
, 1);
115 iscsit_sess_create(iscsit_tgt_t
*tgt
, iscsit_conn_t
*ict
,
116 uint32_t cmdsn
, uint8_t *isid
, uint16_t tag
,
117 char *initiator_name
, char *target_name
,
118 uint8_t *error_class
, uint8_t *error_detail
)
120 iscsit_sess_t
*result
;
122 *error_class
= ISCSI_STATUS_CLASS_SUCCESS
;
125 * Even if this session create "fails" for some reason we still need
126 * to return a valid session pointer so that we can send the failed
129 result
= kmem_zalloc(sizeof (*result
), KM_SLEEP
);
132 if ((result
->ist_tsih
= iscsit_tsih_alloc()) == ISCSI_UNSPEC_TSIH
) {
134 *error_class
= ISCSI_STATUS_CLASS_TARGET_ERR
;
135 *error_detail
= ISCSI_LOGIN_STATUS_NO_RESOURCES
;
137 * Continue initializing this session so we can use it
138 * to complete the login process.
142 idm_sm_audit_init(&result
->ist_state_audit
);
143 mutex_init(&result
->ist_sn_mutex
, NULL
, MUTEX_DEFAULT
, NULL
);
144 mutex_init(&result
->ist_mutex
, NULL
, MUTEX_DEFAULT
, NULL
);
145 cv_init(&result
->ist_cv
, NULL
, CV_DEFAULT
, NULL
);
146 list_create(&result
->ist_events
, sizeof (sess_event_ctx_t
),
147 offsetof(sess_event_ctx_t
, se_ctx_node
));
148 list_create(&result
->ist_conn_list
, sizeof (iscsit_conn_t
),
149 offsetof(iscsit_conn_t
, ict_sess_ln
));
150 avl_create(&result
->ist_task_list
, iscsit_task_itt_compare
,
151 sizeof (iscsit_task_t
), offsetof(iscsit_task_t
, it_sess_ln
));
152 result
->ist_rxpdu_queue
= kmem_zalloc(sizeof (iscsit_cbuf_t
), KM_SLEEP
);
153 result
->ist_state
= SS_Q1_FREE
;
154 result
->ist_last_state
= SS_Q1_FREE
;
155 bcopy(isid
, result
->ist_isid
, ISCSI_ISID_LEN
);
156 result
->ist_tpgt_tag
= tag
;
158 result
->ist_tgt
= tgt
;
160 * cmdsn/expcmdsn do not advance during login phase.
162 result
->ist_expcmdsn
= cmdsn
;
163 result
->ist_maxcmdsn
= result
->ist_expcmdsn
+ 1;
165 result
->ist_initiator_name
=
166 kmem_alloc(strlen(initiator_name
) + 1, KM_SLEEP
);
167 (void) strcpy(result
->ist_initiator_name
, initiator_name
);
169 /* A discovery session might not have a target name */
170 result
->ist_target_name
=
171 kmem_alloc(strlen(target_name
) + 1, KM_SLEEP
);
172 (void) strcpy(result
->ist_target_name
, target_name
);
174 idm_refcnt_init(&result
->ist_refcnt
, result
);
176 /* Login code will fill in ist_stmf_sess if necessary */
178 if (*error_class
== ISCSI_STATUS_CLASS_SUCCESS
) {
180 * Make sure the service is still enabled and if so get a global
181 * hold to represent this session.
183 mutex_enter(&iscsit_global
.global_state_mutex
);
184 if (iscsit_global
.global_svc_state
== ISE_ENABLED
) {
185 iscsit_global_hold();
186 mutex_exit(&iscsit_global
.global_state_mutex
);
189 * Kick session state machine (also binds connection
192 iscsit_sess_sm_event(result
, SE_CONN_IN_LOGIN
, ict
);
194 *error_class
= ISCSI_STATUS_CLASS_SUCCESS
;
196 mutex_exit(&iscsit_global
.global_state_mutex
);
197 *error_class
= ISCSI_STATUS_CLASS_TARGET_ERR
;
198 *error_detail
= ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE
;
203 * As noted above we must return a session pointer even if something
204 * failed. The resources will get freed later.
210 iscsit_sess_unref(void *ist_void
)
212 iscsit_sess_t
*ist
= ist_void
;
213 stmf_scsi_session_t
*iss
;
216 * State machine has run to completion, destroy session
218 * If we have an associated STMF session we should clean it
221 * This session is no longer associated with a target at this
222 * point so don't touch the target.
224 mutex_enter(&ist
->ist_mutex
);
225 ASSERT(ist
->ist_conn_count
== 0);
226 iss
= ist
->ist_stmf_sess
;
228 stmf_deregister_scsi_session(ist
->ist_lport
, iss
);
229 kmem_free(iss
->ss_rport_id
, sizeof (scsi_devid_desc_t
) +
230 strlen(ist
->ist_initiator_name
) + 1);
231 stmf_remote_port_free(iss
->ss_rport
);
232 if (iss
->ss_rport_alias
)
233 strfree(iss
->ss_rport_alias
);
236 mutex_exit(&ist
->ist_mutex
);
238 iscsit_sess_destroy(ist
);
239 iscsit_global_rele();
243 iscsit_sess_destroy(iscsit_sess_t
*ist
)
245 idm_refcnt_destroy(&ist
->ist_refcnt
);
246 if (ist
->ist_initiator_name
)
247 kmem_free(ist
->ist_initiator_name
,
248 strlen(ist
->ist_initiator_name
) + 1);
249 if (ist
->ist_initiator_alias
)
250 kmem_free(ist
->ist_initiator_alias
,
251 strlen(ist
->ist_initiator_alias
) + 1);
252 if (ist
->ist_target_name
)
253 kmem_free(ist
->ist_target_name
,
254 strlen(ist
->ist_target_name
) + 1);
255 if (ist
->ist_target_alias
)
256 kmem_free(ist
->ist_target_alias
,
257 strlen(ist
->ist_target_alias
) + 1);
258 avl_destroy(&ist
->ist_task_list
);
259 kmem_free(ist
->ist_rxpdu_queue
, sizeof (iscsit_cbuf_t
));
260 list_destroy(&ist
->ist_conn_list
);
261 list_destroy(&ist
->ist_events
);
262 cv_destroy(&ist
->ist_cv
);
263 mutex_destroy(&ist
->ist_mutex
);
264 mutex_destroy(&ist
->ist_sn_mutex
);
265 kmem_free(ist
, sizeof (*ist
));
269 iscsit_sess_close(iscsit_sess_t
*ist
)
273 mutex_enter(&ist
->ist_mutex
);
275 * Note in the session state that we are forcing this session
276 * to close so that the session state machine can avoid
277 * pointless delays like transitions to SS_Q4_FAILED state.
279 ist
->ist_admin_close
= B_TRUE
;
280 if (ist
->ist_state
== SS_Q3_LOGGED_IN
) {
281 for (ict
= list_head(&ist
->ist_conn_list
);
283 ict
= list_next(&ist
->ist_conn_list
, ict
)) {
284 iscsit_send_async_event(ict
,
285 ISCSI_ASYNC_EVENT_REQUEST_LOGOUT
);
288 mutex_exit(&ist
->ist_mutex
);
293 iscsit_sess_bind_conn(iscsit_sess_t
*ist
, iscsit_conn_t
*ict
)
295 iscsit_conn_hold(ict
);
296 iscsit_sess_hold(ist
);
298 mutex_enter(&ist
->ist_mutex
);
299 ist
->ist_conn_count
++;
300 list_insert_tail(&ist
->ist_conn_list
, ict
);
301 mutex_exit(&ist
->ist_mutex
);
305 iscsit_sess_unbind_conn(iscsit_sess_t
*ist
, iscsit_conn_t
*ict
)
307 mutex_enter(&ist
->ist_mutex
);
308 list_remove(&ist
->ist_conn_list
, ict
);
309 ist
->ist_conn_count
--;
310 mutex_exit(&ist
->ist_mutex
);
311 iscsit_sess_rele(ist
);
312 iscsit_conn_rele(ict
);
316 iscsit_sess_hold(iscsit_sess_t
*ist
)
318 idm_refcnt_hold(&ist
->ist_refcnt
);
322 iscsit_sess_rele(iscsit_sess_t
*ist
)
324 idm_refcnt_rele(&ist
->ist_refcnt
);
328 iscsit_sess_check_hold(iscsit_sess_t
*ist
)
330 mutex_enter(&ist
->ist_mutex
);
331 if (ist
->ist_state
!= SS_Q6_DONE
&&
332 ist
->ist_state
!= SS_Q7_ERROR
) {
333 idm_refcnt_hold(&ist
->ist_refcnt
);
334 mutex_exit(&ist
->ist_mutex
);
335 return (IDM_STATUS_SUCCESS
);
337 mutex_exit(&ist
->ist_mutex
);
338 return (IDM_STATUS_FAIL
);
342 iscsit_sess_lookup_conn(iscsit_sess_t
*ist
, uint16_t cid
)
344 iscsit_conn_t
*result
;
346 mutex_enter(&ist
->ist_mutex
);
347 for (result
= list_head(&ist
->ist_conn_list
);
349 result
= list_next(&ist
->ist_conn_list
, result
)) {
350 if (result
->ict_cid
== cid
) {
351 iscsit_conn_hold(result
);
352 mutex_exit(&ist
->ist_mutex
);
356 mutex_exit(&ist
->ist_mutex
);
362 iscsit_sess_reinstate(iscsit_tgt_t
*tgt
, iscsit_sess_t
*ist
, iscsit_conn_t
*ict
,
363 uint8_t *error_class
, uint8_t *error_detail
)
365 iscsit_sess_t
*new_sess
;
367 mutex_enter(&ist
->ist_mutex
);
370 * Session reinstatement replaces a current session with a new session.
371 * The new session will have the same ISID as the existing session.
373 new_sess
= iscsit_sess_create(tgt
, ict
, 0,
374 ist
->ist_isid
, ist
->ist_tpgt_tag
,
375 ist
->ist_initiator_name
, ist
->ist_target_name
,
376 error_class
, error_detail
);
377 ASSERT(new_sess
!= NULL
);
379 /* Copy additional fields from original session */
380 new_sess
->ist_expcmdsn
= ist
->ist_expcmdsn
;
381 new_sess
->ist_maxcmdsn
= ist
->ist_expcmdsn
+ 1;
383 if (ist
->ist_state
!= SS_Q6_DONE
&&
384 ist
->ist_state
!= SS_Q7_ERROR
) {
386 * Generate reinstate event
388 sess_sm_event_locked(ist
, SE_SESSION_REINSTATE
, NULL
);
390 mutex_exit(&ist
->ist_mutex
);
396 iscsit_sess_avl_compare(const void *void_sess1
, const void *void_sess2
)
398 const iscsit_sess_t
*sess1
= void_sess1
;
399 const iscsit_sess_t
*sess2
= void_sess2
;
403 * Sort by initiator name, then ISID then portal group tag
405 result
= strcmp(sess1
->ist_initiator_name
, sess2
->ist_initiator_name
);
408 } else if (result
> 0) {
413 * Initiator names match, compare ISIDs
415 result
= memcmp(sess1
->ist_isid
, sess2
->ist_isid
, ISCSI_ISID_LEN
);
418 } else if (result
> 0) {
423 * ISIDs match, compare portal group tags
425 if (sess1
->ist_tpgt_tag
< sess2
->ist_tpgt_tag
) {
427 } else if (sess1
->ist_tpgt_tag
> sess2
->ist_tpgt_tag
) {
432 * Portal group tags match, compare TSIHs
434 if (sess1
->ist_tsih
< sess2
->ist_tsih
) {
436 } else if (sess1
->ist_tsih
> sess2
->ist_tsih
) {
447 iscsit_task_itt_compare(const void *void_task1
, const void *void_task2
)
449 const iscsit_task_t
*task1
= void_task1
;
450 const iscsit_task_t
*task2
= void_task2
;
452 if (task1
->it_itt
< task2
->it_itt
)
454 else if (task1
->it_itt
> task2
->it_itt
)
465 iscsit_sess_sm_event(iscsit_sess_t
*ist
, iscsit_session_event_t event
,
468 mutex_enter(&ist
->ist_mutex
);
469 sess_sm_event_locked(ist
, event
, ict
);
470 mutex_exit(&ist
->ist_mutex
);
474 sess_sm_event_locked(iscsit_sess_t
*ist
, iscsit_session_event_t event
,
477 sess_event_ctx_t
*ctx
;
479 iscsit_sess_hold(ist
);
481 ctx
= kmem_zalloc(sizeof (*ctx
), KM_SLEEP
);
483 ctx
->se_ctx_event
= event
;
484 ctx
->se_event_data
= ict
;
486 list_insert_tail(&ist
->ist_events
, ctx
);
488 * Use the ist_sm_busy to keep the state machine single threaded.
489 * This also serves as recursion avoidance since this flag will
490 * always be set if we call login_sm_event from within the
491 * state machine code.
493 if (!ist
->ist_sm_busy
) {
494 ist
->ist_sm_busy
= B_TRUE
;
495 while (!list_is_empty(&ist
->ist_events
)) {
496 ctx
= list_head(&ist
->ist_events
);
497 list_remove(&ist
->ist_events
, ctx
);
498 idm_sm_audit_event(&ist
->ist_state_audit
,
499 SAS_ISCSIT_SESS
, (int)ist
->ist_state
,
500 (int)ctx
->se_ctx_event
, (uintptr_t)ict
);
501 mutex_exit(&ist
->ist_mutex
);
502 sess_sm_event_dispatch(ist
, ctx
);
503 mutex_enter(&ist
->ist_mutex
);
505 ist
->ist_sm_busy
= B_FALSE
;
509 iscsit_sess_rele(ist
);
513 sess_sm_event_dispatch(iscsit_sess_t
*ist
, sess_event_ctx_t
*ctx
)
517 DTRACE_PROBE2(session__event
, iscsit_sess_t
*, ist
,
518 sess_event_ctx_t
*, ctx
);
520 IDM_SM_LOG(CE_NOTE
, "sess_sm_event_dispatch: sess %p event %s(%d)",
521 (void *)ist
, iscsit_se_name
[ctx
->se_ctx_event
], ctx
->se_ctx_event
);
523 /* State independent actions */
524 switch (ctx
->se_ctx_event
) {
525 case SE_CONN_IN_LOGIN
:
526 ict
= ctx
->se_event_data
;
527 iscsit_sess_bind_conn(ist
, ict
);
530 ict
= ctx
->se_event_data
;
531 iscsit_sess_unbind_conn(ist
, ict
);
535 /* State dependent actions */
536 switch (ist
->ist_state
) {
538 sess_sm_q1_free(ist
, ctx
);
541 sess_sm_q2_active(ist
, ctx
);
543 case SS_Q3_LOGGED_IN
:
544 sess_sm_q3_logged_in(ist
, ctx
);
547 sess_sm_q4_failed(ist
, ctx
);
550 sess_sm_q5_continue(ist
, ctx
);
553 sess_sm_q6_done(ist
, ctx
);
556 sess_sm_q7_error(ist
, ctx
);
563 kmem_free(ctx
, sizeof (*ctx
));
567 sess_sm_q1_free(iscsit_sess_t
*ist
, sess_event_ctx_t
*ctx
)
569 switch (ctx
->se_ctx_event
) {
570 case SE_CONN_IN_LOGIN
:
572 sess_sm_new_state(ist
, ctx
, SS_Q2_ACTIVE
);
582 sess_sm_q2_active(iscsit_sess_t
*ist
, sess_event_ctx_t
*ctx
)
586 switch (ctx
->se_ctx_event
) {
587 case SE_CONN_LOGGED_IN
:
588 /* N2 track FFP connections */
589 ist
->ist_ffp_conn_count
++;
590 sess_sm_new_state(ist
, ctx
, SS_Q3_LOGGED_IN
);
592 case SE_CONN_IN_LOGIN
:
593 /* N2.1, don't care stay in this state */
597 sess_sm_new_state(ist
, ctx
, SS_Q7_ERROR
);
599 case SE_SESSION_REINSTATE
:
602 * Shutdown the iSCSI connections by
603 * sending an implicit logout to all
604 * the IDM connections and transition
605 * the session to SS_Q6_DONE state.
607 mutex_enter(&ist
->ist_mutex
);
608 for (ict
= list_head(&ist
->ist_conn_list
);
610 ict
= list_next(&ist
->ist_conn_list
, ict
)) {
611 iscsit_conn_logout(ict
);
613 mutex_exit(&ist
->ist_mutex
);
614 sess_sm_new_state(ist
, ctx
, SS_Q6_DONE
);
623 sess_sm_q3_logged_in(iscsit_sess_t
*ist
, sess_event_ctx_t
*ctx
)
627 switch (ctx
->se_ctx_event
) {
628 case SE_CONN_IN_LOGIN
:
630 /* N2.2, don't care */
632 case SE_CONN_LOGGED_IN
:
633 /* N2.2, track FFP connections */
634 ist
->ist_ffp_conn_count
++;
636 case SE_CONN_FFP_FAIL
:
637 case SE_CONN_FFP_DISABLE
:
639 * Event data from event context is the associated connection
640 * which in this case happens to be the last FFP connection
641 * for the session. In certain cases we need to refer
642 * to this last valid connection (i.e. RFC3720 section 12.16)
643 * so we'll save off a pointer here for later use.
645 ASSERT(ist
->ist_ffp_conn_count
>= 1);
646 ist
->ist_failed_conn
= (iscsit_conn_t
*)ctx
->se_event_data
;
647 ist
->ist_ffp_conn_count
--;
648 if (ist
->ist_ffp_conn_count
== 0) {
650 * N5(fail) or N3(disable)
652 * If the event is SE_CONN_FFP_FAIL but we are
653 * in the midst of an administrative session close
654 * because of a service or target offline then
655 * there is no need to go to "failed" state.
657 sess_sm_new_state(ist
, ctx
,
658 ((ctx
->se_ctx_event
== SE_CONN_FFP_DISABLE
) ||
659 (ist
->ist_admin_close
)) ?
660 SS_Q6_DONE
: SS_Q4_FAILED
);
663 case SE_SESSION_CLOSE
:
664 case SE_SESSION_REINSTATE
:
666 mutex_enter(&ist
->ist_mutex
);
667 if (ctx
->se_ctx_event
== SE_SESSION_CLOSE
) {
668 ASSERT(ist
->ist_ffp_conn_count
>= 1);
669 ist
->ist_ffp_conn_count
--;
671 for (ict
= list_head(&ist
->ist_conn_list
);
673 ict
= list_next(&ist
->ist_conn_list
, ict
)) {
674 if ((ctx
->se_ctx_event
== SE_SESSION_CLOSE
) &&
675 ((iscsit_conn_t
*)ctx
->se_event_data
== ict
)) {
677 * Skip this connection since it will
678 * see the logout response
682 iscsit_conn_logout(ict
);
684 mutex_exit(&ist
->ist_mutex
);
686 sess_sm_new_state(ist
, ctx
, SS_Q6_DONE
);
695 sess_sm_timeout(void *arg
)
697 iscsit_sess_t
*ist
= arg
;
699 iscsit_sess_sm_event(ist
, SE_SESSION_TIMEOUT
, NULL
);
703 sess_sm_q4_failed(iscsit_sess_t
*ist
, sess_event_ctx_t
*ctx
)
705 /* Session timer must not be running when we leave this event */
706 switch (ctx
->se_ctx_event
) {
707 case SE_CONN_IN_LOGIN
:
709 sess_sm_new_state(ist
, ctx
, SS_Q5_CONTINUE
);
711 case SE_SESSION_REINSTATE
:
713 (void) untimeout(ist
->ist_state_timeout
);
715 case SE_SESSION_TIMEOUT
:
717 sess_sm_new_state(ist
, ctx
, SS_Q6_DONE
);
729 sess_sm_q5_continue(iscsit_sess_t
*ist
, sess_event_ctx_t
*ctx
)
731 switch (ctx
->se_ctx_event
) {
734 sess_sm_new_state(ist
, ctx
, SS_Q4_FAILED
);
736 case SE_CONN_LOGGED_IN
:
738 sess_sm_new_state(ist
, ctx
, SS_Q3_LOGGED_IN
);
740 case SE_SESSION_REINSTATE
:
742 sess_sm_new_state(ist
, ctx
, SS_Q6_DONE
);
751 sess_sm_q6_done(iscsit_sess_t
*ist
, sess_event_ctx_t
*ctx
)
754 switch (ctx
->se_ctx_event
) {
755 case SE_CONN_LOGGED_IN
:
757 * It's possible to get this event if we encountered
758 * an SE_SESSION_REINSTATE_EVENT while we were in
759 * SS_Q2_ACTIVE state. If so we want to update
760 * ist->ist_ffp_conn_count because we know an
761 * SE_CONN_FFP_FAIL or SE_CONN_FFP_DISABLE is on the
764 ist
->ist_ffp_conn_count
++;
766 case SE_CONN_FFP_FAIL
:
767 case SE_CONN_FFP_DISABLE
:
768 ASSERT(ist
->ist_ffp_conn_count
>= 1);
769 ist
->ist_ffp_conn_count
--;
772 if (ist
->ist_conn_count
== 0) {
773 idm_refcnt_async_wait_ref(&ist
->ist_refcnt
,
783 sess_sm_q7_error(iscsit_sess_t
*ist
, sess_event_ctx_t
*ctx
)
786 switch (ctx
->se_ctx_event
) {
788 if (ist
->ist_conn_count
== 0) {
789 idm_refcnt_async_wait_ref(&ist
->ist_refcnt
,
799 sess_sm_new_state(iscsit_sess_t
*ist
, sess_event_ctx_t
*ctx
,
800 iscsit_session_state_t new_state
)
807 ASSERT(new_state
!= SS_UNDEFINED
);
808 ASSERT3U(new_state
, <, SS_MAX_STATE
);
810 new_state
= (new_state
< SS_MAX_STATE
) ?
811 new_state
: SS_UNDEFINED
;
813 IDM_SM_LOG(CE_NOTE
, "sess_sm_new_state: sess %p, evt %s(%d), "
814 "%s(%d) --> %s(%d)\n", (void *) ist
,
815 iscsit_se_name
[ctx
->se_ctx_event
], ctx
->se_ctx_event
,
816 iscsit_ss_name
[ist
->ist_state
], ist
->ist_state
,
817 iscsit_ss_name
[new_state
], new_state
);
819 DTRACE_PROBE3(sess__state__change
,
820 iscsit_sess_t
*, ist
, sess_event_ctx_t
*, ctx
,
821 iscsit_session_state_t
, new_state
);
823 mutex_enter(&ist
->ist_mutex
);
824 idm_sm_audit_state_change(&ist
->ist_state_audit
, SAS_ISCSIT_SESS
,
825 (int)ist
->ist_state
, (int)new_state
);
826 ist
->ist_last_state
= ist
->ist_state
;
827 ist
->ist_state
= new_state
;
828 mutex_exit(&ist
->ist_mutex
);
830 switch (ist
->ist_state
) {
834 iscsit_tgt_bind_sess(ist
->ist_tgt
, ist
);
836 case SS_Q3_LOGGED_IN
:
840 ist
->ist_failed_conn
->ict_op
.op_default_time_2_retain
;
841 ist
->ist_state_timeout
= timeout(sess_sm_timeout
, ist
,
842 drv_usectohz(t2r_secs
*1000000));
849 * We won't need our TSIH anymore and it represents an
850 * implicit reference to the global TSIH pool. Get rid
853 if (ist
->ist_tsih
!= ISCSI_UNSPEC_TSIH
) {
854 iscsit_tsih_free(ist
->ist_tsih
);
858 * We don't want this session to show up anymore so unbind
859 * it now. After this call this session cannot have any
860 * references outside itself (implicit or explicit).
862 iscsit_tgt_unbind_sess(ist
->ist_tgt
, ist
);
865 * If we have more connections bound then more events
866 * are comming so don't wait for idle yet.
868 if (ist
->ist_conn_count
== 0) {
869 idm_refcnt_async_wait_ref(&ist
->ist_refcnt
,