This is a note to let you know that I've just added the patch titled SCSI: dual scan thread bug fix to the 3.14-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: scsi-dual-scan-thread-bug-fix.patch and it can be found in the queue-3.14 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. >From f2495e228fce9f9cec84367547813cbb0d6db15a Mon Sep 17 00:00:00 2001 From: James Bottomley <JBottomley@xxxxxxxxxxxxx> Date: Tue, 21 Jan 2014 07:01:41 -0800 Subject: SCSI: dual scan thread bug fix From: James Bottomley <JBottomley@xxxxxxxxxxxxx> commit f2495e228fce9f9cec84367547813cbb0d6db15a upstream. In the highly unusual case where two threads are running concurrently through the scanning code scanning the same target, we run into the situation where one may allocate the target while the other is still using it. In this case, because the reap checks for STARGET_CREATED and kills the target without reference counting, the second thread will do the wrong thing on reap. Fix this by reference counting even creates and doing the STARGET_CREATED check in the final put. Tested-by: Sarah Sharp <sarah.a.sharp@xxxxxxxxxxxxxxx> Signed-off-by: James Bottomley <JBottomley@xxxxxxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- drivers/scsi/scsi_scan.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -320,6 +320,7 @@ static void scsi_target_destroy(struct s 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 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_ta */ 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); } /** Patches currently in stable-queue which might be from JBottomley@xxxxxxxxxxxxx are queue-3.14/scsi-dual-scan-thread-bug-fix.patch queue-3.14/scsi-fix-our-current-target-reap-infrastructure.patch queue-3.14/scsi-megaraid-missing-bounds-check-in-mimd_to_kioc.patch -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html