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 0a074588bfb8663fe52216edf9052181d38880b0
Author: Vasily Averin <v...@virtuozzo.com>
Date:   Thu Oct 18 16:21:29 2018 +0300

    cbt: bitmap corruption caused by ipi
    
    IPI generated by cbt_flush_cache() can interrupt blk_cbt_add() in "bad" 
places
    and lead to bitmap corruption.
    
    CPU A                       CPU B
    blk_cbt_add()
    ...                         cbt_flush_cache()
       old = *ex;                submit IPI
       ex->start = start;
    
    interrupt
      __cbt_flush_cpu_cache
       if (ex->len)   <<< found non-changed len
         __blk_cbt_set(cbt, ex->start, ex->len, 0, 1); <<< set wrong bitmask
         ex->start += ex->len; <<< incorrectly adjusts ex->start
         ex->len = 0;
    return from interrupt back to blk_cbt_add()
       ex->len = len;   <<< set len and get wrong bitmask
    (because ex->start was changed in __cbt_flush_cpu_cache)
    
    Similar problem happens if IPI will be processed in middle of following 
block in blk_cbt_add()
    
            if (ex->start + ex->len == start) {
                    ex->len += len;
                    goto out_rcu;
            }
    
    Patch disables interrupts in specified places.
    
    https://jira.sw.ru/browse/PSBM-89323
    Signed-off-by: Vasily Averin <v...@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 d83ee9e5a44a..0b5a8c165298 100644
--- a/block/blk-cbt.c
+++ b/block/blk-cbt.c
@@ -229,13 +229,16 @@ static void blk_cbt_add(struct request_queue *q, blkcnt_t 
start, blkcnt_t len)
                goto out_rcu;
        }
        ex = this_cpu_ptr(cbt->cache);
+       local_irq_disable();
        if (ex->start + ex->len == start) {
                ex->len += len;
+               local_irq_enable();
                goto out_rcu;
        }
        old = *ex;
        ex->start = start;
        ex->len = len;
+       local_irq_enable();
 
        if (likely(old.len))
                __blk_cbt_set(cbt, old.start, old.len, 1, 1, NULL, NULL);

_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

Reply via email to