Commit f049cf1a authored by Bart Van Assche's avatar Bart Van Assche Committed by Martin K. Petersen

scsi: sd: Rely on the driver core for asynchronous probing

As explained during the 2018 LSF/MM session about increasing SCSI disk
probing concurrency, the problems with the current probing approach are as
follows:

 - The driver core is unaware of asynchronous SCSI LUN probing.
   wait_for_device_probe() waits for all asynchronous probes except
   asynchronous SCSI disk probes.

 - There is unnecessary serialization between sd_probe() and sd_remove().
   This can lead to a deadlock.

Hence this patch that modifies the sd driver such that it uses the driver
core framework for asynchronous probing. The async domain and
get_device()/put_device() pairs that became superfluous due to this change
are removed.

This patch does not affect the time needed for loading the scsi_debug
kernel module with parameters delay=0 and max_luns=256.

This patch depends on commit ef0ff683 ("driver core: Probe devices
asynchronously instead of the driver") that went upstream in kernel version
v5.1-rc1.

Cc: Lee Duncan <lduncan@suse.com>
Cc: Hannes Reinecke <hare@suse.com>
Cc: Luis Chamberlain <mcgrof@kernel.org>
Cc: Johannes Thumshirn <jthumshirn@suse.de>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Pavel Machek <pavel@ucw.cz>
Cc: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: default avatarBart Van Assche <bvanassche@acm.org>
Reviewed-by: default avatarHannes Reinecke <hare@suse.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 50a1ea5b
...@@ -86,15 +86,10 @@ unsigned int scsi_logging_level; ...@@ -86,15 +86,10 @@ unsigned int scsi_logging_level;
EXPORT_SYMBOL(scsi_logging_level); EXPORT_SYMBOL(scsi_logging_level);
#endif #endif
/* sd, scsi core and power management need to coordinate flushing async actions */
ASYNC_DOMAIN(scsi_sd_probe_domain);
EXPORT_SYMBOL(scsi_sd_probe_domain);
/* /*
* Separate domain (from scsi_sd_probe_domain) to maximize the benefit of * Domain for asynchronous system resume operations. It is marked 'exclusive'
* asynchronous system resume operations. It is marked 'exclusive' to avoid * to avoid being included in the async_synchronize_full() that is invoked by
* being included in the async_synchronize_full() that is invoked by * dpm_resume().
* dpm_resume()
*/ */
ASYNC_DOMAIN_EXCLUSIVE(scsi_sd_pm_domain); ASYNC_DOMAIN_EXCLUSIVE(scsi_sd_pm_domain);
EXPORT_SYMBOL(scsi_sd_pm_domain); EXPORT_SYMBOL(scsi_sd_pm_domain);
...@@ -821,7 +816,6 @@ static void __exit exit_scsi(void) ...@@ -821,7 +816,6 @@ static void __exit exit_scsi(void)
scsi_exit_devinfo(); scsi_exit_devinfo();
scsi_exit_procfs(); scsi_exit_procfs();
scsi_exit_queue(); scsi_exit_queue();
async_unregister_domain(&scsi_sd_probe_domain);
} }
subsys_initcall(init_scsi); subsys_initcall(init_scsi);
......
...@@ -176,11 +176,7 @@ static int scsi_bus_resume_common(struct device *dev, ...@@ -176,11 +176,7 @@ static int scsi_bus_resume_common(struct device *dev,
static int scsi_bus_prepare(struct device *dev) static int scsi_bus_prepare(struct device *dev)
{ {
if (scsi_is_sdev_device(dev)) { if (scsi_is_host_device(dev)) {
/* sd probing uses async_schedule. Wait until it finishes. */
async_synchronize_full_domain(&scsi_sd_probe_domain);
} else if (scsi_is_host_device(dev)) {
/* Wait until async scanning is finished */ /* Wait until async scanning is finished */
scsi_complete_async_scans(); scsi_complete_async_scans();
} }
......
...@@ -175,7 +175,6 @@ static inline void scsi_autopm_put_host(struct Scsi_Host *h) {} ...@@ -175,7 +175,6 @@ static inline void scsi_autopm_put_host(struct Scsi_Host *h) {}
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
extern struct async_domain scsi_sd_pm_domain; extern struct async_domain scsi_sd_pm_domain;
extern struct async_domain scsi_sd_probe_domain;
/* scsi_dh.c */ /* scsi_dh.c */
#ifdef CONFIG_SCSI_DH #ifdef CONFIG_SCSI_DH
......
...@@ -568,6 +568,7 @@ static struct scsi_driver sd_template = { ...@@ -568,6 +568,7 @@ static struct scsi_driver sd_template = {
.name = "sd", .name = "sd",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.probe = sd_probe, .probe = sd_probe,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
.remove = sd_remove, .remove = sd_remove,
.shutdown = sd_shutdown, .shutdown = sd_shutdown,
.pm = &sd_pm_ops, .pm = &sd_pm_ops,
...@@ -3253,12 +3254,8 @@ static int sd_format_disk_name(char *prefix, int index, char *buf, int buflen) ...@@ -3253,12 +3254,8 @@ static int sd_format_disk_name(char *prefix, int index, char *buf, int buflen)
return 0; return 0;
} }
/* static void sd_probe_part2(struct scsi_disk *sdkp)
* The asynchronous part of sd_probe
*/
static void sd_probe_async(void *data, async_cookie_t cookie)
{ {
struct scsi_disk *sdkp = data;
struct scsi_device *sdp; struct scsi_device *sdp;
struct gendisk *gd; struct gendisk *gd;
u32 index; u32 index;
...@@ -3313,7 +3310,6 @@ static void sd_probe_async(void *data, async_cookie_t cookie) ...@@ -3313,7 +3310,6 @@ static void sd_probe_async(void *data, async_cookie_t cookie)
sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n", sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n",
sdp->removable ? "removable " : ""); sdp->removable ? "removable " : "");
scsi_autopm_put_device(sdp); scsi_autopm_put_device(sdp);
put_device(&sdkp->dev);
} }
/** /**
...@@ -3405,8 +3401,7 @@ static int sd_probe(struct device *dev) ...@@ -3405,8 +3401,7 @@ static int sd_probe(struct device *dev)
get_device(dev); get_device(dev);
dev_set_drvdata(dev, sdkp); dev_set_drvdata(dev, sdkp);
get_device(&sdkp->dev); /* prevent release before async_schedule */ sd_probe_part2(sdkp);
async_schedule_domain(sd_probe_async, sdkp, &scsi_sd_probe_domain);
return 0; return 0;
...@@ -3442,7 +3437,6 @@ static int sd_remove(struct device *dev) ...@@ -3442,7 +3437,6 @@ static int sd_remove(struct device *dev)
scsi_autopm_get_device(sdkp->device); scsi_autopm_get_device(sdkp->device);
async_synchronize_full_domain(&scsi_sd_pm_domain); async_synchronize_full_domain(&scsi_sd_pm_domain);
async_synchronize_full_domain(&scsi_sd_probe_domain);
device_del(&sdkp->dev); device_del(&sdkp->dev);
del_gendisk(sdkp->disk); del_gendisk(sdkp->disk);
sd_shutdown(dev); sd_shutdown(dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment