Merge branch 'linux-linaro-lsk' into linux-linaro-lsk-android
[firefly-linux-kernel-4.4.55.git] / drivers / scsi / scsi_scan.c
index 342876ce53c1bb7444887b499491c26605d4b102..859240408f9ee4ce7a04f9ae767153a933d1ba6d 100644 (file)
@@ -320,6 +320,7 @@ static void scsi_target_destroy(struct scsi_target *starget)
        struct Scsi_Host *shost = dev_to_shost(dev->parent);
        unsigned long flags;
 
+       starget->state = STARGET_DEL;
        transport_destroy_device(dev);
        spin_lock_irqsave(shost->host_lock, flags);
        if (shost->hostt->target_destroy)
@@ -384,9 +385,15 @@ static void scsi_target_reap_ref_release(struct kref *kref)
        struct scsi_target *starget
                = container_of(kref, struct scsi_target, reap_ref);
 
-       transport_remove_device(&starget->dev);
-       device_del(&starget->dev);
-       starget->state = STARGET_DEL;
+       /*
+        * if we get here and the target is still in the CREATED state that
+        * means it was allocated but never made visible (because a scan
+        * turned up no LUNs), so don't call device_del() on it.
+        */
+       if (starget->state != STARGET_CREATED) {
+               transport_remove_device(&starget->dev);
+               device_del(&starget->dev);
+       }
        scsi_target_destroy(starget);
 }
 
@@ -506,11 +513,13 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
  */
 void scsi_target_reap(struct scsi_target *starget)
 {
+       /*
+        * serious problem if this triggers: STARGET_DEL is only set in the if
+        * the reap_ref drops to zero, so we're trying to do another final put
+        * on an already released kref
+        */
        BUG_ON(starget->state == STARGET_DEL);
-       if (starget->state == STARGET_CREATED)
-               scsi_target_destroy(starget);
-       else
-               scsi_target_reap_ref_put(starget);
+       scsi_target_reap_ref_put(starget);
 }
 
 /**