lkml.org 
[lkml]   [2015]   [Nov]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    Subject[PATCH 3.2 32/52] scsi: restart list search after unlock in scsi_remove_target
    3.2.74-rc1 review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Christoph Hellwig <hch@lst.de>

    commit 40998193560dab6c3ce8d25f4fa58a23e252ef38 upstream.

    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 bc3f02a795d3b4faa99d37390174be2a75d091bd
    Author: Dan Williams <djbw@fb.com>
    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 f2495e228fce9f9cec84367547813cbb0d6db15a
    Author: James Bottomley <JBottomley@Parallels.com>
    Date: Tue Jan 21 07:01:41 2014 -0800

    [SCSI] dual scan thread bug fix

    Thanks go to Dan Williams <dan.j.williams@intel.com> for tracking all this
    prior history down.

    Reported-by: Johannes Thumshirn <jthumshirn@suse.de>
    Signed-off-by: Christoph Hellwig <hch@lst.de>
    Tested-by: Johannes Thumshirn <jthumshirn@suse.de>
    Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
    Fixes: bc3f02a795d3b4faa99d37390174be2a75d091bd
    Signed-off-by: James Bottomley <JBottomley@Odin.com>
    Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
    ---
    drivers/scsi/scsi_sysfs.c | 16 ++++------------
    1 file changed, 4 insertions(+), 12 deletions(-)

    --- a/drivers/scsi/scsi_sysfs.c
    +++ b/drivers/scsi/scsi_sysfs.c
    @@ -1029,31 +1029,23 @@ static void __scsi_remove_target(struct
    void scsi_remove_target(struct device *dev)
    {
    struct Scsi_Host *shost = dev_to_shost(dev->parent);
    - struct scsi_target *starget, *last = NULL;
    + struct scsi_target *starget;
    unsigned long flags;

    - /* remove targets being careful to lookup next entry before
    - * deleting the last
    - */
    +restart:
    spin_lock_irqsave(shost->host_lock, flags);
    list_for_each_entry(starget, &shost->__targets, siblings) {
    if (starget->state == STARGET_DEL)
    continue;
    if (starget->dev.parent == dev || &starget->dev == dev) {
    - /* assuming new targets arrive at the end */
    kref_get(&starget->reap_ref);
    spin_unlock_irqrestore(shost->host_lock, flags);
    - if (last)
    - scsi_target_reap(last);
    - last = starget;
    __scsi_remove_target(starget);
    - spin_lock_irqsave(shost->host_lock, flags);
    + scsi_target_reap(starget);
    + goto restart;
    }
    }
    spin_unlock_irqrestore(shost->host_lock, flags);
    -
    - if (last)
    - scsi_target_reap(last);
    }
    EXPORT_SYMBOL(scsi_remove_target);



    \
     
     \ /
      Last update: 2015-11-25 00:01    [W:4.071 / U:0.048 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site