ext4: fix block bitmap validation when bigalloc, ^flex_bg
authorDarrick J. Wong <darrick.wong@oracle.com>
Mon, 12 May 2014 14:17:55 +0000 (10:17 -0400)
committerBen Hutchings <ben@decadent.org.uk>
Thu, 31 May 2018 23:30:01 +0000 (00:30 +0100)
commit e674e5cbd0942b42a12106ac0be8330f4301bef4 upstream.

On a bigalloc,^flex_bg filesystem, the ext4_valid_block_bitmap
function fails to convert from blocks to clusters when spot-checking
the validity of the bitmap block that we've just read from disk.  This
causes ext4 to think that the bitmap is garbage, which results in the
block group being taken offline when it's not necessary.  Add in the
necessary EXT4_B2C() calls to perform the conversions.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
[bwh: Backported to 3.2: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
fs/ext4/balloc.c

index 2845a1f..f91de78 100644 (file)
@@ -278,6 +278,7 @@ static int ext4_valid_block_bitmap(struct super_block *sb,
                                        unsigned int block_group,
                                        struct buffer_head *bh)
 {
                                        unsigned int block_group,
                                        struct buffer_head *bh)
 {
+       struct ext4_sb_info *sbi = EXT4_SB(sb);
        ext4_grpblk_t offset;
        ext4_grpblk_t next_zero_bit;
        ext4_fsblk_t bitmap_blk;
        ext4_grpblk_t offset;
        ext4_grpblk_t next_zero_bit;
        ext4_fsblk_t bitmap_blk;
@@ -297,14 +298,14 @@ static int ext4_valid_block_bitmap(struct super_block *sb,
        /* check whether block bitmap block number is set */
        bitmap_blk = ext4_block_bitmap(sb, desc);
        offset = bitmap_blk - group_first_block;
        /* check whether block bitmap block number is set */
        bitmap_blk = ext4_block_bitmap(sb, desc);
        offset = bitmap_blk - group_first_block;
-       if (!ext4_test_bit(offset, bh->b_data))
+       if (!ext4_test_bit(EXT4_B2C(sbi, offset), bh->b_data))
                /* bad block bitmap */
                goto err_out;
 
        /* check whether the inode bitmap block number is set */
        bitmap_blk = ext4_inode_bitmap(sb, desc);
        offset = bitmap_blk - group_first_block;
                /* bad block bitmap */
                goto err_out;
 
        /* check whether the inode bitmap block number is set */
        bitmap_blk = ext4_inode_bitmap(sb, desc);
        offset = bitmap_blk - group_first_block;
-       if (!ext4_test_bit(offset, bh->b_data))
+       if (!ext4_test_bit(EXT4_B2C(sbi, offset), bh->b_data))
                /* bad block bitmap */
                goto err_out;
 
                /* bad block bitmap */
                goto err_out;
 
@@ -312,9 +313,10 @@ static int ext4_valid_block_bitmap(struct super_block *sb,
        bitmap_blk = ext4_inode_table(sb, desc);
        offset = bitmap_blk - group_first_block;
        next_zero_bit = ext4_find_next_zero_bit(bh->b_data,
        bitmap_blk = ext4_inode_table(sb, desc);
        offset = bitmap_blk - group_first_block;
        next_zero_bit = ext4_find_next_zero_bit(bh->b_data,
-                               offset + EXT4_SB(sb)->s_itb_per_group,
-                               offset);
-       if (next_zero_bit >= offset + EXT4_SB(sb)->s_itb_per_group)
+                       EXT4_B2C(sbi, offset + EXT4_SB(sb)->s_itb_per_group),
+                       EXT4_B2C(sbi, offset));
+       if (next_zero_bit >=
+           EXT4_B2C(sbi, offset + EXT4_SB(sb)->s_itb_per_group))
                /* good bitmap for inode tables */
                return 1;
 
                /* good bitmap for inode tables */
                return 1;