linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/14] Set the lockdep class on eb's at allocation time
@ 2020-10-30 21:02 Josef Bacik
  2020-10-30 21:02 ` [PATCH 01/14] btrfs: remove lockdep classes for the fs tree Josef Bacik
                   ` (13 more replies)
  0 siblings, 14 replies; 17+ messages in thread
From: Josef Bacik @ 2020-10-30 21:02 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

Hello,

We've had a lockdep splat show up a few times recently where the extent buffer
doesn't have it's lockdep class set properly.  This can happen if you have
concurrent readers hitting the same block that's not in cache.

This is sort of straightforward to fix, but unfortunately requires quite a bit
of code churn to do it cleanly.  The bulck of these patches are replacing open
coded calls of btrfs_read_node_slot() with the helper to cut down on the number
of people directly calling read_tree_block().  I also cleaned up the readahead
helpers because passing all these arguments around would be unweildy.  The last
patch in the series is the actual fix for what Filipe and Fedora QA saw.

The patches that actually have meaningful changes are

  btrfs: remove lockdep classes for the fs tree
  btrfs: cleanup extent buffer readahead
  btrfs: set the lockdep class for ebs on creation

The rest are cleanups or adding arguments to various functions, so aren't too
tricky.  I've put this through a quick xfstest run for sanity sake, it didn't
appear to break anything, but the full run is still going.  Thanks,

Josef

Josef Bacik (14):
  btrfs: remove lockdep classes for the fs tree
  btrfs: cleanup extent buffer readahead
  btrfs: use btrfs_read_node_slot in btrfs_realloc_node
  btrfs: use btrfs_read_node_slot in walk_down_reloc_tree
  btrfs: use btrfs_read_node_slot in do_relocation
  btrfs: use btrfs_read_node_slot in replace_path
  btrfs: use btrfs_read_node_slot in walk_down_tree
  btrfs: use btrfs_read_node_slot in qgroup_trace_extent_swap
  btrfs: use btrfs_read_node_slot in qgroup_trace_new_subtree_blocks
  btrfs: use btrfs_read_node_slot in btrfs_qgroup_trace_subtree
  btrfs: pass root owner to read_tree_block
  btrfs: pass the root owner and level around for reada
  btrfs: pass the owner_root and level to alloc_extent_buffer
  btrfs: set the lockdep class for ebs on creation

 fs/btrfs/backref.c     |  6 +--
 fs/btrfs/ctree.c       | 86 +++++++++---------------------------------
 fs/btrfs/disk-io.c     | 41 +++++++-------------
 fs/btrfs/disk-io.h     |  8 ++--
 fs/btrfs/extent-tree.c | 20 ++++++----
 fs/btrfs/extent_io.c   | 55 ++++++++++++++++++++++++++-
 fs/btrfs/extent_io.h   |  6 ++-
 fs/btrfs/print-tree.c  |  1 +
 fs/btrfs/qgroup.c      | 43 ++++-----------------
 fs/btrfs/reada.c       | 32 +++++++++++-----
 fs/btrfs/ref-verify.c  | 18 +--------
 fs/btrfs/relocation.c  | 45 +++++-----------------
 fs/btrfs/tree-log.c    |  4 +-
 fs/btrfs/volumes.c     | 12 ++----
 14 files changed, 157 insertions(+), 220 deletions(-)

-- 
2.26.2


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 01/14] btrfs: remove lockdep classes for the fs tree
  2020-10-30 21:02 [PATCH 00/14] Set the lockdep class on eb's at allocation time Josef Bacik
@ 2020-10-30 21:02 ` Josef Bacik
  2020-10-30 21:02 ` [PATCH 02/14] btrfs: cleanup extent buffer readahead Josef Bacik
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 17+ messages in thread
From: Josef Bacik @ 2020-10-30 21:02 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

We have this weird problem where our lockdep class is set after we
read a tree block, which can race with concurrent readers and result in
erroneous lockdep errors.  We want to set the lockdep class at
allocation time if possible, but in certain cases we may not have the
actual root owner, such as with relocation or any backref lookups.  This
is only really a problem for reference counted tree's, because all other
tree's have their root reference set in their extent reference.  Remove
the fs tree specific lock class.  We need to still keep the reloc tree
one, it's still reference counted, because replace_path will lock the
reloc tree and the destination tree, and if they're both set to
tree-<level> we'll have issues.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/disk-io.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 601a7ab2adb4..73eae594e934 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -160,7 +160,6 @@ static struct btrfs_lockdep_keyset {
 	{ .id = BTRFS_EXTENT_TREE_OBJECTID,	.name_stem = "extent"	},
 	{ .id = BTRFS_CHUNK_TREE_OBJECTID,	.name_stem = "chunk"	},
 	{ .id = BTRFS_DEV_TREE_OBJECTID,	.name_stem = "dev"	},
