return ret;
 }
 
+static void calc_refill_bytes(struct btrfs_block_rsv *block_rsv,
+                               u64 *metadata_bytes, u64 *qgroup_bytes)
+{
+       *metadata_bytes = 0;
+       *qgroup_bytes = 0;
+
+       spin_lock(&block_rsv->lock);
+       if (block_rsv->reserved < block_rsv->size)
+               *metadata_bytes = block_rsv->size - block_rsv->reserved;
+       if (block_rsv->qgroup_rsv_reserved < block_rsv->qgroup_rsv_size)
+               *qgroup_bytes = block_rsv->qgroup_rsv_size -
+                       block_rsv->qgroup_rsv_reserved;
+       spin_unlock(&block_rsv->lock);
+}
+
 /**
  * btrfs_inode_rsv_refill - refill the inode block rsv.
  * @inode - the inode we are refilling.
 {
        struct btrfs_root *root = inode->root;
        struct btrfs_block_rsv *block_rsv = &inode->block_rsv;
-       u64 num_bytes = 0;
-       u64 qgroup_num_bytes = 0;
+       u64 num_bytes, last = 0;
+       u64 qgroup_num_bytes;
        int ret = -ENOSPC;
 
-       spin_lock(&block_rsv->lock);
-       if (block_rsv->reserved < block_rsv->size)
-               num_bytes = block_rsv->size - block_rsv->reserved;
-       if (block_rsv->qgroup_rsv_reserved < block_rsv->qgroup_rsv_size)
-               qgroup_num_bytes = block_rsv->qgroup_rsv_size -
-                                  block_rsv->qgroup_rsv_reserved;
-       spin_unlock(&block_rsv->lock);
-
+       calc_refill_bytes(block_rsv, &num_bytes, &qgroup_num_bytes);
        if (num_bytes == 0)
                return 0;
 
-       ret = btrfs_qgroup_reserve_meta_prealloc(root, qgroup_num_bytes, true);
-       if (ret)
-               return ret;
-       ret = reserve_metadata_bytes(root, block_rsv, num_bytes, flush);
+       do {
+               ret = btrfs_qgroup_reserve_meta_prealloc(root, qgroup_num_bytes,
+                                                        true);
+               if (ret)
+                       return ret;
+               ret = reserve_metadata_bytes(root, block_rsv, num_bytes, flush);
+               if (ret) {
+                       btrfs_qgroup_free_meta_prealloc(root, qgroup_num_bytes);
+                       last = num_bytes;
+                       /*
+                        * If we are fragmented we can end up with a lot of
+                        * outstanding extents which will make our size be much
+                        * larger than our reserved amount.
+                        *
+                        * If the reservation happens here, it might be very
+                        * big though not needed in the end, if the delalloc
+                        * flushing happens.
+                        *
+                        * If this is the case try and do the reserve again.
+                        */
+                       if (flush == BTRFS_RESERVE_FLUSH_ALL)
+                               calc_refill_bytes(block_rsv, &num_bytes,
+                                                  &qgroup_num_bytes);
+                       if (num_bytes == 0)
+                               return 0;
+               }
+       } while (ret && last != num_bytes);
+
        if (!ret) {
                block_rsv_add_bytes(block_rsv, num_bytes, false);
                trace_btrfs_space_reservation(root->fs_info, "delalloc",
                spin_lock(&block_rsv->lock);
                block_rsv->qgroup_rsv_reserved += qgroup_num_bytes;
                spin_unlock(&block_rsv->lock);
-       } else
-               btrfs_qgroup_free_meta_prealloc(root, qgroup_num_bytes);
+       }
        return ret;
 }