Commit 0761df9c authored by Hannes Reinecke's avatar Hannes Reinecke Committed by James Bottomley

[SCSI] sd: avoid deadlocks when running under multipath

When multipathed systems run into an all-paths-down scenario
all devices might be dropped, too. This causes 'del_gendisk'
to be called, which will unregister the kobj_map->probe()
function for all disk device numbers.
When the device comes back the default ->probe() function
is run which will call __request_module(), which will
deadlock.
As 'del_gendisk' typically does _not_ trigger a module unload
the default ->probe() function is pointless anyway.
This patch implements a dummy ->probe() function, which will
just return NULL if the disk is not registered.
This will avoid the deadlock. Plus it'll speed up device
scanning.
Signed-off-by: default avatarHannes Reinecke <hare@suse.de>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 70288b4c
...@@ -503,6 +503,16 @@ static struct scsi_driver sd_template = { ...@@ -503,6 +503,16 @@ static struct scsi_driver sd_template = {
.eh_action = sd_eh_action, .eh_action = sd_eh_action,
}; };
/*
* Dummy kobj_map->probe function.
* The default ->probe function will call modprobe, which is
* pointless as this module is already loaded.
*/
static struct kobject *sd_default_probe(dev_t devt, int *partno, void *data)
{
return NULL;
}
/* /*
* Device no to disk mapping: * Device no to disk mapping:
* *
...@@ -2970,8 +2980,10 @@ static int sd_probe(struct device *dev) ...@@ -2970,8 +2980,10 @@ static int sd_probe(struct device *dev)
static int sd_remove(struct device *dev) static int sd_remove(struct device *dev)
{ {
struct scsi_disk *sdkp; struct scsi_disk *sdkp;
dev_t devt;
sdkp = dev_get_drvdata(dev); sdkp = dev_get_drvdata(dev);
devt = disk_devt(sdkp->disk);
scsi_autopm_get_device(sdkp->device); scsi_autopm_get_device(sdkp->device);
async_synchronize_full_domain(&scsi_sd_probe_domain); async_synchronize_full_domain(&scsi_sd_probe_domain);
...@@ -2981,6 +2993,9 @@ static int sd_remove(struct device *dev) ...@@ -2981,6 +2993,9 @@ static int sd_remove(struct device *dev)
del_gendisk(sdkp->disk); del_gendisk(sdkp->disk);
sd_shutdown(dev); sd_shutdown(dev);
blk_register_region(devt, SD_MINORS, NULL,
sd_default_probe, NULL, NULL);
mutex_lock(&sd_ref_mutex); mutex_lock(&sd_ref_mutex);
dev_set_drvdata(dev, NULL); dev_set_drvdata(dev, NULL);
put_device(&sdkp->dev); put_device(&sdkp->dev);
...@@ -3124,9 +3139,13 @@ static int __init init_sd(void) ...@@ -3124,9 +3139,13 @@ static int __init init_sd(void)
SCSI_LOG_HLQUEUE(3, printk("init_sd: sd driver entry point\n")); SCSI_LOG_HLQUEUE(3, printk("init_sd: sd driver entry point\n"));
for (i = 0; i < SD_MAJORS; i++) for (i = 0; i < SD_MAJORS; i++) {
if (register_blkdev(sd_major(i), "sd") == 0) if (register_blkdev(sd_major(i), "sd") != 0)
majors++; continue;
majors++;
blk_register_region(sd_major(i), SD_MINORS, NULL,
sd_default_probe, NULL, NULL);
}
if (!majors) if (!majors)
return -ENODEV; return -ENODEV;
...@@ -3185,8 +3204,10 @@ static void __exit exit_sd(void) ...@@ -3185,8 +3204,10 @@ static void __exit exit_sd(void)
class_unregister(&sd_disk_class); class_unregister(&sd_disk_class);
for (i = 0; i < SD_MAJORS; i++) for (i = 0; i < SD_MAJORS; i++) {
blk_unregister_region(sd_major(i), SD_MINORS);
unregister_blkdev(sd_major(i), "sd"); unregister_blkdev(sd_major(i), "sd");
}
} }
module_init(init_sd); module_init(init_sd);
......
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