ext4: Allow read/only mounts with corrupted block group checksums
authorTheodore Ts'o <tytso@mit.edu>
Sat, 26 Jul 2008 18:34:21 +0000 (14:34 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Sat, 26 Jul 2008 18:34:21 +0000 (14:34 -0400)
If the block group checksums are corrupted, still allow the mount to
succeed, so e2fsck can have a chance to try to fix things up.  Add
code in the remount r/w path to make sure the block group checksums
are valid before allowing the filesystem to be remounted read/write.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
fs/ext4/super.c

index b5479b1dff14b7513b077ddc2c920ceffc67b76d..876e1c620365ccc40ffb0449337e66636bad8c66 100644 (file)
@@ -1626,7 +1626,8 @@ static int ext4_check_descriptors(struct super_block *sb)
                               "Checksum for group %lu failed (%u!=%u)\n",
                               i, le16_to_cpu(ext4_group_desc_csum(sbi, i,
                               gdp)), le16_to_cpu(gdp->bg_checksum));
-                       return 0;
+                       if (!(sb->s_flags & MS_RDONLY))
+                               return 0;
                }
                if (!flexbg_flag)
                        first_block += EXT4_BLOCKS_PER_GROUP(sb);
@@ -2961,6 +2962,7 @@ static int ext4_remount (struct super_block * sb, int * flags, char * data)
        ext4_fsblk_t n_blocks_count = 0;
        unsigned long old_sb_flags;
        struct ext4_mount_options old_opts;
+       ext4_group_t g;
        int err;
 #ifdef CONFIG_QUOTA
        int i;
@@ -3038,6 +3040,26 @@ static int ext4_remount (struct super_block * sb, int * flags, char * data)
                                goto restore_opts;
                        }
 
+                       /*
+                        * Make sure the group descriptor checksums
+                        * are sane.  If they aren't, refuse to
+                        * remount r/w.
+                        */
+                       for (g = 0; g < sbi->s_groups_count; g++) {
+                               struct ext4_group_desc *gdp =
+                                       ext4_get_group_desc(sb, g, NULL);
+
+                               if (!ext4_group_desc_csum_verify(sbi, g, gdp)) {
+                                       printk(KERN_ERR
+              "EXT4-fs: ext4_remount: "
+               "Checksum for group %lu failed (%u!=%u)\n",
+               g, le16_to_cpu(ext4_group_desc_csum(sbi, g, gdp)),
+                                              le16_to_cpu(gdp->bg_checksum));
+                                       err = -EINVAL;
+                                       goto restore_opts;
+                               }
+                       }
+
                        /*
                         * If we have an unprocessed orphan list hanging
                         * around from a previously readonly bdev mount,