aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/super.c
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2012-10-10 01:06:58 -0400
committerTheodore Ts'o <tytso@mit.edu>2012-10-10 01:06:58 -0400
commit06db49e68ae70cf16819b85a14057acb2820776a (patch)
tree4b9ac4222aef2c6605ffea5e0986b91be6e2c797 /fs/ext4/super.c
parentdee1f973ca341c266229faa5a1a5bb268bed3531 (diff)
ext4: fix metadata checksum calculation for the superblock
The function ext4_handle_dirty_super() was calculating the superblock on the wrong block data. As a result, when the superblock is modified while it is mounted (most commonly, when inodes are added or removed from the orphan list), the superblock checksum would be wrong. We didn't notice because the superblock *was* being correctly calculated in ext4_commit_super(), and this would get called when the file system was unmounted. So the problem only became obvious if the system crashed while the file system was mounted. Fix this by removing the poorly designed function signature for ext4_superblock_csum_set(); if it only took a single argument, the pointer to a struct superblock, the ambiguity which caused this mistake would have been impossible. Reported-by: George Spelvin <linux@horizon.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> Cc: stable@vger.kernel.org
Diffstat (limited to 'fs/ext4/super.c')
-rw-r--r--fs/ext4/super.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 982f6fc22c88..5ededf135335 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -143,9 +143,10 @@ int ext4_superblock_csum_verify(struct super_block *sb,
143 return es->s_checksum == ext4_superblock_csum(sb, es); 143 return es->s_checksum == ext4_superblock_csum(sb, es);
144} 144}
145 145
146void ext4_superblock_csum_set(struct super_block *sb, 146void ext4_superblock_csum_set(struct super_block *sb)
147 struct ext4_super_block *es)
148{ 147{
148 struct ext4_super_block *es = EXT4_SB(sb)->s_es;
149
149 if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, 150 if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
150 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) 151 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
151 return; 152 return;
@@ -4387,7 +4388,7 @@ static int ext4_commit_super(struct super_block *sb, int sync)
4387 cpu_to_le32(percpu_counter_sum_positive( 4388 cpu_to_le32(percpu_counter_sum_positive(
4388 &EXT4_SB(sb)->s_freeinodes_counter)); 4389 &EXT4_SB(sb)->s_freeinodes_counter));
4389 BUFFER_TRACE(sbh, "marking dirty"); 4390 BUFFER_TRACE(sbh, "marking dirty");
4390 ext4_superblock_csum_set(sb, es); 4391 ext4_superblock_csum_set(sb);
4391 mark_buffer_dirty(sbh); 4392 mark_buffer_dirty(sbh);
4392 if (sync) { 4393 if (sync) {
4393 error = sync_dirty_buffer(sbh); 4394 error = sync_dirty_buffer(sbh);