mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
block: Don't access request after it might be freed
commit 893d290f1d
upstream.
After we've done __elv_add_request() and __blk_run_queue() in
blk_execute_rq_nowait(), the request might finish and be freed
immediately. Therefore checking if the type is REQ_TYPE_PM_RESUME
isn't safe afterwards, because if it isn't, rq might be gone.
Instead, check beforehand and stash the result in a temporary.
This fixes crashes in blk_execute_rq_nowait() I get occasionally when
running with lots of memory debugging options enabled -- I think this
race is usually harmless because the window for rq to be reallocated
is so small.
Signed-off-by: Roland Dreier <roland@purestorage.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
[xr: Backported to 3.4: adjust context]
Signed-off-by: Rui Xiang <rui.xiang@huawei.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
50e97121b7
commit
0ef4c881e4
1 changed files with 11 additions and 1 deletions
|
@ -49,8 +49,18 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk,
|
||||||
rq_end_io_fn *done)
|
rq_end_io_fn *done)
|
||||||
{
|
{
|
||||||
int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK;
|
int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK;
|
||||||
|
bool is_pm_resume;
|
||||||
|
|
||||||
WARN_ON(irqs_disabled());
|
WARN_ON(irqs_disabled());
|
||||||
|
|
||||||
|
rq->rq_disk = bd_disk;
|
||||||
|
rq->end_io = done;
|
||||||
|
/*
|
||||||
|
* need to check this before __blk_run_queue(), because rq can
|
||||||
|
* be freed before that returns.
|
||||||
|
*/
|
||||||
|
is_pm_resume = rq->cmd_type == REQ_TYPE_PM_RESUME;
|
||||||
|
|
||||||
spin_lock_irq(q->queue_lock);
|
spin_lock_irq(q->queue_lock);
|
||||||
|
|
||||||
if (unlikely(blk_queue_dead(q))) {
|
if (unlikely(blk_queue_dead(q))) {
|
||||||
|
@ -66,7 +76,7 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk,
|
||||||
__elv_add_request(q, rq, where);
|
__elv_add_request(q, rq, where);
|
||||||
__blk_run_queue(q);
|
__blk_run_queue(q);
|
||||||
/* the queue is stopped so it won't be run */
|
/* the queue is stopped so it won't be run */
|
||||||
if (rq->cmd_type == REQ_TYPE_PM_RESUME)
|
if (is_pm_resume)
|
||||||
q->request_fn(q);
|
q->request_fn(q);
|
||||||
spin_unlock_irq(q->queue_lock);
|
spin_unlock_irq(q->queue_lock);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue