diff options
author | Akira Fujita <a-fujita@rs.jp.nec.com> | 2009-09-16 14:25:07 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2009-09-16 14:25:07 -0400 |
commit | 347fa6f1c7cb5df2b38d3c9167cfe242ce0cd1da (patch) | |
tree | 1e4b467f7baa6c5fe291b0f53d6483776b2d5a54 | |
parent | 2147b1a6a48e28399120ca51d4a91840a278611f (diff) |
ext4: Add null extent check to ext_get_path
There is the possibility that path structure which is taken
by ext4_ext_find_extent() indicates null extents.
Because during data block exchanging in ext4_move_extents(),
constitution of an extent tree may be changed.
As a solution, the patch adds null extent check
to ext_get_path().
Reported-by: Peng Tao <bergwolf@gmail.com>
Signed-off-by: Akira Fujita <a-fujita@rs.jp.nec.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
-rw-r--r-- | fs/ext4/move_extent.c | 34 |
1 files changed, 16 insertions, 18 deletions
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index 2258560e9722..1c509d549137 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c | |||
@@ -39,7 +39,9 @@ get_ext_path(struct inode *inode, ext4_lblk_t lblock, | |||
39 | if (IS_ERR(*path)) { | 39 | if (IS_ERR(*path)) { |
40 | ret = PTR_ERR(*path); | 40 | ret = PTR_ERR(*path); |
41 | *path = NULL; | 41 | *path = NULL; |
42 | } | 42 | } else if ((*path)[ext_depth(inode)].p_ext == NULL) |
43 | ret = -ENODATA; | ||
44 | |||
43 | return ret; | 45 | return ret; |
44 | } | 46 | } |
45 | 47 | ||
@@ -316,7 +318,7 @@ mext_insert_across_blocks(handle_t *handle, struct inode *orig_inode, | |||
316 | 318 | ||
317 | if (new_flag) { | 319 | if (new_flag) { |
318 | err = get_ext_path(orig_inode, eblock, &orig_path); | 320 | err = get_ext_path(orig_inode, eblock, &orig_path); |
319 | if (orig_path == NULL) | 321 | if (err) |
320 | goto out; | 322 | goto out; |
321 | 323 | ||
322 | if (ext4_ext_insert_extent(handle, orig_inode, | 324 | if (ext4_ext_insert_extent(handle, orig_inode, |
@@ -327,7 +329,7 @@ mext_insert_across_blocks(handle_t *handle, struct inode *orig_inode, | |||
327 | if (end_flag) { | 329 | if (end_flag) { |
328 | err = get_ext_path(orig_inode, | 330 | err = get_ext_path(orig_inode, |
329 | le32_to_cpu(end_ext->ee_block) - 1, &orig_path); | 331 | le32_to_cpu(end_ext->ee_block) - 1, &orig_path); |
330 | if (orig_path == NULL) | 332 | if (err) |
331 | goto out; | 333 | goto out; |
332 | 334 | ||
333 | if (ext4_ext_insert_extent(handle, orig_inode, | 335 | if (ext4_ext_insert_extent(handle, orig_inode, |
@@ -673,12 +675,12 @@ mext_replace_branches(handle_t *handle, struct inode *orig_inode, | |||
673 | 675 | ||
674 | /* Get the original extent for the block "orig_off" */ | 676 | /* Get the original extent for the block "orig_off" */ |
675 | err = get_ext_path(orig_inode, orig_off, &orig_path); | 677 | err = get_ext_path(orig_inode, orig_off, &orig_path); |
676 | if (orig_path == NULL) | 678 | if (err) |
677 | goto out; | 679 | goto out; |
678 | 680 | ||
679 | /* Get the donor extent for the head */ | 681 | /* Get the donor extent for the head */ |
680 | err = get_ext_path(donor_inode, donor_off, &donor_path); | 682 | err = get_ext_path(donor_inode, donor_off, &donor_path); |
681 | if (donor_path == NULL) | 683 | if (err) |
682 | goto out; | 684 | goto out; |
683 | depth = ext_depth(orig_inode); | 685 | depth = ext_depth(orig_inode); |
684 | oext = orig_path[depth].p_ext; | 686 | oext = orig_path[depth].p_ext; |
@@ -733,7 +735,7 @@ mext_replace_branches(handle_t *handle, struct inode *orig_inode, | |||
733 | if (orig_path) | 735 | if (orig_path) |
734 | ext4_ext_drop_refs(orig_path); | 736 | ext4_ext_drop_refs(orig_path); |
735 | err = get_ext_path(orig_inode, orig_off, &orig_path); | 737 | err = get_ext_path(orig_inode, orig_off, &orig_path); |
736 | if (orig_path == NULL) | 738 | if (err) |
737 | goto out; | 739 | goto out; |
738 | depth = ext_depth(orig_inode); | 740 | depth = ext_depth(orig_inode); |
739 | oext = orig_path[depth].p_ext; | 741 | oext = orig_path[depth].p_ext; |
@@ -747,7 +749,7 @@ mext_replace_branches(handle_t *handle, struct inode *orig_inode, | |||
747 | if (donor_path) | 749 | if (donor_path) |
748 | ext4_ext_drop_refs(donor_path); | 750 | ext4_ext_drop_refs(donor_path); |
749 | err = get_ext_path(donor_inode, donor_off, &donor_path); | 751 | err = get_ext_path(donor_inode, donor_off, &donor_path); |
750 | if (donor_path == NULL) | 752 | if (err) |
751 | goto out; | 753 | goto out; |
752 | depth = ext_depth(donor_inode); | 754 | depth = ext_depth(donor_inode); |
753 | dext = donor_path[depth].p_ext; | 755 | dext = donor_path[depth].p_ext; |
@@ -1221,7 +1223,7 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, | |||
1221 | donor_start, &len, *moved_len); | 1223 | donor_start, &len, *moved_len); |
1222 | mext_double_up_read(orig_inode, donor_inode); | 1224 | mext_double_up_read(orig_inode, donor_inode); |
1223 | if (ret1) | 1225 | if (ret1) |
1224 | goto out2; | 1226 | goto out; |
1225 | 1227 | ||
1226 | file_end = (i_size_read(orig_inode) - 1) >> orig_inode->i_blkbits; | 1228 | file_end = (i_size_read(orig_inode) - 1) >> orig_inode->i_blkbits; |
1227 | block_end = block_start + len - 1; | 1229 | block_end = block_start + len - 1; |
@@ -1229,20 +1231,16 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, | |||
1229 | len -= block_end - file_end; | 1231 | len -= block_end - file_end; |
1230 | 1232 | ||
1231 | ret1 = get_ext_path(orig_inode, block_start, &orig_path); | 1233 | ret1 = get_ext_path(orig_inode, block_start, &orig_path); |
1232 | if (orig_path == NULL) | 1234 | if (ret1) |
1233 | goto out2; | 1235 | goto out; |
1234 | 1236 | ||
1235 | /* Get path structure to check the hole */ | 1237 | /* Get path structure to check the hole */ |
1236 | ret1 = get_ext_path(orig_inode, block_start, &holecheck_path); | 1238 | ret1 = get_ext_path(orig_inode, block_start, &holecheck_path); |
1237 | if (holecheck_path == NULL) | 1239 | if (ret1) |
1238 | goto out; | 1240 | goto out; |
1239 | 1241 | ||
1240 | depth = ext_depth(orig_inode); | 1242 | depth = ext_depth(orig_inode); |
1241 | ext_cur = holecheck_path[depth].p_ext; | 1243 | ext_cur = holecheck_path[depth].p_ext; |
1242 | if (ext_cur == NULL) { | ||
1243 | ret1 = -EINVAL; | ||
1244 | goto out; | ||
1245 | } | ||
1246 | 1244 | ||
1247 | /* | 1245 | /* |
1248 | * Get proper extent whose ee_block is beyond block_start | 1246 | * Get proper extent whose ee_block is beyond block_start |
@@ -1371,7 +1369,7 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, | |||
1371 | if (holecheck_path) | 1369 | if (holecheck_path) |
1372 | ext4_ext_drop_refs(holecheck_path); | 1370 | ext4_ext_drop_refs(holecheck_path); |
1373 | ret1 = get_ext_path(orig_inode, seq_start, &holecheck_path); | 1371 | ret1 = get_ext_path(orig_inode, seq_start, &holecheck_path); |
1374 | if (holecheck_path == NULL) | 1372 | if (ret1) |
1375 | break; | 1373 | break; |
1376 | depth = holecheck_path->p_depth; | 1374 | depth = holecheck_path->p_depth; |
1377 | 1375 | ||
@@ -1379,7 +1377,7 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, | |||
1379 | if (orig_path) | 1377 | if (orig_path) |
1380 | ext4_ext_drop_refs(orig_path); | 1378 | ext4_ext_drop_refs(orig_path); |
1381 | ret1 = get_ext_path(orig_inode, seq_start, &orig_path); | 1379 | ret1 = get_ext_path(orig_inode, seq_start, &orig_path); |
1382 | if (orig_path == NULL) | 1380 | if (ret1) |
1383 | break; | 1381 | break; |
1384 | 1382 | ||
1385 | ext_cur = holecheck_path[depth].p_ext; | 1383 | ext_cur = holecheck_path[depth].p_ext; |
@@ -1396,7 +1394,7 @@ out: | |||
1396 | ext4_ext_drop_refs(holecheck_path); | 1394 | ext4_ext_drop_refs(holecheck_path); |
1397 | kfree(holecheck_path); | 1395 | kfree(holecheck_path); |
1398 | } | 1396 | } |
1399 | out2: | 1397 | |
1400 | ret2 = mext_inode_double_unlock(orig_inode, donor_inode); | 1398 | ret2 = mext_inode_double_unlock(orig_inode, donor_inode); |
1401 | 1399 | ||
1402 | if (ret1) | 1400 | if (ret1) |