From: Ana Bobillo <[email protected]> In the triple indirect branch, read_allocated_block() reads the third level block from ext4fs_indir2_block[(rblock / perblock_child) % (blksz / 4)] and records it in ext4fs_indir3_blkno, but it decides whether that cached block can be reused by comparing against ext4fs_indir2_block[rblock / perblock_child], without the modulo.
For a file block reached through the second or a later entry of the triple indirect block (rblock >= (blksz / 4) * (blksz / 4)), rblock / perblock_child is at least blksz / 4, so the compare reads past the end of the blksz-byte ext4fs_indir2_block buffer and can make the lookup reuse the wrong cached block. Use the same index for the compare as for the read. Signed-off-by: Ana Bobillo <[email protected]> Reviewed-by: Simon Glass <[email protected]> --- (no changes since v1) fs/ext4/ext4_common.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c index 3aab1c87233..cff112fb99b 100644 --- a/fs/ext4/ext4_common.c +++ b/fs/ext4/ext4_common.c @@ -2008,9 +2008,9 @@ long int read_allocated_block(struct ext2_inode *inode, int fileblock, } ext4fs_indir3_size = blksz; } - if ((le32_to_cpu(ext4fs_indir2_block[rblock - / - perblock_child]) << + if ((le32_to_cpu(ext4fs_indir2_block[(rblock / + perblock_child) % + (blksz / 4)]) << log2_blksz) != ext4fs_indir3_blkno) { status = ext4fs_devread((lbaint_t)le32_to_cpu
