>From 44985e4b2f3124bf87e84a4c7572efa00ac28d3b Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Wed, 23 Mar 2016 17:14:57 -0700 Subject: [PATCH 3/4] block: Limit work processed in softirq context Avoid that complaints like the one below are reported against a debug kernel: NMI watchdog: BUG: soft lockup - CPU#1 stuck for 22s! [disk11_0:2708] irq event stamp: 17120809 hardirqs last enabled at (17120808): [] _raw_spin_unlock_irqrestore+0x31/0x50 hardirqs last disabled at (17120809): [] 0xffff88046f223bd0 softirqs last enabled at (17120794): [] scst_check_blocked_dev+0x77/0x1c0 [scst] softirqs last disabled at (17120795): [] do_softirq_own_stack+0x1c/0x30 RIP: 0010:[] [] _raw_spin_unlock_irqrestore+0x33/0x50 Call Trace: [] free_debug_processing+0x270/0x3a0 [] __slab_free+0x17a/0x2c0 [] kmem_cache_free+0x1b4/0x1d0 [] mempool_free_slab+0x12/0x20 [] mempool_free+0x26/0x80 [] bio_free+0x49/0x60 [] bio_put+0x1e/0x30 [] end_clone_bio+0x21/0x70 [dm_mod] [] bio_endio+0x52/0x60 [] blk_update_request+0x7c/0x2a0 [] scsi_end_request+0x2e/0x1d0 [] scsi_io_completion+0xb4/0x610 [] scsi_finish_command+0xca/0x120 [] scsi_softirq_done+0x120/0x140 [] blk_done_softirq+0x76/0x90 [] __do_softirq+0x10f/0x230 [] do_softirq_own_stack+0x1c/0x30 --- block/blk-softirq.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/block/blk-softirq.c b/block/blk-softirq.c index 53b1737..d739949 100644 --- a/block/blk-softirq.c +++ b/block/blk-softirq.c @@ -20,20 +20,26 @@ static DEFINE_PER_CPU(struct list_head, blk_cpu_done); */ static void blk_done_softirq(struct softirq_action *h) { - struct list_head *cpu_list, local_list; + struct list_head *cpu_list = this_cpu_ptr(&blk_cpu_done); + struct request *rq; + int i; local_irq_disable(); - cpu_list = this_cpu_ptr(&blk_cpu_done); - list_replace_init(cpu_list, &local_list); - local_irq_enable(); - - while (!list_empty(&local_list)) { - struct request *rq; - - rq = list_entry(local_list.next, struct request, ipi_list); + for (i = 64; i > 0; i--) { + if (list_empty(cpu_list)) + goto done; + rq = list_first_entry(cpu_list, struct request, ipi_list); list_del_init(&rq->ipi_list); + local_irq_enable(); + rq->q->softirq_done_fn(rq); + + local_irq_disable(); } + raise_softirq_irqoff(BLOCK_SOFTIRQ); + +done: + local_irq_enable(); } #ifdef CONFIG_SMP -- 2.7.3