Skip to content

Commit 38fe73c

Browse files
Nicholas Bellingermartinkpetersen
authored andcommitted
scsi: target: Fix target_wait_for_sess_cmds breakage with active signals
With the addition of commit 00d909a ("scsi: target: Make the session shutdown code also wait for commands that are being aborted") in v4.19-rc, it incorrectly assumes no signals will be pending for task_struct executing the normal session shutdown and I/O quiesce code-path. For example, iscsi-target and iser-target issue SIGINT to all kthreads as part of session shutdown. This has been the behaviour since day one. As-is when signals are pending with se_cmds active in se_sess->sess_cmd_list, wait_event_interruptible_lock_irq_timeout() returns a negative number and immediately kills the machine because of the do while (ret <= 0) loop that was added in commit 00d909a to spin while backend I/O is taking any amount of extended time (say 30 seconds) to complete. Here's what it looks like in action with debug plus delayed backend I/O completion: [ 4951.909951] se_sess: 000000003e7e08fa before target_wait_for_sess_cmds [ 4951.914600] target_wait_for_sess_cmds: signal_pending: 1 [ 4951.918015] wait_event_interruptible_lock_irq_timeout ret: -512 signal_pending: 1 loop count: 0 [ 4951.921639] wait_event_interruptible_lock_irq_timeout ret: -512 signal_pending: 1 loop count: 1 [ 4951.921944] wait_event_interruptible_lock_irq_timeout ret: -512 signal_pending: 1 loop count: 2 [ 4951.921944] wait_event_interruptible_lock_irq_timeout ret: -512 signal_pending: 1 loop count: 3 [ 4951.921944] wait_event_interruptible_lock_irq_timeout ret: -512 signal_pending: 1 loop count: 4 [ 4951.921944] wait_event_interruptible_lock_irq_timeout ret: -512 signal_pending: 1 loop count: 5 [ 4951.921944] wait_event_interruptible_lock_irq_timeout ret: -512 signal_pending: 1 loop count: 6 [ 4951.921944] wait_event_interruptible_lock_irq_timeout ret: -512 signal_pending: 1 loop count: 7 [ 4951.921944] wait_event_interruptible_lock_irq_timeout ret: -512 signal_pending: 1 loop count: 8 [ 4951.921944] wait_event_interruptible_lock_irq_timeout ret: -512 signal_pending: 1 loop count: 9 ... followed by the usual RCU CPU stalls and deadlock. There was never a case pre commit 00d909a where wait_for_complete(&se_cmd->cmd_wait_comp) was able to be interrupted, so to address this for v4.19+ moving forward go ahead and use wait_event_lock_irq_timeout() instead so new code works with all fabric drivers. Also for commit 00d909a, fix a minor regression in target_release_cmd_kref() to only wake_up the new se_sess->cmd_list_wq only when shutdown has actually been triggered via se_sess->sess_tearing_down. Fixes: 00d909a ("scsi: target: Make the session shutdown code also wait for commands that are being aborted") Cc: <stable@vger.kernel.org> # v4.19+ Cc: Bart Van Assche <bvanassche@acm.org> Cc: Mike Christie <mchristi@redhat.com> Cc: Hannes Reinecke <hare@suse.com> Cc: Christoph Hellwig <hch@lst.de> Cc: Sagi Grimberg <sagi@grimberg.me> Cc: Bryant G. Ly <bryantly@linux.vnet.ibm.com> Tested-by: Nicholas Bellinger <nab@linux-iscsi.org> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org> Reviewed-by: Bryant G. Ly <bly@catalogicsoftware.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent 25ab0bc commit 38fe73c

File tree

1 file changed

+2
-2
lines changed

1 file changed

+2
-2
lines changed

drivers/target/target_core_transport.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2754,7 +2754,7 @@ static void target_release_cmd_kref(struct kref *kref)
27542754
if (se_sess) {
27552755
spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
27562756
list_del_init(&se_cmd->se_cmd_list);
2757-
if (list_empty(&se_sess->sess_cmd_list))
2757+
if (se_sess->sess_tearing_down && list_empty(&se_sess->sess_cmd_list))
27582758
wake_up(&se_sess->cmd_list_wq);
27592759
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
27602760
}
@@ -2907,7 +2907,7 @@ void target_wait_for_sess_cmds(struct se_session *se_sess)
29072907

29082908
spin_lock_irq(&se_sess->sess_cmd_lock);
29092909
do {
2910-
ret = wait_event_interruptible_lock_irq_timeout(
2910+
ret = wait_event_lock_irq_timeout(
29112911
se_sess->cmd_list_wq,
29122912
list_empty(&se_sess->sess_cmd_list),
29132913
se_sess->sess_cmd_lock, 180 * HZ);

0 commit comments

Comments
 (0)