cbt: bitmap corruption caused by ipi

Submitted by Vasily Averin on Oct. 11, 2018, 1:51 p.m.

Details

Message ID 3ad55cec-cf9b-a070-8c20-4f6e96359c37@virtuozzo.com
State New
Series "cbt: bitmap corruption caused by ipi"
Headers show

Commit Message

Vasily Averin Oct. 11, 2018, 1:51 p.m.
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 <vvs@virtuozzo.com>

Patch hide | download patch | download mbox

diff --git a/block/blk-cbt.c b/block/blk-cbt.c
index 7a4303f720f..7a437356a24 100644
--- a/block/blk-cbt.c
+++ b/block/blk-cbt.c
@@ -177,13 +179,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);