diff options
author | Theodore Ts'o <tytso@mit.edu> | 2013-08-16 21:20:41 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2013-08-16 21:20:41 -0400 |
commit | 7d7ea89e756ea18a3b08cd396e2a4c0c12d473a8 (patch) | |
tree | 8c14a5c1f9e2a14d2de50e07ec97154fa811ac08 /fs/ext4 | |
parent | a361293f5fedea0016a10599f409631a15d47ee7 (diff) |
ext4: refactor code to read the extent tree block
Refactor out the code needed to read the extent tree block into a
single read_extent_tree_block() function. In addition to simplifying
the code, it also makes sure that we call the ext4_ext_load_extent
tracepoint whenever we need to read an extent tree block from disk.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Reviewed-by: Zheng Liu <wenqing.lz@taobao.com>
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/extents.c | 97 |
1 files changed, 43 insertions, 54 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 72ba4705d4fa..a40be59ddce6 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -464,25 +464,39 @@ int ext4_ext_check_inode(struct inode *inode) | |||
464 | return ext4_ext_check(inode, ext_inode_hdr(inode), ext_depth(inode)); | 464 | return ext4_ext_check(inode, ext_inode_hdr(inode), ext_depth(inode)); |
465 | } | 465 | } |
466 | 466 | ||
467 | static int __ext4_ext_check_block(const char *function, unsigned int line, | 467 | static struct buffer_head * |
468 | struct inode *inode, | 468 | __read_extent_tree_block(const char *function, unsigned int line, |
469 | struct ext4_extent_header *eh, | 469 | struct inode *inode, ext4_fsblk_t pblk, int depth) |
470 | int depth, | ||
471 | struct buffer_head *bh) | ||
472 | { | 470 | { |
473 | int ret; | 471 | struct buffer_head *bh; |
472 | int err; | ||
474 | 473 | ||
474 | bh = sb_getblk(inode->i_sb, pblk); | ||
475 | if (unlikely(!bh)) | ||
476 | return ERR_PTR(-ENOMEM); | ||
477 | |||
478 | if (!bh_uptodate_or_lock(bh)) { | ||
479 | trace_ext4_ext_load_extent(inode, pblk, _RET_IP_); | ||
480 | err = bh_submit_read(bh); | ||
481 | if (err < 0) | ||
482 | goto errout; | ||
483 | } | ||
475 | if (buffer_verified(bh)) | 484 | if (buffer_verified(bh)) |
476 | return 0; | 485 | return bh; |
477 | ret = ext4_ext_check(inode, eh, depth); | 486 | err = __ext4_ext_check(function, line, inode, |
478 | if (ret) | 487 | ext_block_hdr(bh), depth); |
479 | return ret; | 488 | if (err) |
489 | goto errout; | ||
480 | set_buffer_verified(bh); | 490 | set_buffer_verified(bh); |
481 | return ret; | 491 | return bh; |
492 | errout: | ||
493 | put_bh(bh); | ||
494 | return ERR_PTR(err); | ||
495 | |||
482 | } | 496 | } |
483 | 497 | ||
484 | #define ext4_ext_check_block(inode, eh, depth, bh) \ | 498 | #define read_extent_tree_block(inode, pblk, depth) \ |
485 | __ext4_ext_check_block(__func__, __LINE__, inode, eh, depth, bh) | 499 | __read_extent_tree_block(__func__, __LINE__, (inode), (pblk), (depth)) |
486 | 500 | ||
487 | #ifdef EXT_DEBUG | 501 | #ifdef EXT_DEBUG |
488 | static void ext4_ext_show_path(struct inode *inode, struct ext4_ext_path *path) | 502 | static void ext4_ext_show_path(struct inode *inode, struct ext4_ext_path *path) |
@@ -748,20 +762,12 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block, | |||
748 | path[ppos].p_depth = i; | 762 | path[ppos].p_depth = i; |
749 | path[ppos].p_ext = NULL; | 763 | path[ppos].p_ext = NULL; |
750 | 764 | ||
751 | bh = sb_getblk(inode->i_sb, path[ppos].p_block); | 765 | bh = read_extent_tree_block(inode, path[ppos].p_block, --i); |
752 | if (unlikely(!bh)) { | 766 | if (IS_ERR(bh)) { |
753 | ret = -ENOMEM; | 767 | ret = PTR_ERR(bh); |
754 | goto err; | 768 | goto err; |
755 | } | 769 | } |
756 | if (!bh_uptodate_or_lock(bh)) { | 770 | |
757 | trace_ext4_ext_load_extent(inode, block, | ||
758 | path[ppos].p_block); | ||
759 | ret = bh_submit_read(bh); | ||
760 | if (ret < 0) { | ||
761 | put_bh(bh); | ||
762 | goto err; | ||
763 | } | ||
764 | } | ||
765 | eh = ext_block_hdr(bh); | 771 | eh = ext_block_hdr(bh); |
766 | ppos++; | 772 | ppos++; |
767 | if (unlikely(ppos > depth)) { | 773 | if (unlikely(ppos > depth)) { |
@@ -773,11 +779,6 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block, | |||
773 | } | 779 | } |
774 | path[ppos].p_bh = bh; | 780 | path[ppos].p_bh = bh; |
775 | path[ppos].p_hdr = eh; | 781 | path[ppos].p_hdr = eh; |
776 | i--; | ||
777 | |||
778 | ret = ext4_ext_check_block(inode, eh, i, bh); | ||
779 | if (ret < 0) | ||
780 | goto err; | ||
781 | } | 782 | } |
782 | 783 | ||
783 | path[ppos].p_depth = i; | 784 | path[ppos].p_depth = i; |
@@ -1412,29 +1413,21 @@ got_index: | |||
1412 | ix++; | 1413 | ix++; |
1413 | block = ext4_idx_pblock(ix); | 1414 | block = ext4_idx_pblock(ix); |
1414 | while (++depth < path->p_depth) { | 1415 | while (++depth < path->p_depth) { |
1415 | bh = sb_bread(inode->i_sb, block); | ||
1416 | if (bh == NULL) | ||
1417 | return -EIO; | ||
1418 | eh = ext_block_hdr(bh); | ||
1419 | /* subtract from p_depth to get proper eh_depth */ | 1416 | /* subtract from p_depth to get proper eh_depth */ |
1420 | if (ext4_ext_check_block(inode, eh, | 1417 | bh = read_extent_tree_block(inode, block, |
1421 | path->p_depth - depth, bh)) { | 1418 | path->p_depth - depth); |
1422 | put_bh(bh); | 1419 | if (IS_ERR(bh)) |
1423 | return -EIO; | 1420 | return PTR_ERR(bh); |
1424 | } | 1421 | eh = ext_block_hdr(bh); |
1425 | ix = EXT_FIRST_INDEX(eh); | 1422 | ix = EXT_FIRST_INDEX(eh); |
1426 | block = ext4_idx_pblock(ix); | 1423 | block = ext4_idx_pblock(ix); |
1427 | put_bh(bh); | 1424 | put_bh(bh); |
1428 | } | 1425 | } |
1429 | 1426 | ||
1430 | bh = sb_bread(inode->i_sb, block); | 1427 | bh = read_extent_tree_block(inode, block, path->p_depth - depth); |
1431 | if (bh == NULL) | 1428 | if (IS_ERR(bh)) |
1432 | return -EIO; | 1429 | return PTR_ERR(bh); |
1433 | eh = ext_block_hdr(bh); | 1430 | eh = ext_block_hdr(bh); |
1434 | if (ext4_ext_check_block(inode, eh, path->p_depth - depth, bh)) { | ||
1435 | put_bh(bh); | ||
1436 | return -EIO; | ||
1437 | } | ||
1438 | ex = EXT_FIRST_EXTENT(eh); | 1431 | ex = EXT_FIRST_EXTENT(eh); |
1439 | found_extent: | 1432 | found_extent: |
1440 | *logical = le32_to_cpu(ex->ee_block); | 1433 | *logical = le32_to_cpu(ex->ee_block); |
@@ -2829,10 +2822,11 @@ again: | |||
2829 | ext_debug("move to level %d (block %llu)\n", | 2822 | ext_debug("move to level %d (block %llu)\n", |
2830 | i + 1, ext4_idx_pblock(path[i].p_idx)); | 2823 | i + 1, ext4_idx_pblock(path[i].p_idx)); |
2831 | memset(path + i + 1, 0, sizeof(*path)); | 2824 | memset(path + i + 1, 0, sizeof(*path)); |
2832 | bh = sb_bread(sb, ext4_idx_pblock(path[i].p_idx)); | 2825 | bh = read_extent_tree_block(inode, |
2833 | if (!bh) { | 2826 | ext4_idx_pblock(path[i].p_idx), depth - i - 1); |
2827 | if (IS_ERR(bh)) { | ||
2834 | /* should we reset i_size? */ | 2828 | /* should we reset i_size? */ |
2835 | err = -EIO; | 2829 | err = PTR_ERR(bh); |
2836 | break; | 2830 | break; |
2837 | } | 2831 | } |
2838 | /* Yield here to deal with large extent trees. | 2832 | /* Yield here to deal with large extent trees. |
@@ -2842,11 +2836,6 @@ again: | |||
2842 | err = -EIO; | 2836 | err = -EIO; |
2843 | break; | 2837 | break; |
2844 | } | 2838 | } |
2845 | if (ext4_ext_check_block(inode, ext_block_hdr(bh), | ||
2846 | depth - i - 1, bh)) { | ||
2847 | err = -EIO; | ||
2848 | break; | ||
2849 | } | ||
2850 | path[i + 1].p_bh = bh; | 2839 | path[i + 1].p_bh = bh; |
2851 | 2840 | ||
2852 | /* save actual number of indexes since this | 2841 | /* save actual number of indexes since this |