* [PATCH v4] scsi/sd: release scan_mutex during sync_cache and start_stop @ 2017-02-09 1:01 Song Liu 2017-02-09 8:51 ` Christoph Hellwig 0 siblings, 1 reply; 3+ messages in thread From: Song Liu @ 2017-02-09 1:01 UTC (permalink / raw) To: linux-scsi; +Cc: bart.vanassche, hch, hch, Song Liu When a device is deleted through sysfs handle "delete", the code locks shost->scan_mutex. If multiple devices are deleted at the same time, these deletes will be handled in series. On the other hand, sd_shutdown() sometimes issues long latency commands: sync cache and start_stop. It is not necessary for these commands to run in series. To reduce latency of parallel "delete" requests, this patch unlock shost->scan_mutex before calling sd_shutdown(), relock the mutex afterwards. Fixed bug from previous version. Reported-by: kernel test robot <fengguang.wu@intel.com> Signed-off-by: Song Liu <songliubraving@fb.com> Cc: Christoph Hellwig <hch@lst.de> Cc: Bart Van Assche <bart.vanassche@sandisk.com> --- drivers/scsi/sd.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 9e0783b..61ea308 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -3211,9 +3211,13 @@ static int sd_probe(struct device *dev) static int sd_remove(struct device *dev) { struct scsi_disk *sdkp; + struct scsi_device *sdev; + struct Scsi_Host *shost; dev_t devt; sdkp = dev_get_drvdata(dev); + sdev = sdkp->device; + shost = sdev->host; devt = disk_devt(sdkp->disk); scsi_autopm_get_device(sdkp->device); @@ -3221,7 +3225,9 @@ static int sd_remove(struct device *dev) async_synchronize_full_domain(&scsi_sd_probe_domain); device_del(&sdkp->dev); del_gendisk(sdkp->disk); + mutex_unlock(&shost->scan_mutex); sd_shutdown(dev); + mutex_lock(&shost->scan_mutex); sd_zbc_remove(sdkp); -- 2.9.3 ^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH v4] scsi/sd: release scan_mutex during sync_cache and start_stop 2017-02-09 1:01 [PATCH v4] scsi/sd: release scan_mutex during sync_cache and start_stop Song Liu @ 2017-02-09 8:51 ` Christoph Hellwig 2017-02-09 22:24 ` Song Liu 0 siblings, 1 reply; 3+ messages in thread From: Christoph Hellwig @ 2017-02-09 8:51 UTC (permalink / raw) To: Song Liu; +Cc: linux-scsi, bart.vanassche And what is the lock protecting if we can just release and reacquire it safely? Probably nothing, but someone needs to do the audit carefully. Once that is done we can just apply a patch like the one below and be done with it: --- >From 47572d7f0758cc0cbd979b1a2c3791f3b94c566e Mon Sep 17 00:00:00 2001 From: Christoph Hellwig <hch@lst.de> Date: Thu, 9 Feb 2017 09:49:04 +0100 Subject: scsi: remove scan_mutex All our lookup structures are properly locked these days, there shouldn't be any need to serialize the high-level scan process. Signed-off-by: Christoph Hellwig <hch@lst.de> --- drivers/scsi/scsi_scan.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 6f7128f49c30..c92be1ad486c 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -1490,7 +1490,6 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, return ERR_PTR(-ENOMEM); scsi_autopm_get_target(starget); - mutex_lock(&shost->scan_mutex); if (!shost->async_scan) scsi_complete_async_scans(); @@ -1498,7 +1497,6 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata); scsi_autopm_put_host(shost); } - mutex_unlock(&shost->scan_mutex); scsi_autopm_put_target(starget); /* * paired with scsi_alloc_target(). Target will be destroyed unless @@ -1629,7 +1627,6 @@ void scsi_scan_target(struct device *parent, unsigned int channel, strncmp(scsi_scan_type, "manual", 6) == 0) return; - mutex_lock(&shost->scan_mutex); if (!shost->async_scan) scsi_complete_async_scans(); @@ -1637,7 +1634,6 @@ void scsi_scan_target(struct device *parent, unsigned int channel, __scsi_scan_target(parent, channel, id, lun, rescan); scsi_autopm_put_host(shost); } - mutex_unlock(&shost->scan_mutex); } EXPORT_SYMBOL(scsi_scan_target); @@ -1686,7 +1682,6 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, ((lun != SCAN_WILD_CARD) && (lun >= shost->max_lun))) return -EINVAL; - mutex_lock(&shost->scan_mutex); if (!shost->async_scan) scsi_complete_async_scans(); @@ -1700,7 +1695,6 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, scsi_scan_channel(shost, channel, id, lun, rescan); scsi_autopm_put_host(shost); } - mutex_unlock(&shost->scan_mutex); return 0; } @@ -1752,11 +1746,9 @@ static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost) goto err; init_completion(&data->prev_finished); - mutex_lock(&shost->scan_mutex); spin_lock_irqsave(shost->host_lock, flags); shost->async_scan = 1; spin_unlock_irqrestore(shost->host_lock, flags); - mutex_unlock(&shost->scan_mutex); spin_lock(&async_scan_lock); if (list_empty(&scanning_hosts)) @@ -1789,12 +1781,9 @@ static void scsi_finish_async_scan(struct async_scan_data *data) shost = data->shost; - mutex_lock(&shost->scan_mutex); - if (!shost->async_scan) { shost_printk(KERN_INFO, shost, "%s called twice\n", __func__); dump_stack(); - mutex_unlock(&shost->scan_mutex); return; } @@ -1806,8 +1795,6 @@ static void scsi_finish_async_scan(struct async_scan_data *data) shost->async_scan = 0; spin_unlock_irqrestore(shost->host_lock, flags); - mutex_unlock(&shost->scan_mutex); - spin_lock(&async_scan_lock); list_del(&data->list); if (!list_empty(&scanning_hosts)) { @@ -1915,7 +1902,6 @@ struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost) struct scsi_device *sdev = NULL; struct scsi_target *starget; - mutex_lock(&shost->scan_mutex); if (!scsi_host_scan_allowed(shost)) goto out; starget = scsi_alloc_target(&shost->shost_gendev, 0, shost->this_id); @@ -1929,7 +1915,6 @@ struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost) scsi_target_reap(starget); put_device(&starget->dev); out: - mutex_unlock(&shost->scan_mutex); return sdev; } EXPORT_SYMBOL(scsi_get_host_dev); -- 2.11.0 ^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH v4] scsi/sd: release scan_mutex during sync_cache and start_stop 2017-02-09 8:51 ` Christoph Hellwig @ 2017-02-09 22:24 ` Song Liu 0 siblings, 0 replies; 3+ messages in thread From: Song Liu @ 2017-02-09 22:24 UTC (permalink / raw) To: Christoph Hellwig; +Cc: linux-scsi@vger.kernel.org, bart.vanassche@sandisk.com Hi Christoph, IMHO, scan_mutex maybe still needed for other part of scsi_remove_device(). For example, device\x10_del() in sd_remove() and scsi_sysfs_add_devices() in scsi_finish_async_scan() should not run in parallel? On the other hand, other parts of sd_remove(), including sd_shutdown(), does not touch shared resource. So it is safe to run these sections without holding scan_mutex. Another (and maybe better) solution is to move mutex_lock/unlock() of scan_mutex to each _remove function. So we only hold the lock when accessing scsi_host related data. Thanks, Song > On Feb 9, 2017, at 12:51 AM, Christoph Hellwig <hch@lst.de> wrote: > > And what is the lock protecting if we can just release and reacquire it > safely? Probably nothing, but someone needs to do the audit carefully. > > Once that is done we can just apply a patch like the one below and > be done with it: > > --- > From 47572d7f0758cc0cbd979b1a2c3791f3b94c566e Mon Sep 17 00:00:00 2001 > From: Christoph Hellwig <hch@lst.de> > Date: Thu, 9 Feb 2017 09:49:04 +0100 > Subject: scsi: remove scan_mutex > > All our lookup structures are properly locked these days, there shouldn't > be any need to serialize the high-level scan process. > > Signed-off-by: Christoph Hellwig <hch@lst.de> > --- > drivers/scsi/scsi_scan.c | 15 --------------- > 1 file changed, 15 deletions(-) > > diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c > index 6f7128f49c30..c92be1ad486c 100644 > --- a/drivers/scsi/scsi_scan.c > +++ b/drivers/scsi/scsi_scan.c > @@ -1490,7 +1490,6 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, > return ERR_PTR(-ENOMEM); > scsi_autopm_get_target(starget); > > - mutex_lock(&shost->scan_mutex); > if (!shost->async_scan) > scsi_complete_async_scans(); > > @@ -1498,7 +1497,6 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, > scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata); > scsi_autopm_put_host(shost); > } > - mutex_unlock(&shost->scan_mutex); > scsi_autopm_put_target(starget); > /* > * paired with scsi_alloc_target(). Target will be destroyed unless > @@ -1629,7 +1627,6 @@ void scsi_scan_target(struct device *parent, unsigned int channel, > strncmp(scsi_scan_type, "manual", 6) == 0) > return; > > - mutex_lock(&shost->scan_mutex); > if (!shost->async_scan) > scsi_complete_async_scans(); > > @@ -1637,7 +1634,6 @@ void scsi_scan_target(struct device *parent, unsigned int channel, > __scsi_scan_target(parent, channel, id, lun, rescan); > scsi_autopm_put_host(shost); > } > - mutex_unlock(&shost->scan_mutex); > } > EXPORT_SYMBOL(scsi_scan_target); > > @@ -1686,7 +1682,6 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, > ((lun != SCAN_WILD_CARD) && (lun >= shost->max_lun))) > return -EINVAL; > > - mutex_lock(&shost->scan_mutex); > if (!shost->async_scan) > scsi_complete_async_scans(); > > @@ -1700,7 +1695,6 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, > scsi_scan_channel(shost, channel, id, lun, rescan); > scsi_autopm_put_host(shost); > } > - mutex_unlock(&shost->scan_mutex); > > return 0; > } > @@ -1752,11 +1746,9 @@ static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost) > goto err; > init_completion(&data->prev_finished); > > - mutex_lock(&shost->scan_mutex); > spin_lock_irqsave(shost->host_lock, flags); > shost->async_scan = 1; > spin_unlock_irqrestore(shost->host_lock, flags); > - mutex_unlock(&shost->scan_mutex); > > spin_lock(&async_scan_lock); > if (list_empty(&scanning_hosts)) > @@ -1789,12 +1781,9 @@ static void scsi_finish_async_scan(struct async_scan_data *data) > > shost = data->shost; > > - mutex_lock(&shost->scan_mutex); > - > if (!shost->async_scan) { > shost_printk(KERN_INFO, shost, "%s called twice\n", __func__); > dump_stack(); > - mutex_unlock(&shost->scan_mutex); > return; > } > > @@ -1806,8 +1795,6 @@ static void scsi_finish_async_scan(struct async_scan_data *data) > shost->async_scan = 0; > spin_unlock_irqrestore(shost->host_lock, flags); > > - mutex_unlock(&shost->scan_mutex); > - > spin_lock(&async_scan_lock); > list_del(&data->list); > if (!list_empty(&scanning_hosts)) { > @@ -1915,7 +1902,6 @@ struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost) > struct scsi_device *sdev = NULL; > struct scsi_target *starget; > > - mutex_lock(&shost->scan_mutex); > if (!scsi_host_scan_allowed(shost)) > goto out; > starget = scsi_alloc_target(&shost->shost_gendev, 0, shost->this_id); > @@ -1929,7 +1915,6 @@ struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost) > scsi_target_reap(starget); > put_device(&starget->dev); > out: > - mutex_unlock(&shost->scan_mutex); > return sdev; > } > EXPORT_SYMBOL(scsi_get_host_dev); > -- > 2.11.0 > ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2017-02-09 22:27 UTC | newest] Thread overview: 3+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2017-02-09 1:01 [PATCH v4] scsi/sd: release scan_mutex during sync_cache and start_stop Song Liu 2017-02-09 8:51 ` Christoph Hellwig 2017-02-09 22:24 ` Song Liu
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox