[Devel] [PATCH RHEL7 COMMIT] cbt: selfdeadlock in __blk_cbt_set()

Konstantin Khorenko khorenko at virtuozzo.com
Thu Oct 18 16:21:32 MSK 2018


The commit is pushed to "branch-rh7-3.10.0-862.14.4.vz7.72.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-862.14.4.vz7.72.11
------>
commit 1f18342799a428b1f9a7c1b19b3de93657aed059
Author: Vasily Averin <vvs at virtuozzo.com>
Date:   Thu Oct 18 16:21:30 2018 +0300

    cbt: selfdeadlock in __blk_cbt_set()
    
    __blk_cbt_set() can be interrupted by IPI __cbt_flush_cpu_cache()
    that will be cycled forever in spin_lock_page()
    because page was already locked by interrupted process.
    
     #5 [ffff880071e89f50] nmi at ffffffff81569781
        [exception RIP: __blk_cbt_set+133]
        RIP: ffffffff812b1a35  RSP: ffff880071e83ef8  RFLAGS: 00000087
        RAX: 0000000000000001  RBX: 00000000004a0020  RCX: 00000000ffffffff
        RDX: 0000000000000020  RSI: 00000000004a0020  RDI: ffffea007d13d9c0
        RBP: ffff880071e83f38   R8: 0000000000fa0001   R9: 00000000ffffffff
        R10: 0000000000000008  R11: 0000000000000044  R12: ffff880f0b08cbc0
        R13: 0000000000000001  R14: 0000000000000001  R15: 0000000000000094
        ORIG_RAX: ffffffffffffffff  CS: 0010  SS: 0018
        --- <NMI exception stack> ---
     #6 [ffff880071e83ef8] __blk_cbt_set at ffffffff812b1a35
     #7 [ffff880071e83f40] __cbt_flush_cpu_cache at ffffffff812b1c92
     #8 [ffff880071e83f60] generic_smp_call_function_interrupt at ffffffff810dab72
     #9 [ffff880071e83fa0] smp_call_function_interrupt at ffffffff8103950d
    #10 [ffff880071e83fb0] call_function_interrupt at ffffffff81571423
        --- <IRQ stack> ---
    #11 [ffff88101045f678] call_function_interrupt at ffffffff81571423
        [exception RIP: __blk_cbt_set+297]
        RIP: ffffffff812b1ad9  RSP: ffff88101045f720  RFLAGS: 00000202
        RAX: 0000000000000002  RBX: ffff88101045f760  RCX: ffff881f44f67000
        RDX: 000000000000001f  RSI: 0000000000000021  RDI: ffffea007d13d9c0
        RBP: ffffffff8157141e   R8: 0000000000fa0001   R9: 00000000ffffffff
        R10: 0000000000000008  R11: 0000000000000044  R12: 0000000000000086
        R13: ffff8810697ac158  R14: ffff88101045f6b0  R15: 0000000100000001
        ORIG_RAX: ffffffffffffff03  CS: 0010  SS: 0018
    #12 [ffff88101045f768] blk_cbt_bio_queue at ffffffff812b1d59
    #13 [ffff88101045f778] generic_make_request at ffffffff8129412d
    #14 [ffff88101045f838] submit_bio at ffffffff812944e1
    #15 [ffff88101045f8a8] submit_bh at ffffffff81202f9d
        ...
    
    Patch disables interrupts before access to spin_lock_page().
    
    v2: Kirill Tkhai pointed that interrupt handler should not enable interrupts,
    and we need to use safe local_irq_save/restore()
    
    https://jira.sw.ru/browse/PSBM-89323
    Signed-off-by: Vasily Averin <vvs at virtuozzo.com>
---
 block/blk-cbt.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/block/blk-cbt.c b/block/blk-cbt.c
index 0b5a8c165298..5c58bd72adba 100644
--- a/block/blk-cbt.c
+++ b/block/blk-cbt.c
@@ -169,12 +169,15 @@ static int __blk_cbt_set(struct cbt_info  *cbt, blkcnt_t block,
 		unsigned long len = min_t(unsigned long, BITS_PER_PAGE - off,
 					  count);
 		int ret;
+		unsigned long flags;
 
 		page = CBT_PAGE(cbt, idx);
 		if (page) {
+			local_irq_save(flags);
 			spin_lock_page(page);
 			set_bits(page_address(page), off, len, set);
 			unlock_page(page);
+			local_irq_restore(flags);
 			count -= len;
 			block += len;
 			continue;



More information about the Devel mailing list