Skip to content

Commit 10809df

Browse files
committed
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: Theodore Ts'o <[email protected]>
1 parent b7ea89a commit 10809df

File tree

2 files changed

+11
-10
lines changed

2 files changed

+11
-10
lines changed

fs/ext4/ext4_extents.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ find_ext4_extent_tail(struct ext4_extent_header *eh)
123123
struct ext4_ext_path {
124124
ext4_fsblk_t p_block;
125125
__u16 p_depth;
126+
__u16 p_maxdepth;
126127
struct ext4_extent *p_ext;
127128
struct ext4_extent_idx *p_idx;
128129
struct ext4_extent_header *p_hdr;

fs/ext4/extents.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -869,14 +869,20 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
869869
eh = ext_inode_hdr(inode);
870870
depth = ext_depth(inode);
871871

872-
if (path)
872+
if (path) {
873873
ext4_ext_drop_refs(path);
874-
else {
874+
if (depth > path[0].p_maxdepth) {
875+
kfree(path);
876+
*orig_path = path = NULL;
877+
}
878+
}
879+
if (!path) {
875880
/* account possible depth increase */
876881
path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 2),
877882
GFP_NOFS);
878883
if (unlikely(!path))
879884
return ERR_PTR(-ENOMEM);
885+
path[0].p_maxdepth = depth + 1;
880886
}
881887
path[0].p_hdr = eh;
882888
path[0].p_bh = NULL;
@@ -1820,6 +1826,7 @@ static void ext4_ext_try_to_merge_up(handle_t *handle,
18201826
sizeof(struct ext4_extent_idx);
18211827
s += sizeof(struct ext4_extent_header);
18221828

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

2153-
if (path && ext_depth(inode) != depth) {
2154-
/* depth was changed. we have to realloc path */
2155-
kfree(path);
2156-
path = NULL;
2157-
}
2158-
21592160
path = ext4_ext_find_extent(inode, block, &path, 0);
21602161
if (IS_ERR(path)) {
21612162
up_read(&EXT4_I(inode)->i_data_sem);
@@ -2173,7 +2174,6 @@ static int ext4_fill_fiemap_extents(struct inode *inode,
21732174
}
21742175
ex = path[depth].p_ext;
21752176
next = ext4_ext_next_allocated_block(path);
2176-
ext4_ext_drop_refs(path);
21772177

21782178
flags = 0;
21792179
exists = 0;
@@ -2897,7 +2897,7 @@ int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start,
28972897
ext4_journal_stop(handle);
28982898
return -ENOMEM;
28992899
}
2900-
path[0].p_depth = depth;
2900+
path[0].p_maxdepth = path[0].p_depth = depth;
29012901
path[0].p_hdr = ext_inode_hdr(inode);
29022902
i = 0;
29032903

0 commit comments

Comments
 (0)