Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Darrick J. Wong and committed by
Theodore Ts'o
f8489128 69964ea4

+28 -9
+26 -9
fs/ext4/extents.c
··· 412 412 return ext4_ext_check(inode, ext_inode_hdr(inode), ext_depth(inode)); 413 413 } 414 414 415 + static 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 435 #ifdef EXT_DEBUG 416 436 static void ext4_ext_show_path(struct inode *inode, struct ext4_ext_path *path) 417 437 { ··· 688 668 i = depth; 689 669 /* walk through the tree */ 690 670 while (i) { 691 - int need_to_validate = 0; 692 - 693 671 ext_debug("depth %d: num %d, max %d\n", 694 672 ppos, le16_to_cpu(eh->eh_entries), le16_to_cpu(eh->eh_max)); 695 673 ··· 706 688 put_bh(bh); 707 689 goto err; 708 690 } 709 - /* validate the extent entries */ 710 - need_to_validate = 1; 711 691 } 712 692 eh = ext_block_hdr(bh); 713 693 ppos++; ··· 719 703 path[ppos].p_hdr = eh; 720 704 i--; 721 705 722 - if (need_to_validate && ext4_ext_check(inode, eh, i)) 706 + if (ext4_ext_check_block(inode, eh, i, bh)) 723 707 goto err; 724 708 } 725 709 ··· 1360 1344 return -EIO; 1361 1345 eh = ext_block_hdr(bh); 1362 1346 /* subtract from p_depth to get proper eh_depth */ 1363 - if (ext4_ext_check(inode, eh, path->p_depth - depth)) { 1347 + if (ext4_ext_check_block(inode, eh, 1348 + path->p_depth - depth, bh)) { 1364 1349 put_bh(bh); 1365 1350 return -EIO; 1366 1351 } ··· 1374 1357 if (bh == NULL) 1375 1358 return -EIO; 1376 1359 eh = ext_block_hdr(bh); 1377 - if (ext4_ext_check(inode, eh, path->p_depth - depth)) { 1360 + if (ext4_ext_check_block(inode, eh, path->p_depth - depth, bh)) { 1378 1361 put_bh(bh); 1379 1362 return -EIO; 1380 1363 } ··· 2661 2644 err = -EIO; 2662 2645 break; 2663 2646 } 2664 - if (ext4_ext_check(inode, ext_block_hdr(bh), 2665 - depth - i - 1)) { 2647 + if (ext4_ext_check_block(inode, ext_block_hdr(bh), 2648 + depth - i - 1, bh)) { 2666 2649 err = -EIO; 2667 2650 break; 2668 2651 }
+2
include/linux/jbd_common.h
··· 12 12 BH_State, /* Pins most journal_head state */ 13 13 BH_JournalHead, /* Pins bh->b_private and jh->b_bh */ 14 14 BH_Unshadow, /* Dummy bit, for BJ_Shadow wakeup filtering */ 15 + BH_Verified, /* Metadata block has been verified ok */ 15 16 BH_JBDPrivateStart, /* First bit available for private use by FS */ 16 17 }; 17 18 ··· 25 24 BUFFER_FNS(RevokeValid, revokevalid) 26 25 TAS_BUFFER_FNS(RevokeValid, revokevalid) 27 26 BUFFER_FNS(Freed, freed) 27 + BUFFER_FNS(Verified, verified) 28 28 29 29 static inline struct buffer_head *jh2bh(struct journal_head *jh) 30 30 {