Commit 20d32d9d authored by Christoph Hellwig's avatar Christoph Hellwig

[PATCH] serialize bus scanning

Synchronize all scanning activity, this fixes long-standing races
vs /proc/scsi/scsi and sysfs addition and deletion of devices.

Note that this does not serialize removing, the lists will get
their own locking soon.
parent f0a47ab7
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <asm/semaphore.h>
#include "scsi.h" #include "scsi.h"
#include "hosts.h" #include "hosts.h"
...@@ -94,6 +95,13 @@ MODULE_PARM_DESC(max_report_luns, ...@@ -94,6 +95,13 @@ MODULE_PARM_DESC(max_report_luns,
" between 1 and 16384)"); " between 1 and 16384)");
#endif #endif
/*
* This mutex serializes all scsi scanning activity from kernel- and
* userspace. It could easily be made per-host but I'd like to avoid
* the overhead for now.
*/
static DECLARE_MUTEX(scsi_scan_mutex);
/** /**
* scsi_unlock_floptical - unlock device via a special MODE SENSE command * scsi_unlock_floptical - unlock device via a special MODE SENSE command
* @sreq: used to send the command * @sreq: used to send the command
...@@ -1067,9 +1075,12 @@ struct scsi_device *scsi_add_device(struct Scsi_Host *shost, ...@@ -1067,9 +1075,12 @@ struct scsi_device *scsi_add_device(struct Scsi_Host *shost,
struct scsi_device *sdev; struct scsi_device *sdev;
int res; int res;
down(&scsi_scan_mutex);
res = scsi_probe_and_add_lun(shost, channel, id, lun, NULL, &sdev, 1); res = scsi_probe_and_add_lun(shost, channel, id, lun, NULL, &sdev, 1);
if (res != SCSI_SCAN_LUN_PRESENT) if (res != SCSI_SCAN_LUN_PRESENT)
sdev = ERR_PTR(-ENODEV); sdev = ERR_PTR(-ENODEV);
up(&scsi_scan_mutex);
return sdev; return sdev;
} }
...@@ -1191,11 +1202,14 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, ...@@ -1191,11 +1202,14 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
((lun != SCAN_WILD_CARD) && (lun > shost->max_lun))) ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun)))
return -EINVAL; return -EINVAL;
down(&scsi_scan_mutex);
if (channel == SCAN_WILD_CARD) if (channel == SCAN_WILD_CARD)
for (channel = 0; channel <= shost->max_channel; channel++) for (channel = 0; channel <= shost->max_channel; channel++)
scsi_scan_channel(shost, channel, id, lun, rescan); scsi_scan_channel(shost, channel, id, lun, rescan);
else else
scsi_scan_channel(shost, channel, id, lun, rescan); scsi_scan_channel(shost, channel, id, lun, rescan);
up(&scsi_scan_mutex);
return 0; return 0;
} }
......
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