aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2011-03-23 14:54:42 -0400
committerroot <Chris Mason chris.mason@oracle.com>2011-03-28 05:37:22 -0400
commit240f62c8756df285da11469259b3900f32883168 (patch)
treeeb973ef95389a9511c137c7c26248dfd04a2495f /fs
parentc0da7aa1a2d8fcafe271a7077599253c8ed94bb2 (diff)
Btrfs: use RCU instead of a spinlock to protect the root node
The pointer to the extent buffer for the root of each tree is protected by a spinlock so that we can safely read the pointer and take a reference on the extent buffer. But now that the extent buffers are freed via RCU, we can safely use rcu_read_lock instead. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/ctree.c27
1 files changed, 8 insertions, 19 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 73e53009e126..8680110f0a5a 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -147,10 +147,11 @@ noinline void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p)
147struct extent_buffer *btrfs_root_node(struct btrfs_root *root) 147struct extent_buffer *btrfs_root_node(struct btrfs_root *root)
148{ 148{
149 struct extent_buffer *eb; 149 struct extent_buffer *eb;
150 spin_lock(&root->node_lock); 150
151 eb = root->node; 151 rcu_read_lock();
152 eb = rcu_dereference(root->node);
152 extent_buffer_get(eb); 153 extent_buffer_get(eb);
153 spin_unlock(&root->node_lock); 154 rcu_read_unlock();
154 return eb; 155 return eb;
155} 156}
156 157
@@ -165,14 +166,8 @@ struct extent_buffer *btrfs_lock_root_node(struct btrfs_root *root)
165 while (1) { 166 while (1) {
166 eb = btrfs_root_node(root); 167 eb = btrfs_root_node(root);
167 btrfs_tree_lock(eb); 168 btrfs_tree_lock(eb);
168 169 if (eb == root->node)
169 spin_lock(&root->node_lock);
170 if (eb == root->node) {
171 spin_unlock(&root->node_lock);
172 break; 170 break;
173 }
174 spin_unlock(&root->node_lock);
175
176 btrfs_tree_unlock(eb); 171 btrfs_tree_unlock(eb);
177 free_extent_buffer(eb); 172 free_extent_buffer(eb);
178 } 173 }
@@ -458,10 +453,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
458 else 453 else
459 parent_start = 0; 454 parent_start = 0;
460 455
461 spin_lock(&root->node_lock);
462 root->node = cow;
463 extent_buffer_get(cow); 456 extent_buffer_get(cow);
464 spin_unlock(&root->node_lock); 457 rcu_assign_pointer(root->node, cow);
465 458
466 btrfs_free_tree_block(trans, root, buf, parent_start, 459 btrfs_free_tree_block(trans, root, buf, parent_start,
467 last_ref); 460 last_ref);
@@ -930,9 +923,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
930 goto enospc; 923 goto enospc;
931 } 924 }
932 925
933 spin_lock(&root->node_lock); 926 rcu_assign_pointer(root->node, child);
934 root->node = child;
935 spin_unlock(&root->node_lock);
936 927
937 add_root_to_dirty_list(root); 928 add_root_to_dirty_list(root);
938 btrfs_tree_unlock(child); 929 btrfs_tree_unlock(child);
@@ -2007,10 +1998,8 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans,
2007 1998
2008 btrfs_mark_buffer_dirty(c); 1999 btrfs_mark_buffer_dirty(c);
2009 2000
2010 spin_lock(&root->node_lock);
2011 old = root->node; 2001 old = root->node;
2012 root->node = c; 2002 rcu_assign_pointer(root->node, c);
2013 spin_unlock(&root->node_lock);
2014 2003
2015 /* the super has an extra ref to root->node */ 2004 /* the super has an extra ref to root->node */
2016 free_extent_buffer(old); 2005 free_extent_buffer(old);