Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 89877e42827f16fa5f86b1df0c2860b1 > files > 966

kernel-2.6.18-128.1.10.el5.src.rpm

Date: Mon, 02 Oct 2006 17:43:20 -0500
From: Mike Christie <mchristi@redhat.com>
Subject: [PATCH RHEL5] fix oops if iscsi connection setup fails

This is for BZ 209006.

If connection setup fails, we will call list_del on a invalid pointer
causing an oops. This patch fixes this by just removing the list for
now. It is old code for a feature that was rejected upstream but did not
get completely cleaned up upstream. I did leave the list structs for
this RHEL patch. Just in case upstream decides to add it back, we will
not have to worry about KABI later on.

The patch that is going upstream slightly differs from the attached one
in that, the upstream patch removes the unused list structs since from
that perspective they are not needed and they do not have KABI.

diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index c542d0e..dfa4a29 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -778,6 +778,10 @@ int iscsi_queuecommand(struct scsi_cmnd 
 	}
 
 	conn = session->leadconn;
+	if (!conn) {
+		reason = FAILURE_SESSION_FREED;
+		goto fault;
+	}
 
 	if (!__kfifo_get(session->cmdpool.queue, (void*)&ctask,
 			 sizeof(void*))) {
@@ -1580,16 +1584,11 @@ void iscsi_conn_teardown(struct iscsi_cl
 	kfree(conn->persistent_address);
 	__kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask,
 		    sizeof(void*));
-	list_del(&conn->item);
-	if (list_empty(&session->connections))
+	if (session->leadconn == conn) {
 		session->leadconn = NULL;
-	if (session->leadconn && session->leadconn == conn)
-		session->leadconn = container_of(session->connections.next,
-			struct iscsi_conn, item);
-
-	if (session->leadconn == NULL)
 		/* no connections exits.. reset sequencing */
 		session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1;
+	}
 	spin_unlock_bh(&session->lock);
 
 	kfifo_free(conn->immqueue);
@@ -1777,32 +1776,12 @@ int iscsi_conn_bind(struct iscsi_cls_ses
 		    struct iscsi_cls_conn *cls_conn, int is_leading)
 {
 	struct iscsi_session *session = class_to_transport_session(cls_session);
-	struct iscsi_conn *tmp = ERR_PTR(-EEXIST), *conn = cls_conn->dd_data;
+	struct iscsi_conn *conn = cls_conn->dd_data;
 
-	/* lookup for existing connection */
 	spin_lock_bh(&session->lock);
-	list_for_each_entry(tmp, &session->connections, item) {
-		if (tmp == conn) {
-			if (conn->c_stage != ISCSI_CONN_STOPPED ||
-			    conn->stop_stage == STOP_CONN_TERM) {
-				printk(KERN_ERR "iscsi: can't bind "
-				       "non-stopped connection (%d:%d)\n",
-				       conn->c_stage, conn->stop_stage);
-				spin_unlock_bh(&session->lock);
-				return -EIO;
-			}
-			break;
-		}
-	}
-	if (tmp != conn) {
-		/* bind new iSCSI connection to session */
-		conn->session = session;
-		list_add(&conn->item, &session->connections);
-	}
-	spin_unlock_bh(&session->lock);
-
 	if (is_leading)
 		session->leadconn = conn;
+	spin_unlock_bh(&session->lock);
 
 	/*
 	 * Unblock xmitworker(), Login Phase will pass through.