ext4: fix block bitmap validation when bigalloc, ^flex_bg
[pandora-kernel.git] / fs / ext4 / balloc.c
index 6ea7b14..59c3ba8 100644 (file)
@@ -307,6 +307,7 @@ static ext4_fsblk_t ext4_valid_block_bitmap(struct super_block *sb,
                                            ext4_group_t 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 blk;
@@ -326,14 +327,14 @@ static ext4_fsblk_t ext4_valid_block_bitmap(struct super_block *sb,
        /* check whether block bitmap block number is set */
        blk = ext4_block_bitmap(sb, desc);
        offset = 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 */
                return blk;
 
        /* check whether the inode bitmap block number is set */
        blk = ext4_inode_bitmap(sb, desc);
        offset = 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 */
                return blk;
 
@@ -341,9 +342,10 @@ static ext4_fsblk_t ext4_valid_block_bitmap(struct super_block *sb,
        blk = ext4_inode_table(sb, desc);
        offset = 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))
                /* bad bitmap for inode tables */
                return blk;
        return 0;
@@ -667,7 +669,7 @@ ext4_fsblk_t ext4_count_free_clusters(struct super_block *sb)
                        continue;
 
                x = ext4_count_free(bitmap_bh->b_data,
-                                   EXT4_BLOCKS_PER_GROUP(sb) / 8);
+                                   EXT4_CLUSTERS_PER_GROUP(sb) / 8);
                printk(KERN_DEBUG "group %u: stored = %d, counted = %u\n",
                        i, ext4_free_group_clusters(sb, gdp), x);
                bitmap_count += x;
@@ -708,16 +710,6 @@ static inline int test_root(ext4_group_t a, int b)
        }
 }
 
-static int ext4_group_sparse(ext4_group_t group)
-{
-       if (group <= 1)
-               return 1;
-       if (!(group & 1))
-               return 0;
-       return (test_root(group, 7) || test_root(group, 5) ||
-               test_root(group, 3));
-}
-
 /**
  *     ext4_bg_has_super - number of blocks used by the superblock in group
  *     @sb: superblock for filesystem
@@ -728,11 +720,26 @@ static int ext4_group_sparse(ext4_group_t group)
  */
 int ext4_bg_has_super(struct super_block *sb, ext4_group_t group)
 {
-       if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
-                               EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER) &&
-                       !ext4_group_sparse(group))
+       struct ext4_super_block *es = EXT4_SB(sb)->s_es;
+
+       if (group == 0)
+               return 1;
+       if (EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_SPARSE_SUPER2)) {
+               if (group == le32_to_cpu(es->s_backup_bgs[0]) ||
+                   group == le32_to_cpu(es->s_backup_bgs[1]))
+                       return 1;
                return 0;
-       return 1;
+       }
+       if ((group <= 1) || !EXT4_HAS_RO_COMPAT_FEATURE(sb,
+                                       EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER))
+               return 1;
+       if (!(group & 1))
+               return 0;
+       if (test_root(group, 3) || (test_root(group, 5)) ||
+           test_root(group, 7))
+               return 1;
+
+       return 0;
 }
 
 static unsigned long ext4_bg_num_gdb_meta(struct super_block *sb,