changeset 12579:611412d35eb8

6951720 host side port offline whiel IO running made iscsi target system panic 6929441 iscsit sometimes doesn't teardown connections during session reinstatement 6835615 IDM refcnt rules are obscure and to be better defined
author Priya Krishnan <Priya.Krishnan@Sun.COM>
date Mon, 07 Jun 2010 17:33:23 -0400
parents f9062c43c8bc
children 4daad5d7c55d
files usr/src/uts/common/io/comstar/port/iscsit/iscsit.c usr/src/uts/common/io/comstar/port/iscsit/iscsit.h usr/src/uts/common/io/comstar/port/iscsit/iscsit_sess.c usr/src/uts/common/io/comstar/port/iscsit/iscsit_tgt.c usr/src/uts/common/io/idm/idm_conn_sm.c
diffstat 5 files changed, 87 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/io/comstar/port/iscsit/iscsit.c	Mon Jun 07 14:07:27 2010 -0700
+++ b/usr/src/uts/common/io/comstar/port/iscsit/iscsit.c	Mon Jun 07 17:33:23 2010 -0400
@@ -1367,10 +1367,14 @@
 		iscsit_sess_sm_event(ict->ict_sess, SE_CONN_FAIL, ict);
 	}
 
+	idm_refcnt_wait_ref(&ict->ict_refcnt);
+	/*
+	 * The session state machine does not need to post
+	 * events to IDM any longer, so it is safe to set
+	 * the idm connection reference to NULL
+	 */
 	ict->ict_ic = NULL;
 
-	idm_refcnt_wait_ref(&ict->ict_refcnt);
-
 	/* Reap the login state machine */
 	iscsit_login_sm_fini(ict);
 
@@ -1386,6 +1390,23 @@
 	return (IDM_STATUS_SUCCESS);
 }
 
+void
+iscsit_conn_logout(iscsit_conn_t *ict)
+{
+	/*
+	 * If the iscsi connection is active, then
+	 * logout the IDM connection by sending a
+	 * CE_LOGOUT_SESSION_SUCCESS, else, no action
+	 * needs to be taken because the connection
+	 * is already in the teardown process.
+	 */
+	mutex_enter(&ict->ict_mutex);
+	if (ict->ict_lost == B_FALSE && ict->ict_destroyed == B_FALSE) {
+		idm_conn_event(ict->ict_ic, CE_LOGOUT_SESSION_SUCCESS, NULL);
+	}
+	mutex_exit(&ict->ict_mutex);
+}
+
 /*
  * STMF-related functions
  *
--- a/usr/src/uts/common/io/comstar/port/iscsit/iscsit.h	Mon Jun 07 14:07:27 2010 -0700
+++ b/usr/src/uts/common/io/comstar/port/iscsit/iscsit.h	Mon Jun 07 17:33:23 2010 -0400
@@ -688,6 +688,9 @@
 void
 iscsit_conn_rele(iscsit_conn_t *ict);
 
+void
+iscsit_conn_logout(iscsit_conn_t *ict);
+
 /*
  * Session functions
  */
@@ -706,6 +709,9 @@
 void
 iscsit_sess_hold(iscsit_sess_t *ist);
 
+idm_status_t
+iscsit_sess_check_hold(iscsit_sess_t *ist);
+
 void
 iscsit_sess_rele(iscsit_sess_t *ist);
 
--- a/usr/src/uts/common/io/comstar/port/iscsit/iscsit_sess.c	Mon Jun 07 14:07:27 2010 -0700
+++ b/usr/src/uts/common/io/comstar/port/iscsit/iscsit_sess.c	Mon Jun 07 17:33:23 2010 -0400
@@ -319,6 +319,20 @@
 	idm_refcnt_rele(&ist->ist_refcnt);
 }
 
