summaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
authorLiu Bo2013-10-14 06:59:45 +0200
committerChris Mason2014-01-28 22:19:22 +0100
commitc46effa601f869f3d20a7386a745d9c002838eb8 (patch)
tree7aa114c1a78e1834950a34524c8ada82569af50b /fs/btrfs/extent-tree.c
parentBtrfs: fix check-integrity to look at the referenced data properly (diff)
downloadkernel-qcow2-linux-c46effa601f869f3d20a7386a745d9c002838eb8.tar.gz
kernel-qcow2-linux-c46effa601f869f3d20a7386a745d9c002838eb8.tar.xz
kernel-qcow2-linux-c46effa601f869f3d20a7386a745d9c002838eb8.zip
Btrfs: introduce a head ref rbtree
The way how we process delayed refs is 1) get a bunch of head refs, 2) pick up one head ref, 3) go one node back for any delayed ref updates. The head ref is also linked in the same rbtree as the delayed ref is, so in 1) stage, we have to walk one by one including not only head refs, but delayed refs. When we have a great number of delayed refs pending to process, this'll cost time a lot. Here we introduce a head ref specific rbtree, it only has head refs, so troubles go away. Signed-off-by: Liu Bo <bo.li.liu@oracle.com> Signed-off-by: Josef Bacik <jbacik@fusionio.com> Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c21
1 files changed, 14 insertions, 7 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 9c01509dd8ab..d15b4fc07554 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -2438,6 +2438,10 @@ static noinline int run_clustered_refs(struct btrfs_trans_handle *trans,
ref->in_tree = 0;
rb_erase(&ref->rb_node, &delayed_refs->root);
+ if (btrfs_delayed_ref_is_head(ref)) {
+ rb_erase(&locked_ref->href_node,
+ &delayed_refs->href_root);
+ }
delayed_refs->num_entries--;
if (!btrfs_delayed_ref_is_head(ref)) {
/*
@@ -2640,7 +2644,7 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
{
struct rb_node *node;
struct btrfs_delayed_ref_root *delayed_refs;
- struct btrfs_delayed_ref_node *ref;
+ struct btrfs_delayed_ref_head *head;
struct list_head cluster;
int ret;
u64 delayed_start;
@@ -2770,18 +2774,18 @@ again:
spin_lock(&delayed_refs->lock);
}
- node = rb_first(&delayed_refs->root);
+ node = rb_first(&delayed_refs->href_root);
if (!node)
goto out;
count = (unsigned long)-1;
while (node) {
- ref = rb_entry(node, struct btrfs_delayed_ref_node,
- rb_node);
- if (btrfs_delayed_ref_is_head(ref)) {
- struct btrfs_delayed_ref_head *head;
+ head = rb_entry(node, struct btrfs_delayed_ref_head,
+ href_node);
+ if (btrfs_delayed_ref_is_head(&head->node)) {
+ struct btrfs_delayed_ref_node *ref;
- head = btrfs_delayed_node_to_head(ref);
+ ref = &head->node;
atomic_inc(&ref->refs);
spin_unlock(&delayed_refs->lock);
@@ -2795,6 +2799,8 @@ again:
btrfs_put_delayed_ref(ref);
cond_resched();
goto again;
+ } else {
+ WARN_ON(1);
}
node = rb_next(node);
}
@@ -5956,6 +5962,7 @@ static noinline int check_ref_cleanup(struct btrfs_trans_handle *trans,
*/
head->node.in_tree = 0;
rb_erase(&head->node.rb_node, &delayed_refs->root);
+ rb_erase(&head->href_node, &delayed_refs->href_root);
delayed_refs->num_entries--;