[Devel] [PATCH RHEL7 COMMIT] cbt: bitmap corruption caused by ipi
Konstantin Khorenko
khorenko at virtuozzo.com
Thu Oct 18 16:21:31 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 0a074588bfb8663fe52216edf9052181d38880b0
Author: Vasily Averin <vvs at 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 <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 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);
More information about the Devel
mailing list