Skip to content

Commit 4099819

Browse files
Christoph HellwigJames Bottomley
authored andcommitted
scsi: restart list search after unlock in scsi_remove_target
When dropping a lock while iterating a list we must restart the search as other threads could have manipulated the list under us. Without this we can get stuck in an endless loop. This bug was introduced by commit bc3f02a Author: Dan Williams <[email protected]> Date: Tue Aug 28 22:12:10 2012 -0700 [SCSI] scsi_remove_target: fix softlockup regression on hot remove Which was itself trying to fix a reported soft lockup issue http://thread.gmane.org/gmane.linux.kernel/1348679 However, we believe even with this revert of the original patch, the soft lockup problem has been fixed by commit f2495e2 Author: James Bottomley <[email protected]> Date: Tue Jan 21 07:01:41 2014 -0800 [SCSI] dual scan thread bug fix Thanks go to Dan Williams <[email protected]> for tracking all this prior history down. Reported-by: Johannes Thumshirn <[email protected]> Signed-off-by: Christoph Hellwig <[email protected]> Tested-by: Johannes Thumshirn <[email protected]> Reviewed-by: Johannes Thumshirn <[email protected]> Fixes: bc3f02a Cc: [email protected] Signed-off-by: James Bottomley <[email protected]>
1 parent a82544c commit 4099819

File tree

1 file changed

+4
-12
lines changed

1 file changed

+4
-12
lines changed

drivers/scsi/scsi_sysfs.c

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,31 +1158,23 @@ static void __scsi_remove_target(struct scsi_target *starget)
11581158
void scsi_remove_target(struct device *dev)
11591159
{
11601160
struct Scsi_Host *shost = dev_to_shost(dev->parent);
1161-
struct scsi_target *starget, *last = NULL;
1161+
struct scsi_target *starget;
11621162
unsigned long flags;
11631163

1164-
/* remove targets being careful to lookup next entry before
1165-
* deleting the last
1166-
*/
1164+
restart:
11671165
spin_lock_irqsave(shost->host_lock, flags);
11681166
list_for_each_entry(starget, &shost->__targets, siblings) {
11691167
if (starget->state == STARGET_DEL)
11701168
continue;
11711169
if (starget->dev.parent == dev || &starget->dev == dev) {
1172-
/* assuming new targets arrive at the end */
11731170
kref_get(&starget->reap_ref);
11741171
spin_unlock_irqrestore(shost->host_lock, flags);
1175-
if (last)
1176-
scsi_target_reap(last);
1177-
last = starget;
11781172
__scsi_remove_target(starget);
1179-
spin_lock_irqsave(shost->host_lock, flags);
1173+
scsi_target_reap(starget);
1174+
goto restart;
11801175
}
11811176
}
11821177
spin_unlock_irqrestore(shost->host_lock, flags);
1183-
1184-
if (last)
1185-
scsi_target_reap(last);
11861178
}
11871179
EXPORT_SYMBOL(scsi_remove_target);
11881180

0 commit comments

Comments
 (0)