[3.5.y.z,extended,stable] Patch "block: Don't access request after it might be freed" has been added to staging queue

Submitted by Herton Ronaldo Krzesinski on Dec. 10, 2012, 2:20 p.m.


Message ID 1355149211-9542-1-git-send-email-herton.krzesinski@canonical.com
State New
Headers show

Commit Message

Herton Ronaldo Krzesinski Dec. 10, 2012, 2:20 p.m.
This is a note to let you know that I have just added a patch titled

    block: Don't access request after it might be freed

to the linux-3.5.y-queue branch of the 3.5.y.z extended stable tree 
which can be found at:


If you, or anyone else, feels it should not be added to this tree, please 
reply to this email.

For more information about the 3.5.y.z tree, see



From ee5cf30456f95be755b0e6502132c535903aa89f Mon Sep 17 00:00:00 2001
From: Roland Dreier <roland@purestorage.com>
Date: Thu, 22 Nov 2012 02:00:11 -0800
Subject: [PATCH] block: Don't access request after it might be freed

commit 893d290f1d7496db97c9471bc352ad4a11dc8a25 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>
[ herton: adjust context ]
Signed-off-by: Herton Ronaldo Krzesinski <herton.krzesinski@canonical.com>
 block/blk-exec.c |   10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)


Patch hide | download patch | download mbox

diff --git a/block/blk-exec.c b/block/blk-exec.c
index fb2cbd5..9925fbe 100644
--- a/block/blk-exec.c
+++ b/block/blk-exec.c
@@ -49,8 +49,16 @@  void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk,
 			   rq_end_io_fn *done)
+	bool is_pm_resume;

+	/*
+	 * 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;

 	if (unlikely(blk_queue_dead(q))) {
@@ -66,7 +74,7 @@  void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk,
 	__elv_add_request(q, rq, where);
 	/* the queue is stopped so it won't be run */
-	if (rq->cmd_type == REQ_TYPE_PM_RESUME)
+	if (is_pm_resume)