From: Li Ruilin liruilin4@huawei.com
euleros inclusion category: feature bugzilla: https://bugzilla.openeuler.org/show_bug.cgi?id=26 CVE: NA
------------------------------
In writearound cache mode, read request quickly followed by write request may overwrite the invalidate bkey inserted by the write request.
The function bch_data_insert() is invoked asynchronously as the bio subbmited to backend block device, therefore there may be a read request subbmited after the bch_data_insert() done and ended before the backend bio is end. This read request will read data from the backend block device, and insert dirty data to cache device. However by writearound cache mode, bcache will not invalidate data again, so that read request after will read dirty data from the cache, causing a data corruption.
By this patch we delay the invalidation to end of backend bio to avoid this corruption.
Signed-off-by: Li Ruilin liruilin4@huawei.com Reviewed-by: Luan Jianhai luanjianhai@huawei.com Reviewed-by: Peng Junyi pengjunyi1@huawei.com Acked-by: Xie Xiuqi xiexiuqi@huawei.com Signed-off-by: Cheng Jian cj.chengjian@huawei.com --- drivers/md/bcache/request.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c index 7eff3c6cf0f1..18c8e5baa011 100644 --- a/drivers/md/bcache/request.c +++ b/drivers/md/bcache/request.c @@ -993,8 +993,11 @@ static void cached_dev_write_complete(struct closure *cl) struct search *s = container_of(cl, struct search, cl); struct cached_dev *dc = container_of(s->d, struct cached_dev, disk);
+ if (!s->iop.bypass) + closure_call(&s->iop.cl, bch_data_insert, NULL, cl); + up_read_non_owner(&dc->writeback_lock); - cached_dev_bio_complete(cl); + continue_at(cl, cached_dev_bio_complete, NULL); }
static void cached_dev_write(struct cached_dev *dc, struct search *s) @@ -1077,7 +1080,8 @@ static void cached_dev_write(struct cached_dev *dc, struct search *s) }
insert_data: - closure_call(&s->iop.cl, bch_data_insert, NULL, cl); + if (!s->iop.bypass) + closure_call(&s->iop.cl, bch_data_insert, NULL, cl); continue_at(cl, cached_dev_write_complete, NULL); }