Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753364AbbLYO1N (ORCPT ); Fri, 25 Dec 2015 09:27:13 -0500 Received: from mail-wm0-f45.google.com ([74.125.82.45]:37734 "EHLO mail-wm0-f45.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752925AbbLYO1H (ORCPT ); Fri, 25 Dec 2015 09:27:07 -0500 From: Rabin Vincent To: axboe@fb.com Cc: linux-kernel@vger.kernel.org, Rabin Vincent Subject: [PATCH] null_blk: don't enable irqs when in irq Date: Fri, 25 Dec 2015 15:26:34 +0100 Message-Id: <1451053594-12188-1-git-send-email-rabin@rab.in> X-Mailer: git-send-email 2.6.2 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3781 Lines: 91 When using irq_mode=NULL_IRQ_TIMER, blk_start_queue() is called from the hrtimer interrupt. null_request_fn() calls spin_unlock_irq() and this causes the following splat from lockdep since interrupts are being enabled while we're in an interrupt handler. When we're in null_request_fn() we can't know the status of the flags saved before blk_start_queue() was called, but we can use in_irq() to conditionally enable interrupts only if we're not in a hard interrupt in order to handle this case. ------------[ cut here ]------------ WARNING: CPU: 0 PID: 398 at kernel/locking/lockdep.c:2608 trace_hardirqs_on_caller+0x11a/0x1b0() DEBUG_LOCKS_WARN_ON(current->hardirq_context) CPU: 0 PID: 398 Comm: mkfs.ext4 Not tainted 4.4.0-rc6+ #77 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Debian-1.8.2-1 04/01/2014 Call Trace: [] dump_stack+0x4e/0x82 [] warn_slowpath_common+0x82/0xc0 [] ? _raw_spin_unlock_irq+0x2c/0x60 [] ? null_softirq_done_fn+0x30/0x30 [] warn_slowpath_fmt+0x4c/0x50 [] trace_hardirqs_on_caller+0x11a/0x1b0 [] trace_hardirqs_on+0xd/0x10 [] _raw_spin_unlock_irq+0x2c/0x60 [] null_request_fn+0x4e/0xb0 [] __blk_run_queue+0x33/0x40 [] blk_start_queue+0x3f/0x80 [] end_cmd+0x117/0x120 [] null_cmd_timer_expired+0x12/0x20 [] __hrtimer_run_queues+0x12b/0x4b0 [] hrtimer_interrupt+0xaf/0x1b0 [] local_apic_timer_interrupt+0x36/0x60 [] smp_apic_timer_interrupt+0x3d/0x50 [] apic_timer_interrupt+0x8c/0xa0 [] ? fprop_fraction_percpu+0xeb/0x110 [] ? __wb_calc_thresh+0x2f/0xc0 [] __wb_calc_thresh+0x2f/0xc0 [] ? domain_dirty_limits+0x1bc/0x1f0 [] balance_dirty_pages_ratelimited+0x6d5/0xfb0 [] ? rcu_read_lock_sched_held+0x77/0x90 [] ? __block_commit_write.isra.1+0x7a/0xb0 [] generic_perform_write+0x14c/0x1c0 [] __generic_file_write_iter+0x190/0x1f0 [] blkdev_write_iter+0x7b/0x100 [] __vfs_write+0xaa/0xe0 [] vfs_write+0x95/0x100 [] ? __fget_light+0x6f/0x90 [] SyS_pwrite64+0x77/0x90 [] entry_SYSCALL_64_fastpath+0x12/0x76 ---[ end trace 39b7df36fb237be1 ]--- Signed-off-by: Rabin Vincent --- drivers/block/null_blk.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/block/null_blk.c b/drivers/block/null_blk.c index a428e4e..d16c5dc 100644 --- a/drivers/block/null_blk.c +++ b/drivers/block/null_blk.c @@ -342,13 +342,20 @@ static int null_rq_prep_fn(struct request_queue *q, struct request *req) static void null_request_fn(struct request_queue *q) { struct request *rq; + bool irq = in_irq(); while ((rq = blk_fetch_request(q)) != NULL) { struct nullb_cmd *cmd = rq->special; - spin_unlock_irq(q->queue_lock); + if (irq) + spin_unlock(q->queue_lock); + else + spin_unlock_irq(q->queue_lock); null_handle_cmd(cmd); - spin_lock_irq(q->queue_lock); + if (irq) + spin_lock(q->queue_lock); + else + spin_lock_irq(q->queue_lock); } } -- 2.6.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/