aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@us.ibm.com>2012-04-29 18:21:10 -0400
committerTheodore Ts'o <tytso@mit.edu>2012-04-29 18:21:10 -0400
commitf84891289e62a74e9b4942eaad80617368b2d778 (patch)
tree6e86704a9780dd6ed97f25ba1cd32d59ffebf430
parent69964ea4c7b68c9399f7977aa5b9aa6539a6a98a (diff)
ext4: create a new BH_Verified flag to avoid unnecessary metadata validation
Create a new BH_Verified flag to indicate that we've verified all the data in a buffer_head for correctness. This allows us to bypass expensive verification steps when they are not necessary without missing them when they are. Signed-off-by: Darrick J. Wong <djwong@us.ibm.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
-rw-r--r--fs/ext4/extents.c35
-rw-r--r--include/linux/jbd_common.h2
2 files changed, 28 insertions, 9 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index abcdeab67f5..8c1334ee8c7 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -412,6 +412,26 @@ int ext4_ext_check_inode(struct inode *inode)
412 return ext4_ext_check(inode, ext_inode_hdr(inode), ext_depth(inode)); 412 return ext4_ext_check(inode, ext_inode_hdr(inode), ext_depth(inode));
413} 413}
414 414
415static int __ext4_ext_check_block(const char *function, unsigned int line,
416 struct inode *inode,
417 struct ext4_extent_header *eh,
418 int depth,
419 struct buffer_head *bh)
420{
421 int ret;
422
423 if (buffer_verified(bh))
424 return 0;
425 ret = ext4_ext_check(inode, eh, depth);
426 if (ret)
427 return ret;
428 set_buffer_verified(bh);
429 return ret;
430}
431
432#define ext4_ext_check_block(inode, eh, depth, bh) \
433 __ext4_ext_check_block(__func__, __LINE__, inode, eh, depth, bh)
434
415#ifdef EXT_DEBUG 435#ifdef EXT_DEBUG
416static void ext4_ext_show_path(struct inode *inode, struct ext4_ext_path *path) 436static void ext4_ext_show_path(struct inode *inode, struct ext4_ext_path *path)
417{ 437{
@@ -668,8 +688,6 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
668 i = depth; 688 i = depth;
669 /* walk through the tree */ 689 /* walk through the tree */
670 while (i) { 690 while (i) {
671 int need_to_validate = 0;
672
673 ext_debug("depth %d: num %d, max %d\n", 691 ext_debug("depth %d: num %d, max %d\n",
674 ppos, le16_to_cpu(eh->eh_entries), le16_to_cpu(eh->eh_max)); 692 ppos, le16_to_cpu(eh->eh_entries), le16_to_cpu(eh->eh_max));
675 693
@@ -688,8 +706,6 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
688 put_bh(bh); 706 put_bh(bh);
689 goto err; 707 goto err;
690 } 708 }
691 /* validate the extent entries */
692 need_to_validate = 1;
693 } 709 }
694 eh = ext_block_hdr(bh); 710 eh = ext_block_hdr(bh);
695 ppos++; 711 ppos++;
@@ -703,7 +719,7 @@ ext4_ext_find_extent(struct inode *inode, ext4_lblk_t block,
703 path[ppos].p_hdr = eh; 719 path[ppos].p_hdr = eh;
704 i--; 720 i--;
705 721
706 if (need_to_validate && ext4_ext_check(inode, eh, i)) 722 if (ext4_ext_check_block(inode, eh, i, bh))
707 goto err; 723 goto err;
708 } 724 }
709 725
@@ -1344,7 +1360,8 @@ got_index:
1344 return -EIO; 1360 return -EIO;
1345 eh = ext_block_hdr(bh); 1361 eh = ext_block_hdr(bh);
1346 /* subtract from p_depth to get proper eh_depth */ 1362 /* subtract from p_depth to get proper eh_depth */
1347 if (ext4_ext_check(inode, eh, path->p_depth - depth)) { 1363 if (ext4_ext_check_block(inode, eh,
1364 path->p_depth - depth, bh)) {
1348 put_bh(bh); 1365 put_bh(bh);
1349 return -EIO; 1366 return -EIO;
1350 } 1367 }
@@ -1357,7 +1374,7 @@ got_index:
1357 if (bh == NULL) 1374 if (bh == NULL)
1358 return -EIO; 1375 return -EIO;
1359 eh = ext_block_hdr(bh); 1376 eh = ext_block_hdr(bh);
1360 if (ext4_ext_check(inode, eh, path->p_depth - depth)) { 1377 if (ext4_ext_check_block(inode, eh, path->p_depth - depth, bh)) {
1361 put_bh(bh); 1378 put_bh(bh);
1362 return -EIO; 1379 return -EIO;
1363 } 1380 }
@@ -2644,8 +2661,8 @@ cont:
2644 err = -EIO; 2661 err = -EIO;
2645 break; 2662 break;
2646 } 2663 }
2647 if (ext4_ext_check(inode, ext_block_hdr(bh), 2664 if (ext4_ext_check_block(inode, ext_block_hdr(bh),
2648 depth - i - 1)) { 2665 depth - i - 1, bh)) {
2649 err = -EIO; 2666 err = -EIO;
2650 break; 2667 break;
2651 } 2668 }
diff --git a/include/linux/jbd_common.h b/include/linux/jbd_common.h
index 6230f8556a4..6133679bc4c 100644
--- a/include/linux/jbd_common.h
+++ b/include/linux/jbd_common.h
@@ -12,6 +12,7 @@ enum jbd_state_bits {
12 BH_State, /* Pins most journal_head state */ 12 BH_State, /* Pins most journal_head state */
13 BH_JournalHead, /* Pins bh->b_private and jh->b_bh */ 13 BH_JournalHead, /* Pins bh->b_private and jh->b_bh */
14 BH_Unshadow, /* Dummy bit, for BJ_Shadow wakeup filtering */ 14 BH_Unshadow, /* Dummy bit, for BJ_Shadow wakeup filtering */
15 BH_Verified, /* Metadata block has been verified ok */
15 BH_JBDPrivateStart, /* First bit available for private use by FS */ 16 BH_JBDPrivateStart, /* First bit available for private use by FS */
16}; 17};
17 18
@@ -24,6 +25,7 @@ TAS_BUFFER_FNS(Revoked, revoked)
24BUFFER_FNS(RevokeValid, revokevalid) 25BUFFER_FNS(RevokeValid, revokevalid)
25TAS_BUFFER_FNS(RevokeValid, revokevalid) 26TAS_BUFFER_FNS(RevokeValid, revokevalid)
26BUFFER_FNS(Freed, freed) 27BUFFER_FNS(Freed, freed)
28BUFFER_FNS(Verified, verified)
27 29
28static inline struct buffer_head *jh2bh(struct journal_head *jh) 30static inline struct buffer_head *jh2bh(struct journal_head *jh)
29{ 31{