The patch titled

     fix something in scsi

has been added to the -mm tree.  Its filename is

     fix-something-in-scsi.patch

Patches currently in -mm which might be from [EMAIL PROTECTED] are

fix-something-in-scsi.patch
usb-storage-rearrange-stuff.patch
fix-something-in-usb.patch



From: Alan Stern <[EMAIL PROTECTED]>

Related to http://bugzilla.kernel.org/show_bug.cgi?id=4863

This is the patch for the SCSI core.  I originally sent it in not as a real
patch submission but as a starting point for further testing and
modification.  Mike Anderson was working on many of the same issues at the
same time; see

http://marc.theaimsgroup.com/?l=linux-scsi&m=111954227709734&w=2

as well as the thread containing my patch.  Not much progress seems to have
happened since then, and I honestly don't know whether James Bottomley has
applied any of these or not.

Signed-off-by: Alan Stern <[EMAIL PROTECTED]>
Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
---

 drivers/scsi/hosts.c      |    7 ++
 drivers/scsi/scsi_priv.h  |    1 
 drivers/scsi/scsi_scan.c  |  118 ++++++++++++++++++++++++++--------------------
 drivers/scsi/scsi_sysfs.c |   37 ++++++++------
 include/scsi/scsi_host.h  |    1 
 5 files changed, 98 insertions(+), 66 deletions(-)

