3.10-stable review patch.  If anyone has any objections, please let me know.

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

From: Aaron Lu <aaron...@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...@intel.com>
Reported-and-tested-by: Sujit Reddy Thumma <sthu...@codeaurora.org>
Signed-off-by: James Bottomley <jbottom...@parallels.com>
Signed-off-by: Greg Kroah-Hartman <gre...@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);
 }


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to