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.