aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/transaction.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2009-03-13 10:17:05 -0400
committerChris Mason <chris.mason@oracle.com>2009-03-24 16:14:26 -0400
commitc3e69d58e86c3917ae4e9e31b4acf490a7cafe60 (patch)
treebd4f1e62446a208bdae26f0c36d67e3afbc1cd1d /fs/btrfs/transaction.c
parent1887be66dcc3140a81d1299958a41fc0eedfa64f (diff)
Btrfs: process the delayed reference queue in clusters
The delayed reference queue maintains pending operations that need to be done to the extent allocation tree. These are processed by finding records in the tree that are not currently being processed one at a time. This is slow because it uses lots of time searching through the rbtree and because it creates lock contention on the extent allocation tree when lots of different procs are running delayed refs at the same time. This commit changes things to grab a cluster of refs for processing, using a cursor into the rbtree as the starting point of the next search. This way we walk smoothly through the rbtree. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r--fs/btrfs/transaction.c25
1 files changed, 17 insertions, 8 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index f94c2ad8996c..903edab3659a 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -68,7 +68,10 @@ static noinline int join_transaction(struct btrfs_root *root)
68 68
69 cur_trans->delayed_refs.root.rb_node = NULL; 69 cur_trans->delayed_refs.root.rb_node = NULL;
70 cur_trans->delayed_refs.num_entries = 0; 70 cur_trans->delayed_refs.num_entries = 0;
71 cur_trans->delayed_refs.num_heads_ready = 0;
72 cur_trans->delayed_refs.num_heads = 0;
71 cur_trans->delayed_refs.flushing = 0; 73 cur_trans->delayed_refs.flushing = 0;
74 cur_trans->delayed_refs.run_delayed_start = 0;
72 spin_lock_init(&cur_trans->delayed_refs.lock); 75 spin_lock_init(&cur_trans->delayed_refs.lock);
73 76
74 INIT_LIST_HEAD(&cur_trans->pending_snapshots); 77 INIT_LIST_HEAD(&cur_trans->pending_snapshots);
@@ -287,13 +290,19 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
287{ 290{
288 struct btrfs_transaction *cur_trans; 291 struct btrfs_transaction *cur_trans;
289 struct btrfs_fs_info *info = root->fs_info; 292 struct btrfs_fs_info *info = root->fs_info;
290 293 int count = 0;
291 if (trans->delayed_ref_updates && 294
292 (trans->transaction->delayed_refs.flushing || 295 while (count < 4) {
293 trans->transaction->delayed_refs.num_entries > 16384)) { 296 unsigned long cur = trans->delayed_ref_updates;
294 btrfs_run_delayed_refs(trans, root, trans->delayed_ref_updates); 297 trans->delayed_ref_updates = 0;
295 } else if (trans->transaction->delayed_refs.num_entries > 64) { 298 if (cur &&
296 wake_up_process(root->fs_info->transaction_kthread); 299 trans->transaction->delayed_refs.num_heads_ready > 64) {
300 trans->delayed_ref_updates = 0;
301 btrfs_run_delayed_refs(trans, root, cur);
302 } else {
303 break;
304 }
305 count++;
297 } 306 }
298 307
299 mutex_lock(&info->trans_mutex); 308 mutex_lock(&info->trans_mutex);
@@ -929,7 +938,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
929 */ 938 */
930 trans->transaction->delayed_refs.flushing = 1; 939 trans->transaction->delayed_refs.flushing = 1;
931 940
932 ret = btrfs_run_delayed_refs(trans, root, (u64)-1); 941 ret = btrfs_run_delayed_refs(trans, root, 0);
933 BUG_ON(ret); 942 BUG_ON(ret);
934 943
935 INIT_LIST_HEAD(&dirty_fs_roots); 944 INIT_LIST_HEAD(&dirty_fs_roots);