diff mbox series

[1/3] target: iscsi: schedule close_session at timeout

Message ID 20221003202723.22714-2-d.bogdanov@yadro.com (mailing list archive)
State New, archived
Headers show
Series fixes related to iSCSI Time2Retain timer | expand

Commit Message

Dmitry Bogdanov Oct. 3, 2022, 8:27 p.m. UTC
iscsit_close_session in depth has sleepable dependencies, like:

iscsit_close_session()
  iscsit_free_connection_recovery_entries()
    iscsit_free_cmd()
      transport_generic_free_cmd()
        target_wait_free_cmd()
          wait_for_completion_timeout()

But iscsit_handle_time2retain_timeout calls it in timer-context that
leads to WARN on might_sleep();

Schedule iscsit_close_session in work queue.

Signed-off-by: Dmitry Bogdanov <d.bogdanov@yadro.com>
---
 drivers/target/iscsi/iscsi_target.c       | 8 ++++++++
 drivers/target/iscsi/iscsi_target.h       | 1 +
 drivers/target/iscsi/iscsi_target_erl0.c  | 4 +++-
 drivers/target/iscsi/iscsi_target_login.c | 1 +
 include/target/iscsi/iscsi_target_core.h  | 1 +
 5 files changed, 14 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index baf4da7bb3b4..36166eabf595 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -4495,6 +4495,14 @@  int iscsit_close_connection(
 	}
 }
 
+void iscsit_session_close_worker(struct work_struct *workp)
+{
+	struct iscsit_session *sess = container_of(workp, struct iscsit_session,
+						   session_close_worker);
+
+	iscsit_close_session(sess, true);
+}
+
 /*
  * If the iSCSI Session for the iSCSI Initiator Node exists,
  * forcefully shutdown the iSCSI NEXUS.
diff --git a/drivers/target/iscsi/iscsi_target.h b/drivers/target/iscsi/iscsi_target.h
index 0c997a08adec..a529294a21ce 100644
--- a/drivers/target/iscsi/iscsi_target.h
+++ b/drivers/target/iscsi/iscsi_target.h
@@ -42,6 +42,7 @@  extern int iscsi_target_tx_thread(void *);
 extern int iscsi_target_rx_thread(void *);
 extern int iscsit_close_connection(struct iscsit_conn *);
 extern int iscsit_close_session(struct iscsit_session *, bool can_sleep);
+extern void iscsit_session_close_worker(struct work_struct *workp);
 extern void iscsit_fail_session(struct iscsit_session *);
 extern void iscsit_stop_session(struct iscsit_session *, int, int);
 extern int iscsit_release_sessions_for_tpg(struct iscsi_portal_group *, int);
diff --git a/drivers/target/iscsi/iscsi_target_erl0.c b/drivers/target/iscsi/iscsi_target_erl0.c
index 07e9cf431edd..63890a72555b 100644
--- a/drivers/target/iscsi/iscsi_target_erl0.c
+++ b/drivers/target/iscsi/iscsi_target_erl0.c
@@ -764,8 +764,10 @@  void iscsit_handle_time2retain_timeout(struct timer_list *t)
 			" iSCSI session.\n", sess->sid);
 
 	iscsit_fill_cxn_timeout_err_stats(sess);
+	atomic_set(&sess->session_logout, 1);
 	spin_unlock_bh(&se_tpg->session_lock);
-	iscsit_close_session(sess, false);
+
+	schedule_work(&sess->session_close_worker);
 }
 
 void iscsit_start_time2retain_handler(struct iscsit_session *sess)
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c
index 27e448c2d066..cc1895c56dd9 100644
--- a/drivers/target/iscsi/iscsi_target_login.c
+++ b/drivers/target/iscsi/iscsi_target_login.c
@@ -288,6 +288,7 @@  static int iscsi_login_zero_tsih_s1(
 	spin_lock_init(&sess->cr_i_lock);
 	spin_lock_init(&sess->session_usage_lock);
 	spin_lock_init(&sess->ttt_lock);
+	INIT_WORK(&sess->session_close_worker, iscsit_session_close_worker);
 
 	timer_setup(&sess->time2retain_timer,
 		    iscsit_handle_time2retain_timeout, 0);
diff --git a/include/target/iscsi/iscsi_target_core.h b/include/target/iscsi/iscsi_target_core.h
index 94d06ddfd80a..92436b3dd17b 100644
--- a/include/target/iscsi/iscsi_target_core.h
+++ b/include/target/iscsi/iscsi_target_core.h
@@ -684,6 +684,7 @@  struct iscsit_session {
 	struct completion	session_wait_comp;
 	struct completion	session_waiting_on_uc_comp;
 	struct timer_list	time2retain_timer;
+	struct work_struct	session_close_worker;
 	struct iscsi_sess_ops	*sess_ops;
 	struct se_session	*se_sess;
 	struct iscsi_portal_group *tpg;