[Devel] [PATCH RHEL7 COMMIT] blk-cbt: Enable interrupts when unlocking in blk_cbt_update_size()

Konstantin Khorenko khorenko at virtuozzo.com
Fri Mar 3 15:52:04 MSK 2023


The commit is pushed to "branch-rh7-3.10.0-1160.83.1.vz7.194.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-1160.83.1.vz7.194.5
------>
commit c3112aa59c4c452b5d577574c01db064b75c089f
Author: Nikolay Borisov <nikolay.borisov at virtuozzo.com>
Date:   Wed Feb 1 15:22:32 2023 +0200

    blk-cbt: Enable interrupts when unlocking in blk_cbt_update_size()
    
    blk_cbt_update_size() uses spin_lock_irq() to lock the cbt while pages
    are being copied and the new cbt is published at q->cbt.
    
    This lock is used to synchronize against blk_cbt_release(), which can be
    called within softirq context.
    
    Some calltrace from the internet which proves that blk_cbt_release() may be
    called from softirq context:
    
     blk_release_queue+0x90/0xf0
      kobject_cleanup+0x74/0x1cc
       kobject_put+0x5c/0x98
        blk_put_queue+0x20/0x2c
         blkg_free+0xc0/0xe8
          __blkg_release+0x98/0x140
           rcu_do_batch+0x1d4/0x4a4
            rcu_core+0x100/0x2fc
             rcu_core_si+0x1c/0x28
              __do_softirq+0xe8/0x344
    
    blk_cbt_update_size() function requires unlocking be done with
    spin_unlock_irq() so that interrupts are properly reenabled.
    Without this fix the core on which blk_cbt_update_size() run would end
    up with interrupts being disabled.
    
    Fixes: e69ca16f4135 ("cbt: introduce changed block tracking")
    
    Reported-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
    Signed-off-by: Nikolay Borisov <nikolay.borisov at virtuozzo.com>
    Reviewed-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
---
 block/blk-cbt.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/block/blk-cbt.c b/block/blk-cbt.c
index 38ac1e9c0983..a6e1558835f1 100644
--- a/block/blk-cbt.c
+++ b/block/blk-cbt.c
@@ -466,7 +466,7 @@ void blk_cbt_update_size(struct block_device *bdev)
 	}
 	rcu_assign_pointer(q->cbt, new);
 	in_use = cbt->count;
-	spin_unlock(&cbt->lock);
+	spin_unlock_irq(&cbt->lock);
 	if (!in_use)
 		call_rcu(&cbt->rcu, &cbt_release_callback);
 err_mtx:


More information about the Devel mailing list