Merge branch 'for-linus-4.1' of git://git.kernel.org/pub/scm/linux/kernel/git/mason...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 24 Apr 2015 14:40:02 +0000 (07:40 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 24 Apr 2015 14:40:02 +0000 (07:40 -0700)
Pull btrfs updates from Chris Mason:
 "I've been running these through a longer set of load tests because my
  commits change the free space cache writeout.  It fixes commit stalls
  on large filesystems (~20T space used and up) that we have been
  triggering here.  We were seeing new writers blocked for 10 seconds or
  more during commits, which is far from good.

  Josef and I fixed up ENOSPC aborts when deleting huge files (3T or
  more), that are triggered because our metadata reservations were not
  properly accounting for crcs and were not replenishing during the
  truncate.

  Also in this series, a number of qgroup fixes from Fujitsu and Dave
  Sterba collected most of the pending cleanups from the list"

* 'for-linus-4.1' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs: (93 commits)
  btrfs: quota: Update quota tree after qgroup relationship change.
  btrfs: quota: Automatically update related qgroups or mark INCONSISTENT flags when assigning/deleting a qgroup relations.
  btrfs: qgroup: clear STATUS_FLAG_ON in disabling quota.
  btrfs: Update btrfs qgroup status item when rescan is done.
  btrfs: qgroup: Fix dead judgement on qgroup_rescan_leaf() return value.
  btrfs: Don't allow subvolid >= (1 << BTRFS_QGROUP_LEVEL_SHIFT) to be created
  btrfs: Check qgroup level in kernel qgroup assign.
  btrfs: qgroup: allow to remove qgroup which has parent but no child.
  btrfs: qgroup: return EINVAL if level of parent is not higher than child's.
  btrfs: qgroup: do a reservation in a higher level.
  Btrfs: qgroup, Account data space in more proper timings.
  Btrfs: qgroup: Introduce a may_use to account space_info->bytes_may_use.
  Btrfs: qgroup: free reserved in exceeding quota.
  Btrfs: qgroup: cleanup, remove an unsued parameter in btrfs_create_qgroup().
  btrfs: qgroup: fix limit args override whole limit struct
  btrfs: qgroup: update limit info in function btrfs_run_qgroups().
  btrfs: qgroup: consolidate the parameter of fucntion update_qgroup_limit_item().
  btrfs: qgroup: update qgroup in memory at the same time when we update it in btree.
  btrfs: qgroup: inherit limit info from srcgroup in creating snapshot.
  btrfs: Support busy loop of write and delete
  ...

1  2 
fs/btrfs/file.c
fs/btrfs/inode.c

diff --combined fs/btrfs/file.c
index faa7d390841b9a245a95ffb4944d515c3c486cbf,23b6e03f84650612ae964e0417b8f3ad926670f5..467620a3b1f9702f9b2f36f6aec3d5aa971d733e
@@@ -24,6 -24,7 +24,6 @@@
  #include <linux/string.h>
  #include <linux/backing-dev.h>
  #include <linux/mpage.h>
 -#include <linux/aio.h>
  #include <linux/falloc.h>
  #include <linux/swap.h>
  #include <linux/writeback.h>
@@@ -31,7 -32,6 +31,7 @@@
  #include <linux/compat.h>
  #include <linux/slab.h>
  #include <linux/btrfs.h>
 +#include <linux/uio.h>
  #include "ctree.h"
  #include "disk-io.h"
  #include "transaction.h"
@@@ -273,11 -273,7 +273,7 @@@ void btrfs_cleanup_defrag_inodes(struc
                defrag = rb_entry(node, struct inode_defrag, rb_node);
                kmem_cache_free(btrfs_inode_defrag_cachep, defrag);
  
-               if (need_resched()) {
-                       spin_unlock(&fs_info->defrag_inodes_lock);
-                       cond_resched();
-                       spin_lock(&fs_info->defrag_inodes_lock);
-               }
+               cond_resched_lock(&fs_info->defrag_inodes_lock);
  
                node = rb_first(&fs_info->defrag_inodes);
        }
@@@ -868,7 -864,7 +864,7 @@@ next_slot
  
                        memcpy(&new_key, &key, sizeof(new_key));
                        new_key.offset = end;
