summaryrefslogtreecommitdiff
path: root/block
diff options
context:
space:
mode:
authorGilad Broner <gbroner@codeaurora.org>2014-12-28 16:50:10 +0200
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-22 11:01:56 -0700
commitddb20cd6f07fd03283b2a28eba323bdb96a06d34 (patch)
tree54ee1495a5d8d52ab0995cd34430cba231b2f78e /block
parent2e5c505a5059f42b081bf6b6d22377c1eb2ab963 (diff)
block: test-iosched: fix spinlock recursion
blk_run_queue() takes the queue spinlock and disabled irqs. Consider the following callstack: blk_run_queue ->__blk_run_queue -> scsi_request_fn -> blk_peek_request -> __elv_next_request -> elevator_dispatch_fn -> test_dispatch_requests -> test_dispatch_from test_dispatch_from() will release the test-iosched spinlock using spin_unlock_irq which will enable interrupts, however, caller is assuming interrupts are disabled. An interrupt can occur now and scsi soft-irq may be scheduled with the following call stack: scsi_softirq_done -> scsi_finish_command -> scsi_device_unbusy scsi_device_unbusy() tries to lock the queue spinlock which was previously locked when blk_run_queue was called, resulting in a spinlock recursion. Change test_dispatch_from() to use the spinlock irq save/restore variants to prevent enabling the irq in case they were previously disabled. Change-Id: Icaea4f9ba54771edb0302c6005047fcc5478ce8d Signed-off-by: Gilad Broner <gbroner@codeaurora.org>
Diffstat (limited to 'block')
-rw-r--r--block/test-iosched.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/block/test-iosched.c b/block/test-iosched.c
index cc7d28c1ba81..9ac5d1441e0b 100644
--- a/block/test-iosched.c
+++ b/block/test-iosched.c
@@ -988,24 +988,25 @@ static int test_dispatch_from(struct request_queue *q,
struct test_request *test_rq;
struct request *rq;
int ret = 0;
+ unsigned long flags;
if (!ptd)
goto err;
- spin_lock_irq(&ptd->lock);
+ spin_lock_irqsave(&ptd->lock, flags);
if (!list_empty(queue)) {
test_rq = list_entry(queue->next, struct test_request,
queuelist);
rq = test_rq->rq;
if (!rq) {
pr_err("%s: null request,return", __func__);
- spin_unlock_irq(&ptd->lock);
+ spin_unlock_irqrestore(&ptd->lock, flags);
goto err;
}
list_move_tail(&test_rq->queuelist, &ptd->dispatched_queue);
ptd->dispatched_count++;
(*count)--;
- spin_unlock_irq(&ptd->lock);
+ spin_unlock_irqrestore(&ptd->lock, flags);
print_req(rq);
elv_dispatch_sort(q, rq);
@@ -1013,7 +1014,7 @@ static int test_dispatch_from(struct request_queue *q,
ret = 1;
goto err;
}
- spin_unlock_irq(&ptd->lock);
+ spin_unlock_irqrestore(&ptd->lock, flags);
err:
return ret;