All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/25] btrfs: extent tree v2 prep work for global roots
@ 2021-11-05 20:45 Josef Bacik
  2021-11-05 20:45 ` [PATCH 01/25] btrfs: kill BTRFS_FS_BARRIER Josef Bacik
                   ` (24 more replies)
  0 siblings, 25 replies; 34+ messages in thread
From: Josef Bacik @ 2021-11-05 20:45 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

Hello,

This is the kernel side of the prep work for the extent tree v2 global roots and
block group root.  There are a few cleanups around getting rid of trans->root to
make my life easier.  A few BUG_ON() fixes, again mostly just because I was in
the area and they were bugging me.  The main meat is similar to the work for
btrfs-progs, making all users of ->extent_root/->csum_root/->free_space_root to
use helpers, and then implementing a rb tree to track these roots and allow the
reading of multiples of them.  These can be taken without worrying about the
extent tree v2 stuff specifically, they all stand on their own.  These patches
have been through xfstests and fsperf with the rest of the patches to validate
they don't break anything.  Thanks,

Josef

Josef Bacik (25):
  btrfs: kill BTRFS_FS_BARRIER
  btrfs: rework async transaction committing
  btrfs: pass fs_info to trace_btrfs_transaction_commit
  btrfs: remove trans_handle->root
  btrfs: pass the root to add_keyed_refs
  btrfs: move comment in find_parent_nodes()
  btrfs: remove SANITY_TESTS check form find_parent_nodes
  btrfs: remove BUG_ON() in find_parent_nodes()
  btrfs: remove BUG_ON(!eie) in find_parent_nodes
  btrfs: add a btrfs_block_group_root() helper
  btrfs: make remove_extent_backref pass the root
  btrfs: use chunk_root in find_free_extent_update_loop
  btrfs: do not special case the extent root for switch commit roots
  btrfs: remove unnecessary extent root check in btrfs_defrag_leaves
  btrfs: don't use the extent root in btrfs_chunk_alloc_add_chunk_item
  btrfs: don't use extent_root in iterate_extent_inodes
  btrfs: don't use the extent_root in flush_space
  btrfs: init root block_rsv at init root time
  btrfs: stop accessing ->extent_root directly
  btrfs: fix csum assert to check objectid of the root
  btrfs: set BTRFS_FS_STATE_NO_CSUMS if we fail to load the csum root
  btrfs: stop accessing ->csum_root directly
  btrfs: stop accessing ->free_space_root directly
  btrfs: remove useless WARN_ON in record_root_in_trans
  btrfs: track the csum, extent, and free space trees in a rb tree

 fs/btrfs/backref.c                     |  61 +++--
 fs/btrfs/block-group.c                 |  22 +-
 fs/btrfs/block-rsv.c                   |  51 +++--
 fs/btrfs/block-rsv.h                   |   1 +
 fs/btrfs/compression.c                 |   3 +-
 fs/btrfs/ctree.h                       |  15 +-
 fs/btrfs/disk-io.c                     | 306 +++++++++++++++++++------
 fs/btrfs/disk-io.h                     |  13 ++
 fs/btrfs/extent-tree.c                 |  72 +++---
 fs/btrfs/file-item.c                   |   9 +-
 fs/btrfs/free-space-tree.c             |  49 ++--
 fs/btrfs/inode.c                       |  15 +-
 fs/btrfs/ioctl.c                       |   7 +-
 fs/btrfs/qgroup.c                      |   5 +-
 fs/btrfs/ref-verify.c                  |   6 +-
 fs/btrfs/relocation.c                  |   8 +-
 fs/btrfs/scrub.c                       |  13 +-
 fs/btrfs/space-info.c                  |   2 +-
 fs/btrfs/tests/btrfs-tests.c           |   1 +
 fs/btrfs/tests/free-space-tests.c      |   5 +-
 fs/btrfs/tests/free-space-tree-tests.c |   5 +-
 fs/btrfs/tests/qgroup-tests.c          |   5 +-
 fs/btrfs/transaction.c                 |  78 ++-----
 fs/btrfs/transaction.h                 |   3 +-
 fs/btrfs/tree-defrag.c                 |   8 -
 fs/btrfs/tree-log.c                    |  19 +-
 fs/btrfs/volumes.c                     |   3 +-
 fs/btrfs/zoned.c                       |   3 +-
 include/trace/events/btrfs.h           |  10 +-
 29 files changed, 513 insertions(+), 285 deletions(-)

-- 
2.26.3


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

* [PATCH 01/25] btrfs: kill BTRFS_FS_BARRIER
  2021-11-05 20:45 [PATCH 00/25] btrfs: extent tree v2 prep work for global roots Josef Bacik
@ 2021-11-05 20:45 ` Josef Bacik
  2021-11-18 11:50   ` David Sterba
  2021-11-05 20:45 ` [PATCH 02/25] btrfs: rework async transaction committing Josef Bacik
                   ` (23 subsequent siblings)
  24 siblings, 1 reply; 34+ messages in thread
From: Josef Bacik @ 2021-11-05 20:45 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

This is no longer used, it's a relic from when we had -o nobarrier.
Remove the flag.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/ctree.h   | 1 -
 fs/btrfs/disk-io.c | 1 -
 2 files changed, 2 deletions(-)

diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 01f6a40ba2dd..ce48ff69c77f 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -548,7 +548,6 @@ struct btrfs_swapfile_pin {
 bool btrfs_pinned_by_swapfile(struct btrfs_fs_info *fs_info, void *ptr);
 
 enum {
-	BTRFS_FS_BARRIER,
 	BTRFS_FS_CLOSING_START,
 	BTRFS_FS_CLOSING_DONE,
 	BTRFS_FS_LOG_RECOVERING,
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 5be0ae67ceb7..8d36950800f4 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -2949,7 +2949,6 @@ void btrfs_init_fs_info(struct btrfs_fs_info *fs_info)
 
 	extent_io_tree_init(fs_info, &fs_info->excluded_extents,
 			    IO_TREE_FS_EXCLUDED_EXTENTS, NULL);
-	set_bit(BTRFS_FS_BARRIER, &fs_info->flags);
 
 	mutex_init(&fs_info->ordered_operations_mutex);
 	mutex_init(&fs_info->tree_log_mutex);
-- 
2.26.3


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

* [PATCH 02/25] btrfs: rework async transaction committing
  2021-11-05 20:45 [PATCH 00/25] btrfs: extent tree v2 prep work for global roots Josef Bacik
  2021-11-05 20:45 ` [PATCH 01/25] btrfs: kill BTRFS_FS_BARRIER Josef Bacik
@ 2021-11-05 20:45 ` Josef Bacik
  2021-11-18 12:12   ` David Sterba
  2021-11-05 20:45 ` [PATCH 03/25] btrfs: pass fs_info to trace_btrfs_transaction_commit Josef Bacik
                   ` (22 subsequent siblings)
  24 siblings, 1 reply; 34+ messages in thread
From: Josef Bacik @ 2021-11-05 20:45 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

Currently we do this awful thing where we get another ref on a trans
handle, async off that handle and commit the transaction from that work.
Because we do this we have to mess with current->journal_info and the
freeze counting stuff.

We already have an async thing to kick for the transaction commit, the
transaction kthread.  Replace this work struct with a flag on the
fs_info to tell the kthread to go ahead and commit even if it's before
our timeout.  Then we can drastically simplify the async transaction
commit path.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/ctree.h       |  3 ++
 fs/btrfs/disk-io.c     |  3 +-
 fs/btrfs/ioctl.c       |  7 +----
 fs/btrfs/transaction.c | 64 ++++++++----------------------------------
 fs/btrfs/transaction.h |  2 +-
 5 files changed, 18 insertions(+), 61 deletions(-)

diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index ce48ff69c77f..fb49162311b9 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -595,6 +595,9 @@ enum {
 	/* Indicate whether there are any tree modification log users */
 	BTRFS_FS_TREE_MOD_LOG_USERS,
 
+	/* Indicate that we want the transaction kthread to commit right now. */
+	BTRFS_FS_COMMIT_TRANS,
+
 #if BITS_PER_LONG == 32
 	/* Indicate if we have error/warn message printed on 32bit systems */
 	BTRFS_FS_32BIT_ERROR,
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 8d36950800f4..4c4357724ed0 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1926,7 +1926,8 @@ static int transaction_kthread(void *arg)
 		}
 
 		delta = ktime_get_seconds() - cur->start_time;
-		if (cur->state < TRANS_STATE_COMMIT_START &&
+		if (!test_and_clear_bit(BTRFS_FS_COMMIT_TRANS, &fs_info->flags) &&
+		    cur->state < TRANS_STATE_COMMIT_START &&
 		    delta < fs_info->commit_interval) {
 			spin_unlock(&fs_info->trans_lock);
 			delay -= msecs_to_jiffies((delta - 1) * 1000);
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index c474f7e24163..44372f1e61ac 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -3622,7 +3622,6 @@ static noinline long btrfs_ioctl_start_sync(struct btrfs_root *root,
 {
 	struct btrfs_trans_handle *trans;
 	u64 transid;
-	int ret;
 
 	trans = btrfs_attach_transaction_barrier(root);
 	if (IS_ERR(trans)) {
@@ -3634,11 +3633,7 @@ static noinline long btrfs_ioctl_start_sync(struct btrfs_root *root,
 		goto out;
 	}
 	transid = trans->transid;
-	ret = btrfs_commit_transaction_async(trans);
-	if (ret) {
-		btrfs_end_transaction(trans);
-		return ret;
-	}
+	btrfs_commit_transaction_async(trans);
 out:
 	if (argp)
 		if (copy_to_user(argp, &transid, sizeof(transid)))
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index b958e0fdfe10..befe04019271 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -1861,50 +1861,14 @@ int btrfs_transaction_blocked(struct btrfs_fs_info *info)
 	return ret;
 }
 
-/*
- * commit transactions asynchronously. once btrfs_commit_transaction_async
- * returns, any subsequent transaction will not be allowed to join.
- */
-struct btrfs_async_commit {
-	struct btrfs_trans_handle *newtrans;
-	struct work_struct work;
-};
-
-static void do_async_commit(struct work_struct *work)
-{
-	struct btrfs_async_commit *ac =
-		container_of(work, struct btrfs_async_commit, work);
-
-	/*
-	 * We've got freeze protection passed with the transaction.
-	 * Tell lockdep about it.
-	 */
-	if (ac->newtrans->type & __TRANS_FREEZABLE)
-		__sb_writers_acquired(ac->newtrans->fs_info->sb, SB_FREEZE_FS);
-
-	current->journal_info = ac->newtrans;
-
-	btrfs_commit_transaction(ac->newtrans);
-	kfree(ac);
-}
-
-int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans)
+void btrfs_commit_transaction_async(struct btrfs_trans_handle *trans)
 {
 	struct btrfs_fs_info *fs_info = trans->fs_info;
-	struct btrfs_async_commit *ac;
 	struct btrfs_transaction *cur_trans;
 
-	ac = kmalloc(sizeof(*ac), GFP_NOFS);
-	if (!ac)
-		return -ENOMEM;
-
-	INIT_WORK(&ac->work, do_async_commit);
-	ac->newtrans = btrfs_join_transaction(trans->root);
-	if (IS_ERR(ac->newtrans)) {
-		int err = PTR_ERR(ac->newtrans);
-		kfree(ac);
-		return err;
-	}
+	/* Kick the transaction kthread. */
+	set_bit(BTRFS_FS_COMMIT_TRANS, &fs_info->flags);
+	wake_up_process(fs_info->transaction_kthread);
 
 	/* take transaction reference */
 	cur_trans = trans->transaction;
@@ -1912,14 +1876,6 @@ int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans)
 
 	btrfs_end_transaction(trans);
 
-	/*
-	 * Tell lockdep we've released the freeze rwsem, since the
-	 * async commit thread will be the one to unlock it.
-	 */
-	if (ac->newtrans->type & __TRANS_FREEZABLE)
-		__sb_writers_release(fs_info->sb, SB_FREEZE_FS);
-
-	schedule_work(&ac->work);
 	/*
 	 * Wait for the current transaction commit to start and block
 	 * subsequent transaction joins
@@ -1927,14 +1883,9 @@ int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans)
 	wait_event(fs_info->transaction_blocked_wait,
 		   cur_trans->state >= TRANS_STATE_COMMIT_START ||
 		   TRANS_ABORTED(cur_trans));
-	if (current->journal_info == trans)
-		current->journal_info = NULL;
-
 	btrfs_put_transaction(cur_trans);
-	return 0;
 }
 
-
 static void cleanup_transaction(struct btrfs_trans_handle *trans, int err)
 {
 	struct btrfs_fs_info *fs_info = trans->fs_info;
@@ -2200,6 +2151,13 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
 	wait_event(cur_trans->writer_wait,
 		   atomic_read(&cur_trans->num_writers) == 1);
 
+	/*
+	 * We've started the commit, clear the flag in case we were triggered to
+	 * do an async commit but somebody else started before the transaction
+	 * kthread could do the work.
+	 */
+	clear_bit(BTRFS_FS_COMMIT_TRANS, &fs_info->flags);
+
 	if (TRANS_ABORTED(cur_trans)) {
 		ret = cur_trans->aborted;
 		goto scrub_continue;
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
index ba45065f9451..e4b9b251a29e 100644
--- a/fs/btrfs/transaction.h
+++ b/fs/btrfs/transaction.h
@@ -217,7 +217,7 @@ void btrfs_add_dead_root(struct btrfs_root *root);
 int btrfs_defrag_root(struct btrfs_root *root);
 int btrfs_clean_one_deleted_snapshot(struct btrfs_root *root);
 int btrfs_commit_transaction(struct btrfs_trans_handle *trans);
-int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans);
+void btrfs_commit_transaction_async(struct btrfs_trans_handle *trans);
 int btrfs_end_transaction_throttle(struct btrfs_trans_handle *trans);
 bool btrfs_should_end_transaction(struct btrfs_trans_handle *trans);
 void btrfs_throttle(struct btrfs_fs_info *fs_info);
-- 
2.26.3


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

* [PATCH 03/25] btrfs: pass fs_info to trace_btrfs_transaction_commit
  2021-11-05 20:45 [PATCH 00/25] btrfs: extent tree v2 prep work for global roots Josef Bacik
  2021-11-05 20:45 ` [PATCH 01/25] btrfs: kill BTRFS_FS_BARRIER Josef Bacik
  2021-11-05 20:45 ` [PATCH 02/25] btrfs: rework async transaction committing Josef Bacik
@ 2021-11-05 20:45 ` Josef Bacik
  2021-11-05 20:45 ` [PATCH 04/25] btrfs: remove trans_handle->root Josef Bacik
                   ` (21 subsequent siblings)
  24 siblings, 0 replies; 34+ messages in thread
From: Josef Bacik @ 2021-11-05 20:45 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

The root on the trans->root can be anything, and generally we're
committing from the transaction kthread so it's usually the tree_root.
Change this to just take an fs_info, and to maintain compatibility
simply put the ROOT_TREE_OBJECTID as the root objectid for the
tracepoint.  This will allow use to remove trans->root.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/disk-io.c           |  2 +-
 fs/btrfs/transaction.c       |  4 ++--
 include/trace/events/btrfs.h | 10 +++++-----
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 4c4357724ed0..3bd3a06a9627 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -4968,7 +4968,7 @@ static int btrfs_cleanup_transaction(struct btrfs_fs_info *fs_info)
 		spin_unlock(&fs_info->trans_lock);
 
 		btrfs_put_transaction(t);
-		trace_btrfs_transaction_commit(fs_info->tree_root);
+		trace_btrfs_transaction_commit(fs_info);
 		spin_lock(&fs_info->trans_lock);
 	}
 	spin_unlock(&fs_info->trans_lock);
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index befe04019271..4738ad1d826e 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -1937,7 +1937,7 @@ static void cleanup_transaction(struct btrfs_trans_handle *trans, int err)
 	btrfs_put_transaction(cur_trans);
 	btrfs_put_transaction(cur_trans);
 
-	trace_btrfs_transaction_commit(trans->root);
+	trace_btrfs_transaction_commit(fs_info);
 
 	if (current->journal_info == trans)
 		current->journal_info = NULL;
@@ -2351,7 +2351,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
 	if (trans->type & __TRANS_FREEZABLE)
 		sb_end_intwrite(fs_info->sb);
 
-	trace_btrfs_transaction_commit(trans->root);
+	trace_btrfs_transaction_commit(fs_info);
 
 	btrfs_scrub_continue(fs_info);
 
diff --git a/include/trace/events/btrfs.h b/include/trace/events/btrfs.h
index 8f58fd95efc7..0d729664b4b4 100644
--- a/include/trace/events/btrfs.h
+++ b/include/trace/events/btrfs.h
@@ -182,18 +182,18 @@ FLUSH_STATES
 
 TRACE_EVENT(btrfs_transaction_commit,
 
-	TP_PROTO(const struct btrfs_root *root),
+	TP_PROTO(const struct btrfs_fs_info *fs_info),
 
-	TP_ARGS(root),
+	TP_ARGS(fs_info),
 
 	TP_STRUCT__entry_btrfs(
 		__field(	u64,  generation		)
 		__field(	u64,  root_objectid		)
 	),
 
-	TP_fast_assign_btrfs(root->fs_info,
-		__entry->generation	= root->fs_info->generation;
-		__entry->root_objectid	= root->root_key.objectid;
+	TP_fast_assign_btrfs(fs_info,
+		__entry->generation	= fs_info->generation;
+		__entry->root_objectid	= BTRFS_ROOT_TREE_OBJECTID;
 	),
 
 	TP_printk_btrfs("root=%llu(%s) gen=%llu",
-- 
2.26.3


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

* [PATCH 04/25] btrfs: remove trans_handle->root
  2021-11-05 20:45 [PATCH 00/25] btrfs: extent tree v2 prep work for global roots Josef Bacik
                   ` (2 preceding siblings ...)
  2021-11-05 20:45 ` [PATCH 03/25] btrfs: pass fs_info to trace_btrfs_transaction_commit Josef Bacik
@ 2021-11-05 20:45 ` Josef Bacik
  2021-11-05 20:45 ` [PATCH 05/25] btrfs: pass the root to add_keyed_refs Josef Bacik
                   ` (20 subsequent siblings)
  24 siblings, 0 replies; 34+ messages in thread
From: Josef Bacik @ 2021-11-05 20:45 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

Nobody is using this anymore, remove it.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/transaction.c | 1 -
 fs/btrfs/transaction.h | 1 -
 2 files changed, 2 deletions(-)

diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 4738ad1d826e..451788400e17 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -692,7 +692,6 @@ start_transaction(struct btrfs_root *root, unsigned int num_items,
 
 	h->transid = cur_trans->transid;
 	h->transaction = cur_trans;
-	h->root = root;
 	refcount_set(&h->use_count, 1);
 	h->fs_info = root->fs_info;
 
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
index e4b9b251a29e..1852ed9de7fd 100644
--- a/fs/btrfs/transaction.h
+++ b/fs/btrfs/transaction.h
@@ -135,7 +135,6 @@ struct btrfs_trans_handle {
 	bool removing_chunk;
 	bool reloc_reserved;
 	bool in_fsync;
-	struct btrfs_root *root;
 	struct btrfs_fs_info *fs_info;
 	struct list_head new_bgs;
 };
-- 
2.26.3


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

* [PATCH 05/25] btrfs: pass the root to add_keyed_refs
  2021-11-05 20:45 [PATCH 00/25] btrfs: extent tree v2 prep work for global roots Josef Bacik
                   ` (3 preceding siblings ...)
  2021-11-05 20:45 ` [PATCH 04/25] btrfs: remove trans_handle->root Josef Bacik
@ 2021-11-05 20:45 ` Josef Bacik
  2021-11-05 20:45 ` [PATCH 06/25] btrfs: move comment in find_parent_nodes() Josef Bacik
                   ` (19 subsequent siblings)
  24 siblings, 0 replies; 34+ messages in thread
From: Josef Bacik @ 2021-11-05 20:45 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

We pass in the path, but use btrfs_next_item() using the root we
searched with.  Pass the root down to add_keyed_refs() instead of the
fs_info so we can continue to use the same root we searched with.

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

diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index f735b8798ba1..53140f6ba78a 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -1049,12 +1049,12 @@ static int add_inline_refs(const struct btrfs_fs_info *fs_info,
  *
  * Returns 0 on success, <0 on error, or BACKREF_FOUND_SHARED.
  */
-static int add_keyed_refs(struct btrfs_fs_info *fs_info,
+static int add_keyed_refs(struct btrfs_root *extent_root,
 			  struct btrfs_path *path, u64 bytenr,
 			  int info_level, struct preftrees *preftrees,
 			  struct share_check *sc)
 {
-	struct btrfs_root *extent_root = fs_info->extent_root;
+	struct btrfs_fs_info *fs_info = extent_root->fs_info;
 	int ret;
 	int slot;
 	struct extent_buffer *leaf;
@@ -1170,6 +1170,7 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
 			     struct ulist *roots, const u64 *extent_item_pos,
 			     struct share_check *sc, bool ignore_offset)
 {
+	struct btrfs_root *root = fs_info->extent_root;
 	struct btrfs_key key;
 	struct btrfs_path *path;
 	struct btrfs_delayed_ref_root *delayed_refs = NULL;
@@ -1211,7 +1212,7 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
 again:
 	head = NULL;
 
-	ret = btrfs_search_slot(NULL, fs_info->extent_root, &key, path, 0, 0);
+	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
 	if (ret < 0)
 		goto out;
 	BUG_ON(ret == 0);
@@ -1271,7 +1272,7 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
 					      &info_level, &preftrees, sc);
 			if (ret)
 				goto out;
-			ret = add_keyed_refs(fs_info, path, bytenr, info_level,
+			ret = add_keyed_refs(root, path, bytenr, info_level,
 					     &preftrees, sc);
 			if (ret)
 				goto out;
-- 
2.26.3


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

* [PATCH 06/25] btrfs: move comment in find_parent_nodes()
  2021-11-05 20:45 [PATCH 00/25] btrfs: extent tree v2 prep work for global roots Josef Bacik
                   ` (4 preceding siblings ...)
  2021-11-05 20:45 ` [PATCH 05/25] btrfs: pass the root to add_keyed_refs Josef Bacik
@ 2021-11-05 20:45 ` Josef Bacik
  2021-11-05 20:45 ` [PATCH 07/25] btrfs: remove SANITY_TESTS check form find_parent_nodes Josef Bacik
                   ` (18 subsequent siblings)
  24 siblings, 0 replies; 34+ messages in thread
From: Josef Bacik @ 2021-11-05 20:45 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

This comment was much closer to the related code when it was originally
added, but has slowly migrated north far from its ancestral lands.  Move
it back down with its people.

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

diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index 53140f6ba78a..17766b7635f9 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -1204,11 +1204,6 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
 	if (time_seq == BTRFS_SEQ_LAST)
 		path->skip_locking = 1;
 
-	/*
-	 * grab both a lock on the path and a lock on the delayed ref head.
-	 * We need both to get a consistent picture of how the refs look
-	 * at a specified point in time
-	 */
 again:
 	head = NULL;
 
@@ -1224,8 +1219,10 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
 	if (trans && time_seq != BTRFS_SEQ_LAST) {
 #endif
 		/*
-		 * look if there are updates for this ref queued and lock the
-		 * head
+		 * We have a specific time_seq we care about and trans which
+		 * means we have the path lock, we need to grab the ref head and
+		 * lock it so we have a consistent view of the refs at the given
+		 * time.
 		 */
 		delayed_refs = &trans->transaction->delayed_refs;
 		spin_lock(&delayed_refs->lock);
-- 
2.26.3


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

* [PATCH 07/25] btrfs: remove SANITY_TESTS check form find_parent_nodes
  2021-11-05 20:45 [PATCH 00/25] btrfs: extent tree v2 prep work for global roots Josef Bacik
                   ` (5 preceding siblings ...)
  2021-11-05 20:45 ` [PATCH 06/25] btrfs: move comment in find_parent_nodes() Josef Bacik
@ 2021-11-05 20:45 ` Josef Bacik
  2021-11-05 20:45 ` [PATCH 08/25] btrfs: remove BUG_ON() in find_parent_nodes() Josef Bacik
                   ` (17 subsequent siblings)
  24 siblings, 0 replies; 34+ messages in thread
From: Josef Bacik @ 2021-11-05 20:45 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

We define __TRANS_DUMMY always, so this extra ifdef stuff is not needed.

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

diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index 17766b7635f9..12276ff08dd4 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -1212,12 +1212,8 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
 		goto out;
 	BUG_ON(ret == 0);
 
-#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
 	if (trans && likely(trans->type != __TRANS_DUMMY) &&
 	    time_seq != BTRFS_SEQ_LAST) {
-#else
-	if (trans && time_seq != BTRFS_SEQ_LAST) {
-#endif
 		/*
 		 * We have a specific time_seq we care about and trans which
 		 * means we have the path lock, we need to grab the ref head and
-- 
2.26.3


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

* [PATCH 08/25] btrfs: remove BUG_ON() in find_parent_nodes()
  2021-11-05 20:45 [PATCH 00/25] btrfs: extent tree v2 prep work for global roots Josef Bacik
                   ` (6 preceding siblings ...)
  2021-11-05 20:45 ` [PATCH 07/25] btrfs: remove SANITY_TESTS check form find_parent_nodes Josef Bacik
@ 2021-11-05 20:45 ` Josef Bacik
  2021-11-23 20:53   ` Nikolay Borisov
  2021-11-05 20:45 ` [PATCH 09/25] btrfs: remove BUG_ON(!eie) in find_parent_nodes Josef Bacik
                   ` (16 subsequent siblings)
  24 siblings, 1 reply; 34+ messages in thread
From: Josef Bacik @ 2021-11-05 20:45 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

We search for an extent entry with .offset = -1, which shouldn't be a
thing, but corruption happens.  Add an ASSERT() for the developers,
return -EUCLEAN for mortals.

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

diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index 12276ff08dd4..7d942f5d6443 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -1210,7 +1210,12 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
 	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
 	if (ret < 0)
 		goto out;
-	BUG_ON(ret == 0);
+	if (ret == 0) {
+		/* This shouldn't happen, indicates a bug or fs corruption. */
+		ASSERT(ret != 0);
+		ret = -EUCLEAN;
+		goto out;
+	}
 
 	if (trans && likely(trans->type != __TRANS_DUMMY) &&
 	    time_seq != BTRFS_SEQ_LAST) {
-- 
2.26.3


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

* [PATCH 09/25] btrfs: remove BUG_ON(!eie) in find_parent_nodes
  2021-11-05 20:45 [PATCH 00/25] btrfs: extent tree v2 prep work for global roots Josef Bacik
                   ` (7 preceding siblings ...)
  2021-11-05 20:45 ` [PATCH 08/25] btrfs: remove BUG_ON() in find_parent_nodes() Josef Bacik
@ 2021-11-05 20:45 ` Josef Bacik
  2021-11-05 20:45 ` [PATCH 10/25] btrfs: add a btrfs_block_group_root() helper Josef Bacik
                   ` (15 subsequent siblings)
  24 siblings, 0 replies; 34+ messages in thread
From: Josef Bacik @ 2021-11-05 20:45 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

If we're looking for leafs that point to a data extent we want to record
the extent items that point at our bytenr.  At this point we have the
reference and we know for a fact that this leaf should have a reference
to our bytenr.  However if there's some sort of corruption we may not
find any references to our leaf, and thus could end up with eie == NULL.
Replace this BUG_ON() with an ASSERT() and then return -EUCLEAN for the
mortals.

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

diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index 7d942f5d6443..72ca4334186c 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -1359,10 +1359,18 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
 				goto out;
 			if (!ret && extent_item_pos) {
 				/*
-				 * we've recorded that parent, so we must extend
-				 * its inode list here
+				 * We've recorded that parent, so we must extend
+				 * its inode list here.
+				 *
+				 * However if there was corruption we may not
+				 * have found an eie, return an error in this
+				 * case.
 				 */
-				BUG_ON(!eie);
+				ASSERT(eie);
+				if (!eie) {
+					ret = -EUCLEAN;
+					goto out;
+				}
 				while (eie->next)
 					eie = eie->next;
 				eie->next = ref->inode_list;
-- 
2.26.3


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

* [PATCH 10/25] btrfs: add a btrfs_block_group_root() helper
  2021-11-05 20:45 [PATCH 00/25] btrfs: extent tree v2 prep work for global roots Josef Bacik
                   ` (8 preceding siblings ...)
  2021-11-05 20:45 ` [PATCH 09/25] btrfs: remove BUG_ON(!eie) in find_parent_nodes Josef Bacik
@ 2021-11-05 20:45 ` Josef Bacik
  2021-11-05 20:45 ` [PATCH 11/25] btrfs: make remove_extent_backref pass the root Josef Bacik
                   ` (14 subsequent siblings)
  24 siblings, 0 replies; 34+ messages in thread
From: Josef Bacik @ 2021-11-05 20:45 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

With extent tree v2 we will have a separate root to hold the block group
items.  Add a btrfs_block_group_root() that will return the appropriate
root given the flags of the fs, and convert all functions that need to
modify block group items to use the helper.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/block-group.c | 19 ++++++++++---------
 fs/btrfs/disk-io.h     |  5 +++++
 2 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c
index 2390df7fa345..b5dfb1e3446e 100644
--- a/fs/btrfs/block-group.c
+++ b/fs/btrfs/block-group.c
@@ -841,7 +841,7 @@ static int remove_block_group_item(struct btrfs_trans_handle *trans,
 	struct btrfs_key key;
 	int ret;
 
-	root = fs_info->extent_root;
+	root = btrfs_block_group_root(fs_info);
 	key.objectid = block_group->start;
 	key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
 	key.offset = block_group->length;
@@ -1106,6 +1106,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
 struct btrfs_trans_handle *btrfs_start_trans_remove_block_group(
 		struct btrfs_fs_info *fs_info, const u64 chunk_offset)
 {
+	struct btrfs_root *root = btrfs_block_group_root(fs_info);
 	struct extent_map_tree *em_tree = &fs_info->mapping_tree;
 	struct extent_map *em;
 	struct map_lookup *map;
@@ -1139,8 +1140,7 @@ struct btrfs_trans_handle *btrfs_start_trans_remove_block_group(
 	num_items = 3 + map->num_stripes;
 	free_extent_map(em);
 
-	return btrfs_start_transaction_fallback_global_rsv(fs_info->extent_root,
-							   num_items);
+	return btrfs_start_transaction_fallback_global_rsv(root, num_items);
 }
 
 /*
@@ -1678,7 +1678,7 @@ static int find_first_block_group(struct btrfs_fs_info *fs_info,
 				  struct btrfs_path *path,
 				  struct btrfs_key *key)
 {
-	struct btrfs_root *root = fs_info->extent_root;
+	struct btrfs_root *root = btrfs_block_group_root(fs_info);
 	int ret;
 	struct btrfs_key found_key;
 	struct extent_buffer *leaf;
@@ -2165,6 +2165,7 @@ static int fill_dummy_bgs(struct btrfs_fs_info *fs_info)
 
 int btrfs_read_block_groups(struct btrfs_fs_info *info)
 {
+	struct btrfs_root *root = btrfs_block_group_root(info);
 	struct btrfs_path *path;
 	int ret;
 	struct btrfs_block_group *cache;
@@ -2173,7 +2174,7 @@ int btrfs_read_block_groups(struct btrfs_fs_info *info)
 	int need_clear = 0;
 	u64 cache_gen;
 
-	if (!info->extent_root)
+	if (!root)
 		return fill_dummy_bgs(info);
 
 	key.objectid = 0;
@@ -2276,7 +2277,7 @@ static int insert_block_group_item(struct btrfs_trans_handle *trans,
 {
 	struct btrfs_fs_info *fs_info = trans->fs_info;
 	struct btrfs_block_group_item bgi;
-	struct btrfs_root *root;
+	struct btrfs_root *root = btrfs_block_group_root(fs_info);
 	struct btrfs_key key;
 
 	spin_lock(&block_group->lock);
@@ -2289,7 +2290,6 @@ static int insert_block_group_item(struct btrfs_trans_handle *trans,
 	key.offset = block_group->length;
 	spin_unlock(&block_group->lock);
 
-	root = fs_info->extent_root;
 	return btrfs_insert_item(trans, root, &key, &bgi, sizeof(bgi));
 }
 
@@ -2543,12 +2543,13 @@ int btrfs_inc_block_group_ro(struct btrfs_block_group *cache,
 {
 	struct btrfs_fs_info *fs_info = cache->fs_info;
 	struct btrfs_trans_handle *trans;
+	struct btrfs_root *root = btrfs_block_group_root(fs_info);
 	u64 alloc_flags;
 	int ret;
 	bool dirty_bg_running;
 
 	do {
-		trans = btrfs_join_transaction(fs_info->extent_root);
+		trans = btrfs_join_transaction(root);
 		if (IS_ERR(trans))
 			return PTR_ERR(trans);
 
@@ -2653,7 +2654,7 @@ static int update_block_group_item(struct btrfs_trans_handle *trans,
 {
 	struct btrfs_fs_info *fs_info = trans->fs_info;
 	int ret;
-	struct btrfs_root *root = fs_info->extent_root;
+	struct btrfs_root *root = btrfs_block_group_root(fs_info);
 	unsigned long bi;
 	struct extent_buffer *leaf;
 	struct btrfs_block_group_item bgi;
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
index a2b5db4ba262..baca29523d35 100644
--- a/fs/btrfs/disk-io.h
+++ b/fs/btrfs/disk-io.h
@@ -103,6 +103,11 @@ static inline struct btrfs_root *btrfs_grab_root(struct btrfs_root *root)
 	return NULL;
 }
 
+static inline struct btrfs_root *btrfs_block_group_root(struct btrfs_fs_info *fs_info)
+{
+	return fs_info->extent_root;
+}
+
 void btrfs_put_root(struct btrfs_root *root);
 void btrfs_mark_buffer_dirty(struct extent_buffer *buf);
 int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid,
-- 
2.26.3


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

* [PATCH 11/25] btrfs: make remove_extent_backref pass the root
  2021-11-05 20:45 [PATCH 00/25] btrfs: extent tree v2 prep work for global roots Josef Bacik
                   ` (9 preceding siblings ...)
  2021-11-05 20:45 ` [PATCH 10/25] btrfs: add a btrfs_block_group_root() helper Josef Bacik
@ 2021-11-05 20:45 ` Josef Bacik
  2021-11-05 20:45 ` [PATCH 12/25] btrfs: use chunk_root in find_free_extent_update_loop Josef Bacik
                   ` (13 subsequent siblings)
  24 siblings, 0 replies; 34+ messages in thread
From: Josef Bacik @ 2021-11-05 20:45 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

With extent tree v2 we'll have a different extent root based on where
the bytenr is located, so adjust the remove_extent_backref() helper and
it's helpers to pass the extent_root around.

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

diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 3fd736a02c1e..c33f3dc6b322 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -593,6 +593,7 @@ static noinline int insert_extent_data_ref(struct btrfs_trans_handle *trans,
 }
 
 static noinline int remove_extent_data_ref(struct btrfs_trans_handle *trans,
+					   struct btrfs_root *root,
 					   struct btrfs_path *path,
 					   int refs_to_drop, int *last_ref)
 {
@@ -626,7 +627,7 @@ static noinline int remove_extent_data_ref(struct btrfs_trans_handle *trans,
 	num_refs -= refs_to_drop;
 
 	if (num_refs == 0) {
-		ret = btrfs_del_item(trans, trans->fs_info->extent_root, path);
+		ret = btrfs_del_item(trans, root, path);
 		*last_ref = 1;
 	} else {
 		if (key.type == BTRFS_EXTENT_DATA_REF_KEY)
@@ -1174,6 +1175,7 @@ int insert_inline_extent_backref(struct btrfs_trans_handle *trans,
 }
 
 static int remove_extent_backref(struct btrfs_trans_handle *trans,
+				 struct btrfs_root *root,
 				 struct btrfs_path *path,
 				 struct btrfs_extent_inline_ref *iref,
 				 int refs_to_drop, int is_data, int *last_ref)
@@ -1185,11 +1187,11 @@ static int remove_extent_backref(struct btrfs_trans_handle *trans,
 		update_inline_extent_backref(path, iref, -refs_to_drop, NULL,
 					     last_ref);
 	} else if (is_data) {
-		ret = remove_extent_data_ref(trans, path, refs_to_drop,
+		ret = remove_extent_data_ref(trans, root, path, refs_to_drop,
 					     last_ref);
 	} else {
 		*last_ref = 1;
-		ret = btrfs_del_item(trans, trans->fs_info->extent_root, path);
+		ret = btrfs_del_item(trans, root, path);
 	}
 	return ret;
 }
@@ -2996,9 +2998,9 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
 				goto err_dump;
 			}
 			/* Must be SHARED_* item, remove the backref first */
-			ret = remove_extent_backref(trans, path, NULL,
-						    refs_to_drop,
-						    is_data, &last_ref);
+			ret = remove_extent_backref(trans, extent_root, path,
+						    NULL, refs_to_drop, is_data,
+						    &last_ref);
 			if (ret) {
 				btrfs_abort_transaction(trans, ret);
 				goto out;
@@ -3122,8 +3124,8 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
 			btrfs_mark_buffer_dirty(leaf);
 		}
 		if (found_extent) {
-			ret = remove_extent_backref(trans, path, iref,
-						    refs_to_drop, is_data,
+			ret = remove_extent_backref(trans, extent_root, path,
+						    iref, refs_to_drop, is_data,
 						    &last_ref);
 			if (ret) {
 				btrfs_abort_transaction(trans, ret);
-- 
2.26.3


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

* [PATCH 12/25] btrfs: use chunk_root in find_free_extent_update_loop
  2021-11-05 20:45 [PATCH 00/25] btrfs: extent tree v2 prep work for global roots Josef Bacik
                   ` (10 preceding siblings ...)
  2021-11-05 20:45 ` [PATCH 11/25] btrfs: make remove_extent_backref pass the root Josef Bacik
@ 2021-11-05 20:45 ` Josef Bacik
  2021-11-25 10:11   ` Nikolay Borisov
  2021-11-05 20:45 ` [PATCH 13/25] btrfs: do not special case the extent root for switch commit roots Josef Bacik
                   ` (12 subsequent siblings)
  24 siblings, 1 reply; 34+ messages in thread
From: Josef Bacik @ 2021-11-05 20:45 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

We're only using this to start the transaction with to possibly allocate
a chunk.  It doesn't really matter which root to use, but with extent
tree v2 we'll need a bytenr to look up a extent root which makes the
usage of the extent_root awkward here.  Simply change it to the
chunk_root.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/extent-tree.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index c33f3dc6b322..f40b97072231 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -3977,7 +3977,7 @@ static int find_free_extent_update_loop(struct btrfs_fs_info *fs_info,
 					struct find_free_extent_ctl *ffe_ctl,
 					bool full_search)
 {
-	struct btrfs_root *root = fs_info->extent_root;
+	struct btrfs_root *root = fs_info->chunk_root;
 	int ret;
 
 	if ((ffe_ctl->loop == LOOP_CACHING_NOWAIT) &&
-- 
2.26.3


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

* [PATCH 13/25] btrfs: do not special case the extent root for switch commit roots
  2021-11-05 20:45 [PATCH 00/25] btrfs: extent tree v2 prep work for global roots Josef Bacik
                   ` (11 preceding siblings ...)
  2021-11-05 20:45 ` [PATCH 12/25] btrfs: use chunk_root in find_free_extent_update_loop Josef Bacik
@ 2021-11-05 20:45 ` Josef Bacik
  2021-11-05 20:45 ` [PATCH 14/25] btrfs: remove unnecessary extent root check in btrfs_defrag_leaves Josef Bacik
                   ` (11 subsequent siblings)
  24 siblings, 0 replies; 34+ messages in thread
From: Josef Bacik @ 2021-11-05 20:45 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

This is a leftover from when we used to independently swap the extent
root's commit root and the fs tree commit roots.  At the time I simply
changed the helper to a list_add.  There's actually no reason to not add
the extent root to the switch commit root at this point, we don't care
about the order we do the switching since it's all done under the
commit_root_sem.

If we re-mark the extent root dirty after adding it to the
switch_commits list we'll see that BTRFS_ROOT_DIRTY isn't set and then
list_move it back onto the dirty list, and then we'll redo the tree
update and everything will be ok.

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

diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 451788400e17..9f03c727aa6a 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -1266,9 +1266,8 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans)
 		root = list_entry(next, struct btrfs_root, dirty_list);
 		clear_bit(BTRFS_ROOT_DIRTY, &root->state);
 
-		if (root != fs_info->extent_root)
-			list_add_tail(&root->dirty_list,
-				      &trans->transaction->switch_commits);
+		list_add_tail(&root->dirty_list,
+			      &trans->transaction->switch_commits);
 		ret = update_cowonly_root(trans, root);
 		if (ret)
 			return ret;
@@ -1298,9 +1297,6 @@ static noinline int commit_cowonly_roots(struct btrfs_trans_handle *trans)
 	if (!list_empty(&fs_info->dirty_cowonly_roots))
 		goto again;
 
-	list_add_tail(&fs_info->extent_root->dirty_list,
-		      &trans->transaction->switch_commits);
-
 	/* Update dev-replace pointer once everything is committed */
 	fs_info->dev_replace.committed_cursor_left =
 		fs_info->dev_replace.cursor_left_last_write_of_item;
-- 
2.26.3


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

* [PATCH 14/25] btrfs: remove unnecessary extent root check in btrfs_defrag_leaves
  2021-11-05 20:45 [PATCH 00/25] btrfs: extent tree v2 prep work for global roots Josef Bacik
                   ` (12 preceding siblings ...)
  2021-11-05 20:45 ` [PATCH 13/25] btrfs: do not special case the extent root for switch commit roots Josef Bacik
@ 2021-11-05 20:45 ` Josef Bacik
  2021-11-05 20:45 ` [PATCH 15/25] btrfs: don't use the extent root in btrfs_chunk_alloc_add_chunk_item Josef Bacik
                   ` (10 subsequent siblings)
  24 siblings, 0 replies; 34+ messages in thread
From: Josef Bacik @ 2021-11-05 20:45 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

We only defrag leaves on roots that have SHAREABLE set, so we don't need
to check if we're the extent root as it doesn't have SHAREABLE set.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/tree-defrag.c | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/fs/btrfs/tree-defrag.c b/fs/btrfs/tree-defrag.c
index 7c45d960b53c..b6cf39f4e7e4 100644
--- a/fs/btrfs/tree-defrag.c
+++ b/fs/btrfs/tree-defrag.c
@@ -27,14 +27,6 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
 	int next_key_ret = 0;
 	u64 last_ret = 0;
 
-	if (root->fs_info->extent_root == root) {
-		/*
-		 * there's recursion here right now in the tree locking,
-		 * we can't defrag the extent root without deadlock
-		 */
-		goto out;
-	}
-
 	if (!test_bit(BTRFS_ROOT_SHAREABLE, &root->state))
 		goto out;
 
-- 
2.26.3


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

* [PATCH 15/25] btrfs: don't use the extent root in btrfs_chunk_alloc_add_chunk_item
  2021-11-05 20:45 [PATCH 00/25] btrfs: extent tree v2 prep work for global roots Josef Bacik
                   ` (13 preceding siblings ...)
  2021-11-05 20:45 ` [PATCH 14/25] btrfs: remove unnecessary extent root check in btrfs_defrag_leaves Josef Bacik
@ 2021-11-05 20:45 ` Josef Bacik
  2021-11-05 20:45 ` [PATCH 16/25] btrfs: don't use extent_root in iterate_extent_inodes Josef Bacik
                   ` (9 subsequent siblings)
  24 siblings, 0 replies; 34+ messages in thread
From: Josef Bacik @ 2021-11-05 20:45 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

We're just using the extent_root to set the chunk owner to
root_key->objectid, which is BTRFS_EXTENT_TREE_OBJECTID, so use that
directly instead of using the root.

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

diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 546bf1146b2d..85842eb1f7b1 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -5502,7 +5502,6 @@ int btrfs_chunk_alloc_add_chunk_item(struct btrfs_trans_handle *trans,
 				     struct btrfs_block_group *bg)
 {
 	struct btrfs_fs_info *fs_info = trans->fs_info;
-	struct btrfs_root *extent_root = fs_info->extent_root;
 	struct btrfs_root *chunk_root = fs_info->chunk_root;
 	struct btrfs_key key;
 	struct btrfs_chunk *chunk;
@@ -5574,7 +5573,7 @@ int btrfs_chunk_alloc_add_chunk_item(struct btrfs_trans_handle *trans,
 	}
 
 	btrfs_set_stack_chunk_length(chunk, bg->length);
-	btrfs_set_stack_chunk_owner(chunk, extent_root->root_key.objectid);
+	btrfs_set_stack_chunk_owner(chunk, BTRFS_EXTENT_TREE_OBJECTID);
 	btrfs_set_stack_chunk_stripe_len(chunk, map->stripe_len);
 	btrfs_set_stack_chunk_type(chunk, map->type);
 	btrfs_set_stack_chunk_num_stripes(chunk, map->num_stripes);
-- 
2.26.3


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

* [PATCH 16/25] btrfs: don't use extent_root in iterate_extent_inodes
  2021-11-05 20:45 [PATCH 00/25] btrfs: extent tree v2 prep work for global roots Josef Bacik
                   ` (14 preceding siblings ...)
  2021-11-05 20:45 ` [PATCH 15/25] btrfs: don't use the extent root in btrfs_chunk_alloc_add_chunk_item Josef Bacik
@ 2021-11-05 20:45 ` Josef Bacik
  2021-11-05 20:45 ` [PATCH 17/25] btrfs: don't use the extent_root in flush_space Josef Bacik
                   ` (8 subsequent siblings)
  24 siblings, 0 replies; 34+ messages in thread
From: Josef Bacik @ 2021-11-05 20:45 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

We are going to have many extent_roots soon, and we don't need a root
here necessarily as we're not modifying anything, we're just getting the
trans handle so we can have an accurate view of references, so use the
tree_root here.

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

diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index 72ca4334186c..0c5c7cc14604 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -1969,7 +1969,7 @@ int iterate_extent_inodes(struct btrfs_fs_info *fs_info,
 			extent_item_objectid);
 
 	if (!search_commit_root) {
-		trans = btrfs_attach_transaction(fs_info->extent_root);
+		trans = btrfs_attach_transaction(fs_info->tree_root);
 		if (IS_ERR(trans)) {
 			if (PTR_ERR(trans) != -ENOENT &&
 			    PTR_ERR(trans) != -EROFS)
-- 
2.26.3


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

* [PATCH 17/25] btrfs: don't use the extent_root in flush_space
  2021-11-05 20:45 [PATCH 00/25] btrfs: extent tree v2 prep work for global roots Josef Bacik
                   ` (15 preceding siblings ...)
  2021-11-05 20:45 ` [PATCH 16/25] btrfs: don't use extent_root in iterate_extent_inodes Josef Bacik
@ 2021-11-05 20:45 ` Josef Bacik
  2021-11-05 20:45 ` [PATCH 18/25] btrfs: init root block_rsv at init root time Josef Bacik
                   ` (7 subsequent siblings)
  24 siblings, 0 replies; 34+ messages in thread
From: Josef Bacik @ 2021-11-05 20:45 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

We only need the root to start a transaction, and since it's a global
root we can pick anything, change to the tree_root as we'll have a lot
of extent roots in the future.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/space-info.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c
index f74b4063772e..f6a1486bb6e5 100644
--- a/fs/btrfs/space-info.c
+++ b/fs/btrfs/space-info.c
@@ -617,7 +617,7 @@ static void flush_space(struct btrfs_fs_info *fs_info,
 		       struct btrfs_space_info *space_info, u64 num_bytes,
 		       enum btrfs_flush_state state, bool for_preempt)
 {
-	struct btrfs_root *root = fs_info->extent_root;
+	struct btrfs_root *root = fs_info->tree_root;
 	struct btrfs_trans_handle *trans;
 	int nr;
 	int ret = 0;
-- 
2.26.3


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

* [PATCH 18/25] btrfs: init root block_rsv at init root time
  2021-11-05 20:45 [PATCH 00/25] btrfs: extent tree v2 prep work for global roots Josef Bacik
                   ` (16 preceding siblings ...)
  2021-11-05 20:45 ` [PATCH 17/25] btrfs: don't use the extent_root in flush_space Josef Bacik
@ 2021-11-05 20:45 ` Josef Bacik
  2021-11-05 20:45 ` [PATCH 19/25] btrfs: stop accessing ->extent_root directly Josef Bacik
                   ` (6 subsequent siblings)
  24 siblings, 0 replies; 34+ messages in thread
From: Josef Bacik @ 2021-11-05 20:45 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

In the future we're going to have multiple csum and extent root trees,
so init the roots block_rsv at setup_root time based on their root key
objectid.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/block-rsv.c | 39 +++++++++++++++++++++++----------------
 fs/btrfs/block-rsv.h |  1 +
 fs/btrfs/disk-io.c   | 15 ++++++++-------
 3 files changed, 32 insertions(+), 23 deletions(-)

diff --git a/fs/btrfs/block-rsv.c b/fs/btrfs/block-rsv.c
index ac6fbe75cace..166f6c74c943 100644
--- a/fs/btrfs/block-rsv.c
+++ b/fs/btrfs/block-rsv.c
@@ -414,6 +414,29 @@ void btrfs_update_global_block_rsv(struct btrfs_fs_info *fs_info)
 	spin_unlock(&sinfo->lock);
 }
 
+void btrfs_init_root_block_rsv(struct btrfs_root *root)
+{
+	struct btrfs_fs_info *fs_info = root->fs_info;
+
+	switch (root->root_key.objectid) {
+	case BTRFS_CSUM_TREE_OBJECTID:
+	case BTRFS_EXTENT_TREE_OBJECTID:
+		root->block_rsv = &fs_info->delayed_refs_rsv;
+		break;
+	case BTRFS_ROOT_TREE_OBJECTID:
+	case BTRFS_DEV_TREE_OBJECTID:
+	case BTRFS_QUOTA_TREE_OBJECTID:
+		root->block_rsv = &fs_info->global_block_rsv;
+		break;
+	case BTRFS_CHUNK_TREE_OBJECTID:
+		root->block_rsv = &fs_info->chunk_block_rsv;
+		break;
+	default:
+		root->block_rsv = NULL;
+		break;
+	}
+}
+
 void btrfs_init_global_block_rsv(struct btrfs_fs_info *fs_info)
 {
 	struct btrfs_space_info *space_info;
@@ -428,22 +451,6 @@ void btrfs_init_global_block_rsv(struct btrfs_fs_info *fs_info)
 	fs_info->delayed_block_rsv.space_info = space_info;
 	fs_info->delayed_refs_rsv.space_info = space_info;
 
-	/*
-	 * Our various recovery options can leave us with NULL roots, so check
-	 * here and just bail before we go dereferencing NULLs everywhere.
-	 */
-	if (!fs_info->extent_root || !fs_info->csum_root ||
-	    !fs_info->dev_root || !fs_info->chunk_root || !fs_info->tree_root)
-		return;
-
-	fs_info->extent_root->block_rsv = &fs_info->delayed_refs_rsv;
-	fs_info->csum_root->block_rsv = &fs_info->delayed_refs_rsv;
-	fs_info->dev_root->block_rsv = &fs_info->global_block_rsv;
-	fs_info->tree_root->block_rsv = &fs_info->global_block_rsv;
-	if (fs_info->quota_root)
-		fs_info->quota_root->block_rsv = &fs_info->global_block_rsv;
-	fs_info->chunk_root->block_rsv = &fs_info->chunk_block_rsv;
-
 	btrfs_update_global_block_rsv(fs_info);
 }
 
diff --git a/fs/btrfs/block-rsv.h b/fs/btrfs/block-rsv.h
index 07d61c2c5d28..3b67ff08d434 100644
--- a/fs/btrfs/block-rsv.h
+++ b/fs/btrfs/block-rsv.h
@@ -50,6 +50,7 @@ struct btrfs_block_rsv {
 };
 
 void btrfs_init_block_rsv(struct btrfs_block_rsv *rsv, unsigned short type);
+void btrfs_init_root_block_rsv(struct btrfs_root *root);
 struct btrfs_block_rsv *btrfs_alloc_block_rsv(struct btrfs_fs_info *fs_info,
 					      unsigned short type);
 void btrfs_init_metadata_block_rsv(struct btrfs_fs_info *fs_info,
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 3bd3a06a9627..372adb8ec20f 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1140,7 +1140,12 @@ static void __setup_root(struct btrfs_root *root, struct btrfs_fs_info *fs_info,
 			 u64 objectid)
 {
 	bool dummy = test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state);
+
+	memset(&root->root_key, 0, sizeof(root->root_key));
+	memset(&root->root_item, 0, sizeof(root->root_item));
+	memset(&root->defrag_progress, 0, sizeof(root->defrag_progress));
 	root->fs_info = fs_info;
+	root->root_key.objectid = objectid;
 	root->node = NULL;
 	root->commit_root = NULL;
 	root->state = 0;
@@ -1151,7 +1156,8 @@ static void __setup_root(struct btrfs_root *root, struct btrfs_fs_info *fs_info,
 	root->nr_ordered_extents = 0;
 	root->inode_tree = RB_ROOT;
 	INIT_RADIX_TREE(&root->delayed_nodes_tree, GFP_ATOMIC);
-	root->block_rsv = NULL;
+
+	btrfs_init_root_block_rsv(root);
 
 	INIT_LIST_HEAD(&root->dirty_list);
 	INIT_LIST_HEAD(&root->root_list);
@@ -1189,6 +1195,7 @@ static void __setup_root(struct btrfs_root *root, struct btrfs_fs_info *fs_info,
 	root->log_transid = 0;
 	root->log_transid_committed = -1;
 	root->last_log_commit = 0;
+	root->anon_dev = 0;
 	if (!dummy) {
 		extent_io_tree_init(fs_info, &root->dirty_log_pages,
 				    IO_TREE_ROOT_DIRTY_LOG_PAGES, NULL);
@@ -1196,12 +1203,6 @@ static void __setup_root(struct btrfs_root *root, struct btrfs_fs_info *fs_info,
 				    IO_TREE_LOG_CSUM_RANGE, NULL);
 	}
 
-	memset(&root->root_key, 0, sizeof(root->root_key));
-	memset(&root->root_item, 0, sizeof(root->root_item));
-	memset(&root->defrag_progress, 0, sizeof(root->defrag_progress));
-	root->root_key.objectid = objectid;
-	root->anon_dev = 0;
-
 	spin_lock_init(&root->root_item_lock);
 	btrfs_qgroup_init_swapped_blocks(&root->swapped_blocks);
 #ifdef CONFIG_BTRFS_DEBUG
-- 
2.26.3


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

* [PATCH 19/25] btrfs: stop accessing ->extent_root directly
  2021-11-05 20:45 [PATCH 00/25] btrfs: extent tree v2 prep work for global roots Josef Bacik
                   ` (17 preceding siblings ...)
  2021-11-05 20:45 ` [PATCH 18/25] btrfs: init root block_rsv at init root time Josef Bacik
@ 2021-11-05 20:45 ` Josef Bacik
  2021-11-05 20:45 ` [PATCH 20/25] btrfs: fix csum assert to check objectid of the root Josef Bacik
                   ` (5 subsequent siblings)
  24 siblings, 0 replies; 34+ messages in thread
From: Josef Bacik @ 2021-11-05 20:45 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

When we start having multiple extent roots we'll need to use a helper to
get to the correct extent_root.  Rename fs_info->extent_root to
_extent_root and convert all of the users of the extent root to using
the btrfs_extent_root() helper.  This will allow us to easily clean up
the remaining direct accesses in the future.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/backref.c                | 16 ++++++++-----
 fs/btrfs/block-group.c            |  3 ++-
 fs/btrfs/block-rsv.c              |  4 +++-
 fs/btrfs/ctree.h                  |  2 +-
 fs/btrfs/disk-io.c                | 15 ++++++------
 fs/btrfs/disk-io.h                |  8 ++++++-
 fs/btrfs/extent-tree.c            | 40 +++++++++++++++++++------------
 fs/btrfs/free-space-tree.c        |  3 ++-
 fs/btrfs/qgroup.c                 |  5 +++-
 fs/btrfs/ref-verify.c             |  6 +++--
 fs/btrfs/relocation.c             |  4 ++--
 fs/btrfs/scrub.c                  |  6 +++--
 fs/btrfs/tests/free-space-tests.c |  2 +-
 fs/btrfs/tests/qgroup-tests.c     |  2 +-
 fs/btrfs/transaction.c            |  2 +-
 fs/btrfs/zoned.c                  |  3 ++-
 16 files changed, 77 insertions(+), 44 deletions(-)

diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
index 0c5c7cc14604..96c520634521 100644
--- a/fs/btrfs/backref.c
+++ b/fs/btrfs/backref.c
@@ -1170,7 +1170,7 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
 			     struct ulist *roots, const u64 *extent_item_pos,
 			     struct share_check *sc, bool ignore_offset)
 {
-	struct btrfs_root *root = fs_info->extent_root;
+	struct btrfs_root *root = btrfs_extent_root(fs_info, bytenr);
 	struct btrfs_key key;
 	struct btrfs_path *path;
 	struct btrfs_delayed_ref_root *delayed_refs = NULL;
@@ -1747,6 +1747,7 @@ int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical,
 			struct btrfs_path *path, struct btrfs_key *found_key,
 			u64 *flags_ret)
 {
+	struct btrfs_root *extent_root = btrfs_extent_root(fs_info, logical);
 	int ret;
 	u64 flags;
 	u64 size = 0;
@@ -1762,11 +1763,11 @@ int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical,
 	key.objectid = logical;
 	key.offset = (u64)-1;
 
-	ret = btrfs_search_slot(NULL, fs_info->extent_root, &key, path, 0, 0);
+	ret = btrfs_search_slot(NULL, extent_root, &key, path, 0, 0);
 	if (ret < 0)
 		return ret;
 
-	ret = btrfs_previous_extent_item(fs_info->extent_root, path, 0);
+	ret = btrfs_previous_extent_item(extent_root, path, 0);
 	if (ret) {
 		if (ret > 0)
 			ret = -ENOENT;
@@ -2337,6 +2338,7 @@ struct btrfs_backref_iter *btrfs_backref_iter_alloc(
 int btrfs_backref_iter_start(struct btrfs_backref_iter *iter, u64 bytenr)
 {
 	struct btrfs_fs_info *fs_info = iter->fs_info;
+	struct btrfs_root *extent_root = btrfs_extent_root(fs_info, bytenr);
 	struct btrfs_path *path = iter->path;
 	struct btrfs_extent_item *ei;
 	struct btrfs_key key;
@@ -2347,7 +2349,7 @@ int btrfs_backref_iter_start(struct btrfs_backref_iter *iter, u64 bytenr)
 	key.offset = (u64)-1;
 	iter->bytenr = bytenr;
 
-	ret = btrfs_search_slot(NULL, fs_info->extent_root, &key, path, 0, 0);
+	ret = btrfs_search_slot(NULL, extent_root, &key, path, 0, 0);
 	if (ret < 0)
 		return ret;
 	if (ret == 0) {
@@ -2390,7 +2392,7 @@ int btrfs_backref_iter_start(struct btrfs_backref_iter *iter, u64 bytenr)
 
 	/* If there is no inline backref, go search for keyed backref */
 	if (iter->cur_ptr >= iter->end_ptr) {
-		ret = btrfs_next_item(fs_info->extent_root, path);
+		ret = btrfs_next_item(extent_root, path);
 
 		/* No inline nor keyed ref */
 		if (ret > 0) {
@@ -2434,6 +2436,7 @@ int btrfs_backref_iter_start(struct btrfs_backref_iter *iter, u64 bytenr)
 int btrfs_backref_iter_next(struct btrfs_backref_iter *iter)
 {
 	struct extent_buffer *eb = btrfs_backref_get_eb(iter);
+	struct btrfs_root *extent_root;
 	struct btrfs_path *path = iter->path;
 	struct btrfs_extent_inline_ref *iref;
 	int ret;
@@ -2464,7 +2467,8 @@ int btrfs_backref_iter_next(struct btrfs_backref_iter *iter)
 	}
 
 	/* We're at keyed items, there is no inline item, go to the next one */
-	ret = btrfs_next_item(iter->fs_info->extent_root, iter->path);
+	extent_root = btrfs_extent_root(iter->fs_info, iter->bytenr);
+	ret = btrfs_next_item(extent_root, iter->path);
 	if (ret)
 		return ret;
 
diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c
index b5dfb1e3446e..7eb0a8632a01 100644
--- a/fs/btrfs/block-group.c
+++ b/fs/btrfs/block-group.c
@@ -514,7 +514,7 @@ static int load_extent_tree_free(struct btrfs_caching_control *caching_ctl)
 {
 	struct btrfs_block_group *block_group = caching_ctl->block_group;
 	struct btrfs_fs_info *fs_info = block_group->fs_info;
-	struct btrfs_root *extent_root = fs_info->extent_root;
+	struct btrfs_root *extent_root;
 	struct btrfs_path *path;
 	struct extent_buffer *leaf;
 	struct btrfs_key key;
@@ -529,6 +529,7 @@ static int load_extent_tree_free(struct btrfs_caching_control *caching_ctl)
 		return -ENOMEM;
 
 	last = max_t(u64, block_group->start, BTRFS_SUPER_INFO_OFFSET);
+	extent_root = btrfs_extent_root(fs_info, last);
 
 #ifdef CONFIG_BTRFS_DEBUG
 	/*
diff --git a/fs/btrfs/block-rsv.c b/fs/btrfs/block-rsv.c
index 166f6c74c943..7f5c230ea547 100644
--- a/fs/btrfs/block-rsv.c
+++ b/fs/btrfs/block-rsv.c
@@ -6,6 +6,7 @@
 #include "space-info.h"
 #include "transaction.h"
 #include "block-group.h"
+#include "disk-io.h"
 
 /*
  * HOW DO BLOCK RESERVES WORK
@@ -353,6 +354,7 @@ void btrfs_update_global_block_rsv(struct btrfs_fs_info *fs_info)
 {
 	struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv;
 	struct btrfs_space_info *sinfo = block_rsv->space_info;
+	struct btrfs_root *extent_root = btrfs_extent_root(fs_info, 0);
 	u64 num_bytes;
 	unsigned min_items;
 
@@ -361,7 +363,7 @@ void btrfs_update_global_block_rsv(struct btrfs_fs_info *fs_info)
 	 * checksum tree and the root tree.  If the fs is empty we want to set
 	 * it to a minimal amount for safety.
 	 */
-	num_bytes = btrfs_root_used(&fs_info->extent_root->root_item) +
+	num_bytes = btrfs_root_used(&extent_root->root_item) +
 		btrfs_root_used(&fs_info->csum_root->root_item) +
 		btrfs_root_used(&fs_info->tree_root->root_item);
 
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index fb49162311b9..dac5741cb6fa 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -621,7 +621,7 @@ enum btrfs_exclusive_operation {
 struct btrfs_fs_info {
 	u8 chunk_tree_uuid[BTRFS_UUID_SIZE];
 	unsigned long flags;
-	struct btrfs_root *extent_root;
+	struct btrfs_root *_extent_root;
 	struct btrfs_root *tree_root;
 	struct btrfs_root *chunk_root;
 	struct btrfs_root *dev_root;
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 372adb8ec20f..1ada4c96ef71 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1557,7 +1557,7 @@ static struct btrfs_root *btrfs_get_global_root(struct btrfs_fs_info *fs_info,
 	if (objectid == BTRFS_ROOT_TREE_OBJECTID)
 		return btrfs_grab_root(fs_info->tree_root);
 	if (objectid == BTRFS_EXTENT_TREE_OBJECTID)
-		return btrfs_grab_root(fs_info->extent_root);
+		return btrfs_grab_root(fs_info->_extent_root);
 	if (objectid == BTRFS_CHUNK_TREE_OBJECTID)
 		return btrfs_grab_root(fs_info->chunk_root);
 	if (objectid == BTRFS_DEV_TREE_OBJECTID)
@@ -1630,7 +1630,7 @@ void btrfs_free_fs_info(struct btrfs_fs_info *fs_info)
 	btrfs_free_ref_cache(fs_info);
 	kfree(fs_info->balance_ctl);
 	kfree(fs_info->delayed_root);
-	btrfs_put_root(fs_info->extent_root);
+	btrfs_put_root(fs_info->_extent_root);
 	btrfs_put_root(fs_info->tree_root);
 	btrfs_put_root(fs_info->chunk_root);
 	btrfs_put_root(fs_info->dev_root);
@@ -2000,6 +2000,7 @@ static void backup_super_roots(struct btrfs_fs_info *info)
 {
 	const int next_backup = info->backup_root_index;
 	struct btrfs_root_backup *root_backup;
+	struct btrfs_root *extent_root = btrfs_extent_root(info, 0);
 
 	root_backup = info->super_for_commit->super_roots + next_backup;
 
@@ -2024,11 +2025,11 @@ static void backup_super_roots(struct btrfs_fs_info *info)
 	btrfs_set_backup_chunk_root_level(root_backup,
 			       btrfs_header_level(info->chunk_root->node));
 
-	btrfs_set_backup_extent_root(root_backup, info->extent_root->node->start);
+	btrfs_set_backup_extent_root(root_backup, extent_root->node->start);
 	btrfs_set_backup_extent_root_gen(root_backup,
-			       btrfs_header_generation(info->extent_root->node));
+			       btrfs_header_generation(extent_root->node));
 	btrfs_set_backup_extent_root_level(root_backup,
-			       btrfs_header_level(info->extent_root->node));
+			       btrfs_header_level(extent_root->node));
 
 	/*
 	 * we might commit during log recovery, which happens before we set
@@ -2158,7 +2159,7 @@ static void free_root_pointers(struct btrfs_fs_info *info, bool free_chunk_root)
 	free_root_extent_buffers(info->tree_root);
 
 	free_root_extent_buffers(info->dev_root);
-	free_root_extent_buffers(info->extent_root);
+	free_root_extent_buffers(info->_extent_root);
 	free_root_extent_buffers(info->csum_root);
 	free_root_extent_buffers(info->quota_root);
 	free_root_extent_buffers(info->uuid_root);
@@ -2449,7 +2450,7 @@ static int btrfs_read_roots(struct btrfs_fs_info *fs_info)
 		}
 	} else {
 		set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state);
-		fs_info->extent_root = root;
+		fs_info->_extent_root = root;
 	}
 
 	location.objectid = BTRFS_DEV_TREE_OBJECTID;
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
index baca29523d35..e2824c6ada72 100644
--- a/fs/btrfs/disk-io.h
+++ b/fs/btrfs/disk-io.h
@@ -103,9 +103,15 @@ static inline struct btrfs_root *btrfs_grab_root(struct btrfs_root *root)
 	return NULL;
 }
 
+static inline struct btrfs_root *btrfs_extent_root(struct btrfs_fs_info *fs_info,
+						   u64 bytenr)
+{
+	return fs_info->_extent_root;
+}
+
 static inline struct btrfs_root *btrfs_block_group_root(struct btrfs_fs_info *fs_info)
 {
-	return fs_info->extent_root;
+	return btrfs_extent_root(fs_info, 0);
 }
 
 void btrfs_put_root(struct btrfs_root *root);
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index f40b97072231..de80b7109a08 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -87,6 +87,7 @@ void btrfs_free_excluded_extents(struct btrfs_block_group *cache)
 /* simple helper to search for an existing data extent at a given offset */
 int btrfs_lookup_data_extent(struct btrfs_fs_info *fs_info, u64 start, u64 len)
 {
+	struct btrfs_root *root = btrfs_extent_root(fs_info, start);
 	int ret;
 	struct btrfs_key key;
 	struct btrfs_path *path;
@@ -98,7 +99,7 @@ int btrfs_lookup_data_extent(struct btrfs_fs_info *fs_info, u64 start, u64 len)
 	key.objectid = start;
 	key.offset = len;
 	key.type = BTRFS_EXTENT_ITEM_KEY;
-	ret = btrfs_search_slot(NULL, fs_info->extent_root, &key, path, 0, 0);
+	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
 	btrfs_free_path(path);
 	return ret;
 }
@@ -116,6 +117,7 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
 			     struct btrfs_fs_info *fs_info, u64 bytenr,
 			     u64 offset, int metadata, u64 *refs, u64 *flags)
 {
+	struct btrfs_root *extent_root;
 	struct btrfs_delayed_ref_head *head;
 	struct btrfs_delayed_ref_root *delayed_refs;
 	struct btrfs_path *path;
@@ -153,7 +155,8 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
 	else
 		key.type = BTRFS_EXTENT_ITEM_KEY;
 
-	ret = btrfs_search_slot(NULL, fs_info->extent_root, &key, path, 0, 0);
+	extent_root = btrfs_extent_root(fs_info, bytenr);
+	ret = btrfs_search_slot(NULL, extent_root, &key, path, 0, 0);
 	if (ret < 0)
 		goto out_free;
 
@@ -443,7 +446,7 @@ static noinline int lookup_extent_data_ref(struct btrfs_trans_handle *trans,
 					   u64 root_objectid,
 					   u64 owner, u64 offset)
 {
-	struct btrfs_root *root = trans->fs_info->extent_root;
+	struct btrfs_root *root = btrfs_extent_root(trans->fs_info, bytenr);
 	struct btrfs_key key;
 	struct btrfs_extent_data_ref *ref;
 	struct extent_buffer *leaf;
@@ -519,7 +522,7 @@ static noinline int insert_extent_data_ref(struct btrfs_trans_handle *trans,
 					   u64 root_objectid, u64 owner,
 					   u64 offset, int refs_to_add)
 {
-	struct btrfs_root *root = trans->fs_info->extent_root;
+	struct btrfs_root *root = btrfs_extent_root(trans->fs_info, bytenr);
 	struct btrfs_key key;
 	struct extent_buffer *leaf;
 	u32 size;
@@ -686,7 +689,7 @@ static noinline int lookup_tree_block_ref(struct btrfs_trans_handle *trans,
 					  u64 bytenr, u64 parent,
 					  u64 root_objectid)
 {
-	struct btrfs_root *root = trans->fs_info->extent_root;
+	struct btrfs_root *root = btrfs_extent_root(trans->fs_info, bytenr);
 	struct btrfs_key key;
 	int ret;
 
@@ -710,6 +713,7 @@ static noinline int insert_tree_block_ref(struct btrfs_trans_handle *trans,
 					  u64 bytenr, u64 parent,
 					  u64 root_objectid)
 {
+	struct btrfs_root *root = btrfs_extent_root(trans->fs_info, bytenr);
 	struct btrfs_key key;
 	int ret;
 
@@ -722,8 +726,7 @@ static noinline int insert_tree_block_ref(struct btrfs_trans_handle *trans,
 		key.offset = root_objectid;
 	}
 
-	ret = btrfs_insert_empty_item(trans, trans->fs_info->extent_root,
-				      path, &key, 0);
+	ret = btrfs_insert_empty_item(trans, root, path, &key, 0);
 	btrfs_release_path(path);
 	return ret;
 }
@@ -788,7 +791,7 @@ int lookup_inline_extent_backref(struct btrfs_trans_handle *trans,
 				 u64 owner, u64 offset, int insert)
 {
 	struct btrfs_fs_info *fs_info = trans->fs_info;
-	struct btrfs_root *root = fs_info->extent_root;
+	struct btrfs_root *root = btrfs_extent_root(fs_info, bytenr);
 	struct btrfs_key key;
 	struct extent_buffer *leaf;
 	struct btrfs_extent_item *ei;
@@ -1574,6 +1577,7 @@ static int run_delayed_extent_op(struct btrfs_trans_handle *trans,
 				 struct btrfs_delayed_extent_op *extent_op)
 {
 	struct btrfs_fs_info *fs_info = trans->fs_info;
+	struct btrfs_root *root;
 	struct btrfs_key key;
 	struct btrfs_path *path;
 	struct btrfs_extent_item *ei;
@@ -1603,8 +1607,9 @@ static int run_delayed_extent_op(struct btrfs_trans_handle *trans,
 		key.offset = head->num_bytes;
 	}
 
+	root = btrfs_extent_root(fs_info, key.objectid);
 again:
-	ret = btrfs_search_slot(trans, fs_info->extent_root, &key, path, 0, 1);
+	ret = btrfs_search_slot(trans, root, &key, path, 0, 1);
 	if (ret < 0) {
 		err = ret;
 		goto out;
@@ -2287,7 +2292,7 @@ static noinline int check_committed_ref(struct btrfs_root *root,
 					bool strict)
 {
 	struct btrfs_fs_info *fs_info = root->fs_info;
-	struct btrfs_root *extent_root = fs_info->extent_root;
+	struct btrfs_root *extent_root = btrfs_extent_root(fs_info, bytenr);
 	struct extent_buffer *leaf;
 	struct btrfs_extent_data_ref *ref;
 	struct btrfs_extent_inline_ref *iref;
@@ -2922,7 +2927,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
 	struct btrfs_fs_info *info = trans->fs_info;
 	struct btrfs_key key;
 	struct btrfs_path *path;
-	struct btrfs_root *extent_root = info->extent_root;
+	struct btrfs_root *extent_root;
 	struct extent_buffer *leaf;
 	struct btrfs_extent_item *ei;
 	struct btrfs_extent_inline_ref *iref;
@@ -2938,6 +2943,8 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
 	int last_ref = 0;
 	bool skinny_metadata = btrfs_fs_incompat(info, SKINNY_METADATA);
 
+	extent_root = btrfs_extent_root(info, bytenr);
+
 	path = btrfs_alloc_path();
 	if (!path)
 		return -ENOMEM;
@@ -4572,6 +4579,7 @@ static int alloc_reserved_file_extent(struct btrfs_trans_handle *trans,
 				      struct btrfs_key *ins, int ref_mod)
 {
 	struct btrfs_fs_info *fs_info = trans->fs_info;
+	struct btrfs_root *extent_root;
 	int ret;
 	struct btrfs_extent_item *extent_item;
 	struct btrfs_extent_inline_ref *iref;
@@ -4591,8 +4599,8 @@ static int alloc_reserved_file_extent(struct btrfs_trans_handle *trans,
 	if (!path)
 		return -ENOMEM;
 
-	ret = btrfs_insert_empty_item(trans, fs_info->extent_root, path,
-				      ins, size);
+	extent_root = btrfs_extent_root(fs_info, ins->objectid);
+	ret = btrfs_insert_empty_item(trans, extent_root, path, ins, size);
 	if (ret) {
 		btrfs_free_path(path);
 		return ret;
@@ -4644,6 +4652,7 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
 				     struct btrfs_delayed_extent_op *extent_op)
 {
 	struct btrfs_fs_info *fs_info = trans->fs_info;
+	struct btrfs_root *extent_root;
 	int ret;
 	struct btrfs_extent_item *extent_item;
 	struct btrfs_key extent_key;
@@ -4675,8 +4684,9 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
 	if (!path)
 		return -ENOMEM;
 
-	ret = btrfs_insert_empty_item(trans, fs_info->extent_root, path,
-				      &extent_key, size);
+	extent_root = btrfs_extent_root(fs_info, extent_key.objectid);
+	ret = btrfs_insert_empty_item(trans, extent_root, path, &extent_key,
+				      size);
 	if (ret) {
 		btrfs_free_path(path);
 		return ret;
diff --git a/fs/btrfs/free-space-tree.c b/fs/btrfs/free-space-tree.c
index a33bca94d133..968c79d86d72 100644
--- a/fs/btrfs/free-space-tree.c
+++ b/fs/btrfs/free-space-tree.c
@@ -1046,7 +1046,7 @@ int add_to_free_space_tree(struct btrfs_trans_handle *trans,
 static int populate_free_space_tree(struct btrfs_trans_handle *trans,
 				    struct btrfs_block_group *block_group)
 {
-	struct btrfs_root *extent_root = trans->fs_info->extent_root;
+	struct btrfs_root *extent_root;
 	struct btrfs_path *path, *path2;
 	struct btrfs_key key;
 	u64 start, end;
@@ -1080,6 +1080,7 @@ static int populate_free_space_tree(struct btrfs_trans_handle *trans,
 	key.type = BTRFS_EXTENT_ITEM_KEY;
 	key.offset = 0;
 
+	extent_root = btrfs_extent_root(trans->fs_info, key.objectid);
 	ret = btrfs_search_slot_for_read(extent_root, &key, path, 1, 0);
 	if (ret < 0)
 		goto out_locked;
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
index db680f5be745..be0c6ce3205d 100644
--- a/fs/btrfs/qgroup.c
+++ b/fs/btrfs/qgroup.c
@@ -3141,6 +3141,7 @@ static int qgroup_rescan_leaf(struct btrfs_trans_handle *trans,
 			      struct btrfs_path *path)
 {
 	struct btrfs_fs_info *fs_info = trans->fs_info;
+	struct btrfs_root *extent_root;
 	struct btrfs_key found;
 	struct extent_buffer *scratch_leaf = NULL;
 	struct ulist *roots = NULL;
@@ -3150,7 +3151,9 @@ static int qgroup_rescan_leaf(struct btrfs_trans_handle *trans,
 	int ret;
 
 	mutex_lock(&fs_info->qgroup_rescan_lock);
-	ret = btrfs_search_slot_for_read(fs_info->extent_root,
+	extent_root = btrfs_extent_root(fs_info,
+				fs_info->qgroup_rescan_progress.objectid);
+	ret = btrfs_search_slot_for_read(extent_root,
 					 &fs_info->qgroup_rescan_progress,
 					 path, 1, 0);
 
diff --git a/fs/btrfs/ref-verify.c b/fs/btrfs/ref-verify.c
index e2b9f8616501..a1ee19501030 100644
--- a/fs/btrfs/ref-verify.c
+++ b/fs/btrfs/ref-verify.c
@@ -972,6 +972,7 @@ void btrfs_free_ref_tree_range(struct btrfs_fs_info *fs_info, u64 start,
 /* Walk down all roots and build the ref tree, meant to be called at mount */
 int btrfs_build_ref_tree(struct btrfs_fs_info *fs_info)
 {
+	struct btrfs_root *extent_root;
 	struct btrfs_path *path;
 	struct extent_buffer *eb;
 	int tree_block_level = 0;
@@ -985,7 +986,8 @@ int btrfs_build_ref_tree(struct btrfs_fs_info *fs_info)
 	if (!path)
 		return -ENOMEM;
 
-	eb = btrfs_read_lock_root_node(fs_info->extent_root);
+	extent_root = btrfs_extent_root(fs_info, 0);
+	eb = btrfs_read_lock_root_node(extent_root);
 	level = btrfs_header_level(eb);
 	path->nodes[level] = eb;
 	path->slots[level] = 0;
@@ -998,7 +1000,7 @@ int btrfs_build_ref_tree(struct btrfs_fs_info *fs_info)
 		 * would have had to added a ref key item which may appear on a
 		 * different leaf from the original extent item.
 		 */
-		ret = walk_down_tree(fs_info->extent_root, path, level,
+		ret = walk_down_tree(extent_root, path, level,
 				     &bytenr, &num_bytes, &tree_block_level);
 		if (ret)
 			break;
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index f167ce645016..dc99b4a27d5f 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -3964,7 +3964,7 @@ static const char *stage_to_string(int stage)
 int btrfs_relocate_block_group(struct btrfs_fs_info *fs_info, u64 group_start)
 {
 	struct btrfs_block_group *bg;
-	struct btrfs_root *extent_root = fs_info->extent_root;
+	struct btrfs_root *extent_root = btrfs_extent_root(fs_info, group_start);
 	struct reloc_control *rc;
 	struct inode *inode;
 	struct btrfs_path *path;
@@ -4215,7 +4215,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)
 		goto out_end;
 	}
 
-	rc->extent_root = fs_info->extent_root;
+	rc->extent_root = btrfs_extent_root(fs_info, 0);
 
 	set_reloc_control(rc);
 
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index cf82ea6f54fb..7c272cfd241f 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -2897,7 +2897,7 @@ static noinline_for_stack int scrub_raid56_parity(struct scrub_ctx *sctx,
 						  u64 logic_end)
 {
 	struct btrfs_fs_info *fs_info = sctx->fs_info;
-	struct btrfs_root *root = fs_info->extent_root;
+	struct btrfs_root *root = btrfs_extent_root(fs_info, logic_start);
 	struct btrfs_root *csum_root = fs_info->csum_root;
 	struct btrfs_extent_item *extent;
 	struct btrfs_io_context *bioc = NULL;
@@ -3168,7 +3168,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
 {
 	struct btrfs_path *path, *ppath;
 	struct btrfs_fs_info *fs_info = sctx->fs_info;
-	struct btrfs_root *root = fs_info->extent_root;
+	struct btrfs_root *root;
 	struct btrfs_root *csum_root = fs_info->csum_root;
 	struct btrfs_extent_item *extent;
 	struct blk_plug plug;
@@ -3262,6 +3262,8 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
 		   atomic_read(&sctx->bios_in_flight) == 0);
 	scrub_blocked_if_needed(fs_info);
 
+	root = btrfs_extent_root(fs_info, logical);
+
 	/* FIXME it might be better to start readahead at commit root */
 	key.objectid = logical;
 	key.type = BTRFS_EXTENT_ITEM_KEY;
diff --git a/fs/btrfs/tests/free-space-tests.c b/fs/btrfs/tests/free-space-tests.c
index 8f05c1eb833f..c3709138f7cf 100644
--- a/fs/btrfs/tests/free-space-tests.c
+++ b/fs/btrfs/tests/free-space-tests.c
@@ -858,7 +858,7 @@ int btrfs_test_free_space_cache(u32 sectorsize, u32 nodesize)
 		goto out;
 	}
 
-	root->fs_info->extent_root = root;
+	root->fs_info->_extent_root = root;
 
 	ret = test_extents(cache);
 	if (ret)
diff --git a/fs/btrfs/tests/qgroup-tests.c b/fs/btrfs/tests/qgroup-tests.c
index 19ba7d5b7d8f..88e19781e83f 100644
--- a/fs/btrfs/tests/qgroup-tests.c
+++ b/fs/btrfs/tests/qgroup-tests.c
@@ -455,7 +455,7 @@ int btrfs_test_qgroups(u32 sectorsize, u32 nodesize)
 	}
 
 	/* We are using this root as our extent root */
-	root->fs_info->extent_root = root;
+	root->fs_info->_extent_root = root;
 
 	/*
 	 * Some of the paths we test assume we have a filled out fs_info, so we
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 9f03c727aa6a..f51edfe3681d 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -413,7 +413,7 @@ static int record_root_in_trans(struct btrfs_trans_handle *trans,
 
 	if ((test_bit(BTRFS_ROOT_SHAREABLE, &root->state) &&
 	    root->last_trans < trans->transid) || force) {
-		WARN_ON(root == fs_info->extent_root);
+		WARN_ON(root == fs_info->_extent_root);
 		WARN_ON(!force && root->commit_root != root->node);
 
 		/*
diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c
index 67d932d70798..90d73e4e1827 100644
--- a/fs/btrfs/zoned.c
+++ b/fs/btrfs/zoned.c
@@ -1104,7 +1104,7 @@ static int calculate_alloc_pointer(struct btrfs_block_group *cache,
 				   u64 *offset_ret)
 {
 	struct btrfs_fs_info *fs_info = cache->fs_info;
-	struct btrfs_root *root = fs_info->extent_root;
+	struct btrfs_root *root;
 	struct btrfs_path *path;
 	struct btrfs_key key;
 	struct btrfs_key found_key;
@@ -1119,6 +1119,7 @@ static int calculate_alloc_pointer(struct btrfs_block_group *cache,
 	key.type = 0;
 	key.offset = 0;
 
+	root = btrfs_extent_root(fs_info, key.objectid);
 	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
 	/* We should not find the exact match */
 	if (!ret)
-- 
2.26.3


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

* [PATCH 20/25] btrfs: fix csum assert to check objectid of the root
  2021-11-05 20:45 [PATCH 00/25] btrfs: extent tree v2 prep work for global roots Josef Bacik
                   ` (18 preceding siblings ...)
  2021-11-05 20:45 ` [PATCH 19/25] btrfs: stop accessing ->extent_root directly Josef Bacik
@ 2021-11-05 20:45 ` Josef Bacik
  2021-11-05 20:45 ` [PATCH 21/25] btrfs: set BTRFS_FS_STATE_NO_CSUMS if we fail to load the csum root Josef Bacik
                   ` (4 subsequent siblings)
  24 siblings, 0 replies; 34+ messages in thread
From: Josef Bacik @ 2021-11-05 20:45 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

In the future we may have multiple csum roots, so simply check the
objectid is for a csum root instead of checking against ->csum_root.

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

diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c
index d1cbb64a78f3..359f3a047360 100644
--- a/fs/btrfs/file-item.c
+++ b/fs/btrfs/file-item.c
@@ -801,7 +801,7 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans,
 	const u32 csum_size = fs_info->csum_size;
 	u32 blocksize_bits = fs_info->sectorsize_bits;
 
-	ASSERT(root == fs_info->csum_root ||
+	ASSERT(root->root_key.objectid == BTRFS_CSUM_TREE_OBJECTID ||
 	       root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID);
 
 	path = btrfs_alloc_path();
-- 
2.26.3


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

* [PATCH 21/25] btrfs: set BTRFS_FS_STATE_NO_CSUMS if we fail to load the csum root
  2021-11-05 20:45 [PATCH 00/25] btrfs: extent tree v2 prep work for global roots Josef Bacik
                   ` (19 preceding siblings ...)
  2021-11-05 20:45 ` [PATCH 20/25] btrfs: fix csum assert to check objectid of the root Josef Bacik
@ 2021-11-05 20:45 ` Josef Bacik
  2021-11-25 15:05   ` Nikolay Borisov
  2021-11-05 20:45 ` [PATCH 22/25] btrfs: stop accessing ->csum_root directly Josef Bacik
                   ` (3 subsequent siblings)
  24 siblings, 1 reply; 34+ messages in thread
From: Josef Bacik @ 2021-11-05 20:45 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

We have a few places where we skip doing csums if we mounted with one of
the rescue options that ignores bad csum roots.  In the future when
there are multiple csum roots it'll be costly to check and see if there
are any missing csum roots, so simply add a flag to indicate the fs
should skip loading csums in case of errors.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/compression.c | 3 ++-
 fs/btrfs/ctree.h       | 2 ++
 fs/btrfs/disk-io.c     | 5 +++++
 fs/btrfs/file-item.c   | 3 ++-
 fs/btrfs/inode.c       | 4 ++--
 5 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
index 1d071c8d6fff..a76107d6f7f2 100644
--- a/fs/btrfs/compression.c
+++ b/fs/btrfs/compression.c
@@ -156,7 +156,8 @@ static int check_compressed_csum(struct btrfs_inode *inode, struct bio *bio,
 	struct compressed_bio *cb = bio->bi_private;
 	u8 *cb_sum = cb->sums;
 
-	if (!fs_info->csum_root || (inode->flags & BTRFS_INODE_NODATASUM))
+	if ((inode->flags & BTRFS_INODE_NODATASUM) ||
+	    test_bit(BTRFS_FS_STATE_NO_CSUMS, &fs_info->fs_state))
 		return 0;
 
 	shash->tfm = fs_info->csum_shash;
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index dac5741cb6fa..13bd6fc3901a 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -143,6 +143,8 @@ enum {
 	BTRFS_FS_STATE_DEV_REPLACING,
 	/* The btrfs_fs_info created for self-tests */
 	BTRFS_FS_STATE_DUMMY_FS_INFO,
+
+	BTRFS_FS_STATE_NO_CSUMS,
 };
 
 #define BTRFS_BACKREF_REV_MAX		256
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 1ada4c96ef71..898b4ff83718 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -2475,11 +2475,16 @@ static int btrfs_read_roots(struct btrfs_fs_info *fs_info)
 			if (!btrfs_test_opt(fs_info, IGNOREBADROOTS)) {
 				ret = PTR_ERR(root);
 				goto out;
+			} else {
+				set_bit(BTRFS_FS_STATE_NO_CSUMS,
+					&fs_info->fs_state);
 			}
 		} else {
 			set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state);
 			fs_info->csum_root = root;
 		}
+	} else {
+		set_bit(BTRFS_FS_STATE_NO_CSUMS, &fs_info->fs_state);
 	}
 
 	/*
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c
index 359f3a047360..4904286139bf 100644
--- a/fs/btrfs/file-item.c
+++ b/fs/btrfs/file-item.c
@@ -376,7 +376,8 @@ blk_status_t btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio, u8 *dst
 	const unsigned int nblocks = orig_len >> fs_info->sectorsize_bits;
 	int count = 0;
 
-	if (!fs_info->csum_root || (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM))
+	if ((BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM) ||
+	    test_bit(BTRFS_FS_STATE_NO_CSUMS, &fs_info->fs_state))
 		return BLK_STS_OK;
 
 	/*
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 9e81fd94ab09..6d14dd2cf36e 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -2516,7 +2516,7 @@ blk_status_t btrfs_submit_data_bio(struct inode *inode, struct bio *bio,
 	int async = !atomic_read(&BTRFS_I(inode)->sync_writers);
 
 	skip_sum = (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM) ||
-		   !fs_info->csum_root;
+		test_bit(BTRFS_FS_STATE_NO_CSUMS, &fs_info->fs_state);
 
 	if (btrfs_is_free_space_inode(BTRFS_I(inode)))
 		metadata = BTRFS_WQ_ENDIO_FREE_SPACE;
@@ -3314,7 +3314,7 @@ unsigned int btrfs_verify_data_csum(struct btrfs_bio *bbio,
 	if (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)
 		return 0;
 
-	if (!root->fs_info->csum_root)
+	if (unlikely(test_bit(BTRFS_FS_STATE_NO_CSUMS, &fs_info->fs_state)))
 		return 0;
 
 	ASSERT(page_offset(page) <= start &&
-- 
2.26.3


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

* [PATCH 22/25] btrfs: stop accessing ->csum_root directly
  2021-11-05 20:45 [PATCH 00/25] btrfs: extent tree v2 prep work for global roots Josef Bacik
                   ` (20 preceding siblings ...)
  2021-11-05 20:45 ` [PATCH 21/25] btrfs: set BTRFS_FS_STATE_NO_CSUMS if we fail to load the csum root Josef Bacik
@ 2021-11-05 20:45 ` Josef Bacik
  2021-11-05 20:45 ` [PATCH 23/25] btrfs: stop accessing ->free_space_root directly Josef Bacik
                   ` (2 subsequent siblings)
  24 siblings, 0 replies; 34+ messages in thread
From: Josef Bacik @ 2021-11-05 20:45 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

We are going to have multiple csum roots in the future, so convert all
users of ->csum_root to btrfs_csum_root() and rename ->csum_root to
->_csum_root so we can easily find remaining users in the future.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/block-rsv.c   |  8 +++++---
 fs/btrfs/ctree.h       |  2 +-
 fs/btrfs/disk-io.c     | 15 ++++++++-------
 fs/btrfs/disk-io.h     |  6 ++++++
 fs/btrfs/extent-tree.c | 11 ++++++++---
 fs/btrfs/file-item.c   |  4 +++-
 fs/btrfs/inode.c       | 11 ++++++++---
 fs/btrfs/relocation.c  |  4 +++-
 fs/btrfs/scrub.c       |  7 +++++--
 fs/btrfs/tree-log.c    | 19 +++++++++++++------
 10 files changed, 60 insertions(+), 27 deletions(-)

diff --git a/fs/btrfs/block-rsv.c b/fs/btrfs/block-rsv.c
index 7f5c230ea547..7dcbe901b583 100644
--- a/fs/btrfs/block-rsv.c
+++ b/fs/btrfs/block-rsv.c
@@ -355,6 +355,7 @@ void btrfs_update_global_block_rsv(struct btrfs_fs_info *fs_info)
 	struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv;
 	struct btrfs_space_info *sinfo = block_rsv->space_info;
 	struct btrfs_root *extent_root = btrfs_extent_root(fs_info, 0);
+	struct btrfs_root *csum_root = btrfs_csum_root(fs_info, 0);
 	u64 num_bytes;
 	unsigned min_items;
 
@@ -364,7 +365,7 @@ void btrfs_update_global_block_rsv(struct btrfs_fs_info *fs_info)
 	 * it to a minimal amount for safety.
 	 */
 	num_bytes = btrfs_root_used(&extent_root->root_item) +
-		btrfs_root_used(&fs_info->csum_root->root_item) +
+		btrfs_root_used(&csum_root->root_item) +
 		btrfs_root_used(&fs_info->tree_root->root_item);
 
 	/*
@@ -478,8 +479,9 @@ static struct btrfs_block_rsv *get_block_rsv(
 	struct btrfs_block_rsv *block_rsv = NULL;
 
 	if (test_bit(BTRFS_ROOT_SHAREABLE, &root->state) ||
-	    (root == fs_info->csum_root && trans->adding_csums) ||
-	    (root == fs_info->uuid_root))
+	    (root == fs_info->uuid_root) ||
+	    (trans->adding_csums &&
+	     root->root_key.objectid == BTRFS_CSUM_TREE_OBJECTID))
 		block_rsv = trans->block_rsv;
 
 	if (!block_rsv)
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 13bd6fc3901a..c8bd1abc7b89 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -628,7 +628,7 @@ struct btrfs_fs_info {
 	struct btrfs_root *chunk_root;
 	struct btrfs_root *dev_root;
 	struct btrfs_root *fs_root;
-	struct btrfs_root *csum_root;
+	struct btrfs_root *_csum_root;
 	struct btrfs_root *quota_root;
 	struct btrfs_root *uuid_root;
 	struct btrfs_root *free_space_root;
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 898b4ff83718..b8a92bb6081d 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1563,7 +1563,7 @@ static struct btrfs_root *btrfs_get_global_root(struct btrfs_fs_info *fs_info,
 	if (objectid == BTRFS_DEV_TREE_OBJECTID)
 		return btrfs_grab_root(fs_info->dev_root);
 	if (objectid == BTRFS_CSUM_TREE_OBJECTID)
-		return btrfs_grab_root(fs_info->csum_root);
+		return btrfs_grab_root(fs_info->_csum_root);
 	if (objectid == BTRFS_QUOTA_TREE_OBJECTID)
 		return btrfs_grab_root(fs_info->quota_root) ?
 			fs_info->quota_root : ERR_PTR(-ENOENT);
@@ -1634,7 +1634,7 @@ void btrfs_free_fs_info(struct btrfs_fs_info *fs_info)
 	btrfs_put_root(fs_info->tree_root);
 	btrfs_put_root(fs_info->chunk_root);
 	btrfs_put_root(fs_info->dev_root);
-	btrfs_put_root(fs_info->csum_root);
+	btrfs_put_root(fs_info->_csum_root);
 	btrfs_put_root(fs_info->quota_root);
 	btrfs_put_root(fs_info->uuid_root);
 	btrfs_put_root(fs_info->free_space_root);
@@ -2001,6 +2001,7 @@ static void backup_super_roots(struct btrfs_fs_info *info)
 	const int next_backup = info->backup_root_index;
 	struct btrfs_root_backup *root_backup;
 	struct btrfs_root *extent_root = btrfs_extent_root(info, 0);
+	struct btrfs_root *csum_root = btrfs_csum_root(info, 0);
 
 	root_backup = info->super_for_commit->super_roots + next_backup;
 
@@ -2050,11 +2051,11 @@ static void backup_super_roots(struct btrfs_fs_info *info)
 	btrfs_set_backup_dev_root_level(root_backup,
 				       btrfs_header_level(info->dev_root->node));
 
-	btrfs_set_backup_csum_root(root_backup, info->csum_root->node->start);
+	btrfs_set_backup_csum_root(root_backup, csum_root->node->start);
 	btrfs_set_backup_csum_root_gen(root_backup,
-			       btrfs_header_generation(info->csum_root->node));
+				       btrfs_header_generation(csum_root->node));
 	btrfs_set_backup_csum_root_level(root_backup,
-			       btrfs_header_level(info->csum_root->node));
+					 btrfs_header_level(csum_root->node));
 
 	btrfs_set_backup_total_bytes(root_backup,
 			     btrfs_super_total_bytes(info->super_copy));
@@ -2160,7 +2161,7 @@ static void free_root_pointers(struct btrfs_fs_info *info, bool free_chunk_root)
 
 	free_root_extent_buffers(info->dev_root);
 	free_root_extent_buffers(info->_extent_root);
-	free_root_extent_buffers(info->csum_root);
+	free_root_extent_buffers(info->_csum_root);
 	free_root_extent_buffers(info->quota_root);
 	free_root_extent_buffers(info->uuid_root);
 	free_root_extent_buffers(info->fs_root);
@@ -2481,7 +2482,7 @@ static int btrfs_read_roots(struct btrfs_fs_info *fs_info)
 			}
 		} else {
 			set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state);
-			fs_info->csum_root = root;
+			fs_info->_csum_root = root;
 		}
 	} else {
 		set_bit(BTRFS_FS_STATE_NO_CSUMS, &fs_info->fs_state);
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
index e2824c6ada72..a4d1788acd24 100644
--- a/fs/btrfs/disk-io.h
+++ b/fs/btrfs/disk-io.h
@@ -109,6 +109,12 @@ static inline struct btrfs_root *btrfs_extent_root(struct btrfs_fs_info *fs_info
 	return fs_info->_extent_root;
 }
 
+static inline struct btrfs_root *btrfs_csum_root(struct btrfs_fs_info *fs_info,
+						 u64 bytenr)
+{
+	return fs_info->_csum_root;
+}
+
 static inline struct btrfs_root *btrfs_block_group_root(struct btrfs_fs_info *fs_info)
 {
 	return btrfs_extent_root(fs_info, 0);
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index de80b7109a08..3cf354223e55 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -1851,8 +1851,11 @@ static int cleanup_ref_head(struct btrfs_trans_handle *trans,
 	if (head->must_insert_reserved) {
 		btrfs_pin_extent(trans, head->bytenr, head->num_bytes, 1);
 		if (head->is_data) {
-			ret = btrfs_del_csums(trans, fs_info->csum_root,
-					      head->bytenr, head->num_bytes);
+			struct btrfs_root *csum_root;
+
+			csum_root = btrfs_csum_root(fs_info, head->bytenr);
+			ret = btrfs_del_csums(trans, csum_root, head->bytenr,
+					      head->num_bytes);
 		}
 	}
 
@@ -3188,7 +3191,9 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
 		btrfs_release_path(path);
 
 		if (is_data) {
-			ret = btrfs_del_csums(trans, info->csum_root, bytenr,
+			struct btrfs_root *csum_root;
+			csum_root = btrfs_csum_root(info, bytenr);
+			ret = btrfs_del_csums(trans, csum_root, bytenr,
 					      num_bytes);
 			if (ret) {
 				btrfs_abort_transaction(trans, ret);
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c
index 4904286139bf..be2bd13b34e0 100644
--- a/fs/btrfs/file-item.c
+++ b/fs/btrfs/file-item.c
@@ -257,6 +257,7 @@ static int search_csum_tree(struct btrfs_fs_info *fs_info,
 			    struct btrfs_path *path, u64 disk_bytenr,
 			    u64 len, u8 *dst)
 {
+	struct btrfs_root *csum_root;
 	struct btrfs_csum_item *item = NULL;
 	struct btrfs_key key;
 	const u32 sectorsize = fs_info->sectorsize;
@@ -285,7 +286,8 @@ static int search_csum_tree(struct btrfs_fs_info *fs_info,
 
 	/* Current item doesn't contain the desired range, search again */
 	btrfs_release_path(path);
-	item = btrfs_lookup_csum(NULL, fs_info->csum_root, path, disk_bytenr, 0);
+	csum_root = btrfs_csum_root(fs_info, disk_bytenr);
+	item = btrfs_lookup_csum(NULL, csum_root, path, disk_bytenr, 0);
 	if (IS_ERR(item)) {
 		ret = PTR_ERR(item);
 		goto out;
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 6d14dd2cf36e..613b4dd13aec 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -1530,11 +1530,12 @@ static noinline int run_delalloc_zoned(struct btrfs_inode *inode,
 static noinline int csum_exist_in_range(struct btrfs_fs_info *fs_info,
 					u64 bytenr, u64 num_bytes)
 {
-	int ret;
+	struct btrfs_root *csum_root = btrfs_csum_root(fs_info, bytenr);
 	struct btrfs_ordered_sum *sums;
+	int ret;
 	LIST_HEAD(list);
 
-	ret = btrfs_lookup_csums_range(fs_info->csum_root, bytenr,
+	ret = btrfs_lookup_csums_range(csum_root, bytenr,
 				       bytenr + num_bytes - 1, &list, 0);
 	if (ret == 0 && list_empty(&list))
 		return 0;
@@ -2584,11 +2585,15 @@ static int add_pending_csums(struct btrfs_trans_handle *trans,
 			     struct list_head *list)
 {
 	struct btrfs_ordered_sum *sum;
+	struct btrfs_root *csum_root = NULL;
 	int ret;
 
 	list_for_each_entry(sum, list, list) {
 		trans->adding_csums = true;
-		ret = btrfs_csum_file_blocks(trans, trans->fs_info->csum_root, sum);
+		if (!csum_root)
+			csum_root = btrfs_csum_root(trans->fs_info,
+						    sum->bytenr);
+		ret = btrfs_csum_file_blocks(trans, csum_root, sum);
 		trans->adding_csums = false;
 		if (ret)
 			return ret;
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index dc99b4a27d5f..1bbe15dfb496 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -4306,6 +4306,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)
 int btrfs_reloc_clone_csums(struct btrfs_inode *inode, u64 file_pos, u64 len)
 {
 	struct btrfs_fs_info *fs_info = inode->root->fs_info;
+	struct btrfs_root *csum_root;
 	struct btrfs_ordered_sum *sums;
 	struct btrfs_ordered_extent *ordered;
 	int ret;
@@ -4317,7 +4318,8 @@ int btrfs_reloc_clone_csums(struct btrfs_inode *inode, u64 file_pos, u64 len)
 	BUG_ON(ordered->file_offset != file_pos || ordered->num_bytes != len);
 
 	disk_bytenr = file_pos + inode->index_cnt;
-	ret = btrfs_lookup_csums_range(fs_info->csum_root, disk_bytenr,
+	csum_root = btrfs_csum_root(fs_info, disk_bytenr);
+	ret = btrfs_lookup_csums_range(csum_root, disk_bytenr,
 				       disk_bytenr + len - 1, &list, 0);
 	if (ret)
 		goto out;
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index 7c272cfd241f..6b0ee1b17ae5 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -2898,7 +2898,7 @@ static noinline_for_stack int scrub_raid56_parity(struct scrub_ctx *sctx,
 {
 	struct btrfs_fs_info *fs_info = sctx->fs_info;
 	struct btrfs_root *root = btrfs_extent_root(fs_info, logic_start);
-	struct btrfs_root *csum_root = fs_info->csum_root;
+	struct btrfs_root *csum_root;
 	struct btrfs_extent_item *extent;
 	struct btrfs_io_context *bioc = NULL;
 	u64 flags;
@@ -3060,6 +3060,7 @@ static noinline_for_stack int scrub_raid56_parity(struct scrub_ctx *sctx,
 			extent_dev = bioc->stripes[0].dev;
 			btrfs_put_bioc(bioc);
 
+			csum_root = btrfs_csum_root(fs_info, extent_logical);
 			ret = btrfs_lookup_csums_range(csum_root,
 						extent_logical,
 						extent_logical + extent_len - 1,
@@ -3169,7 +3170,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
 	struct btrfs_path *path, *ppath;
 	struct btrfs_fs_info *fs_info = sctx->fs_info;
 	struct btrfs_root *root;
-	struct btrfs_root *csum_root = fs_info->csum_root;
+	struct btrfs_root *csum_root;
 	struct btrfs_extent_item *extent;
 	struct blk_plug plug;
 	u64 flags;
@@ -3273,6 +3274,8 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
 	key_end.offset = (u64)-1;
 	reada1 = btrfs_reada_add(root, &key, &key_end);
 
+	csum_root = btrfs_csum_root(fs_info, logical);
+
 	if (cache->flags & BTRFS_BLOCK_GROUP_DATA) {
 		key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
 		key.type = BTRFS_EXTENT_CSUM_KEY;
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 8ab33caf016f..3dcee69299c4 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -872,17 +872,21 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans,
 			 */
 			while (!list_empty(&ordered_sums)) {
 				struct btrfs_ordered_sum *sums;
+				struct btrfs_root *csum_root;
+
 				sums = list_entry(ordered_sums.next,
 						struct btrfs_ordered_sum,
 						list);
+				csum_root = btrfs_csum_root(fs_info,
+							    sums->bytenr);
 				if (!ret)
-					ret = btrfs_del_csums(trans,
-							      fs_info->csum_root,
+					ret = btrfs_del_csums(trans, csum_root,
 							      sums->bytenr,
 							      sums->len);
 				if (!ret)
 					ret = btrfs_csum_file_blocks(trans,
-						fs_info->csum_root, sums);
+								     csum_root,
+								     sums);
 				list_del(&sums->list);
 				kfree(sums);
 			}
@@ -4391,6 +4395,7 @@ static noinline int copy_items(struct btrfs_trans_handle *trans,
 
 			found_type = btrfs_file_extent_type(src, extent);
 			if (found_type == BTRFS_FILE_EXTENT_REG) {
+				struct btrfs_root *csum_root;
 				u64 ds, dl, cs, cl;
 				ds = btrfs_file_extent_disk_bytenr(src,
 								extent);
@@ -4409,8 +4414,8 @@ static noinline int copy_items(struct btrfs_trans_handle *trans,
 					cl = dl;
 				}
 
-				ret = btrfs_lookup_csums_range(
-						fs_info->csum_root,
+				csum_root = btrfs_csum_root(fs_info, ds);
+				ret = btrfs_lookup_csums_range(csum_root,
 						ds + cs, ds + cs + cl - 1,
 						&ordered_sums, 0);
 				if (ret)
@@ -4462,6 +4467,7 @@ static int log_extent_csums(struct btrfs_trans_handle *trans,
 			    struct btrfs_log_ctx *ctx)
 {
 	struct btrfs_ordered_extent *ordered;
+	struct btrfs_root *csum_root;
 	u64 csum_offset;
 	u64 csum_len;
 	u64 mod_start = em->mod_start;
@@ -4542,7 +4548,8 @@ static int log_extent_csums(struct btrfs_trans_handle *trans,
 	}
 
 	/* block start is already adjusted for the file extent offset. */
-	ret = btrfs_lookup_csums_range(trans->fs_info->csum_root,
+	csum_root = btrfs_csum_root(trans->fs_info, em->block_start);
+	ret = btrfs_lookup_csums_range(csum_root,
 				       em->block_start + csum_offset,
 				       em->block_start + csum_offset +
 				       csum_len - 1, &ordered_sums, 0);
-- 
2.26.3


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

* [PATCH 23/25] btrfs: stop accessing ->free_space_root directly
  2021-11-05 20:45 [PATCH 00/25] btrfs: extent tree v2 prep work for global roots Josef Bacik
                   ` (21 preceding siblings ...)
  2021-11-05 20:45 ` [PATCH 22/25] btrfs: stop accessing ->csum_root directly Josef Bacik
@ 2021-11-05 20:45 ` Josef Bacik
  2021-11-05 20:45 ` [PATCH 24/25] btrfs: remove useless WARN_ON in record_root_in_trans Josef Bacik
  2021-11-05 20:45 ` [PATCH 25/25] btrfs: track the csum, extent, and free space trees in a rb tree Josef Bacik
  24 siblings, 0 replies; 34+ messages in thread
From: Josef Bacik @ 2021-11-05 20:45 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

We're going to have multiple free space roots in the future, so adjust
all the users of the free space root to use a helper to access the root.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/ctree.h                       |  2 +-
 fs/btrfs/disk-io.c                     | 10 ++++----
 fs/btrfs/free-space-tree.c             | 32 +++++++++++++++-----------
 fs/btrfs/tests/free-space-tree-tests.c |  2 +-
 4 files changed, 26 insertions(+), 20 deletions(-)

diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index c8bd1abc7b89..773a45470610 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -631,7 +631,7 @@ struct btrfs_fs_info {
 	struct btrfs_root *_csum_root;
 	struct btrfs_root *quota_root;
 	struct btrfs_root *uuid_root;
-	struct btrfs_root *free_space_root;
+	struct btrfs_root *_free_space_root;
 	struct btrfs_root *data_reloc_root;
 
 	/* the log root tree is a directory of all the other log roots */
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index b8a92bb6081d..b0efc9ca9eaa 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1571,8 +1571,8 @@ static struct btrfs_root *btrfs_get_global_root(struct btrfs_fs_info *fs_info,
 		return btrfs_grab_root(fs_info->uuid_root) ?
 			fs_info->uuid_root : ERR_PTR(-ENOENT);
 	if (objectid == BTRFS_FREE_SPACE_TREE_OBJECTID)
-		return btrfs_grab_root(fs_info->free_space_root) ?
-			fs_info->free_space_root : ERR_PTR(-ENOENT);
+		return btrfs_grab_root(fs_info->_free_space_root) ?
+			fs_info->_free_space_root : ERR_PTR(-ENOENT);
 	return NULL;
 }
 
@@ -1637,7 +1637,7 @@ void btrfs_free_fs_info(struct btrfs_fs_info *fs_info)
 	btrfs_put_root(fs_info->_csum_root);
 	btrfs_put_root(fs_info->quota_root);
 	btrfs_put_root(fs_info->uuid_root);
-	btrfs_put_root(fs_info->free_space_root);
+	btrfs_put_root(fs_info->_free_space_root);
 	btrfs_put_root(fs_info->fs_root);
 	btrfs_put_root(fs_info->data_reloc_root);
 	btrfs_check_leaked_roots(fs_info);
@@ -2168,7 +2168,7 @@ static void free_root_pointers(struct btrfs_fs_info *info, bool free_chunk_root)
 	free_root_extent_buffers(info->data_reloc_root);
 	if (free_chunk_root)
 		free_root_extent_buffers(info->chunk_root);
-	free_root_extent_buffers(info->free_space_root);
+	free_root_extent_buffers(info->_free_space_root);
 }
 
 void btrfs_put_root(struct btrfs_root *root)
@@ -2535,7 +2535,7 @@ static int btrfs_read_roots(struct btrfs_fs_info *fs_info)
 			}
 		}  else {
 			set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state);
-			fs_info->free_space_root = root;
+			fs_info->_free_space_root = root;
 		}
 	}
 
diff --git a/fs/btrfs/free-space-tree.c b/fs/btrfs/free-space-tree.c
index 968c79d86d72..c0f0ba66b5ae 100644
--- a/fs/btrfs/free-space-tree.c
+++ b/fs/btrfs/free-space-tree.c
@@ -16,6 +16,12 @@ static int __add_block_group_free_space(struct btrfs_trans_handle *trans,
 					struct btrfs_block_group *block_group,
 					struct btrfs_path *path);
 
+static struct btrfs_root *btrfs_free_space_root(
+				struct btrfs_block_group *block_group)
+{
+	return block_group->fs_info->_free_space_root;
+}
+
 void set_free_space_tree_thresholds(struct btrfs_block_group *cache)
 {
 	u32 bitmap_range;
@@ -51,7 +57,7 @@ static int add_new_free_space_info(struct btrfs_trans_handle *trans,
 				   struct btrfs_block_group *block_group,
 				   struct btrfs_path *path)
 {
-	struct btrfs_root *root = trans->fs_info->free_space_root;
+	struct btrfs_root *root = btrfs_free_space_root(block_group);
 	struct btrfs_free_space_info *info;
 	struct btrfs_key key;
 	struct extent_buffer *leaf;
@@ -85,7 +91,7 @@ struct btrfs_free_space_info *search_free_space_info(
 		struct btrfs_path *path, int cow)
 {
 	struct btrfs_fs_info *fs_info = block_group->fs_info;
-	struct btrfs_root *root = fs_info->free_space_root;
+	struct btrfs_root *root = btrfs_free_space_root(block_group);
 	struct btrfs_key key;
 	int ret;
 
@@ -188,7 +194,7 @@ int convert_free_space_to_bitmaps(struct btrfs_trans_handle *trans,
 				  struct btrfs_path *path)
 {
 	struct btrfs_fs_info *fs_info = trans->fs_info;
-	struct btrfs_root *root = fs_info->free_space_root;
+	struct btrfs_root *root = btrfs_free_space_root(block_group);
 	struct btrfs_free_space_info *info;
 	struct btrfs_key key, found_key;
 	struct extent_buffer *leaf;
@@ -326,7 +332,7 @@ int convert_free_space_to_extents(struct btrfs_trans_handle *trans,
 				  struct btrfs_path *path)
 {
 	struct btrfs_fs_info *fs_info = trans->fs_info;
-	struct btrfs_root *root = fs_info->free_space_root;
+	struct btrfs_root *root = btrfs_free_space_root(block_group);
 	struct btrfs_free_space_info *info;
 	struct btrfs_key key, found_key;
 	struct extent_buffer *leaf;
@@ -586,7 +592,7 @@ static int modify_free_space_bitmap(struct btrfs_trans_handle *trans,
 				    struct btrfs_path *path,
 				    u64 start, u64 size, int remove)
 {
-	struct btrfs_root *root = block_group->fs_info->free_space_root;
+	struct btrfs_root *root = btrfs_free_space_root(block_group);
 	struct btrfs_key key;
 	u64 end = start + size;
 	u64 cur_start, cur_size;
@@ -699,7 +705,7 @@ static int remove_free_space_extent(struct btrfs_trans_handle *trans,
 				    struct btrfs_path *path,
 				    u64 start, u64 size)
 {
-	struct btrfs_root *root = trans->fs_info->free_space_root;
+	struct btrfs_root *root = btrfs_free_space_root(block_group);
 	struct btrfs_key key;
 	u64 found_start, found_end;
 	u64 end = start + size;
@@ -851,7 +857,7 @@ static int add_free_space_extent(struct btrfs_trans_handle *trans,
 				 struct btrfs_path *path,
 				 u64 start, u64 size)
 {
-	struct btrfs_root *root = trans->fs_info->free_space_root;
+	struct btrfs_root *root = btrfs_free_space_root(block_group);
 	struct btrfs_key key, new_key;
 	u64 found_start, found_end;
 	u64 end = start + size;
@@ -1158,7 +1164,7 @@ int btrfs_create_free_space_tree(struct btrfs_fs_info *fs_info)
 		ret = PTR_ERR(free_space_root);
 		goto abort;
 	}
-	fs_info->free_space_root = free_space_root;
+	fs_info->_free_space_root = free_space_root;
 
 	node = rb_first(&fs_info->block_group_cache_tree);
 	while (node) {
@@ -1233,7 +1239,7 @@ int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info)
 {
 	struct btrfs_trans_handle *trans;
 	struct btrfs_root *tree_root = fs_info->tree_root;
-	struct btrfs_root *free_space_root = fs_info->free_space_root;
+	struct btrfs_root *free_space_root = fs_info->_free_space_root;
 	int ret;
 
 	trans = btrfs_start_transaction(tree_root, 0);
@@ -1242,7 +1248,7 @@ int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info)
 
 	btrfs_clear_fs_compat_ro(fs_info, FREE_SPACE_TREE);
 	btrfs_clear_fs_compat_ro(fs_info, FREE_SPACE_TREE_VALID);
-	fs_info->free_space_root = NULL;
+	fs_info->_free_space_root = NULL;
 
 	ret = clear_free_space_tree(trans, free_space_root);
 	if (ret)
@@ -1320,7 +1326,7 @@ int add_block_group_free_space(struct btrfs_trans_handle *trans,
 int remove_block_group_free_space(struct btrfs_trans_handle *trans,
 				  struct btrfs_block_group *block_group)
 {
-	struct btrfs_root *root = trans->fs_info->free_space_root;
+	struct btrfs_root *root = btrfs_free_space_root(block_group);
 	struct btrfs_path *path;
 	struct btrfs_key key, found_key;
 	struct extent_buffer *leaf;
@@ -1411,7 +1417,7 @@ static int load_free_space_bitmaps(struct btrfs_caching_control *caching_ctl,
 
 	block_group = caching_ctl->block_group;
 	fs_info = block_group->fs_info;
-	root = fs_info->free_space_root;
+	root = btrfs_free_space_root(block_group);
 
 	end = block_group->start + block_group->length;
 
@@ -1489,7 +1495,7 @@ static int load_free_space_extents(struct btrfs_caching_control *caching_ctl,
 
 	block_group = caching_ctl->block_group;
 	fs_info = block_group->fs_info;
-	root = fs_info->free_space_root;
+	root = btrfs_free_space_root(block_group);
 
 	end = block_group->start + block_group->length;
 
diff --git a/fs/btrfs/tests/free-space-tree-tests.c b/fs/btrfs/tests/free-space-tree-tests.c
index 2c783d2f5228..7d6de8b53038 100644
--- a/fs/btrfs/tests/free-space-tree-tests.c
+++ b/fs/btrfs/tests/free-space-tree-tests.c
@@ -446,7 +446,7 @@ static int run_test(test_func_t test_func, int bitmaps, u32 sectorsize,
 
 	btrfs_set_super_compat_ro_flags(root->fs_info->super_copy,
 					BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE);
-	root->fs_info->free_space_root = root;
+	root->fs_info->_free_space_root = root;
 	root->fs_info->tree_root = root;
 
 	root->node = alloc_test_extent_buffer(root->fs_info, nodesize);
-- 
2.26.3


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

* [PATCH 24/25] btrfs: remove useless WARN_ON in record_root_in_trans
  2021-11-05 20:45 [PATCH 00/25] btrfs: extent tree v2 prep work for global roots Josef Bacik
                   ` (22 preceding siblings ...)
  2021-11-05 20:45 ` [PATCH 23/25] btrfs: stop accessing ->free_space_root directly Josef Bacik
@ 2021-11-05 20:45 ` Josef Bacik
  2021-11-05 20:45 ` [PATCH 25/25] btrfs: track the csum, extent, and free space trees in a rb tree Josef Bacik
  24 siblings, 0 replies; 34+ messages in thread
From: Josef Bacik @ 2021-11-05 20:45 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

We don't set SHAREABLE on the extent root, we don't need to have this
safety check here.

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

diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index f51edfe3681d..ba8dd90ac3ce 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -413,7 +413,6 @@ static int record_root_in_trans(struct btrfs_trans_handle *trans,
 
 	if ((test_bit(BTRFS_ROOT_SHAREABLE, &root->state) &&
 	    root->last_trans < trans->transid) || force) {
-		WARN_ON(root == fs_info->_extent_root);
 		WARN_ON(!force && root->commit_root != root->node);
 
 		/*
-- 
2.26.3


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

* [PATCH 25/25] btrfs: track the csum, extent, and free space trees in a rb tree
  2021-11-05 20:45 [PATCH 00/25] btrfs: extent tree v2 prep work for global roots Josef Bacik
                   ` (23 preceding siblings ...)
  2021-11-05 20:45 ` [PATCH 24/25] btrfs: remove useless WARN_ON in record_root_in_trans Josef Bacik
@ 2021-11-05 20:45 ` Josef Bacik
  2021-11-18 12:22   ` David Sterba
  24 siblings, 1 reply; 34+ messages in thread
From: Josef Bacik @ 2021-11-05 20:45 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

In the future we are going to have multiple copies of these trees.  To
facilitate this we need a way to lookup the different roots we are
looking for.  Handle this by adding a global root rb tree that is
indexed on the root->root_key.  Then instead of loading the roots at
mount time with individually targeted keys, simply search the tree_root
for anything with the specific objectid we want.  This will make it
straightforward to support both old style and new style file systems.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/ctree.h                       |   9 +-
 fs/btrfs/disk-io.c                     | 276 +++++++++++++++++++------
 fs/btrfs/disk-io.h                     |  20 +-
 fs/btrfs/extent-tree.c                 |   1 +
 fs/btrfs/free-space-tree.c             |  22 +-
 fs/btrfs/tests/btrfs-tests.c           |   1 +
 fs/btrfs/tests/free-space-tests.c      |   5 +-
 fs/btrfs/tests/free-space-tree-tests.c |   5 +-
 fs/btrfs/tests/qgroup-tests.c          |   5 +-
 9 files changed, 264 insertions(+), 80 deletions(-)

diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 773a45470610..d32aa0fe1415 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -623,20 +623,21 @@ enum btrfs_exclusive_operation {
 struct btrfs_fs_info {
 	u8 chunk_tree_uuid[BTRFS_UUID_SIZE];
 	unsigned long flags;
-	struct btrfs_root *_extent_root;
 	struct btrfs_root *tree_root;
 	struct btrfs_root *chunk_root;
 	struct btrfs_root *dev_root;
 	struct btrfs_root *fs_root;
-	struct btrfs_root *_csum_root;
 	struct btrfs_root *quota_root;
 	struct btrfs_root *uuid_root;
-	struct btrfs_root *_free_space_root;
 	struct btrfs_root *data_reloc_root;
 
 	/* the log root tree is a directory of all the other log roots */
 	struct btrfs_root *log_root_tree;
 
+	/* The tree that holds the global roots (csum, extent, etc) */
+	rwlock_t global_root_lock;
+	struct rb_root global_root_tree;
+
 	spinlock_t fs_roots_radix_lock;
 	struct radix_tree_root fs_roots_radix;
 
@@ -1129,6 +1130,8 @@ struct btrfs_qgroup_swapped_blocks {
  * and for the extent tree extent_root root.
  */
 struct btrfs_root {
+	struct rb_node rb_node;
+
 	struct extent_buffer *node;
 
 	struct extent_buffer *commit_root;
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index b0efc9ca9eaa..2a80b9b6d52d 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1149,6 +1149,7 @@ static void __setup_root(struct btrfs_root *root, struct btrfs_fs_info *fs_info,
 	root->node = NULL;
 	root->commit_root = NULL;
 	root->state = 0;
+	RB_CLEAR_NODE(&root->rb_node);
 
 	root->last_trans = 0;
 	root->free_objectid = 0;
@@ -1242,6 +1243,82 @@ struct btrfs_root *btrfs_alloc_dummy_root(struct btrfs_fs_info *fs_info)
 }
 #endif
 
+static int global_root_cmp(struct rb_node *a_node, const struct rb_node *b_node)
+{
+	struct btrfs_root *a = rb_entry(a_node, struct btrfs_root, rb_node);
+	struct btrfs_root *b = rb_entry(b_node, struct btrfs_root, rb_node);
+	return btrfs_comp_cpu_keys(&a->root_key, &b->root_key);
+}
+
+static int global_root_key_cmp(const void *k, const struct rb_node *node)
+{
+	struct btrfs_key *key = (struct btrfs_key *)k;
+	struct btrfs_root *root = rb_entry(node, struct btrfs_root, rb_node);
+	return btrfs_comp_cpu_keys(key, &root->root_key);
+}
+
+int btrfs_global_root_insert(struct btrfs_root *root)
+{
+	struct btrfs_fs_info *fs_info = root->fs_info;
+	struct rb_node *tmp;
+
+	write_lock(&fs_info->global_root_lock);
+	tmp = rb_find_add(&root->rb_node, &fs_info->global_root_tree,
+			  global_root_cmp);
+	write_unlock(&fs_info->global_root_lock);
+	ASSERT(!tmp);
+
+	return tmp ? -EEXIST : 0;
+}
+
+void btrfs_global_root_delete(struct btrfs_root *root)
+{
+	struct btrfs_fs_info *fs_info = root->fs_info;
+
+	write_lock(&fs_info->global_root_lock);
+	rb_erase(&root->rb_node, &fs_info->global_root_tree);
+	write_unlock(&fs_info->global_root_lock);
+}
+
+struct btrfs_root *btrfs_global_root(struct btrfs_fs_info *fs_info,
+				     struct btrfs_key *key)
+{
+	struct rb_node *node;
+	struct btrfs_root *root = NULL;
+
+	read_lock(&fs_info->global_root_lock);
+	node = rb_find(key, &fs_info->global_root_tree, global_root_key_cmp);
+	if (node)
+		root = container_of(node, struct btrfs_root, rb_node);
+	read_unlock(&fs_info->global_root_lock);
+
+	return root;
+}
+
+struct btrfs_root *btrfs_csum_root(struct btrfs_fs_info *fs_info,
+				   u64 bytenr)
+{
+	struct btrfs_key key = {
+		.objectid = BTRFS_CSUM_TREE_OBJECTID,
+		.type = BTRFS_ROOT_ITEM_KEY,
+		.offset = 0,
+	};
+
+	return btrfs_global_root(fs_info, &key);
+}
+
+struct btrfs_root *btrfs_extent_root(struct btrfs_fs_info *fs_info,
+				     u64 bytenr)
+{
+	struct btrfs_key key = {
+		.objectid = BTRFS_EXTENT_TREE_OBJECTID,
+		.type = BTRFS_ROOT_ITEM_KEY,
+		.offset = 0,
+	};
+
+	return btrfs_global_root(fs_info, &key);
+}
+
 struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans,
 				     u64 objectid)
 {
@@ -1554,25 +1631,31 @@ static struct btrfs_root *btrfs_lookup_fs_root(struct btrfs_fs_info *fs_info,
 static struct btrfs_root *btrfs_get_global_root(struct btrfs_fs_info *fs_info,
 						u64 objectid)
 {
+	struct btrfs_key key = {
+		.objectid = objectid,
+		.type = BTRFS_ROOT_ITEM_KEY,
+		.offset = 0,
+	};
 	if (objectid == BTRFS_ROOT_TREE_OBJECTID)
 		return btrfs_grab_root(fs_info->tree_root);
 	if (objectid == BTRFS_EXTENT_TREE_OBJECTID)
-		return btrfs_grab_root(fs_info->_extent_root);
+		return btrfs_grab_root(btrfs_global_root(fs_info, &key));
 	if (objectid == BTRFS_CHUNK_TREE_OBJECTID)
 		return btrfs_grab_root(fs_info->chunk_root);
 	if (objectid == BTRFS_DEV_TREE_OBJECTID)
 		return btrfs_grab_root(fs_info->dev_root);
 	if (objectid == BTRFS_CSUM_TREE_OBJECTID)
-		return btrfs_grab_root(fs_info->_csum_root);
+		return btrfs_grab_root(btrfs_global_root(fs_info, &key));
 	if (objectid == BTRFS_QUOTA_TREE_OBJECTID)
 		return btrfs_grab_root(fs_info->quota_root) ?
 			fs_info->quota_root : ERR_PTR(-ENOENT);
 	if (objectid == BTRFS_UUID_TREE_OBJECTID)
 		return btrfs_grab_root(fs_info->uuid_root) ?
 			fs_info->uuid_root : ERR_PTR(-ENOENT);
-	if (objectid == BTRFS_FREE_SPACE_TREE_OBJECTID)
-		return btrfs_grab_root(fs_info->_free_space_root) ?
-			fs_info->_free_space_root : ERR_PTR(-ENOENT);
+	if (objectid == BTRFS_FREE_SPACE_TREE_OBJECTID) {
+		struct btrfs_root *root = btrfs_global_root(fs_info, &key);
+		return btrfs_grab_root(root) ? root : ERR_PTR(-ENOENT);
+	}
 	return NULL;
 }
 
@@ -1619,6 +1702,18 @@ void btrfs_check_leaked_roots(struct btrfs_fs_info *fs_info)
 #endif
 }
 
+static void free_global_roots(struct btrfs_fs_info *fs_info)
+{
+	struct btrfs_root *root;
+	struct rb_node *n;
+
+	while ((n = rb_first_postorder(&fs_info->global_root_tree)) != NULL) {
+		root = rb_entry(n, struct btrfs_root, rb_node);
+		rb_erase(&root->rb_node, &fs_info->global_root_tree);
+		btrfs_put_root(root);
+	}
+}
+
 void btrfs_free_fs_info(struct btrfs_fs_info *fs_info)
 {
 	percpu_counter_destroy(&fs_info->dirty_metadata_bytes);
@@ -1630,14 +1725,12 @@ void btrfs_free_fs_info(struct btrfs_fs_info *fs_info)
 	btrfs_free_ref_cache(fs_info);
 	kfree(fs_info->balance_ctl);
 	kfree(fs_info->delayed_root);
-	btrfs_put_root(fs_info->_extent_root);
+	free_global_roots(fs_info);
 	btrfs_put_root(fs_info->tree_root);
 	btrfs_put_root(fs_info->chunk_root);
 	btrfs_put_root(fs_info->dev_root);
-	btrfs_put_root(fs_info->_csum_root);
 	btrfs_put_root(fs_info->quota_root);
 	btrfs_put_root(fs_info->uuid_root);
-	btrfs_put_root(fs_info->_free_space_root);
 	btrfs_put_root(fs_info->fs_root);
 	btrfs_put_root(fs_info->data_reloc_root);
 	btrfs_check_leaked_roots(fs_info);
@@ -2154,21 +2247,29 @@ static void free_root_extent_buffers(struct btrfs_root *root)
 	}
 }
 
+static void free_global_root_pointers(struct btrfs_fs_info *fs_info)
+{
+	struct btrfs_root *root, *tmp;
+
+	rbtree_postorder_for_each_entry_safe(root, tmp,
+					     &fs_info->global_root_tree,
+					     rb_node)
+		free_root_extent_buffers(root);
+}
+
 /* helper to cleanup tree roots */
 static void free_root_pointers(struct btrfs_fs_info *info, bool free_chunk_root)
 {
 	free_root_extent_buffers(info->tree_root);
 
+	free_global_root_pointers(info);
 	free_root_extent_buffers(info->dev_root);
-	free_root_extent_buffers(info->_extent_root);
-	free_root_extent_buffers(info->_csum_root);
 	free_root_extent_buffers(info->quota_root);
 	free_root_extent_buffers(info->uuid_root);
 	free_root_extent_buffers(info->fs_root);
 	free_root_extent_buffers(info->data_reloc_root);
 	if (free_chunk_root)
 		free_root_extent_buffers(info->chunk_root);
-	free_root_extent_buffers(info->_free_space_root);
 }
 
 void btrfs_put_root(struct btrfs_root *root)
@@ -2430,6 +2531,105 @@ static int btrfs_replay_log(struct btrfs_fs_info *fs_info,
 	return 0;
 }
 
+static int load_global_roots_objectid(struct btrfs_root *tree_root,
+				      struct btrfs_path *path, u64 objectid,
+				      const char *name)
+{
+	struct btrfs_fs_info *fs_info = tree_root->fs_info;
+	struct btrfs_root *root;
+	int ret;
+	struct btrfs_key key = {
+		.objectid = objectid,
+		.type = BTRFS_ROOT_ITEM_KEY,
+		.offset = 0,
+	};
+	bool found = false;
+
+	/* If we have IGNOREDATACSUMS skip loading these roots. */
+	if (objectid == BTRFS_CSUM_TREE_OBJECTID &&
+	    btrfs_test_opt(fs_info, IGNOREDATACSUMS)) {
+		set_bit(BTRFS_FS_STATE_NO_CSUMS, &fs_info->fs_state);
+		return 0;
+	}
+
+	while (1) {
+		ret = btrfs_search_slot(NULL, tree_root, &key, path, 0, 0);
+		if (ret < 0)
+			break;
+
+		if (path->slots[0] >= btrfs_header_nritems(path->nodes[0])) {
+			ret = btrfs_next_leaf(tree_root, path);
+			if (ret) {
+				if (ret > 0)
+					ret = 0;
+				break;
+			}
+		}
+		ret = 0;
+
+		btrfs_item_key_to_cpu(path->nodes[0], &key,
+				      path->slots[0]);
+		if (key.objectid != objectid)
+			break;
+		btrfs_release_path(path);
+
+		found = true;
+		root = read_tree_root_path(tree_root, path, &key);
+		if (IS_ERR(root)) {
+			if (!btrfs_test_opt(fs_info, IGNOREBADROOTS))
+				ret = PTR_ERR(root);
+			break;
+		}
+		set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state);
+		ret = btrfs_global_root_insert(root);
+		if (ret) {
+			btrfs_put_root(root);
+			break;
+		}
+		key.offset++;
+	}
+	btrfs_release_path(path);
+
+	if (!found || ret) {
+		if (objectid == BTRFS_CSUM_TREE_OBJECTID)
+			set_bit(BTRFS_FS_STATE_NO_CSUMS, &fs_info->fs_state);
+
+		if (!btrfs_test_opt(fs_info, IGNOREBADROOTS))
+			ret = ret ? ret : -ENOENT;
+		else
+			ret = 0;
+		btrfs_err(fs_info, "failed to load root %s", name);
+	}
+	return ret;
+}
+
+static int load_global_roots(struct btrfs_root *tree_root)
+{
+	struct btrfs_path *path;
+	int ret = 0;
+
+	path = btrfs_alloc_path();
+	if (!path)
+		return -ENOMEM;
+
+	ret = load_global_roots_objectid(tree_root, path,
+					 BTRFS_EXTENT_TREE_OBJECTID, "extent");
+	if (ret)
+		goto out;
+	ret = load_global_roots_objectid(tree_root, path,
+					 BTRFS_CSUM_TREE_OBJECTID, "csum");
+	if (ret)
+		goto out;
+	if (!btrfs_fs_compat_ro(tree_root->fs_info, FREE_SPACE_TREE))
+		goto out;
+	ret = load_global_roots_objectid(tree_root, path,
+					 BTRFS_FREE_SPACE_TREE_OBJECTID,
+					 "free space");
+out:
+	btrfs_free_path(path);
+	return ret;
+}
+
 static int btrfs_read_roots(struct btrfs_fs_info *fs_info)
 {
 	struct btrfs_root *tree_root = fs_info->tree_root;
@@ -2439,22 +2639,14 @@ static int btrfs_read_roots(struct btrfs_fs_info *fs_info)
 
 	BUG_ON(!fs_info->tree_root);
 
-	location.objectid = BTRFS_EXTENT_TREE_OBJECTID;
+	ret = load_global_roots(tree_root);
+	if (ret)
+		return ret;
+
+	location.objectid = BTRFS_DEV_TREE_OBJECTID;
 	location.type = BTRFS_ROOT_ITEM_KEY;
 	location.offset = 0;
 
-	root = btrfs_read_tree_root(tree_root, &location);
-	if (IS_ERR(root)) {
-		if (!btrfs_test_opt(fs_info, IGNOREBADROOTS)) {
-			ret = PTR_ERR(root);
-			goto out;
-		}
-	} else {
-		set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state);
-		fs_info->_extent_root = root;
-	}
-
-	location.objectid = BTRFS_DEV_TREE_OBJECTID;
 	root = btrfs_read_tree_root(tree_root, &location);
 	if (IS_ERR(root)) {
 		if (!btrfs_test_opt(fs_info, IGNOREBADROOTS)) {
@@ -2468,26 +2660,6 @@ static int btrfs_read_roots(struct btrfs_fs_info *fs_info)
 	/* Initialize fs_info for all devices in any case */
 	btrfs_init_devices_late(fs_info);
 
-	/* If IGNOREDATACSUMS is set don't bother reading the csum root. */
-	if (!btrfs_test_opt(fs_info, IGNOREDATACSUMS)) {
-		location.objectid = BTRFS_CSUM_TREE_OBJECTID;
-		root = btrfs_read_tree_root(tree_root, &location);
-		if (IS_ERR(root)) {
-			if (!btrfs_test_opt(fs_info, IGNOREBADROOTS)) {
-				ret = PTR_ERR(root);
-				goto out;
-			} else {
-				set_bit(BTRFS_FS_STATE_NO_CSUMS,
-					&fs_info->fs_state);
-			}
-		} else {
-			set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state);
-			fs_info->_csum_root = root;
-		}
-	} else {
-		set_bit(BTRFS_FS_STATE_NO_CSUMS, &fs_info->fs_state);
-	}
-
 	/*
 	 * This tree can share blocks with some other fs tree during relocation
 	 * and we need a proper setup by btrfs_get_fs_root
@@ -2525,20 +2697,6 @@ static int btrfs_read_roots(struct btrfs_fs_info *fs_info)
 		fs_info->uuid_root = root;
 	}
 
-	if (btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) {
-		location.objectid = BTRFS_FREE_SPACE_TREE_OBJECTID;
-		root = btrfs_read_tree_root(tree_root, &location);
-		if (IS_ERR(root)) {
-			if (!btrfs_test_opt(fs_info, IGNOREBADROOTS)) {
-				ret = PTR_ERR(root);
-				goto out;
-			}
-		}  else {
-			set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state);
-			fs_info->_free_space_root = root;
-		}
-	}
-
 	return 0;
 out:
 	btrfs_warn(fs_info, "failed to read root (objectid=%llu): %d",
@@ -2893,6 +3051,7 @@ void btrfs_init_fs_info(struct btrfs_fs_info *fs_info)
 	spin_lock_init(&fs_info->zone_active_bgs_lock);
 	spin_lock_init(&fs_info->relocation_bg_lock);
 	rwlock_init(&fs_info->tree_mod_log_lock);
+	rwlock_init(&fs_info->global_root_lock);
 	mutex_init(&fs_info->unused_bg_unpin_mutex);
 	mutex_init(&fs_info->reclaim_bgs_lock);
 	mutex_init(&fs_info->reloc_mutex);
@@ -2927,6 +3086,7 @@ void btrfs_init_fs_info(struct btrfs_fs_info *fs_info)
 	atomic_set(&fs_info->reada_works_cnt, 0);
 	atomic_set(&fs_info->nr_delayed_iputs, 0);
 	atomic64_set(&fs_info->tree_mod_seq, 0);
+	fs_info->global_root_tree = RB_ROOT;
 	fs_info->max_inline = BTRFS_DEFAULT_MAX_INLINE;
 	fs_info->metadata_ratio = 0;
 	fs_info->defrag_inodes = RB_ROOT;
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
index a4d1788acd24..80b45fcac72a 100644
--- a/fs/btrfs/disk-io.h
+++ b/fs/btrfs/disk-io.h
@@ -71,6 +71,14 @@ struct btrfs_root *btrfs_get_new_fs_root(struct btrfs_fs_info *fs_info,
 struct btrfs_root *btrfs_get_fs_root_commit_root(struct btrfs_fs_info *fs_info,
 						 struct btrfs_path *path,
 						 u64 objectid);
+int btrfs_global_root_insert(struct btrfs_root *root);
+void btrfs_global_root_delete(struct btrfs_root *root);
+struct btrfs_root *btrfs_global_root(struct btrfs_fs_info *fs_info,
+				     struct btrfs_key *key);
+struct btrfs_root *btrfs_csum_root(struct btrfs_fs_info *fs_info,
+				   u64 bytenr);
+struct btrfs_root *btrfs_extent_root(struct btrfs_fs_info *fs_info,
+				     u64 bytenr);
 
 void btrfs_free_fs_info(struct btrfs_fs_info *fs_info);
 int btrfs_cleanup_fs_roots(struct btrfs_fs_info *fs_info);
@@ -103,18 +111,6 @@ static inline struct btrfs_root *btrfs_grab_root(struct btrfs_root *root)
 	return NULL;
 }
 
-static inline struct btrfs_root *btrfs_extent_root(struct btrfs_fs_info *fs_info,
-						   u64 bytenr)
-{
-	return fs_info->_extent_root;
-}
-
-static inline struct btrfs_root *btrfs_csum_root(struct btrfs_fs_info *fs_info,
-						 u64 bytenr)
-{
-	return fs_info->_csum_root;
-}
-
 static inline struct btrfs_root *btrfs_block_group_root(struct btrfs_fs_info *fs_info)
 {
 	return btrfs_extent_root(fs_info, 0);
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 3cf354223e55..e080ee72e5bb 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -2947,6 +2947,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
 	bool skinny_metadata = btrfs_fs_incompat(info, SKINNY_METADATA);
 
 	extent_root = btrfs_extent_root(info, bytenr);
+	ASSERT(extent_root);
 
 	path = btrfs_alloc_path();
 	if (!path)
diff --git a/fs/btrfs/free-space-tree.c b/fs/btrfs/free-space-tree.c
index c0f0ba66b5ae..cf227450f356 100644
--- a/fs/btrfs/free-space-tree.c
+++ b/fs/btrfs/free-space-tree.c
@@ -19,7 +19,12 @@ static int __add_block_group_free_space(struct btrfs_trans_handle *trans,
 static struct btrfs_root *btrfs_free_space_root(
 				struct btrfs_block_group *block_group)
 {
-	return block_group->fs_info->_free_space_root;
+	struct btrfs_key key = {
+		.objectid = BTRFS_FREE_SPACE_TREE_OBJECTID,
+		.type = BTRFS_ROOT_ITEM_KEY,
+		.offset = 0,
+	};
+	return btrfs_global_root(block_group->fs_info, &key);
 }
 
 void set_free_space_tree_thresholds(struct btrfs_block_group *cache)
@@ -1164,7 +1169,11 @@ int btrfs_create_free_space_tree(struct btrfs_fs_info *fs_info)
 		ret = PTR_ERR(free_space_root);
 		goto abort;
 	}
-	fs_info->_free_space_root = free_space_root;
+	ret = btrfs_global_root_insert(free_space_root);
+	if (ret) {
+		btrfs_put_root(free_space_root);
+		goto abort;
+	}
 
 	node = rb_first(&fs_info->block_group_cache_tree);
 	while (node) {
@@ -1239,7 +1248,12 @@ int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info)
 {
 	struct btrfs_trans_handle *trans;
 	struct btrfs_root *tree_root = fs_info->tree_root;
-	struct btrfs_root *free_space_root = fs_info->_free_space_root;
+	struct btrfs_key key = {
+		.objectid = BTRFS_FREE_SPACE_TREE_OBJECTID,
+		.type = BTRFS_ROOT_ITEM_KEY,
+		.offset = 0,
+	};
+	struct btrfs_root *free_space_root = btrfs_global_root(fs_info, &key);
 	int ret;
 
 	trans = btrfs_start_transaction(tree_root, 0);
@@ -1248,7 +1262,6 @@ int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info)
 
 	btrfs_clear_fs_compat_ro(fs_info, FREE_SPACE_TREE);
 	btrfs_clear_fs_compat_ro(fs_info, FREE_SPACE_TREE_VALID);
-	fs_info->_free_space_root = NULL;
 
 	ret = clear_free_space_tree(trans, free_space_root);
 	if (ret)
@@ -1258,6 +1271,7 @@ int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info)
 	if (ret)
 		goto abort;
 
+	btrfs_global_root_delete(free_space_root);
 	list_del(&free_space_root->dirty_list);
 
 	btrfs_tree_lock(free_space_root->node);
diff --git a/fs/btrfs/tests/btrfs-tests.c b/fs/btrfs/tests/btrfs-tests.c
index 3a4099a2bf05..d8e56edd6991 100644
--- a/fs/btrfs/tests/btrfs-tests.c
+++ b/fs/btrfs/tests/btrfs-tests.c
@@ -204,6 +204,7 @@ void btrfs_free_dummy_root(struct btrfs_root *root)
 	/* Will be freed by btrfs_free_fs_roots */
 	if (WARN_ON(test_bit(BTRFS_ROOT_IN_RADIX, &root->state)))
 		return;
+	btrfs_global_root_delete(root);
 	btrfs_put_root(root);
 }
 
diff --git a/fs/btrfs/tests/free-space-tests.c b/fs/btrfs/tests/free-space-tests.c
index c3709138f7cf..ab823adf1192 100644
--- a/fs/btrfs/tests/free-space-tests.c
+++ b/fs/btrfs/tests/free-space-tests.c
@@ -858,7 +858,10 @@ int btrfs_test_free_space_cache(u32 sectorsize, u32 nodesize)
 		goto out;
 	}
 
-	root->fs_info->_extent_root = root;
+	root->root_key.objectid = BTRFS_EXTENT_TREE_OBJECTID;
+	root->root_key.type = BTRFS_ROOT_ITEM_KEY;
+	root->root_key.offset = 0;
+	btrfs_global_root_insert(root);
 
 	ret = test_extents(cache);
 	if (ret)
diff --git a/fs/btrfs/tests/free-space-tree-tests.c b/fs/btrfs/tests/free-space-tree-tests.c
index 7d6de8b53038..13734ed43bfc 100644
--- a/fs/btrfs/tests/free-space-tree-tests.c
+++ b/fs/btrfs/tests/free-space-tree-tests.c
@@ -446,7 +446,10 @@ static int run_test(test_func_t test_func, int bitmaps, u32 sectorsize,
 
 	btrfs_set_super_compat_ro_flags(root->fs_info->super_copy,
 					BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE);
-	root->fs_info->_free_space_root = root;
+	root->root_key.objectid = BTRFS_FREE_SPACE_TREE_OBJECTID;
+	root->root_key.type = BTRFS_ROOT_ITEM_KEY;
+	root->root_key.offset = 0;
+	btrfs_global_root_insert(root);
 	root->fs_info->tree_root = root;
 
 	root->node = alloc_test_extent_buffer(root->fs_info, nodesize);
diff --git a/fs/btrfs/tests/qgroup-tests.c b/fs/btrfs/tests/qgroup-tests.c
index 88e19781e83f..eee1e4459541 100644
--- a/fs/btrfs/tests/qgroup-tests.c
+++ b/fs/btrfs/tests/qgroup-tests.c
@@ -455,7 +455,10 @@ int btrfs_test_qgroups(u32 sectorsize, u32 nodesize)
 	}
 
 	/* We are using this root as our extent root */
-	root->fs_info->_extent_root = root;
+	root->root_key.objectid = BTRFS_EXTENT_TREE_OBJECTID;
+	root->root_key.type = BTRFS_ROOT_ITEM_KEY;
+	root->root_key.offset = 0;
+	btrfs_global_root_insert(root);
 
 	/*
 	 * Some of the paths we test assume we have a filled out fs_info, so we
-- 
2.26.3


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

* Re: [PATCH 01/25] btrfs: kill BTRFS_FS_BARRIER
  2021-11-05 20:45 ` [PATCH 01/25] btrfs: kill BTRFS_FS_BARRIER Josef Bacik
@ 2021-11-18 11:50   ` David Sterba
  0 siblings, 0 replies; 34+ messages in thread
From: David Sterba @ 2021-11-18 11:50 UTC (permalink / raw)
  To: Josef Bacik; +Cc: linux-btrfs, kernel-team

On Fri, Nov 05, 2021 at 04:45:27PM -0400, Josef Bacik wrote:
> This is no longer used, it's a relic from when we had -o nobarrier.

We still have nobarrier, but it's implemented by the mount option bit
BTRFS_MOUNT_NOBARRIER, I'll update the changelog.

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

* Re: [PATCH 02/25] btrfs: rework async transaction committing
  2021-11-05 20:45 ` [PATCH 02/25] btrfs: rework async transaction committing Josef Bacik
@ 2021-11-18 12:12   ` David Sterba
  2021-11-23 17:19     ` David Sterba
  0 siblings, 1 reply; 34+ messages in thread
From: David Sterba @ 2021-11-18 12:12 UTC (permalink / raw)
  To: Josef Bacik; +Cc: linux-btrfs, kernel-team

On Fri, Nov 05, 2021 at 04:45:28PM -0400, Josef Bacik wrote:
> Currently we do this awful thing where we get another ref on a trans
> handle, async off that handle and commit the transaction from that work.
> Because we do this we have to mess with current->journal_info and the
> freeze counting stuff.
> 
> We already have an async thing to kick for the transaction commit, the
> transaction kthread.  Replace this work struct with a flag on the
> fs_info to tell the kthread to go ahead and commit even if it's before
> our timeout.  Then we can drastically simplify the async transaction
> commit path.

I wanted to get rid of the async commit completely and reusing the
pending operations that's basically the same what you add as the new fs
bit.

https://lore.kernel.org/linux-btrfs/808c557f1ae3034fdfa2d2361e864aac90ba5a94.1622733245.git.dsterba@suse.com/

There's also a followup removing transaction_blocked_wait, I got some
hangs in btrfs/011. I haven't tested 3/4 separately so I don't know the
exact cause.

> --- a/fs/btrfs/ctree.h
> +++ b/fs/btrfs/ctree.h
> @@ -595,6 +595,9 @@ enum {
>  	/* Indicate whether there are any tree modification log users */
>  	BTRFS_FS_TREE_MOD_LOG_USERS,
>  
> +	/* Indicate that we want the transaction kthread to commit right now. */
> +	BTRFS_FS_COMMIT_TRANS,

This is duplicating functionality behind BTRFS_PENDING_COMMIT, otherwise
simplifying the async commit is good of course.

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

* Re: [PATCH 25/25] btrfs: track the csum, extent, and free space trees in a rb tree
  2021-11-05 20:45 ` [PATCH 25/25] btrfs: track the csum, extent, and free space trees in a rb tree Josef Bacik
@ 2021-11-18 12:22   ` David Sterba
  0 siblings, 0 replies; 34+ messages in thread
From: David Sterba @ 2021-11-18 12:22 UTC (permalink / raw)
  To: Josef Bacik; +Cc: linux-btrfs, kernel-team

On Fri, Nov 05, 2021 at 04:45:51PM -0400, Josef Bacik wrote:
> @@ -1242,6 +1243,82 @@ struct btrfs_root *btrfs_alloc_dummy_root(struct btrfs_fs_info *fs_info)
>  }
>  #endif
>  
> +static int global_root_cmp(struct rb_node *a_node, const struct rb_node *b_node)
> +{
> +	struct btrfs_root *a = rb_entry(a_node, struct btrfs_root, rb_node);
> +	struct btrfs_root *b = rb_entry(b_node, struct btrfs_root, rb_node);

Comparators can use some consts, at least for the local variables. The
rb_add_new comparator prototype has const only for the node, so
global_root_cmp is OK. I'll update the commit.

> +	return btrfs_comp_cpu_keys(&a->root_key, &b->root_key);
> +}

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

* Re: [PATCH 02/25] btrfs: rework async transaction committing
  2021-11-18 12:12   ` David Sterba
@ 2021-11-23 17:19     ` David Sterba
  0 siblings, 0 replies; 34+ messages in thread
From: David Sterba @ 2021-11-23 17:19 UTC (permalink / raw)
  To: dsterba, Josef Bacik, linux-btrfs, kernel-team

On Thu, Nov 18, 2021 at 01:12:03PM +0100, David Sterba wrote:
> On Fri, Nov 05, 2021 at 04:45:28PM -0400, Josef Bacik wrote:
> > Currently we do this awful thing where we get another ref on a trans
> > handle, async off that handle and commit the transaction from that work.
> > Because we do this we have to mess with current->journal_info and the
> > freeze counting stuff.
> > 
> > We already have an async thing to kick for the transaction commit, the
> > transaction kthread.  Replace this work struct with a flag on the
> > fs_info to tell the kthread to go ahead and commit even if it's before
> > our timeout.  Then we can drastically simplify the async transaction
> > commit path.
> 
> I wanted to get rid of the async commit completely and reusing the
> pending operations that's basically the same what you add as the new fs
> bit.
> 
> https://lore.kernel.org/linux-btrfs/808c557f1ae3034fdfa2d2361e864aac90ba5a94.1622733245.git.dsterba@suse.com/
> 
> There's also a followup removing transaction_blocked_wait, I got some
> hangs in btrfs/011. I haven't tested 3/4 separately so I don't know the
> exact cause.
> 
> > --- a/fs/btrfs/ctree.h
> > +++ b/fs/btrfs/ctree.h
> > @@ -595,6 +595,9 @@ enum {
> >  	/* Indicate whether there are any tree modification log users */
> >  	BTRFS_FS_TREE_MOD_LOG_USERS,
> >  
> > +	/* Indicate that we want the transaction kthread to commit right now. */
> > +	BTRFS_FS_COMMIT_TRANS,
> 
> This is duplicating functionality behind BTRFS_PENDING_COMMIT, otherwise
> simplifying the async commit is good of course.

I'll add a note about that and leave it as a future cleanup so the
patchset can get merged.

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

* Re: [PATCH 08/25] btrfs: remove BUG_ON() in find_parent_nodes()
  2021-11-05 20:45 ` [PATCH 08/25] btrfs: remove BUG_ON() in find_parent_nodes() Josef Bacik
@ 2021-11-23 20:53   ` Nikolay Borisov
  2021-11-23 21:35     ` Josef Bacik
  0 siblings, 1 reply; 34+ messages in thread
From: Nikolay Borisov @ 2021-11-23 20:53 UTC (permalink / raw)
  To: Josef Bacik, linux-btrfs, kernel-team



On 5.11.21 г. 22:45, Josef Bacik wrote:
> We search for an extent entry with .offset = -1, which shouldn't be a
> thing, but corruption happens.  Add an ASSERT() for the developers,
> return -EUCLEAN for mortals.
> 
> Signed-off-by: Josef Bacik <josef@toxicpanda.com>
> ---
>  fs/btrfs/backref.c | 7 ++++++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
> index 12276ff08dd4..7d942f5d6443 100644
> --- a/fs/btrfs/backref.c
> +++ b/fs/btrfs/backref.c
> @@ -1210,7 +1210,12 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
>  	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
>  	if (ret < 0)
>  		goto out;
> -	BUG_ON(ret == 0);
> +	if (ret == 0) {
> +		/* This shouldn't happen, indicates a bug or fs corruption. */
> +		ASSERT(ret != 0);

This can never trigger in this branch, because ret is guaranteed to be 0
o_O?

> +		ret = -EUCLEAN;
> +		goto out;
> +	}
>  
>  	if (trans && likely(trans->type != __TRANS_DUMMY) &&
>  	    time_seq != BTRFS_SEQ_LAST) {
> 

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

* Re: [PATCH 08/25] btrfs: remove BUG_ON() in find_parent_nodes()
  2021-11-23 20:53   ` Nikolay Borisov
@ 2021-11-23 21:35     ` Josef Bacik
  0 siblings, 0 replies; 34+ messages in thread
From: Josef Bacik @ 2021-11-23 21:35 UTC (permalink / raw)
  To: Nikolay Borisov; +Cc: linux-btrfs, kernel-team

On Tue, Nov 23, 2021 at 10:53:07PM +0200, Nikolay Borisov wrote:
> 
> 
> On 5.11.21 г. 22:45, Josef Bacik wrote:
> > We search for an extent entry with .offset = -1, which shouldn't be a
> > thing, but corruption happens.  Add an ASSERT() for the developers,
> > return -EUCLEAN for mortals.
> > 
> > Signed-off-by: Josef Bacik <josef@toxicpanda.com>
> > ---
> >  fs/btrfs/backref.c | 7 ++++++-
> >  1 file changed, 6 insertions(+), 1 deletion(-)
> > 
> > diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
> > index 12276ff08dd4..7d942f5d6443 100644
> > --- a/fs/btrfs/backref.c
> > +++ b/fs/btrfs/backref.c
> > @@ -1210,7 +1210,12 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
> >  	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
> >  	if (ret < 0)
> >  		goto out;
> > -	BUG_ON(ret == 0);
> > +	if (ret == 0) {
> > +		/* This shouldn't happen, indicates a bug or fs corruption. */
> > +		ASSERT(ret != 0);
> 
> This can never trigger in this branch, because ret is guaranteed to be 0
> o_O?
> 

It'll always trigger right?  ASSERT(false) == BUG_ON(true), and in this case ret
== 0, so we'll BUG_ON() in this case because it's wrong.  Thanks,

Jsoef

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

* Re: [PATCH 12/25] btrfs: use chunk_root in find_free_extent_update_loop
  2021-11-05 20:45 ` [PATCH 12/25] btrfs: use chunk_root in find_free_extent_update_loop Josef Bacik
@ 2021-11-25 10:11   ` Nikolay Borisov
  0 siblings, 0 replies; 34+ messages in thread
From: Nikolay Borisov @ 2021-11-25 10:11 UTC (permalink / raw)
  To: Josef Bacik, linux-btrfs, kernel-team



On 5.11.21 г. 22:45, Josef Bacik wrote:
> We're only using this to start the transaction with to possibly allocate
                                                  ^^
delete "with"

> a chunk.  It doesn't really matter which root to use, but with extent
> tree v2 we'll need a bytenr to look up a extent root which makes the
> usage of the extent_root awkward here.  Simply change it to the
> chunk_root.
> 
> Signed-off-by: Josef Bacik <josef@toxicpanda.com>
> ---
>  fs/btrfs/extent-tree.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
> index c33f3dc6b322..f40b97072231 100644
> --- a/fs/btrfs/extent-tree.c
> +++ b/fs/btrfs/extent-tree.c
> @@ -3977,7 +3977,7 @@ static int find_free_extent_update_loop(struct btrfs_fs_info *fs_info,
>  					struct find_free_extent_ctl *ffe_ctl,
>  					bool full_search)
>  {
> -	struct btrfs_root *root = fs_info->extent_root;
> +	struct btrfs_root *root = fs_info->chunk_root;
>  	int ret;
>  
>  	if ((ffe_ctl->loop == LOOP_CACHING_NOWAIT) &&
> 

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

* Re: [PATCH 21/25] btrfs: set BTRFS_FS_STATE_NO_CSUMS if we fail to load the csum root
  2021-11-05 20:45 ` [PATCH 21/25] btrfs: set BTRFS_FS_STATE_NO_CSUMS if we fail to load the csum root Josef Bacik
@ 2021-11-25 15:05   ` Nikolay Borisov
  0 siblings, 0 replies; 34+ messages in thread
From: Nikolay Borisov @ 2021-11-25 15:05 UTC (permalink / raw)
  To: Josef Bacik, linux-btrfs, kernel-team



On 5.11.21 г. 22:45, Josef Bacik wrote:
> We have a few places where we skip doing csums if we mounted with one of
> the rescue options that ignores bad csum roots.  In the future when
> there are multiple csum roots it'll be costly to check and see if there
> are any missing csum roots, so simply add a flag to indicate the fs
> should skip loading csums in case of errors.
> 
> Signed-off-by: Josef Bacik <josef@toxicpanda.com>
> ---
>  fs/btrfs/compression.c | 3 ++-
>  fs/btrfs/ctree.h       | 2 ++
>  fs/btrfs/disk-io.c     | 5 +++++
>  fs/btrfs/file-item.c   | 3 ++-
>  fs/btrfs/inode.c       | 4 ++--
>  5 files changed, 13 insertions(+), 4 deletions(-)
> 
> diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
> index 1d071c8d6fff..a76107d6f7f2 100644
> --- a/fs/btrfs/compression.c
> +++ b/fs/btrfs/compression.c
> @@ -156,7 +156,8 @@ static int check_compressed_csum(struct btrfs_inode *inode, struct bio *bio,
>  	struct compressed_bio *cb = bio->bi_private;
>  	u8 *cb_sum = cb->sums;
>  
> -	if (!fs_info->csum_root || (inode->flags & BTRFS_INODE_NODATASUM))
> +	if ((inode->flags & BTRFS_INODE_NODATASUM) ||
> +	    test_bit(BTRFS_FS_STATE_NO_CSUMS, &fs_info->fs_state))
>  		return 0;
>  
>  	shash->tfm = fs_info->csum_shash;
> diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
> index dac5741cb6fa..13bd6fc3901a 100644
> --- a/fs/btrfs/ctree.h
> +++ b/fs/btrfs/ctree.h
> @@ -143,6 +143,8 @@ enum {
>  	BTRFS_FS_STATE_DEV_REPLACING,
>  	/* The btrfs_fs_info created for self-tests */
>  	BTRFS_FS_STATE_DUMMY_FS_INFO,
> +
> +	BTRFS_FS_STATE_NO_CSUMS,
>  };
>  
>  #define BTRFS_BACKREF_REV_MAX		256
> diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
> index 1ada4c96ef71..898b4ff83718 100644
> --- a/fs/btrfs/disk-io.c
> +++ b/fs/btrfs/disk-io.c
> @@ -2475,11 +2475,16 @@ static int btrfs_read_roots(struct btrfs_fs_info *fs_info)
>  			if (!btrfs_test_opt(fs_info, IGNOREBADROOTS)) {
>  				ret = PTR_ERR(root);
>  				goto out;
> +			} else {
> +				set_bit(BTRFS_FS_STATE_NO_CSUMS,
> +					&fs_info->fs_state);
>  			}
>  		} else {
>  			set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state);
>  			fs_info->csum_root = root;
>  		}
> +	} else {
> +		set_bit(BTRFS_FS_STATE_NO_CSUMS, &fs_info->fs_state);
>  	}
>  
>  	/*
> diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c
> index 359f3a047360..4904286139bf 100644
> --- a/fs/btrfs/file-item.c
> +++ b/fs/btrfs/file-item.c
> @@ -376,7 +376,8 @@ blk_status_t btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio, u8 *dst
>  	const unsigned int nblocks = orig_len >> fs_info->sectorsize_bits;
>  	int count = 0;
>  
> -	if (!fs_info->csum_root || (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM))
> +	if ((BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM) ||
> +	    test_bit(BTRFS_FS_STATE_NO_CSUMS, &fs_info->fs_state))
>  		return BLK_STS_OK;
>  
>  	/*
> diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
> index 9e81fd94ab09..6d14dd2cf36e 100644
> --- a/fs/btrfs/inode.c
> +++ b/fs/btrfs/inode.c
> @@ -2516,7 +2516,7 @@ blk_status_t btrfs_submit_data_bio(struct inode *inode, struct bio *bio,
>  	int async = !atomic_read(&BTRFS_I(inode)->sync_writers);
>  
>  	skip_sum = (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM) ||
> -		   !fs_info->csum_root;
> +		test_bit(BTRFS_FS_STATE_NO_CSUMS, &fs_info->fs_state);
>  
>  	if (btrfs_is_free_space_inode(BTRFS_I(inode)))
>  		metadata = BTRFS_WQ_ENDIO_FREE_SPACE;
> @@ -3314,7 +3314,7 @@ unsigned int btrfs_verify_data_csum(struct btrfs_bio *bbio,
>  	if (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)
>  		return 0;
>  
> -	if (!root->fs_info->csum_root)
> +	if (unlikely(test_bit(BTRFS_FS_STATE_NO_CSUMS, &fs_info->fs_state)))
>  		return 0;

Should writes be allowed to proceed when FS_STATE_NO_CSUMS is set, which
indicates errors while loading trees?

>  
>  	ASSERT(page_offset(page) <= start &&
> 

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

end of thread, other threads:[~2021-11-25 15:07 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-05 20:45 [PATCH 00/25] btrfs: extent tree v2 prep work for global roots Josef Bacik
2021-11-05 20:45 ` [PATCH 01/25] btrfs: kill BTRFS_FS_BARRIER Josef Bacik
2021-11-18 11:50   ` David Sterba
2021-11-05 20:45 ` [PATCH 02/25] btrfs: rework async transaction committing Josef Bacik
2021-11-18 12:12   ` David Sterba
2021-11-23 17:19     ` David Sterba
2021-11-05 20:45 ` [PATCH 03/25] btrfs: pass fs_info to trace_btrfs_transaction_commit Josef Bacik
2021-11-05 20:45 ` [PATCH 04/25] btrfs: remove trans_handle->root Josef Bacik
2021-11-05 20:45 ` [PATCH 05/25] btrfs: pass the root to add_keyed_refs Josef Bacik
2021-11-05 20:45 ` [PATCH 06/25] btrfs: move comment in find_parent_nodes() Josef Bacik
2021-11-05 20:45 ` [PATCH 07/25] btrfs: remove SANITY_TESTS check form find_parent_nodes Josef Bacik
2021-11-05 20:45 ` [PATCH 08/25] btrfs: remove BUG_ON() in find_parent_nodes() Josef Bacik
2021-11-23 20:53   ` Nikolay Borisov
2021-11-23 21:35     ` Josef Bacik
2021-11-05 20:45 ` [PATCH 09/25] btrfs: remove BUG_ON(!eie) in find_parent_nodes Josef Bacik
2021-11-05 20:45 ` [PATCH 10/25] btrfs: add a btrfs_block_group_root() helper Josef Bacik
2021-11-05 20:45 ` [PATCH 11/25] btrfs: make remove_extent_backref pass the root Josef Bacik
2021-11-05 20:45 ` [PATCH 12/25] btrfs: use chunk_root in find_free_extent_update_loop Josef Bacik
2021-11-25 10:11   ` Nikolay Borisov
2021-11-05 20:45 ` [PATCH 13/25] btrfs: do not special case the extent root for switch commit roots Josef Bacik
2021-11-05 20:45 ` [PATCH 14/25] btrfs: remove unnecessary extent root check in btrfs_defrag_leaves Josef Bacik
2021-11-05 20:45 ` [PATCH 15/25] btrfs: don't use the extent root in btrfs_chunk_alloc_add_chunk_item Josef Bacik
2021-11-05 20:45 ` [PATCH 16/25] btrfs: don't use extent_root in iterate_extent_inodes Josef Bacik
2021-11-05 20:45 ` [PATCH 17/25] btrfs: don't use the extent_root in flush_space Josef Bacik
2021-11-05 20:45 ` [PATCH 18/25] btrfs: init root block_rsv at init root time Josef Bacik
2021-11-05 20:45 ` [PATCH 19/25] btrfs: stop accessing ->extent_root directly Josef Bacik
2021-11-05 20:45 ` [PATCH 20/25] btrfs: fix csum assert to check objectid of the root Josef Bacik
2021-11-05 20:45 ` [PATCH 21/25] btrfs: set BTRFS_FS_STATE_NO_CSUMS if we fail to load the csum root Josef Bacik
2021-11-25 15:05   ` Nikolay Borisov
2021-11-05 20:45 ` [PATCH 22/25] btrfs: stop accessing ->csum_root directly Josef Bacik
2021-11-05 20:45 ` [PATCH 23/25] btrfs: stop accessing ->free_space_root directly Josef Bacik
2021-11-05 20:45 ` [PATCH 24/25] btrfs: remove useless WARN_ON in record_root_in_trans Josef Bacik
2021-11-05 20:45 ` [PATCH 25/25] btrfs: track the csum, extent, and free space trees in a rb tree Josef Bacik
2021-11-18 12:22   ` David Sterba

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.