diff mbox series

libext2fs: refactor code which fixes up the checksums in an extent tree

Message ID 20181021135520.31566-1-tytso@mit.edu
State Accepted, archived
Headers show
Series libext2fs: refactor code which fixes up the checksums in an extent tree | expand

Commit Message

Theodore Ts'o Oct. 21, 2018, 1:55 p.m. UTC
The code to recalculate the checksums in an extent tree (which is
needed after an inode is relocated so it has a different inode number)
was duplicated in tune2fs and resize2fs.  In addition, this work could
be done in a much more efficient way inside lib/ext2fs/extent.c.

This commit creates a new library function which corrects the
checksums in an inode's extent tree, named: ext2fs_fix_extents_checksums()

Signed-off-by: Theodore Ts'o <tytso@mit.edu>
---
 lib/ext2fs/ext2fs.h |  4 ++-
 lib/ext2fs/extent.c | 48 ++++++++++++++++++++++++++++++++++++
 misc/tune2fs.c      | 60 +--------------------------------------------
 resize/resize2fs.c  | 56 ++----------------------------------------
 4 files changed, 54 insertions(+), 114 deletions(-)
diff mbox series

Patch

diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index 185be5df5..a5fc90a9e 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -1295,7 +1295,9 @@  extern errcode_t ext2fs_extent_goto(ext2_extent_handle_t handle,
 extern errcode_t ext2fs_extent_goto2(ext2_extent_handle_t handle,
 				     int leaf_level, blk64_t blk);
 extern errcode_t ext2fs_extent_fix_parents(ext2_extent_handle_t handle);
-size_t ext2fs_max_extent_depth(ext2_extent_handle_t handle);
+extern size_t ext2fs_max_extent_depth(ext2_extent_handle_t handle);
+extern errcode_t ext2fs_fix_extents_checksums(ext2_filsys fs, ext2_ino_t ino,
+					      struct ext2_inode *inode);
 
 /* fallocate.c */
 #define EXT2_FALLOCATE_ZERO_BLOCKS	(0x1)
diff --git a/lib/ext2fs/extent.c b/lib/ext2fs/extent.c
index a9cdae797..ac3dbfec9 100644
--- a/lib/ext2fs/extent.c
+++ b/lib/ext2fs/extent.c
@@ -1737,6 +1737,54 @@  size_t ext2fs_max_extent_depth(ext2_extent_handle_t handle)
 	return last_result;
 }
 
+errcode_t ext2fs_fix_extents_checksums(ext2_filsys fs, ext2_ino_t ino,
+				       struct ext2_inode *inode)
+{
+	ext2_extent_handle_t	handle;
+	struct ext2fs_extent	extent;
+	errcode_t		errcode;
+	int    			save_flags = fs->flags;
+
+	if (!ext2fs_has_feature_metadata_csum(fs->super) ||
+	    (inode && !(inode->i_flags & EXT4_EXTENTS_FL)))
+		return 0;
+
+	errcode = ext2fs_extent_open2(fs, ino, inode, &handle);
+	if (errcode) {
+		if (errcode == EXT2_ET_INODE_NOT_EXTENT)
+			errcode = 0;
+		return errcode;
+	}
+
+	fs->flags &= ~EXT2_FLAG_IGNORE_CSUM_ERRORS;
+	errcode = ext2fs_extent_get(handle, EXT2_EXTENT_ROOT, &extent);
+	if (errcode)
+		goto out;
+
+	do {
+		/* 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);
+		if (errcode == EXT2_ET_EXTENT_CSUM_INVALID)
+			errcode = update_path(handle);
+	} while (errcode == 0);
+
+out:
+	/* Ok if we run off the end */
+	if (errcode == EXT2_ET_EXTENT_NO_NEXT)
+		errcode = 0;
+	ext2fs_extent_free(handle);
+	fs->flags = save_flags;
+	return errcode;
+}
+
 #ifdef DEBUG
 /*
  * Override debugfs's prompt
diff --git a/misc/tune2fs.c b/misc/tune2fs.c
index a680b461c..616bdc630 100644
--- a/misc/tune2fs.c
+++ b/misc/tune2fs.c
@@ -497,64 +497,6 @@  static void convert_64bit(ext2_filsys fs, int direction)
 		fprintf(stderr, _("' to disable 64-bit mode.\n"));
 }
 
-/* Rewrite extents */
-static errcode_t rewrite_extents(ext2_filsys fs, ext2_ino_t ino,
-				 struct ext2_inode *inode)
-{
-	ext2_extent_handle_t	handle;
-	struct ext2fs_extent	extent;
-	errcode_t		errcode;
-	struct ext2_extent_info	info;
-
-	if (!(inode->i_flags & EXT4_EXTENTS_FL) ||
-	    !ext2fs_has_feature_metadata_csum(fs->super))
-		return 0;
-
-	errcode = ext2fs_extent_open(fs, ino, &handle);
-	if (errcode)
-		return errcode;
-
-	errcode = ext2fs_extent_get(handle, EXT2_EXTENT_ROOT, &extent);
-	if (errcode)
-		goto out;
-
-	do {
-		errcode = ext2fs_extent_get_info(handle, &info);
-		if (errcode)
-			break;
-
-		/*
-		 * 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;
-		}
-
-		/* 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;
-}
-
 /*
  * Rewrite directory blocks with checksums
  */
@@ -849,7 +791,7 @@  static void rewrite_one_inode(struct rewrite_context *ctx, ext2_ino_t ino,
 	if (retval)
 		fatal_err(retval, "while writing inode");
 
-	retval = rewrite_extents(ctx->fs, ino, inode);
+	retval = ext2fs_fix_extents_checksums(ctx->fs, ino, inode);
 	if (retval)
 		fatal_err(retval, "while rewriting extents");
 
diff --git a/resize/resize2fs.c b/resize/resize2fs.c
index 38032e5c3..c2e10471b 100644
--- a/resize/resize2fs.c
+++ b/resize/resize2fs.c
@@ -1927,59 +1927,6 @@  out:
 	return err;
 }
 
-/* Rewrite extents */
-static errcode_t rewrite_extents(ext2_filsys fs, ext2_ino_t ino)
-{
-	ext2_extent_handle_t	handle;
-	struct ext2fs_extent	extent;
-	errcode_t		errcode;
-	struct ext2_extent_info	info;
-
-	errcode = ext2fs_extent_open(fs, ino, &handle);
-	if (errcode)
-		return errcode;
-
-	errcode = ext2fs_extent_get(handle, EXT2_EXTENT_ROOT, &extent);
-	if (errcode)
-		goto out;
-
-	do {
-		errcode = ext2fs_extent_get_info(handle, &info);
-		if (errcode)
-			break;
-
-		/*
-		 * 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;
-		}
-
-		/* 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;
-}
-
 static void quiet_com_err_proc(const char *whoami EXT2FS_ATTR((unused)),
 			       errcode_t code EXT2FS_ATTR((unused)),
 			       const char *fmt EXT2FS_ATTR((unused)),
@@ -2276,7 +2223,8 @@  remap_blocks:
 		/* Fix up extent block checksums with the new inode number */
 		if (ext2fs_has_feature_metadata_csum(rfs->old_fs->super) &&
 		    (inode->i_flags & EXT4_EXTENTS_FL)) {
-			retval = rewrite_extents(rfs->old_fs, new_inode);
+			retval = ext2fs_fix_extents_checksums(rfs->old_fs,
+							      new_inode, NULL);
 			if (retval)
 				goto errout;
 		}