diff options
Diffstat (limited to 'drivers/scsi/scsi_sysfs.c')
-rw-r--r-- | drivers/scsi/scsi_sysfs.c | 30 |
1 files changed, 14 insertions, 16 deletions
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 093d4f6a54d..ce5224c92ed 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c | |||
@@ -1031,33 +1031,31 @@ static void __scsi_remove_target(struct scsi_target *starget) | |||
1031 | void scsi_remove_target(struct device *dev) | 1031 | void scsi_remove_target(struct device *dev) |
1032 | { | 1032 | { |
1033 | struct Scsi_Host *shost = dev_to_shost(dev->parent); | 1033 | struct Scsi_Host *shost = dev_to_shost(dev->parent); |
1034 | struct scsi_target *starget, *found; | 1034 | struct scsi_target *starget, *last = NULL; |
1035 | unsigned long flags; | 1035 | unsigned long flags; |
1036 | 1036 | ||
1037 | restart: | 1037 | /* remove targets being careful to lookup next entry before |
1038 | found = NULL; | 1038 | * deleting the last |
1039 | */ | ||
1039 | spin_lock_irqsave(shost->host_lock, flags); | 1040 | spin_lock_irqsave(shost->host_lock, flags); |
1040 | list_for_each_entry(starget, &shost->__targets, siblings) { | 1041 | list_for_each_entry(starget, &shost->__targets, siblings) { |
1041 | if (starget->state == STARGET_DEL) | 1042 | if (starget->state == STARGET_DEL) |
1042 | continue; | 1043 | continue; |
1043 | if (starget->dev.parent == dev || &starget->dev == dev) { | 1044 | if (starget->dev.parent == dev || &starget->dev == dev) { |
1044 | found = starget; | 1045 | /* assuming new targets arrive at the end */ |
1045 | found->reap_ref++; | 1046 | starget->reap_ref++; |
1046 | break; | 1047 | spin_unlock_irqrestore(shost->host_lock, flags); |
1048 | if (last) | ||
1049 | scsi_target_reap(last); | ||
1050 | last = starget; | ||
1051 | __scsi_remove_target(starget); | ||
1052 | spin_lock_irqsave(shost->host_lock, flags); | ||
1047 | } | 1053 | } |
1048 | } | 1054 | } |
1049 | spin_unlock_irqrestore(shost->host_lock, flags); | 1055 | spin_unlock_irqrestore(shost->host_lock, flags); |
1050 | 1056 | ||
1051 | if (found) { | 1057 | if (last) |
1052 | __scsi_remove_target(found); | 1058 | scsi_target_reap(last); |
1053 | scsi_target_reap(found); | ||
1054 | /* in the case where @dev has multiple starget children, | ||
1055 | * continue removing. | ||
1056 | * | ||
1057 | * FIXME: does such a case exist? | ||
1058 | */ | ||
1059 | goto restart; | ||
1060 | } | ||
1061 | } | 1059 | } |
1062 | EXPORT_SYMBOL(scsi_remove_target); | 1060 | EXPORT_SYMBOL(scsi_remove_target); |
1063 | 1061 | ||