aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4/super.c')
-rw-r--r--fs/ext4/super.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 11a0a7078da7..f80c7e612829 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -122,6 +122,38 @@ static int ext4_verify_csum_type(struct super_block *sb,
122 return es->s_checksum_type == EXT4_CRC32C_CHKSUM; 122 return es->s_checksum_type == EXT4_CRC32C_CHKSUM;
123} 123}
124 124
125static __le32 ext4_superblock_csum(struct super_block *sb,
126 struct ext4_super_block *es)
127{
128 struct ext4_sb_info *sbi = EXT4_SB(sb);
129 int offset = offsetof(struct ext4_super_block, s_checksum);
130 __u32 csum;
131
132 csum = ext4_chksum(sbi, ~0, (char *)es, offset);
133
134 return cpu_to_le32(csum);
135}
136
137int ext4_superblock_csum_verify(struct super_block *sb,
138 struct ext4_super_block *es)
139{
140 if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
141 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
142 return 1;
143
144 return es->s_checksum == ext4_superblock_csum(sb, es);
145}
146
147void ext4_superblock_csum_set(struct super_block *sb,
148 struct ext4_super_block *es)
149{
150 if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
151 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
152 return;
153
154 es->s_checksum = ext4_superblock_csum(sb, es);
155}
156
125void *ext4_kvmalloc(size_t size, gfp_t flags) 157void *ext4_kvmalloc(size_t size, gfp_t flags)
126{ 158{
127 void *ret; 159 void *ret;
@@ -3057,6 +3089,20 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
3057 } 3089 }
3058 } 3090 }
3059 3091
3092 /* Check superblock checksum */
3093 if (!ext4_superblock_csum_verify(sb, es)) {
3094 ext4_msg(sb, KERN_ERR, "VFS: Found ext4 filesystem with "
3095 "invalid superblock checksum. Run e2fsck?");
3096 silent = 1;
3097 goto cantfind_ext4;
3098 }
3099
3100 /* Precompute checksum seed for all metadata */
3101 if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
3102 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
3103 sbi->s_csum_seed = ext4_chksum(sbi, ~0, es->s_uuid,
3104 sizeof(es->s_uuid));
3105
3060 /* Set defaults before we parse the mount options */ 3106 /* Set defaults before we parse the mount options */
3061 def_mount_opts = le32_to_cpu(es->s_default_mount_opts); 3107 def_mount_opts = le32_to_cpu(es->s_default_mount_opts);
3062 set_opt(sb, INIT_INODE_TABLE); 3108 set_opt(sb, INIT_INODE_TABLE);
@@ -4059,6 +4105,7 @@ static int ext4_commit_super(struct super_block *sb, int sync)
4059 &EXT4_SB(sb)->s_freeinodes_counter)); 4105 &EXT4_SB(sb)->s_freeinodes_counter));
4060 sb->s_dirt = 0; 4106 sb->s_dirt = 0;
4061 BUFFER_TRACE(sbh, "marking dirty"); 4107 BUFFER_TRACE(sbh, "marking dirty");
4108 ext4_superblock_csum_set(sb, es);
4062 mark_buffer_dirty(sbh); 4109 mark_buffer_dirty(sbh);
4063 if (sync) { 4110 if (sync) {
4064 error = sync_dirty_buffer(sbh); 4111 error = sync_dirty_buffer(sbh);