|
@@ -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);
|
|
|
}
|
|
|
|
|
|
/**
|