Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 240f62c8 authored by Chris Mason's avatar Chris Mason Committed by root
Browse files

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: default avatarChris Mason <chris.mason@oracle.com>
parent c0da7aa1
Loading
Loading
Loading
Loading
+8 −19
Original line number Diff line number Diff line
@@ -147,10 +147,11 @@ noinline void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p)
struct extent_buffer *btrfs_root_node(struct btrfs_root *root)
{
	struct extent_buffer *eb;
	spin_lock(&root->node_lock);
	eb = root->node;

	rcu_read_lock();
	eb = rcu_dereference(root->node);
	extent_buffer_get(eb);
	spin_unlock(&root->node_lock);
	rcu_read_unlock();
	return eb;
}

@@ -165,14 +166,8 @@ struct extent_buffer *btrfs_lock_root_node(struct btrfs_root *root)
	while (1) {
		eb = btrfs_root_node(root);
		btrfs_tree_lock(eb);

		spin_lock(&root->node_lock);
		if (eb == root->node) {
			spin_unlock(&root->node_lock);
		if (eb == root->node)
			break;
		}
		spin_unlock(&root->node_lock);

		btrfs_tree_unlock(eb);
		free_extent_buffer(eb);
	}
@@ -458,10 +453,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
		else
			parent_start = 0;

		spin_lock(&root->node_lock);
		root->node = cow;
		extent_buffer_get(cow);
		spin_unlock(&root->node_lock);
		rcu_assign_pointer(root->node, cow);

		btrfs_free_tree_block(trans, root, buf, parent_start,
				      last_ref);
@@ -930,9 +923,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
			goto enospc;
		}

		spin_lock(&root->node_lock);
		root->node = child;
		spin_unlock(&root->node_lock);
		rcu_assign_pointer(root->node, child);

		add_root_to_dirty_list(root);
		btrfs_tree_unlock(child);
@@ -2007,10 +1998,8 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans,

	btrfs_mark_buffer_dirty(c);

	spin_lock(&root->node_lock);
	old = root->node;
	root->node = c;
	spin_unlock(&root->node_lock);
	rcu_assign_pointer(root->node, c);

	/* the super has an extra ref to root->node */
	free_extent_buffer(old);