+idm_status_t
+iscsit_sess_check_hold(iscsit_sess_t *ist)
+{
+	mutex_enter(&ist->ist_mutex);
+	if (ist->ist_state != SS_Q6_DONE &&
+	    ist->ist_state != SS_Q7_ERROR) {
+		idm_refcnt_hold(&ist->ist_refcnt);
+		mutex_exit(&ist->ist_mutex);
+		return (IDM_STATUS_SUCCESS);
+	}
+	mutex_exit(&ist->ist_mutex);
+	return (IDM_STATUS_FAIL);
+}
+
 iscsit_conn_t *
 iscsit_sess_lookup_conn(iscsit_sess_t *ist, uint16_t cid)
 {
@@ -562,6 +576,8 @@
 static void
 sess_sm_q2_active(iscsit_sess_t *ist, sess_event_ctx_t *ctx)
 {
+	iscsit_conn_t	*ict;
+
 	switch (ctx->se_ctx_event) {
 	case SE_CONN_LOGGED_IN:
 		/* N2 track FFP connections */
@@ -577,6 +593,19 @@
 		break;
 	case SE_SESSION_REINSTATE:
 		/* N11 */
+		/*
+		 * Shutdown the iSCSI connections by
+		 * sending an implicit logout to all
+		 * the IDM connections and transition
+		 * the session to SS_Q6_DONE state.
+		 */
+		mutex_enter(&ist->ist_mutex);
+		for (ict = list_head(&ist->ist_conn_list);
+		    ict != NULL;
+		    ict = list_next(&ist->ist_conn_list, ict)) {
+			iscsit_conn_logout(ict);
+		}
+		mutex_exit(&ist->ist_mutex);
 		sess_sm_new_state(ist, ctx, SS_Q6_DONE);
 		break;
 	default:
@@ -588,7 +617,7 @@
 static void
 sess_sm_q3_logged_in(iscsit_sess_t *ist, sess_event_ctx_t *ctx)
 {
-	iscsit_conn_t *ict;
+	iscsit_conn_t	*ict;
 
 	switch (ctx->se_ctx_event) {
 	case SE_CONN_IN_LOGIN:
@@ -645,8 +674,7 @@
 				 */
 				continue;
 			}
-			idm_conn_event(ict->ict_ic, CE_LOGOUT_SESSION_SUCCESS,
-			    NULL);
+			iscsit_conn_logout(ict);
 		}
 		mutex_exit(&ist->ist_mutex);
 
--- a/usr/src/uts/common/io/comstar/port/iscsit/iscsit_tgt.c	Mon Jun 07 14:07:27 2010 -0700
+++ b/usr/src/uts/common/io/comstar/port/iscsit/iscsit_tgt.c	Mon Jun 07 17:33:23 2010 -0400
@@ -1230,9 +1230,7 @@
 
 	result = avl_find(sess_avl, &tmp_sess, &where);
 	if (result != NULL) {
-		iscsit_sess_hold(result);
-		UNLOCK_FOR_SESS_LOOKUP(tgt);
-		return (result);
+		goto found_result;
 	}
 
 	/*
@@ -1244,9 +1242,7 @@
 	    (strcmp(result->ist_initiator_name, initiator_name) == 0) &&
 	    (memcmp(result->ist_isid, isid, ISCSI_ISID_LEN) == 0) &&
 	    (result->ist_tpgt_tag == tag)) {
-		iscsit_sess_hold(result);
-		UNLOCK_FOR_SESS_LOOKUP(tgt);
-		return (result);
+		goto found_result;
 	}
 
 	result = avl_nearest(sess_avl, where, AVL_AFTER);
@@ -1254,14 +1250,18 @@
 	    (strcmp(result->ist_initiator_name, initiator_name) == 0) &&
 	    (memcmp(result->ist_isid, isid, ISCSI_ISID_LEN) == 0) &&
 	    (result->ist_tpgt_tag == tag)) {
-		iscsit_sess_hold(result);
-		UNLOCK_FOR_SESS_LOOKUP(tgt);
-		return (result);
+		goto found_result;
 	}
 
-	UNLOCK_FOR_SESS_LOOKUP(tgt);
+	result = NULL;
 
-	return (NULL);
+found_result:
+	if ((result != NULL) &&
+	    (iscsit_sess_check_hold(result) != IDM_STATUS_SUCCESS)) {
+		result = NULL;
+	}
+	UNLOCK_FOR_SESS_LOOKUP(tgt);
+	return (result);
 }
 
 static idm_status_t
--- a/usr/src/uts/common/io/idm/idm_conn_sm.c	Mon Jun 07 14:07:27 2010 -0700
+++ b/usr/src/uts/common/io/idm/idm_conn_sm.c	Mon Jun 07 17:33:23 2010 -0400
@@ -601,6 +601,22 @@
 		(void) idm_notify_client(ic, CN_LOGIN_FAIL, NULL);
 		idm_update_state(ic, CS_S9_INIT_ERROR, event_ctx);
 		break;
+	case CE_LOGOUT_SESSION_SUCCESS:
+		/*
+		 * T8
+		 * A session reinstatement request can be received while a
+		 * session is active and a login is in process. The iSCSI
+		 * connections are shut down by a CE_LOGOUT_SESSION_SUCCESS
+		 * event sent from the session to the IDM layer.
+		 */
+		if (IDM_CONN_ISTGT(ic)) {
+			ic->ic_transport_ops->it_tgt_conn_disconnect(ic);
+		} else {
+			ic->ic_transport_ops->it_ini_conn_disconnect(ic);
+		}
+		idm_update_state(ic, CS_S11_COMPLETE, event_ctx);
+		break;
+
 	case CE_LOGIN_SND:
 		ASSERT(ic->ic_client_callback == NULL);
 		/*