diff options
author | Bart Van Assche <bart.vanassche@sandisk.com> | 2017-06-02 14:21:55 -0700 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2017-06-12 20:55:59 -0400 |
commit | 0db6ca8a5e1ea585795db3643ec7d50fc8cb1aff (patch) | |
tree | 52ae689dcddbc9155a840617c405de2b377de618 /drivers/scsi/scsi_error.c | |
parent | 43f7571be077ee4673466cbcba115427d68440e1 (diff) | |
download | linux-0db6ca8a5e1ea585795db3643ec7d50fc8cb1aff.tar.gz linux-0db6ca8a5e1ea585795db3643ec7d50fc8cb1aff.tar.bz2 linux-0db6ca8a5e1ea585795db3643ec7d50fc8cb1aff.zip |
scsi: Protect SCSI device state changes with a mutex
Serializing SCSI device state changes avoids that two state changes can
occur concurrently, e.g. the state changes in scsi_target_block() and
__scsi_remove_device(). This serialization is essential to make patch
"Make __scsi_remove_device go straight from BLOCKED to DEL" work
reliably.
Enable this mechanism for all scsi_target_*block() callers but not for
the scsi_internal_device_unblock() calls from the mpt3sas driver because
that driver can call scsi_internal_device_unblock() from atomic context.
Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Hannes Reinecke <hare@suse.com>
Cc: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/scsi_error.c')
-rw-r--r-- | drivers/scsi/scsi_error.c | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index ecc07dab893d..ac3196420435 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -1628,11 +1628,17 @@ static void scsi_eh_offline_sdevs(struct list_head *work_q, struct list_head *done_q) { struct scsi_cmnd *scmd, *next; + struct scsi_device *sdev; list_for_each_entry_safe(scmd, next, work_q, eh_entry) { sdev_printk(KERN_INFO, scmd->device, "Device offlined - " "not ready after error recovery\n"); - scsi_device_set_state(scmd->device, SDEV_OFFLINE); + sdev = scmd->device; + + mutex_lock(&sdev->state_mutex); + scsi_device_set_state(sdev, SDEV_OFFLINE); + mutex_unlock(&sdev->state_mutex); + scsi_eh_finish_cmd(scmd, done_q); } return; |