-                       btrfs_set_item_key_safe(root, path, &new_key);
+                       btrfs_set_item_key_safe(root->fs_info, path, &new_key);
  
                        extent_offset += end - key.offset;
                        btrfs_set_file_extent_offset(leaf, fi, extent_offset);
@@@ -1126,7 -1122,7 +1122,7 @@@ again
                                     ino, bytenr, orig_offset,
                                     &other_start, &other_end)) {
                        new_key.offset = end;
-                       btrfs_set_item_key_safe(root, path, &new_key);
+                       btrfs_set_item_key_safe(root->fs_info, path, &new_key);
                        fi = btrfs_item_ptr(leaf, path->slots[0],
                                            struct btrfs_file_extent_item);
                        btrfs_set_file_extent_generation(leaf, fi,
                                                         trans->transid);
                        path->slots[0]++;
                        new_key.offset = start;
-                       btrfs_set_item_key_safe(root, path, &new_key);
+                       btrfs_set_item_key_safe(root->fs_info, path, &new_key);
  
                        fi = btrfs_item_ptr(leaf, path->slots[0],
                                            struct btrfs_file_extent_item);
@@@ -1485,7 -1481,7 +1481,7 @@@ static noinline ssize_t __btrfs_buffere
                        PAGE_CACHE_SIZE / (sizeof(struct page *)));
        nrptrs = min(nrptrs, current->nr_dirtied_pause - current->nr_dirtied);
        nrptrs = max(nrptrs, 8);
-       pages = kmalloc(nrptrs * sizeof(struct page *), GFP_KERNEL);
+       pages = kmalloc_array(nrptrs, sizeof(struct page *), GFP_KERNEL);
        if (!pages)
                return -ENOMEM;
  
                }
  
                reserve_bytes = num_pages << PAGE_CACHE_SHIFT;
