summaryrefslogtreecommitdiffstats
path: root/include/scsi
diff options
context:
space:
mode:
authorBart Van Assche <bart.vanassche@wdc.com>2017-12-04 19:06:23 +0100
committerMartin K. Petersen <martin.petersen@oracle.com>2017-12-08 03:06:31 +0100
commit3bd6f43f5cb3714f70c591514f344389df593501 (patch)
tree0d287d0b562c064adf4ce1b45c1ea0cb2b97b401 /include/scsi
parentrcu: Export init_rcu_head() and destroy_rcu_head() to GPL modules (diff)
downloadlinux-3bd6f43f5cb3714f70c591514f344389df593501.tar.xz
linux-3bd6f43f5cb3714f70c591514f344389df593501.zip
scsi: core: Ensure that the SCSI error handler gets woken up
If scsi_eh_scmd_add() is called concurrently with scsi_host_queue_ready() while shost->host_blocked > 0 then it can happen that neither function wakes up the SCSI error handler. Fix this by making every function that decreases the host_busy counter wake up the error handler if necessary and by protecting the host_failed checks with the SCSI host lock. Reported-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com> References: https://marc.info/?l=linux-kernel&m=150461610630736 Fixes: commit 746650160866 ("scsi: convert host_busy to atomic_t") Signed-off-by: Bart Van Assche <bart.vanassche@wdc.com> Reviewed-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com> Tested-by: Stuart Hayes <stuart.w.hayes@gmail.com> Cc: Konstantin Khorenko <khorenko@virtuozzo.com> Cc: Stuart Hayes <stuart.w.hayes@gmail.com> Cc: Pavel Tikhomirov <ptikhomirov@virtuozzo.com> Cc: Christoph Hellwig <hch@lst.de> Cc: Hannes Reinecke <hare@suse.com> Cc: Johannes Thumshirn <jthumshirn@suse.de> Cc: <stable@vger.kernel.org> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'include/scsi')
-rw-r--r--include/scsi/scsi_host.h2
1 files changed, 2 insertions, 0 deletions
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index a8b7bf879ced..1a1df0d21ee3 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -571,6 +571,8 @@ struct Scsi_Host {
struct blk_mq_tag_set tag_set;
};
+ struct rcu_head rcu;
+
atomic_t host_busy; /* commands actually active on low-level */
atomic_t host_blocked;