From: Jan Kara Date: Thu, 26 Jun 2014 16:30:54 +0000 (-0400) Subject: ext4: Fix hole punching for files with indirect blocks X-Git-Tag: v4.9.8~6162^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a93cd4cf86466caa49cfe64607bea7f0bde3f916;p=platform%2Fkernel%2Flinux-rpi3.git ext4: Fix hole punching for files with indirect blocks Hole punching code for files with indirect blocks wrongly computed number of blocks which need to be cleared when traversing the indirect block tree. That could result in punching more blocks than actually requested and thus effectively cause a data loss. For example: fallocate -n -p 10240000 4096 will punch the range 10240000 - 12632064 instead of the range 1024000 - 10244096. Fix the calculation. CC: stable@vger.kernel.org Fixes: 8bad6fc813a3a5300f51369c39d315679fd88c72 Signed-off-by: Jan Kara Signed-off-by: Theodore Ts'o --- diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c index 6f3bb55..fd69da1 100644 --- a/fs/ext4/indirect.c +++ b/fs/ext4/indirect.c @@ -1316,16 +1316,24 @@ static int free_hole_blocks(handle_t *handle, struct inode *inode, blk = *i_data; if (level > 0) { ext4_lblk_t first2; + ext4_lblk_t count2; + bh = sb_bread(inode->i_sb, le32_to_cpu(blk)); if (!bh) { EXT4_ERROR_INODE_BLOCK(inode, le32_to_cpu(blk), "Read failure"); return -EIO; } - first2 = (first > offset) ? first - offset : 0; + if (first > offset) { + first2 = first - offset; + count2 = count; + } else { + first2 = 0; + count2 = count - (offset - first); + } ret = free_hole_blocks(handle, inode, bh, (__le32 *)bh->b_data, level - 1, - first2, count - offset, + first2, count2, inode->i_sb->s_blocksize >> 2); if (ret) { brelse(bh);