Commit 43759903 authored by Baokun Li's avatar Baokun Li
Browse files

erofs: correct the blknr/blkoff calculation in erofs_read_raw_page()

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: default avatarBaokun Li <libaokun1@huawei.com>
parent 51eda068
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -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) {