[SCSI] remove target parent limitiation
When James Smart fixed the issue of the userspace scan atributes
crashing the system with the FC transport class he added a patch to
let the transport class check if the parent is valid for a given
transport class.
When adding support for the integrated raid of fusion sas devices
we ran into a problem with that, as it didn't allow adding virtual
raid volumes without the transport class knowing about it.
So this patch adds a user_scan attribute instead, that takes over from
scsi_scan_host_selected if the transport class sets it and thus lets
the transport class control the user-initiated scanning. As this
plugs the hole about user-initiated scanning the target_parent hook
goes away and we rely on callers of the scanning routines to do
something sensible.
For SAS this meant I had to switch from a spinlock to a mutex to
synchronize the topology linked lists, in FC they were completely
unsynchronized which seems wrong.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index e950435..fb6641b 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -29,6 +29,7 @@
#include <linux/slab.h>
#include <linux/string.h>
+#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport.h>
@@ -62,7 +63,7 @@
struct sas_host_attrs {
struct list_head rphy_list;
- spinlock_t lock;
+ struct mutex lock;
u32 next_target_id;
};
#define to_sas_host_attrs(host) ((struct sas_host_attrs *)(host)->shost_data)
@@ -165,7 +166,7 @@
struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
INIT_LIST_HEAD(&sas_host->rphy_list);
- spin_lock_init(&sas_host->lock);
+ mutex_init(&sas_host->lock);
sas_host->next_target_id = 0;
return 0;
}
@@ -626,7 +627,7 @@
transport_add_device(&rphy->dev);
transport_configure_device(&rphy->dev);
- spin_lock(&sas_host->lock);
+ mutex_lock(&sas_host->lock);
list_add_tail(&rphy->list, &sas_host->rphy_list);
if (identify->device_type == SAS_END_DEVICE &&
(identify->target_port_protocols &
@@ -634,7 +635,7 @@
rphy->scsi_target_id = sas_host->next_target_id++;
else
rphy->scsi_target_id = -1;
- spin_unlock(&sas_host->lock);
+ mutex_unlock(&sas_host->lock);
if (rphy->scsi_target_id != -1) {
scsi_scan_target(&rphy->dev, parent->number,
@@ -661,9 +662,9 @@
struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
- spin_lock(&sas_host->lock);
+ mutex_lock(&sas_host->lock);
list_del(&rphy->list);
- spin_unlock(&sas_host->lock);
+ mutex_unlock(&sas_host->lock);
transport_destroy_device(&rphy->dev);
put_device(rphy->dev.parent);
@@ -703,9 +704,9 @@
device_del(dev);
transport_destroy_device(dev);
- spin_lock(&sas_host->lock);
+ mutex_lock(&sas_host->lock);
list_del(&rphy->list);
- spin_unlock(&sas_host->lock);
+ mutex_unlock(&sas_host->lock);
parent->rphy = NULL;
@@ -731,23 +732,28 @@
* SCSI scan helper
*/
-static struct device *sas_target_parent(struct Scsi_Host *shost,
- int channel, uint id)
+static int sas_user_scan(struct Scsi_Host *shost, uint channel,
+ uint id, uint lun)
{
struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
struct sas_rphy *rphy;
- struct device *dev = NULL;
- spin_lock(&sas_host->lock);
+ mutex_lock(&sas_host->lock);
list_for_each_entry(rphy, &sas_host->rphy_list, list) {
struct sas_phy *parent = dev_to_phy(rphy->dev.parent);
- if (parent->number == channel &&
- rphy->scsi_target_id == id)
- dev = &rphy->dev;
- }
- spin_unlock(&sas_host->lock);
- return dev;
+ if (rphy->scsi_target_id == -1)
+ continue;
+
+ if ((channel == SCAN_WILD_CARD || channel == parent->number) &&
+ (id == SCAN_WILD_CARD || id == rphy->scsi_target_id)) {
+ scsi_scan_target(&rphy->dev, parent->number,
+ rphy->scsi_target_id, lun, 1);
+ }
+ }
+ mutex_unlock(&sas_host->lock);
+
+ return 0;
}
@@ -792,7 +798,7 @@
return NULL;
memset(i, 0, sizeof(struct sas_internal));
- i->t.target_parent = sas_target_parent;
+ i->t.user_scan = sas_user_scan;
i->t.host_attrs.ac.attrs = &i->host_attrs[0];
i->t.host_attrs.ac.class = &sas_host_class.class;