Commit 10c580e4 authored by Aaron Lu's avatar Aaron Lu Committed by James Bottomley

[SCSI] sd: call blk_pm_runtime_init before add_disk

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: default avatarAaron Lu <aaron.lu@intel.com>
Reported-and-tested-by: default avatarSujit Reddy Thumma <sthumma@codeaurora.org>
Cc: stable@vger.kernel.org
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 36008cf1
...@@ -2854,6 +2854,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie) ...@@ -2854,6 +2854,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie)
gd->events |= DISK_EVENT_MEDIA_CHANGE; gd->events |= DISK_EVENT_MEDIA_CHANGE;
} }
blk_pm_runtime_init(sdp->request_queue, dev);
add_disk(gd); add_disk(gd);
if (sdkp->capacity) if (sdkp->capacity)
sd_dif_config_host(sdkp); sd_dif_config_host(sdkp);
...@@ -2862,7 +2863,6 @@ static void sd_probe_async(void *data, async_cookie_t cookie) ...@@ -2862,7 +2863,6 @@ static void sd_probe_async(void *data, async_cookie_t cookie)
sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n", sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n",
sdp->removable ? "removable " : ""); sdp->removable ? "removable " : "");
blk_pm_runtime_init(sdp->request_queue, dev);
scsi_autopm_put_device(sdp); scsi_autopm_put_device(sdp);
put_device(&sdkp->dev); put_device(&sdkp->dev);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment