On Wed, 2017-05-24 at 07:51 +0200, Hannes Reinecke wrote: > On 05/24/2017 02:33 AM, Bart Van Assche wrote: > > 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@xxxxxxxxxxx> > > Cc: Christoph Hellwig <hch@xxxxxx> > > Cc: Hannes Reinecke <hare@xxxxxxxx> > > Cc: Johannes Thumshirn <jthumshirn@xxxxxxx> > > --- > > drivers/scsi/scsi_error.c | 8 +++++++- > > drivers/scsi/scsi_lib.c | 27 +++++++++++++++++++++------ > > drivers/scsi/scsi_scan.c | 16 +++++++++------- > > drivers/scsi/scsi_sysfs.c | 24 +++++++++++++++++++----- > > drivers/scsi/scsi_transport_srp.c | 7 ++++--- > > drivers/scsi/sd.c | 7 +++++-- > > include/scsi/scsi_device.h | 1 + > > 7 files changed, 66 insertions(+), 24 deletions(-) > > > > [ .. ] > > diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c > > index 3c5d89852e9f..f617021c94f7 100644 > > --- a/drivers/scsi/scsi_transport_srp.c > > +++ b/drivers/scsi/scsi_transport_srp.c > > @@ -554,11 +554,12 @@ int srp_reconnect_rport(struct srp_rport *rport) > > * invoking scsi_target_unblock() won't change the state of > > * these devices into running so do that explicitly. > > */ > > - spin_lock_irq(shost->host_lock); > > - __shost_for_each_device(sdev, shost) > > + shost_for_each_device(sdev, shost) { > > + mutex_lock(&sdev->state_mutex); > > if (sdev->sdev_state == SDEV_OFFLINE) > > sdev->sdev_state = SDEV_RUNNING; > > - spin_unlock_irq(shost->host_lock); > > + mutex_unlock(&sdev->state_mutex); > > + } > > } else if (rport->state == SRP_RPORT_RUNNING) { > > /* > > * srp_reconnect_rport() has been invoked with fast_io_fail > > Why do you drop the host lock here? I thought that the host lock is > needed to protect shost_for_each_device()? Hello Hannes, The only purpose of holding the host lock was to protect the SCSI device list iteration by __shost_for_each_device(). shost_for_each_device() obtains that lock itself. From <scsi/scsi_device.h>: #define shost_for_each_device(sdev, shost) \ for ((sdev) = __scsi_iterate_devices((shost), NULL); \ (sdev); \ (sdev) = __scsi_iterate_devices((shost), (sdev))) >From drivers/scsi/scsi.c: struct scsi_device *__scsi_iterate_devices(struct Scsi_Host *shost, struct scsi_device *prev) { struct list_head *list = (prev ? &prev->siblings : &shost->__devices); struct scsi_device *next = NULL; unsigned long flags; spin_lock_irqsave(shost->host_lock, flags); while (list->next != &shost->__devices) { next = list_entry(list->next, struct scsi_device, siblings); /* skip devices that we can't get a reference to */ if (!scsi_device_get(next)) break; next = NULL; list = list->next; } spin_unlock_irqrestore(shost->host_lock, flags); if (prev) scsi_device_put(prev); return next; } Bart.