add patch report-delalloc-reserve-as-non-free-in-statfs-for-project-quota
[ext4-patch-queue.git] / fix-hole-length-detectin-in-ext4_ind_map_blocks
blobd00d1388af2c653737578fe66c96de846c0ed1bb
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>
19 ---
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);
31                 int i;
33 -               /* Count number blocks in a subtree under 'partial' */
34 -               count = 1;
35 -               for (i = 0; partial + i != chain + depth - 1; i++)
36 -                       count *= epb;
37 +               /*
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.
42 +                */
43 +               count = 0;
44 +               for (i = partial - chain + 1; i < depth; i++)
45 +                       count = count * epb + (epb - offsets[i] - 1);
46 +               count++;
47                 /* Fill in size of a hole we found */
48                 map->m_pblk = 0;
49                 map->m_len = min_t(unsigned int, map->m_len, count);
50 -- 
51 2.13.6