-out_cleanup_transport:
- if (shost->transportt->cleanup)
- shost->transportt->cleanup(sdev);
-out_cleanup_slave:
- if (shost->hostt->slave_destroy)
- shost->hostt->slave_destroy(sdev);
-out_free_queue:
- scsi_free_queue(sdev->request_queue);
-out_free_dev:
- kfree(sdev);
-out:
- printk(ALLOC_FAILURE_MSG, __FUNCTION__);
- return NULL;
+ return starget;
+
+ found:
+ found_target->reap_ref++;
+ spin_unlock_irqrestore(shost->host_lock, flags);
+ put_device(parent);
+ if (found_target->state != STARGET_DEL) {
+ kfree(starget);
+ return found_target;
+ }
+ /* Unfortunately, we found a dying target; need to
+ * wait until it's dead before we can get a new one */
+ put_device(&found_target->dev);
+ flush_scheduled_work();
+ goto retry;
+}
+
+static void scsi_target_reap_usercontext(void *data)
+{
+ struct scsi_target *starget = data;
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ unsigned long flags;
+
+ transport_remove_device(&starget->dev);
+ device_del(&starget->dev);
+ transport_destroy_device(&starget->dev);
+ spin_lock_irqsave(shost->host_lock, flags);
+ if (shost->hostt->target_destroy)
+ shost->hostt->target_destroy(starget);
+ list_del_init(&starget->siblings);
+ spin_unlock_irqrestore(shost->host_lock, flags);
+ put_device(&starget->dev);
+}
+
+/**
+ * scsi_target_reap - check to see if target is in use and destroy if not
+ *
+ * @starget: target to be checked
+ *
+ * This is used after removing a LUN or doing a last put of the target
+ * it checks atomically that nothing is using the target and removes
+ * it if so.
+ */
+void scsi_target_reap(struct scsi_target *starget)
+{
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ unsigned long flags;
+
+ spin_lock_irqsave(shost->host_lock, flags);
+
+ if (--starget->reap_ref == 0 && list_empty(&starget->devices)) {
+ BUG_ON(starget->state == STARGET_DEL);
+ starget->state = STARGET_DEL;
+ spin_unlock_irqrestore(shost->host_lock, flags);
+ execute_in_process_context(scsi_target_reap_usercontext,
+ starget, &starget->ew);
+ return;
+
+ }
+ spin_unlock_irqrestore(shost->host_lock, flags);
+
+ return;