]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - fs/ext4/mballoc.c
ext4: grow the s_flex_groups array as needed when resizing
[mirror_ubuntu-bionic-kernel.git] / fs / ext4 / mballoc.c
index 1cd6994fc446008b74dc9b77863edf0f24e14c33..6873571c9f4482fe017e71c3514acfc203d56223 100644 (file)
@@ -969,7 +969,6 @@ static int ext4_mb_get_buddy_page_lock(struct super_block *sb,
 
        block++;
        pnum = block / blocks_per_page;
-       poff = block % blocks_per_page;
        page = find_or_create_page(inode->i_mapping, pnum, GFP_NOFS);
        if (!page)
                return -EIO;
@@ -1339,17 +1338,17 @@ static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b,
        mb_check_buddy(e4b);
 }
 
-static int mb_find_extent(struct ext4_buddy *e4b, int order, int block,
+static int mb_find_extent(struct ext4_buddy *e4b, int block,
                                int needed, struct ext4_free_extent *ex)
 {
        int next = block;
-       int max;
+       int max, order;
        void *buddy;
 
        assert_spin_locked(ext4_group_lock_ptr(e4b->bd_sb, e4b->bd_group));
        BUG_ON(ex == NULL);
 
-       buddy = mb_find_buddy(e4b, order, &max);
+       buddy = mb_find_buddy(e4b, 0, &max);
        BUG_ON(buddy == NULL);
        BUG_ON(block >= max);
        if (mb_test_bit(block, buddy)) {
@@ -1359,12 +1358,9 @@ static int mb_find_extent(struct ext4_buddy *e4b, int order, int block,
                return 0;
        }
 
-       /* FIXME dorp order completely ? */
-       if (likely(order == 0)) {
-               /* find actual order */
-               order = mb_find_order_for_block(e4b, block);
-               block = block >> order;
-       }
+       /* find actual order */
+       order = mb_find_order_for_block(e4b, block);
+       block = block >> order;
 
        ex->fe_len = 1 << order;
        ex->fe_start = block << order;
@@ -1550,7 +1546,7 @@ static void ext4_mb_check_limits(struct ext4_allocation_context *ac,
                /* recheck chunk's availability - we don't know
                 * when it was found (within this lock-unlock
                 * period or not) */
-               max = mb_find_extent(e4b, 0, bex->fe_start, gex->fe_len, &ex);
+               max = mb_find_extent(e4b, bex->fe_start, gex->fe_len, &ex);
                if (max >= gex->fe_len) {
                        ext4_mb_use_best_found(ac, e4b);
                        return;
@@ -1642,7 +1638,7 @@ int ext4_mb_try_best_found(struct ext4_allocation_context *ac,
                return err;
 
        ext4_lock_group(ac->ac_sb, group);
-       max = mb_find_extent(e4b, 0, ex.fe_start, ex.fe_len, &ex);
+       max = mb_find_extent(e4b, ex.fe_start, ex.fe_len, &ex);
 
        if (max > 0) {
                ac->ac_b_ex = ex;
@@ -1673,7 +1669,7 @@ int ext4_mb_find_by_goal(struct ext4_allocation_context *ac,
                return err;
 
        ext4_lock_group(ac->ac_sb, group);
-       max = mb_find_extent(e4b, 0, ac->ac_g_ex.fe_start,
+       max = mb_find_extent(e4b, ac->ac_g_ex.fe_start,
                             ac->ac_g_ex.fe_len, &ex);
 
        if (max >= ac->ac_g_ex.fe_len && ac->ac_g_ex.fe_len == sbi->s_stripe) {
@@ -1789,7 +1785,7 @@ void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac,
                        break;
                }
 
-               mb_find_extent(e4b, 0, i, ac->ac_g_ex.fe_len, &ex);
+               mb_find_extent(e4b, i, ac->ac_g_ex.fe_len, &ex);
                BUG_ON(ex.fe_len <= 0);
                if (free < ex.fe_len) {
                        ext4_grp_locked_error(sb, e4b->bd_group, 0, 0,
@@ -1841,7 +1837,7 @@ void ext4_mb_scan_aligned(struct ext4_allocation_context *ac,
 
        while (i < EXT4_CLUSTERS_PER_GROUP(sb)) {
                if (!mb_test_bit(i, bitmap)) {
-                       max = mb_find_extent(e4b, 0, i, sbi->s_stripe, &ex);
+                       max = mb_find_extent(e4b, i, sbi->s_stripe, &ex);
                        if (max >= sbi->s_stripe) {
                                ac->ac_found++;
                                ac->ac_b_ex = ex;
@@ -1863,6 +1859,12 @@ static int ext4_mb_good_group(struct ext4_allocation_context *ac,
 
        BUG_ON(cr < 0 || cr >= 4);
 
+       free = grp->bb_free;
+       if (free == 0)
+               return 0;
+       if (cr <= 2 && free < ac->ac_g_ex.fe_len)
+               return 0;
+
        /* We only do this if the grp has never been initialized */
        if (unlikely(EXT4_MB_GRP_NEED_INIT(grp))) {
                int ret = ext4_mb_init_group(ac->ac_sb, group);
@@ -1870,10 +1872,7 @@ static int ext4_mb_good_group(struct ext4_allocation_context *ac,
                        return 0;
        }
 
-       free = grp->bb_free;
        fragments = grp->bb_fragments;
-       if (free == 0)
-               return 0;
        if (fragments == 0)
                return 0;
 
@@ -2077,8 +2076,9 @@ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v)
        struct super_block *sb = seq->private;
        ext4_group_t group = (ext4_group_t) ((unsigned long) v);
        int i;
-       int err;
+       int err, buddy_loaded = 0;
        struct ext4_buddy e4b;
+       struct ext4_group_info *grinfo;
        struct sg {
                struct ext4_group_info info;
                ext4_grpblk_t counters[16];
@@ -2095,15 +2095,21 @@ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v)
 
        i = (sb->s_blocksize_bits + 2) * sizeof(sg.info.bb_counters[0]) +
                sizeof(struct ext4_group_info);
-       err = ext4_mb_load_buddy(sb, group, &e4b);
-       if (err) {
-               seq_printf(seq, "#%-5u: I/O error\n", group);
-               return 0;
+       grinfo = ext4_get_group_info(sb, group);
+       /* Load the group info in memory only if not already loaded. */
+       if (unlikely(EXT4_MB_GRP_NEED_INIT(grinfo))) {
+               err = ext4_mb_load_buddy(sb, group, &e4b);
+               if (err) {
+                       seq_printf(seq, "#%-5u: I/O error\n", group);
+                       return 0;
+               }
+               buddy_loaded = 1;
        }
-       ext4_lock_group(sb, group);
+
        memcpy(&sg, ext4_get_group_info(sb, group), i);
-       ext4_unlock_group(sb, group);
-       ext4_mb_unload_buddy(&e4b);
+
+       if (buddy_loaded)
+               ext4_mb_unload_buddy(&e4b);
 
        seq_printf(seq, "#%-5u: %-5u %-5u %-5u [", group, sg.info.bb_free,
                        sg.info.bb_fragments, sg.info.bb_first_free);
@@ -2825,7 +2831,6 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
        err = ext4_handle_dirty_metadata(handle, NULL, gdp_bh);
 
 out_err:
-       ext4_mark_super_dirty(sb);
        brelse(bitmap_bh);
        return err;
 }
@@ -4694,7 +4699,6 @@ do_more:
                put_bh(bitmap_bh);
                goto do_more;
        }
-       ext4_mark_super_dirty(sb);
 error_return:
        brelse(bitmap_bh);
        ext4_std_error(sb, err);