From: Tejun Heo Date: Thu, 3 Nov 2011 17:52:11 +0000 (+0100) Subject: block: don't call blk_drain_queue() if elevator is not up X-Git-Tag: upstream/snapshot3+hdmi~8809^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6dd9ad7df2019b1e33a372a501907db293ebcd0d;p=platform%2Fadaptation%2Frenesas_rcar%2Frenesas_kernel.git block: don't call blk_drain_queue() if elevator is not up blk_cleanup_queue() may be called before elevator is set up on a queue which triggers the following oops. BUG: unable to handle kernel NULL pointer dereference at (null) IP: [] elv_drain_elevator+0x1c/0x70 ... Pid: 830, comm: kworker/0:2 Not tainted 3.1.0-next-20111025_64+ #1590 Bochs Bochs RIP: 0010:[] [] elv_drain_elevator+0x1c/0x70 ... Call Trace: [] blk_drain_queue+0x42/0x70 [] blk_cleanup_queue+0xd0/0x1c0 [] md_free+0x50/0x70 [] kobject_release+0x8b/0x1d0 [] kref_put+0x36/0xa0 [] kobject_put+0x27/0x60 [] mddev_delayed_delete+0x2f/0x40 [] process_one_work+0x100/0x3b0 [] worker_thread+0x15f/0x3a0 [] kthread+0x87/0x90 [] kernel_thread_helper+0x4/0x10 Fix it by making blk_cleanup_queue() check whether q->elevator is set up before invoking blk_drain_queue. Signed-off-by: Tejun Heo Reported-and-tested-by: Jiri Slaby Signed-off-by: Jens Axboe --- diff --git a/block/blk-core.c b/block/blk-core.c index f658711..f43c8a5 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -407,8 +407,13 @@ void blk_cleanup_queue(struct request_queue *q) spin_unlock_irq(lock); mutex_unlock(&q->sysfs_lock); - /* drain all requests queued before DEAD marking */ - blk_drain_queue(q, true); + /* + * Drain all requests queued before DEAD marking. The caller might + * be trying to tear down @q before its elevator is initialized, in + * which case we don't want to call into draining. + */ + if (q->elevator) + blk_drain_queue(q, true); /* @q won't process any more request, flush async actions */ del_timer_sync(&q->backing_dev_info.laptop_mode_wb_timer);