diff options
author | Chris Mason <chris.mason@oracle.com> | 2011-03-23 14:54:42 -0400 |
---|---|---|
committer | root <Chris Mason chris.mason@oracle.com> | 2011-03-28 05:37:22 -0400 |
commit | 240f62c8756df285da11469259b3900f32883168 (patch) | |
tree | eb973ef95389a9511c137c7c26248dfd04a2495f /fs/btrfs/ctree.c | |
parent | c0da7aa1a2d8fcafe271a7077599253c8ed94bb2 (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/btrfs/ctree.c')
-rw-r--r-- | fs/btrfs/ctree.c | 27 |
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) | |||
147 | struct extent_buffer *btrfs_root_node(struct btrfs_root *root) | 147 | struct 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); |