Commit 4274f516 authored by Theodore Ts'o's avatar Theodore Ts'o

ext4: recalucate superblock checksum after updating free blocks/inodes

When mounting the superblock, ext4_fill_super() calculates the free
blocks and free inodes and stores them in the superblock.  It's not
strictly necessary, since we don't use them any more, but it's nice to
keep them roughly aligned to reality.

Since it's not critical for file system correctness, the code doesn't
call ext4_commit_super().  The problem is that it's in
ext4_commit_super() that we recalculate the superblock checksum.  So
if we're not going to call ext4_commit_super(), we need to call
ext4_superblock_csum_set() to make sure the superblock checksum is
consistent.

Most of the time, this doesn't matter, since we end up calling
ext4_commit_super() very soon thereafter, and definitely by the time
the file system is unmounted.  However, it doesn't work in this
sequence:

mke2fs -Fq -t ext4 /dev/vdc 128M
mount /dev/vdc /vdc
cp xfstests/git-versions /vdc
godown /vdc
umount /vdc
mount /dev/vdc
tune2fs -l /dev/vdc

With this commit, the "tune2fs -l" no longer fails.
Reported-by: default avatarChengguang Xu <cgxu519@gmx.com>
Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
Cc: stable@vger.kernel.org

parent bcd8e91f
...@@ -4378,11 +4378,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) ...@@ -4378,11 +4378,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
block = ext4_count_free_clusters(sb); block = ext4_count_free_clusters(sb);
ext4_free_blocks_count_set(sbi->s_es, ext4_free_blocks_count_set(sbi->s_es,
EXT4_C2B(sbi, block)); EXT4_C2B(sbi, block));
ext4_superblock_csum_set(sb);
err = percpu_counter_init(&sbi->s_freeclusters_counter, block, err = percpu_counter_init(&sbi->s_freeclusters_counter, block,
GFP_KERNEL); GFP_KERNEL);
if (!err) { if (!err) {
unsigned long freei = ext4_count_free_inodes(sb); unsigned long freei = ext4_count_free_inodes(sb);
sbi->s_es->s_free_inodes_count = cpu_to_le32(freei); sbi->s_es->s_free_inodes_count = cpu_to_le32(freei);
ext4_superblock_csum_set(sb);
err = percpu_counter_init(&sbi->s_freeinodes_counter, freei, err = percpu_counter_init(&sbi->s_freeinodes_counter, freei,
GFP_KERNEL); GFP_KERNEL);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment