diff options
-rw-r--r-- | fs/ext4/extents.c | 26 |
1 files changed, 24 insertions, 2 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 9ae6e67090cd..a38f32427826 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -2154,7 +2154,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle, | |||
2154 | ext4_lblk_t iblock, | 2154 | ext4_lblk_t iblock, |
2155 | unsigned long max_blocks) | 2155 | unsigned long max_blocks) |
2156 | { | 2156 | { |
2157 | struct ext4_extent *ex, newex; | 2157 | struct ext4_extent *ex, newex, orig_ex; |
2158 | struct ext4_extent *ex1 = NULL; | 2158 | struct ext4_extent *ex1 = NULL; |
2159 | struct ext4_extent *ex2 = NULL; | 2159 | struct ext4_extent *ex2 = NULL; |
2160 | struct ext4_extent *ex3 = NULL; | 2160 | struct ext4_extent *ex3 = NULL; |
@@ -2173,6 +2173,9 @@ static int ext4_ext_convert_to_initialized(handle_t *handle, | |||
2173 | allocated = ee_len - (iblock - ee_block); | 2173 | allocated = ee_len - (iblock - ee_block); |
2174 | newblock = iblock - ee_block + ext_pblock(ex); | 2174 | newblock = iblock - ee_block + ext_pblock(ex); |
2175 | ex2 = ex; | 2175 | ex2 = ex; |
2176 | orig_ex.ee_block = ex->ee_block; | ||
2177 | orig_ex.ee_len = cpu_to_le16(ee_len); | ||
2178 | ext4_ext_store_pblock(&orig_ex, ext_pblock(ex)); | ||
2176 | 2179 | ||
2177 | err = ext4_ext_get_access(handle, inode, path + depth); | 2180 | err = ext4_ext_get_access(handle, inode, path + depth); |
2178 | if (err) | 2181 | if (err) |
@@ -2201,13 +2204,25 @@ static int ext4_ext_convert_to_initialized(handle_t *handle, | |||
2201 | ex3->ee_len = cpu_to_le16(allocated - max_blocks); | 2204 | ex3->ee_len = cpu_to_le16(allocated - max_blocks); |
2202 | ext4_ext_mark_uninitialized(ex3); | 2205 | ext4_ext_mark_uninitialized(ex3); |
2203 | err = ext4_ext_insert_extent(handle, inode, path, ex3); | 2206 | err = ext4_ext_insert_extent(handle, inode, path, ex3); |
2204 | if (err) | 2207 | if (err) { |
2208 | ex->ee_block = orig_ex.ee_block; | ||
2209 | ex->ee_len = orig_ex.ee_len; | ||
2210 | ext4_ext_store_pblock(ex, ext_pblock(&orig_ex)); | ||
2211 | ext4_ext_mark_uninitialized(ex); | ||
2212 | ext4_ext_dirty(handle, inode, path + depth); | ||
2205 | goto out; | 2213 | goto out; |
2214 | } | ||
2206 | /* | 2215 | /* |
2207 | * The depth, and hence eh & ex might change | 2216 | * The depth, and hence eh & ex might change |
2208 | * as part of the insert above. | 2217 | * as part of the insert above. |
2209 | */ | 2218 | */ |
2210 | newdepth = ext_depth(inode); | 2219 | newdepth = ext_depth(inode); |
2220 | /* | ||
2221 | * update the extent length after successfull insert of the | ||
2222 | * split extent | ||
2223 | */ | ||
2224 | orig_ex.ee_len = cpu_to_le16(ee_len - | ||
2225 | ext4_ext_get_actual_len(ex3)); | ||
2211 | if (newdepth != depth) { | 2226 | if (newdepth != depth) { |
2212 | depth = newdepth; | 2227 | depth = newdepth; |
2213 | ext4_ext_drop_refs(path); | 2228 | ext4_ext_drop_refs(path); |
@@ -2282,6 +2297,13 @@ static int ext4_ext_convert_to_initialized(handle_t *handle, | |||
2282 | goto out; | 2297 | goto out; |
2283 | insert: | 2298 | insert: |
2284 | err = ext4_ext_insert_extent(handle, inode, path, &newex); | 2299 | err = ext4_ext_insert_extent(handle, inode, path, &newex); |
2300 | if (err) { | ||
2301 | ex->ee_block = orig_ex.ee_block; | ||
2302 | ex->ee_len = orig_ex.ee_len; | ||
2303 | ext4_ext_store_pblock(ex, ext_pblock(&orig_ex)); | ||
2304 | ext4_ext_mark_uninitialized(ex); | ||
2305 | ext4_ext_dirty(handle, inode, path + depth); | ||
2306 | } | ||
2285 | out: | 2307 | out: |
2286 | return err ? err : allocated; | 2308 | return err ? err : allocated; |
2287 | } | 2309 | } |