From: "Ewan D. Milne" <emi...@redhat.com>

Add a "rescan" attribute to sysfs for scsi_target objects,
to permit them to be scanned for LUN changes (e.g. from udev).

Signed-off-by: Ewan D. Milne <emi...@redhat.com>
---
 drivers/scsi/scsi_priv.h  |  4 +++-
 drivers/scsi/scsi_scan.c  | 30 +++--------------------
 drivers/scsi/scsi_sysfs.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 67 insertions(+), 28 deletions(-)

diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index ed80f21..7c33799 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -131,7 +131,9 @@ extern int scsi_sysfs_add_host(struct Scsi_Host *);
 extern int scsi_sysfs_register(void);
 extern void scsi_sysfs_unregister(void);
 extern void scsi_sysfs_device_initialize(struct scsi_device *);
-extern int scsi_sysfs_target_initialize(struct scsi_device *);
+extern void scsi_sysfs_target_initialize(struct scsi_target *,
+                                        struct Scsi_Host *,
+                                        struct device *parent);
 extern struct scsi_transport_template blank_transport_template;
 extern void __scsi_remove_device(struct scsi_device *);
 
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 0adfecb..243c8b4 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -343,26 +343,6 @@ static void scsi_target_destroy(struct scsi_target 
*starget)
        put_device(dev);
 }
 
-static void scsi_target_dev_release(struct device *dev)
-{
-       struct device *parent = dev->parent;
-       struct scsi_target *starget = to_scsi_target(dev);
-
-       kfree(starget);
-       put_device(parent);
-}
-
-static struct device_type scsi_target_type = {
-       .name =         "scsi_target",
-       .release =      scsi_target_dev_release,
-};
-
-int scsi_is_target_device(const struct device *dev)
-{
-       return dev->type == &scsi_target_type;
-}
-EXPORT_SYMBOL(scsi_is_target_device);
-
 static struct scsi_target *__scsi_find_target(struct device *parent,
                                              int channel, uint id)
 {
@@ -413,15 +393,11 @@ static struct scsi_target *scsi_alloc_target(struct 
device *parent,
                printk(KERN_ERR "%s: allocation failure\n", __func__);
                return NULL;
        }
-       dev = &starget->dev;
-       device_initialize(dev);
-       starget->reap_ref = 1;
-       dev->parent = get_device(parent);
-       dev_set_name(dev, "target%d:%d:%d", shost->host_no, channel, id);
-       dev->bus = &scsi_bus_type;
-       dev->type = &scsi_target_type;
        starget->id = id;
        starget->channel = channel;
+       scsi_sysfs_target_initialize(starget, shost, parent);
+       dev = &starget->dev;
+       starget->reap_ref = 1;
        starget->can_queue = 0;
        INIT_LIST_HEAD(&starget->siblings);
        INIT_LIST_HEAD(&starget->devices);
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index d5d86b2..212b43a 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -1129,6 +1129,67 @@ int scsi_is_sdev_device(const struct device *dev)
 }
 EXPORT_SYMBOL(scsi_is_sdev_device);
 
+static ssize_t
+starget_store_rescan_field(struct device *dev, struct device_attribute *attr,
+                          const char *buf, size_t count)
+{
+       struct scsi_target *starget = to_scsi_target(dev);
+
+       scsi_scan_target(starget->dev.parent, starget->channel, starget->id,
+                        SCAN_WILD_CARD, 1);
+       return count;
+}
+/* DEVICE_ATTR(rescan) clashes with dev_attr_rescan for sdev */
+struct device_attribute dev_attr_trescan =
+       __ATTR(rescan, S_IWUSR, NULL, starget_store_rescan_field);
+
+static struct attribute *scsi_target_attrs[] = {
+       &dev_attr_trescan.attr,
+       NULL
+};
+
+static struct attribute_group scsi_target_attr_group = {
+       .attrs =        scsi_target_attrs,
+};
+
+static const struct attribute_group *scsi_target_attr_groups[] = {
+       &scsi_target_attr_group,
+       NULL
+};
+
+static void scsi_target_dev_release(struct device *dev)
+{
+       struct device *parent = dev->parent;
+       struct scsi_target *starget = to_scsi_target(dev);
+
+       kfree(starget);
+       put_device(parent);
+}
+
+static struct device_type scsi_target_type = {
+       .name =         "scsi_target",
+       .release =      scsi_target_dev_release,
+       .groups =       scsi_target_attr_groups,
+};
+
+int scsi_is_target_device(const struct device *dev)
+{
+       return dev->type == &scsi_target_type;
+}
+EXPORT_SYMBOL(scsi_is_target_device);
+
+void scsi_sysfs_target_initialize(struct scsi_target *starget,
+                                 struct Scsi_Host *shost,
+                                 struct device *parent)
+{
+       device_initialize(&starget->dev);
+       starget->dev.parent = get_device(parent);
+       starget->dev.bus = &scsi_bus_type;
+       starget->dev.type = &scsi_target_type;
+       dev_set_name(&starget->dev, "target%d:%d:%d", shost->host_no,
+                    starget->channel, starget->id);
+}
+
 /* A blank transport template that is used in drivers that don't
  * yet implement Transport Attributes */
 struct scsi_transport_template blank_transport_template = { { { {NULL, }, }, 
}, };
-- 
1.7.11.7

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to