aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorAkira Fujita <a-fujita@rs.jp.nec.com>2009-09-16 14:25:07 -0400
committerTheodore Ts'o <tytso@mit.edu>2009-09-16 14:25:07 -0400
commit347fa6f1c7cb5df2b38d3c9167cfe242ce0cd1da (patch)
tree1e4b467f7baa6c5fe291b0f53d6483776b2d5a54 /fs/ext4
parent2147b1a6a48e28399120ca51d4a91840a278611f (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>
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/move_extent.c34
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 }
1399out2: 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)