From: ashok.vairavan Date: Sat, 8 Oct 2016 01:47:01 +0000 (-0400) Subject: scsi: Add intermediate STARGET_REMOVE state to scsi_target_state X-Git-Tag: v4.1.12-92~66^2~1 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=d008c14d3cbef1ad7ef31e63b2eadd971fdded57;p=users%2Fjedix%2Flinux-maple.git scsi: Add intermediate STARGET_REMOVE state to scsi_target_state Add intermediate STARGET_REMOVE state to scsi_target_state to avoid running into the BUG_ON() in scsi_target_reap(). The STARGET_REMOVE state is only valid in the path from scsi_remove_target() to scsi_target_destroy() indicating this target is going to be removed. This re-fixes the problem introduced in commits bc3f02a795d3 ("[SCSI] scsi_remove_target: fix softlockup regression on hot remove") and 40998193560d ("scsi: restart list search after unlock in scsi_remove_target") in a more comprehensive way. [mkp: Included James' fix for scsi_target_destroy()] Signed-off-by: Johannes Thumshirn Fixes: 40998193560dab6c3ce8d25f4fa58a23e252ef38 Cc: stable@vger.kernel.org Reported-by: Sergey Senozhatsky Tested-by: Sergey Senozhatsky Reviewed-by: Ewan D. Milne Reviewed-by: Hannes Reinecke Reviewed-by: James Bottomley Signed-off-by: Martin K. Petersen Orabug: 24844559 Mainline commit: f05795d3d771f30a7bdc3a138bf714b06d42aa95 Conflicts: The following changes are done to fix kabi breakage. #ifndef __GENKSYMS__ STARGET_REMOVE, #endif --- diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 6efab1c455e1..7a1a39a4817c 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -313,6 +313,7 @@ static void scsi_target_destroy(struct scsi_target *starget) struct Scsi_Host *shost = dev_to_shost(dev->parent); unsigned long flags; + BUG_ON(starget->state == STARGET_DEL); starget->state = STARGET_DEL; transport_destroy_device(dev); spin_lock_irqsave(shost->host_lock, flags); diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index fb17f57a65e6..a24b810407ab 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -1155,11 +1155,13 @@ restart: spin_lock_irqsave(shost->host_lock, flags); list_for_each_entry(starget, &shost->__targets, siblings) { if (starget->state == STARGET_DEL || + starget->state == STARGET_REMOVE || starget == last_target) continue; if (starget->dev.parent == dev || &starget->dev == dev) { kref_get(&starget->reap_ref); last_target = starget; + starget->state = STARGET_REMOVE; spin_unlock_irqrestore(shost->host_lock, flags); __scsi_remove_target(starget); scsi_target_reap(starget); diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index a4c9336811d1..7109f3d5b03b 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -260,6 +260,9 @@ enum scsi_target_state { STARGET_CREATED = 1, STARGET_RUNNING, STARGET_DEL, + #ifndef __GENKSYMS__ + STARGET_REMOVE, + #endif }; /*