Skip to content

Commit 2ee3ee0

Browse files
jankaratytso
authored andcommitted
ext4: fix hole length detection in ext4_ind_map_blocks()
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: [email protected] Reported-by: Jeff Mahoney <[email protected]> Signed-off-by: Jan Kara <[email protected]> Signed-off-by: Theodore Ts'o <[email protected]>
1 parent 736dedb commit 2ee3ee0

File tree

1 file changed

+10
-4
lines changed

1 file changed

+10
-4
lines changed

fs/ext4/indirect.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -561,10 +561,16 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
561561
unsigned epb = inode->i_sb->s_blocksize / sizeof(u32);
562562
int i;
563563

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

0 commit comments

Comments
 (0)