lkml.org 
[lkml]   [2013]   [Nov]   [9]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.10 24/74] SCSI: sd: call blk_pm_runtime_init before add_disk
    Date
    3.10-stable review patch.  If anyone has any objections, please let me know.

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

    From: Aaron Lu <aaron.lu@intel.com>

    commit 10c580e4239df5c3344ca00322eca86ab2de880b upstream.

    Sujit has found a race condition that would make q->nr_pending
    unbalanced, it occurs as Sujit explained:

    "
    sd_probe_async() ->
    add_disk() ->
    disk_add_event() ->
    schedule(disk_events_workfn)
    sd_revalidate_disk()
    blk_pm_runtime_init()
    return;

    Let's say the disk_events_workfn() calls sd_check_events() which tries
    to send test_unit_ready() and because of sd_revalidate_disk() trying to
    send another commands the test_unit_ready() might be re-queued as the
    tagged command queuing is disabled.

    So the race condition is -

    Thread 1 | Thread 2
    sd_revalidate_disk() | sd_check_events()
    ...nr_pending = 0 as q->dev = NULL| scsi_queue_insert()
    blk_runtime_pm_init() | blk_pm_requeue_request() ->
    | nr_pending = -1 since
    | q->dev != NULL
    "

    The problem is, the test_unit_ready request doesn't get counted the
    first time it is queued, so the later decrement of q->nr_pending in
    blk_pm_requeue_request makes it unbalanced.

    Fix this by calling blk_pm_runtime_init before add_disk so that all
    requests initiated there will all be counted.

    Signed-off-by: Aaron Lu <aaron.lu@intel.com>
    Reported-and-tested-by: Sujit Reddy Thumma <sthumma@codeaurora.org>
    Signed-off-by: James Bottomley <JBottomley@Parallels.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/scsi/sd.c | 2 +-
    1 file changed, 1 insertion(+), 1 deletion(-)

    --- a/drivers/scsi/sd.c
    +++ b/drivers/scsi/sd.c
    @@ -2843,6 +2843,7 @@ static void sd_probe_async(void *data, a
    gd->events |= DISK_EVENT_MEDIA_CHANGE;
    }

    + blk_pm_runtime_init(sdp->request_queue, dev);
    add_disk(gd);
    if (sdkp->capacity)
    sd_dif_config_host(sdkp);
    @@ -2851,7 +2852,6 @@ static void sd_probe_async(void *data, a

    sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n",
    sdp->removable ? "removable " : "");
    - blk_pm_runtime_init(sdp->request_queue, dev);
    scsi_autopm_put_device(sdp);
    put_device(&sdkp->dev);
    }



    \
     
     \ /
      Last update: 2013-11-09 10:21    [W:4.422 / U:0.136 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site