From 8302e2e68813fa1b18b15cbeab7d7a58934553ea Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Tue, 4 Nov 2014 11:52:03 -0500 Subject: [PATCH] tune2fs: speed up rewriting extent tree when enabling metadata_csum When enabling checksums, tune2fs naively rewrites every extent in the entire tree! This is unnecessary since we only need to rewrite each extent tree block; therefore, only rewrite the extent if it's the first one in an internal extent tree block. Also, don't bother iterating the extent tree when clearing checksums. Signed-off-by: Darrick J. Wong Signed-off-by: Theodore Ts'o --- misc/tune2fs.c | 49 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/misc/tune2fs.c b/misc/tune2fs.c index d17c8de..ecbdea0 100644 --- a/misc/tune2fs.c +++ b/misc/tune2fs.c @@ -442,39 +442,56 @@ static errcode_t rewrite_extents(ext2_filsys fs, ext2_ino_t ino, { ext2_extent_handle_t handle; struct ext2fs_extent extent; - int op = EXT2_EXTENT_ROOT; errcode_t errcode; + struct ext2_extent_info info; - if (!(inode->i_flags & EXT4_EXTENTS_FL)) + if (!(inode->i_flags & EXT4_EXTENTS_FL) || + !EXT2_HAS_RO_COMPAT_FEATURE(fs->super, + EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) return 0; errcode = ext2fs_extent_open(fs, ino, &handle); if (errcode) return errcode; - while (1) { - errcode = ext2fs_extent_get(handle, op, &extent); + errcode = ext2fs_extent_get(handle, EXT2_EXTENT_ROOT, &extent); + if (errcode) + goto out; + + do { + errcode = ext2fs_extent_get_info(handle, &info); if (errcode) break; - /* Root node is in the separately checksummed inode */ - if (op == EXT2_EXTENT_ROOT) { - op = EXT2_EXTENT_NEXT; - continue; + /* + * If this is the first extent in an extent block that we + * haven't visited, rewrite the extent to force the ETB + * checksum to be rewritten. + */ + if (info.curr_entry == 1 && info.curr_level != 0 && + !(extent.e_flags & EXT2_EXTENT_FLAGS_SECOND_VISIT)) { + errcode = ext2fs_extent_replace(handle, 0, &extent); + if (errcode) + break; } - op = EXT2_EXTENT_NEXT; - /* Only visit the first extent in each extent block */ - if (extent.e_flags & EXT2_EXTENT_FLAGS_SECOND_VISIT) - continue; - errcode = ext2fs_extent_replace(handle, 0, &extent); - if (errcode) - break; - } + /* Skip to the end of a block of leaf nodes */ + if (extent.e_flags & EXT2_EXTENT_FLAGS_LEAF) { + errcode = ext2fs_extent_get(handle, + EXT2_EXTENT_LAST_SIB, + &extent); + if (errcode) + break; + } + errcode = ext2fs_extent_get(handle, EXT2_EXTENT_NEXT, &extent); + } while (errcode == 0); + +out: /* Ok if we run off the end */ if (errcode == EXT2_ET_EXTENT_NO_NEXT) errcode = 0; + ext2fs_extent_free(handle); return errcode; } -- 1.8.3.1