diff options
author | Akira Fujita <a-fujita@rs.jp.nec.com> | 2010-03-04 00:31:06 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2010-03-04 00:31:06 -0500 |
commit | 5fd5249aa36fad98c9fd5edced352939e54f9324 (patch) | |
tree | ee8add19d98cc2fc47133b3346b5e55ecc68478e /fs/ext4 | |
parent | 731eb1a03a8445cde2cb23ecfb3580c6fa7bb690 (diff) |
ext4: Fix insertion point of extent in mext_insert_across_blocks()
If the leaf node has 2 extent space or fewer and EXT4_IOC_MOVE_EXT
ioctl is called with the file offset where after the 2nd extent
covers, mext_insert_across_blocks() always tries to insert extent into
the first extent. As a result, the file gets corrupted because of
wrong extent order. The patch fixes this problem.
Signed-off-by: Akira Fujita <a-fujita@rs.jp.nec.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/move_extent.c | 4 |
1 files changed, 4 insertions, 0 deletions
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index 1654eb862d74..9eca1c0ec546 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c | |||
@@ -252,6 +252,7 @@ mext_insert_across_blocks(handle_t *handle, struct inode *orig_inode, | |||
252 | } | 252 | } |
253 | 253 | ||
254 | o_start->ee_len = start_ext->ee_len; | 254 | o_start->ee_len = start_ext->ee_len; |
255 | eblock = le32_to_cpu(start_ext->ee_block); | ||
255 | new_flag = 1; | 256 | new_flag = 1; |
256 | 257 | ||
257 | } else if (start_ext->ee_len && new_ext->ee_len && | 258 | } else if (start_ext->ee_len && new_ext->ee_len && |
@@ -262,6 +263,7 @@ mext_insert_across_blocks(handle_t *handle, struct inode *orig_inode, | |||
262 | * orig |------------------------------| | 263 | * orig |------------------------------| |
263 | */ | 264 | */ |
264 | o_start->ee_len = start_ext->ee_len; | 265 | o_start->ee_len = start_ext->ee_len; |
266 | eblock = le32_to_cpu(start_ext->ee_block); | ||
265 | new_flag = 1; | 267 | new_flag = 1; |
266 | 268 | ||
267 | } else if (!start_ext->ee_len && new_ext->ee_len && | 269 | } else if (!start_ext->ee_len && new_ext->ee_len && |
@@ -502,6 +504,7 @@ mext_leaf_block(handle_t *handle, struct inode *orig_inode, | |||
502 | le32_to_cpu(oext->ee_block) + oext_alen) { | 504 | le32_to_cpu(oext->ee_block) + oext_alen) { |
503 | start_ext.ee_len = cpu_to_le16(le32_to_cpu(new_ext.ee_block) - | 505 | start_ext.ee_len = cpu_to_le16(le32_to_cpu(new_ext.ee_block) - |
504 | le32_to_cpu(oext->ee_block)); | 506 | le32_to_cpu(oext->ee_block)); |
507 | start_ext.ee_block = oext->ee_block; | ||
505 | copy_extent_status(oext, &start_ext); | 508 | copy_extent_status(oext, &start_ext); |
506 | } else if (oext > EXT_FIRST_EXTENT(orig_path[depth].p_hdr)) { | 509 | } else if (oext > EXT_FIRST_EXTENT(orig_path[depth].p_hdr)) { |
507 | prev_ext = oext - 1; | 510 | prev_ext = oext - 1; |
@@ -515,6 +518,7 @@ mext_leaf_block(handle_t *handle, struct inode *orig_inode, | |||
515 | start_ext.ee_len = cpu_to_le16( | 518 | start_ext.ee_len = cpu_to_le16( |
516 | ext4_ext_get_actual_len(prev_ext) + | 519 | ext4_ext_get_actual_len(prev_ext) + |
517 | new_ext_alen); | 520 | new_ext_alen); |
521 | start_ext.ee_block = oext->ee_block; | ||
518 | copy_extent_status(prev_ext, &start_ext); | 522 | copy_extent_status(prev_ext, &start_ext); |
519 | new_ext.ee_len = 0; | 523 | new_ext.ee_len = 0; |
520 | } | 524 | } |