Whamcloud - gitweb
tune2fs: speed up rewriting extent tree when enabling metadata_csum
authorDarrick J. Wong <darrick.wong@oracle.com>
Tue, 4 Nov 2014 16:52:03 +0000 (11:52 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Tue, 4 Nov 2014 16:52:03 +0000 (11:52 -0500)
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 <darrick.wong@oracle.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
misc/tune2fs.c

index d17c8de..ecbdea0 100644 (file)
@@ -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;
 }