Add Jan Kara's ext4 data corruption bugs for blocksize < pagesize
[ext4-patch-queue.git] / collapse-ext4_convert_initialized_extents-into-ext4_ext_convert_initialized_extent
blobd4f5eb860ce71930f578d862627344dd4eccfbe4
1 ext4: collapse ext4_convert_initialized_extents()
3 The function ext4_convert_initialized_extents() is only called by a
4 single function --- ext4_ext_convert_initalized_extents().  Inline the
5 code and get rid of the unnecessary bits in order to simplify the code.
7 Rename ext4_ext_convert_initalized_extents() to
8 convert_initalized_extents() since it's a static function that is
9 actually only used in a single caller, ext4_ext_map_blocks().
11 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
12 ---
13  fs/ext4/extents.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------------------------------------------------------
14  1 file changed, 59 insertions(+), 77 deletions(-)
16 diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
17 index fc76be8..985848d 100644
18 --- a/fs/ext4/extents.c
19 +++ b/fs/ext4/extents.c
20 @@ -3683,67 +3683,6 @@ static int ext4_split_convert_extents(handle_t *handle,
21         return ext4_split_extent(handle, inode, path, map, split_flag, flags);
22  }
24 -static int ext4_convert_initialized_extents(handle_t *handle,
25 -                                           struct inode *inode,
26 -                                           struct ext4_map_blocks *map,
27 -                                           struct ext4_ext_path *path)
29 -       struct ext4_extent *ex;
30 -       ext4_lblk_t ee_block;
31 -       unsigned int ee_len;
32 -       int depth;
33 -       int err = 0;
35 -       depth = ext_depth(inode);
36 -       ex = path[depth].p_ext;
37 -       ee_block = le32_to_cpu(ex->ee_block);
38 -       ee_len = ext4_ext_get_actual_len(ex);
40 -       ext_debug("%s: inode %lu, logical"
41 -               "block %llu, max_blocks %u\n", __func__, inode->i_ino,
42 -                 (unsigned long long)ee_block, ee_len);
44 -       if (ee_block != map->m_lblk || ee_len > map->m_len) {
45 -               err = ext4_split_convert_extents(handle, inode, map, path,
46 -                               EXT4_GET_BLOCKS_CONVERT_UNWRITTEN);
47 -               if (err < 0)
48 -                       goto out;
49 -               ext4_ext_drop_refs(path);
50 -               path = ext4_ext_find_extent(inode, map->m_lblk, &path,
51 -                                           EXT4_EX_NOFREE_ON_ERR);
52 -               if (IS_ERR(path)) {
53 -                       err = PTR_ERR(path);
54 -                       goto out;
55 -               }
56 -               depth = ext_depth(inode);
57 -               ex = path[depth].p_ext;
58 -               if (!ex) {
59 -                       EXT4_ERROR_INODE(inode, "unexpected hole at %lu",
60 -                                        (unsigned long) map->m_lblk);
61 -                       err = -EIO;
62 -                       goto out;
63 -               }
64 -       }
66 -       err = ext4_ext_get_access(handle, inode, path + depth);
67 -       if (err)
68 -               goto out;
69 -       /* first mark the extent as unwritten */
70 -       ext4_ext_mark_unwritten(ex);
72 -       /* note: ext4_ext_correct_indexes() isn't needed here because
73 -        * borders are not changed
74 -        */
75 -       ext4_ext_try_to_merge(handle, inode, path, ex);
77 -       /* Mark modified extent as dirty */
78 -       err = ext4_ext_dirty(handle, inode, path + path->p_depth);
79 -out:
80 -       ext4_ext_show_leaf(inode, path);
81 -       return err;
85  static int ext4_convert_unwritten_extents_endio(handle_t *handle,
86                                                 struct inode *inode,
87                                                 struct ext4_map_blocks *map,
88 @@ -3980,12 +3919,15 @@ get_reserved_cluster_alloc(struct inode *inode, ext4_lblk_t lblk_start,
89  }
91  static int
92 -ext4_ext_convert_initialized_extent(handle_t *handle, struct inode *inode,
93 -                       struct ext4_map_blocks *map,
94 -                       struct ext4_ext_path *path, int flags,
95 -                       unsigned int allocated, ext4_fsblk_t newblock)
96 +convert_initialized_extent(handle_t *handle, struct inode *inode,
97 +                          struct ext4_map_blocks *map,
98 +                          struct ext4_ext_path *path, int flags,
99 +                          unsigned int allocated, ext4_fsblk_t newblock)
101 -       int ret = 0;
102 +       struct ext4_extent *ex;
103 +       ext4_lblk_t ee_block;
104 +       unsigned int ee_len;
105 +       int depth;
106         int err = 0;
108         /*
109 @@ -3995,20 +3937,60 @@ ext4_ext_convert_initialized_extent(handle_t *handle, struct inode *inode,
110         if (map->m_len > EXT_UNWRITTEN_MAX_LEN)
111                 map->m_len = EXT_UNWRITTEN_MAX_LEN / 2;
113 -       ret = ext4_convert_initialized_extents(handle, inode, map,
114 -                                               path);
115 -       if (ret >= 0) {
116 -               ext4_update_inode_fsync_trans(handle, inode, 1);
117 -               err = check_eofblocks_fl(handle, inode, map->m_lblk,
118 -                                        path, map->m_len);
119 -       } else
120 -               err = ret;
121 +       depth = ext_depth(inode);
122 +       ex = path[depth].p_ext;
123 +       ee_block = le32_to_cpu(ex->ee_block);
124 +       ee_len = ext4_ext_get_actual_len(ex);
126 +       ext_debug("%s: inode %lu, logical"
127 +               "block %llu, max_blocks %u\n", __func__, inode->i_ino,
128 +                 (unsigned long long)ee_block, ee_len);
130 +       if (ee_block != map->m_lblk || ee_len > map->m_len) {
131 +               err = ext4_split_convert_extents(handle, inode, map, path,
132 +                               EXT4_GET_BLOCKS_CONVERT_UNWRITTEN);
133 +               if (err < 0)
134 +                       return err;
135 +               ext4_ext_drop_refs(path);
136 +               path = ext4_ext_find_extent(inode, map->m_lblk, &path,
137 +                                           EXT4_EX_NOFREE_ON_ERR);
138 +               if (IS_ERR(path))
139 +                       return PTR_ERR(path);
140 +               depth = ext_depth(inode);
141 +               ex = path[depth].p_ext;
142 +               if (!ex) {
143 +                       EXT4_ERROR_INODE(inode, "unexpected hole at %lu",
144 +                                        (unsigned long) map->m_lblk);
145 +                       return -EIO;
146 +               }
147 +       }
149 +       err = ext4_ext_get_access(handle, inode, path + depth);
150 +       if (err)
151 +               return err;
152 +       /* first mark the extent as unwritten */
153 +       ext4_ext_mark_unwritten(ex);
155 +       /* note: ext4_ext_correct_indexes() isn't needed here because
156 +        * borders are not changed
157 +        */
158 +       ext4_ext_try_to_merge(handle, inode, path, ex);
160 +       /* Mark modified extent as dirty */
161 +       err = ext4_ext_dirty(handle, inode, path + path->p_depth);
162 +       if (err)
163 +               return err;
164 +       ext4_ext_show_leaf(inode, path);
166 +       ext4_update_inode_fsync_trans(handle, inode, 1);
167 +       err = check_eofblocks_fl(handle, inode, map->m_lblk, path, map->m_len);
168 +       if (err)
169 +               return err;
170         map->m_flags |= EXT4_MAP_UNWRITTEN;
171         if (allocated > map->m_len)
172                 allocated = map->m_len;
173         map->m_len = allocated;
175 -       return err ? err : allocated;
176 +       return allocated;
179  static int
180 @@ -4348,7 +4330,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
181                          */
182                         if ((!ext4_ext_is_unwritten(ex)) &&
183                             (flags & EXT4_GET_BLOCKS_CONVERT_UNWRITTEN)) {
184 -                               allocated = ext4_ext_convert_initialized_extent(
185 +                               allocated = convert_initialized_extent(
186                                                 handle, inode, map, path, flags,
187                                                 allocated, newblock);
188                                 goto out2;