1 ext4: fix hole length detection in ext4_ind_map_blocks()
3 From: Jan Kara <jack@suse.cz>
5 When ext4_ind_map_blocks() computes a length of a hole, it doesn't count
6 with the fact that mapped offset may be somewhere in the middle of the
7 completely empty subtree. In such case it will return too large length
8 of the hole which then results in lseek(SEEK_DATA) to end up returning
9 an incorrect offset beyond the end of the hole.
11 Fix the problem by correctly taking offset within a subtree into account
12 when computing a length of a hole.
14 Fixes: facab4d9711e7aa3532cb82643803e8f1b9518e8
15 CC: stable@vger.kernel.org
16 Reported-by: Jeff Mahoney <jeffm@suse.com>
17 Signed-off-by: Jan Kara <jack@suse.cz>
18 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
20 fs/ext4/indirect.c | 14 ++++++++++----
21 1 file changed, 10 insertions(+), 4 deletions(-)
23 I'll submit corresponding fstest shortly.
25 diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
26 index c32802c956d5..bf7fa1507e81 100644
27 --- a/fs/ext4/indirect.c
28 +++ b/fs/ext4/indirect.c
29 @@ -561,10 +561,16 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
30 unsigned epb = inode->i_sb->s_blocksize / sizeof(u32);
33 - /* Count number blocks in a subtree under 'partial' */
35 - for (i = 0; partial + i != chain + depth - 1; i++)
38 + * Count number blocks in a subtree under 'partial'. At each
39 + * level we count number of complete empty subtrees beyond
40 + * current offset and then descend into the subtree only
41 + * partially beyond current offset.
44 + for (i = partial - chain + 1; i < depth; i++)
45 + count = count * epb + (epb - offsets[i] - 1);
47 /* Fill in size of a hole we found */
49 map->m_len = min_t(unsigned int, map->m_len, count);