*/
 static noinline_for_stack int
 ext4_mb_discard_group_preallocations(struct super_block *sb,
-                                       ext4_group_t group, int needed)
+                                    ext4_group_t group, int *busy)
 {
        struct ext4_group_info *grp = ext4_get_group_info(sb, group);
        struct buffer_head *bitmap_bh = NULL;
        struct list_head list;
        struct ext4_buddy e4b;
        int err;
-       int busy = 0;
-       int free, free_total = 0;
+       int free = 0;
 
        mb_debug(sb, "discard preallocation for group %u\n", group);
        if (list_empty(&grp->bb_prealloc_list))
                goto out_dbg;
        }
 
-       if (needed == 0)
-               needed = EXT4_CLUSTERS_PER_GROUP(sb) + 1;
-
        INIT_LIST_HEAD(&list);
-repeat:
-       free = 0;
        ext4_lock_group(sb, group);
        list_for_each_entry_safe(pa, tmp,
                                &grp->bb_prealloc_list, pa_group_list) {
                spin_lock(&pa->pa_lock);
                if (atomic_read(&pa->pa_count)) {
                        spin_unlock(&pa->pa_lock);
-                       busy = 1;
+                       *busy = 1;
                        continue;
                }
                if (pa->pa_deleted) {
                call_rcu(&(pa)->u.pa_rcu, ext4_mb_pa_callback);
        }
 
-       free_total += free;
-
-       /* if we still need more blocks and some PAs were used, try again */
-       if (free_total < needed && busy) {
-               ext4_unlock_group(sb, group);
-               cond_resched();
-               busy = 0;
-               goto repeat;
-       }
        ext4_unlock_group(sb, group);
        ext4_mb_unload_buddy(&e4b);
        put_bh(bitmap_bh);
 out_dbg:
        mb_debug(sb, "discarded (%d) blocks preallocated for group %u bb_free (%d)\n",
-                free_total, group, grp->bb_free);
-       return free_total;
+                free, group, grp->bb_free);
+       return free;
 }
 
 /*
 {
        ext4_group_t i, ngroups = ext4_get_groups_count(sb);
        int ret;
-       int freed = 0;
+       int freed = 0, busy = 0;
+       int retry = 0;
 
        trace_ext4_mb_discard_preallocations(sb, needed);
+
+       if (needed == 0)
+               needed = EXT4_CLUSTERS_PER_GROUP(sb) + 1;
+ repeat:
        for (i = 0; i < ngroups && needed > 0; i++) {
-               ret = ext4_mb_discard_group_preallocations(sb, i, needed);
+               ret = ext4_mb_discard_group_preallocations(sb, i, &busy);
                freed += ret;
                needed -= ret;
+               cond_resched();
+       }
+
+       if (needed > 0 && busy && ++retry < 3) {
+               busy = 0;
+               goto repeat;
        }
 
        return freed;