aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ext4/extents.c26
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;
2283insert: 2298insert:
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 }
2285out: 2307out:
2286 return err ? err : allocated; 2308 return err ? err : allocated;
2287} 2309}