Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
[linux-2.6-microblaze.git] / drivers / scsi / scsi_sysfs.c
index 2c76d7a..677b5c5 100644 (file)
@@ -467,14 +467,14 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work)
        sdev->request_queue = NULL;
 
        mutex_lock(&sdev->inquiry_mutex);
-       rcu_swap_protected(sdev->vpd_pg0, vpd_pg0,
-                          lockdep_is_held(&sdev->inquiry_mutex));
-       rcu_swap_protected(sdev->vpd_pg80, vpd_pg80,
-                          lockdep_is_held(&sdev->inquiry_mutex));
-       rcu_swap_protected(sdev->vpd_pg83, vpd_pg83,
-                          lockdep_is_held(&sdev->inquiry_mutex));
-       rcu_swap_protected(sdev->vpd_pg89, vpd_pg89,
-                          lockdep_is_held(&sdev->inquiry_mutex));
+       vpd_pg0 = rcu_replace_pointer(sdev->vpd_pg0, vpd_pg0,
+                                      lockdep_is_held(&sdev->inquiry_mutex));
+       vpd_pg80 = rcu_replace_pointer(sdev->vpd_pg80, vpd_pg80,
+                                      lockdep_is_held(&sdev->inquiry_mutex));
+       vpd_pg83 = rcu_replace_pointer(sdev->vpd_pg83, vpd_pg83,
+                                      lockdep_is_held(&sdev->inquiry_mutex));
+       vpd_pg89 = rcu_replace_pointer(sdev->vpd_pg89, vpd_pg89,
+                                      lockdep_is_held(&sdev->inquiry_mutex));
        mutex_unlock(&sdev->inquiry_mutex);
 
        if (vpd_pg0)
@@ -739,6 +739,14 @@ sdev_store_delete(struct device *dev, struct device_attribute *attr,
                  const char *buf, size_t count)
 {
        struct kernfs_node *kn;
+       struct scsi_device *sdev = to_scsi_device(dev);
+
+       /*
+        * We need to try to get module, avoiding the module been removed
+        * during delete.
+        */
+       if (scsi_device_get(sdev))
+               return -ENODEV;
 
        kn = sysfs_break_active_protection(&dev->kobj, &attr->attr);
        WARN_ON_ONCE(!kn);
@@ -753,9 +761,10 @@ sdev_store_delete(struct device *dev, struct device_attribute *attr,
         * state into SDEV_DEL.
         */
        device_remove_file(dev, attr);
-       scsi_remove_device(to_scsi_device(dev));
+       scsi_remove_device(sdev);
        if (kn)
                sysfs_unbreak_active_protection(kn);
+       scsi_device_put(sdev);
        return count;
 };
 static DEVICE_ATTR(delete, S_IWUSR, NULL, sdev_store_delete);