@@ -4280,7 +4280,7 @@ int iscsit_close_connection(
if (!atomic_read(&sess->session_stop_active)) {
atomic_set(&sess->session_stop_active, 1);
spin_unlock_bh(&sess->conn_lock);
- iscsit_stop_session(sess, 0, 0);
+ iscsit_stop_session(sess, 0, 0, 0);
return 0;
}
spin_unlock_bh(&sess->conn_lock);
@@ -4371,7 +4371,7 @@ int iscsit_close_session(struct iscsi_session *sess)
*/
if (!in_interrupt()) {
if (iscsit_check_session_usage_count(sess) == 1)
- iscsit_stop_session(sess, 1, 1);
+ iscsit_stop_session(sess, 1, 1, 0);
} else {
if (iscsit_check_session_usage_count(sess) == 2) {
atomic_set(&sess->session_logout, 0);
@@ -4432,7 +4432,7 @@ static void iscsit_logout_post_handler_closesession(
complete(&conn->conn_logout_comp);
iscsit_dec_conn_usage_count(conn);
- iscsit_stop_session(sess, sleep, sleep);
+ iscsit_stop_session(sess, sleep, sleep, 0);
iscsit_dec_session_usage_count(sess);
iscsit_close_session(sess);
}
@@ -4609,10 +4609,11 @@ int iscsit_free_session(struct iscsi_session *sess)
return 0;
}
-void iscsit_stop_session(
+int iscsit_stop_session(
struct iscsi_session *sess,
int session_sleep,
- int connection_sleep)
+ int connection_sleep,
+ int interruptible)
{
u16 conn_count = atomic_read(&sess->nconn);
struct iscsi_conn *conn, *conn_tmp = NULL;
@@ -4652,9 +4653,14 @@ void iscsit_stop_session(
if (session_sleep && atomic_read(&sess->nconn)) {
spin_unlock_bh(&sess->conn_lock);
- wait_for_completion(&sess->session_wait_comp);
+ if (interruptible)
+ return wait_for_completion_interruptible(&sess->session_wait_comp);
+ else
+ wait_for_completion(&sess->session_wait_comp);
+
} else
spin_unlock_bh(&sess->conn_lock);
+ return 0;
}
int iscsit_release_sessions_for_tpg(struct iscsi_portal_group *tpg, int force)
@@ -43,7 +43,7 @@ extern int iscsit_reset_np_thread(struct iscsi_np *, struct iscsi_tpg_np *,
extern int iscsit_close_session(struct iscsi_session *);
extern void iscsit_fail_session(struct iscsi_session *);
extern int iscsit_free_session(struct iscsi_session *);
-extern void iscsit_stop_session(struct iscsi_session *, int, int);
+extern int iscsit_stop_session(struct iscsi_session *, int, int, int);
extern int iscsit_release_sessions_for_tpg(struct iscsi_portal_group *, int);
extern struct iscsit_global *iscsit_global;
@@ -1536,7 +1536,7 @@ static void lio_tpg_close_session(struct se_session *se_sess)
iscsit_stop_time2retain_timer(sess);
spin_unlock_bh(&se_tpg->session_lock);
- iscsit_stop_session(sess, 1, 1);
+ iscsit_stop_session(sess, 1, 1, 0);
iscsit_close_session(sess);
}
@@ -176,6 +176,7 @@ int iscsi_check_for_session_reinstatement(struct iscsi_conn *conn)
struct iscsi_session *sess = NULL, *sess_p = NULL;
struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
struct se_session *se_sess, *se_sess_tmp;
+ int ret;
initiatorname_param = iscsi_find_param_from_key(
INITIATORNAME, conn->param_list);
@@ -235,8 +236,10 @@ int iscsi_check_for_session_reinstatement(struct iscsi_conn *conn)
}
spin_unlock_bh(&sess->conn_lock);
- iscsit_stop_session(sess, 1, 1);
+ ret = iscsit_stop_session(sess, 1, 1, 1);
iscsit_dec_session_usage_count(sess);
+ if (ret)
+ return -1;
iscsit_close_session(sess);
return 0;
To handle initiators dropping tcp connections while the login process is waiting on a connection getting cleaned up, we need to make that login path interruptible, so we do not have to wait for long periods of time and let relogins pile up. This patch modifies iscsit_stop_connection, so it can be woken up and return failure. We want to use it in the login path. I am not sure if it is needed in other paths. I was thinking it might be useful in the configfs path, but I think that will take more work. Signed-off-by: Mike Christie <mchristi@redhat.com> --- drivers/target/iscsi/iscsi_target.c | 18 ++++++++++++------ drivers/target/iscsi/iscsi_target.h | 2 +- drivers/target/iscsi/iscsi_target_configfs.c | 2 +- drivers/target/iscsi/iscsi_target_login.c | 5 ++++- 4 files changed, 18 insertions(+), 9 deletions(-)