ext4: mark block group as corrupt on block bitmap error
[pandora-kernel.git] / fs / ext4 / balloc.c
index 5833939..d9b66c4 100644 (file)
@@ -38,8 +38,8 @@ ext4_group_t ext4_get_group_number(struct super_block *sb,
        ext4_group_t group;
 
        if (test_opt2(sb, STD_GROUP_SIZE))
-               group = (le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block) +
-                        block) >>
+               group = (block -
+                        le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block)) >>
                        (EXT4_BLOCK_SIZE_BITS(sb) + EXT4_CLUSTER_BITS(sb) + 3);
        else
                ext4_get_group_no_and_offset(sb, block, &group, NULL);
@@ -305,7 +305,7 @@ struct ext4_group_desc * ext4_get_group_desc(struct super_block *sb,
  */
 static ext4_fsblk_t ext4_valid_block_bitmap(struct super_block *sb,
                                            struct ext4_group_desc *desc,
-                                           unsigned int block_group,
+                                           ext4_group_t block_group,
                                            struct buffer_head *bh)
 {
        ext4_grpblk_t offset;
@@ -352,10 +352,11 @@ static ext4_fsblk_t ext4_valid_block_bitmap(struct super_block *sb,
 
 void ext4_validate_block_bitmap(struct super_block *sb,
                               struct ext4_group_desc *desc,
-                              unsigned int block_group,
+                              ext4_group_t block_group,
                               struct buffer_head *bh)
 {
        ext4_fsblk_t    blk;
+       struct ext4_group_info *grp = ext4_get_group_info(sb, block_group);
 
        if (buffer_verified(bh))
                return;
@@ -366,12 +367,14 @@ void ext4_validate_block_bitmap(struct super_block *sb,
                ext4_unlock_group(sb, block_group);
                ext4_error(sb, "bg %u: block %llu: invalid block bitmap",
                           block_group, blk);
+               set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state);
                return;
        }
        if (unlikely(!ext4_block_bitmap_csum_verify(sb, block_group,
                        desc, bh))) {
                ext4_unlock_group(sb, block_group);
                ext4_error(sb, "bg %u: bad block bitmap checksum", block_group);
+               set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state);
                return;
        }
        set_buffer_verified(bh);
@@ -445,7 +448,10 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group)
        return bh;
 verify:
        ext4_validate_block_bitmap(sb, desc, block_group, bh);
-       return bh;
+       if (buffer_verified(bh))
+               return bh;
+       put_bh(bh);
+       return NULL;
 }
 
 /* Returns 0 on success, 1 on error */
@@ -469,7 +475,8 @@ int ext4_wait_block_bitmap(struct super_block *sb, ext4_group_t block_group,
        clear_buffer_new(bh);
        /* Panic or remount fs read-only if block bitmap is invalid */
        ext4_validate_block_bitmap(sb, desc, block_group, bh);
-       return 0;
+       /* ...but check for error just in case errors=continue. */
+       return !buffer_verified(bh);
 }
 
 struct buffer_head *