-	{ .id = BTRFS_FS_TREE_OBJECTID,		.name_stem = "fs"	},
 	{ .id = BTRFS_CSUM_TREE_OBJECTID,	.name_stem = "csum"	},
 	{ .id = BTRFS_QUOTA_TREE_OBJECTID,	.name_stem = "quota"	},
 	{ .id = BTRFS_TREE_LOG_OBJECTID,	.name_stem = "log"	},
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 02/14] btrfs: cleanup extent buffer readahead
  2020-10-30 21:02 [PATCH 00/14] Set the lockdep class on eb's at allocation time Josef Bacik
  2020-10-30 21:02 ` [PATCH 01/14] btrfs: remove lockdep classes for the fs tree Josef Bacik
@ 2020-10-30 21:02 ` Josef Bacik
  2020-10-30 21:02 ` [PATCH 03/14] btrfs: use btrfs_read_node_slot in btrfs_realloc_node Josef Bacik
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 17+ messages in thread
From: Josef Bacik @ 2020-10-30 21:02 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

I'm going to need to start passing around a lot more information when we
allocate extent buffers, in order to make that cleaner we need to
cleanup how we do readahead.  Most of the callers have the parent node
that we're getting our blockptr from, with the sole exception of
relocation which simply has the bytenr it wants to read.  Add a helper
that takes the current arguments that we need (bytenr and gen), and add
another helper for simply reading the slot out of a node.  In followup
patches the helper that takes all the extra arguments will be expanded,
and the simpler helper won't need to have it's arguments adjusted.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/ctree.c       | 45 ++++++++--------------------------------
 fs/btrfs/disk-io.c     | 16 --------------
 fs/btrfs/disk-io.h     |  1 -
 fs/btrfs/extent-tree.c |  2 +-
 fs/btrfs/extent_io.c   | 47 ++++++++++++++++++++++++++++++++++++++++++
 fs/btrfs/extent_io.h   |  3 +++
 fs/btrfs/relocation.c  |  3 ++-
 fs/btrfs/volumes.c     |  8 ++-----
 8 files changed, 64 insertions(+), 61 deletions(-)

diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 113da62dc17f..f8a7416d8a24 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -2243,7 +2243,7 @@ static void reada_for_search(struct btrfs_fs_info *fs_info,
 		search = btrfs_node_blockptr(node, nr);
 		if ((search <= target && target - search <= 65536) ||
 		    (search > target && search - target <= 65536)) {
-			readahead_tree_block(fs_info, search);
+			btrfs_readahead_node_child(node, nr);
 			nread += blocksize;
 		}
 		nscan++;
@@ -2252,16 +2252,11 @@ static void reada_for_search(struct btrfs_fs_info *fs_info,
 	}
 }
 
-static noinline void reada_for_balance(struct btrfs_fs_info *fs_info,
-				       struct btrfs_path *path, int level)
+static noinline void reada_for_balance(struct btrfs_path *path, int level)
 {
+	struct extent_buffer *parent;
 	int slot;
 	int nritems;
-	struct extent_buffer *parent;
-	struct extent_buffer *eb;
-	u64 gen;
-	u64 block1 = 0;
-	u64 block2 = 0;
 
 	parent = path->nodes[level + 1];
 	if (!parent)
@@ -2270,32 +2265,10 @@ static noinline void reada_for_balance(struct btrfs_fs_info *fs_info,
 	nritems = btrfs_header_nritems(parent);
 	slot = path->slots[level + 1];
 
-	if (slot > 0) {
-		block1 = btrfs_node_blockptr(parent, slot - 1);
-		gen = btrfs_node_ptr_generation(parent, slot - 1);
-		eb = find_extent_buffer(fs_info, block1);
-		/*
-		 * if we get -eagain from btrfs_buffer_uptodate, we
-		 * don't want to return eagain here.  That will loop
-		 * forever
-		 */
-		if (eb && btrfs_buffer_uptodate(eb, gen, 1) != 0)
-			block1 = 0;
-		free_extent_buffer(eb);
-	}
-	if (slot + 1 < nritems) {
-		block2 = btrfs_node_blockptr(parent, slot + 1);
-		gen = btrfs_node_ptr_generation(parent, slot + 1);
-		eb = find_extent_buffer(fs_info, block2);
-		if (eb && btrfs_buffer_uptodate(eb, gen, 1) != 0)
-			block2 = 0;
-		free_extent_buffer(eb);
-	}
-
-	if (block1)
-		readahead_tree_block(fs_info, block1);
-	if (block2)
-		readahead_tree_block(fs_info, block2);
+	if (slot > 0)
+		btrfs_readahead_node_child(parent, slot - 1);
+	if (slot + 1 < nritems)
+		btrfs_readahead_node_child(parent, slot + 1);
 }
 
 
@@ -2481,7 +2454,7 @@ setup_nodes_for_search(struct btrfs_trans_handle *trans,
 		}
 
 		btrfs_set_path_blocking(p);
-		reada_for_balance(fs_info, p, level);
+		reada_for_balance(p, level);
 		sret = split_node(trans, root, p, level);
 
 		BUG_ON(sret > 0);
@@ -2501,7 +2474,7 @@ setup_nodes_for_search(struct btrfs_trans_handle *trans,
 		}
 
 		btrfs_set_path_blocking(p);
-		reada_for_balance(fs_info, p, level);
+		reada_for_balance(p, level);
 		sret = balance_level(trans, root, p, level);
 
 		if (sret) {
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 73eae594e934..464dfb15b054 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -946,22 +946,6 @@ static const struct address_space_operations btree_aops = {
 	.set_page_dirty = btree_set_page_dirty,
 };
 
-void readahead_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr)
-{
-	struct extent_buffer *buf = NULL;
-	int ret;
-
-	buf = btrfs_find_create_tree_block(fs_info, bytenr);
-	if (IS_ERR(buf))
-		return;
-
-	ret = read_extent_buffer_pages(buf, WAIT_NONE, 0);
-	if (ret < 0)
-		free_extent_buffer_stale(buf);
-	else
-		free_extent_buffer(buf);
-}
-
 struct extent_buffer *btrfs_find_create_tree_block(
 						struct btrfs_fs_info *fs_info,
 						u64 bytenr)
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
index 182540bdcea0..34934f38582b 100644
--- a/fs/btrfs/disk-io.h
+++ b/fs/btrfs/disk-io.h
@@ -45,7 +45,6 @@ int btrfs_verify_level_key(struct extent_buffer *eb, int level,
 struct extent_buffer *read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr,
 				      u64 parent_transid, int level,
 				      struct btrfs_key *first_key);
-void readahead_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr);
 struct extent_buffer *btrfs_find_create_tree_block(
 						struct btrfs_fs_info *fs_info,
 						u64 bytenr);
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 5fd60b13f4f8..0ca1135dab8c 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -4905,7 +4905,7 @@ static noinline void reada_walk_down(struct btrfs_trans_handle *trans,
 				continue;
 		}
 reada:
-		readahead_tree_block(fs_info, bytenr);
+		btrfs_readahead_node_child(eb, slot);
 		nread++;
 	}
 	wc->reada_slot = slot;
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index cf3f576d6277..654e2e517f3d 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -6106,3 +6106,50 @@ int try_release_extent_buffer(struct page *page)
 
 	return release_extent_buffer(eb);
 }
+
+/**
+ * btrfs_readahead_tree_block - attempt to readahead a child block.
+ * @fs_info - the fs_info for the fs.
+ * @bytenr - the bytenr to read.
+ * @gen - the generation for the uptodate check, can be 0.
+ *
+ * Attempt to readahead a tree block at @bytenr.  If @gen is 0 then we do a
+ * normal uptodate check of the eb, without checking the generation.  If we have
+ * to read the block we will not block on anything.
+ */
+void btrfs_readahead_tree_block(struct btrfs_fs_info *fs_info,
+				u64 bytenr, u64 gen)
+{
+	struct extent_buffer *eb;
+	int ret;
+
+	eb = btrfs_find_create_tree_block(fs_info, bytenr);
+	if (IS_ERR(eb))
+		return;
+
+	if (btrfs_buffer_uptodate(eb, gen, 1)) {
+		free_extent_buffer(eb);
+		return;
+	}
+
+	ret = read_extent_buffer_pages(eb, WAIT_NONE, 0);
+	if (ret < 0)
+		free_extent_buffer_stale(eb);
+	else
+		free_extent_buffer(eb);
+}
+
+/**
+ * btrfs_readahead_node_child - readahead a node's child block.
+ * @node - the parent node we're reading from.
+ * @slot - the slot in the parent node for the child we want to read.
+ *
+ * A helper for btrfs_readahead_tree_block, we simply read the bytenr pointed at
+ * the slot in the node provided.
+ */
+void btrfs_readahead_node_child(struct extent_buffer *node, int slot)
+{
+	btrfs_readahead_tree_block(node->fs_info,
+				   btrfs_node_blockptr(node, slot),
+				   btrfs_node_ptr_generation(node, slot));
+}
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
index 3801eb3b726e..4f95b087a901 100644
--- a/fs/btrfs/extent_io.h
+++ b/fs/btrfs/extent_io.h
@@ -198,6 +198,9 @@ void free_extent_buffer_stale(struct extent_buffer *eb);
 int read_extent_buffer_pages(struct extent_buffer *eb, int wait,
 			     int mirror_num);
 void wait_on_extent_buffer_writeback(struct extent_buffer *eb);
+void btrfs_readahead_tree_block(struct btrfs_fs_info *fs_info,
+				u64 bytenr, u64 gen);
+void btrfs_readahead_node_child(struct extent_buffer *node, int slot);
 
 static inline int num_extent_pages(const struct extent_buffer *eb)
 {
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 9ba92d86da0b..50ca5a4f0a96 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -2546,7 +2546,8 @@ int relocate_tree_blocks(struct btrfs_trans_handle *trans,
 	/* Kick in readahead for tree blocks with missing keys */
 	rbtree_postorder_for_each_entry_safe(block, next, blocks, rb_node) {
 		if (!block->key_ready)
-			readahead_tree_block(fs_info, block->bytenr);
+			btrfs_readahead_tree_block(fs_info,
+						   block->bytenr, 0);
 	}
 
 	/* Get first keys */
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index eb9ee7c2998f..75350c78ca02 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -7077,12 +7077,8 @@ static void readahead_tree_node_children(struct extent_buffer *node)
 	int i;
 	const int nr_items = btrfs_header_nritems(node);
 
-	for (i = 0; i < nr_items; i++) {
-		u64 start;
-
-		start = btrfs_node_blockptr(node, i);
-		readahead_tree_block(node->fs_info, start);
-	}
+	for (i = 0; i < nr_items; i++)
+		btrfs_readahead_node_child(node, i);
 }
 
 int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info)
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 03/14] btrfs: use btrfs_read_node_slot in btrfs_realloc_node
  2020-10-30 21:02 [PATCH 00/14] Set the lockdep class on eb's at allocation time Josef Bacik
  2020-10-30 21:02 ` [PATCH 01/14] btrfs: remove lockdep classes for the fs tree Josef Bacik
  2020-10-30 21:02 ` [PATCH 02/14] btrfs: cleanup extent buffer readahead Josef Bacik
@ 2020-10-30 21:02 ` Josef Bacik
  2020-10-30 21:02 ` [PATCH 04/14] btrfs: use btrfs_read_node_slot in walk_down_reloc_tree Josef Bacik
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 17+ messages in thread
From: Josef Bacik @ 2020-10-30 21:02 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

We have this giant open-coded nightmare in btrfs_realloc_node that does
the same thing that the normal read path does, which is to see if we
have the eb in memory already, and if not read it, and verify the eb is
uptodate.  Delete this open coding and simply use btrfs_read_node_slot.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/ctree.c | 33 +++------------------------------
 1 file changed, 3 insertions(+), 30 deletions(-)

diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index f8a7416d8a24..000f18923c5a 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -1578,7 +1578,6 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
 	struct btrfs_fs_info *fs_info = root->fs_info;
 	struct extent_buffer *cur;
 	u64 blocknr;
-	u64 gen;
 	u64 search_start = *last_ret;
 	u64 last_block = 0;
 	u64 other;
@@ -1587,7 +1586,6 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
 	int i;
 	int err = 0;
 	int parent_level;
-	int uptodate;
 	u32 blocksize;
 	int progress_passed = 0;
 	struct btrfs_disk_key disk_key;
@@ -1607,7 +1605,6 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
 	btrfs_set_lock_blocking_write(parent);
 
 	for (i = start_slot; i <= end_slot; i++) {
-		struct btrfs_key first_key;
 		int close = 1;
 
 		btrfs_node_key(parent, &disk_key, i);
@@ -1616,8 +1613,6 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
 
 		progress_passed = 1;
 		blocknr = btrfs_node_blockptr(parent, i);
-		gen = btrfs_node_ptr_generation(parent, i);
-		btrfs_node_key_to_cpu(parent, &first_key, i);
 		if (last_block == 0)
 			last_block = blocknr;
 
@@ -1634,31 +1629,9 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
 			continue;
 		}
 
-		cur = find_extent_buffer(fs_info, blocknr);
-		if (cur)
-			uptodate = btrfs_buffer_uptodate(cur, gen, 0);
-		else
-			uptodate = 0;
-		if (!cur || !uptodate) {
-			if (!cur) {
-				cur = read_tree_block(fs_info, blocknr, gen,
-						      parent_level - 1,
-						      &first_key);
-				if (IS_ERR(cur)) {
-					return PTR_ERR(cur);
-				} else if (!extent_buffer_uptodate(cur)) {
-					free_extent_buffer(cur);
-					return -EIO;
-				}
-			} else if (!uptodate) {
-				err = btrfs_read_buffer(cur, gen,
-						parent_level - 1,&first_key);
-				if (err) {
-					free_extent_buffer(cur);
-					return err;
-				}
-			}
-		}
+		cur = btrfs_read_node_slot(parent, i);
+		if (IS_ERR(cur))
+			return PTR_ERR(cur);
 		if (search_start == 0)
 			search_start = last_block;
 
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 04/14] btrfs: use btrfs_read_node_slot in walk_down_reloc_tree
  2020-10-30 21:02 [PATCH 00/14] Set the lockdep class on eb's at allocation time Josef Bacik
                   ` (2 preceding siblings ...)
  2020-10-30 21:02 ` [PATCH 03/14] btrfs: use btrfs_read_node_slot in btrfs_realloc_node Josef Bacik
@ 2020-10-30 21:02 ` Josef Bacik
  2020-10-30 21:02 ` [PATCH 05/14] btrfs: use btrfs_read_node_slot in do_relocation Josef Bacik
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 17+ messages in thread
From: Josef Bacik @ 2020-10-30 21:02 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

We do not need to call read_tree_block() here, simply use the
btrfs_read_node_slot helper.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/relocation.c | 15 ++-------------
 1 file changed, 2 insertions(+), 13 deletions(-)

diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 50ca5a4f0a96..bf31b86945d5 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -1418,10 +1418,8 @@ static noinline_for_stack
 int walk_down_reloc_tree(struct btrfs_root *root, struct btrfs_path *path,
 			 int *level)
 {
-	struct btrfs_fs_info *fs_info = root->fs_info;
 	struct extent_buffer *eb = NULL;
 	int i;
-	u64 bytenr;
 	u64 ptr_gen = 0;
 	u64 last_snapshot;
 	u32 nritems;
@@ -1429,8 +1427,6 @@ int walk_down_reloc_tree(struct btrfs_root *root, struct btrfs_path *path,
 	last_snapshot = btrfs_root_last_snapshot(&root->root_item);
 
 	for (i = *level; i > 0; i--) {
-		struct btrfs_key first_key;
-
 		eb = path->nodes[i];
 		nritems = btrfs_header_nritems(eb);
 		while (path->slots[i] < nritems) {
@@ -1450,16 +1446,9 @@ int walk_down_reloc_tree(struct btrfs_root *root, struct btrfs_path *path,
 			return 0;
 		}
 
-		bytenr = btrfs_node_blockptr(eb, path->slots[i]);
-		btrfs_node_key_to_cpu(eb, &first_key, path->slots[i]);
-		eb = read_tree_block(fs_info, bytenr, ptr_gen, i - 1,
-				     &first_key);
-		if (IS_ERR(eb)) {
+		eb = btrfs_read_node_slot(eb, path->slots[i]);
+		if (IS_ERR(eb))
 			return PTR_ERR(eb);
-		} else if (!extent_buffer_uptodate(eb)) {
-			free_extent_buffer(eb);
-			return -EIO;
-		}
 		BUG_ON(btrfs_header_level(eb) != i - 1);
 		path->nodes[i - 1] = eb;
 		path->slots[i - 1] = 0;
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 05/14] btrfs: use btrfs_read_node_slot in do_relocation
  2020-10-30 21:02 [PATCH 00/14] Set the lockdep class on eb's at allocation time Josef Bacik
                   ` (3 preceding siblings ...)
  2020-10-30 21:02 ` [PATCH 04/14] btrfs: use btrfs_read_node_slot in walk_down_reloc_tree Josef Bacik
@ 2020-10-30 21:02 ` Josef Bacik
  2020-10-30 21:02 ` [PATCH 06/14] btrfs: use btrfs_read_node_slot in replace_path Josef Bacik
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 17+ messages in thread
From: Josef Bacik @ 2020-10-30 21:02 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

We're open coding btrfs_read_node_slot in do_relocation, replace this
with the proper helper.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/relocation.c | 12 +-----------
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index bf31b86945d5..874ae92c0df4 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -2194,7 +2194,6 @@ static int do_relocation(struct btrfs_trans_handle *trans,
 			 struct btrfs_key *key,
 			 struct btrfs_path *path, int lowest)
 {
-	struct btrfs_fs_info *fs_info = rc->extent_root->fs_info;
 	struct btrfs_backref_node *upper;
 	struct btrfs_backref_edge *edge;
 	struct btrfs_backref_edge *edges[BTRFS_MAX_LEVEL - 1];
@@ -2202,7 +2201,6 @@ static int do_relocation(struct btrfs_trans_handle *trans,
 	struct extent_buffer *eb;
 	u32 blocksize;
 	u64 bytenr;
-	u64 generation;
 	int slot;
 	int ret;
 	int err = 0;
@@ -2212,7 +2210,6 @@ static int do_relocation(struct btrfs_trans_handle *trans,
 	path->lowest_level = node->level + 1;
 	rc->backref_cache.path[node->level] = node;
 	list_for_each_entry(edge, &node->upper, list[LOWER]) {
-		struct btrfs_key first_key;
 		struct btrfs_ref ref = { 0 };
 
 		cond_resched();
@@ -2285,17 +2282,10 @@ static int do_relocation(struct btrfs_trans_handle *trans,
 		}
 
 		blocksize = root->fs_info->nodesize;
-		generation = btrfs_node_ptr_generation(upper->eb, slot);
-		btrfs_node_key_to_cpu(upper->eb, &first_key, slot);
-		eb = read_tree_block(fs_info, bytenr, generation,
-				     upper->level - 1, &first_key);
+		eb = btrfs_read_node_slot(upper->eb, slot);
 		if (IS_ERR(eb)) {
 			err = PTR_ERR(eb);
 			goto next;
-		} else if (!extent_buffer_uptodate(eb)) {
-			free_extent_buffer(eb);
-			err = -EIO;
-			goto next;
 		}
 		btrfs_tree_lock(eb);
 		btrfs_set_lock_blocking_write(eb);
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 06/14] btrfs: use btrfs_read_node_slot in replace_path
  2020-10-30 21:02 [PATCH 00/14] Set the lockdep class on eb's at allocation time Josef Bacik
                   ` (4 preceding siblings ...)
  2020-10-30 21:02 ` [PATCH 05/14] btrfs: use btrfs_read_node_slot in do_relocation Josef Bacik
@ 2020-10-30 21:02 ` Josef Bacik
  2020-10-30 21:02 ` [PATCH 07/14] btrfs: use btrfs_read_node_slot in walk_down_tree Josef Bacik
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 17+ messages in thread
From: Josef Bacik @ 2020-10-30 21:02 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

We're open-coding btrfs_read_node_slot() here, replace with the helper.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/relocation.c | 10 +---------
 1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 874ae92c0df4..55a745cb28d4 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -1220,8 +1220,6 @@ int replace_path(struct btrfs_trans_handle *trans, struct reloc_control *rc,
 
 	parent = eb;
 	while (1) {
-		struct btrfs_key first_key;
-
 		level = btrfs_header_level(parent);
 		BUG_ON(level < lowest_level);
 
@@ -1237,7 +1235,6 @@ int replace_path(struct btrfs_trans_handle *trans, struct reloc_control *rc,
 		old_bytenr = btrfs_node_blockptr(parent, slot);
 		blocksize = fs_info->nodesize;
 		old_ptr_gen = btrfs_node_ptr_generation(parent, slot);
-		btrfs_node_key_to_cpu(parent, &first_key, slot);
 
 		if (level <= max_level) {
 			eb = path->nodes[level];
@@ -1262,15 +1259,10 @@ int replace_path(struct btrfs_trans_handle *trans, struct reloc_control *rc,
 				break;
 			}
 
-			eb = read_tree_block(fs_info, old_bytenr, old_ptr_gen,
-					     level - 1, &first_key);
+			eb = btrfs_read_node_slot(parent, slot);
 			if (IS_ERR(eb)) {
 				ret = PTR_ERR(eb);
 				break;
-			} else if (!extent_buffer_uptodate(eb)) {
-				ret = -EIO;
-				free_extent_buffer(eb);
-				break;
 			}
 			btrfs_tree_lock(eb);
 			if (cow) {
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 07/14] btrfs: use btrfs_read_node_slot in walk_down_tree
  2020-10-30 21:02 [PATCH 00/14] Set the lockdep class on eb's at allocation time Josef Bacik
                   ` (5 preceding siblings ...)
  2020-10-30 21:02 ` [PATCH 06/14] btrfs: use btrfs_read_node_slot in replace_path Josef Bacik
@ 2020-10-30 21:02 ` Josef Bacik
  2020-10-30 21:03 ` [PATCH 08/14] btrfs: use btrfs_read_node_slot in qgroup_trace_extent_swap Josef Bacik
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 17+ messages in thread
From: Josef Bacik @ 2020-10-30 21:02 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

We're open-coding btrfs_read_node_slot() here, replace with the helper.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/ref-verify.c | 18 ++----------------
 1 file changed, 2 insertions(+), 16 deletions(-)

diff --git a/fs/btrfs/ref-verify.c b/fs/btrfs/ref-verify.c
index 7f03dbe5b609..4c9ddc750914 100644
--- a/fs/btrfs/ref-verify.c
+++ b/fs/btrfs/ref-verify.c
@@ -551,29 +551,15 @@ static int process_leaf(struct btrfs_root *root,
 static int walk_down_tree(struct btrfs_root *root, struct btrfs_path *path,
 			  int level, u64 *bytenr, u64 *num_bytes)
 {
-	struct btrfs_fs_info *fs_info = root->fs_info;
 	struct extent_buffer *eb;
-	u64 block_bytenr, gen;
 	int ret = 0;
 
 	while (level >= 0) {
 		if (level) {
-			struct btrfs_key first_key;
-
-			block_bytenr = btrfs_node_blockptr(path->nodes[level],
-							   path->slots[level]);
-			gen = btrfs_node_ptr_generation(path->nodes[level],
-							path->slots[level]);
-			btrfs_node_key_to_cpu(path->nodes[level], &first_key,
-					      path->slots[level]);
-			eb = read_tree_block(fs_info, block_bytenr, gen,
-					     level - 1, &first_key);
+			eb = btrfs_read_node_slot(path->nodes[level],
+						  path->slots[level]);
 			if (IS_ERR(eb))
 				return PTR_ERR(eb);
-			if (!extent_buffer_uptodate(eb)) {
-				free_extent_buffer(eb);
-				return -EIO;
-			}
 			btrfs_tree_read_lock(eb);
 			btrfs_set_lock_blocking_read(eb);
 			path->nodes[level-1] = eb;
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 08/14] btrfs: use btrfs_read_node_slot in qgroup_trace_extent_swap
  2020-10-30 21:02 [PATCH 00/14] Set the lockdep class on eb's at allocation time Josef Bacik
                   ` (6 preceding siblings ...)
  2020-10-30 21:02 ` [PATCH 07/14] btrfs: use btrfs_read_node_slot in walk_down_tree Josef Bacik
@ 2020-10-30 21:03 ` Josef Bacik
  2020-10-30 21:03 ` [PATCH 09/14] btrfs: use btrfs_read_node_slot in qgroup_trace_new_subtree_blocks Josef Bacik
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 17+ messages in thread
From: Josef Bacik @ 2020-10-30 21:03 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

We're open-coding btrfs_read_node_slot() here, replace with the helper.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/qgroup.c | 13 +------------
 1 file changed, 1 insertion(+), 12 deletions(-)

diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
index 77c54749f432..f009beeba385 100644
--- a/fs/btrfs/qgroup.c
+++ b/fs/btrfs/qgroup.c
@@ -1894,27 +1894,16 @@ static int qgroup_trace_extent_swap(struct btrfs_trans_handle* trans,
 		struct btrfs_key dst_key;
 
 		if (src_path->nodes[cur_level] == NULL) {
-			struct btrfs_key first_key;
 			struct extent_buffer *eb;
 			int parent_slot;
-			u64 child_gen;
-			u64 child_bytenr;
 
 			eb = src_path->nodes[cur_level + 1];
 			parent_slot = src_path->slots[cur_level + 1];
-			child_bytenr = btrfs_node_blockptr(eb, parent_slot);
-			child_gen = btrfs_node_ptr_generation(eb, parent_slot);
-			btrfs_node_key_to_cpu(eb, &first_key, parent_slot);
 
-			eb = read_tree_block(fs_info, child_bytenr, child_gen,
-					     cur_level, &first_key);
+			eb = btrfs_read_node_slot(eb, parent_slot);
 			if (IS_ERR(eb)) {
 				ret = PTR_ERR(eb);
 				goto out;
-			} else if (!extent_buffer_uptodate(eb)) {
-				free_extent_buffer(eb);
-				ret = -EIO;
-				goto out;
 			}
 
 			src_path->nodes[cur_level] = eb;
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 09/14] btrfs: use btrfs_read_node_slot in qgroup_trace_new_subtree_blocks
  2020-10-30 21:02 [PATCH 00/14] Set the lockdep class on eb's at allocation time Josef Bacik
                   ` (7 preceding siblings ...)
  2020-10-30 21:03 ` [PATCH 08/14] btrfs: use btrfs_read_node_slot in qgroup_trace_extent_swap Josef Bacik
@ 2020-10-30 21:03 ` Josef Bacik
  2020-10-30 21:03 ` [PATCH 10/14] btrfs: use btrfs_read_node_slot in btrfs_qgroup_trace_subtree Josef Bacik
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 17+ messages in thread
From: Josef Bacik @ 2020-10-30 21:03 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

We're open-coding btrfs_read_node_slot() here, replace with the helper.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/qgroup.c | 13 ++-----------
 1 file changed, 2 insertions(+), 11 deletions(-)

diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
index f009beeba385..ddd1cd6db6c4 100644
--- a/fs/btrfs/qgroup.c
+++ b/fs/btrfs/qgroup.c
@@ -2005,10 +2005,8 @@ static int qgroup_trace_new_subtree_blocks(struct btrfs_trans_handle* trans,
 
 	/* Read the tree block if needed */
 	if (dst_path->nodes[cur_level] == NULL) {
-		struct btrfs_key first_key;
-		int parent_slot;
 		u64 child_gen;
-		u64 child_bytenr;
+		int parent_slot;
 
 		/*
 		 * dst_path->nodes[root_level] must be initialized before
@@ -2027,23 +2025,16 @@ static int qgroup_trace_new_subtree_blocks(struct btrfs_trans_handle* trans,
 		  */
 		eb = dst_path->nodes[cur_level + 1];
 		parent_slot = dst_path->slots[cur_level + 1];
-		child_bytenr = btrfs_node_blockptr(eb, parent_slot);
 		child_gen = btrfs_node_ptr_generation(eb, parent_slot);
-		btrfs_node_key_to_cpu(eb, &first_key, parent_slot);
 
 		/* This node is old, no need to trace */
 		if (child_gen < last_snapshot)
 			goto out;
 
-		eb = read_tree_block(fs_info, child_bytenr, child_gen,
-				     cur_level, &first_key);
+		eb = btrfs_read_node_slot(eb, parent_slot);
 		if (IS_ERR(eb)) {
 			ret = PTR_ERR(eb);
 			goto out;
-		} else if (!extent_buffer_uptodate(eb)) {
-			free_extent_buffer(eb);
-			ret = -EIO;
-			goto out;
 		}
 
 		dst_path->nodes[cur_level] = eb;
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 10/14] btrfs: use btrfs_read_node_slot in btrfs_qgroup_trace_subtree
  2020-10-30 21:02 [PATCH 00/14] Set the lockdep class on eb's at allocation time Josef Bacik
                   ` (8 preceding siblings ...)
  2020-10-30 21:03 ` [PATCH 09/14] btrfs: use btrfs_read_node_slot in qgroup_trace_new_subtree_blocks Josef Bacik
@ 2020-10-30 21:03 ` Josef Bacik
  2020-10-30 21:03 ` [PATCH 11/14] btrfs: pass root owner to read_tree_block Josef Bacik
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 17+ messages in thread
From: Josef Bacik @ 2020-10-30 21:03 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

We're open-coding btrfs_read_node_slot() here, replace with the helper.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/qgroup.c | 15 +++------------
 1 file changed, 3 insertions(+), 12 deletions(-)

diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
index ddd1cd6db6c4..0052b1c7d4c3 100644
--- a/fs/btrfs/qgroup.c
+++ b/fs/btrfs/qgroup.c
@@ -2186,30 +2186,21 @@ int btrfs_qgroup_trace_subtree(struct btrfs_trans_handle *trans,
 	level = root_level;
 	while (level >= 0) {
 		if (path->nodes[level] == NULL) {
-			struct btrfs_key first_key;
 			int parent_slot;
-			u64 child_gen;
 			u64 child_bytenr;
 
 			/*
-			 * We need to get child blockptr/gen from parent before
-			 * we can read it.
+			 * We need to get child blockptr from parent before we
+			 * can read it.
 			  */
 			eb = path->nodes[level + 1];
 			parent_slot = path->slots[level + 1];
 			child_bytenr = btrfs_node_blockptr(eb, parent_slot);
-			child_gen = btrfs_node_ptr_generation(eb, parent_slot);
-			btrfs_node_key_to_cpu(eb, &first_key, parent_slot);
 
-			eb = read_tree_block(fs_info, child_bytenr, child_gen,
-					     level, &first_key);
+			eb = btrfs_read_node_slot(eb, parent_slot);
 			if (IS_ERR(eb)) {
 				ret = PTR_ERR(eb);
 				goto out;
-			} else if (!extent_buffer_uptodate(eb)) {
-				free_extent_buffer(eb);
-				ret = -EIO;
-				goto out;
 			}
 
 			path->nodes[level] = eb;
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 11/14] btrfs: pass root owner to read_tree_block
  2020-10-30 21:02 [PATCH 00/14] Set the lockdep class on eb's at allocation time Josef Bacik
                   ` (9 preceding siblings ...)
  2020-10-30 21:03 ` [PATCH 10/14] btrfs: use btrfs_read_node_slot in btrfs_qgroup_trace_subtree Josef Bacik
@ 2020-10-30 21:03 ` Josef Bacik
  2020-10-30 21:03 ` [PATCH 12/14] btrfs: pass the root owner and level around for reada Josef Bacik
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 17+ messages in thread
From: Josef Bacik @ 2020-10-30 21:03 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

In order to properly set the lockdep class of a newly allocated block we
need to know the owner of the block.  For non refcount'ed tree's this is
straightforward, we always know in advance what tree we're reading from.
For refcount'ed trees we don't necessarily know, however all refcount'ed
trees share the same lockdep class name, tree-<level>.

Fix all of the callers of read_tree_block() to pass in the root objectid
we're using.  In places like relocation and backref we could probably
unconditionally use 0, but just in case use the root when we have it,
otherwise use 0 in the cases we don't have the root as it's going to be
a refcount'ed tree anyway.

This is a preparation patch for further changes.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/backref.c     |  6 +++---
 fs/btrfs/ctree.c       |  8 +++++---
 fs/btrfs/disk-io.c     | 14 +++++++++-----
 fs/btrfs/disk-io.h     |  4 ++--
 fs/btrfs/extent-tree.c |  4 ++--
 fs/btrfs/print-tree.c  |  1 +
 fs/btrfs/qgroup.c      |  2 +-
 fs/btrfs/relocation.c  |  4 ++--
 8 files changed, 25 insertions(+), 18 deletions(-)

diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index 771a036867dc..23d01d152377 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -783,8 +783,8 @@ static int add_missing_keys(struct btrfs_fs_info *fs_info,
 		BUG_ON(ref->key_for_search.type);
 		BUG_ON(!ref->wanted_disk_byte);
 
-		eb = read_tree_block(fs_info, ref->wanted_disk_byte, 0,
-				     ref->level - 1, NULL);
+		eb = read_tree_block(fs_info, ref->wanted_disk_byte,
+				     ref->root_id, 0, ref->level - 1, NULL);
 		if (IS_ERR(eb)) {
 			free_pref(ref);
 			return PTR_ERR(eb);
@@ -1331,7 +1331,7 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
 				struct extent_buffer *eb;
 
 				eb = read_tree_block(fs_info, ref->parent, 0,
-						     ref->level, NULL);
+						     0, ref->level, NULL);
 				if (IS_ERR(eb)) {
 					ret = PTR_ERR(eb);
 					goto out;
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 000f18923c5a..c675bd8e8266 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -1356,7 +1356,8 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
 	if (old_root && tm && tm->op != MOD_LOG_KEY_REMOVE_WHILE_FREEING) {
 		btrfs_tree_read_unlock(eb_root);
 		free_extent_buffer(eb_root);
-		old = read_tree_block(fs_info, logical, 0, level, NULL);
+		old = read_tree_block(fs_info, logical,
+				      root->root_key.objectid, 0, level, NULL);
 		if (WARN_ON(IS_ERR(old) || !extent_buffer_uptodate(old))) {
 			if (!IS_ERR(old))
 				free_extent_buffer(old);
@@ -1774,6 +1775,7 @@ struct extent_buffer *btrfs_read_node_slot(struct extent_buffer *parent,
 
 	btrfs_node_key_to_cpu(parent, &first_key, slot);
 	eb = read_tree_block(parent->fs_info, btrfs_node_blockptr(parent, slot),
+			     btrfs_header_owner(parent),
 			     btrfs_node_ptr_generation(parent, slot),
 			     level - 1, &first_key);
 	if (!IS_ERR(eb) && !extent_buffer_uptodate(eb)) {
@@ -2378,8 +2380,8 @@ read_block_for_search(struct btrfs_root *root, struct btrfs_path *p,
 		reada_for_search(fs_info, p, level, slot, key->objectid);
 
 	ret = -EAGAIN;
-	tmp = read_tree_block(fs_info, blocknr, gen, parent_level - 1,
-			      &first_key);
+	tmp = read_tree_block(fs_info, blocknr, root->root_key.objectid,
+			      gen, parent_level - 1, &first_key);
 	if (!IS_ERR(tmp)) {
 		/*
 		 * If the read above didn't mark this buffer up to date,
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 464dfb15b054..8a7f2b26e98a 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -959,13 +959,14 @@ struct extent_buffer *btrfs_find_create_tree_block(
  * Read tree block at logical address @bytenr and do variant basic but critical
  * verification.
  *
+ * @owner_root:		the objectid of the root owner for this block.
  * @parent_transid:	expected transid of this tree block, skip check if 0
  * @level:		expected level, mandatory check
  * @first_key:		expected key in slot 0, skip check if NULL
  */
 struct extent_buffer *read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr,
-				      u64 parent_transid, int level,
-				      struct btrfs_key *first_key)
+				      u64 owner_root, u64 parent_transid,
+				      int level, struct btrfs_key *first_key)
 {
 	struct extent_buffer *buf = NULL;
 	int ret;
@@ -1290,7 +1291,7 @@ static struct btrfs_root *read_tree_root_path(struct btrfs_root *tree_root,
 	level = btrfs_root_level(&root->root_item);
 	root->node = read_tree_block(fs_info,
 				     btrfs_root_bytenr(&root->root_item),
-				     generation, level, NULL);
+				     key->objectid, generation, level, NULL);
 	if (IS_ERR(root->node)) {
 		ret = PTR_ERR(root->node);
 		root->node = NULL;
@@ -2244,8 +2245,9 @@ static int btrfs_replay_log(struct btrfs_fs_info *fs_info,
 		return -ENOMEM;
 
 	log_tree_root->node = read_tree_block(fs_info, bytenr,
-					      fs_info->generation + 1,
-					      level, NULL);
+					      BTRFS_TREE_LOG_OBJECTID,
+					      fs_info->generation + 1, level,
+					      NULL);
 	if (IS_ERR(log_tree_root->node)) {
 		btrfs_warn(fs_info, "failed to read log tree");
 		ret = PTR_ERR(log_tree_root->node);
@@ -2631,6 +2633,7 @@ static int __cold init_tree_roots(struct btrfs_fs_info *fs_info)
 		generation = btrfs_super_generation(sb);
 		level = btrfs_super_root_level(sb);
 		tree_root->node = read_tree_block(fs_info, btrfs_super_root(sb),
+						  BTRFS_ROOT_TREE_OBJECTID,
 						  generation, level, NULL);
 		if (IS_ERR(tree_root->node)) {
 			handle_error = true;
@@ -3117,6 +3120,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
 
 	chunk_root->node = read_tree_block(fs_info,
 					   btrfs_super_chunk_root(disk_super),
+					   BTRFS_CHUNK_TREE_OBJECTID,
 					   generation, level, NULL);
 	if (IS_ERR(chunk_root->node) ||
 	    !extent_buffer_uptodate(chunk_root->node)) {
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
index 34934f38582b..f3bc5ff8a8cf 100644
--- a/fs/btrfs/disk-io.h
+++ b/fs/btrfs/disk-io.h
@@ -43,8 +43,8 @@ void btrfs_init_fs_info(struct btrfs_fs_info *fs_info);
 int btrfs_verify_level_key(struct extent_buffer *eb, int level,
 			   struct btrfs_key *first_key, u64 parent_transid);
 struct extent_buffer *read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr,
-				      u64 parent_transid, int level,
-				      struct btrfs_key *first_key);
+				      u64 owner_root, u64 parent_transid,
+				      int level, struct btrfs_key *first_key);
 struct extent_buffer *btrfs_find_create_tree_block(
 						struct btrfs_fs_info *fs_info,
 						u64 bytenr);
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 0ca1135dab8c..898b26f1a391 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -5124,8 +5124,8 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
 	if (!next) {
 		if (reada && level == 1)
 			reada_walk_down(trans, root, wc, path);
-		next = read_tree_block(fs_info, bytenr, generation, level - 1,
-				       &first_key);
+		next = read_tree_block(fs_info, bytenr, root->root_key.objectid,
+				       generation, level - 1, &first_key);
 		if (IS_ERR(next)) {
 			return PTR_ERR(next);
 		} else if (!extent_buffer_uptodate(next)) {
diff --git a/fs/btrfs/print-tree.c b/fs/btrfs/print-tree.c
index 48b57dd57436..5b8c03985226 100644
--- a/fs/btrfs/print-tree.c
+++ b/fs/btrfs/print-tree.c
@@ -391,6 +391,7 @@ void btrfs_print_tree(struct extent_buffer *c, bool follow)
 
 		btrfs_node_key_to_cpu(c, &first_key, i);
 		next = read_tree_block(fs_info, btrfs_node_blockptr(c, i),
+				       btrfs_header_owner(c),
 				       btrfs_node_ptr_generation(c, i),
 				       level - 1, &first_key);
 		if (IS_ERR(next)) {
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
index 0052b1c7d4c3..959ff4ed9df6 100644
--- a/fs/btrfs/qgroup.c
+++ b/fs/btrfs/qgroup.c
@@ -4145,7 +4145,7 @@ int btrfs_qgroup_trace_subtree_after_cow(struct btrfs_trans_handle *trans,
 	spin_unlock(&blocks->lock);
 
 	/* Read out reloc subtree root */
-	reloc_eb = read_tree_block(fs_info, block->reloc_bytenr,
+	reloc_eb = read_tree_block(fs_info, block->reloc_bytenr, 0,
 				   block->reloc_generation, block->level,
 				   &block->first_key);
 	if (IS_ERR(reloc_eb)) {
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 55a745cb28d4..48a95a115149 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -2417,7 +2417,7 @@ static int get_tree_block_key(struct btrfs_fs_info *fs_info,
 {
 	struct extent_buffer *eb;
 
-	eb = read_tree_block(fs_info, block->bytenr, block->key.offset,
+	eb = read_tree_block(fs_info, block->bytenr, 0, block->key.offset,
 			     block->level, NULL);
 	if (IS_ERR(eb)) {
 		return PTR_ERR(eb);
@@ -3043,7 +3043,7 @@ int add_data_references(struct reloc_control *rc,
 	while ((ref_node = ulist_next(leaves, &leaf_uiter))) {
 		struct extent_buffer *eb;
 
-		eb = read_tree_block(fs_info, ref_node->val, 0, 0, NULL);
+		eb = read_tree_block(fs_info, ref_node->val, 0, 0, 0, NULL);
 		if (IS_ERR(eb)) {
 			ret = PTR_ERR(eb);
 			break;
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 12/14] btrfs: pass the root owner and level around for reada
  2020-10-30 21:02 [PATCH 00/14] Set the lockdep class on eb's at allocation time Josef Bacik
                   ` (10 preceding siblings ...)
  2020-10-30 21:03 ` [PATCH 11/14] btrfs: pass root owner to read_tree_block Josef Bacik
@ 2020-10-30 21:03 ` Josef Bacik
  2020-10-30 21:03 ` [PATCH 13/14] btrfs: pass the owner_root and level to alloc_extent_buffer Josef Bacik
  2020-10-30 21:03 ` [PATCH 14/14] btrfs: set the lockdep class for ebs on creation Josef Bacik
  13 siblings, 0 replies; 17+ messages in thread
