changeset 10317:0a8cd85041eb

6842646 iSCSI initiator will hang when logging in iscsitgt:default target with the same IP in different tpgt
author yi zhang - Sun Microsystems - Beijing China <Zhang.Yi@Sun.COM>
date Sun, 16 Aug 2009 01:17:24 +0800
parents d68e26bd3bfd
children 811db323512d
files usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_conn.c usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_login.c
diffstat 2 files changed, 39 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_conn.c	Sat Aug 15 09:43:34 2009 +0800
+++ b/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_conn.c	Sun Aug 16 01:17:24 2009 +0800
@@ -478,13 +478,14 @@
 
 		/*
 		 * This logic assumes that the IDM login-snooping code
-		 * and the initiator login code will agree on whether
-		 * the connection is in FFP.  The reason we do this
-		 * is that we don't want to process CN_FFP_DISABLED until
-		 * CN_FFP_ENABLED has been full handled.
+		 * and the initiator login code will agree to go when
+		 * the connection is in FFP or final error received.
+		 * The reason we do this is that we don't want to process
+		 * CN_FFP_DISABLED until CN_FFP_ENABLED has been full handled.
 		 */
 		mutex_enter(&icp->conn_login_mutex);
-		while (icp->conn_login_state != LOGIN_FFP) {
+		while ((icp->conn_login_state != LOGIN_FFP) &&
+		    (icp->conn_login_state != LOGIN_ERROR)) {
 			cv_wait(&icp->conn_login_cv, &icp->conn_login_mutex);
 		}
 		mutex_exit(&icp->conn_login_mutex);
@@ -524,8 +525,13 @@
 
 		case FD_CONN_FAIL:
 		default:
-			iscsi_conn_update_state_locked(icp,
-			    ISCSI_CONN_STATE_FAILED);
+			if (icp->conn_state == ISCSI_CONN_STATE_IN_LOGIN) {
+				iscsi_conn_update_state_locked(icp,
+				    ISCSI_CONN_STATE_FREE);
+			} else {
+				iscsi_conn_update_state_locked(icp,
+				    ISCSI_CONN_STATE_FAILED);
+			}
 			break;
 		}
 
@@ -544,7 +550,8 @@
 		 * what CN_CONNECT_LOST means to us.
 		 */
 		in_login = (boolean_t)data;
-		if (in_login) {
+		if (in_login ||
+		    (icp->conn_prev_state == ISCSI_CONN_STATE_IN_LOGIN)) {
 			mutex_enter(&icp->conn_state_mutex);
 
 			icp->conn_state_idm_connected = B_FALSE;
--- a/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_login.c	Sat Aug 15 09:43:34 2009 +0800
+++ b/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_login.c	Sun Aug 16 01:17:24 2009 +0800
@@ -57,6 +57,14 @@
 
 #define	ISCSI_LOGIN_RETRY_DELAY		5	/* seconds */
 
+#define	ISCSI_LOGIN_TRANSIT_FFP(flags) \
+	(!(flags & ISCSI_FLAG_LOGIN_CONTINUE) && \
+	(flags & ISCSI_FLAG_LOGIN_TRANSIT) && \
+	(ISCSI_LOGIN_CURRENT_STAGE(flags) == \
+	ISCSI_OP_PARMS_NEGOTIATION_STAGE) && \
+	(ISCSI_LOGIN_NEXT_STAGE(flags) == \
+	ISCSI_FULL_FEATURE_PHASE))
+
 /*
  * +--------------------------------------------------------------------+
  * | External Login Interface						|
@@ -310,7 +318,11 @@
 				}
 			}
 			break;
+		case ISCSI_CONN_STATE_FREE:
+			mutex_exit(&icp->conn_state_mutex);
+			break;
 		default:
+			mutex_exit(&icp->conn_state_mutex);
 			ASSERT(0);
 			break;
 		}
@@ -535,6 +547,18 @@
 			    icp->conn_login_max_data_length);
 			/* pass back whatever error we discovered */
 			if (!ISCSI_SUCCESS(rval)) {
+				if (ISCSI_LOGIN_TRANSIT_FFP(ilrhp->flags)) {
+					/*
+					 * iSCSI connection transit to next
+					 * FFP stage while iscsi params
+					 * ngeotiate error, LOGIN_ERROR
+					 * marked so CN_FFP_ENABLED can
+					 * be fully handled before
+					 * CN_FFP_DISABLED can be processed.
+					 */
+					iscsi_login_update_state(icp,
+					    LOGIN_ERROR);
+				}
 				goto iscsi_login_done;
 			}