Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 10809df8 authored by Theodore Ts'o's avatar Theodore Ts'o
Browse files

ext4: teach ext4_ext_find_extent() to realloc path if necessary



This adds additional safety in case for some reason we end reusing a
path structure which isn't big enough for current depth of the inode.

Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
parent b7ea89ad
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -123,6 +123,7 @@ find_ext4_extent_tail(struct ext4_extent_header *eh)
struct ext4_ext_path {
	ext4_fsblk_t			p_block;
	__u16				p_depth;
	__u16				p_maxdepth;
	struct ext4_extent		*p_ext;
	struct ext4_extent_idx		*p_idx;
	struct ext4_extent_header	*p_hdr;
+10 −10
Original line number Diff line number Diff line
@@ -869,14 +869,20 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
	eh = ext_inode_hdr(inode);
	depth = ext_depth(inode);

	if (path)
	if (path) {
		ext4_ext_drop_refs(path);
	else {
		if (depth > path[0].p_maxdepth) {
			kfree(path);
			*orig_path = path = NULL;
		}
	}
	if (!path) {
		/* account possible depth increase */
		path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 2),
				GFP_NOFS);
		if (unlikely(!path))
			return ERR_PTR(-ENOMEM);
		path[0].p_maxdepth = depth + 1;
	}
	path[0].p_hdr = eh;
	path[0].p_bh = NULL;
@@ -1820,6 +1826,7 @@ static void ext4_ext_try_to_merge_up(handle_t *handle,
		sizeof(struct ext4_extent_idx);
	s += sizeof(struct ext4_extent_header);

	path[1].p_maxdepth = path[0].p_maxdepth;
	memcpy(path[0].p_hdr, path[1].p_hdr, s);
	path[0].p_depth = 0;
	path[0].p_ext = EXT_FIRST_EXTENT(path[0].p_hdr) +
@@ -2150,12 +2157,6 @@ static int ext4_fill_fiemap_extents(struct inode *inode,
		/* find extent for this block */
		down_read(&EXT4_I(inode)->i_data_sem);

		if (path && ext_depth(inode) != depth) {
			/* depth was changed. we have to realloc path */
			kfree(path);
			path = NULL;
		}

		path = ext4_ext_find_extent(inode, block, &path, 0);
		if (IS_ERR(path)) {
			up_read(&EXT4_I(inode)->i_data_sem);
@@ -2173,7 +2174,6 @@ static int ext4_fill_fiemap_extents(struct inode *inode,
		}
		ex = path[depth].p_ext;
		next = ext4_ext_next_allocated_block(path);
		ext4_ext_drop_refs(path);

		flags = 0;
		exists = 0;
@@ -2897,7 +2897,7 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
			ext4_journal_stop(handle);
			return -ENOMEM;
		}
		path[0].p_depth = depth;
		path[0].p_maxdepth = path[0].p_depth = depth;
		path[0].p_hdr = ext_inode_hdr(inode);
		i = 0;