hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IB5UKT
--------------------------------
When mounting an erofs image locally with a chunk layout as below, inconsistent data may be read:
mkfs.erofs -E noinline_data test-plain.img /tmp/stress/ mkfs.erofs --chunksize=1048576 test-chunk-array.img /tmp/stress/ mount -o loop -t erofs test-plain.img mnt-plain mount -o loop -t erofs test-chunk-array.img mnt-array diff mnt-array/lib/compress.c mnt-plain/lib/compress.c // The output is non-empty, so the two files are inconsistent.
This is because erofs_read_raw_page() doesn't take current_block offset into account when calculating blknr, so it will take the first block of the map as the currently read block, resulting in data inconsistency, correct the blknr calculation logic to fix the problem.
Signed-off-by: Baokun Li libaokun1@huawei.com --- fs/erofs/data.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/fs/erofs/data.c b/fs/erofs/data.c index 44fea7bf7bb8..e228a2d52aaf 100644 --- a/fs/erofs/data.c +++ b/fs/erofs/data.c @@ -269,6 +269,7 @@ static inline struct bio *erofs_read_raw_page(struct bio *bio, struct inode *const inode = mapping->host; struct super_block *const sb = inode->i_sb; erofs_off_t current_block = (erofs_off_t)page->index; + erofs_off_t pos = blknr_to_addr(current_block); int err;
DBG_BUGON(!nblocks); @@ -289,7 +290,7 @@ static inline struct bio *erofs_read_raw_page(struct bio *bio,
if (!bio) { struct erofs_map_blocks map = { - .m_la = blknr_to_addr(current_block), + .m_la = pos, }; struct erofs_map_dev mdev; erofs_blk_t blknr; @@ -319,8 +320,8 @@ static inline struct bio *erofs_read_raw_page(struct bio *bio, /* for RAW access mode, m_plen must be equal to m_llen */ DBG_BUGON(map.m_plen != map.m_llen);
- blknr = erofs_blknr(mdev.m_pa); - blkoff = erofs_blkoff(mdev.m_pa); + blknr = erofs_blknr(mdev.m_pa + (pos - map.m_la)); + blkoff = erofs_blkoff(mdev.m_pa + (pos - map.m_la));
/* deal with inline page */ if (map.m_flags & EROFS_MAP_META) {