From 3e5844b778d0104fcea44f63a3df0ff9ff0ca494 Mon Sep 17 00:00:00 2001 From: Brian M Date: Thu, 26 Feb 2026 17:24:27 -0800 Subject: [PATCH] qla2xxx: fix session free stall by using scst_unregister_session wait=0 Calling scst_unregister_session(wait=1) from qlt_free_session_done blocks the qla2xxx_wq worker until session teardown completes, but teardown requires the TM thread to process SCST_UNREG_SESS_TM while the TM thread is blocked on scst_mutex held by concurrent session teardown in the global management thread. Under load this stall exceeds the hung-task timeout. Switch to wait=0 and wait on fcport->unreg_done instead, matching the pattern in iscsi-scst. --- qla2x00t-32gbit/qla2x00-target/scst_qla2xxx.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/qla2x00t-32gbit/qla2x00-target/scst_qla2xxx.c b/qla2x00t-32gbit/qla2x00-target/scst_qla2xxx.c index 3fca87ff0..1657ba5a0 100644 --- a/qla2x00t-32gbit/qla2x00-target/scst_qla2xxx.c +++ b/qla2x00t-32gbit/qla2x00-target/scst_qla2xxx.c @@ -740,7 +740,23 @@ static void sqa_qla2xxx_free_session(struct fc_port *fcport) DECLARE_COMPLETION_ONSTACK(c); fcport->unreg_done = &c; - scst_unregister_session(scst_sess, 1, sqa_free_session_done); + /* + * Use wait=0 (async) to avoid a severe stall under concurrent + * session teardown. With wait=1 the workqueue thread blocks + * inside scst_unregister_session() until + * scst_free_session_callback() fires. That callback cannot be + * scheduled until the TM thread processes SCST_UNREG_SESS_TM, + * but the TM thread is blocked on scst_mutex which the global + * management thread holds during concurrent session teardown + * (scst_sess_free_tgt_devs -> synchronize_rcu()). Under load + * this stall exceeds the hung-task timeout. With wait=0 the + * workqueue thread is released immediately; we wait only on + * fcport->unreg_done, signalled by sqa_free_session_done() at + * a point where scst_mutex is not held. + * See also: iscsi-scst session_free() which carries a similar + * warning. + */ + scst_unregister_session(scst_sess, 0, sqa_free_session_done); wait_for_completion(&c); }