Commit 9af0b3d1 authored by Wang Shilong's avatar Wang Shilong Committed by Theodore Ts'o

ext4: fix race when setting the bitmap corrupted flag

Whenever we hit block or inode bitmap corruptions we set
bit and then reduce this block group free inode/clusters
counter to expose right available space.

However some of ext4_mark_group_bitmap_corrupted() is called
inside group spinlock, some are not, this could make it happen
that we double reduce one block group free counters from system.

Always hold group spinlock for it could fix it, but it looks
a little heavy, we could use test_and_set_bit() to fix race
problems here.
Signed-off-by: default avatarWang Shilong <wshilong@ddn.com>
Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
Cc: stable@vger.kernel.org
parent f39b3f45
...@@ -795,26 +795,26 @@ void ext4_mark_group_bitmap_corrupted(struct super_block *sb, ...@@ -795,26 +795,26 @@ void ext4_mark_group_bitmap_corrupted(struct super_block *sb,
struct ext4_sb_info *sbi = EXT4_SB(sb); struct ext4_sb_info *sbi = EXT4_SB(sb);
struct ext4_group_info *grp = ext4_get_group_info(sb, group); struct ext4_group_info *grp = ext4_get_group_info(sb, group);
struct ext4_group_desc *gdp = ext4_get_group_desc(sb, group, NULL); struct ext4_group_desc *gdp = ext4_get_group_desc(sb, group, NULL);
int ret;
if ((flags & EXT4_GROUP_INFO_BBITMAP_CORRUPT) && if (flags & EXT4_GROUP_INFO_BBITMAP_CORRUPT) {
!EXT4_MB_GRP_BBITMAP_CORRUPT(grp)) { ret = ext4_test_and_set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT,
&grp->bb_state);
if (!ret)
percpu_counter_sub(&sbi->s_freeclusters_counter, percpu_counter_sub(&sbi->s_freeclusters_counter,
grp->bb_free); grp->bb_free);
set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT,
&grp->bb_state);
} }
if ((flags & EXT4_GROUP_INFO_IBITMAP_CORRUPT) && if (flags & EXT4_GROUP_INFO_IBITMAP_CORRUPT) {
!EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) { ret = ext4_test_and_set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT,
if (gdp) { &grp->bb_state);
if (!ret && gdp) {
int count; int count;
count = ext4_free_inodes_count(sb, gdp); count = ext4_free_inodes_count(sb, gdp);
percpu_counter_sub(&sbi->s_freeinodes_counter, percpu_counter_sub(&sbi->s_freeinodes_counter,
count); count);
} }
set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT,
&grp->bb_state);
} }
} }
......
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