]> git.ipfire.org Git - thirdparty/kernel/stable.git/commit
SCSI: sd: call blk_pm_runtime_init before add_disk
authorAaron Lu <aaron.lu@intel.com>
Thu, 10 Oct 2013 05:22:36 +0000 (13:22 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 13 Nov 2013 03:08:08 +0000 (12:08 +0900)
commit836a6eec8e00243f10b40b066673e572d690adf7
treec2746ef2c417ebfef51579b8a6727423def96018
parente353d5ce7cc2c6636bde123869e43b3b007708f2
SCSI: sd: call blk_pm_runtime_init before add_disk

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