aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fb.com>2016-04-11 17:37:40 -0400
committerChris Mason <clm@fb.com>2016-06-22 20:54:18 -0400
commit31b9655f439a26856edca0f3f8daa368a61f16d5 (patch)
treeac17462f6647fa2740ba9854ffeff250917db675
parentde18c165509edb36bde42ca6ff930854f85e21ea (diff)
Btrfs: track transid for delayed ref flushing
Using the offwakecputime bpf script I noticed most of our time was spent waiting on the delayed ref throttling. This is what is supposed to happen, but sometimes the transaction can commit and then we're waiting for throttling that doesn't matter anymore. So change this stuff to be a little smarter by tracking the transid we were in when we initiated the throttling. If the transaction we get is different then we can just bail out. This resulted in a 50% speedup in my fs_mark test, and reduced the amount of time spent throttling by 60 seconds over the entire run (which is about 30 minutes). Thanks, Signed-off-by: Josef Bacik <jbacik@fb.com> Signed-off-by: Chris Mason <clm@fb.com>
-rw-r--r--fs/btrfs/ctree.h2
-rw-r--r--fs/btrfs/extent-tree.c15
-rw-r--r--fs/btrfs/inode.c1
-rw-r--r--fs/btrfs/transaction.c3
4 files changed, 16 insertions, 5 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 101c3cfd3f7c..4274a7bfdaed 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -2518,7 +2518,7 @@ void btrfs_put_block_group(struct btrfs_block_group_cache *cache);
2518int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, 2518int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
2519 struct btrfs_root *root, unsigned long count); 2519 struct btrfs_root *root, unsigned long count);
2520int btrfs_async_run_delayed_refs(struct btrfs_root *root, 2520int btrfs_async_run_delayed_refs(struct btrfs_root *root,
2521 unsigned long count, int wait); 2521 unsigned long count, u64 transid, int wait);
2522int btrfs_lookup_data_extent(struct btrfs_root *root, u64 start, u64 len); 2522int btrfs_lookup_data_extent(struct btrfs_root *root, u64 start, u64 len);
2523int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans, 2523int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
2524 struct btrfs_root *root, u64 bytenr, 2524 struct btrfs_root *root, u64 bytenr,
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 29e5d000bbee..ecfa52002363 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -2835,6 +2835,7 @@ int btrfs_should_throttle_delayed_refs(struct btrfs_trans_handle *trans,
2835 2835
2836struct async_delayed_refs { 2836struct async_delayed_refs {
2837 struct btrfs_root *root; 2837 struct btrfs_root *root;
2838 u64 transid;
2838 int count; 2839 int count;
2839 int error; 2840 int error;
2840 int sync; 2841 int sync;
@@ -2850,9 +2851,16 @@ static void delayed_ref_async_start(struct btrfs_work *work)
2850 2851
2851 async = container_of(work, struct async_delayed_refs, work); 2852 async = container_of(work, struct async_delayed_refs, work);
2852 2853
2853 trans = btrfs_join_transaction(async->root); 2854 trans = btrfs_attach_transaction(async->root);
2854 if (IS_ERR(trans)) { 2855 if (IS_ERR(trans)) {
2855 async->error = PTR_ERR(trans); 2856 if (PTR_ERR(trans) != -ENOENT)
2857 async->error = PTR_ERR(trans);
2858 goto done;
2859 }
2860
2861 /* Don't bother flushing if we got into a different transaction */
2862 if (trans->transid != async->transid) {
2863 btrfs_end_transaction(trans, async->root);
2856 goto done; 2864 goto done;
2857 } 2865 }
2858 2866
@@ -2876,7 +2884,7 @@ done:
2876} 2884}
2877 2885
2878int btrfs_async_run_delayed_refs(struct btrfs_root *root, 2886int btrfs_async_run_delayed_refs(struct btrfs_root *root,
2879 unsigned long count, int wait) 2887 unsigned long count, u64 transid, int wait)
2880{ 2888{
2881 struct async_delayed_refs *async; 2889 struct async_delayed_refs *async;
2882 int ret; 2890 int ret;
@@ -2888,6 +2896,7 @@ int btrfs_async_run_delayed_refs(struct btrfs_root *root,
2888 async->root = root->fs_info->tree_root; 2896 async->root = root->fs_info->tree_root;
2889 async->count = count; 2897 async->count = count;
2890 async->error = 0; 2898 async->error = 0;
2899 async->transid = transid;
2891 if (wait) 2900 if (wait)
2892 async->sync = 1; 2901 async->sync = 1;
2893 else 2902 else
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index bb62418b8023..78582e339f33 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -4558,6 +4558,7 @@ delete:
4558 BUG_ON(ret); 4558 BUG_ON(ret);
4559 if (btrfs_should_throttle_delayed_refs(trans, root)) 4559 if (btrfs_should_throttle_delayed_refs(trans, root))
4560 btrfs_async_run_delayed_refs(root, 4560 btrfs_async_run_delayed_refs(root,
4561 trans->transid,
4561 trans->delayed_ref_updates * 2, 0); 4562 trans->delayed_ref_updates * 2, 0);
4562 if (be_nice) { 4563 if (be_nice) {
4563 if (truncate_space_check(trans, root, 4564 if (truncate_space_check(trans, root,
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 765845742fde..948aa186b353 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -818,6 +818,7 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
818{ 818{
819 struct btrfs_transaction *cur_trans = trans->transaction; 819 struct btrfs_transaction *cur_trans = trans->transaction;
820 struct btrfs_fs_info *info = root->fs_info; 820 struct btrfs_fs_info *info = root->fs_info;
821 u64 transid = trans->transid;
821 unsigned long cur = trans->delayed_ref_updates; 822 unsigned long cur = trans->delayed_ref_updates;
822 int lock = (trans->type != TRANS_JOIN_NOLOCK); 823 int lock = (trans->type != TRANS_JOIN_NOLOCK);
823 int err = 0; 824 int err = 0;
@@ -905,7 +906,7 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
905 906
906 kmem_cache_free(btrfs_trans_handle_cachep, trans); 907 kmem_cache_free(btrfs_trans_handle_cachep, trans);
907 if (must_run_delayed_refs) { 908 if (must_run_delayed_refs) {
908 btrfs_async_run_delayed_refs(root, cur, 909 btrfs_async_run_delayed_refs(root, cur, transid,
909 must_run_delayed_refs == 1); 910 must_run_delayed_refs == 1);
910 } 911 }
911 return err; 912 return err;