aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@us.ibm.com>2012-08-02 20:47:45 -0400
committerTheodore Ts'o <tytso@mit.edu>2012-08-02 20:47:45 -0400
commit9d25f643efc1b7845f0199a67d4f8220ad395353 (patch)
tree95d47fd6086be88b51196faa722b96ec86c4ec83
parent387e6384cbb74fb68f6c0a64c9c3b72b8abc6699 (diff)
downloadandroid_external_e2fsprogs-9d25f643efc1b7845f0199a67d4f8220ad395353.tar.gz
android_external_e2fsprogs-9d25f643efc1b7845f0199a67d4f8220ad395353.tar.bz2
android_external_e2fsprogs-9d25f643efc1b7845f0199a67d4f8220ad395353.zip
tune2fs: rewrite block group checksums when changing checksumming feature flags
When toggling the metadata_csum and uninit_bg feature flags, we should rewrite the block groups with the desired checksum. Signed-off-by: Darrick J. Wong <djwong@us.ibm.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-rw-r--r--misc/tune2fs.c116
1 files changed, 90 insertions, 26 deletions
diff --git a/misc/tune2fs.c b/misc/tune2fs.c
index bc3f832c..3505215a 100644
--- a/misc/tune2fs.c
+++ b/misc/tune2fs.c
@@ -694,8 +694,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 +714,49 @@ static void rewrite_metadata_checksums(ext2_filsys fs)
ext2fs_mark_super_dirty(fs);
}
+static void enable_uninit_bg(ext2_filsys fs)
+{
+ struct ext2_group_desc *gd;
+ int i;
+
+ for (i = 0; i < fs->group_desc_count; i++) {
+ gd = ext2fs_group_desc(fs, fs->group_desc, i);
+ gd->bg_itable_unused = 0;
+ gd->bg_flags = EXT2_BG_INODE_ZEROED;
+ ext2fs_group_desc_csum_set(fs, i);
+ }
+ fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
+}
+
+static void disable_uninit_bg(ext2_filsys fs, __u32 csum_feature_flag)
+{
+ struct ext2_group_desc *gd;
+ int i;
+
+ /* Load bitmaps to ensure that the uninit ones get written out */
+ fs->super->s_feature_ro_compat |= csum_feature_flag;
+ ext2fs_read_bitmaps(fs);
+ ext2fs_mark_ib_dirty(fs);
+ ext2fs_mark_bb_dirty(fs);
+ fs->super->s_feature_ro_compat &= ~csum_feature_flag;
+
+ for (i = 0; i < fs->group_desc_count; i++) {
+ gd = ext2fs_group_desc(fs, fs->group_desc, i);
+ if ((gd->bg_flags & EXT2_BG_INODE_ZEROED) == 0) {
+ /*
+ * XXX what we really should do is zap
+ * uninitialized inode tables instead.
+ */
+ request_fsck_afterwards(fs);
+ break;
+ }
+ gd->bg_itable_unused = 0;
+ gd->bg_flags = 0;
+ ext2fs_group_desc_csum_set(fs, i);
+ }
+ fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
+}
+
/*
* Update the feature set as provided by the user.
*/
@@ -887,6 +934,21 @@ mmp_error:
if (check_fsck_needed(fs))
exit(1);
rewrite_checksums = 1;
+ /* metadata_csum supersedes uninit_bg */
+ fs->super->s_feature_ro_compat &=
+ ~EXT4_FEATURE_RO_COMPAT_GDT_CSUM;
+
+ /* if uninit_bg was previously off, rewrite group desc */
+ if (!(old_features[E2P_FEATURE_RO_INCOMPAT] &
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM))
+ enable_uninit_bg(fs);
+
+ /*
+ * Since metadata_csum supersedes uninit_bg, pretend like
+ * uninit_bg has been off all along.
+ */
+ old_features[E2P_FEATURE_RO_INCOMPAT] &=
+ ~EXT4_FEATURE_RO_COMPAT_GDT_CSUM;
}
if (FEATURE_OFF(E2P_FEATURE_RO_INCOMPAT,
@@ -894,37 +956,40 @@ mmp_error:
if (check_fsck_needed(fs))
exit(1);
rewrite_checksums = 1;
+ /*
+ * If we're turning off metadata_csum and not turning on
+ * uninit_bg, rewrite group desc.
+ */
+ if (!(fs->super->s_feature_ro_compat &
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM))
+ disable_uninit_bg(fs,
+ EXT4_FEATURE_RO_COMPAT_METADATA_CSUM);
+ else
+ /*
+ * metadata_csum previously provided uninit_bg, so if
+ * we're also setting the uninit_bg feature bit,
+ * pretend like it was previously enabled. Checksums
+ * will be rewritten with crc16 later.
+ */
+ old_features[E2P_FEATURE_RO_INCOMPAT] |=
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM;
}
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);
- gd->bg_itable_unused = 0;
- gd->bg_flags = EXT2_BG_INODE_ZEROED;
- ext2fs_group_desc_csum_set(fs, i);
- }
- fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
+ /* Do not enable uninit_bg when metadata_csum enabled */
+ if (fs->super->s_feature_ro_compat &
+ EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)
+ fs->super->s_feature_ro_compat &=
+ ~EXT4_FEATURE_RO_COMPAT_GDT_CSUM;
+ else
+ enable_uninit_bg(fs);
}
if (FEATURE_OFF(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);
- if ((gd->bg_flags & EXT2_BG_INODE_ZEROED) == 0) {
- /*
- * XXX what we really should do is zap
- * uninitialized inode tables instead.
- */
- request_fsck_afterwards(fs);
- break;
- }
- gd->bg_itable_unused = 0;
- gd->bg_flags = 0;
- gd->bg_checksum = 0;
- }
- fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
- }
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM))
+ disable_uninit_bg(fs,
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM);
if (FEATURE_ON(E2P_FEATURE_RO_INCOMPAT,
EXT4_FEATURE_RO_COMPAT_QUOTA)) {
@@ -2498,8 +2563,7 @@ retry_open:
exit(1);
}
- if (sb->s_feature_ro_compat &
- EXT4_FEATURE_RO_COMPAT_GDT_CSUM) {
+ if (ext2fs_has_group_desc_csum(fs)) {
/*
* Determine if the block group checksums are
* correct so we know whether or not to set