diff -puN drivers/scsi/hosts.c~fix-something-in-scsi drivers/scsi/hosts.c
--- 25/drivers/scsi/hosts.c~fix-something-in-scsi       Fri Jul  8 16:50:49 2005
+++ 25-akpm/drivers/scsi/hosts.c        Fri Jul  8 16:50:49 2005
@@ -74,8 +74,13 @@ static void scsi_host_cancel(struct Scsi
  **/
 void scsi_remove_host(struct Scsi_Host *shost)
 {
-       scsi_forget_host(shost);
+       set_bit(SHOST_REMOVE, &shost->shost_state);
        scsi_host_cancel(shost, 0);
+
+       down(&shost->scan_mutex);       /* Wait for scanning to stop */
+       up(&shost->scan_mutex);
+
+       scsi_forget_host(shost);
        scsi_proc_host_rm(shost);
 
        set_bit(SHOST_DEL, &shost->shost_state);
diff -puN drivers/scsi/scsi_priv.h~fix-something-in-scsi 
drivers/scsi/scsi_priv.h
--- 25/drivers/scsi/scsi_priv.h~fix-something-in-scsi   Fri Jul  8 16:50:49 2005
+++ 25-akpm/drivers/scsi/scsi_priv.h    Fri Jul  8 16:50:49 2005
@@ -121,6 +121,7 @@ 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 struct scsi_transport_template blank_transport_template;
+extern void __scsi_remove_device(struct scsi_device *);
 
 extern struct bus_type scsi_bus_type;
 
diff -puN drivers/scsi/scsi_scan.c~fix-something-in-scsi 
drivers/scsi/scsi_scan.c
--- 25/drivers/scsi/scsi_scan.c~fix-something-in-scsi   Fri Jul  8 16:50:49 2005
+++ 25-akpm/drivers/scsi/scsi_scan.c    Fri Jul  8 16:50:49 2005
@@ -855,8 +855,12 @@ static int scsi_probe_and_add_lun(struct
  out_free_sdev:
        if (res == SCSI_SCAN_LUN_PRESENT) {
                if (sdevp) {
-                       scsi_device_get(sdev);
-                       *sdevp = sdev;
+                       if (scsi_device_get(sdev) == 0) {
+                               *sdevp = sdev;
+                       } else {
+                               __scsi_remove_device(sdev);
+                               res = SCSI_SCAN_NO_RESPONSE;
+                       }
                }
        } else {
                if (sdev->host->hostt->slave_destroy)
@@ -1190,22 +1194,28 @@ struct scsi_device *__scsi_add_device(st
                                      uint id, uint lun, void *hostdata)
 {
        struct scsi_device *sdev;
-       struct device *parent = &shost->shost_gendev;
        int res;
-       struct scsi_target *starget = scsi_alloc_target(parent, channel, id);
+       struct scsi_target *starget;
 
-       if (!starget)
-               return ERR_PTR(-ENOMEM);
+       down(&shost->scan_mutex);
+       if (test_bit(SHOST_REMOVE, &shost->shost_state)) {
+               sdev = ERR_PTR(-ENODEV);
+               goto out;
+       }
+       starget = scsi_alloc_target(&shost->shost_gendev, channel, id);
+       if (!starget) {
+               sdev = ERR_PTR(-ENOMEM);
+               goto out;
+       }
 
        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);
-       up(&shost->scan_mutex);
        scsi_target_reap(starget);
        put_device(&starget->dev);
-
+out:
+       up(&shost->scan_mutex);
        return sdev;
 }
 EXPORT_SYMBOL(__scsi_add_device);
@@ -1226,27 +1236,8 @@ void scsi_rescan_device(struct device *d
 }
 EXPORT_SYMBOL(scsi_rescan_device);
 
-/**
- * scsi_scan_target - scan a target id, possibly including all LUNs on the
- *     target.
- * @sdevsca:   Scsi_Device handle for scanning
- * @shost:     host to scan
- * @channel:   channel to scan
- * @id:                target id to scan
- *
- * Description:
- *     Scan the target id on @shost, @channel, and @id. Scan at least LUN
- *     0, and possibly all LUNs on the target id.
- *
- *     Use the pre-allocated @sdevscan as a handle for the scanning. This
- *     function sets sdevscan->host, sdevscan->id and sdevscan->lun; the
- *     scanning functions modify sdevscan->lun.
- *
- *     First try a REPORT LUN scan, if that does not scan the target, do a
- *     sequential scan of LUNs on the target id.
- **/
-void scsi_scan_target(struct device *parent, unsigned int channel,
-                     unsigned int id, unsigned int lun, int rescan)
+static void __scsi_scan_target(struct device *parent, unsigned int channel,
+               unsigned int id, unsigned int lun, int rescan)
 {
        struct Scsi_Host *shost = dev_to_shost(parent);
        int bflags = 0;
@@ -1260,9 +1251,7 @@ void scsi_scan_target(struct device *par
                 */
                return;
 
-
        starget = scsi_alloc_target(parent, channel, id);
-
        if (!starget)
                return;
 
@@ -1308,6 +1297,32 @@ void scsi_scan_target(struct device *par
 
        put_device(&starget->dev);
 }
+
+/**
+ * scsi_scan_target - scan a target id, possibly including all LUNs on the
+ *     target.
+ * @parent:    host to scan
+ * @channel:   channel to scan
+ * @id:                target id to scan
+ * @rescan:    passed to LUN scanning routines
+ *
+ * Description:
+ *     Scan the target id on @shost, @channel, and @id. Scan at least LUN
+ *     0, and possibly all LUNs on the target id.
+ *
+ *     First try a REPORT LUN scan, if that does not scan the target, do a
+ *     sequential scan of LUNs on the target id.
+ **/
+void scsi_scan_target(struct device *parent, unsigned int channel,
+                     unsigned int id, unsigned int lun, int rescan)
+{
+       struct Scsi_Host *shost = dev_to_shost(parent);
+
+       down(&shost->scan_mutex);
+       if (!test_bit(SHOST_REMOVE, &shost->shost_state))
+               __scsi_scan_target(parent, channel, id, lun, rescan);
+       up(&shost->scan_mutex);
+}
 EXPORT_SYMBOL(scsi_scan_target);
 
 static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel,
@@ -1333,10 +1348,12 @@ static void scsi_scan_channel(struct Scs
                                order_id = shost->max_id - id - 1;
                        else
                                order_id = id;
-                       scsi_scan_target(&shost->shost_gendev, channel, 
order_id, lun, rescan);
+                       __scsi_scan_target(&shost->shost_gendev, channel,
+                                       order_id, lun, rescan);
                }
        else
-               scsi_scan_target(&shost->shost_gendev, channel, id, lun, 
rescan);
+               __scsi_scan_target(&shost->shost_gendev, channel,
+                               id, lun, rescan);
 }
 
 int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,
@@ -1351,11 +1368,14 @@ int scsi_scan_host_selected(struct Scsi_
                return -EINVAL;
 
        down(&shost->scan_mutex);
+       if (test_bit(SHOST_REMOVE, &shost->shost_state))
+               goto out;
        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);
+out:
        up(&shost->scan_mutex);
 
        return 0;
@@ -1387,23 +1407,17 @@ EXPORT_SYMBOL(scsi_scan_single_target);
 
 void scsi_forget_host(struct Scsi_Host *shost)
 {
-       struct scsi_target *starget, *tmp;
+       struct scsi_device *sdev;
        unsigned long flags;
 
-       /*
-        * Ok, this look a bit strange.  We always look for the first device
-        * on the list as scsi_remove_device removes them from it - thus we
-        * also have to release the lock.
-        * We don't need to get another reference to the device before
-        * releasing the lock as we already own the reference from
-        * scsi_register_device that's release in scsi_remove_device.  And
-        * after that we don't look at sdev anymore.
-        */
+restart:
        spin_lock_irqsave(shost->host_lock, flags);
-       list_for_each_entry_safe(starget, tmp, &shost->__targets, siblings) {
+       list_for_each_entry(sdev, &shost->__devices, siblings) {
+               if (sdev->sdev_state == SDEV_DEL)
+                       continue;
                spin_unlock_irqrestore(shost->host_lock, flags);
-               scsi_remove_target(&starget->dev);
-               spin_lock_irqsave(shost->host_lock, flags);
+               __scsi_remove_device(sdev);
+               goto restart;
        }
        spin_unlock_irqrestore(shost->host_lock, flags);
 }
@@ -1430,12 +1444,16 @@ void scsi_forget_host(struct Scsi_Host *
  */
 struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost)
 {
-       struct scsi_device *sdev;
+       struct scsi_device *sdev = NULL;
        struct scsi_target *starget;
 
+       down(&shost->scan_mutex);
+       if (test_bit(SHOST_REMOVE, &shost->shost_state))
+               goto out;
+
        starget = scsi_alloc_target(&shost->shost_gendev, 0, shost->this_id);
        if (!starget)
-               return NULL;
+               goto out;
 
        sdev = scsi_alloc_sdev(starget, 0, NULL);
        if (sdev) {
@@ -1443,6 +1461,8 @@ struct scsi_device *scsi_get_host_dev(st
                sdev->borken = 0;
        }
        put_device(&starget->dev);
+out:
+       up(&shost->scan_mutex);
        return sdev;
 }
 EXPORT_SYMBOL(scsi_get_host_dev);
diff -puN drivers/scsi/scsi_sysfs.c~fix-something-in-scsi 
drivers/scsi/scsi_sysfs.c
--- 25/drivers/scsi/scsi_sysfs.c~fix-something-in-scsi  Fri Jul  8 16:50:49 2005
+++ 25-akpm/drivers/scsi/scsi_sysfs.c   Fri Jul  8 16:50:49 2005
@@ -591,7 +591,7 @@ int scsi_sysfs_add_sdev(struct scsi_devi
                        error = attr_add(&sdev->sdev_gendev,
                                        sdev->host->hostt->sdev_attrs[i]);
                        if (error) {
-                               scsi_remove_device(sdev);
+                               __scsi_remove_device(sdev);
                                goto out;
                        }
                }
@@ -605,7 +605,7 @@ int scsi_sysfs_add_sdev(struct scsi_devi
                                                        
scsi_sysfs_sdev_attrs[i]);
                        error = device_create_file(&sdev->sdev_gendev, attr);
                        if (error) {
-                               scsi_remove_device(sdev);
+                               __scsi_remove_device(sdev);
                                goto out;
                        }
                }
@@ -625,17 +625,10 @@ int scsi_sysfs_add_sdev(struct scsi_devi
        return error;
 }
 
-/**
- * scsi_remove_device - unregister a device from the scsi bus
- * @sdev:      scsi_device to unregister
- **/
-void scsi_remove_device(struct scsi_device *sdev)
+void __scsi_remove_device(struct scsi_device *sdev)
 {
-       struct Scsi_Host *shost = sdev->host;
-
-       down(&shost->scan_mutex);
        if (scsi_device_set_state(sdev, SDEV_CANCEL) != 0)
-               goto out;
+               return;
 
        class_device_unregister(&sdev->sdev_classdev);
        device_del(&sdev->sdev_gendev);
@@ -644,8 +637,17 @@ void scsi_remove_device(struct scsi_devi
                sdev->host->hostt->slave_destroy(sdev);
        transport_unregister_device(&sdev->sdev_gendev);
        put_device(&sdev->sdev_gendev);
-out:
-       up(&shost->scan_mutex);
+}
+
+/**
+ * scsi_remove_device - unregister a device from the scsi bus
+ * @sdev:      scsi_device to unregister
+ **/
+void scsi_remove_device(struct scsi_device *sdev)
+{
+       down(&sdev->host->scan_mutex);
+       __scsi_remove_device(sdev);
+       up(&sdev->host->scan_mutex);
 }
 EXPORT_SYMBOL(scsi_remove_device);
 
@@ -653,17 +655,20 @@ void __scsi_remove_target(struct scsi_ta
 {
        struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
        unsigned long flags;
-       struct scsi_device *sdev, *tmp;
+       struct scsi_device *sdev;
 
        spin_lock_irqsave(shost->host_lock, flags);
        starget->reap_ref++;
-       list_for_each_entry_safe(sdev, tmp, &shost->__devices, siblings) {
+restart:
+       list_for_each_entry(sdev, &shost->__devices, siblings) {
                if (sdev->channel != starget->channel ||
-                   sdev->id != starget->id)
+                   sdev->id != starget->id ||
+                   sdev->sdev_state == SDEV_DEL)
                        continue;
                spin_unlock_irqrestore(shost->host_lock, flags);
                scsi_remove_device(sdev);
                spin_lock_irqsave(shost->host_lock, flags);
+               goto restart;
        }
        spin_unlock_irqrestore(shost->host_lock, flags);
        scsi_target_reap(starget);
diff -puN include/scsi/scsi_host.h~fix-something-in-scsi 
include/scsi/scsi_host.h
--- 25/include/scsi/scsi_host.h~fix-something-in-scsi   Fri Jul  8 16:50:49 2005
+++ 25-akpm/include/scsi/scsi_host.h    Fri Jul  8 16:50:49 2005
@@ -436,6 +436,7 @@ enum {
        SHOST_DEL,
        SHOST_CANCEL,
        SHOST_RECOVERY,
+       SHOST_REMOVE,
 };
 
 struct Scsi_Host {
_
-
To unsubscribe from this list: send the line "unsubscribe mm-commits" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to