Merge tag 'backlight-for-linus-4.8' of git://git.kernel.org/pub/scm/linux/kernel...
[deliverable/linux.git] / fs / btrfs / delayed-inode.c
index d3aaabbfada0adcbb09936a5d47063a4adec65dd..dd3c040139a2ffb38957177b383790d2a6782e51 100644 (file)
@@ -553,7 +553,7 @@ static int btrfs_delayed_item_reserve_metadata(struct btrfs_trans_handle *trans,
        dst_rsv = &root->fs_info->delayed_block_rsv;
 
        num_bytes = btrfs_calc_trans_metadata_size(root, 1);
-       ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes);
+       ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes, 1);
        if (!ret) {
                trace_btrfs_space_reservation(root->fs_info, "delayed_item",
                                              item->key.objectid,
@@ -597,6 +597,29 @@ static int btrfs_delayed_inode_reserve_metadata(
 
        num_bytes = btrfs_calc_trans_metadata_size(root, 1);
 
+       /*
+        * If our block_rsv is the delalloc block reserve then check and see if
+        * we have our extra reservation for updating the inode.  If not fall
+        * through and try to reserve space quickly.
+        *
+        * We used to try and steal from the delalloc block rsv or the global
+        * reserve, but we'd steal a full reservation, which isn't kind.  We are
+        * here through delalloc which means we've likely just cowed down close
+        * to the leaf that contains the inode, so we would steal less just
+        * doing the fallback inode update, so if we do end up having to steal
+        * from the global block rsv we hopefully only steal one or two blocks
+        * worth which is less likely to hurt us.
+        */
+       if (src_rsv && src_rsv->type == BTRFS_BLOCK_RSV_DELALLOC) {
+               spin_lock(&BTRFS_I(inode)->lock);
+               if (test_and_clear_bit(BTRFS_INODE_DELALLOC_META_RESERVED,
+                                      &BTRFS_I(inode)->runtime_flags))
+                       release = true;
+               else
+                       src_rsv = NULL;
+               spin_unlock(&BTRFS_I(inode)->lock);
+       }
+
        /*
         * btrfs_dirty_inode will update the inode under btrfs_join_transaction
         * which doesn't reserve space for speed.  This is a problem since we
@@ -626,51 +649,10 @@ static int btrfs_delayed_inode_reserve_metadata(
                                                      num_bytes, 1);
                }
                return ret;
-       } else if (src_rsv->type == BTRFS_BLOCK_RSV_DELALLOC) {
-               spin_lock(&BTRFS_I(inode)->lock);
-               if (test_and_clear_bit(BTRFS_INODE_DELALLOC_META_RESERVED,
-                                      &BTRFS_I(inode)->runtime_flags)) {
-                       spin_unlock(&BTRFS_I(inode)->lock);
-                       release = true;
-                       goto migrate;
-               }
-               spin_unlock(&BTRFS_I(inode)->lock);
-
-               /* Ok we didn't have space pre-reserved.  This shouldn't happen
-                * too often but it can happen if we do delalloc to an existing
-                * inode which gets dirtied because of the time update, and then
-                * isn't touched again until after the transaction commits and
-                * then we try to write out the data.  First try to be nice and
-                * reserve something strictly for us.  If not be a pain and try
-                * to steal from the delalloc block rsv.
-                */
-               ret = btrfs_block_rsv_add(root, dst_rsv, num_bytes,
-                                         BTRFS_RESERVE_NO_FLUSH);
-               if (!ret)
-                       goto out;
-
-               ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes);
-               if (!ret)
-                       goto out;
-
-               if (btrfs_test_opt(root, ENOSPC_DEBUG)) {
-                       btrfs_debug(root->fs_info,
-                                   "block rsv migrate returned %d", ret);
-                       WARN_ON(1);
-               }
-               /*
-                * Ok this is a problem, let's just steal from the global rsv
-                * since this really shouldn't happen that often.
-                */
-               ret = btrfs_block_rsv_migrate(&root->fs_info->global_block_rsv,
-                                             dst_rsv, num_bytes);
-               goto out;
        }
 
-migrate:
-       ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes);
+       ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes, 1);
 
-out:
        /*
         * Migrate only takes a reservation, it doesn't touch the size of the
         * block_rsv.  This is to simplify people who don't normally have things
This page took 0.026242 seconds and 5 git commands to generate.