-               ret = btrfs_check_data_free_space(inode, reserve_bytes);
+               ret = btrfs_check_data_free_space(inode, reserve_bytes, write_bytes);
                if (ret == -ENOSPC &&
                    (BTRFS_I(inode)->flags & (BTRFS_INODE_NODATACOW |
                                              BTRFS_INODE_PREALLOC))) {
@@@ -1635,8 -1631,8 +1631,8 @@@ again
                        btrfs_end_write_no_snapshoting(root);
  
                if (only_release_metadata && copied > 0) {
-                       u64 lockstart = round_down(pos, root->sectorsize);
-                       u64 lockend = lockstart +
+                       lockstart = round_down(pos, root->sectorsize);
+                       lockend = lockstart +
                                (dirty_pages << PAGE_CACHE_SHIFT) - 1;
  
                        set_extent_bit(&BTRFS_I(inode)->io_tree, lockstart,
@@@ -1739,19 -1735,27 +1735,19 @@@ static ssize_t btrfs_file_write_iter(st
        u64 start_pos;
        u64 end_pos;
        ssize_t num_written = 0;
 -      ssize_t err = 0;
 -      size_t count = iov_iter_count(from);
        bool sync = (file->f_flags & O_DSYNC) || IS_SYNC(file->f_mapping->host);
 -      loff_t pos = iocb->ki_pos;
 +      ssize_t err;
 +      loff_t pos;
 +      size_t count;
  
        mutex_lock(&inode->i_mutex);
 -
 -      current->backing_dev_info = inode_to_bdi(inode);
 -      err = generic_write_checks(file, &pos, &count, S_ISBLK(inode->i_mode));
 -      if (err) {
 +      err = generic_write_checks(iocb, from);
 +      if (err <= 0) {
                mutex_unlock(&inode->i_mutex);
 -              goto out;
 -      }
 -
 -      if (count == 0) {
 -              mutex_unlock(&inode->i_mutex);
 -              goto out;
 +              return err;
        }
  
 -      iov_iter_truncate(from, count);
 -
 +      current->backing_dev_info = inode_to_bdi(inode);
        err = file_remove_suid(file);
        if (err) {
                mutex_unlock(&inode->i_mutex);
         */
        update_time_for_write(inode);
  
 +      pos = iocb->ki_pos;
 +      count = iov_iter_count(from);
        start_pos = round_down(pos, root->sectorsize);
        if (start_pos > i_size_read(inode)) {
                /* Expand hole size to cover write data, preventing empty gap */
        if (sync)
                atomic_inc(&BTRFS_I(inode)->sync_writers);
  
 -      if (file->f_flags & O_DIRECT) {
 +      if (iocb->ki_flags & IOCB_DIRECT) {
                num_written = __btrfs_direct_write(iocb, from, pos);
        } else {
                num_written = __btrfs_buffered_write(file, from, pos);
         * otherwise subsequent syncs to a file that's been synced in this
         * transaction will appear to have already occured.
         */
+       spin_lock(&BTRFS_I(inode)->lock);
        BTRFS_I(inode)->last_sub_trans = root->log_transid;
+       spin_unlock(&BTRFS_I(inode)->lock);
        if (num_written > 0) {
                err = generic_write_sync(file, pos, num_written);
                if (err < 0)
@@@ -2162,7 -2166,7 +2160,7 @@@ static int fill_holes(struct btrfs_tran
                u64 num_bytes;
  
                key.offset = offset;
-               btrfs_set_item_key_safe(root, path, &key);
+               btrfs_set_item_key_safe(root->fs_info, path, &key);
                fi = btrfs_item_ptr(leaf, path->slots[0],
                                    struct btrfs_file_extent_item);
                num_bytes = btrfs_file_extent_num_bytes(leaf, fi) + end -
@@@ -2545,7 -2549,6 +2543,6 @@@ static long btrfs_fallocate(struct fil
  {
        struct inode *inode = file_inode(file);
        struct extent_state *cached_state = NULL;
-       struct btrfs_root *root = BTRFS_I(inode)->root;
        u64 cur_offset;
        u64 last_byte;
        u64 alloc_start;
         * Make sure we have enough space before we do the
         * allocation.
         */
-       ret = btrfs_check_data_free_space(inode, alloc_end - alloc_start);
+       ret = btrfs_check_data_free_space(inode, alloc_end - alloc_start, alloc_end - alloc_start);
        if (ret)
                return ret;
-       if (root->fs_info->quota_enabled) {
-               ret = btrfs_qgroup_reserve(root, alloc_end - alloc_start);
-               if (ret)
-                       goto out_reserve_fail;
-       }
  
        mutex_lock(&inode->i_mutex);
        ret = inode_newsize_ok(inode, alloc_end);
                                                        1 << inode->i_blkbits,
                                                        offset + len,
                                                        &alloc_hint);
-                       if (ret < 0) {
-                               free_extent_map(em);
-                               break;
-                       }
                } else if (actual_end > inode->i_size &&
                           !(mode & FALLOC_FL_KEEP_SIZE)) {
+                       struct btrfs_trans_handle *trans;
+                       struct btrfs_root *root = BTRFS_I(inode)->root;
                        /*
                         * We didn't need to allocate any more space, but we
                         * still extended the size of the file so we need to
-                        * update i_size.
+                        * update i_size and the inode item.
                         */
-                       inode->i_ctime = CURRENT_TIME;
-                       i_size_write(inode, actual_end);
-                       btrfs_ordered_update_i_size(inode, actual_end, NULL);
+                       trans = btrfs_start_transaction(root, 1);
+                       if (IS_ERR(trans)) {
+                               ret = PTR_ERR(trans);
+                       } else {
+                               inode->i_ctime = CURRENT_TIME;
+                               i_size_write(inode, actual_end);
+                               btrfs_ordered_update_i_size(inode, actual_end,
+                                                           NULL);
+                               ret = btrfs_update_inode(trans, root, inode);
+                               if (ret)
+                                       btrfs_end_transaction(trans, root);
+                               else
+                                       ret = btrfs_end_transaction(trans,
+                                                                   root);
+                       }
                }
                free_extent_map(em);
+               if (ret < 0)
+                       break;
  
                cur_offset = last_byte;
                if (cur_offset >= alloc_end) {
                             &cached_state, GFP_NOFS);
  out:
        mutex_unlock(&inode->i_mutex);
-       if (root->fs_info->quota_enabled)
-               btrfs_qgroup_free(root, alloc_end - alloc_start);
- out_reserve_fail:
        /* Let go of our reservation. */
        btrfs_free_reserved_data_space(inode, alloc_end - alloc_start);
        return ret;
@@@ -2800,6 -2807,8 +2801,6 @@@ out
  
  const struct file_operations btrfs_file_operations = {
        .llseek         = btrfs_file_llseek,
 -      .read           = new_sync_read,
 -      .write          = new_sync_write,
        .read_iter      = generic_file_read_iter,
        .splice_read    = generic_file_splice_read,
        .write_iter     = btrfs_file_write_iter,
diff --combined fs/btrfs/inode.c
index 43192e10cc4331f9f533c61f10f21c602bdee806,27b59b8362f9ca9b5ee518421706655138cacc63..56f00a25c003515f2821e1a45ad4502cfba72d33
@@@ -32,6 -32,7 +32,6 @@@
  #include <linux/writeback.h>
  #include <linux/statfs.h>
  #include <linux/compat.h>
 -#include <linux/aio.h>
  #include <linux/bit_spinlock.h>
  #include <linux/xattr.h>
  #include <linux/posix_acl.h>
@@@ -59,6 -60,7 +59,7 @@@
  #include "backref.h"
  #include "hash.h"
  #include "props.h"
+ #include "qgroup.h"
  
  struct btrfs_iget_args {
        struct btrfs_key *location;
@@@ -470,7 -472,7 +471,7 @@@ again
         */
        if (inode_need_compress(inode)) {
                WARN_ON(pages);
-               pages = kzalloc(sizeof(struct page *) * nr_pages, GFP_NOFS);
+               pages = kcalloc(nr_pages, sizeof(struct page *), GFP_NOFS);
                if (!pages) {
                        /* just bail out to the uncompressed code */
                        goto cont;
@@@ -752,7 -754,6 +753,6 @@@ retry
                        }
                        goto out_free;
                }
                /*
                 * here we're doing allocation and writeback of the
                 * compressed pages
@@@ -3110,6 -3111,8 +3110,8 @@@ void btrfs_run_delayed_iputs(struct btr
        if (empty)
                return;
  
+       down_read(&fs_info->delayed_iput_sem);
        spin_lock(&fs_info->delayed_iput_lock);
        list_splice_init(&fs_info->delayed_iputs, &list);
        spin_unlock(&fs_info->delayed_iput_lock);
                iput(delayed->inode);
                kfree(delayed);
        }
+       up_read(&root->fs_info->delayed_iput_sem);
  }
  
  /*
        return err;
  }
  
+ static int truncate_space_check(struct btrfs_trans_handle *trans,
+                               struct btrfs_root *root,
+                               u64 bytes_deleted)
+ {
+       int ret;
+       bytes_deleted = btrfs_csum_bytes_to_leaves(root, bytes_deleted);
+       ret = btrfs_block_rsv_add(root, &root->fs_info->trans_block_rsv,
+                                 bytes_deleted, BTRFS_RESERVE_NO_FLUSH);
+       if (!ret)
+               trans->bytes_reserved += bytes_deleted;
+       return ret;
+ }
  /*
   * this can truncate away extent items, csum items and directory items.
   * It starts at a high offset and removes keys until it can't find
@@@ -4197,9 -4217,21 +4216,21 @@@ int btrfs_truncate_inode_items(struct b
        int ret;
        int err = 0;
        u64 ino = btrfs_ino(inode);
+       u64 bytes_deleted = 0;
+       bool be_nice = 0;
+       bool should_throttle = 0;
+       bool should_end = 0;
  
        BUG_ON(new_size > 0 && min_type != BTRFS_EXTENT_DATA_KEY);
  
+       /*
+        * for non-free space inodes and ref cows, we want to back off from
+        * time to time
+        */
+       if (!btrfs_is_free_space_inode(inode) &&
+           test_bit(BTRFS_ROOT_REF_COWS, &root->state))
+               be_nice = 1;
        path = btrfs_alloc_path();
        if (!path)
                return -ENOMEM;
        key.type = (u8)-1;
  
  search_again:
+       /*
+        * with a 16K leaf size and 128MB extents, you can actually queue
+        * up a huge file in a single leaf.  Most of the time that
+        * bytes_deleted is > 0, it will be huge by the time we get here
+        */
+       if (be_nice && bytes_deleted > 32 * 1024 * 1024) {
+               if (btrfs_should_end_transaction(trans, root)) {
+                       err = -EAGAIN;
+                       goto error;
+               }
+       }
        path->leave_spinning = 1;
        ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
        if (ret < 0) {
@@@ -4371,22 -4416,39 +4415,39 @@@ delete
                } else {
                        break;
                }
+               should_throttle = 0;
                if (found_extent &&
                    (test_bit(BTRFS_ROOT_REF_COWS, &root->state) ||
                     root == root->fs_info->tree_root)) {
                        btrfs_set_path_blocking(path);
+                       bytes_deleted += extent_num_bytes;
                        ret = btrfs_free_extent(trans, root, extent_start,
                                                extent_num_bytes, 0,
                                                btrfs_header_owner(leaf),
                                                ino, extent_offset, 0);
                        BUG_ON(ret);
+                       if (btrfs_should_throttle_delayed_refs(trans, root))
+                               btrfs_async_run_delayed_refs(root,
+                                       trans->delayed_ref_updates * 2, 0);
+                       if (be_nice) {
+                               if (truncate_space_check(trans, root,
+                                                        extent_num_bytes)) {
+                                       should_end = 1;
+                               }
+                               if (btrfs_should_throttle_delayed_refs(trans,
+                                                                      root)) {
+                                       should_throttle = 1;
+                               }
+                       }
                }
  
                if (found_type == BTRFS_INODE_ITEM_KEY)
                        break;
  
                if (path->slots[0] == 0 ||
-                   path->slots[0] != pending_del_slot) {
+                   path->slots[0] != pending_del_slot ||
+                   should_throttle || should_end) {
                        if (pending_del_nr) {
                                ret = btrfs_del_items(trans, root, path,
                                                pending_del_slot,
                                pending_del_nr = 0;
                        }
                        btrfs_release_path(path);
+                       if (should_throttle) {
+                               unsigned long updates = trans->delayed_ref_updates;
+                               if (updates) {
+                                       trans->delayed_ref_updates = 0;
+                                       ret = btrfs_run_delayed_refs(trans, root, updates * 2);
+                                       if (ret && !err)
+                                               err = ret;
+                               }
+                       }
+                       /*
+                        * if we failed to refill our space rsv, bail out
+                        * and let the transaction restart
+                        */
+                       if (should_end) {
+                               err = -EAGAIN;
+                               goto error;
+                       }
                        goto search_again;
                } else {
                        path->slots[0]--;
@@@ -4415,7 -4494,18 +4493,18 @@@ error
        if (last_size != (u64)-1 &&
            root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID)
                btrfs_ordered_update_i_size(inode, last_size, NULL);
        btrfs_free_path(path);
+       if (be_nice && bytes_deleted > 32 * 1024 * 1024) {
+               unsigned long updates = trans->delayed_ref_updates;
+               if (updates) {
+                       trans->delayed_ref_updates = 0;
+                       ret = btrfs_run_delayed_refs(trans, root, updates * 2);
+                       if (ret && !err)
+                               err = ret;
+               }
+       }
        return err;
  }
  
@@@ -4924,6 -5014,7 +5013,7 @@@ void btrfs_evict_inode(struct inode *in
        struct btrfs_trans_handle *trans;
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct btrfs_block_rsv *rsv, *global_rsv;
+       int steal_from_global = 0;
        u64 min_size = btrfs_calc_trunc_metadata_size(root, 1);
        int ret;
  
                 * hard as possible to get this to work.
                 */
                if (ret)
-                       ret = btrfs_block_rsv_migrate(global_rsv, rsv, min_size);
+                       steal_from_global++;
+               else
+                       steal_from_global = 0;
+               ret = 0;
  
-               if (ret) {
+               /*
+                * steal_from_global == 0: we reserved stuff, hooray!
+                * steal_from_global == 1: we didn't reserve stuff, boo!
+                * steal_from_global == 2: we've committed, still not a lot of
+                * room but maybe we'll have room in the global reserve this
+                * time.
+                * steal_from_global == 3: abandon all hope!
+                */
+               if (steal_from_global > 2) {
                        btrfs_warn(root->fs_info,
                                "Could not get space for a delete, will truncate on mount %d",
                                ret);
                        goto no_delete;
                }
  
+               /*
+                * We can't just steal from the global reserve, we need tomake
+                * sure there is room to do it, if not we need to commit and try
+                * again.
+                */
+               if (steal_from_global) {
+                       if (!btrfs_check_space_for_delayed_refs(trans, root))
+                               ret = btrfs_block_rsv_migrate(global_rsv, rsv,
+                                                             min_size);
+                       else
+                               ret = -ENOSPC;
+               }
+               /*
+                * Couldn't steal from the global reserve, we have too much
+                * pending stuff built up, commit the transaction and try it
+                * again.
+                */
+               if (ret) {
+                       ret = btrfs_commit_transaction(trans, root);
+                       if (ret) {
+                               btrfs_orphan_del(NULL, inode);
+                               btrfs_free_block_rsv(root, rsv);
+                               goto no_delete;
+                       }
+                       continue;
+               } else {
+                       steal_from_global = 0;
+               }
                trans->block_rsv = rsv;
  
                ret = btrfs_truncate_inode_items(trans, root, inode, 0, 0);
-               if (ret != -ENOSPC)
+               if (ret != -ENOSPC && ret != -EAGAIN)
                        break;
  
                trans->block_rsv = &root->fs_info->trans_block_rsv;
@@@ -8081,7 -8213,7 +8212,7 @@@ free_ordered
        bio_endio(dio_bio, ret);
  }
  
 -static ssize_t check_direct_IO(struct btrfs_root *root, int rw, struct kiocb *iocb,
 +static ssize_t check_direct_IO(struct btrfs_root *root, struct kiocb *iocb,
                        const struct iov_iter *iter, loff_t offset)
  {
        int seg;
                goto out;
  
        /* If this is a write we don't need to check anymore */
 -      if (rw & WRITE)
 +      if (iov_iter_rw(iter) == WRITE)
                return 0;
        /*
         * Check to make sure we don't have duplicate iov_base's in this
@@@ -8114,8 -8246,8 +8245,8 @@@ out
        return retval;
  }
  
 -static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
 -                      struct iov_iter *iter, loff_t offset)
 +static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
 +                             loff_t offset)
  {
        struct file *file = iocb->ki_filp;
        struct inode *inode = file->f_mapping->host;
        bool relock = false;
        ssize_t ret;
  
 -      if (check_direct_IO(BTRFS_I(inode)->root, rw, iocb, iter, offset))
 +      if (check_direct_IO(BTRFS_I(inode)->root, iocb, iter, offset))
                return 0;
  
        atomic_inc(&inode->i_dio_count);
                filemap_fdatawrite_range(inode->i_mapping, offset,
                                         offset + count - 1);
  
 -      if (rw & WRITE) {
 +      if (iov_iter_rw(iter) == WRITE) {
                /*
                 * If the write DIO is beyond the EOF, we need update
                 * the isize, but it is protected by i_mutex. So we can
                wakeup = false;
        }
  
 -      ret = __blockdev_direct_IO(rw, iocb, inode,
 -                      BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev,
 -                      iter, offset, btrfs_get_blocks_direct, NULL,
 -                      btrfs_submit_direct, flags);
 -      if (rw & WRITE) {
 +      ret = __blockdev_direct_IO(iocb, inode,
 +                                 BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev,
 +                                 iter, offset, btrfs_get_blocks_direct, NULL,
 +                                 btrfs_submit_direct, flags);
 +      if (iov_iter_rw(iter) == WRITE) {
                current->journal_info = NULL;
                if (ret < 0 && ret != -EIOCBQUEUED)
                        btrfs_delalloc_release_space(inode, count);
@@@ -8581,7 -8713,7 +8712,7 @@@ static int btrfs_truncate(struct inode 
                ret = btrfs_truncate_inode_items(trans, root, inode,
                                                 inode->i_size,
                                                 BTRFS_EXTENT_DATA_KEY);
-               if (ret != -ENOSPC) {
+               if (ret != -ENOSPC && ret != -EAGAIN) {
                        err = ret;
                        break;
                }
@@@ -9451,6 -9583,7 +9582,7 @@@ static int __btrfs_prealloc_file_range(
                                btrfs_end_transaction(trans, root);
                        break;
                }
                btrfs_drop_extent_cache(inode, cur_offset,
                                        cur_offset + ins.offset -1, 0);