When toggling the bg_use_meta_csum feature, we should rewrite the block groups with the desired checksum. Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> --- misc/tune2fs.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 48 insertions(+), 2 deletions(-) diff --git a/misc/tune2fs.c b/misc/tune2fs.c index ac5e945..2d0ea50 100644 --- a/misc/tune2fs.c +++ b/misc/tune2fs.c @@ -92,6 +92,7 @@ static unsigned long new_inode_size; static char *ext_mount_opts; static int usrquota, grpquota; static int rewrite_checksums; +static int rewrite_bgs_for_checksum; int journal_size, journal_flags; char *journal_device; @@ -137,7 +138,8 @@ static __u32 ok_features[3] = { EXT2_FEATURE_INCOMPAT_FILETYPE | EXT3_FEATURE_INCOMPAT_EXTENTS | EXT4_FEATURE_INCOMPAT_FLEX_BG | - EXT4_FEATURE_INCOMPAT_MMP, + EXT4_FEATURE_INCOMPAT_MMP | + EXT4_FEATURE_INCOMPAT_BG_USE_META_CSUM, /* R/O compat */ EXT2_FEATURE_RO_COMPAT_LARGE_FILE | EXT4_FEATURE_RO_COMPAT_HUGE_FILE| @@ -157,7 +159,8 @@ static __u32 clear_ok_features[3] = { /* Incompat */ EXT2_FEATURE_INCOMPAT_FILETYPE | EXT4_FEATURE_INCOMPAT_FLEX_BG | - EXT4_FEATURE_INCOMPAT_MMP, + EXT4_FEATURE_INCOMPAT_MMP | + EXT4_FEATURE_INCOMPAT_BG_USE_META_CSUM, /* R/O compat */ EXT2_FEATURE_RO_COMPAT_LARGE_FILE | EXT4_FEATURE_RO_COMPAT_HUGE_FILE| @@ -693,8 +696,12 @@ static void rewrite_inodes(ext2_filsys fs) static void rewrite_metadata_checksums(ext2_filsys fs) { + int i; + fs->flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS; ext2fs_init_csum_seed(fs); + for (i = 0; i < fs->group_desc_count; i++) + ext2fs_group_desc_csum_set(fs, i); rewrite_inodes(fs); ext2fs_read_bitmaps(fs); ext2fs_mark_ib_dirty(fs); @@ -710,6 +717,29 @@ static void rewrite_metadata_checksums(ext2_filsys fs) } /* + * Rewrite just the block group checksums. Only call this function if + * you're _not_ calling rewrite_metadata_checksums; this function exists + * to handle the case that you're changing bg_use_meta_csum and NOT changing + * either gdt_csum or metadata_csum. + */ +static void rewrite_bg_checksums(ext2_filsys fs) +{ + int i; + + if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super, + EXT4_FEATURE_RO_COMPAT_GDT_CSUM) || + !EXT2_HAS_RO_COMPAT_FEATURE(fs->super, + EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) + return; + + ext2fs_init_csum_seed(fs); + for (i = 0; i < fs->group_desc_count; i++) + ext2fs_group_desc_csum_set(fs, i); + fs->flags &= ~EXT2_FLAG_SUPER_ONLY; + ext2fs_mark_super_dirty(fs); +} + +/* * Update the feature set as provided by the user. */ static int update_feature_set(ext2_filsys fs, char *features) @@ -881,6 +911,20 @@ mmp_error: } } + if (FEATURE_ON(E2P_FEATURE_INCOMPAT, + EXT4_FEATURE_INCOMPAT_BG_USE_META_CSUM)) { + if (check_fsck_needed(fs)) + exit(1); + rewrite_bgs_for_checksum = 1; + } + + if (FEATURE_OFF(E2P_FEATURE_INCOMPAT, + EXT4_FEATURE_INCOMPAT_BG_USE_META_CSUM)) { + if (check_fsck_needed(fs)) + exit(1); + rewrite_bgs_for_checksum = 1; + } + if (FEATURE_ON(E2P_FEATURE_RO_INCOMPAT, EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) { if (check_fsck_needed(fs)) @@ -2543,6 +2587,8 @@ retry_open: } if (rewrite_checksums) rewrite_metadata_checksums(fs); + else if (rewrite_bgs_for_checksum) + rewrite_bg_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