]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blobdiff - src/patches/suse-2.6.27.31/patches.fixes/libiscsi-fix-nop-response-reply-and-session-cleanup.patch
Reenabled linux-xen, added patches for Xen Kernel Version 2.6.27.31,
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.fixes / libiscsi-fix-nop-response-reply-and-session-cleanup.patch
diff --git a/src/patches/suse-2.6.27.31/patches.fixes/libiscsi-fix-nop-response-reply-and-session-cleanup.patch b/src/patches/suse-2.6.27.31/patches.fixes/libiscsi-fix-nop-response-reply-and-session-cleanup.patch
new file mode 100644 (file)
index 0000000..f49fb25
--- /dev/null
@@ -0,0 +1,61 @@
+From: Mike Christie <michaelc@cs.wisc.edu>
+Date: Tue, 28 Apr 2009 13:38:18 -0400
+Subject: libiscsi: fix nop response/reply and session cleanup race
+References: bnc#499558
+
+If we are responding to a nop from the target by sending our nop,
+and the session is getting torn down, then iscsi_start_session_recovery
+could set the conn stop bits while the recv path is sending the nop
+response and we will hit the bug ons in __iscsi_conn_send_pdu.
+
+This has us check the state in __iscsi_conn_send_pdu and fail all
+incoming mgmt IO if we are  not logged in and if the pdu is not login
+related. It also changes the ordering of the setting of conn stop state
+bits so they are set after the session state is set (both are set under
+the session lock).
+
+Acked-by: Jean Delvare <jdelvare@suse.de>
+---
+ drivers/scsi/libiscsi.c |   11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+--- a/drivers/scsi/libiscsi.c
++++ b/drivers/scsi/libiscsi.c
+@@ -502,6 +502,9 @@ __iscsi_conn_send_pdu(struct iscsi_conn 
+                */
+               task = conn->login_task;
+       else {
++              if (session->state != ISCSI_STATE_LOGGED_IN)
++                      return NULL;
++
+               BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE);
+               BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED);
+@@ -2414,8 +2417,6 @@ static void iscsi_start_session_recovery
+ {
+       int old_stop_stage;
+-      del_timer_sync(&conn->transport_timer);
+-
+       mutex_lock(&session->eh_mutex);
+       spin_lock_bh(&session->lock);
+       if (conn->stop_stage == STOP_CONN_TERM) {
+@@ -2433,13 +2434,17 @@ static void iscsi_start_session_recovery
+               session->state = ISCSI_STATE_TERMINATE;
+       else if (conn->stop_stage != STOP_CONN_RECOVER)
+               session->state = ISCSI_STATE_IN_RECOVERY;
++      spin_unlock_bh(&session->lock);
++      del_timer_sync(&conn->transport_timer);
++      iscsi_suspend_tx(conn);
++
++      spin_lock_bh(&session->lock);
+       old_stop_stage = conn->stop_stage;
+       conn->stop_stage = flag;
+       conn->c_stage = ISCSI_CONN_STOPPED;
+       spin_unlock_bh(&session->lock);
+-      iscsi_suspend_tx(conn);
+       /*
+        * for connection level recovery we should not calculate
+        * header digest. conn->hdr_size used for optimization