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