summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Anderson <andmike@us.ibm.com>2005-06-16 20:14:33 +0200
committerJames Bottomley <jejb@mulgrave.(none)>2005-07-30 18:13:01 +0200
commit82f29467a025f6a2192d281e97fca0be46e905cc (patch)
tree5cf356ece53caf2936ca85803676b326094f7c38
parent[SCSI] host state model update: reimplement scsi_host_cancel (diff)
downloadlinux-82f29467a025f6a2192d281e97fca0be46e905cc.tar.xz
linux-82f29467a025f6a2192d281e97fca0be46e905cc.zip
[SCSI] host state model update: mediate host add/remove race
Add support to not allow additions to a host when it is being removed. Signed-off-by: Mike Anderson <andmike@us.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r--drivers/scsi/hosts.c2
-rw-r--r--drivers/scsi/scsi_scan.c21
-rw-r--r--include/scsi/scsi_host.h9
3 files changed, 25 insertions, 7 deletions
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 67c4c0c3aa5e..8640ad1c17e2 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -133,7 +133,9 @@ EXPORT_SYMBOL(scsi_host_set_state);
**/
void scsi_remove_host(struct Scsi_Host *shost)
{
+ down(&shost->scan_mutex);
scsi_host_set_state(shost, SHOST_CANCEL);
+ up(&shost->scan_mutex);
scsi_forget_host(shost);
scsi_proc_host_rm(shost);
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 2d3c4ac475f2..076cbe3b5a05 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -1251,9 +1251,12 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
get_device(&starget->dev);
down(&shost->scan_mutex);
- res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata);
- if (res != SCSI_SCAN_LUN_PRESENT)
- sdev = ERR_PTR(-ENODEV);
+ if (scsi_host_scan_allowed(shost)) {
+ res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1,
+ hostdata);
+ if (res != SCSI_SCAN_LUN_PRESENT)
+ sdev = ERR_PTR(-ENODEV);
+ }
up(&shost->scan_mutex);
scsi_target_reap(starget);
put_device(&starget->dev);
@@ -1403,11 +1406,15 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
return -EINVAL;
down(&shost->scan_mutex);
- if (channel == SCAN_WILD_CARD)
- for (channel = 0; channel <= shost->max_channel; channel++)
+ if (scsi_host_scan_allowed(shost)) {
+ if (channel == SCAN_WILD_CARD)
+ for (channel = 0; channel <= shost->max_channel;
+ channel++)
+ scsi_scan_channel(shost, channel, id, lun,
+ rescan);
+ else
scsi_scan_channel(shost, channel, id, lun, rescan);
- else
- scsi_scan_channel(shost, channel, id, lun, rescan);
+ }
up(&shost->scan_mutex);
return 0;
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 0b1e275b2699..1ea5b51d1749 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -650,6 +650,15 @@ static inline struct device *scsi_get_device(struct Scsi_Host *shost)
return shost->shost_gendev.parent;
}
+/**
+ * scsi_host_scan_allowed - Is scanning of this host allowed
+ * @shost: Pointer to Scsi_Host.
+ **/
+static inline int scsi_host_scan_allowed(struct Scsi_Host *shost)
+{
+ return shost->shost_state == SHOST_RUNNING;
+}
+
extern void scsi_unblock_requests(struct Scsi_Host *);
extern void scsi_block_requests(struct Scsi_Host *);