Skip to content

Commit

Permalink
ext4: fix hole length detection in ext4_ind_map_blocks()
Browse files Browse the repository at this point in the history
When ext4_ind_map_blocks() computes a length of a hole, it doesn't count
with the fact that mapped offset may be somewhere in the middle of the
completely empty subtree. In such case it will return too large length
of the hole which then results in lseek(SEEK_DATA) to end up returning
an incorrect offset beyond the end of the hole.

Fix the problem by correctly taking offset within a subtree into account
when computing a length of a hole.

Fixes: facab4d
CC: stable@vger.kernel.org
Reported-by: Jeff Mahoney <jeffm@suse.com>
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
  • Loading branch information
jankara authored and tytso committed May 12, 2018
1 parent 736dedb commit 2ee3ee0
Showing 1 changed file with 10 additions and 4 deletions.
14 changes: 10 additions & 4 deletions fs/ext4/indirect.c
Original file line number Diff line number Diff line change
Expand Up @@ -561,10 +561,16 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
unsigned epb = inode->i_sb->s_blocksize / sizeof(u32);
int i;

/* Count number blocks in a subtree under 'partial' */
count = 1;
for (i = 0; partial + i != chain + depth - 1; i++)
count *= epb;
/*
* Count number blocks in a subtree under 'partial'. At each
* level we count number of complete empty subtrees beyond
* current offset and then descend into the subtree only
* partially beyond current offset.
*/
count = 0;
for (i = partial - chain + 1; i < depth; i++)
count = count * epb + (epb - offsets[i] - 1);
count++;
/* Fill in size of a hole we found */
map->m_pblk = 0;
map->m_len = min_t(unsigned int, map->m_len, count);
Expand Down

0 comments on commit 2ee3ee0

Please sign in to comment.