summaryrefslogtreecommitdiff
path: root/Documentation
diff options
context:
space:
mode:
authorWei Fang <fangwei1@huawei.com>2016-06-07 14:53:56 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-07-27 09:55:51 -0700
commit44df69e75e1c6b8e4f3e55d4b7977726392d511e (patch)
tree44e13f107e3db58df37ac3d94c93cc78620be48a /Documentation
parent9381f9edbff5357cd5df6f4544c66620142d1169 (diff)
downloadlwn-44df69e75e1c6b8e4f3e55d4b7977726392d511e.tar.gz
lwn-44df69e75e1c6b8e4f3e55d4b7977726392d511e.zip
scsi: fix race between simultaneous decrements of ->host_failed
commit 72d8c36ec364c82bf1bf0c64dfa1041cfaf139f7 upstream. sas_ata_strategy_handler() adds the works of the ata error handler to system_unbound_wq. This workqueue asynchronously runs work items, so the ata error handler will be performed concurrently on different CPUs. In this case, ->host_failed will be decreased simultaneously in scsi_eh_finish_cmd() on different CPUs, and become abnormal. It will lead to permanently inequality between ->host_failed and ->host_busy, and scsi error handler thread won't start running. IO errors after that won't be handled. Since all scmds must have been handled in the strategy handler, just remove the decrement in scsi_eh_finish_cmd() and zero ->host_busy after the strategy handler to fix this race. Fixes: 50824d6c5657 ("[SCSI] libsas: async ata-eh") Signed-off-by: Wei Fang <fangwei1@huawei.com> Reviewed-by: James Bottomley <jejb@linux.vnet.ibm.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'Documentation')
-rw-r--r--Documentation/scsi/scsi_eh.txt8
1 files changed, 6 insertions, 2 deletions
diff --git a/Documentation/scsi/scsi_eh.txt b/Documentation/scsi/scsi_eh.txt
index a0c85110a07e..689ab9b9953a 100644
--- a/Documentation/scsi/scsi_eh.txt
+++ b/Documentation/scsi/scsi_eh.txt
@@ -263,19 +263,23 @@ scmd->allowed.
3. scmd recovered
ACTION: scsi_eh_finish_cmd() is invoked to EH-finish scmd
- - shost->host_failed--
- clear scmd->eh_eflags
- scsi_setup_cmd_retry()
- move from local eh_work_q to local eh_done_q
LOCKING: none
+ CONCURRENCY: at most one thread per separate eh_work_q to
+ keep queue manipulation lockless
4. EH completes
ACTION: scsi_eh_flush_done_q() retries scmds or notifies upper
- layer of failure.
+ layer of failure. May be called concurrently but must have
+ a no more than one thread per separate eh_work_q to
+ manipulate the queue locklessly
- scmd is removed from eh_done_q and scmd->eh_entry is cleared
- if retry is necessary, scmd is requeued using
scsi_queue_insert()
- otherwise, scsi_finish_command() is invoked for scmd
+ - zero shost->host_failed
LOCKING: queue or finish function performs appropriate locking