ext4: mark the group block bitmap as corrupted before reporting an error
authorBaokun Li <libaokun1@huawei.com>
Thu, 4 Jan 2024 14:20:40 +0000 (22:20 +0800)
committerTheodore Ts'o <tytso@mit.edu>
Thu, 18 Jan 2024 15:50:24 +0000 (10:50 -0500)
Otherwise unlocking the group in ext4_grp_locked_error may allow other
processes to modify the core block bitmap that is known to be corrupt.

Signed-off-by: Baokun Li <libaokun1@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Link: https://lore.kernel.org/r/20240104142040.2835097-9-libaokun1@huawei.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
fs/ext4/mballoc.c

index 2069d768c619881810d7c65bca6a2147c54c7a24..c7f63dd7afccb0bf63f12e8fe475163660d36eaa 100644 (file)
@@ -564,14 +564,14 @@ static void mb_free_blocks_double(struct inode *inode, struct ext4_buddy *e4b,
 
                        blocknr = ext4_group_first_block_no(sb, e4b->bd_group);
                        blocknr += EXT4_C2B(EXT4_SB(sb), first + i);
+                       ext4_mark_group_bitmap_corrupted(sb, e4b->bd_group,
+                                       EXT4_GROUP_INFO_BBITMAP_CORRUPT);
                        ext4_grp_locked_error(sb, e4b->bd_group,
                                              inode ? inode->i_ino : 0,
                                              blocknr,
                                              "freeing block already freed "
                                              "(bit %u)",
                                              first + i);
-                       ext4_mark_group_bitmap_corrupted(sb, e4b->bd_group,
-                                       EXT4_GROUP_INFO_BBITMAP_CORRUPT);
                }
                mb_clear_bit(first + i, e4b->bd_info->bb_bitmap);
        }
@@ -1933,12 +1933,12 @@ static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b,
 
                blocknr = ext4_group_first_block_no(sb, e4b->bd_group);
                blocknr += EXT4_C2B(sbi, block);
+               ext4_mark_group_bitmap_corrupted(sb, e4b->bd_group,
+                               EXT4_GROUP_INFO_BBITMAP_CORRUPT);
                ext4_grp_locked_error(sb, e4b->bd_group,
                                      inode ? inode->i_ino : 0, blocknr,
                                      "freeing already freed block (bit %u); block bitmap corrupt.",
                                      block);
-               ext4_mark_group_bitmap_corrupted(sb, e4b->bd_group,
-                               EXT4_GROUP_INFO_BBITMAP_CORRUPT);
                return;
        }
 
@@ -2406,12 +2406,12 @@ void ext4_mb_simple_scan_group(struct ext4_allocation_context *ac,
 
                k = mb_find_next_zero_bit(buddy, max, 0);
                if (k >= max) {
+                       ext4_mark_group_bitmap_corrupted(ac->ac_sb,
+                                       e4b->bd_group,
+                                       EXT4_GROUP_INFO_BBITMAP_CORRUPT);
                        ext4_grp_locked_error(ac->ac_sb, e4b->bd_group, 0, 0,
                                "%d free clusters of order %d. But found 0",
                                grp->bb_counters[i], i);
-                       ext4_mark_group_bitmap_corrupted(ac->ac_sb,
-                                        e4b->bd_group,
-                                       EXT4_GROUP_INFO_BBITMAP_CORRUPT);
                        break;
                }
                ac->ac_found++;
@@ -2462,12 +2462,12 @@ void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac,
                         * free blocks even though group info says we
                         * have free blocks
                         */
+                       ext4_mark_group_bitmap_corrupted(sb, e4b->bd_group,
+                                       EXT4_GROUP_INFO_BBITMAP_CORRUPT);
                        ext4_grp_locked_error(sb, e4b->bd_group, 0, 0,
                                        "%d free clusters as per "
                                        "group info. But bitmap says 0",
                                        free);
-                       ext4_mark_group_bitmap_corrupted(sb, e4b->bd_group,
-                                       EXT4_GROUP_INFO_BBITMAP_CORRUPT);
                        break;
                }
 
@@ -2493,12 +2493,12 @@ void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac,
                if (WARN_ON(ex.fe_len <= 0))
                        break;
                if (free < ex.fe_len) {
+                       ext4_mark_group_bitmap_corrupted(sb, e4b->bd_group,
+                                       EXT4_GROUP_INFO_BBITMAP_CORRUPT);
                        ext4_grp_locked_error(sb, e4b->bd_group, 0, 0,
                                        "%d free clusters as per "
                                        "group info. But got %d blocks",
                                        free, ex.fe_len);
-                       ext4_mark_group_bitmap_corrupted(sb, e4b->bd_group,
-                                       EXT4_GROUP_INFO_BBITMAP_CORRUPT);
                        /*
                         * The number of free blocks differs. This mostly
                         * indicate that the bitmap is corrupt. So exit