add patch get-rid-of-code-duplication
[ext4-patch-queue.git] / teach-ext4_ext_find_extent-to-realloc-path-if-necessary
blob0645ade0780e84ceee6075dd1614e4c49980e85e
1 ext4: teach ext4_ext_find_extent() to realloc path if necessary
3 This adds additional safety in case for some reason we end reusing a
4 path structure which isn't big enough for current depth of the inode.
6 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
7 diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h
8 index a867f5c..3c93815 100644
9 --- a/fs/ext4/ext4_extents.h
10 +++ b/fs/ext4/ext4_extents.h
11 @@ -123,6 +123,7 @@ find_ext4_extent_tail(struct ext4_extent_header *eh)
12  struct ext4_ext_path {
13         ext4_fsblk_t                    p_block;
14         __u16                           p_depth;
15 +       __u16                           p_maxdepth;
16         struct ext4_extent              *p_ext;
17         struct ext4_extent_idx          *p_idx;
18         struct ext4_extent_header       *p_hdr;
19 diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
20 index d3fe3b2..ecd86e0 100644
21 --- a/fs/ext4/extents.c
22 +++ b/fs/ext4/extents.c
23 @@ -861,14 +861,20 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
24         eh = ext_inode_hdr(inode);
25         depth = ext_depth(inode);
27 -       if (path)
28 +       if (path) {
29                 ext4_ext_drop_refs(path);
30 -       else {
31 +               if (depth > path[0].p_maxdepth) {
32 +                       kfree(path);
33 +                       *orig_path = path = NULL;
34 +               }
35 +       }
36 +       if (!path) {
37                 /* account possible depth increase */
38                 path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 2),
39                                 GFP_NOFS);
40                 if (unlikely(!path))
41                         return ERR_PTR(-ENOMEM);
42 +               path[0].p_maxdepth = depth + 1;
43         }
44         path[0].p_hdr = eh;
45         path[0].p_bh = NULL;
46 @@ -1812,6 +1818,7 @@ static void ext4_ext_try_to_merge_up(handle_t *handle,
47                 sizeof(struct ext4_extent_idx);
48         s += sizeof(struct ext4_extent_header);
50 +       path[1].p_maxdepth = path[0].p_maxdepth;
51         memcpy(path[0].p_hdr, path[1].p_hdr, s);
52         path[0].p_depth = 0;
53         path[0].p_ext = EXT_FIRST_EXTENT(path[0].p_hdr) +
54 @@ -2142,12 +2149,6 @@ static int ext4_fill_fiemap_extents(struct inode *inode,
55                 /* find extent for this block */
56                 down_read(&EXT4_I(inode)->i_data_sem);
58 -               if (path && ext_depth(inode) != depth) {
59 -                       /* depth was changed. we have to realloc path */
60 -                       kfree(path);
61 -                       path = NULL;
62 -               }
64                 path = ext4_ext_find_extent(inode, block, &path, 0);
65                 if (IS_ERR(path)) {
66                         up_read(&EXT4_I(inode)->i_data_sem);
67 @@ -2165,7 +2166,6 @@ static int ext4_fill_fiemap_extents(struct inode *inode,
68                 }
69                 ex = path[depth].p_ext;
70                 next = ext4_ext_next_allocated_block(path);
71 -               ext4_ext_drop_refs(path);
73                 flags = 0;
74                 exists = 0;
75 @@ -2889,7 +2889,7 @@ again:
76                         ext4_journal_stop(handle);
77                         return -ENOMEM;
78                 }
79 -               path[0].p_depth = depth;
80 +               path[0].p_maxdepth = path[0].p_depth = depth;
81                 path[0].p_hdr = ext_inode_hdr(inode);
82                 i = 0;