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) |
