Merge branch 'for-4.2/writeback' of git://git.kernel.dk/linux-block
[firefly-linux-kernel-4.4.55.git] / fs / ext4 / mballoc.c
index 440987c8ba9ef2dc27eee2092e244d6f4c32bb7b..f6aedf88da437ee324c314bb1020baa51db0423c 100644 (file)
@@ -883,10 +883,8 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
 
        /* wait for I/O completion */
        for (i = 0, group = first_group; i < groups_per_page; i++, group++) {
-               if (bh[i] && ext4_wait_block_bitmap(sb, group, bh[i])) {
+               if (bh[i] && ext4_wait_block_bitmap(sb, group, bh[i]))
                        err = -EIO;
-                       goto out;
-               }
        }
 
        first_block = page->index * blocks_per_page;
@@ -899,6 +897,11 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
                        /* skip initialized uptodate buddy */
                        continue;
 
+               if (!buffer_verified(bh[group - first_group]))
+                       /* Skip faulty bitmaps */
+                       continue;
+               err = 0;
+
                /*
                 * data carry information regarding this
                 * particular group in the format specified
@@ -2009,7 +2012,12 @@ void ext4_mb_scan_aligned(struct ext4_allocation_context *ac,
        }
 }
 
-/* This is now called BEFORE we load the buddy bitmap. */
+/*
+ * This is now called BEFORE we load the buddy bitmap.
+ * Returns either 1 or 0 indicating that the group is either suitable
+ * for the allocation or not. In addition it can also return negative
+ * error code when something goes wrong.
+ */
 static int ext4_mb_good_group(struct ext4_allocation_context *ac,
                                ext4_group_t group, int cr)
 {
@@ -2032,7 +2040,7 @@ static int ext4_mb_good_group(struct ext4_allocation_context *ac,
        if (unlikely(EXT4_MB_GRP_NEED_INIT(grp))) {
                int ret = ext4_mb_init_group(ac->ac_sb, group);
                if (ret)
-                       return 0;
+                       return ret;
        }
 
        fragments = grp->bb_fragments;
@@ -2079,7 +2087,7 @@ ext4_mb_regular_allocator(struct ext4_allocation_context *ac)
 {
        ext4_group_t ngroups, group, i;
        int cr;
-       int err = 0;
+       int err = 0, first_err = 0;
        struct ext4_sb_info *sbi;
        struct super_block *sb;
        struct ext4_buddy e4b;
@@ -2146,6 +2154,7 @@ repeat:
                group = ac->ac_g_ex.fe_group;
 
                for (i = 0; i < ngroups; group++, i++) {
+                       int ret = 0;
                        cond_resched();
                        /*
                         * Artificially restricted ngroups for non-extent
@@ -2155,8 +2164,12 @@ repeat:
                                group = 0;
 
                        /* This now checks without needing the buddy page */
-                       if (!ext4_mb_good_group(ac, group, cr))
+                       ret = ext4_mb_good_group(ac, group, cr);
+                       if (ret <= 0) {
+                               if (!first_err)
+                                       first_err = ret;
                                continue;
+                       }
 
                        err = ext4_mb_load_buddy(sb, group, &e4b);
                        if (err)
@@ -2168,9 +2181,12 @@ repeat:
                         * We need to check again after locking the
                         * block group
                         */
-                       if (!ext4_mb_good_group(ac, group, cr)) {
+                       ret = ext4_mb_good_group(ac, group, cr);
+                       if (ret <= 0) {
                                ext4_unlock_group(sb, group);
                                ext4_mb_unload_buddy(&e4b);
+                               if (!first_err)
+                                       first_err = ret;
                                continue;
                        }
 
@@ -2217,6 +2233,8 @@ repeat:
                }
        }
 out:
+       if (!err && ac->ac_status != AC_STATUS_FOUND && first_err)
+               err = first_err;
        return err;
 }
 
@@ -2258,12 +2276,9 @@ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v)
 
        group--;
        if (group == 0)
-               seq_printf(seq, "#%-5s: %-5s %-5s %-5s "
-                               "[ %-5s %-5s %-5s %-5s %-5s %-5s %-5s "
-                                 "%-5s %-5s %-5s %-5s %-5s %-5s %-5s ]\n",
-                          "group", "free", "frags", "first",
-                          "2^0", "2^1", "2^2", "2^3", "2^4", "2^5", "2^6",
-                          "2^7", "2^8", "2^9", "2^10", "2^11", "2^12", "2^13");
+               seq_puts(seq, "#group: free  frags first ["
+                             " 2^0   2^1   2^2   2^3   2^4   2^5   2^6  "
+                             " 2^7   2^8   2^9   2^10  2^11  2^12  2^13  ]");
 
        i = (sb->s_blocksize_bits + 2) * sizeof(sg.info.bb_counters[0]) +
                sizeof(struct ext4_group_info);