These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / fs / ext4 / balloc.c
index 955bf49..fe1f50f 100644 (file)
@@ -203,7 +203,7 @@ static int ext4_init_block_bitmap(struct super_block *sb,
                                           count);
                }
                set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state);
-               return -EIO;
+               return -EFSBADCRC;
        }
        memset(bh->b_data, 0, sb->s_blocksize);
 
@@ -213,7 +213,7 @@ static int ext4_init_block_bitmap(struct super_block *sb,
 
        start = ext4_group_first_block_no(sb, block_group);
 
-       if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG))
+       if (ext4_has_feature_flex_bg(sb))
                flex_bg = 1;
 
        /* Set bits for block and inode bitmaps, and inode table */
@@ -322,7 +322,7 @@ static ext4_fsblk_t ext4_valid_block_bitmap(struct super_block *sb,
        ext4_fsblk_t blk;
        ext4_fsblk_t group_first_block;
 
-       if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
+       if (ext4_has_feature_flex_bg(sb)) {
                /* with FLEX_BG, the inode/block bitmaps and itable
                 * blocks may not be in the group at all
                 * so the bitmap validation will be skipped for those groups
@@ -360,42 +360,45 @@ static ext4_fsblk_t ext4_valid_block_bitmap(struct super_block *sb,
        return 0;
 }
 
-static void ext4_validate_block_bitmap(struct super_block *sb,
-                                      struct ext4_group_desc *desc,
-                                      ext4_group_t block_group,
-                                      struct buffer_head *bh)
+static int ext4_validate_block_bitmap(struct super_block *sb,
+                                     struct ext4_group_desc *desc,
+                                     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);
        struct ext4_sb_info *sbi = EXT4_SB(sb);
 
        if (buffer_verified(bh))
-               return;
+               return 0;
+       if (EXT4_MB_GRP_BBITMAP_CORRUPT(grp))
+               return -EFSCORRUPTED;
 
        ext4_lock_group(sb, block_group);
-       blk = ext4_valid_block_bitmap(sb, desc, block_group, bh);
-       if (unlikely(blk != 0)) {
+       if (unlikely(!ext4_block_bitmap_csum_verify(sb, block_group,
+                       desc, bh))) {
                ext4_unlock_group(sb, block_group);
-               ext4_error(sb, "bg %u: block %llu: invalid block bitmap",
-                          block_group, blk);
+               ext4_error(sb, "bg %u: bad block bitmap checksum", block_group);
                if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp))
                        percpu_counter_sub(&sbi->s_freeclusters_counter,
                                           grp->bb_free);
                set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state);
-               return;
+               return -EFSBADCRC;
        }
-       if (unlikely(!ext4_block_bitmap_csum_verify(sb, block_group,
-                       desc, bh))) {
+       blk = ext4_valid_block_bitmap(sb, desc, block_group, bh);
+       if (unlikely(blk != 0)) {
                ext4_unlock_group(sb, block_group);
-               ext4_error(sb, "bg %u: bad block bitmap checksum", block_group);
+               ext4_error(sb, "bg %u: block %llu: invalid block bitmap",
+                          block_group, blk);
                if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp))
                        percpu_counter_sub(&sbi->s_freeclusters_counter,
                                           grp->bb_free);
                set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state);
-               return;
+               return -EFSCORRUPTED;
        }
        set_buffer_verified(bh);
        ext4_unlock_group(sb, block_group);
+       return 0;
 }
 
 /**
@@ -414,17 +417,18 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group)
        struct ext4_group_desc *desc;
        struct buffer_head *bh;
        ext4_fsblk_t bitmap_blk;
+       int err;
 
        desc = ext4_get_group_desc(sb, block_group, NULL);
        if (!desc)
-               return NULL;
+               return ERR_PTR(-EFSCORRUPTED);
        bitmap_blk = ext4_block_bitmap(sb, desc);
        bh = sb_getblk(sb, bitmap_blk);
        if (unlikely(!bh)) {
                ext4_error(sb, "Cannot get buffer for block bitmap - "
                           "block_group = %u, block_bitmap = %llu",
                           block_group, bitmap_blk);
-               return NULL;
+               return ERR_PTR(-ENOMEM);
        }
 
        if (bitmap_uptodate(bh))
@@ -437,16 +441,17 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group)
        }
        ext4_lock_group(sb, block_group);
        if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
-               int err;
-
                err = ext4_init_block_bitmap(sb, bh, block_group, desc);
                set_bitmap_uptodate(bh);
                set_buffer_uptodate(bh);
                ext4_unlock_group(sb, block_group);
                unlock_buffer(bh);
-               if (err)
-                       ext4_error(sb, "Checksum bad for grp %u", block_group);
-               return bh;
+               if (err) {
+                       ext4_error(sb, "Failed to init block bitmap for group "
+                                  "%u: %d", block_group, err);
+                       goto out;
+               }
+               goto verify;
        }
        ext4_unlock_group(sb, block_group);
        if (buffer_uptodate(bh)) {
@@ -468,11 +473,13 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group)
        submit_bh(READ | REQ_META | REQ_PRIO, bh);
        return bh;
 verify:
-       ext4_validate_block_bitmap(sb, desc, block_group, bh);
-       if (buffer_verified(bh))
-               return bh;
+       err = ext4_validate_block_bitmap(sb, desc, block_group, bh);
+       if (err)
+               goto out;
+       return bh;
+out:
        put_bh(bh);
-       return NULL;
+       return ERR_PTR(err);
 }
 
 /* Returns 0 on success, 1 on error */
@@ -485,32 +492,32 @@ int ext4_wait_block_bitmap(struct super_block *sb, ext4_group_t block_group,
                return 0;
        desc = ext4_get_group_desc(sb, block_group, NULL);
        if (!desc)
-               return 1;
+               return -EFSCORRUPTED;
        wait_on_buffer(bh);
        if (!buffer_uptodate(bh)) {
                ext4_error(sb, "Cannot read block bitmap - "
                           "block_group = %u, block_bitmap = %llu",
                           block_group, (unsigned long long) bh->b_blocknr);
-               return 1;
+               return -EIO;
        }
        clear_buffer_new(bh);
        /* Panic or remount fs read-only if block bitmap is invalid */
-       ext4_validate_block_bitmap(sb, desc, block_group, bh);
-       /* ...but check for error just in case errors=continue. */
-       return !buffer_verified(bh);
+       return ext4_validate_block_bitmap(sb, desc, block_group, bh);
 }
 
 struct buffer_head *
 ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group)
 {
        struct buffer_head *bh;
+       int err;
 
        bh = ext4_read_block_bitmap_nowait(sb, block_group);
-       if (!bh)
-               return NULL;
-       if (ext4_wait_block_bitmap(sb, block_group, bh)) {
+       if (IS_ERR(bh))
+               return bh;
+       err = ext4_wait_block_bitmap(sb, block_group, bh);
+       if (err) {
                put_bh(bh);
-               return NULL;
+               return ERR_PTR(err);
        }
        return bh;
 }
@@ -681,8 +688,10 @@ ext4_fsblk_t ext4_count_free_clusters(struct super_block *sb)
                        desc_count += ext4_free_group_clusters(sb, gdp);
                brelse(bitmap_bh);
                bitmap_bh = ext4_read_block_bitmap(sb, i);
-               if (bitmap_bh == NULL)
+               if (IS_ERR(bitmap_bh)) {
+                       bitmap_bh = NULL;
                        continue;
+               }
 
                x = ext4_count_free(bitmap_bh->b_data,
                                    EXT4_CLUSTERS_PER_GROUP(sb) / 8);
@@ -740,14 +749,13 @@ int ext4_bg_has_super(struct super_block *sb, ext4_group_t group)
 
        if (group == 0)
                return 1;
-       if (EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_SPARSE_SUPER2)) {
+       if (ext4_has_feature_sparse_super2(sb)) {
                if (group == le32_to_cpu(es->s_backup_bgs[0]) ||
                    group == le32_to_cpu(es->s_backup_bgs[1]))
                        return 1;
                return 0;
        }
-       if ((group <= 1) || !EXT4_HAS_RO_COMPAT_FEATURE(sb,
-                                       EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER))
+       if ((group <= 1) || !ext4_has_feature_sparse_super(sb))
                return 1;
        if (!(group & 1))
                return 0;
@@ -776,7 +784,7 @@ static unsigned long ext4_bg_num_gdb_nometa(struct super_block *sb,
        if (!ext4_bg_has_super(sb, group))
                return 0;
 
-       if (EXT4_HAS_INCOMPAT_FEATURE(sb,EXT4_FEATURE_INCOMPAT_META_BG))
+       if (ext4_has_feature_meta_bg(sb))
                return le32_to_cpu(EXT4_SB(sb)->s_es->s_first_meta_bg);
        else
                return EXT4_SB(sb)->s_gdb_count;
@@ -797,8 +805,7 @@ unsigned long ext4_bg_num_gdb(struct super_block *sb, ext4_group_t group)
                        le32_to_cpu(EXT4_SB(sb)->s_es->s_first_meta_bg);
        unsigned long metagroup = group / EXT4_DESC_PER_BLOCK(sb);
 
-       if (!EXT4_HAS_INCOMPAT_FEATURE(sb,EXT4_FEATURE_INCOMPAT_META_BG) ||
-                       metagroup < first_meta_bg)
+       if (!ext4_has_feature_meta_bg(sb) || metagroup < first_meta_bg)
                return ext4_bg_num_gdb_nometa(sb, group);
 
        return ext4_bg_num_gdb_meta(sb,group);
@@ -818,7 +825,7 @@ static unsigned ext4_num_base_meta_clusters(struct super_block *sb,
        /* Check for superblock and gdt backups in this group */
        num = ext4_bg_has_super(sb, block_group);
 
-       if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_META_BG) ||
+       if (!ext4_has_feature_meta_bg(sb) ||
            block_group < le32_to_cpu(sbi->s_es->s_first_meta_bg) *
                          sbi->s_desc_per_block) {
                if (num) {