summaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2013-08-16 21:20:41 -0400
committerTheodore Ts'o <tytso@mit.edu>2013-08-16 21:20:41 -0400
commit7d7ea89e756ea18a3b08cd396e2a4c0c12d473a8 (patch)
tree8c14a5c1f9e2a14d2de50e07ec97154fa811ac08 /fs/ext4
parenta361293f5fedea0016a10599f409631a15d47ee7 (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.c97
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
467static int __ext4_ext_check_block(const char *function, unsigned int line, 467static 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;
492errout:
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
488static void ext4_ext_show_path(struct inode *inode, struct ext4_ext_path *path) 502static 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);
1439found_extent: 1432found_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