From: Nicholas Bellinger <[email protected]>
This patch fixes a regression introduced with the following commit
in v4.0-rc1 code:
commit 88dcd2dab5c23b1c9cfc396246d8f476c872f0ca
Author: Nicholas Bellinger <[email protected]>
Date: Thu Feb 26 22:19:15 2015 -0800
iscsi-target: Convert iscsi_thread_set usage to kthread.h
where iscsit_start_kthreads() failure would result in a NULL pointer
dereference OOPs.
To address this bug, it adds a iscsit_kthread_err() helper to cleanup
both zero_tsih and !zero_tsih cases, and a iscsi_target_tx_thread()
special case to avoid iscsit_take_action_for_connection_exit() during
the late iscsit_start_kthreads() -> kthread_run() failure case for
iscsi_target_rx_thread().
Cc: Sagi Grimberg <[email protected]>
Cc: <[email protected]> # v3.10+
Signed-off-by: Nicholas Bellinger <[email protected]>
---
drivers/target/iscsi/iscsi_target.c | 3 ++-
drivers/target/iscsi/iscsi_target_login.c | 39 +++++++++++++++++++++++++++----
2 files changed, 36 insertions(+), 6 deletions(-)
diff --git a/drivers/target/iscsi/iscsi_target.c
b/drivers/target/iscsi/iscsi_target.c
index 4e68b62..66655b7 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -3998,7 +3998,8 @@ get_immediate:
}
transport_err:
- iscsit_take_action_for_connection_exit(conn);
+ if (conn->rx_thread_active)
+ iscsit_take_action_for_connection_exit(conn);
out:
return 0;
}
diff --git a/drivers/target/iscsi/iscsi_target_login.c
b/drivers/target/iscsi/iscsi_target_login.c
index 3d0fe4f..76dedb6 100644
--- a/drivers/target/iscsi/iscsi_target_login.c
+++ b/drivers/target/iscsi/iscsi_target_login.c
@@ -679,6 +679,7 @@ static int iscsit_start_kthreads(struct iscsi_conn *conn)
return 0;
out_tx:
+ send_sig(SIGINT, conn->tx_thread, 1);
kthread_stop(conn->tx_thread);
conn->tx_thread_active = false;
out_bitmap:
@@ -689,6 +690,23 @@ out_bitmap:
return ret;
}
+static void iscsit_kthread_err(struct iscsi_session *sess,
+ struct iscsi_conn *conn, bool new_sess)
+{
+ spin_lock_bh(&sess->conn_lock);
+ list_del(&conn->conn_list);
+ if (atomic_dec_and_test(&sess->nconn))
+ sess->session_state = TARG_SESS_STATE_FAILED;
+ spin_unlock_bh(&sess->conn_lock);
+
+ if (!new_sess)
+ return;
+
+ transport_deregister_session_configfs(sess->se_sess);
+ transport_deregister_session(sess->se_sess);
+ sess->se_sess = NULL;
+}
+
int iscsi_post_login_handler(
struct iscsi_np *np,
struct iscsi_conn *conn,
@@ -740,8 +758,10 @@ int iscsi_post_login_handler(
spin_unlock_bh(&sess->conn_lock);
rc = iscsit_start_kthreads(conn);
- if (rc)
- return rc;
+ if (rc) {
+ iscsit_kthread_err(sess, conn, false);
+ goto out_old_sess;
+ }
iscsi_post_login_start_timers(conn);
/*
@@ -751,7 +771,7 @@ int iscsi_post_login_handler(
iscsit_thread_get_cpumask(conn);
conn->conn_rx_reset_cpumask = 1;
conn->conn_tx_reset_cpumask = 1;
-
+out_old_sess:
iscsit_dec_conn_usage_count(conn);
if (stop_timer) {
spin_lock_bh(&se_tpg->session_lock);
@@ -759,7 +779,7 @@ int iscsi_post_login_handler(
spin_unlock_bh(&se_tpg->session_lock);
}
iscsit_dec_session_usage_count(sess);
- return 0;
+ return rc;
}
iscsi_set_session_parameters(sess->sess_ops, conn->param_list, 1);
@@ -801,8 +821,17 @@ int iscsi_post_login_handler(
spin_unlock_bh(&se_tpg->session_lock);
rc = iscsit_start_kthreads(conn);
- if (rc)
+ if (rc) {
+ spin_lock_bh(&se_tpg->session_lock);
+ if (tpg->tpg_tiqn)
+ tpg->tpg_tiqn->tiqn_nsessions--;
+ tpg->nsessions--;
+ spin_unlock_bh(&se_tpg->session_lock);
+
+ iscsit_kthread_err(sess, conn, true);
+ iscsit_dec_conn_usage_count(conn);
return rc;
+ }
iscsi_post_login_start_timers(conn);
/*
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html