summaryrefslogtreecommitdiffstats
path: root/fs/btrfs/locking.c
diff options
context:
space:
mode:
authorJosef Bacik <josef@toxicpanda.com>2020-08-20 11:46:01 -0400
committerDavid Sterba <dsterba@suse.com>2020-10-07 12:12:16 +0200
commit51899412dd95b2d9f50297c527b22ada3da0000c (patch)
tree8f5b2c4d45f492cb6b7c917e4af30043314c9690 /fs/btrfs/locking.c
parent329ced799be881feab445b68163cd3869340cc08 (diff)
btrfs: introduce btrfs_path::recurse
Our current tree locking stuff allows us to recurse with read locks if we're already holding the write lock. This is necessary for the space cache inode, as we could be holding a lock on the root_tree root when we need to cache a block group, and thus need to be able to read down the root_tree to read in the inode cache. We can get away with this in our current locking, but we won't be able to with a rwsem. Handle this by purposefully annotating the places where we require recursion, so that in the future we can maybe come up with a way to avoid the recursion. In the case of the free space inode, this will be superseded by the free space tree. Signed-off-by: Josef Bacik <josef@toxicpanda.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs/locking.c')
-rw-r--r--fs/btrfs/locking.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/fs/btrfs/locking.c b/fs/btrfs/locking.c
index 14ceb2ce33ac..740a0cde5731 100644
--- a/fs/btrfs/locking.c
+++ b/fs/btrfs/locking.c
@@ -244,7 +244,7 @@ void btrfs_set_lock_blocking_write(struct extent_buffer *eb)
*
* The rwlock is held upon exit.
*/
-void btrfs_tree_read_lock(struct extent_buffer *eb)
+void __btrfs_tree_read_lock(struct extent_buffer *eb, bool recurse)
{
u64 start_ns = 0;
@@ -263,6 +263,7 @@ again:
* depends on this as it may be called on a partly
* (write-)locked tree.
*/
+ WARN_ON(!recurse);
BUG_ON(eb->lock_recursed);
eb->lock_recursed = true;
read_unlock(&eb->lock);
@@ -279,6 +280,11 @@ again:
trace_btrfs_tree_read_lock(eb, start_ns);
}
+void btrfs_tree_read_lock(struct extent_buffer *eb)
+{
+ __btrfs_tree_read_lock(eb, false);
+}
+
/*
* Lock extent buffer for read, optimistically expecting that there are no
* contending blocking writers. If there are, don't wait.
@@ -552,13 +558,14 @@ struct extent_buffer *btrfs_lock_root_node(struct btrfs_root *root)
*
* Return: root extent buffer with read lock held
*/
-struct extent_buffer *btrfs_read_lock_root_node(struct btrfs_root *root)
+struct extent_buffer *__btrfs_read_lock_root_node(struct btrfs_root *root,
+ bool recurse)
{
struct extent_buffer *eb;
while (1) {
eb = btrfs_root_node(root);
- btrfs_tree_read_lock(eb);
+ __btrfs_tree_read_lock(eb, recurse);
if (eb == root->node)
break;
btrfs_tree_read_unlock(eb);