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>
This commit is contained in:
+16
-7
@@ -68,7 +68,10 @@ static noinline int join_transaction(struct btrfs_root *root)
|
||||
|
||||
cur_trans->delayed_refs.root.rb_node = NULL;
|
||||
cur_trans->delayed_refs.num_entries = 0;
|
||||
cur_trans->delayed_refs.num_heads_ready = 0;
|
||||
cur_trans->delayed_refs.num_heads = 0;
|
||||
cur_trans->delayed_refs.flushing = 0;
|
||||
cur_trans->delayed_refs.run_delayed_start = 0;
|
||||
spin_lock_init(&cur_trans->delayed_refs.lock);
|
||||
|
||||
INIT_LIST_HEAD(&cur_trans->pending_snapshots);
|
||||
@@ -287,13 +290,19 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
|
||||
{
|
||||
struct btrfs_transaction *cur_trans;
|
||||
struct btrfs_fs_info *info = root->fs_info;
|
||||
int count = 0;
|
||||
|
||||
if (trans->delayed_ref_updates &&
|
||||
(trans->transaction->delayed_refs.flushing ||
|
||||
trans->transaction->delayed_refs.num_entries > 16384)) {
|
||||
btrfs_run_delayed_refs(trans, root, trans->delayed_ref_updates);
|
||||
} else if (trans->transaction->delayed_refs.num_entries > 64) {
|
||||
wake_up_process(root->fs_info->transaction_kthread);
|
||||
while (count < 4) {
|
||||
unsigned long cur = trans->delayed_ref_updates;
|
||||
trans->delayed_ref_updates = 0;
|
||||
if (cur &&
|
||||
trans->transaction->delayed_refs.num_heads_ready > 64) {
|
||||
trans->delayed_ref_updates = 0;
|
||||
btrfs_run_delayed_refs(trans, root, cur);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
mutex_lock(&info->trans_mutex);
|
||||
@@ -929,7 +938,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
|
||||
*/
|
||||
trans->transaction->delayed_refs.flushing = 1;
|
||||
|
||||
ret = btrfs_run_delayed_refs(trans, root, (u64)-1);
|
||||
ret = btrfs_run_delayed_refs(trans, root, 0);
|
||||
BUG_ON(ret);
|
||||
|
||||
INIT_LIST_HEAD(&dirty_fs_roots);
|
||||
|
||||
Reference in New Issue
Block a user