aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2008-04-29 22:03:59 -0400
committerTheodore Ts'o <tytso@mit.edu>2008-04-29 22:03:59 -0400
commit161e7b7c1d24112d188df9a7b30d468a8d135b96 (patch)
treebac6cea21f4a3bb96b8d16660ec9a503427c01a8
parent1a89734d4057066344356e9c7e13b6379497aebe (diff)
ext4: Cache the correct extent length for uninit extents
When we convert an uninitialized extent to an initialized extent we need to make sure we return the number of blocks in the extent from the file system block corresponding to logical file block. Otherwise we cache wrong extent details and this results in file system corruption. Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Signed-off-by: Mingming Cao <cmm@us.ibm.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
-rw-r--r--fs/ext4/extents.c48
1 files changed, 43 insertions, 5 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 7733e2943367..c7c42c9c7bf7 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -2266,7 +2266,8 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
2266 ex->ee_len = orig_ex.ee_len; 2266 ex->ee_len = orig_ex.ee_len;
2267 ext4_ext_store_pblock(ex, ext_pblock(&orig_ex)); 2267 ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
2268 ext4_ext_dirty(handle, inode, path + depth); 2268 ext4_ext_dirty(handle, inode, path + depth);
2269 return le16_to_cpu(ex->ee_len); 2269 /* zeroed the full extent */
2270 return allocated;
2270 } 2271 }
2271 2272
2272 /* ex1: ee_block to iblock - 1 : uninitialized */ 2273 /* ex1: ee_block to iblock - 1 : uninitialized */
@@ -2311,11 +2312,45 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
2311 ex->ee_len = orig_ex.ee_len; 2312 ex->ee_len = orig_ex.ee_len;
2312 ext4_ext_store_pblock(ex, ext_pblock(&orig_ex)); 2313 ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
2313 ext4_ext_dirty(handle, inode, path + depth); 2314 ext4_ext_dirty(handle, inode, path + depth);
2314 return le16_to_cpu(ex->ee_len); 2315 /* zeroed the full extent */
2316 return allocated;
2315 2317
2316 } else if (err) 2318 } else if (err)
2317 goto fix_extent_len; 2319 goto fix_extent_len;
2318 2320
2321 /*
2322 * We need to zero out the second half because
2323 * an fallocate request can update file size and
2324 * converting the second half to initialized extent
2325 * implies that we can leak some junk data to user
2326 * space.
2327 */
2328 err = ext4_ext_zeroout(inode, ex3);
2329 if (err) {
2330 /*
2331 * We should actually mark the
2332 * second half as uninit and return error
2333 * Insert would have changed the extent
2334 */
2335 depth = ext_depth(inode);
2336 ext4_ext_drop_refs(path);
2337 path = ext4_ext_find_extent(inode,
2338 iblock, path);
2339 if (IS_ERR(path)) {
2340 err = PTR_ERR(path);
2341 return err;
2342 }
2343 ex = path[depth].p_ext;
2344 err = ext4_ext_get_access(handle, inode,
2345 path + depth);
2346 if (err)
2347 return err;
2348 ext4_ext_mark_uninitialized(ex);
2349 ext4_ext_dirty(handle, inode, path + depth);
2350 return err;
2351 }
2352
2353 /* zeroed the second half */
2319 return allocated; 2354 return allocated;
2320 } 2355 }
2321 ex3 = &newex; 2356 ex3 = &newex;
@@ -2333,7 +2368,8 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
2333 ex->ee_len = orig_ex.ee_len; 2368 ex->ee_len = orig_ex.ee_len;
2334 ext4_ext_store_pblock(ex, ext_pblock(&orig_ex)); 2369 ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
2335 ext4_ext_dirty(handle, inode, path + depth); 2370 ext4_ext_dirty(handle, inode, path + depth);
2336 return le16_to_cpu(ex->ee_len); 2371 /* zeroed the full extent */
2372 return allocated;
2337 2373
2338 } else if (err) 2374 } else if (err)
2339 goto fix_extent_len; 2375 goto fix_extent_len;
@@ -2381,7 +2417,8 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
2381 ex->ee_len = orig_ex.ee_len; 2417 ex->ee_len = orig_ex.ee_len;
2382 ext4_ext_store_pblock(ex, ext_pblock(&orig_ex)); 2418 ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
2383 ext4_ext_dirty(handle, inode, path + depth); 2419 ext4_ext_dirty(handle, inode, path + depth);
2384 return le16_to_cpu(ex->ee_len); 2420 /* zero out the first half */
2421 return allocated;
2385 } 2422 }
2386 } 2423 }
2387 /* 2424 /*
@@ -2448,7 +2485,8 @@ insert:
2448 ex->ee_len = orig_ex.ee_len; 2485 ex->ee_len = orig_ex.ee_len;
2449 ext4_ext_store_pblock(ex, ext_pblock(&orig_ex)); 2486 ext4_ext_store_pblock(ex, ext_pblock(&orig_ex));
2450 ext4_ext_dirty(handle, inode, path + depth); 2487 ext4_ext_dirty(handle, inode, path + depth);
2451 return le16_to_cpu(ex->ee_len); 2488 /* zero out the first half */
2489 return allocated;
2452 } else if (err) 2490 } else if (err)
2453 goto fix_extent_len; 2491 goto fix_extent_len;
2454out: 2492out: