This patch adds to tune2fs the ability to toggle the metadata checksum rocompat feature flag, which will rewrite the inode table with checksums. Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> --- misc/tune2fs.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 75 insertions(+), 2 deletions(-) diff --git a/misc/tune2fs.c b/misc/tune2fs.c index 82833ad..283ad1d 100644 --- a/misc/tune2fs.c +++ b/misc/tune2fs.c @@ -82,6 +82,7 @@ static int stride_set, stripe_width_set; static char *extended_cmd; static unsigned long new_inode_size; static char *ext_mount_opts; +static int rewrite_checksums; int journal_size, journal_flags; char *journal_device; @@ -131,7 +132,8 @@ static __u32 ok_features[3] = { EXT4_FEATURE_RO_COMPAT_DIR_NLINK| EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE| EXT4_FEATURE_RO_COMPAT_GDT_CSUM | - EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER + EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER | + EXT4_FEATURE_RO_COMPAT_METADATA_CSUM }; static __u32 clear_ok_features[3] = { @@ -147,7 +149,8 @@ static __u32 clear_ok_features[3] = { EXT4_FEATURE_RO_COMPAT_HUGE_FILE| EXT4_FEATURE_RO_COMPAT_DIR_NLINK| EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE| - EXT4_FEATURE_RO_COMPAT_GDT_CSUM + EXT4_FEATURE_RO_COMPAT_GDT_CSUM | + EXT4_FEATURE_RO_COMPAT_METADATA_CSUM }; /* @@ -330,6 +333,16 @@ static void update_mntopts(ext2_filsys fs, char *mntopts) ext2fs_mark_super_dirty(fs); } +static int check_fsck_needed(ext2_filsys fs) +{ + if (fs->super->s_state & EXT2_VALID_FS) + return 0; + printf("\n%s\n", _(please_fsck)); + if (mount_flags & EXT2_MF_READONLY) + printf(_("(and reboot afterwards!)\n")); + return 1; +} + static void request_fsck_afterwards(ext2_filsys fs) { static int requested = 0; @@ -343,6 +356,49 @@ static void request_fsck_afterwards(ext2_filsys fs) } /* + * Forcibly set checksums in all inodes. + */ +static void rewrite_inodes(ext2_filsys fs) +{ + struct ext2_inode_large inode; + ext2_inode_scan scan; + errcode_t retval; + ext2_ino_t ino; + + if (fs->super->s_creator_os != EXT2_OS_LINUX) + return; + + retval = ext2fs_open_inode_scan(fs, 0, &scan); + if (retval) { + com_err("set_csum", retval, "While opening inode scan"); + exit(1); + } + + do { + retval = ext2fs_get_next_inode(scan, &ino, &inode); + if (retval) { + com_err("set_csum", retval, "while getting next inode"); + exit(1); + } + if (!ino) + break; + retval = ext2fs_write_inode(fs, ino, &inode); + if (retval) { + com_err("set_csum", retval, "while writing inode"); + exit(1); + } + } while (ino); + ext2fs_close_inode_scan(scan); +} + +static void rewrite_metadata_checksums(ext2_filsys fs) +{ + fs->flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS; + rewrite_inodes(fs); + fs->flags &= ~EXT2_FLAG_IGNORE_CSUM_ERRORS; +} + +/* * Update the feature set as provided by the user. */ static void update_feature_set(ext2_filsys fs, char *features) @@ -448,6 +504,20 @@ static void update_feature_set(ext2_filsys fs, char *features) } if (FEATURE_ON(E2P_FEATURE_RO_INCOMPAT, + EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) { + if (check_fsck_needed(fs)) + exit(1); + rewrite_checksums = 1; + } + + if (FEATURE_OFF(E2P_FEATURE_RO_INCOMPAT, + EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) { + if (check_fsck_needed(fs)) + exit(1); + rewrite_checksums = 1; + } + + if (FEATURE_ON(E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) { for (i = 0; i < fs->group_desc_count; i++) { gd = ext2fs_group_desc(fs, fs->group_desc, i); @@ -1824,7 +1894,10 @@ retry_open: fs->flags &= ~EXT2_FLAG_SUPER_ONLY; } ext2fs_mark_super_dirty(fs); + rewrite_checksums = 1; } + if (rewrite_checksums) + rewrite_metadata_checksums(fs); if (I_flag) { if (mount_flags & EXT2_MF_MOUNTED) { fputs(_("The inode size may only be " -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html