From: Josef Bacik @ 2020-10-30 21:03 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

The reada infrastructure does raw reads of extent buffers, but we're
going to need to know their owner and level in order to set the lockdep
key properly, so plumb in the infrastructure that we'll need to have
this information when we start allocating extent buffers.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/reada.c | 24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/fs/btrfs/reada.c b/fs/btrfs/reada.c
index 6e33cb755fa5..83f4e6c53e46 100644
--- a/fs/btrfs/reada.c
+++ b/fs/btrfs/reada.c
@@ -52,6 +52,7 @@ struct reada_extctl {
 
 struct reada_extent {
 	u64			logical;
+	u64			owner_root;
 	struct btrfs_key	top;
 	struct list_head	extctl;
 	int 			refcnt;
@@ -59,6 +60,7 @@ struct reada_extent {
 	struct reada_zone	*zones[BTRFS_MAX_MIRRORS];
 	int			nzones;
 	int			scheduled;
+	int			level;
 };
 
 struct reada_zone {
@@ -87,7 +89,8 @@ static void reada_start_machine(struct btrfs_fs_info *fs_info);
 static void __reada_start_machine(struct btrfs_fs_info *fs_info);
 
 static int reada_add_block(struct reada_control *rc, u64 logical,
-			   struct btrfs_key *top, u64 generation);
+			   struct btrfs_key *top, u64 owner_root,
+			   u64 generation, int level);
 
 /* recurses */
 /* in case of err, eb might be NULL */
@@ -165,7 +168,9 @@ static void __readahead_hook(struct btrfs_fs_info *fs_info,
 			if (rec->generation == generation &&
 			    btrfs_comp_cpu_keys(&key, &rc->key_end) < 0 &&
 			    btrfs_comp_cpu_keys(&next_key, &rc->key_start) > 0)
-				reada_add_block(rc, bytenr, &next_key, n_gen);
+				reada_add_block(rc, bytenr, &next_key,
+						btrfs_header_owner(eb), n_gen,
+						btrfs_header_level(eb) - 1);
 		}
 	}
 
@@ -298,7 +303,8 @@ static struct reada_zone *reada_find_zone(struct btrfs_device *dev, u64 logical,
 
 static struct reada_extent *reada_find_extent(struct btrfs_fs_info *fs_info,
 					      u64 logical,
-					      struct btrfs_key *top)
+					      struct btrfs_key *top,
+					      u64 owner_root, int level)
 {
 	int ret;
 	struct reada_extent *re = NULL;
@@ -331,6 +337,8 @@ static struct reada_extent *reada_find_extent(struct btrfs_fs_info *fs_info,
 	INIT_LIST_HEAD(&re->extctl);
 	spin_lock_init(&re->lock);
 	re->refcnt = 1;
+	re->owner_root = owner_root;
+	re->level = level;
 
 	/*
 	 * map block
@@ -548,14 +556,15 @@ static void reada_control_release(struct kref *kref)
 }
 
 static int reada_add_block(struct reada_control *rc, u64 logical,
-			   struct btrfs_key *top, u64 generation)
+			   struct btrfs_key *top, u64 owner_root,
+			   u64 generation, int level)
 {
 	struct btrfs_fs_info *fs_info = rc->fs_info;
 	struct reada_extent *re;
 	struct reada_extctl *rec;
 
 	/* takes one ref */
-	re = reada_find_extent(fs_info, logical, top);
+	re = reada_find_extent(fs_info, logical, top, owner_root, level);
 	if (!re)
 		return -1;
 
@@ -947,6 +956,7 @@ struct reada_control *btrfs_reada_add(struct btrfs_root *root,
 	u64 start;
 	u64 generation;
 	int ret;
+	int level;
 	struct extent_buffer *node;
 	static struct btrfs_key max_key = {
 		.objectid = (u64)-1,
@@ -969,9 +979,11 @@ struct reada_control *btrfs_reada_add(struct btrfs_root *root,
 	node = btrfs_root_node(root);
 	start = node->start;
 	generation = btrfs_header_generation(node);
+	level = btrfs_header_level(node);
 	free_extent_buffer(node);
 
-	ret = reada_add_block(rc, start, &max_key, generation);
+	ret = reada_add_block(rc, start, &max_key,
+			      root->root_key.objectid, generation, level);
 	if (ret) {
 		kfree(rc);
 		return ERR_PTR(ret);
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 13/14] btrfs: pass the owner_root and level to alloc_extent_buffer
  2020-10-30 21:02 [PATCH 00/14] Set the lockdep class on eb's at allocation time Josef Bacik
                   ` (11 preceding siblings ...)
  2020-10-30 21:03 ` [PATCH 12/14] btrfs: pass the root owner and level around for reada Josef Bacik
@ 2020-10-30 21:03 ` Josef Bacik
  2020-10-30 21:03 ` [PATCH 14/14] btrfs: set the lockdep class for ebs on creation Josef Bacik
  13 siblings, 0 replies; 17+ messages in thread
From: Josef Bacik @ 2020-10-30 21:03 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

Now that we've plumbed all of the callers to have the owner root and the
level, plumb it down into alloc_extent_buffer().

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/disk-io.c     |  7 ++++---
 fs/btrfs/disk-io.h     |  3 ++-
 fs/btrfs/extent-tree.c |  6 ++++--
 fs/btrfs/extent_io.c   | 13 +++++++++----
 fs/btrfs/extent_io.h   |  5 +++--
 fs/btrfs/reada.c       |  8 +++++---
 fs/btrfs/relocation.c  |  3 ++-
 fs/btrfs/tree-log.c    |  4 +++-
 fs/btrfs/volumes.c     |  3 ++-
 9 files changed, 34 insertions(+), 18 deletions(-)

diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 8a7f2b26e98a..989412501a92 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -948,11 +948,12 @@ static const struct address_space_operations btree_aops = {
 
 struct extent_buffer *btrfs_find_create_tree_block(
 						struct btrfs_fs_info *fs_info,
-						u64 bytenr)
+						u64 bytenr, u64 owner_root,
+						int level)
 {
 	if (btrfs_is_testing(fs_info))
 		return alloc_test_extent_buffer(fs_info, bytenr);
-	return alloc_extent_buffer(fs_info, bytenr);
+	return alloc_extent_buffer(fs_info, bytenr, owner_root, level);
 }
 
 /*
@@ -971,7 +972,7 @@ struct extent_buffer *read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr,
 	struct extent_buffer *buf = NULL;
 	int ret;
 
-	buf = btrfs_find_create_tree_block(fs_info, bytenr);
+	buf = btrfs_find_create_tree_block(fs_info, bytenr, owner_root, level);
 	if (IS_ERR(buf))
 		return buf;
 
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
index f3bc5ff8a8cf..740667700e6c 100644
--- a/fs/btrfs/disk-io.h
+++ b/fs/btrfs/disk-io.h
@@ -47,7 +47,8 @@ struct extent_buffer *read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr,
 				      int level, struct btrfs_key *first_key);
 struct extent_buffer *btrfs_find_create_tree_block(
 						struct btrfs_fs_info *fs_info,
-						u64 bytenr);
+						u64 bytenr, u64 owner_root,
+						int level);
 void btrfs_clean_tree_block(struct extent_buffer *buf);
 int __cold open_ctree(struct super_block *sb,
 	       struct btrfs_fs_devices *fs_devices,
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 898b26f1a391..a2c611a83057 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -4662,7 +4662,7 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 	struct btrfs_fs_info *fs_info = root->fs_info;
 	struct extent_buffer *buf;
 
-	buf = btrfs_find_create_tree_block(fs_info, bytenr);
+	buf = btrfs_find_create_tree_block(fs_info, bytenr, owner, level);
 	if (IS_ERR(buf))
 		return buf;
 
@@ -5064,7 +5064,9 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
 
 	next = find_extent_buffer(fs_info, bytenr);
 	if (!next) {
-		next = btrfs_find_create_tree_block(fs_info, bytenr);
+		next = btrfs_find_create_tree_block(fs_info, bytenr,
+						    root->root_key.objectid,
+						    level - 1);
 		if (IS_ERR(next))
 			return PTR_ERR(next);
 
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 654e2e517f3d..0af8333ccca1 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -5163,7 +5163,7 @@ struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info,
 #endif
 
 struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info,
-					  u64 start)
+					  u64 start, u64 owner_root, int level)
 {
 	unsigned long len = fs_info->nodesize;
 	int num_pages;
@@ -6111,19 +6111,22 @@ int try_release_extent_buffer(struct page *page)
  * btrfs_readahead_tree_block - attempt to readahead a child block.
  * @fs_info - the fs_info for the fs.
  * @bytenr - the bytenr to read.
+ * @owner_root - the objectid of the root that owns this eb.
  * @gen - the generation for the uptodate check, can be 0.
+ * @level - the level for the eb.
  *
  * Attempt to readahead a tree block at @bytenr.  If @gen is 0 then we do a
  * normal uptodate check of the eb, without checking the generation.  If we have
  * to read the block we will not block on anything.
  */
 void btrfs_readahead_tree_block(struct btrfs_fs_info *fs_info,
-				u64 bytenr, u64 gen)
+				u64 bytenr, u64 owner_root, u64 gen,
+				int level)
 {
 	struct extent_buffer *eb;
 	int ret;
 
-	eb = btrfs_find_create_tree_block(fs_info, bytenr);
+	eb = btrfs_find_create_tree_block(fs_info, bytenr, owner_root, level);
 	if (IS_ERR(eb))
 		return;
 
@@ -6151,5 +6154,7 @@ void btrfs_readahead_node_child(struct extent_buffer *node, int slot)
 {
 	btrfs_readahead_tree_block(node->fs_info,
 				   btrfs_node_blockptr(node, slot),
-				   btrfs_node_ptr_generation(node, slot));
+				   btrfs_header_owner(node),
+				   btrfs_node_ptr_generation(node, slot),
+				   btrfs_header_level(node) - 1);
 }
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
index 4f95b087a901..9e97d28f2d8f 100644
--- a/fs/btrfs/extent_io.h
+++ b/fs/btrfs/extent_io.h
@@ -182,7 +182,7 @@ int extent_fiemap(struct btrfs_inode *inode, struct fiemap_extent_info *fieinfo,
 void set_page_extent_mapped(struct page *page);
 
 struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info,
-					  u64 start);
+					  u64 start, u64 owner_root, int level);
 struct extent_buffer *__alloc_dummy_extent_buffer(struct btrfs_fs_info *fs_info,
 						  u64 start, unsigned long len);
 struct extent_buffer *alloc_dummy_extent_buffer(struct btrfs_fs_info *fs_info,
@@ -199,7 +199,8 @@ int read_extent_buffer_pages(struct extent_buffer *eb, int wait,
 			     int mirror_num);
 void wait_on_extent_buffer_writeback(struct extent_buffer *eb);
 void btrfs_readahead_tree_block(struct btrfs_fs_info *fs_info,
-				u64 bytenr, u64 gen);
+				u64 bytenr, u64 owner_root, u64 gen,
+				int level);
 void btrfs_readahead_node_child(struct extent_buffer *node, int slot);
 
 static inline int num_extent_pages(const struct extent_buffer *eb)
diff --git a/fs/btrfs/reada.c b/fs/btrfs/reada.c
index 83f4e6c53e46..8f26b3b22308 100644
--- a/fs/btrfs/reada.c
+++ b/fs/btrfs/reada.c
@@ -656,12 +656,13 @@ static int reada_pick_zone(struct btrfs_device *dev)
 }
 
 static int reada_tree_block_flagged(struct btrfs_fs_info *fs_info, u64 bytenr,
-				    int mirror_num, struct extent_buffer **eb)
+				    u64 owner_root, int level, int mirror_num,
+				    struct extent_buffer **eb)
 {
 	struct extent_buffer *buf = NULL;
 	int ret;
 
-	buf = btrfs_find_create_tree_block(fs_info, bytenr);
+	buf = btrfs_find_create_tree_block(fs_info, bytenr, owner_root, level);
 	if (IS_ERR(buf))
 		return 0;
 
@@ -749,7 +750,8 @@ static int reada_start_machine_dev(struct btrfs_device *dev)
 	logical = re->logical;
 
 	atomic_inc(&dev->reada_in_flight);
-	ret = reada_tree_block_flagged(fs_info, logical, mirror_num, &eb);
+	ret = reada_tree_block_flagged(fs_info, logical, re->owner_root,
+				       re->level, mirror_num, &eb);
 	if (ret)
 		__readahead_hook(fs_info, re, NULL, ret);
 	else if (eb)
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 48a95a115149..7954f2389d70 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -2518,7 +2518,8 @@ int relocate_tree_blocks(struct btrfs_trans_handle *trans,
 	rbtree_postorder_for_each_entry_safe(block, next, blocks, rb_node) {
 		if (!block->key_ready)
 			btrfs_readahead_tree_block(fs_info,
-						   block->bytenr, 0);
+						   block->bytenr, 0, 0,
+						   block->level);
 	}
 
 	/* Get first keys */
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 135cb40295c1..0db96c263c94 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -2699,7 +2699,9 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
 		btrfs_node_key_to_cpu(cur, &first_key, path->slots[*level]);
 		blocksize = fs_info->nodesize;
 
-		next = btrfs_find_create_tree_block(fs_info, bytenr);
+		next = btrfs_find_create_tree_block(fs_info, bytenr,
+						    btrfs_header_owner(cur),
+						    *level - 1);
 		if (IS_ERR(next))
 			return PTR_ERR(next);
 
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 75350c78ca02..9ef1a51379e9 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -6909,7 +6909,8 @@ int btrfs_read_sys_array(struct btrfs_fs_info *fs_info)
 	 * fixed to BTRFS_SUPER_INFO_SIZE. If nodesize > sb size, this will
 	 * overallocate but we can keep it as-is, only the first page is used.
 	 */
-	sb = btrfs_find_create_tree_block(fs_info, BTRFS_SUPER_INFO_OFFSET);
+	sb = btrfs_find_create_tree_block(fs_info, BTRFS_SUPER_INFO_OFFSET,
+					  root->root_key.objectid, 0);
 	if (IS_ERR(sb))
 		return PTR_ERR(sb);
 	set_extent_buffer_uptodate(sb);
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 14/14] btrfs: set the lockdep class for ebs on creation
  2020-10-30 21:02 [PATCH 00/14] Set the lockdep class on eb's at allocation time Josef Bacik
                   ` (12 preceding siblings ...)
  2020-10-30 21:03 ` [PATCH 13/14] btrfs: pass the owner_root and level to alloc_extent_buffer Josef Bacik
@ 2020-10-30 21:03 ` Josef Bacik
  13 siblings, 0 replies; 17+ messages in thread
From: Josef Bacik @ 2020-10-30 21:03 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

Both Filipe and Fedora QA recently hit the following lockdep splat

WARNING: possible recursive locking detected
5.10.0-0.rc1.20201028gited8780e3f2ec.57.fc34.x86_64 #1 Not tainted
--------------------------------------------
rsync/2610 is trying to acquire lock:
ffff89617ed48f20 (&eb->lock){++++}-{2:2}, at: btrfs_tree_read_lock_atomic+0x34/0x140

but task is already holding lock:
ffff8961757b1130 (&eb->lock){++++}-{2:2}, at: btrfs_tree_read_lock_atomic+0x34/0x140

other info that might help us debug this:
 Possible unsafe locking scenario:
       CPU0
       ----
  lock(&eb->lock);
  lock(&eb->lock);

 *** DEADLOCK ***
 May be due to missing lock nesting notation
2 locks held by rsync/2610:
 #0: ffff896107212b90 (&type->i_mutex_dir_key#10){++++}-{3:3}, at: walk_component+0x10c/0x190
 #1: ffff8961757b1130 (&eb->lock){++++}-{2:2}, at: btrfs_tree_read_lock_atomic+0x34/0x140

stack backtrace:
CPU: 1 PID: 2610 Comm: rsync Not tainted 5.10.0-0.rc1.20201028gited8780e3f2ec.57.fc34.x86_64 #1
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 0.0.0 02/06/2015
Call Trace:
 dump_stack+0x8b/0xb0
 __lock_acquire.cold+0x12d/0x2a4
 ? kvm_sched_clock_read+0x14/0x30
 ? sched_clock+0x5/0x10
 lock_acquire+0xc8/0x400
 ? btrfs_tree_read_lock_atomic+0x34/0x140
 ? read_block_for_search.isra.0+0xdd/0x320
 _raw_read_lock+0x3d/0xa0
 ? btrfs_tree_read_lock_atomic+0x34/0x140
 btrfs_tree_read_lock_atomic+0x34/0x140
 btrfs_search_slot+0x616/0x9a0
 btrfs_lookup_dir_item+0x6c/0xb0
 btrfs_lookup_dentry+0xa8/0x520
 ? lockdep_init_map_waits+0x4c/0x210
 btrfs_lookup+0xe/0x30
 __lookup_slow+0x10f/0x1e0
 walk_component+0x11b/0x190
 path_lookupat+0x72/0x1c0
 filename_lookup+0x97/0x180
 ? strncpy_from_user+0x96/0x1e0
 ? getname_flags.part.0+0x45/0x1a0
 vfs_statx+0x64/0x100
 ? lockdep_hardirqs_on_prepare+0xff/0x180
 ? _raw_spin_unlock_irqrestore+0x41/0x50
 __do_sys_newlstat+0x26/0x40
 ? lockdep_hardirqs_on_prepare+0xff/0x180
 ? syscall_enter_from_user_mode+0x27/0x80
 ? syscall_enter_from_user_mode+0x27/0x80
 do_syscall_64+0x33/0x40
 entry_SYSCALL_64_after_hwframe+0x44/0xa9

I have also seen a report of lockdep complaining about the lock class
that was looked up being the same as the lock class on the lock we were
using, but I can't find the report.

These are problems that occur because we do not have the lockdep class
set on the extent buffer until _after_ we read the eb in properly.  This
is problematic for concurrent readers, because we will create the extent
buffer, lock it, and then attempt to read the extent buffer.

If a second thread comes in and tries to do a search down the same path
they'll get the above lockdep splat because the class isn't set properly
on the extent buffer.

There was a good reason for this, we generally didn't know the real
owner of the eb until we read it, specifically in refcount'ed roots.

However now all refcount'ed roots have the same class name, so we no
longer need to worry about this.  For non-refcount'ed tree's we know
which root we're on based on the parent.

Fix this by setting the lockdep class on the eb at creation time instead
of read time.  This will fix the splat and the weirdness where the class
changes in the middle of locking the block.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/disk-io.c     | 3 ---
 fs/btrfs/extent-tree.c | 8 +++++---
 fs/btrfs/extent_io.c   | 1 +
 fs/btrfs/volumes.c     | 1 -
 4 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 989412501a92..d8ce8bbb3a45 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -578,9 +578,6 @@ int btrfs_validate_metadata_buffer(struct btrfs_io_bio *io_bio, u64 phy_offset,
 		goto err;
 	}
 
-	btrfs_set_buffer_lockdep_class(btrfs_header_owner(eb),
-				       eb, found_level);
-
 	csum_tree_block(eb, result);
 
 	if (memcmp_extent_buffer(eb, result, 0, csum_size)) {
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index a2c611a83057..1ddd8f4e9564 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -4679,6 +4679,11 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 		return ERR_PTR(-EUCLEAN);
 	}
 
+	/*
+	 * This needs to stay, because we could allocate a free'd block from an
+	 * old tree into a new tree, so we need to make sure this new block is
+	 * set to the appropriate level and owner.
+	 */
 	btrfs_set_buffer_lockdep_class(owner, buf, level);
 	__btrfs_tree_lock(buf, nest);
 	btrfs_clean_tree_block(buf);
@@ -5069,9 +5074,6 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
 						    level - 1);
 		if (IS_ERR(next))
 			return PTR_ERR(next);
-
-		btrfs_set_buffer_lockdep_class(root->root_key.objectid, next,
-					       level - 1);
 		reada = 1;
 	}
 	btrfs_tree_lock(next);
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 0af8333ccca1..4e758d670fc1 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -5188,6 +5188,7 @@ struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info,
 	eb = __alloc_extent_buffer(fs_info, start, len);
 	if (!eb)
 		return ERR_PTR(-ENOMEM);
+	btrfs_set_buffer_lockdep_class(owner_root, eb, level);
 
 	num_pages = num_extent_pages(eb);
 	for (i = 0; i < num_pages; i++, index++) {
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 9ef1a51379e9..ad244b44a3a1 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -6914,7 +6914,6 @@ int btrfs_read_sys_array(struct btrfs_fs_info *fs_info)
 	if (IS_ERR(sb))
 		return PTR_ERR(sb);
 	set_extent_buffer_uptodate(sb);
-	btrfs_set_buffer_lockdep_class(root->root_key.objectid, sb, 0);
 	/*
 	 * The sb extent buffer is artificial and just used to read the system array.
 	 * set_extent_buffer_uptodate() call does not properly mark all it's
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH 13/14] btrfs: pass the owner_root and level to alloc_extent_buffer
  2020-11-05 15:45 ` [PATCH 13/14] btrfs: pass the owner_root and level to alloc_extent_buffer Josef Bacik
@ 2020-11-06 11:54   ` Filipe Manana
  0 siblings, 0 replies; 17+ messages in thread
From: Filipe Manana @ 2020-11-06 11:54 UTC (permalink / raw)
  To: Josef Bacik; +Cc: linux-btrfs, kernel-team

On Thu, Nov 5, 2020 at 3:47 PM Josef Bacik <josef@toxicpanda.com> wrote:
>
> Now that we've plumbed all of the callers to have the owner root and the
> level, plumb it down into alloc_extent_buffer().
>
> Signed-off-by: Josef Bacik <josef@toxicpanda.com>

Reviewed-by: Filipe Manana <fdmanana@suse.com>

I couldn't get anymore the lockdep splat I reported before (after
applying the whole patchset of course), it used to happen very often
with btrfs/033.

Looks good, thanks.

> ---
>  fs/btrfs/disk-io.c     |  7 ++++---
>  fs/btrfs/disk-io.h     |  3 ++-
>  fs/btrfs/extent-tree.c |  6 ++++--
>  fs/btrfs/extent_io.c   | 13 +++++++++----
>  fs/btrfs/extent_io.h   |  5 +++--
>  fs/btrfs/reada.c       |  8 +++++---
>  fs/btrfs/relocation.c  |  3 ++-
>  fs/btrfs/tree-log.c    |  4 +++-
>  fs/btrfs/volumes.c     |  3 ++-
>  9 files changed, 34 insertions(+), 18 deletions(-)
>
> diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
> index 934723785ab8..f14398b5d933 100644
> --- a/fs/btrfs/disk-io.c
> +++ b/fs/btrfs/disk-io.c
> @@ -947,11 +947,12 @@ static const struct address_space_operations btree_aops = {
>
>  struct extent_buffer *btrfs_find_create_tree_block(
>                                                 struct btrfs_fs_info *fs_info,
> -                                               u64 bytenr)
> +                                               u64 bytenr, u64 owner_root,
> +                                               int level)
>  {
>         if (btrfs_is_testing(fs_info))
>                 return alloc_test_extent_buffer(fs_info, bytenr);
> -       return alloc_extent_buffer(fs_info, bytenr);
> +       return alloc_extent_buffer(fs_info, bytenr, owner_root, level);
>  }
>
>  /*
> @@ -970,7 +971,7 @@ struct extent_buffer *read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr,
>         struct extent_buffer *buf = NULL;
>         int ret;
>
> -       buf = btrfs_find_create_tree_block(fs_info, bytenr);
> +       buf = btrfs_find_create_tree_block(fs_info, bytenr, owner_root, level);
>         if (IS_ERR(buf))
>                 return buf;
>
> diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
> index 41588babf2ed..e75ea6092942 100644
> --- a/fs/btrfs/disk-io.h
> +++ b/fs/btrfs/disk-io.h
> @@ -47,7 +47,8 @@ struct extent_buffer *read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr,
>                                       int level, struct btrfs_key *first_key);
>  struct extent_buffer *btrfs_find_create_tree_block(
>                                                 struct btrfs_fs_info *fs_info,
> -                                               u64 bytenr);
> +                                               u64 bytenr, u64 owner_root,
> +                                               int level);
>  void btrfs_clean_tree_block(struct extent_buffer *buf);
>  int __cold open_ctree(struct super_block *sb,
>                struct btrfs_fs_devices *fs_devices,
> diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
> index fe829bb528b5..14b6e19f6151 100644
> --- a/fs/btrfs/extent-tree.c
> +++ b/fs/btrfs/extent-tree.c
> @@ -4612,7 +4612,7 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root,
>         struct btrfs_fs_info *fs_info = root->fs_info;
>         struct extent_buffer *buf;
>
> -       buf = btrfs_find_create_tree_block(fs_info, bytenr);
> +       buf = btrfs_find_create_tree_block(fs_info, bytenr, owner, level);
>         if (IS_ERR(buf))
>                 return buf;
>
> @@ -5013,7 +5013,9 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
>
>         next = find_extent_buffer(fs_info, bytenr);
>         if (!next) {
> -               next = btrfs_find_create_tree_block(fs_info, bytenr);
> +               next = btrfs_find_create_tree_block(fs_info, bytenr,
> +                                                   root->root_key.objectid,
> +                                                   level - 1);
>                 if (IS_ERR(next))
>                         return PTR_ERR(next);
>
> diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
> index c9d652b0770a..a883350d5e7f 100644
> --- a/fs/btrfs/extent_io.c
> +++ b/fs/btrfs/extent_io.c
> @@ -5171,7 +5171,7 @@ struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info,
>  #endif
>
>  struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info,
> -                                         u64 start)
> +                                         u64 start, u64 owner_root, int level)
>  {
>         unsigned long len = fs_info->nodesize;
>         int num_pages;
> @@ -6119,19 +6119,22 @@ int try_release_extent_buffer(struct page *page)
>   * btrfs_readahead_tree_block - attempt to readahead a child block.
>   * @fs_info - the fs_info for the fs.
>   * @bytenr - the bytenr to read.
> + * @owner_root - the objectid of the root that owns this eb.
>   * @gen - the generation for the uptodate check, can be 0.
> + * @level - the level for the eb.
>   *
>   * Attempt to readahead a tree block at @bytenr.  If @gen is 0 then we do a
>   * normal uptodate check of the eb, without checking the generation.  If we have
>   * to read the block we will not block on anything.
>   */
>  void btrfs_readahead_tree_block(struct btrfs_fs_info *fs_info,
> -                               u64 bytenr, u64 gen)
> +                               u64 bytenr, u64 owner_root, u64 gen,
> +                               int level)
>  {
>         struct extent_buffer *eb;
>         int ret;
>
> -       eb = btrfs_find_create_tree_block(fs_info, bytenr);
> +       eb = btrfs_find_create_tree_block(fs_info, bytenr, owner_root, level);
>         if (IS_ERR(eb))
>                 return;
>
> @@ -6159,5 +6162,7 @@ void btrfs_readahead_node_child(struct extent_buffer *node, int slot)
>  {
>         btrfs_readahead_tree_block(node->fs_info,
>                                    btrfs_node_blockptr(node, slot),
> -                                  btrfs_node_ptr_generation(node, slot));
> +                                  btrfs_header_owner(node),
> +                                  btrfs_node_ptr_generation(node, slot),
> +                                  btrfs_header_level(node) - 1);
>  }
> diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
> index a211e90292f8..578c2e56c5e4 100644
> --- a/fs/btrfs/extent_io.h
> +++ b/fs/btrfs/extent_io.h
> @@ -182,7 +182,7 @@ int extent_fiemap(struct btrfs_inode *inode, struct fiemap_extent_info *fieinfo,
>  void set_page_extent_mapped(struct page *page);
>
>  struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info,
> -                                         u64 start);
> +                                         u64 start, u64 owner_root, int level);
>  struct extent_buffer *__alloc_dummy_extent_buffer(struct btrfs_fs_info *fs_info,
>                                                   u64 start, unsigned long len);
>  struct extent_buffer *alloc_dummy_extent_buffer(struct btrfs_fs_info *fs_info,
> @@ -199,7 +199,8 @@ int read_extent_buffer_pages(struct extent_buffer *eb, int wait,
>                              int mirror_num);
>  void wait_on_extent_buffer_writeback(struct extent_buffer *eb);
>  void btrfs_readahead_tree_block(struct btrfs_fs_info *fs_info,
> -                               u64 bytenr, u64 gen);
> +                               u64 bytenr, u64 owner_root, u64 gen,
> +                               int level);
>  void btrfs_readahead_node_child(struct extent_buffer *node, int slot);
>
>  static inline int num_extent_pages(const struct extent_buffer *eb)
> diff --git a/fs/btrfs/reada.c b/fs/btrfs/reada.c
> index 83f4e6c53e46..8f26b3b22308 100644
> --- a/fs/btrfs/reada.c
> +++ b/fs/btrfs/reada.c
> @@ -656,12 +656,13 @@ static int reada_pick_zone(struct btrfs_device *dev)
>  }
>
>  static int reada_tree_block_flagged(struct btrfs_fs_info *fs_info, u64 bytenr,
> -                                   int mirror_num, struct extent_buffer **eb)
> +                                   u64 owner_root, int level, int mirror_num,
> +                                   struct extent_buffer **eb)
>  {
>         struct extent_buffer *buf = NULL;
>         int ret;
>
> -       buf = btrfs_find_create_tree_block(fs_info, bytenr);
> +       buf = btrfs_find_create_tree_block(fs_info, bytenr, owner_root, level);
>         if (IS_ERR(buf))
>                 return 0;
>
> @@ -749,7 +750,8 @@ static int reada_start_machine_dev(struct btrfs_device *dev)
>         logical = re->logical;
>
>         atomic_inc(&dev->reada_in_flight);
> -       ret = reada_tree_block_flagged(fs_info, logical, mirror_num, &eb);
> +       ret = reada_tree_block_flagged(fs_info, logical, re->owner_root,
> +                                      re->level, mirror_num, &eb);
>         if (ret)
>                 __readahead_hook(fs_info, re, NULL, ret);
>         else if (eb)
> diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
> index 3e792bf31ecd..4551650a270d 100644
> --- a/fs/btrfs/relocation.c
> +++ b/fs/btrfs/relocation.c
> @@ -2514,7 +2514,8 @@ int relocate_tree_blocks(struct btrfs_trans_handle *trans,
>         rbtree_postorder_for_each_entry_safe(block, next, blocks, rb_node) {
>                 if (!block->key_ready)
>                         btrfs_readahead_tree_block(fs_info,
> -                                                  block->bytenr, 0);
> +                                                  block->bytenr, 0, 0,
> +                                                  block->level);
>         }
>
>         /* Get first keys */
> diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
> index eb86c632535a..b1f97be57bb3 100644
> --- a/fs/btrfs/tree-log.c
> +++ b/fs/btrfs/tree-log.c
> @@ -2699,7 +2699,9 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
>                 btrfs_node_key_to_cpu(cur, &first_key, path->slots[*level]);
>                 blocksize = fs_info->nodesize;
>
> -               next = btrfs_find_create_tree_block(fs_info, bytenr);
> +               next = btrfs_find_create_tree_block(fs_info, bytenr,
> +                                                   btrfs_header_owner(cur),
> +                                                   *level - 1);
>                 if (IS_ERR(next))
>                         return PTR_ERR(next);
>
> diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
> index 8beb91d3cd88..0ca2e96a9cda 100644
> --- a/fs/btrfs/volumes.c
> +++ b/fs/btrfs/volumes.c
> @@ -6897,7 +6897,8 @@ int btrfs_read_sys_array(struct btrfs_fs_info *fs_info)
>          * fixed to BTRFS_SUPER_INFO_SIZE. If nodesize > sb size, this will
>          * overallocate but we can keep it as-is, only the first page is used.
>          */
> -       sb = btrfs_find_create_tree_block(fs_info, BTRFS_SUPER_INFO_OFFSET);
> +       sb = btrfs_find_create_tree_block(fs_info, BTRFS_SUPER_INFO_OFFSET,
> +                                         root->root_key.objectid, 0);
>         if (IS_ERR(sb))
>                 return PTR_ERR(sb);
>         set_extent_buffer_uptodate(sb);
> --
> 2.26.2
>


-- 
Filipe David Manana,

“Whether you think you can, or you think you can't — you're right.”

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 13/14] btrfs: pass the owner_root and level to alloc_extent_buffer
  2020-11-05 15:45 [PATCH 00/14][REBASED] Set the lockdep class on eb's at allocation time Josef Bacik
@ 2020-11-05 15:45 ` Josef Bacik
  2020-11-06 11:54   ` Filipe Manana
  0 siblings, 1 reply; 17+ messages in thread
From: Josef Bacik @ 2020-11-05 15:45 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

Now that we've plumbed all of the callers to have the owner root and the
level, plumb it down into alloc_extent_buffer().

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/disk-io.c     |  7 ++++---
 fs/btrfs/disk-io.h     |  3 ++-
 fs/btrfs/extent-tree.c |  6 ++++--
 fs/btrfs/extent_io.c   | 13 +++++++++----
 fs/btrfs/extent_io.h   |  5 +++--
 fs/btrfs/reada.c       |  8 +++++---
 fs/btrfs/relocation.c  |  3 ++-
 fs/btrfs/tree-log.c    |  4 +++-
 fs/btrfs/volumes.c     |  3 ++-
 9 files changed, 34 insertions(+), 18 deletions(-)

diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 934723785ab8..f14398b5d933 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -947,11 +947,12 @@ static const struct address_space_operations btree_aops = {
 
 struct extent_buffer *btrfs_find_create_tree_block(
 						struct btrfs_fs_info *fs_info,
-						u64 bytenr)
+						u64 bytenr, u64 owner_root,
+						int level)
 {
 	if (btrfs_is_testing(fs_info))
 		return alloc_test_extent_buffer(fs_info, bytenr);
-	return alloc_extent_buffer(fs_info, bytenr);
+	return alloc_extent_buffer(fs_info, bytenr, owner_root, level);
 }
 
 /*
@@ -970,7 +971,7 @@ struct extent_buffer *read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr,
 	struct extent_buffer *buf = NULL;
 	int ret;
 
-	buf = btrfs_find_create_tree_block(fs_info, bytenr);
+	buf = btrfs_find_create_tree_block(fs_info, bytenr, owner_root, level);
 	if (IS_ERR(buf))
 		return buf;
 
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
index 41588babf2ed..e75ea6092942 100644
--- a/fs/btrfs/disk-io.h
+++ b/fs/btrfs/disk-io.h
@@ -47,7 +47,8 @@ struct extent_buffer *read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr,
 				      int level, struct btrfs_key *first_key);
 struct extent_buffer *btrfs_find_create_tree_block(
 						struct btrfs_fs_info *fs_info,
-						u64 bytenr);
+						u64 bytenr, u64 owner_root,
+						int level);
 void btrfs_clean_tree_block(struct extent_buffer *buf);
 int __cold open_ctree(struct super_block *sb,
 	       struct btrfs_fs_devices *fs_devices,
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index fe829bb528b5..14b6e19f6151 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -4612,7 +4612,7 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 	struct btrfs_fs_info *fs_info = root->fs_info;
 	struct extent_buffer *buf;
 
-	buf = btrfs_find_create_tree_block(fs_info, bytenr);
+	buf = btrfs_find_create_tree_block(fs_info, bytenr, owner, level);
 	if (IS_ERR(buf))
 		return buf;
 
@@ -5013,7 +5013,9 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
 
 	next = find_extent_buffer(fs_info, bytenr);
 	if (!next) {
-		next = btrfs_find_create_tree_block(fs_info, bytenr);
+		next = btrfs_find_create_tree_block(fs_info, bytenr,
+						    root->root_key.objectid,
+						    level - 1);
 		if (IS_ERR(next))
 			return PTR_ERR(next);
 
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index c9d652b0770a..a883350d5e7f 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -5171,7 +5171,7 @@ struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info,
 #endif
 
 struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info,
-					  u64 start)
+					  u64 start, u64 owner_root, int level)
 {
 	unsigned long len = fs_info->nodesize;
 	int num_pages;
@@ -6119,19 +6119,22 @@ int try_release_extent_buffer(struct page *page)
  * btrfs_readahead_tree_block - attempt to readahead a child block.
  * @fs_info - the fs_info for the fs.
  * @bytenr - the bytenr to read.
+ * @owner_root - the objectid of the root that owns this eb.
  * @gen - the generation for the uptodate check, can be 0.
+ * @level - the level for the eb.
  *
  * Attempt to readahead a tree block at @bytenr.  If @gen is 0 then we do a
  * normal uptodate check of the eb, without checking the generation.  If we have
  * to read the block we will not block on anything.
  */
 void btrfs_readahead_tree_block(struct btrfs_fs_info *fs_info,
-				u64 bytenr, u64 gen)
+				u64 bytenr, u64 owner_root, u64 gen,
+				int level)
 {
 	struct extent_buffer *eb;
 	int ret;
 
-	eb = btrfs_find_create_tree_block(fs_info, bytenr);
+	eb = btrfs_find_create_tree_block(fs_info, bytenr, owner_root, level);
 	if (IS_ERR(eb))
 		return;
 
@@ -6159,5 +6162,7 @@ void btrfs_readahead_node_child(struct extent_buffer *node, int slot)
 {
 	btrfs_readahead_tree_block(node->fs_info,
 				   btrfs_node_blockptr(node, slot),
-				   btrfs_node_ptr_generation(node, slot));
+				   btrfs_header_owner(node),
+				   btrfs_node_ptr_generation(node, slot),
+				   btrfs_header_level(node) - 1);
 }
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
index a211e90292f8..578c2e56c5e4 100644
--- a/fs/btrfs/extent_io.h
+++ b/fs/btrfs/extent_io.h
@@ -182,7 +182,7 @@ int extent_fiemap(struct btrfs_inode *inode, struct fiemap_extent_info *fieinfo,
 void set_page_extent_mapped(struct page *page);
 
 struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info,
-					  u64 start);
+					  u64 start, u64 owner_root, int level);
 struct extent_buffer *__alloc_dummy_extent_buffer(struct btrfs_fs_info *fs_info,
 						  u64 start, unsigned long len);
 struct extent_buffer *alloc_dummy_extent_buffer(struct btrfs_fs_info *fs_info,
@@ -199,7 +199,8 @@ int read_extent_buffer_pages(struct extent_buffer *eb, int wait,
 			     int mirror_num);
 void wait_on_extent_buffer_writeback(struct extent_buffer *eb);
 void btrfs_readahead_tree_block(struct btrfs_fs_info *fs_info,
-				u64 bytenr, u64 gen);
+				u64 bytenr, u64 owner_root, u64 gen,
+				int level);
 void btrfs_readahead_node_child(struct extent_buffer *node, int slot);
 
 static inline int num_extent_pages(const struct extent_buffer *eb)
diff --git a/fs/btrfs/reada.c b/fs/btrfs/reada.c
index 83f4e6c53e46..8f26b3b22308 100644
--- a/fs/btrfs/reada.c
+++ b/fs/btrfs/reada.c
@@ -656,12 +656,13 @@ static int reada_pick_zone(struct btrfs_device *dev)
 }
 
 static int reada_tree_block_flagged(struct btrfs_fs_info *fs_info, u64 bytenr,
-				    int mirror_num, struct extent_buffer **eb)
+				    u64 owner_root, int level, int mirror_num,
+				    struct extent_buffer **eb)
 {
 	struct extent_buffer *buf = NULL;
 	int ret;
 
-	buf = btrfs_find_create_tree_block(fs_info, bytenr);
+	buf = btrfs_find_create_tree_block(fs_info, bytenr, owner_root, level);
 	if (IS_ERR(buf))
 		return 0;
 
@@ -749,7 +750,8 @@ static int reada_start_machine_dev(struct btrfs_device *dev)
 	logical = re->logical;
 
 	atomic_inc(&dev->reada_in_flight);
-	ret = reada_tree_block_flagged(fs_info, logical, mirror_num, &eb);
+	ret = reada_tree_block_flagged(fs_info, logical, re->owner_root,
+				       re->level, mirror_num, &eb);
 	if (ret)
 		__readahead_hook(fs_info, re, NULL, ret);
 	else if (eb)
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 3e792bf31ecd..4551650a270d 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -2514,7 +2514,8 @@ int relocate_tree_blocks(struct btrfs_trans_handle *trans,
 	rbtree_postorder_for_each_entry_safe(block, next, blocks, rb_node) {
 		if (!block->key_ready)
 			btrfs_readahead_tree_block(fs_info,
-						   block->bytenr, 0);
+						   block->bytenr, 0, 0,
+						   block->level);
 	}
 
 	/* Get first keys */
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index eb86c632535a..b1f97be57bb3 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -2699,7 +2699,9 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
 		btrfs_node_key_to_cpu(cur, &first_key, path->slots[*level]);
 		blocksize = fs_info->nodesize;
 
-		next = btrfs_find_create_tree_block(fs_info, bytenr);
+		next = btrfs_find_create_tree_block(fs_info, bytenr,
+						    btrfs_header_owner(cur),
+						    *level - 1);
 		if (IS_ERR(next))
 			return PTR_ERR(next);
 
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 8beb91d3cd88..0ca2e96a9cda 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -6897,7 +6897,8 @@ int btrfs_read_sys_array(struct btrfs_fs_info *fs_info)
 	 * fixed to BTRFS_SUPER_INFO_SIZE. If nodesize > sb size, this will
 	 * overallocate but we can keep it as-is, only the first page is used.
 	 */
-	sb = btrfs_find_create_tree_block(fs_info, BTRFS_SUPER_INFO_OFFSET);
+	sb = btrfs_find_create_tree_block(fs_info, BTRFS_SUPER_INFO_OFFSET,
+					  root->root_key.objectid, 0);
 	if (IS_ERR(sb))
 		return PTR_ERR(sb);
 	set_extent_buffer_uptodate(sb);
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2020-11-06 11:54 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-30 21:02 [PATCH 00/14] Set the lockdep class on eb's at allocation time Josef Bacik
2020-10-30 21:02 ` [PATCH 01/14] btrfs: remove lockdep classes for the fs tree Josef Bacik
2020-10-30 21:02 ` [PATCH 02/14] btrfs: cleanup extent buffer readahead Josef Bacik
2020-10-30 21:02 ` [PATCH 03/14] btrfs: use btrfs_read_node_slot in btrfs_realloc_node Josef Bacik
2020-10-30 21:02 ` [PATCH 04/14] btrfs: use btrfs_read_node_slot in walk_down_reloc_tree Josef Bacik
2020-10-30 21:02 ` [PATCH 05/14] btrfs: use btrfs_read_node_slot in do_relocation Josef Bacik
2020-10-30 21:02 ` [PATCH 06/14] btrfs: use btrfs_read_node_slot in replace_path Josef Bacik
2020-10-30 21:02 ` [PATCH 07/14] btrfs: use btrfs_read_node_slot in walk_down_tree Josef Bacik
2020-10-30 21:03 ` [PATCH 08/14] btrfs: use btrfs_read_node_slot in qgroup_trace_extent_swap Josef Bacik
2020-10-30 21:03 ` [PATCH 09/14] btrfs: use btrfs_read_node_slot in qgroup_trace_new_subtree_blocks Josef Bacik
2020-10-30 21:03 ` [PATCH 10/14] btrfs: use btrfs_read_node_slot in btrfs_qgroup_trace_subtree Josef Bacik
2020-10-30 21:03 ` [PATCH 11/14] btrfs: pass root owner to read_tree_block Josef Bacik
2020-10-30 21:03 ` [PATCH 12/14] btrfs: pass the root owner and level around for reada Josef Bacik
2020-10-30 21:03 ` [PATCH 13/14] btrfs: pass the owner_root and level to alloc_extent_buffer Josef Bacik
2020-10-30 21:03 ` [PATCH 14/14] btrfs: set the lockdep class for ebs on creation Josef Bacik
2020-11-05 15:45 [PATCH 00/14][REBASED] Set the lockdep class on eb's at allocation time Josef Bacik
2020-11-05 15:45 ` [PATCH 13/14] btrfs: pass the owner_root and level to alloc_extent_buffer Josef Bacik
2020-11-06 11:54   ` Filipe Manana

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).