All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/20] btrfs-progs: extent tree v2 global root support prep work
@ 2021-11-05 20:28 Josef Bacik
  2021-11-05 20:28 ` [PATCH 01/20] btrfs-progs: simplify btrfs_make_block_group Josef Bacik
                   ` (20 more replies)
  0 siblings, 21 replies; 42+ messages in thread
From: Josef Bacik @ 2021-11-05 20:28 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

Hello,

This is a series of patches to do all the prep work needed to support extent
tree v2.  These patches are independent of the actual extent tree v2 support,
some of them are fixes, some of them are purely to pave the way for the global
root support.  These patches are mostly around stopping direct access of
->extent_root/->csum_root/->free_space_root, putting these roots into a rb_tree,
and changing the code to look up the roots in the rb_tree instead of accessing
them directly.  There are a variety of fixes to help make this easier, mostly
removing access to these roots that are strictly necessary.  Thanks,

Josef

Josef Bacik (20):
  btrfs-progs: simplify btrfs_make_block_group
  btrfs-progs: check: don't walk down non fs-trees for qgroup check
  btrfs-progs: filesystem-show: close ctree once we're done
  btrfs-progs: add a helper for setting up a root node
  btrfs-progs: btrfs-shared: stop passing root to csum related functions
  btrfs-progs: check: stop passing csum root around
  btrfs-progs: stop accessing ->csum_root directly
  btrfs-progs: image: keep track of seen blocks when walking trees
  btrfs-progs: common: move btrfs_fix_block_accounting to repair.c
  btrfs-progs: check: abstract out the used marking helpers
  btrfs-progs: check: move btrfs_mark_used_tree_blocks to common
  btrfs-progs: mark reloc roots as used
  btrfs-progs: stop accessing ->extent_root directly
  btrfs-progs: stop accessing ->free_space_root directly
  btrfs-progs: track csum, extent, and free space trees in a rb tree
  btrfs-progs: check: make reinit work per found root item
  btrfs-progs: check: check the global roots for uptodate root nodes
  btrfs-progs: check: check all of the csum roots
  btrfs-progs: check: fill csum root from all extent roots
  btrfs-progs: common: search all extent roots for marking used space

 btrfs-corrupt-block.c           |  15 +-
 btrfs-map-logical.c             |   9 +-
 btrfstune.c                     |   2 +-
 check/main.c                    | 223 ++++++++++++++------
 check/mode-common.c             | 132 +-----------
 check/mode-lowmem.c             |  72 ++++---
 check/qgroup-verify.c           |   6 +-
 cmds/filesystem.c               |  19 +-
 cmds/rescue-chunk-recover.c     |  35 ++--
 common/repair.c                 | 230 +++++++++++++++++++++
 common/repair.h                 |   5 +
 convert/main.c                  |   5 +-
 image/main.c                    |  14 +-
 kernel-shared/backref.c         |  10 +-
 kernel-shared/ctree.h           |  10 +-
 kernel-shared/disk-io.c         | 356 +++++++++++++++++++++++---------
 kernel-shared/disk-io.h         |   8 +-
 kernel-shared/extent-tree.c     | 159 ++++----------
 kernel-shared/file-item.c       |   6 +-
 kernel-shared/free-space-tree.c |  54 +++--
 kernel-shared/volumes.c         |   3 +-
 kernel-shared/zoned.c           |   2 +-
 mkfs/main.c                     |  29 ++-
 mkfs/rootdir.c                  |   2 +-
 24 files changed, 892 insertions(+), 514 deletions(-)

-- 
2.26.3


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

* [PATCH 01/20] btrfs-progs: simplify btrfs_make_block_group
  2021-11-05 20:28 [PATCH 00/20] btrfs-progs: extent tree v2 global root support prep work Josef Bacik
@ 2021-11-05 20:28 ` Josef Bacik
  2021-11-06  0:14   ` Qu Wenruo
  2021-11-08 10:13   ` Anand Jain
  2021-11-05 20:28 ` [PATCH 02/20] btrfs-progs: check: don't walk down non fs-trees for qgroup check Josef Bacik
                   ` (19 subsequent siblings)
  20 siblings, 2 replies; 42+ messages in thread
From: Josef Bacik @ 2021-11-05 20:28 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

This is doing the same work as insert_block_group_item, rework it to
call the helper instead.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 kernel-shared/extent-tree.c | 43 ++++++++++++++-----------------------
 1 file changed, 16 insertions(+), 27 deletions(-)

diff --git a/kernel-shared/extent-tree.c b/kernel-shared/extent-tree.c
index 8e0614e0..a918e5aa 100644
--- a/kernel-shared/extent-tree.c
+++ b/kernel-shared/extent-tree.c
@@ -2791,33 +2791,6 @@ btrfs_add_block_group(struct btrfs_fs_info *fs_info, u64 bytes_used, u64 type,
 	return cache;
 }
 
-int btrfs_make_block_group(struct btrfs_trans_handle *trans,
-			   struct btrfs_fs_info *fs_info, u64 bytes_used,
-			   u64 type, u64 chunk_offset, u64 size)
-{
-	int ret;
-	struct btrfs_root *extent_root = fs_info->extent_root;
-	struct btrfs_block_group *cache;
-	struct btrfs_block_group_item bgi;
-	struct btrfs_key key;
-
-	cache = btrfs_add_block_group(fs_info, bytes_used, type, chunk_offset,
-				      size);
-	btrfs_set_stack_block_group_used(&bgi, cache->used);
-	btrfs_set_stack_block_group_flags(&bgi, cache->flags);
-	btrfs_set_stack_block_group_chunk_objectid(&bgi,
-			BTRFS_FIRST_CHUNK_TREE_OBJECTID);
-	key.objectid = cache->start;
-	key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
-	key.offset = cache->length;
-	ret = btrfs_insert_item(trans, extent_root, &key, &bgi, sizeof(bgi));
-	BUG_ON(ret);
-
-	add_block_group_free_space(trans, cache);
-
-	return 0;
-}
-
 static int insert_block_group_item(struct btrfs_trans_handle *trans,
 				   struct btrfs_block_group *block_group)
 {
@@ -2838,6 +2811,22 @@ static int insert_block_group_item(struct btrfs_trans_handle *trans,
 	return btrfs_insert_item(trans, root, &key, &bgi, sizeof(bgi));
 }
 
+int btrfs_make_block_group(struct btrfs_trans_handle *trans,
+			   struct btrfs_fs_info *fs_info, u64 bytes_used,
+			   u64 type, u64 chunk_offset, u64 size)
+{
+	struct btrfs_block_group *cache;
+	int ret;
+
+	cache = btrfs_add_block_group(fs_info, bytes_used, type, chunk_offset,
+				      size);
+	ret = insert_block_group_item(trans, cache);
+	if (ret)
+		return ret;
+	add_block_group_free_space(trans, cache);
+	return 0;
+}
+
 /*
  * This is for converter use only.
  *
-- 
2.26.3


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

* [PATCH 02/20] btrfs-progs: check: don't walk down non fs-trees for qgroup check
  2021-11-05 20:28 [PATCH 00/20] btrfs-progs: extent tree v2 global root support prep work Josef Bacik
  2021-11-05 20:28 ` [PATCH 01/20] btrfs-progs: simplify btrfs_make_block_group Josef Bacik
@ 2021-11-05 20:28 ` Josef Bacik
  2021-11-06  0:14   ` Qu Wenruo
  2021-11-05 20:28 ` [PATCH 03/20] btrfs-progs: filesystem-show: close ctree once we're done Josef Bacik
                   ` (18 subsequent siblings)
  20 siblings, 1 reply; 42+ messages in thread
From: Josef Bacik @ 2021-11-05 20:28 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

We will lookup implied refs for every root id for every block that we
find when verifying qgroups, but we don't need to worry about non
fstrees, so skip them here.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 check/qgroup-verify.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/check/qgroup-verify.c b/check/qgroup-verify.c
index 14645c85..a514fee1 100644
--- a/check/qgroup-verify.c
+++ b/check/qgroup-verify.c
@@ -765,6 +765,10 @@ static int add_refs_for_implied(struct btrfs_fs_info *info, u64 bytenr,
 	struct btrfs_root *root;
 	struct btrfs_key key;
 
+	/* If this is a global tree skip it. */
+	if (!is_fstree(root_id))
+		return 0;
+
 	/* Tree reloc tree doesn't contribute qgroup, skip it */
 	if (root_id == BTRFS_TREE_RELOC_OBJECTID)
 		return 0;
-- 
2.26.3


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

* [PATCH 03/20] btrfs-progs: filesystem-show: close ctree once we're done
  2021-11-05 20:28 [PATCH 00/20] btrfs-progs: extent tree v2 global root support prep work Josef Bacik
  2021-11-05 20:28 ` [PATCH 01/20] btrfs-progs: simplify btrfs_make_block_group Josef Bacik
  2021-11-05 20:28 ` [PATCH 02/20] btrfs-progs: check: don't walk down non fs-trees for qgroup check Josef Bacik
@ 2021-11-05 20:28 ` Josef Bacik
  2021-11-08 10:23   ` Anand Jain
  2021-11-05 20:28 ` [PATCH 04/20] btrfs-progs: add a helper for setting up a root node Josef Bacik
                   ` (17 subsequent siblings)
  20 siblings, 1 reply; 42+ messages in thread
From: Josef Bacik @ 2021-11-05 20:28 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

Running with ASAN we won't pass the self tests because we leak the whole
fs_info with btrfs filesystem show.  Fix this by making sure we close
out the fs_info and clean up all of the memory and such.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 cmds/filesystem.c | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/cmds/filesystem.c b/cmds/filesystem.c
index 6a9e46d2..624d0288 100644
--- a/cmds/filesystem.c
+++ b/cmds/filesystem.c
@@ -655,6 +655,7 @@ static int cmd_filesystem_show(const struct cmd_struct *cmd,
 {
 	LIST_HEAD(all_uuids);
 	struct btrfs_fs_devices *fs_devices;
+	struct btrfs_root *root = NULL;
 	char *search = NULL;
 	int ret;
 	/* default, search both kernel and udev */
@@ -753,12 +754,8 @@ static int cmd_filesystem_show(const struct cmd_struct *cmd,
 
 devs_only:
 	if (type == BTRFS_ARG_REG) {
-		/*
-		 * Given input (search) is regular file.
-		 * We don't close the fs_info because it will free the device,
-		 * this is not a long-running process so it's fine
-		 */
-		if (open_ctree(search, btrfs_sb_offset(0), 0))
+		root = open_ctree(search, btrfs_sb_offset(0), 0);
+		if (root)
 			ret = 0;
 		else
 			ret = 1;
@@ -768,7 +765,7 @@ devs_only:
 
 	if (ret) {
 		error("blkid device scan returned %d", ret);
-		return 1;
+		goto out;
 	}
 
 	/*
@@ -779,13 +776,13 @@ devs_only:
 	ret = search_umounted_fs_uuids(&all_uuids, search, &found);
 	if (ret < 0) {
 		error("searching target device returned error %d", ret);
-		return 1;
+		goto out;
 	}
 
 	ret = map_seed_devices(&all_uuids);
 	if (ret) {
 		error("mapping seed devices returned error %d", ret);
-		return 1;
+		goto out;
 	}
 
 	list_for_each_entry(fs_devices, &all_uuids, list)
@@ -801,8 +798,10 @@ devs_only:
 		free_fs_devices(fs_devices);
 	}
 out:
+	if (root)
+		close_ctree(root);
 	free_seen_fsid(seen_fsid_hash);
-	return ret;
+	return !!ret;
 }
 static DEFINE_SIMPLE_COMMAND(filesystem_show, "show");
 
-- 
2.26.3


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

* [PATCH 04/20] btrfs-progs: add a helper for setting up a root node
  2021-11-05 20:28 [PATCH 00/20] btrfs-progs: extent tree v2 global root support prep work Josef Bacik
                   ` (2 preceding siblings ...)
  2021-11-05 20:28 ` [PATCH 03/20] btrfs-progs: filesystem-show: close ctree once we're done Josef Bacik
@ 2021-11-05 20:28 ` Josef Bacik
  2021-11-06  0:18   ` Qu Wenruo
  2021-11-05 20:28 ` [PATCH 05/20] btrfs-progs: btrfs-shared: stop passing root to csum related functions Josef Bacik
                   ` (16 subsequent siblings)
  20 siblings, 1 reply; 42+ messages in thread
From: Josef Bacik @ 2021-11-05 20:28 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

We use this pattern in a few places, and will use it more with different
roots in the future.  Extract out this helper to read the root nodes.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 kernel-shared/disk-io.c | 58 +++++++++++++++++++++--------------------
 1 file changed, 30 insertions(+), 28 deletions(-)

diff --git a/kernel-shared/disk-io.c b/kernel-shared/disk-io.c
index 3b3c4523..1f940221 100644
--- a/kernel-shared/disk-io.c
+++ b/kernel-shared/disk-io.c
@@ -578,12 +578,23 @@ void btrfs_setup_root(struct btrfs_root *root, struct btrfs_fs_info *fs_info,
 	root->root_key.objectid = objectid;
 }
 
+static int read_root_node(struct btrfs_fs_info *fs_info,
+			  struct btrfs_root *root, u64 bytenr, u64 gen)
+{
+	root->node = read_tree_block(fs_info, bytenr, gen);
+	if (!extent_buffer_uptodate(root->node)) {
+		free_extent_buffer(root->node);
+		root->node = NULL;
+		return -EIO;
+	}
+	return 0;
+}
+
 static int find_and_setup_root(struct btrfs_root *tree_root,
 			       struct btrfs_fs_info *fs_info,
 			       u64 objectid, struct btrfs_root *root)
 {
 	int ret;
-	u64 generation;
 
 	btrfs_setup_root(root, fs_info, objectid);
 	ret = btrfs_find_last_root(tree_root, objectid,
@@ -591,13 +602,9 @@ static int find_and_setup_root(struct btrfs_root *tree_root,
 	if (ret)
 		return ret;
 
-	generation = btrfs_root_generation(&root->root_item);
-	root->node = read_tree_block(fs_info,
-			btrfs_root_bytenr(&root->root_item), generation);
-	if (!extent_buffer_uptodate(root->node))
-		return -EIO;
-
-	return 0;
+	return read_root_node(fs_info, root,
+			      btrfs_root_bytenr(&root->root_item),
+			      btrfs_root_generation(&root->root_item));
 }
 
 static int find_and_setup_log_root(struct btrfs_root *tree_root,
@@ -606,6 +613,7 @@ static int find_and_setup_log_root(struct btrfs_root *tree_root,
 {
 	u64 blocknr = btrfs_super_log_root(disk_super);
 	struct btrfs_root *log_root = malloc(sizeof(struct btrfs_root));
+	int ret;
 
 	if (!log_root)
 		return -ENOMEM;
@@ -615,20 +623,15 @@ static int find_and_setup_log_root(struct btrfs_root *tree_root,
 		return 0;
 	}
 
-	btrfs_setup_root(log_root, fs_info,
-			 BTRFS_TREE_LOG_OBJECTID);
-
-	log_root->node = read_tree_block(fs_info, blocknr,
-				     btrfs_super_generation(disk_super) + 1);
-
-	fs_info->log_root_tree = log_root;
-
-	if (!extent_buffer_uptodate(log_root->node)) {
-		free_extent_buffer(log_root->node);
+	btrfs_setup_root(log_root, fs_info, BTRFS_TREE_LOG_OBJECTID);
+	ret = read_root_node(fs_info, log_root, blocknr,
+			     btrfs_super_generation(disk_super) + 1);
+	if (ret) {
 		free(log_root);
 		fs_info->log_root_tree = NULL;
-		return -EIO;
+		return ret;
 	}
+	fs_info->log_root_tree = log_root;
 
 	return 0;
 }
@@ -704,9 +707,9 @@ out:
 		return ERR_PTR(ret);
 	}
 	generation = btrfs_root_generation(&root->root_item);
-	root->node = read_tree_block(fs_info,
-			btrfs_root_bytenr(&root->root_item), generation);
-	if (!extent_buffer_uptodate(root->node)) {
+	ret = read_root_node(fs_info, root,
+			     btrfs_root_bytenr(&root->root_item), generation);
+	if (ret) {
 		free(root);
 		return ERR_PTR(-EIO);
 	}
@@ -970,8 +973,8 @@ int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info, u64 root_tree_bytenr,
 		generation = btrfs_backup_tree_root_gen(backup);
 	}
 
-	root->node = read_tree_block(fs_info, root_tree_bytenr, generation);
-	if (!extent_buffer_uptodate(root->node)) {
+	ret = read_root_node(fs_info, root, root_tree_bytenr, generation);
+	if (ret) {
 		fprintf(stderr, "Couldn't read tree root\n");
 		return -EIO;
 	}
@@ -1179,10 +1182,9 @@ int btrfs_setup_chunk_tree_and_device_map(struct btrfs_fs_info *fs_info,
 	else
 		generation = 0;
 
-	fs_info->chunk_root->node = read_tree_block(fs_info,
-						    chunk_root_bytenr,
-						    generation);
-	if (!extent_buffer_uptodate(fs_info->chunk_root->node)) {
+	ret = read_root_node(fs_info, fs_info->chunk_root, chunk_root_bytenr,
+			     generation);
+	if (ret) {
 		if (fs_info->ignore_chunk_tree_error) {
 			warning("cannot read chunk root, continue anyway");
 			fs_info->chunk_root = NULL;
-- 
2.26.3


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

* [PATCH 05/20] btrfs-progs: btrfs-shared: stop passing root to csum related functions
  2021-11-05 20:28 [PATCH 00/20] btrfs-progs: extent tree v2 global root support prep work Josef Bacik
                   ` (3 preceding siblings ...)
  2021-11-05 20:28 ` [PATCH 04/20] btrfs-progs: add a helper for setting up a root node Josef Bacik
@ 2021-11-05 20:28 ` Josef Bacik
  2021-11-06  0:20   ` Qu Wenruo
  2021-11-05 20:28 ` [PATCH 06/20] btrfs-progs: check: stop passing csum root around Josef Bacik
                   ` (15 subsequent siblings)
  20 siblings, 1 reply; 42+ messages in thread
From: Josef Bacik @ 2021-11-05 20:28 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

We are going to need to start looking up the csum root based on the
bytenr with extent tree v2.  To that end stop passing the root to the
csum related functions so that can be done in the helper functions
themselves.

There's an unrelated deletion of a function prototype that no longer
exists, if desired I can break that out from this patch.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 check/main.c              | 4 ++--
 convert/main.c            | 1 -
 kernel-shared/ctree.h     | 6 +-----
 kernel-shared/file-item.c | 4 ++--
 mkfs/rootdir.c            | 2 +-
 5 files changed, 6 insertions(+), 11 deletions(-)

diff --git a/check/main.c b/check/main.c
index 235a9bab..08810c5f 100644
--- a/check/main.c
+++ b/check/main.c
@@ -9484,8 +9484,8 @@ static int populate_csum(struct btrfs_trans_handle *trans,
 				       &sectorsize, 0);
 		if (ret)
 			break;
-		ret = btrfs_csum_file_block(trans, csum_root, start + len,
-					    start + offset, buf, sectorsize);
+		ret = btrfs_csum_file_block(trans, start + len, start + offset,
+					    buf, sectorsize);
 		if (ret)
 			break;
 		offset += sectorsize;
diff --git a/convert/main.c b/convert/main.c
index 223eebad..7f33d4e1 100644
--- a/convert/main.c
+++ b/convert/main.c
@@ -187,7 +187,6 @@ static int csum_disk_extent(struct btrfs_trans_handle *trans,
 		if (ret)
 			break;
 		ret = btrfs_csum_file_block(trans,
-					    root->fs_info->csum_root,
 					    disk_bytenr + num_bytes,
 					    disk_bytenr + offset,
 					    buffer, blocksize);
diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h
index 3c0743cc..73904255 100644
--- a/kernel-shared/ctree.h
+++ b/kernel-shared/ctree.h
@@ -2847,12 +2847,8 @@ int btrfs_insert_file_extent(struct btrfs_trans_handle *trans,
 int btrfs_insert_inline_extent(struct btrfs_trans_handle *trans,
 				struct btrfs_root *root, u64 objectid,
 				u64 offset, const char *buffer, size_t size);
-int btrfs_csum_file_block(struct btrfs_trans_handle *trans,
-			  struct btrfs_root *root, u64 alloc_end,
+int btrfs_csum_file_block(struct btrfs_trans_handle *trans, u64 alloc_end,
 			  u64 bytenr, char *data, size_t len);
-int btrfs_csum_truncate(struct btrfs_trans_handle *trans,
-			struct btrfs_root *root, struct btrfs_path *path,
-			u64 isize);
 
 /* uuid-tree.c, interface for mounted mounted filesystem */
 int btrfs_lookup_uuid_subvol_item(int fd, const u8 *uuid, u64 *subvol_id);
diff --git a/kernel-shared/file-item.c b/kernel-shared/file-item.c
index c910e27e..5bf6aab4 100644
--- a/kernel-shared/file-item.c
+++ b/kernel-shared/file-item.c
@@ -183,9 +183,9 @@ fail:
 }
 
 int btrfs_csum_file_block(struct btrfs_trans_handle *trans,
-			  struct btrfs_root *root, u64 alloc_end,
-			  u64 bytenr, char *data, size_t len)
+			  u64 alloc_end, u64 bytenr, char *data, size_t len)
 {
+	struct btrfs_root *root = trans->fs_info->csum_root;
 	int ret = 0;
 	struct btrfs_key file_key;
 	struct btrfs_key found_key;
diff --git a/mkfs/rootdir.c b/mkfs/rootdir.c
index 16ff257a..92be32ea 100644
--- a/mkfs/rootdir.c
+++ b/mkfs/rootdir.c
@@ -403,7 +403,7 @@ again:
 		 * we're doing the csum before we record the extent, but
 		 * that's ok
 		 */
-		ret = btrfs_csum_file_block(trans, root->fs_info->csum_root,
+		ret = btrfs_csum_file_block(trans,
 				first_block + bytes_read + sectorsize,
 				first_block + bytes_read,
 				eb->data, sectorsize);
-- 
2.26.3


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

* [PATCH 06/20] btrfs-progs: check: stop passing csum root around
  2021-11-05 20:28 [PATCH 00/20] btrfs-progs: extent tree v2 global root support prep work Josef Bacik
                   ` (4 preceding siblings ...)
  2021-11-05 20:28 ` [PATCH 05/20] btrfs-progs: btrfs-shared: stop passing root to csum related functions Josef Bacik
@ 2021-11-05 20:28 ` Josef Bacik
  2021-11-06  0:21   ` Qu Wenruo
  2021-11-05 20:28 ` [PATCH 07/20] btrfs-progs: stop accessing ->csum_root directly Josef Bacik
                   ` (14 subsequent siblings)
  20 siblings, 1 reply; 42+ messages in thread
From: Josef Bacik @ 2021-11-05 20:28 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

We pass the csum root from way high in the call chain in check down to
where we actually need it.  However we can just get it from the fs_info
in these places, so clean up the functions to skip passing around the
csum root needlessly.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 check/main.c | 22 +++++++++-------------
 1 file changed, 9 insertions(+), 13 deletions(-)

diff --git a/check/main.c b/check/main.c
index 08810c5f..22306cf4 100644
--- a/check/main.c
+++ b/check/main.c
@@ -9494,9 +9494,9 @@ static int populate_csum(struct btrfs_trans_handle *trans,
 }
 
 static int fill_csum_tree_from_one_fs_root(struct btrfs_trans_handle *trans,
-				      struct btrfs_root *csum_root,
-				      struct btrfs_root *cur_root)
+					   struct btrfs_root *cur_root)
 {
+	struct btrfs_root *csum_root = gfs_info->csum_root;
 	struct btrfs_path path;
 	struct btrfs_key key;
 	struct extent_buffer *node;
@@ -9557,8 +9557,7 @@ out:
 	return ret;
 }
 
-static int fill_csum_tree_from_fs(struct btrfs_trans_handle *trans,
-				  struct btrfs_root *csum_root)
+static int fill_csum_tree_from_fs(struct btrfs_trans_handle *trans)
 {
 	struct btrfs_path path;
 	struct btrfs_root *tree_root = gfs_info->tree_root;
@@ -9598,8 +9597,7 @@ static int fill_csum_tree_from_fs(struct btrfs_trans_handle *trans,
 				key.objectid);
 			goto out;
 		}
-		ret = fill_csum_tree_from_one_fs_root(trans, csum_root,
-				cur_root);
+		ret = fill_csum_tree_from_one_fs_root(trans, cur_root);
 		if (ret < 0)
 			goto out;
 next:
@@ -9617,10 +9615,10 @@ out:
 	return ret;
 }
 
-static int fill_csum_tree_from_extent(struct btrfs_trans_handle *trans,
-				      struct btrfs_root *csum_root)
+static int fill_csum_tree_from_extent(struct btrfs_trans_handle *trans)
 {
 	struct btrfs_root *extent_root = gfs_info->extent_root;
+	struct btrfs_root *csum_root = gfs_info->csum_root;
 	struct btrfs_path path;
 	struct btrfs_extent_item *ei;
 	struct extent_buffer *leaf;
@@ -9690,13 +9688,12 @@ static int fill_csum_tree_from_extent(struct btrfs_trans_handle *trans,
  * will use fs/subvol trees to init the csum tree.
  */
 static int fill_csum_tree(struct btrfs_trans_handle *trans,
-			  struct btrfs_root *csum_root,
 			  int search_fs_tree)
 {
 	if (search_fs_tree)
-		return fill_csum_tree_from_fs(trans, csum_root);
+		return fill_csum_tree_from_fs(trans);
 	else
-		return fill_csum_tree_from_extent(trans, csum_root);
+		return fill_csum_tree_from_extent(trans);
 }
 
 static void free_roots_info_cache(void)
@@ -10700,8 +10697,7 @@ static int cmd_check(const struct cmd_struct *cmd, int argc, char **argv)
 				goto close_out;
 			}
 
-			ret = fill_csum_tree(trans, gfs_info->csum_root,
-					     init_extent_tree);
+			ret = fill_csum_tree(trans, init_extent_tree);
 			err |= !!ret;
 			if (ret) {
 				error("checksum tree refilling failed: %d", ret);
-- 
2.26.3


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

* [PATCH 07/20] btrfs-progs: stop accessing ->csum_root directly
  2021-11-05 20:28 [PATCH 00/20] btrfs-progs: extent tree v2 global root support prep work Josef Bacik
                   ` (5 preceding siblings ...)
  2021-11-05 20:28 ` [PATCH 06/20] btrfs-progs: check: stop passing csum root around Josef Bacik
@ 2021-11-05 20:28 ` Josef Bacik
  2021-11-06  0:23   ` Qu Wenruo
  2021-11-05 20:28 ` [PATCH 08/20] btrfs-progs: image: keep track of seen blocks when walking trees Josef Bacik
                   ` (13 subsequent siblings)
  20 siblings, 1 reply; 42+ messages in thread
From: Josef Bacik @ 2021-11-05 20:28 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

With extent tree v2 we will have per-block group checksums, so add a
helper to access the csum root and rename the fs_info csum_root to
_csum_root to catch all the places that are accessing it directly.
Convert everybody to use the helper except for internal things.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 btrfs-corrupt-block.c       |  2 +-
 check/main.c                | 15 ++++++++++-----
 check/mode-common.c         |  6 +++---
 cmds/rescue-chunk-recover.c | 17 ++++++++---------
 kernel-shared/ctree.h       |  2 +-
 kernel-shared/disk-io.c     | 28 +++++++++++++++++-----------
 kernel-shared/disk-io.h     |  2 +-
 kernel-shared/file-item.c   |  4 ++--
 mkfs/main.c                 |  3 ++-
 9 files changed, 45 insertions(+), 34 deletions(-)

diff --git a/btrfs-corrupt-block.c b/btrfs-corrupt-block.c
index c1624ee1..d7904b6f 100644
--- a/btrfs-corrupt-block.c
+++ b/btrfs-corrupt-block.c
@@ -1031,7 +1031,7 @@ static int delete_csum(struct btrfs_root *root, u64 bytenr, u64 bytes)
 	struct btrfs_trans_handle *trans;
 	int ret;
 
-	root = root->fs_info->csum_root;
+	root = btrfs_csum_root(root->fs_info, bytenr);
 	trans = btrfs_start_transaction(root, 1);
 	if (IS_ERR(trans)) {
 		fprintf(stderr, "Couldn't start transaction %ld\n",
diff --git a/check/main.c b/check/main.c
index 22306cf4..632dfba0 100644
--- a/check/main.c
+++ b/check/main.c
@@ -5988,7 +5988,7 @@ static int check_csums(struct btrfs_root *root)
 	unsigned long leaf_offset;
 	bool verify_csum = !!check_data_csum;
 
-	root = gfs_info->csum_root;
+	root = btrfs_csum_root(gfs_info, 0);
 	if (!extent_buffer_uptodate(root->node)) {
 		fprintf(stderr, "No valid csum tree found\n");
 		return -ENOENT;
@@ -9496,7 +9496,7 @@ static int populate_csum(struct btrfs_trans_handle *trans,
 static int fill_csum_tree_from_one_fs_root(struct btrfs_trans_handle *trans,
 					   struct btrfs_root *cur_root)
 {
-	struct btrfs_root *csum_root = gfs_info->csum_root;
+	struct btrfs_root *csum_root;
 	struct btrfs_path path;
 	struct btrfs_key key;
 	struct extent_buffer *node;
@@ -9532,6 +9532,7 @@ static int fill_csum_tree_from_one_fs_root(struct btrfs_trans_handle *trans,
 		start = btrfs_file_extent_disk_bytenr(node, fi);
 		len = btrfs_file_extent_disk_num_bytes(node, fi);
 
+		csum_root = btrfs_csum_root(gfs_info, start);
 		ret = populate_csum(trans, csum_root, buf, start, len);
 		if (ret == -EEXIST)
 			ret = 0;
@@ -9618,7 +9619,7 @@ out:
 static int fill_csum_tree_from_extent(struct btrfs_trans_handle *trans)
 {
 	struct btrfs_root *extent_root = gfs_info->extent_root;
-	struct btrfs_root *csum_root = gfs_info->csum_root;
+	struct btrfs_root *csum_root;
 	struct btrfs_path path;
 	struct btrfs_extent_item *ei;
 	struct extent_buffer *leaf;
@@ -9668,6 +9669,7 @@ static int fill_csum_tree_from_extent(struct btrfs_trans_handle *trans)
 			continue;
 		}
 
+		csum_root = btrfs_csum_root(gfs_info, key.objectid);
 		ret = populate_csum(trans, csum_root, buf, key.objectid,
 				    key.offset);
 		if (ret)
@@ -10688,7 +10690,8 @@ static int cmd_check(const struct cmd_struct *cmd, int argc, char **argv)
 
 		if (init_csum_tree) {
 			printf("Reinitialize checksum tree\n");
-			ret = btrfs_fsck_reinit_root(trans, gfs_info->csum_root);
+			ret = btrfs_fsck_reinit_root(trans,
+						btrfs_csum_root(gfs_info, 0));
 			if (ret) {
 				error("checksum tree initialization failed: %d",
 						ret);
@@ -10719,7 +10722,9 @@ static int cmd_check(const struct cmd_struct *cmd, int argc, char **argv)
 		err |= !!ret;
 		goto close_out;
 	}
-	if (!extent_buffer_uptodate(gfs_info->csum_root->node)) {
+
+	root = btrfs_csum_root(gfs_info, 0);
+	if (!extent_buffer_uptodate(root->node)) {
 		error("critical: csum_root, unable to check the filesystem");
 		ret = -EIO;
 		err |= !!ret;
diff --git a/check/mode-common.c b/check/mode-common.c
index 0059672c..0c3bd38b 100644
--- a/check/mode-common.c
+++ b/check/mode-common.c
@@ -287,6 +287,7 @@ out:
  */
 int count_csum_range(u64 start, u64 len, u64 *found)
 {
+	struct btrfs_root *csum_root = btrfs_csum_root(gfs_info, start);
 	struct btrfs_key key;
 	struct btrfs_path path;
 	struct extent_buffer *leaf;
@@ -302,8 +303,7 @@ int count_csum_range(u64 start, u64 len, u64 *found)
 	key.offset = start;
 	key.type = BTRFS_EXTENT_CSUM_KEY;
 
-	ret = btrfs_search_slot(NULL, gfs_info->csum_root,
-				&key, &path, 0, 0);
+	ret = btrfs_search_slot(NULL, csum_root, &key, &path, 0, 0);
 	if (ret < 0)
 		goto out;
 	if (ret > 0 && path.slots[0] > 0) {
@@ -317,7 +317,7 @@ int count_csum_range(u64 start, u64 len, u64 *found)
 	while (len > 0) {
 		leaf = path.nodes[0];
 		if (path.slots[0] >= btrfs_header_nritems(leaf)) {
-			ret = btrfs_next_leaf(gfs_info->csum_root, &path);
+			ret = btrfs_next_leaf(csum_root, &path);
 			if (ret > 0)
 				break;
 			else if (ret < 0)
diff --git a/cmds/rescue-chunk-recover.c b/cmds/rescue-chunk-recover.c
index 03c7f48f..115d91d7 100644
--- a/cmds/rescue-chunk-recover.c
+++ b/cmds/rescue-chunk-recover.c
@@ -1801,7 +1801,7 @@ static int btrfs_rebuild_chunk_stripes(struct recover_control *rc,
 	return ret;
 }
 
-static int next_csum(struct btrfs_root *root,
+static int next_csum(struct btrfs_root *csum_root,
 		     struct extent_buffer **leaf,
 		     struct btrfs_path *path,
 		     int *slot,
@@ -1811,10 +1811,9 @@ static int next_csum(struct btrfs_root *root,
 		     struct btrfs_key *key)
 {
 	int ret = 0;
-	struct btrfs_root *csum_root = root->fs_info->csum_root;
 	struct btrfs_csum_item *csum_item;
-	u32 blocksize = root->fs_info->sectorsize;
-	u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
+	u32 blocksize = csum_root->fs_info->sectorsize;
+	u16 csum_size = btrfs_super_csum_size(csum_root->fs_info->super_copy);
 	int csums_in_item = btrfs_item_size_nr(*leaf, *slot) / csum_size;
 
 	if (*csum_offset >= csums_in_item) {
@@ -1994,7 +1993,6 @@ static int rebuild_raid_data_chunk_stripes(struct recover_control *rc,
 	LIST_HEAD(unordered);
 	LIST_HEAD(candidates);
 
-	csum_root = root->fs_info->csum_root;
 	btrfs_init_path(&path);
 	list_splice_init(&chunk->dextents, &candidates);
 again:
@@ -2005,6 +2003,7 @@ again:
 	key.type = BTRFS_EXTENT_CSUM_KEY;
 	key.offset = start;
 
+	csum_root = btrfs_csum_root(root->fs_info, start);
 	ret = btrfs_search_slot(NULL, csum_root, &key, &path, 0, 0);
 	if (ret < 0) {
 		fprintf(stderr, "Search csum failed(%d)\n", ret);
@@ -2022,8 +2021,8 @@ again:
 			} else if (ret > 0) {
 				slot = btrfs_header_nritems(leaf) - 1;
 				btrfs_item_key_to_cpu(leaf, &key, slot);
-				if (item_end_offset(root, &key, leaf, slot)
-								> start) {
+				if (item_end_offset(csum_root, &key,
+						    leaf, slot) > start) {
 					csum_offset = start - key.offset;
 					csum_offset /= blocksize;
 					goto next_csum;
@@ -2061,8 +2060,8 @@ again:
 			goto out;
 	}
 next_csum:
-	ret = next_csum(root, &leaf, &path, &slot, &csum_offset, &tree_csum,
-			end, &key);
+	ret = next_csum(csum_root, &leaf, &path, &slot, &csum_offset,
+			&tree_csum, end, &key);
 	if (ret < 0) {
 		fprintf(stderr, "Fetch csum failed\n");
 		goto fail_out;
diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h
index 73904255..d2d1a006 100644
--- a/kernel-shared/ctree.h
+++ b/kernel-shared/ctree.h
@@ -1161,7 +1161,7 @@ struct btrfs_fs_info {
 	struct btrfs_root *tree_root;
 	struct btrfs_root *chunk_root;
 	struct btrfs_root *dev_root;
-	struct btrfs_root *csum_root;
+	struct btrfs_root *_csum_root;
 	struct btrfs_root *quota_root;
 	struct btrfs_root *free_space_root;
 	struct btrfs_root *uuid_root;
diff --git a/kernel-shared/disk-io.c b/kernel-shared/disk-io.c
index 1f940221..c1d55692 100644
--- a/kernel-shared/disk-io.c
+++ b/kernel-shared/disk-io.c
@@ -744,6 +744,12 @@ int btrfs_fs_roots_compare_roots(struct rb_node *node1, struct rb_node *node2)
 	return btrfs_fs_roots_compare_objectids(node1, (void *)&root->objectid);
 }
 
+struct btrfs_root *btrfs_csum_root(struct btrfs_fs_info *fs_info,
+				   u64 bytenr)
+{
+	return fs_info->_csum_root;
+}
+
 struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
 				      struct btrfs_key *location)
 {
@@ -761,7 +767,7 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
 	if (location->objectid == BTRFS_DEV_TREE_OBJECTID)
 		return fs_info->dev_root;
 	if (location->objectid == BTRFS_CSUM_TREE_OBJECTID)
-		return fs_info->csum_root;
+		return btrfs_csum_root(fs_info, location->offset);
 	if (location->objectid == BTRFS_UUID_TREE_OBJECTID)
 		return fs_info->uuid_root ? fs_info->uuid_root : ERR_PTR(-ENOENT);
 	if (location->objectid == BTRFS_QUOTA_TREE_OBJECTID)
@@ -797,7 +803,7 @@ void btrfs_free_fs_info(struct btrfs_fs_info *fs_info)
 	free(fs_info->extent_root);
 	free(fs_info->chunk_root);
 	free(fs_info->dev_root);
-	free(fs_info->csum_root);
+	free(fs_info->_csum_root);
 	free(fs_info->free_space_root);
 	free(fs_info->uuid_root);
 	free(fs_info->super_copy);
@@ -817,7 +823,7 @@ struct btrfs_fs_info *btrfs_new_fs_info(int writable, u64 sb_bytenr)
 	fs_info->extent_root = calloc(1, sizeof(struct btrfs_root));
 	fs_info->chunk_root = calloc(1, sizeof(struct btrfs_root));
 	fs_info->dev_root = calloc(1, sizeof(struct btrfs_root));
-	fs_info->csum_root = calloc(1, sizeof(struct btrfs_root));
+	fs_info->_csum_root = calloc(1, sizeof(struct btrfs_root));
 	fs_info->quota_root = calloc(1, sizeof(struct btrfs_root));
 	fs_info->free_space_root = calloc(1, sizeof(struct btrfs_root));
 	fs_info->uuid_root = calloc(1, sizeof(struct btrfs_root));
@@ -825,7 +831,7 @@ struct btrfs_fs_info *btrfs_new_fs_info(int writable, u64 sb_bytenr)
 
 	if (!fs_info->tree_root || !fs_info->extent_root ||
 	    !fs_info->chunk_root || !fs_info->dev_root ||
-	    !fs_info->csum_root || !fs_info->quota_root ||
+	    !fs_info->_csum_root || !fs_info->quota_root ||
 	    !fs_info->free_space_root || !fs_info->uuid_root ||
 	    !fs_info->super_copy)
 		goto free_all;
@@ -993,11 +999,11 @@ int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info, u64 root_tree_bytenr,
 	}
 	fs_info->dev_root->track_dirty = 1;
 
-	ret = setup_root_or_create_block(fs_info, flags, fs_info->csum_root,
+	ret = setup_root_or_create_block(fs_info, flags, fs_info->_csum_root,
 					 BTRFS_CSUM_TREE_OBJECTID, "csum");
 	if (ret)
 		return ret;
-	fs_info->csum_root->track_dirty = 1;
+	fs_info->_csum_root->track_dirty = 1;
 
 	ret = find_and_setup_root(root, fs_info, BTRFS_UUID_TREE_OBJECTID,
 				  fs_info->uuid_root);
@@ -1072,8 +1078,8 @@ void btrfs_release_all_roots(struct btrfs_fs_info *fs_info)
 		free_extent_buffer(fs_info->free_space_root->node);
 	if (fs_info->quota_root)
 		free_extent_buffer(fs_info->quota_root->node);
-	if (fs_info->csum_root)
-		free_extent_buffer(fs_info->csum_root->node);
+	if (fs_info->_csum_root)
+		free_extent_buffer(fs_info->_csum_root->node);
 	if (fs_info->dev_root)
 		free_extent_buffer(fs_info->dev_root->node);
 	if (fs_info->extent_root)
@@ -1854,11 +1860,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, info->_csum_root->node->start);
 	btrfs_set_backup_csum_root_gen(root_backup,
-			       btrfs_header_generation(info->csum_root->node));
+			       btrfs_header_generation(info->_csum_root->node));
 	btrfs_set_backup_csum_root_level(root_backup,
-			       btrfs_header_level(info->csum_root->node));
+			       btrfs_header_level(info->_csum_root->node));
 
 	btrfs_set_backup_total_bytes(root_backup,
 			     btrfs_super_total_bytes(info->super_copy));
diff --git a/kernel-shared/disk-io.h b/kernel-shared/disk-io.h
index e113d842..38abbca5 100644
--- a/kernel-shared/disk-io.h
+++ b/kernel-shared/disk-io.h
@@ -217,5 +217,5 @@ int btrfs_fs_roots_compare_roots(struct rb_node *node1, struct rb_node *node2);
 struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans,
 				     struct btrfs_fs_info *fs_info,
 				     u64 objectid);
-
+struct btrfs_root *btrfs_csum_root(struct btrfs_fs_info *fs_info, u64 bytenr);
 #endif
diff --git a/kernel-shared/file-item.c b/kernel-shared/file-item.c
index 5bf6aab4..12932e1d 100644
--- a/kernel-shared/file-item.c
+++ b/kernel-shared/file-item.c
@@ -185,7 +185,7 @@ fail:
 int btrfs_csum_file_block(struct btrfs_trans_handle *trans,
 			  u64 alloc_end, u64 bytenr, char *data, size_t len)
 {
-	struct btrfs_root *root = trans->fs_info->csum_root;
+	struct btrfs_root *root = btrfs_csum_root(trans->fs_info, bytenr);
 	int ret = 0;
 	struct btrfs_key file_key;
 	struct btrfs_key found_key;
@@ -401,7 +401,7 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans, u64 bytenr, u64 len)
 	int ret;
 	u16 csum_size = btrfs_super_csum_size(trans->fs_info->super_copy);
 	int blocksize = trans->fs_info->sectorsize;
-	struct btrfs_root *csum_root = trans->fs_info->csum_root;
+	struct btrfs_root *csum_root = btrfs_csum_root(trans->fs_info, bytenr);
 
 
 	path = btrfs_alloc_path();
diff --git a/mkfs/main.c b/mkfs/main.c
index ce86a0db..c6cc51e9 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -268,6 +268,7 @@ static int recow_roots(struct btrfs_trans_handle *trans,
 		       struct btrfs_root *root)
 {
 	struct btrfs_fs_info *info = root->fs_info;
+	struct btrfs_root *csum_root = btrfs_csum_root(info, 0);
 	int ret;
 
 	ret = __recow_root(trans, info->fs_root);
@@ -285,7 +286,7 @@ static int recow_roots(struct btrfs_trans_handle *trans,
 	ret = __recow_root(trans, info->dev_root);
 	if (ret)
 		return ret;
-	ret = __recow_root(trans, info->csum_root);
+	ret = __recow_root(trans, csum_root);
 	if (ret)
 		return ret;
 	if (info->free_space_root) {
-- 
2.26.3


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

* [PATCH 08/20] btrfs-progs: image: keep track of seen blocks when walking trees
  2021-11-05 20:28 [PATCH 00/20] btrfs-progs: extent tree v2 global root support prep work Josef Bacik
                   ` (6 preceding siblings ...)
  2021-11-05 20:28 ` [PATCH 07/20] btrfs-progs: stop accessing ->csum_root directly Josef Bacik
@ 2021-11-05 20:28 ` Josef Bacik
  2021-11-06  0:26   ` Qu Wenruo
  2021-11-05 20:28 ` [PATCH 09/20] btrfs-progs: common: move btrfs_fix_block_accounting to repair.c Josef Bacik
                   ` (12 subsequent siblings)
  20 siblings, 1 reply; 42+ messages in thread
From: Josef Bacik @ 2021-11-05 20:28 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

Extent tree v2 no longer tracks all allocated blocks on the file system,
so we'll have to default to walking trees to generate metadata images.
There's an annoying drawback with walking trees with btrfs-image where
we'll happily copy multiple blocks over and over again if there are
snapshots.  Fix this by keeping track of blocks we've seen and simply
skipping blocks that we've already queued up for copying.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 image/main.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/image/main.c b/image/main.c
index dbce17e7..57e0cb6c 100644
--- a/image/main.c
+++ b/image/main.c
@@ -93,6 +93,8 @@ struct metadump_struct {
 	pthread_cond_t cond;
 	struct rb_root name_tree;
 
+	struct extent_io_tree seen;
+
 	struct list_head list;
 	struct list_head ordered;
 	size_t num_items;
@@ -461,6 +463,7 @@ static void metadump_destroy(struct metadump_struct *md, int num_threads)
 		free(name->sub);
 		free(name);
 	}
+	extent_io_tree_cleanup(&md->seen);
 }
 
 static int metadump_init(struct metadump_struct *md, struct btrfs_root *root,
@@ -476,6 +479,7 @@ static int metadump_init(struct metadump_struct *md, struct btrfs_root *root,
 	memset(md, 0, sizeof(*md));
 	INIT_LIST_HEAD(&md->list);
 	INIT_LIST_HEAD(&md->ordered);
+	extent_io_tree_init(&md->seen);
 	md->root = root;
 	md->out = out;
 	md->pending_start = (u64)-1;
@@ -771,6 +775,14 @@ static int copy_tree_blocks(struct btrfs_root *root, struct extent_buffer *eb,
 	int i = 0;
 	int ret;
 
+	bytenr = btrfs_header_bytenr(eb);
+	if (test_range_bit(&metadump->seen, bytenr,
+			   bytenr + fs_info->nodesize - 1, EXTENT_DIRTY, 1))
+		return 0;
+
+	set_extent_dirty(&metadump->seen, bytenr,
+			 bytenr + fs_info->nodesize - 1);
+
 	ret = add_extent(btrfs_header_bytenr(eb), fs_info->nodesize,
 			 metadump, 0);
 	if (ret) {
-- 
2.26.3


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

* [PATCH 09/20] btrfs-progs: common: move btrfs_fix_block_accounting to repair.c
  2021-11-05 20:28 [PATCH 00/20] btrfs-progs: extent tree v2 global root support prep work Josef Bacik
                   ` (7 preceding siblings ...)
  2021-11-05 20:28 ` [PATCH 08/20] btrfs-progs: image: keep track of seen blocks when walking trees Josef Bacik
@ 2021-11-05 20:28 ` Josef Bacik
  2021-11-06  0:30   ` Qu Wenruo
  2021-11-05 20:28 ` [PATCH 10/20] btrfs-progs: check: abstract out the used marking helpers Josef Bacik
                   ` (11 subsequent siblings)
  20 siblings, 1 reply; 42+ messages in thread
From: Josef Bacik @ 2021-11-05 20:28 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

We have this helper sitting in extent-tree.c, but it's a repair
function.  I'm going to need to make changes to this for extent-tree-v2
and would rather this live outside of the code we need to share with the
kernel.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 common/repair.c             | 75 +++++++++++++++++++++++++++++++++++++
 common/repair.h             |  1 +
 kernel-shared/extent-tree.c | 74 ------------------------------------
 3 files changed, 76 insertions(+), 74 deletions(-)

diff --git a/common/repair.c b/common/repair.c
index 6eed7cec..a5ba43e2 100644
--- a/common/repair.c
+++ b/common/repair.c
@@ -17,6 +17,7 @@
  */
 
 #include "kernel-shared/ctree.h"
+#include "kernel-shared/transaction.h"
 #include "common/extent-cache.h"
 #include "common/utils.h"
 #include "common/repair.h"
@@ -50,3 +51,77 @@ int btrfs_add_corrupt_extent_record(struct btrfs_fs_info *info,
 	return ret;
 }
 
+/*
+ * Fixup block accounting. The initial block accounting created by
+ * make_block_groups isn't accuracy in this case.
+ */
+int btrfs_fix_block_accounting(struct btrfs_trans_handle *trans)
+{
+	int ret = 0;
+	int slot;
+	u64 start = 0;
+	u64 bytes_used = 0;
+	struct btrfs_path path;
+	struct btrfs_key key;
+	struct extent_buffer *leaf;
+	struct btrfs_block_group *cache;
+	struct btrfs_fs_info *fs_info = trans->fs_info;
+	struct btrfs_root *root = fs_info->extent_root;
+
+	ret = btrfs_run_delayed_refs(trans, -1);
+	if (ret)
+		return ret;
+
+	while(1) {
+		cache = btrfs_lookup_first_block_group(fs_info, start);
+		if (!cache)
+			break;
+
+		start = cache->start + cache->length;
+		cache->used = 0;
+		cache->space_info->bytes_used = 0;
+		if (list_empty(&cache->dirty_list))
+			list_add_tail(&cache->dirty_list, &trans->dirty_bgs);
+	}
+
+	btrfs_init_path(&path);
+	key.offset = 0;
+	key.objectid = 0;
+	key.type = BTRFS_EXTENT_ITEM_KEY;
+	ret = btrfs_search_slot(trans, root->fs_info->extent_root,
+				&key, &path, 0, 0);
+	if (ret < 0)
+		return ret;
+	while(1) {
+		leaf = path.nodes[0];
+		slot = path.slots[0];
+		if (slot >= btrfs_header_nritems(leaf)) {
+			ret = btrfs_next_leaf(root, &path);
+			if (ret < 0)
+				return ret;
+			if (ret > 0)
+				break;
+			leaf = path.nodes[0];
+			slot = path.slots[0];
+		}
+		btrfs_item_key_to_cpu(leaf, &key, slot);
+		if (key.type == BTRFS_EXTENT_ITEM_KEY) {
+			bytes_used += key.offset;
+			ret = btrfs_update_block_group(trans,
+				  key.objectid, key.offset, 1, 0);
+			BUG_ON(ret);
+		} else if (key.type == BTRFS_METADATA_ITEM_KEY) {
+			bytes_used += fs_info->nodesize;
+			ret = btrfs_update_block_group(trans,
+				  key.objectid, fs_info->nodesize, 1, 0);
+			if (ret)
+				goto out;
+		}
+		path.slots[0]++;
+	}
+	btrfs_set_super_bytes_used(root->fs_info->super_copy, bytes_used);
+	ret = 0;
+out:
+	btrfs_release_path(&path);
+	return ret;
+}
diff --git a/common/repair.h b/common/repair.h
index d1794610..4e1fa3e7 100644
--- a/common/repair.h
+++ b/common/repair.h
@@ -32,5 +32,6 @@ struct btrfs_corrupt_block {
 int btrfs_add_corrupt_extent_record(struct btrfs_fs_info *info,
 				    struct btrfs_key *first_key,
 				    u64 start, u64 len, int level);
+int btrfs_fix_block_accounting(struct btrfs_trans_handle *trans);
 
 #endif
diff --git a/kernel-shared/extent-tree.c b/kernel-shared/extent-tree.c
index a918e5aa..402904d1 100644
--- a/kernel-shared/extent-tree.c
+++ b/kernel-shared/extent-tree.c
@@ -3247,80 +3247,6 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
 	return ret;
 }
 
-/*
- * Fixup block accounting. The initial block accounting created by
- * make_block_groups isn't accuracy in this case.
- */
-int btrfs_fix_block_accounting(struct btrfs_trans_handle *trans)
-{
-	int ret = 0;
-	int slot;
-	u64 start = 0;
-	u64 bytes_used = 0;
-	struct btrfs_path path;
-	struct btrfs_key key;
-	struct extent_buffer *leaf;
-	struct btrfs_block_group *cache;
-	struct btrfs_fs_info *fs_info = trans->fs_info;
-	struct btrfs_root *root = fs_info->extent_root;
-
-	ret = btrfs_run_delayed_refs(trans, -1);
-	if (ret)
-		return ret;
-
-	while(1) {
-		cache = btrfs_lookup_first_block_group(fs_info, start);
-		if (!cache)
-			break;
-
-		start = cache->start + cache->length;
-		cache->used = 0;
-		cache->space_info->bytes_used = 0;
-		if (list_empty(&cache->dirty_list))
-			list_add_tail(&cache->dirty_list, &trans->dirty_bgs);
-	}
-
-	btrfs_init_path(&path);
-	key.offset = 0;
-	key.objectid = 0;
-	key.type = BTRFS_EXTENT_ITEM_KEY;
-	ret = btrfs_search_slot(trans, root->fs_info->extent_root,
-				&key, &path, 0, 0);
-	if (ret < 0)
-		return ret;
-	while(1) {
-		leaf = path.nodes[0];
-		slot = path.slots[0];
-		if (slot >= btrfs_header_nritems(leaf)) {
-			ret = btrfs_next_leaf(root, &path);
-			if (ret < 0)
-				return ret;
-			if (ret > 0)
-				break;
-			leaf = path.nodes[0];
-			slot = path.slots[0];
-		}
-		btrfs_item_key_to_cpu(leaf, &key, slot);
-		if (key.type == BTRFS_EXTENT_ITEM_KEY) {
-			bytes_used += key.offset;
-			ret = btrfs_update_block_group(trans,
-				  key.objectid, key.offset, 1, 0);
-			BUG_ON(ret);
-		} else if (key.type == BTRFS_METADATA_ITEM_KEY) {
-			bytes_used += fs_info->nodesize;
-			ret = btrfs_update_block_group(trans,
-				  key.objectid, fs_info->nodesize, 1, 0);
-			if (ret)
-				goto out;
-		}
-		path.slots[0]++;
-	}
-	btrfs_set_super_bytes_used(root->fs_info->super_copy, bytes_used);
-	ret = 0;
-out:
-	btrfs_release_path(&path);
-	return ret;
-}
 
 static void __get_extent_size(struct btrfs_root *root, struct btrfs_path *path,
 			      u64 *start, u64 *len)
-- 
2.26.3


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

* [PATCH 10/20] btrfs-progs: check: abstract out the used marking helpers
  2021-11-05 20:28 [PATCH 00/20] btrfs-progs: extent tree v2 global root support prep work Josef Bacik
                   ` (8 preceding siblings ...)
  2021-11-05 20:28 ` [PATCH 09/20] btrfs-progs: common: move btrfs_fix_block_accounting to repair.c Josef Bacik
@ 2021-11-05 20:28 ` Josef Bacik
  2021-11-06  0:37   ` Qu Wenruo
  2021-11-05 20:28 ` [PATCH 11/20] btrfs-progs: check: move btrfs_mark_used_tree_blocks to common Josef Bacik
                   ` (10 subsequent siblings)
  20 siblings, 1 reply; 42+ messages in thread
From: Josef Bacik @ 2021-11-05 20:28 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

We will walk all referenced tree blocks during check in order to avoid
writing over any referenced blocks during fsck.  However in the future
we're going to need to do this for things like fixing block group
accounting with extent tree v2.  This is because extent tree v2 will not
refer to all of the allocated blocks in the extent tree.  Refactor the
code some to allow us to send down an arbitrary extent_io_tree so we can
use this helper for any case where we need to figure out where all the
used space is on an extent tree v2 file system.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 check/mode-common.c | 57 ++++++++++++++++++++-------------------------
 1 file changed, 25 insertions(+), 32 deletions(-)

diff --git a/check/mode-common.c b/check/mode-common.c
index 0c3bd38b..a4a09714 100644
--- a/check/mode-common.c
+++ b/check/mode-common.c
@@ -599,23 +599,21 @@ void reset_cached_block_groups()
 	}
 }
 
-static int traverse_tree_blocks(struct extent_buffer *eb, int tree_root, int pin)
+static int traverse_tree_blocks(struct btrfs_fs_info *fs_info,
+				struct extent_io_tree *tree,
+				struct extent_buffer *eb, int tree_root)
 {
 	struct extent_buffer *tmp;
 	struct btrfs_root_item *ri;
 	struct btrfs_key key;
-	struct extent_io_tree *tree;
 	u64 bytenr;
 	int level = btrfs_header_level(eb);
 	int nritems;
 	int ret;
 	int i;
 	u64 end = eb->start + eb->len;
+	bool pin = tree == &fs_info->pinned_extents;
 
-	if (pin)
-		tree = &gfs_info->pinned_extents;
-	else
-		tree = gfs_info->excluded_extents;
 	/*
 	 * If we have pinned/excluded this block before, don't do it again.
 	 * This can not only avoid forever loop with broken filesystem
@@ -625,7 +623,7 @@ static int traverse_tree_blocks(struct extent_buffer *eb, int tree_root, int pin
 		return 0;
 
 	if (pin)
-		btrfs_pin_extent(gfs_info, eb->start, eb->len);
+		btrfs_pin_extent(fs_info, eb->start, eb->len);
 	else
 		set_extent_dirty(tree, eb->start, end - 1);
 
@@ -654,12 +652,12 @@ static int traverse_tree_blocks(struct extent_buffer *eb, int tree_root, int pin
 			 * in, but for now this doesn't actually use the root so
 			 * just pass in extent_root.
 			 */
-			tmp = read_tree_block(gfs_info, bytenr, 0);
+			tmp = read_tree_block(fs_info, bytenr, 0);
 			if (!extent_buffer_uptodate(tmp)) {
 				fprintf(stderr, "Error reading root block\n");
 				return -EIO;
 			}
-			ret = traverse_tree_blocks(tmp, 0, pin);
+			ret = traverse_tree_blocks(fs_info, tree, tmp, 0);
 			free_extent_buffer(tmp);
 			if (ret)
 				return ret;
@@ -669,20 +667,21 @@ static int traverse_tree_blocks(struct extent_buffer *eb, int tree_root, int pin
 			/* If we aren't the tree root don't read the block */
 			if (level == 1 && !tree_root) {
 				if (pin)
-					btrfs_pin_extent(gfs_info, bytenr,
-							 gfs_info->nodesize);
+					btrfs_pin_extent(fs_info, bytenr,
+							 fs_info->nodesize);
 				else
 					set_extent_dirty(tree, bytenr,
-							 gfs_info->nodesize);
+							 fs_info->nodesize);
 				continue;
 			}
 
-			tmp = read_tree_block(gfs_info, bytenr, 0);
+			tmp = read_tree_block(fs_info, bytenr, 0);
 			if (!extent_buffer_uptodate(tmp)) {
 				fprintf(stderr, "Error reading tree block\n");
 				return -EIO;
 			}
-			ret = traverse_tree_blocks(tmp, tree_root, pin);
+			ret = traverse_tree_blocks(fs_info, tree, tmp,
+						   tree_root);
 			free_extent_buffer(tmp);
 			if (ret)
 				return ret;
@@ -692,30 +691,27 @@ static int traverse_tree_blocks(struct extent_buffer *eb, int tree_root, int pin
 	return 0;
 }
 
-static int pin_down_tree_blocks(struct extent_buffer *eb, int tree_root)
-{
-	return traverse_tree_blocks(eb, tree_root, 1);
-}
-
-int pin_metadata_blocks(void)
+int btrfs_mark_used_tree_blocks(struct btrfs_fs_info *fs_info,
+				struct extent_io_tree *tree)
 {
 	int ret;
 
-	ret = pin_down_tree_blocks(gfs_info->chunk_root->node, 0);
-	if (ret)
-		return ret;
-
-	return pin_down_tree_blocks(gfs_info->tree_root->node, 1);
+	ret = traverse_tree_blocks(fs_info, tree,
+				   fs_info->chunk_root->node, 0);
+	if (!ret)
+		ret = traverse_tree_blocks(fs_info, tree,
+					   fs_info->tree_root->node, 1);
+	return ret;
 }
 
-static int exclude_tree_blocks(struct extent_buffer *eb, int tree_root)
+int pin_metadata_blocks(void)
 {
-	return traverse_tree_blocks(eb, tree_root, 0);
+	return btrfs_mark_used_tree_blocks(gfs_info,
+					   &gfs_info->pinned_extents);
 }
 
 int exclude_metadata_blocks(void)
 {
-	int ret;
 	struct extent_io_tree *excluded_extents;
 
 	excluded_extents = malloc(sizeof(*excluded_extents));
@@ -724,10 +720,7 @@ int exclude_metadata_blocks(void)
 	extent_io_tree_init(excluded_extents);
 	gfs_info->excluded_extents = excluded_extents;
 
-	ret = exclude_tree_blocks(gfs_info->chunk_root->node, 0);
-	if (ret)
-		return ret;
-	return exclude_tree_blocks(gfs_info->tree_root->node, 1);
+	return btrfs_mark_used_tree_blocks(gfs_info, excluded_extents);
 }
 
 void cleanup_excluded_extents(void)
-- 
2.26.3


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

* [PATCH 11/20] btrfs-progs: check: move btrfs_mark_used_tree_blocks to common
  2021-11-05 20:28 [PATCH 00/20] btrfs-progs: extent tree v2 global root support prep work Josef Bacik
                   ` (9 preceding siblings ...)
  2021-11-05 20:28 ` [PATCH 10/20] btrfs-progs: check: abstract out the used marking helpers Josef Bacik
@ 2021-11-05 20:28 ` Josef Bacik
  2021-11-05 20:28 ` [PATCH 12/20] btrfs-progs: mark reloc roots as used Josef Bacik
                   ` (9 subsequent siblings)
  20 siblings, 0 replies; 42+ messages in thread
From: Josef Bacik @ 2021-11-05 20:28 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

This is going to be used for the extent tree v2 stuff more commonly, so
move it out so that it is accessible from everywhere that we need it.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 check/mode-common.c | 105 -------------------------------------------
 common/repair.c     | 106 ++++++++++++++++++++++++++++++++++++++++++++
 common/repair.h     |   2 +
 3 files changed, 108 insertions(+), 105 deletions(-)

diff --git a/check/mode-common.c b/check/mode-common.c
index a4a09714..56377840 100644
--- a/check/mode-common.c
+++ b/check/mode-common.c
@@ -599,111 +599,6 @@ void reset_cached_block_groups()
 	}
 }
 
-static int traverse_tree_blocks(struct btrfs_fs_info *fs_info,
-				struct extent_io_tree *tree,
-				struct extent_buffer *eb, int tree_root)
-{
-	struct extent_buffer *tmp;
-	struct btrfs_root_item *ri;
-	struct btrfs_key key;
-	u64 bytenr;
-	int level = btrfs_header_level(eb);
-	int nritems;
-	int ret;
-	int i;
-	u64 end = eb->start + eb->len;
-	bool pin = tree == &fs_info->pinned_extents;
-
-	/*
-	 * If we have pinned/excluded this block before, don't do it again.
-	 * This can not only avoid forever loop with broken filesystem
-	 * but also give us some speedups.
-	 */
-	if (test_range_bit(tree, eb->start, end - 1, EXTENT_DIRTY, 0))
-		return 0;
-
-	if (pin)
-		btrfs_pin_extent(fs_info, eb->start, eb->len);
-	else
-		set_extent_dirty(tree, eb->start, end - 1);
-
-	nritems = btrfs_header_nritems(eb);
-	for (i = 0; i < nritems; i++) {
-		if (level == 0) {
-			bool is_extent_root;
-			btrfs_item_key_to_cpu(eb, &key, i);
-			if (key.type != BTRFS_ROOT_ITEM_KEY)
-				continue;
-			/* Skip the extent root and reloc roots */
-			if (key.objectid == BTRFS_TREE_RELOC_OBJECTID ||
-			    key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID)
-				continue;
-			is_extent_root =
-				key.objectid == BTRFS_EXTENT_TREE_OBJECTID;
-			/* If pin, skip the extent root */
-			if (pin && is_extent_root)
-				continue;
-			ri = btrfs_item_ptr(eb, i, struct btrfs_root_item);
-			bytenr = btrfs_disk_root_bytenr(eb, ri);
-
-			/*
-			 * If at any point we start needing the real root we
-			 * will have to build a stump root for the root we are
-			 * in, but for now this doesn't actually use the root so
-			 * just pass in extent_root.
-			 */
-			tmp = read_tree_block(fs_info, bytenr, 0);
-			if (!extent_buffer_uptodate(tmp)) {
-				fprintf(stderr, "Error reading root block\n");
-				return -EIO;
-			}
-			ret = traverse_tree_blocks(fs_info, tree, tmp, 0);
-			free_extent_buffer(tmp);
-			if (ret)
-				return ret;
-		} else {
-			bytenr = btrfs_node_blockptr(eb, i);
-
-			/* If we aren't the tree root don't read the block */
-			if (level == 1 && !tree_root) {
-				if (pin)
-					btrfs_pin_extent(fs_info, bytenr,
-							 fs_info->nodesize);
-				else
-					set_extent_dirty(tree, bytenr,
-							 fs_info->nodesize);
-				continue;
-			}
-
-			tmp = read_tree_block(fs_info, bytenr, 0);
-			if (!extent_buffer_uptodate(tmp)) {
-				fprintf(stderr, "Error reading tree block\n");
-				return -EIO;
-			}
-			ret = traverse_tree_blocks(fs_info, tree, tmp,
-						   tree_root);
-			free_extent_buffer(tmp);
-			if (ret)
-				return ret;
-		}
-	}
-
-	return 0;
-}
-
-int btrfs_mark_used_tree_blocks(struct btrfs_fs_info *fs_info,
-				struct extent_io_tree *tree)
-{
-	int ret;
-
-	ret = traverse_tree_blocks(fs_info, tree,
-				   fs_info->chunk_root->node, 0);
-	if (!ret)
-		ret = traverse_tree_blocks(fs_info, tree,
-					   fs_info->tree_root->node, 1);
-	return ret;
-}
-
 int pin_metadata_blocks(void)
 {
 	return btrfs_mark_used_tree_blocks(gfs_info,
diff --git a/common/repair.c b/common/repair.c
index a5ba43e2..79519140 100644
--- a/common/repair.c
+++ b/common/repair.c
@@ -18,6 +18,7 @@
 
 #include "kernel-shared/ctree.h"
 #include "kernel-shared/transaction.h"
+#include "kernel-shared/disk-io.h"
 #include "common/extent-cache.h"
 #include "common/utils.h"
 #include "common/repair.h"
@@ -51,6 +52,111 @@ int btrfs_add_corrupt_extent_record(struct btrfs_fs_info *info,
 	return ret;
 }
 
+static int traverse_tree_blocks(struct btrfs_fs_info *fs_info,
+				struct extent_io_tree *tree,
+				struct extent_buffer *eb, int tree_root)
+{
+	struct extent_buffer *tmp;
+	struct btrfs_root_item *ri;
+	struct btrfs_key key;
+	u64 bytenr;
+	int level = btrfs_header_level(eb);
+	int nritems;
+	int ret;
+	int i;
+	u64 end = eb->start + eb->len;
+	bool pin = tree == &fs_info->pinned_extents;
+
+	/*
+	 * If we have pinned/excluded this block before, don't do it again.
+	 * This can not only avoid forever loop with broken filesystem
+	 * but also give us some speedups.
+	 */
+	if (test_range_bit(tree, eb->start, end - 1, EXTENT_DIRTY, 0))
+		return 0;
+
+	if (pin)
+		btrfs_pin_extent(fs_info, eb->start, eb->len);
+	else
+		set_extent_dirty(tree, eb->start, end - 1);
+
+	nritems = btrfs_header_nritems(eb);
+	for (i = 0; i < nritems; i++) {
+		if (level == 0) {
+			bool is_extent_root;
+			btrfs_item_key_to_cpu(eb, &key, i);
+			if (key.type != BTRFS_ROOT_ITEM_KEY)
+				continue;
+			/* Skip the extent root and reloc roots */
+			if (key.objectid == BTRFS_TREE_RELOC_OBJECTID ||
+			    key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID)
+				continue;
+			is_extent_root =
+				key.objectid == BTRFS_EXTENT_TREE_OBJECTID;
+			/* If pin, skip the extent root */
+			if (pin && is_extent_root)
+				continue;
+			ri = btrfs_item_ptr(eb, i, struct btrfs_root_item);
+			bytenr = btrfs_disk_root_bytenr(eb, ri);
+
+			/*
+			 * If at any point we start needing the real root we
+			 * will have to build a stump root for the root we are
+			 * in, but for now this doesn't actually use the root so
+			 * just pass in extent_root.
+			 */
+			tmp = read_tree_block(fs_info, bytenr, 0);
+			if (!extent_buffer_uptodate(tmp)) {
+				fprintf(stderr, "Error reading root block\n");
+				return -EIO;
+			}
+			ret = traverse_tree_blocks(fs_info, tree, tmp, 0);
+			free_extent_buffer(tmp);
+			if (ret)
+				return ret;
+		} else {
+			bytenr = btrfs_node_blockptr(eb, i);
+
+			/* If we aren't the tree root don't read the block */
+			if (level == 1 && !tree_root) {
+				if (pin)
+					btrfs_pin_extent(fs_info, bytenr,
+							 fs_info->nodesize);
+				else
+					set_extent_dirty(tree, bytenr,
+							 fs_info->nodesize);
+				continue;
+			}
+
+			tmp = read_tree_block(fs_info, bytenr, 0);
+			if (!extent_buffer_uptodate(tmp)) {
+				fprintf(stderr, "Error reading tree block\n");
+				return -EIO;
+			}
+			ret = traverse_tree_blocks(fs_info, tree, tmp,
+						   tree_root);
+			free_extent_buffer(tmp);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return 0;
+}
+
+int btrfs_mark_used_tree_blocks(struct btrfs_fs_info *fs_info,
+				struct extent_io_tree *tree)
+{
+	int ret;
+
+	ret = traverse_tree_blocks(fs_info, tree,
+				   fs_info->chunk_root->node, 0);
+	if (!ret)
+		ret = traverse_tree_blocks(fs_info, tree,
+					   fs_info->tree_root->node, 1);
+	return ret;
+}
+
 /*
  * Fixup block accounting. The initial block accounting created by
  * make_block_groups isn't accuracy in this case.
diff --git a/common/repair.h b/common/repair.h
index 4e1fa3e7..793ebcd2 100644
--- a/common/repair.h
+++ b/common/repair.h
@@ -33,5 +33,7 @@ int btrfs_add_corrupt_extent_record(struct btrfs_fs_info *info,
 				    struct btrfs_key *first_key,
 				    u64 start, u64 len, int level);
 int btrfs_fix_block_accounting(struct btrfs_trans_handle *trans);
+int btrfs_mark_used_tree_blocks(struct btrfs_fs_info *fs_info,
+				struct extent_io_tree *tree);
 
 #endif
-- 
2.26.3


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

* [PATCH 12/20] btrfs-progs: mark reloc roots as used
  2021-11-05 20:28 [PATCH 00/20] btrfs-progs: extent tree v2 global root support prep work Josef Bacik
                   ` (10 preceding siblings ...)
  2021-11-05 20:28 ` [PATCH 11/20] btrfs-progs: check: move btrfs_mark_used_tree_blocks to common Josef Bacik
@ 2021-11-05 20:28 ` Josef Bacik
  2021-11-06  0:39   ` Qu Wenruo
  2021-11-05 20:28 ` [PATCH 13/20] btrfs-progs: stop accessing ->extent_root directly Josef Bacik
                   ` (8 subsequent siblings)
  20 siblings, 1 reply; 42+ messages in thread
From: Josef Bacik @ 2021-11-05 20:28 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

btrfs_mark_used_tree_blocks skips the reloc roots for some reason, which
causes problems because these blocks are in use, and we use this helper
to determine if the block accounting is correct with extent tree v2.

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

diff --git a/common/repair.c b/common/repair.c
index 79519140..413c3e86 100644
--- a/common/repair.c
+++ b/common/repair.c
@@ -87,10 +87,6 @@ static int traverse_tree_blocks(struct btrfs_fs_info *fs_info,
 			btrfs_item_key_to_cpu(eb, &key, i);
 			if (key.type != BTRFS_ROOT_ITEM_KEY)
 				continue;
-			/* Skip the extent root and reloc roots */
-			if (key.objectid == BTRFS_TREE_RELOC_OBJECTID ||
-			    key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID)
-				continue;
 			is_extent_root =
 				key.objectid == BTRFS_EXTENT_TREE_OBJECTID;
 			/* If pin, skip the extent root */
-- 
2.26.3


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

* [PATCH 13/20] btrfs-progs: stop accessing ->extent_root directly
  2021-11-05 20:28 [PATCH 00/20] btrfs-progs: extent tree v2 global root support prep work Josef Bacik
                   ` (11 preceding siblings ...)
  2021-11-05 20:28 ` [PATCH 12/20] btrfs-progs: mark reloc roots as used Josef Bacik
@ 2021-11-05 20:28 ` Josef Bacik
  2021-11-06  0:41   ` Qu Wenruo
  2021-11-05 20:28 ` [PATCH 14/20] btrfs-progs: stop accessing ->free_space_root directly Josef Bacik
                   ` (7 subsequent siblings)
  20 siblings, 1 reply; 42+ messages in thread
From: Josef Bacik @ 2021-11-05 20:28 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

When we switch to multiple global trees we'll need to access the
appropriate extent root depending on the block group or possibly root.
To handle this, use a helper in most places and then the actual root in
places where it is required.  We will whittle down the direct accessors
with future patches, but this does the bulk of the preparatory work.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 btrfs-corrupt-block.c           | 13 +++---
 btrfs-map-logical.c             |  9 ++--
 btrfstune.c                     |  2 +-
 check/main.c                    | 78 +++++++++++++++++++--------------
 check/mode-common.c             |  8 ++--
 check/mode-lowmem.c             | 72 +++++++++++++++++-------------
 check/qgroup-verify.c           |  2 +-
 cmds/rescue-chunk-recover.c     | 18 ++++----
 common/repair.c                 |  5 +--
 convert/main.c                  |  4 +-
 image/main.c                    |  2 +-
 kernel-shared/backref.c         | 10 +++--
 kernel-shared/ctree.h           |  2 +-
 kernel-shared/disk-io.c         | 30 ++++++++-----
 kernel-shared/disk-io.h         |  1 +
 kernel-shared/extent-tree.c     | 42 ++++++++++--------
 kernel-shared/free-space-tree.c |  8 +++-
 kernel-shared/volumes.c         |  3 +-
 kernel-shared/zoned.c           |  2 +-
 mkfs/main.c                     |  4 +-
 20 files changed, 179 insertions(+), 136 deletions(-)

diff --git a/btrfs-corrupt-block.c b/btrfs-corrupt-block.c
index d7904b6f..d976345c 100644
--- a/btrfs-corrupt-block.c
+++ b/btrfs-corrupt-block.c
@@ -183,6 +183,7 @@ static int corrupt_keys_in_block(struct btrfs_fs_info *fs_info, u64 bytenr)
 static int corrupt_extent(struct btrfs_trans_handle *trans,
 			  struct btrfs_root *root, u64 bytenr)
 {
+	struct btrfs_root *extent_root;
 	struct btrfs_key key;
 	struct extent_buffer *leaf;
 	u32 item_size;
@@ -200,9 +201,9 @@ static int corrupt_extent(struct btrfs_trans_handle *trans,
 	key.type = (u8)-1;
 	key.offset = (u64)-1;
 
+	extent_root = btrfs_extent_root(trans->fs_info, bytenr);
 	while(1) {
-		ret = btrfs_search_slot(trans, root->fs_info->extent_root,
-					&key, path, -1, 1);
+		ret = btrfs_search_slot(trans, extent_root, &key, path, -1, 1);
 		if (ret < 0)
 			break;
 
@@ -472,7 +473,7 @@ static int corrupt_block_group(struct btrfs_root *root, u64 bg, char *field)
 	u64 orig, bogus;
 	int ret = 0;
 
-	root = root->fs_info->extent_root;
+	root = btrfs_extent_root(root->fs_info, 0);
 
 	corrupt_field = convert_block_group_field(field);
 	if (corrupt_field == BTRFS_BLOCK_GROUP_ITEM_BAD) {
@@ -1382,11 +1383,13 @@ int main(int argc, char **argv)
 	}
 	if (extent_tree) {
 		struct btrfs_trans_handle *trans;
+		struct btrfs_root *extent_root;
 
+		extent_root = btrfs_extent_root(root->fs_info, 0);
 		trans = btrfs_start_transaction(root, 1);
 		BUG_ON(IS_ERR(trans));
-		btrfs_corrupt_extent_tree(trans, root->fs_info->extent_root,
-					  root->fs_info->extent_root->node);
+		btrfs_corrupt_extent_tree(trans, extent_root,
+					  extent_root->node);
 		btrfs_commit_transaction(trans, root);
 		goto out_close;
 	}
diff --git a/btrfs-map-logical.c b/btrfs-map-logical.c
index 4ac644b4..b3a7526b 100644
--- a/btrfs-map-logical.c
+++ b/btrfs-map-logical.c
@@ -42,6 +42,7 @@ static FILE *info_file;
 static int map_one_extent(struct btrfs_fs_info *fs_info,
 			  u64 *logical_ret, u64 *len_ret, int search_forward)
 {
+	struct btrfs_root *extent_root;
 	struct btrfs_path *path;
 	struct btrfs_key key;
 	u64 logical;
@@ -59,8 +60,8 @@ static int map_one_extent(struct btrfs_fs_info *fs_info,
 	key.type = 0;
 	key.offset = 0;
 
-	ret = btrfs_search_slot(NULL, fs_info->extent_root, &key, path,
-				0, 0);
+	extent_root = btrfs_extent_root(fs_info, logical);
+	ret = btrfs_search_slot(NULL, extent_root, &key, path, 0, 0);
 	if (ret < 0)
 		goto out;
 	BUG_ON(ret == 0);
@@ -73,10 +74,10 @@ again:
 	    (key.type != BTRFS_EXTENT_ITEM_KEY &&
 	     key.type != BTRFS_METADATA_ITEM_KEY)) {
 		if (!search_forward)
-			ret = btrfs_previous_extent_item(fs_info->extent_root,
+			ret = btrfs_previous_extent_item(extent_root,
 							 path, 0);
 		else
-			ret = btrfs_next_extent_item(fs_info->extent_root,
+			ret = btrfs_next_extent_item(extent_root,
 						     path, 0);
 		if (ret)
 			goto out;
diff --git a/btrfstune.c b/btrfstune.c
index d34d89c1..4f77cfc0 100644
--- a/btrfstune.c
+++ b/btrfstune.c
@@ -233,7 +233,7 @@ static int change_buffer_header_uuid(struct extent_buffer *eb, uuid_t new_fsid)
 
 static int change_extents_uuid(struct btrfs_fs_info *fs_info, uuid_t new_fsid)
 {
-	struct btrfs_root *root = fs_info->extent_root;
+	struct btrfs_root *root = btrfs_extent_root(fs_info, 0);
 	struct btrfs_path path;
 	struct btrfs_key key = {0, 0, 0};
 	int ret = 0;
diff --git a/check/main.c b/check/main.c
index 632dfba0..e3e5a336 100644
--- a/check/main.c
+++ b/check/main.c
@@ -5619,7 +5619,7 @@ static int verify_space_cache(struct btrfs_root *root,
 	u64 last;
 	int ret = 0;
 
-	root = gfs_info->extent_root;
+	root = btrfs_extent_root(root->fs_info, cache->start);
 
 	last = max_t(u64, cache->start, BTRFS_SUPER_INFO_OFFSET);
 
@@ -5837,6 +5837,7 @@ out:
 static int check_extent_exists(struct btrfs_root *root, u64 bytenr,
 			       u64 num_bytes)
 {
+	struct btrfs_root *extent_root;
 	struct btrfs_path path;
 	struct extent_buffer *leaf;
 	struct btrfs_key key;
@@ -5848,7 +5849,8 @@ static int check_extent_exists(struct btrfs_root *root, u64 bytenr,
 	key.offset = (u64)-1;
 
 again:
-	ret = btrfs_search_slot(NULL, gfs_info->extent_root, &key, &path,
+	extent_root = btrfs_extent_root(gfs_info, key.objectid);
+	ret = btrfs_search_slot(NULL, extent_root, &key, &path,
 				0, 0);
 	if (ret < 0) {
 		fprintf(stderr, "Error looking up extent record %d\n", ret);
@@ -5858,7 +5860,7 @@ again:
 		if (path.slots[0] > 0) {
 			path.slots[0]--;
 		} else {
-			ret = btrfs_prev_leaf(root, &path);
+			ret = btrfs_prev_leaf(extent_root, &path);
 			if (ret < 0) {
 				goto out;
 			} else if (ret > 0) {
@@ -5882,7 +5884,7 @@ again:
 		if (path.slots[0] > 0) {
 			path.slots[0]--;
 		} else {
-			ret = btrfs_prev_leaf(root, &path);
+			ret = btrfs_prev_leaf(extent_root, &path);
 			if (ret < 0) {
 				goto out;
 			} else if (ret > 0) {
@@ -5895,7 +5897,7 @@ again:
 
 	while (num_bytes) {
 		if (path.slots[0] >= btrfs_header_nritems(path.nodes[0])) {
-			ret = btrfs_next_leaf(root, &path);
+			ret = btrfs_next_leaf(extent_root, &path);
 			if (ret < 0) {
 				fprintf(stderr, "Error going to next leaf "
 					"%d\n", ret);
@@ -5946,7 +5948,8 @@ again:
 				 * anyway just in case.
 				 */
 				btrfs_release_path(&path);
-				ret = check_extent_exists(root, new_start,
+				ret = check_extent_exists(extent_root,
+							  new_start,
 							  new_bytes);
 				if (ret) {
 					fprintf(stderr, "Right section didn't "
@@ -6720,6 +6723,7 @@ static int delete_extent_records(struct btrfs_trans_handle *trans,
 				 struct btrfs_path *path,
 				 u64 bytenr)
 {
+	struct btrfs_root *extent_root = btrfs_extent_root(gfs_info, bytenr);
 	struct btrfs_key key;
 	struct btrfs_key found_key;
 	struct extent_buffer *leaf;
@@ -6732,7 +6736,7 @@ static int delete_extent_records(struct btrfs_trans_handle *trans,
 	key.offset = (u64)-1;
 
 	while (1) {
-		ret = btrfs_search_slot(trans, gfs_info->extent_root, &key,
+		ret = btrfs_search_slot(trans, extent_root, &key,
 					path, 0, 1);
 		if (ret < 0)
 			break;
@@ -6775,7 +6779,7 @@ static int delete_extent_records(struct btrfs_trans_handle *trans,
 			"repair deleting extent record: key [%llu,%u,%llu]\n",
 			found_key.objectid, found_key.type, found_key.offset);
 
-		ret = btrfs_del_item(trans, gfs_info->extent_root, path);
+		ret = btrfs_del_item(trans, extent_root, path);
 		if (ret)
 			break;
 		btrfs_release_path(path);
@@ -6807,7 +6811,8 @@ static int record_extent(struct btrfs_trans_handle *trans,
 			 int allocated, u64 flags)
 {
 	int ret = 0;
-	struct btrfs_root *extent_root = gfs_info->extent_root;
+	struct btrfs_root *extent_root = btrfs_extent_root(gfs_info,
+							   rec->start);
 	struct extent_buffer *leaf;
 	struct btrfs_key ins_key;
 	struct btrfs_extent_item *ei;
@@ -6888,7 +6893,7 @@ static int record_extent(struct btrfs_trans_handle *trans,
 			 * just makes the backref allocator create a data
 			 * backref
 			 */
-			ret = btrfs_inc_extent_ref(trans, gfs_info->extent_root,
+			ret = btrfs_inc_extent_ref(trans, extent_root,
 						   rec->start, rec->max_size,
 						   parent,
 						   dback->root,
@@ -6917,7 +6922,7 @@ static int record_extent(struct btrfs_trans_handle *trans,
 		else
 			parent = 0;
 
-		ret = btrfs_inc_extent_ref(trans, gfs_info->extent_root,
+		ret = btrfs_inc_extent_ref(trans, extent_root,
 					   rec->start, rec->max_size,
 					   parent, tback->root, 0, 0);
 		fprintf(stderr,
@@ -7437,7 +7442,6 @@ static int delete_duplicate_records(struct btrfs_root *root,
 		list_move_tail(&tmp->list, &delete_list);
 	}
 
-	root = gfs_info->extent_root;
 	trans = btrfs_start_transaction(root, 1);
 	if (IS_ERR(trans)) {
 		ret = PTR_ERR(trans);
@@ -7459,6 +7463,7 @@ static int delete_duplicate_records(struct btrfs_root *root,
 			abort();
 		}
 
+		root = btrfs_extent_root(gfs_info, key.objectid);
 		ret = btrfs_search_slot(trans, root, &key, &path, -1, 1);
 		if (ret) {
 			if (ret > 0)
@@ -7697,7 +7702,7 @@ static int fixup_extent_refs(struct cache_tree *extent_cache,
 	if (ret < 0)
 		goto out;
 
-	trans = btrfs_start_transaction(gfs_info->extent_root, 1);
+	trans = btrfs_start_transaction(gfs_info->tree_root, 1);
 	if (IS_ERR(trans)) {
 		ret = PTR_ERR(trans);
 		goto out;
@@ -7736,7 +7741,7 @@ static int fixup_extent_refs(struct cache_tree *extent_cache,
 	}
 out:
 	if (trans) {
-		int err = btrfs_commit_transaction(trans, gfs_info->extent_root);
+		int err = btrfs_commit_transaction(trans, gfs_info->tree_root);
 
 		if (!ret)
 			ret = err;
@@ -7753,7 +7758,7 @@ out:
 static int fixup_extent_flags(struct extent_record *rec)
 {
 	struct btrfs_trans_handle *trans;
-	struct btrfs_root *root = gfs_info->extent_root;
+	struct btrfs_root *root = btrfs_extent_root(gfs_info, rec->start);
 	struct btrfs_path path;
 	struct btrfs_extent_item *ei;
 	struct btrfs_key key;
@@ -7822,6 +7827,7 @@ retry:
 static int prune_one_block(struct btrfs_trans_handle *trans,
 			   struct btrfs_corrupt_block *corrupt)
 {
+	struct btrfs_root *extent_root;
 	int ret;
 	struct btrfs_path path;
 	struct extent_buffer *eb;
@@ -7832,11 +7838,12 @@ static int prune_one_block(struct btrfs_trans_handle *trans,
 
 	btrfs_init_path(&path);
 again:
+	extent_root = btrfs_extent_root(gfs_info, corrupt->key.objectid);
 	/* we want to stop at the parent to our busted block */
 	path.lowest_level = level;
 
-	ret = btrfs_search_slot(trans, gfs_info->extent_root,
-				&corrupt->key, &path, -1, 1);
+	ret = btrfs_search_slot(trans, extent_root, &corrupt->key, &path,
+				-1, 1);
 
 	if (ret < 0)
 		goto out;
@@ -7868,7 +7875,7 @@ again:
 	 * We couldn't find the bad block.
 	 * TODO: search all the nodes for pointers to this block
 	 */
-	if (eb == gfs_info->extent_root->node) {
+	if (eb == extent_root->node) {
 		ret = -ENOENT;
 		goto out;
 	} else {
@@ -7879,7 +7886,7 @@ again:
 
 del_ptr:
 	printk("deleting pointer to block %llu\n", corrupt->cache.start);
-	ret = btrfs_del_ptr(gfs_info->extent_root, &path, level, slot);
+	ret = btrfs_del_ptr(extent_root, &path, level, slot);
 
 out:
 	btrfs_release_path(&path);
@@ -7897,7 +7904,7 @@ static int prune_corrupt_blocks(void)
 		if (!cache)
 			break;
 		if (!trans) {
-			trans = btrfs_start_transaction(gfs_info->extent_root, 1);
+			trans = btrfs_start_transaction(gfs_info->tree_root, 1);
 			if (IS_ERR(trans))
 				return PTR_ERR(trans);
 		}
@@ -7906,7 +7913,7 @@ static int prune_corrupt_blocks(void)
 		remove_cache_extent(gfs_info->corrupt_blocks, cache);
 	}
 	if (trans)
-		return btrfs_commit_transaction(trans, gfs_info->extent_root);
+		return btrfs_commit_transaction(trans, gfs_info->tree_root);
 	return 0;
 }
 
@@ -8011,7 +8018,8 @@ static int repair_extent_item_generation(struct extent_record *rec)
 	struct btrfs_path path;
 	struct btrfs_key key;
 	struct btrfs_extent_item *ei;
-	struct btrfs_root *extent_root = gfs_info->extent_root;
+	struct btrfs_root *extent_root = btrfs_extent_root(gfs_info,
+							   rec->start);
 	u64 new_gen = 0;;
 	int ret;
 
@@ -8258,7 +8266,6 @@ repair_abort:
 		} else if (!ret) {
 			struct btrfs_trans_handle *trans;
 
-			root = gfs_info->extent_root;
 			trans = btrfs_start_transaction(root, 1);
 			if (IS_ERR(trans)) {
 				ret = PTR_ERR(trans);
@@ -8714,7 +8721,7 @@ static int check_block_groups(struct block_group_tree *bg_cache)
 	if (!repair || !ret)
 		return ret;
 
-	trans = btrfs_start_transaction(gfs_info->extent_root, 1);
+	trans = btrfs_start_transaction(gfs_info->tree_root, 1);
 	if (IS_ERR(trans)) {
 		ret = PTR_ERR(trans);
 		fprintf(stderr, "Failed to start a transaction\n");
@@ -8722,7 +8729,7 @@ static int check_block_groups(struct block_group_tree *bg_cache)
 	}
 
 	ret = btrfs_fix_block_accounting(trans);
-	btrfs_commit_transaction(trans, gfs_info->extent_root);
+	btrfs_commit_transaction(trans, gfs_info->tree_root);
 	return ret ? ret : -EAGAIN;
 }
 
@@ -9368,7 +9375,7 @@ again:
 	}
 
 	/* Ok we can allocate now, reinit the extent root */
-	ret = btrfs_fsck_reinit_root(trans, gfs_info->extent_root);
+	ret = btrfs_fsck_reinit_root(trans, btrfs_extent_root(gfs_info, 0));
 	if (ret) {
 		fprintf(stderr, "extent root initialization failed\n");
 		/*
@@ -9387,6 +9394,7 @@ again:
 	while (1) {
 		struct btrfs_block_group_item bgi;
 		struct btrfs_block_group *cache;
+		struct btrfs_root *extent_root = btrfs_extent_root(gfs_info, 0);
 		struct btrfs_key key;
 
 		cache = btrfs_lookup_first_block_group(gfs_info, start);
@@ -9400,8 +9408,8 @@ again:
 		key.objectid = cache->start;
 		key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
 		key.offset = cache->length;
-		ret = btrfs_insert_item(trans, gfs_info->extent_root, &key,
-					&bgi, sizeof(bgi));
+		ret = btrfs_insert_item(trans, extent_root, &key, &bgi,
+					sizeof(bgi));
 		if (ret) {
 			fprintf(stderr, "Error adding block group\n");
 			return ret;
@@ -9618,7 +9626,7 @@ out:
 
 static int fill_csum_tree_from_extent(struct btrfs_trans_handle *trans)
 {
-	struct btrfs_root *extent_root = gfs_info->extent_root;
+	struct btrfs_root *extent_root = btrfs_extent_root(gfs_info, 0);
 	struct btrfs_root *csum_root;
 	struct btrfs_path path;
 	struct btrfs_extent_item *ei;
@@ -9721,6 +9729,7 @@ static void free_roots_info_cache(void)
 
 static int build_roots_info_cache(void)
 {
+	struct btrfs_root *extent_root = btrfs_extent_root(gfs_info, 0);
 	int ret = 0;
 	struct btrfs_key key;
 	struct extent_buffer *leaf;
@@ -9737,7 +9746,7 @@ static int build_roots_info_cache(void)
 	key.objectid = 0;
 	key.type = BTRFS_EXTENT_ITEM_KEY;
 	key.offset = 0;
-	ret = btrfs_search_slot(NULL, gfs_info->extent_root, &key, &path, 0, 0);
+	ret = btrfs_search_slot(NULL, extent_root, &key, &path, 0, 0);
 	if (ret < 0)
 		goto out;
 	leaf = path.nodes[0];
@@ -9757,7 +9766,7 @@ static int build_roots_info_cache(void)
 
 		ctx.item_count++;
 		if (slot >= btrfs_header_nritems(leaf)) {
-			ret = btrfs_next_leaf(gfs_info->extent_root, &path);
+			ret = btrfs_next_leaf(extent_root, &path);
 			if (ret < 0) {
 				break;
 			} else if (ret) {
@@ -10670,7 +10679,7 @@ static int cmd_check(const struct cmd_struct *cmd, int argc, char **argv)
 	if (init_extent_tree || init_csum_tree) {
 		struct btrfs_trans_handle *trans;
 
-		trans = btrfs_start_transaction(gfs_info->extent_root, 0);
+		trans = btrfs_start_transaction(gfs_info->tree_root, 0);
 		if (IS_ERR(trans)) {
 			error("error starting transaction");
 			ret = PTR_ERR(trans);
@@ -10711,12 +10720,13 @@ static int cmd_check(const struct cmd_struct *cmd, int argc, char **argv)
 		 * Ok now we commit and run the normal fsck, which will add
 		 * extent entries for all of the items it finds.
 		 */
-		ret = btrfs_commit_transaction(trans, gfs_info->extent_root);
+		ret = btrfs_commit_transaction(trans, gfs_info->tree_root);
 		err |= !!ret;
 		if (ret)
 			goto close_out;
 	}
-	if (!extent_buffer_uptodate(gfs_info->extent_root->node)) {
+	root = btrfs_extent_root(gfs_info, 0);
+	if (!extent_buffer_uptodate(root->node)) {
 		error("critical: extent_root, unable to check the filesystem");
 		ret = -EIO;
 		err |= !!ret;
diff --git a/check/mode-common.c b/check/mode-common.c
index 56377840..72fec47c 100644
--- a/check/mode-common.c
+++ b/check/mode-common.c
@@ -176,6 +176,8 @@ static int check_prealloc_shared_data_ref(u64 parent, u64 disk_bytenr)
  */
 int check_prealloc_extent_written(u64 disk_bytenr, u64 num_bytes)
 {
+	struct btrfs_root *extent_root = btrfs_extent_root(gfs_info,
+							   disk_bytenr);
 	struct btrfs_path path;
 	struct btrfs_key key;
 	int ret;
@@ -189,7 +191,7 @@ int check_prealloc_extent_written(u64 disk_bytenr, u64 num_bytes)
 	key.offset = num_bytes;
 
 	btrfs_init_path(&path);
-	ret = btrfs_search_slot(NULL, gfs_info->extent_root, &key, &path, 0, 0);
+	ret = btrfs_search_slot(NULL, extent_root, &key, &path, 0, 0);
 	if (ret > 0) {
 		fprintf(stderr,
 	"Missing extent item in extent tree for disk_bytenr %llu, num_bytes %llu\n",
@@ -240,7 +242,7 @@ int check_prealloc_extent_written(u64 disk_bytenr, u64 num_bytes)
 	path.slots[0]++;
 	while (true) {
 		if (path.slots[0] >= btrfs_header_nritems(path.nodes[0])) {
-			ret = btrfs_next_leaf(gfs_info->extent_root, &path);
+			ret = btrfs_next_leaf(extent_root, &path);
 			if (ret < 0)
 				goto out;
 			if (ret > 0) {
@@ -1083,7 +1085,7 @@ int recow_extent_buffer(struct btrfs_root *root, struct extent_buffer *eb)
  */
 int get_extent_item_generation(u64 bytenr, u64 *gen_ret)
 {
-	struct btrfs_root *root = gfs_info->extent_root;
+	struct btrfs_root *root = btrfs_extent_root(gfs_info, bytenr);
 	struct btrfs_extent_item *ei;
 	struct btrfs_path path;
 	struct btrfs_key key;
diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c
index 696ad215..cc6773cd 100644
--- a/check/mode-lowmem.c
+++ b/check/mode-lowmem.c
@@ -33,7 +33,7 @@ static u64 total_used = 0;
 static int calc_extent_flag(struct btrfs_root *root, struct extent_buffer *eb,
 			    u64 *flags_ret)
 {
-	struct btrfs_root *extent_root = gfs_info->extent_root;
+	struct btrfs_root *extent_root;
 	struct btrfs_root_item *ri = &root->root_item;
 	struct btrfs_extent_inline_ref *iref;
 	struct btrfs_extent_item *ei;
@@ -73,6 +73,7 @@ static int calc_extent_flag(struct btrfs_root *root, struct extent_buffer *eb,
 	key.type = (u8)-1;
 	key.offset = (u64)-1;
 
+	extent_root = btrfs_extent_root(gfs_info, key.objectid);
 	ret = btrfs_search_slot(NULL, extent_root, &key, path, 0, 0);
 	if (ret <= 0) {
 		ret = -EIO;
@@ -265,7 +266,7 @@ static int modify_block_group_cache(struct btrfs_block_group *block_group, int c
  */
 static int modify_block_groups_cache(u64 flags, int cache)
 {
-	struct btrfs_root *root = gfs_info->extent_root;
+	struct btrfs_root *root = btrfs_extent_root(gfs_info, 0);
 	struct btrfs_key key;
 	struct btrfs_path path;
 	struct btrfs_block_group *bg_cache;
@@ -330,7 +331,7 @@ static int clear_block_groups_full(u64 flags)
 static int create_chunk_and_block_group(u64 flags, u64 *start, u64 *nbytes)
 {
 	struct btrfs_trans_handle *trans;
-	struct btrfs_root *root = gfs_info->extent_root;
+	struct btrfs_root *root = btrfs_extent_root(gfs_info, 0);
 	int ret;
 
 	if ((flags & BTRFS_BLOCK_GROUP_TYPE_MASK) == 0)
@@ -418,7 +419,7 @@ static int is_chunk_almost_full(u64 start)
 {
 	struct btrfs_path path;
 	struct btrfs_key key;
-	struct btrfs_root *root = gfs_info->extent_root;
+	struct btrfs_root *root = btrfs_extent_root(gfs_info, 0);
 	struct btrfs_block_group_item *bi;
 	struct btrfs_block_group_item bg_item;
 	struct extent_buffer *eb;
@@ -594,10 +595,9 @@ out:
 static int repair_block_accounting(void)
 {
 	struct btrfs_trans_handle *trans = NULL;
-	struct btrfs_root *root = gfs_info->extent_root;
 	int ret;
 
-	trans = btrfs_start_transaction(root, 1);
+	trans = btrfs_start_transaction(gfs_info->tree_root, 1);
 	if (IS_ERR(trans)) {
 		ret = PTR_ERR(trans);
 		errno = -ret;
@@ -606,7 +606,7 @@ static int repair_block_accounting(void)
 	}
 
 	ret = btrfs_fix_block_accounting(trans);
-	btrfs_commit_transaction(trans, root);
+	btrfs_commit_transaction(trans, gfs_info->tree_root);
 	return ret;
 }
 
@@ -622,7 +622,7 @@ static int repair_tree_block_ref(struct btrfs_root *root,
 				 struct node_refs *nrefs, int level, int err)
 {
 	struct btrfs_trans_handle *trans = NULL;
-	struct btrfs_root *extent_root = gfs_info->extent_root;
+	struct btrfs_root *extent_root;
 	struct btrfs_path path;
 	struct btrfs_extent_item *ei;
 	struct btrfs_tree_block_info *bi;
@@ -656,6 +656,7 @@ static int repair_tree_block_ref(struct btrfs_root *root,
 	key.offset = (u64)-1;
 
 	/* Search for the extent item */
+	extent_root = btrfs_extent_root(gfs_info, bytenr);
 	ret = btrfs_search_slot(NULL, extent_root, &key, &path, 0, 0);
 	if (ret <= 0) {
 		ret = -EIO;
@@ -3001,7 +3002,7 @@ static int check_tree_block_ref(struct btrfs_root *root,
 				int level, u64 owner, struct node_refs *nrefs)
 {
 	struct btrfs_key key;
-	struct btrfs_root *extent_root = gfs_info->extent_root;
+	struct btrfs_root *extent_root;
 	struct btrfs_path path;
 	struct btrfs_extent_item *ei;
 	struct btrfs_extent_inline_ref *iref;
@@ -3030,6 +3031,7 @@ static int check_tree_block_ref(struct btrfs_root *root,
 	key.offset = (u64)-1;
 
 	/* Search for the backref in extent tree */
+	extent_root = btrfs_extent_root(gfs_info, bytenr);
 	ret = btrfs_search_slot(NULL, extent_root, &key, &path, 0, 0);
 	if (ret < 0) {
 		err |= BACKREF_MISSING;
@@ -3222,7 +3224,7 @@ static int repair_extent_data_item(struct btrfs_root *root,
 	struct btrfs_key key;
 	struct btrfs_extent_item *ei;
 	struct btrfs_path path;
-	struct btrfs_root *extent_root = gfs_info->extent_root;
+	struct btrfs_root *extent_root;
 	struct extent_buffer *eb;
 	u64 size;
 	u64 disk_bytenr;
@@ -3274,6 +3276,7 @@ static int repair_extent_data_item(struct btrfs_root *root,
 	key.offset = num_bytes;
 
 	btrfs_init_path(&path);
+	extent_root = btrfs_extent_root(gfs_info, key.objectid);
 	ret = btrfs_search_slot(NULL, extent_root, &key, &path, 0, 0);
 	if (ret < 0) {
 		ret = -EIO;
@@ -3356,7 +3359,7 @@ static int check_extent_data_item(struct btrfs_root *root,
 	struct btrfs_file_extent_item *fi;
 	struct extent_buffer *eb = pathp->nodes[0];
 	struct btrfs_path path;
-	struct btrfs_root *extent_root = gfs_info->extent_root;
+	struct btrfs_root *extent_root;
 	struct btrfs_key fi_key;
 	struct btrfs_key dbref_key;
 	struct extent_buffer *leaf;
@@ -3426,6 +3429,7 @@ static int check_extent_data_item(struct btrfs_root *root,
 	dbref_key.type = BTRFS_EXTENT_ITEM_KEY;
 	dbref_key.offset = btrfs_file_extent_disk_num_bytes(eb, fi);
 
+	extent_root = btrfs_extent_root(gfs_info, dbref_key.objectid);
 	ret = btrfs_search_slot(NULL, extent_root, &dbref_key, &path, 0, 0);
 	if (ret)
 		goto out;
@@ -3499,8 +3503,9 @@ static int check_extent_data_item(struct btrfs_root *root,
 		dbref_key.offset = hash_extent_data_ref(owner, fi_key.objectid,
 							fi_key.offset - offset);
 
-		ret = btrfs_search_slot(NULL, gfs_info->extent_root,
-					&dbref_key, &path, 0, 0);
+		extent_root = btrfs_extent_root(gfs_info, dbref_key.objectid);
+		ret = btrfs_search_slot(NULL, extent_root, &dbref_key, &path, 0,
+					0);
 		if (!ret) {
 			found_dbackref = 1;
 			goto out;
@@ -3516,8 +3521,8 @@ static int check_extent_data_item(struct btrfs_root *root,
 		dbref_key.type = BTRFS_SHARED_DATA_REF_KEY;
 		dbref_key.offset = eb->start;
 
-		ret = btrfs_search_slot(NULL, gfs_info->extent_root,
-					&dbref_key, &path, 0, 0);
+		ret = btrfs_search_slot(NULL, extent_root, &dbref_key, &path, 0,
+					0);
 		if (!ret) {
 			found_dbackref = 1;
 			goto out;
@@ -3542,7 +3547,7 @@ out:
  */
 static int check_block_group_item(struct extent_buffer *eb, int slot)
 {
-	struct btrfs_root *extent_root = gfs_info->extent_root;
+	struct btrfs_root *extent_root;
 	struct btrfs_root *chunk_root = gfs_info->chunk_root;
 	struct btrfs_block_group_item *bi;
 	struct btrfs_block_group_item bg_item;
@@ -3598,6 +3603,7 @@ static int check_block_group_item(struct extent_buffer *eb, int slot)
 	extent_key.offset = 0;
 
 	btrfs_init_path(&path);
+	extent_root = btrfs_extent_root(gfs_info, extent_key.objectid);
 	ret = btrfs_search_slot(NULL, extent_root, &extent_key, &path, 0, 0);
 	if (ret < 0)
 		goto out;
@@ -3673,6 +3679,7 @@ out:
  */
 static int query_tree_block_level(u64 bytenr)
 {
+	struct btrfs_root *extent_root;
 	struct extent_buffer *eb;
 	struct btrfs_path path;
 	struct btrfs_key key;
@@ -3689,10 +3696,12 @@ static int query_tree_block_level(u64 bytenr)
 	key.offset = (u64)-1;
 
 	btrfs_init_path(&path);
-	ret = btrfs_search_slot(NULL, gfs_info->extent_root, &key, &path, 0, 0);
+
+	extent_root = btrfs_extent_root(gfs_info, bytenr);
+	ret = btrfs_search_slot(NULL, extent_root, &key, &path, 0, 0);
 	if (ret < 0)
 		goto release_out;
-	ret = btrfs_previous_extent_item(gfs_info->extent_root, &path, bytenr);
+	ret = btrfs_previous_extent_item(extent_root, &path, bytenr);
 	if (ret < 0)
 		goto release_out;
 	if (ret > 0) {
@@ -3920,7 +3929,7 @@ static int check_extent_data_backref(u64 root_id, u64 objectid, u64 offset,
 				     u64 bytenr, u64 len, u32 count)
 {
 	struct btrfs_root *root;
-	struct btrfs_root *extent_root = gfs_info->extent_root;
+	struct btrfs_root *extent_root;
 	struct btrfs_key key;
 	struct btrfs_path path;
 	struct extent_buffer *leaf;
@@ -3935,6 +3944,7 @@ static int check_extent_data_backref(u64 root_id, u64 objectid, u64 offset,
 		key.offset = (u64)-1;
 
 		btrfs_init_path(&path);
+		extent_root = btrfs_extent_root(gfs_info, bytenr);
 		ret = btrfs_search_slot(NULL, extent_root, &key, &path, 0, 0);
 		if (ret < 0)
 			goto out;
@@ -4084,13 +4094,13 @@ out:
  * Returns >0   the backref was deleted but extent still exists
  * Returns =0   the whole extent item was deleted
  */
-static int repair_extent_item(struct btrfs_root *root, struct btrfs_path *path,
-		      u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid,
-		      u64 owner, u64 offset)
+static int repair_extent_item(struct btrfs_path *path, u64 bytenr, u64
+			      num_bytes, u64 parent, u64 root_objectid, u64
+			      owner, u64 offset)
 {
 	struct btrfs_trans_handle *trans;
-	struct btrfs_root *extent_root = gfs_info->extent_root;
 	struct btrfs_key old_key;
+	struct btrfs_root *extent_root = btrfs_extent_root(gfs_info, bytenr);
 	int ret;
 
 	btrfs_item_key_to_cpu(path->nodes[0], &old_key, path->slots[0]);
@@ -4121,7 +4131,7 @@ static int repair_extent_item(struct btrfs_root *root, struct btrfs_path *path,
 	btrfs_commit_transaction(trans, extent_root);
 
 	btrfs_release_path(path);
-	ret = btrfs_search_slot(NULL, root, &old_key, path, 0, 0);
+	ret = btrfs_search_slot(NULL, extent_root, &old_key, path, 0, 0);
 	if (ret > 0) {
 		/* odd, there must be one block group before at least */
 		if (path->slots[0] == 0) {
@@ -4159,7 +4169,7 @@ static int repair_extent_item_generation(struct btrfs_path *path)
 	struct btrfs_trans_handle *trans;
 	struct btrfs_key key;
 	struct btrfs_extent_item *ei;
-	struct btrfs_root *extent_root = gfs_info->extent_root;
+	struct btrfs_root *extent_root;
 	u64 new_gen = 0;;
 	int ret;
 
@@ -4172,6 +4182,7 @@ static int repair_extent_item_generation(struct btrfs_path *path)
 	if (ret)
 		return ret;
 	btrfs_release_path(path);
+	extent_root = btrfs_extent_root(gfs_info, key.objectid);
 	trans = btrfs_start_transaction(extent_root, 1);
 	if (IS_ERR(trans)) {
 		ret = PTR_ERR(trans);
@@ -4349,9 +4360,8 @@ next:
 
 	if ((tmp_err & (REFERENCER_MISSING | REFERENCER_MISMATCH))
 	    && repair) {
-		ret = repair_extent_item(gfs_info->extent_root, path,
-			 key.objectid, num_bytes, parent, root_objectid,
-			 owner, owner_offset);
+		ret = repair_extent_item(path, key.objectid, num_bytes, parent,
+					 root_objectid, owner, owner_offset);
 		if (ret < 0) {
 			err |= tmp_err;
 			err |= FATAL_ERROR;
@@ -4581,6 +4591,7 @@ next:
 static int find_block_group_item(struct btrfs_path *path, u64 bytenr, u64 len,
 				 u64 type)
 {
+	struct btrfs_root *root = btrfs_extent_root(gfs_info, 0);
 	struct btrfs_block_group_item bgi;
 	struct btrfs_key key;
 	int ret;
@@ -4589,7 +4600,7 @@ static int find_block_group_item(struct btrfs_path *path, u64 bytenr, u64 len,
 	key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
 	key.offset = len;
 
-	ret = btrfs_search_slot(NULL, gfs_info->extent_root, &key, path, 0, 0);
+	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
 	if (ret < 0)
 		return ret;
 	if (ret > 0) {
@@ -4705,7 +4716,7 @@ static int repair_chunk_item(struct btrfs_root *chunk_root,
 	struct btrfs_chunk *chunk;
 	struct btrfs_key chunk_key;
 	struct extent_buffer *eb = path->nodes[0];
-	struct btrfs_root *extent_root = gfs_info->extent_root;
+	struct btrfs_root *extent_root;
 	struct btrfs_trans_handle *trans;
 	u64 length;
 	int slot = path->slots[0];
@@ -4715,6 +4726,7 @@ static int repair_chunk_item(struct btrfs_root *chunk_root,
 	btrfs_item_key_to_cpu(eb, &chunk_key, slot);
 	if (chunk_key.type != BTRFS_CHUNK_ITEM_KEY)
 		return err;
+	extent_root = btrfs_extent_root(gfs_info, chunk_key.offset);
 	chunk = btrfs_item_ptr(eb, slot, struct btrfs_chunk);
 	type = btrfs_chunk_type(path->nodes[0], chunk);
 	length = btrfs_chunk_length(eb, chunk);
diff --git a/check/qgroup-verify.c b/check/qgroup-verify.c
index a514fee1..0813b841 100644
--- a/check/qgroup-verify.c
+++ b/check/qgroup-verify.c
@@ -1157,7 +1157,7 @@ static int scan_extents(struct btrfs_fs_info *info,
 			u64 start, u64 end)
 {
 	int ret, i, nr, level;
-	struct btrfs_root *root = info->extent_root;
+	struct btrfs_root *root = btrfs_extent_root(info, start);
 	struct btrfs_key key;
 	struct btrfs_path path;
 	struct btrfs_disk_key disk_key;
diff --git a/cmds/rescue-chunk-recover.c b/cmds/rescue-chunk-recover.c
index 115d91d7..3bf9c36c 100644
--- a/cmds/rescue-chunk-recover.c
+++ b/cmds/rescue-chunk-recover.c
@@ -555,6 +555,7 @@ static int check_chunk_by_metadata(struct recover_control *rc,
 				   struct btrfs_root *root,
 				   struct chunk_record *chunk, int bg_only)
 {
+	struct btrfs_fs_info *fs_info = root->fs_info;
 	int ret;
 	int i;
 	int slot;
@@ -616,7 +617,8 @@ bg_check:
 	key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
 	key.offset = chunk->length;
 
-	ret = btrfs_search_slot(NULL, root->fs_info->extent_root, &key, &path,
+	root = btrfs_extent_root(fs_info, key.objectid);
+	ret = btrfs_search_slot(NULL, root, &key, &path,
 				0, 0);
 	if (ret < 0) {
 		fprintf(stderr, "Search block group failed(%d)\n", ret);
@@ -997,7 +999,7 @@ static int block_group_remove_all_extent_items(struct btrfs_trans_handle *trans,
 	int del_s, del_nr;
 
 	btrfs_init_path(&path);
-	root = root->fs_info->extent_root;
+	root = btrfs_extent_root(fs_info, start);
 
 	key.objectid = start;
 	key.offset = 0;
@@ -1382,6 +1384,7 @@ static int rebuild_block_group(struct btrfs_trans_handle *trans,
 			       struct recover_control *rc,
 			       struct btrfs_root *root)
 {
+	struct btrfs_fs_info *fs_info = root->fs_info;
 	struct chunk_record *chunk_rec;
 	struct btrfs_key search_key;
 	struct btrfs_path path;
@@ -1396,12 +1399,11 @@ static int rebuild_block_group(struct btrfs_trans_handle *trans,
 		search_key.objectid = chunk_rec->offset;
 		search_key.type = BTRFS_EXTENT_ITEM_KEY;
 		search_key.offset = 0;
-		ret = btrfs_search_slot(NULL, root->fs_info->extent_root,
-					&search_key, &path, 0, 0);
+		root = btrfs_extent_root(fs_info, chunk_rec->offset);
+		ret = btrfs_search_slot(NULL, root, &search_key, &path, 0, 0);
 		if (ret < 0)
 			goto out;
-		ret = calculate_bg_used(root->fs_info->extent_root,
-					chunk_rec, &path, &used);
+		ret = calculate_bg_used(root, chunk_rec, &path, &used);
 		/*
 		 * Extent tree is damaged, better to rebuild the whole extent
 		 * tree. Currently, change the used to chunk's len to prevent
@@ -1417,9 +1419,7 @@ static int rebuild_block_group(struct btrfs_trans_handle *trans,
 			used = chunk_rec->length;
 		}
 		btrfs_release_path(&path);
-		ret = __insert_block_group(trans, chunk_rec,
-					   root->fs_info->extent_root,
-					   used);
+		ret = __insert_block_group(trans, chunk_rec, root, used);
 		if (ret < 0)
 			goto out;
 	}
diff --git a/common/repair.c b/common/repair.c
index 413c3e86..c8624eaa 100644
--- a/common/repair.c
+++ b/common/repair.c
@@ -168,7 +168,7 @@ int btrfs_fix_block_accounting(struct btrfs_trans_handle *trans)
 	struct extent_buffer *leaf;
 	struct btrfs_block_group *cache;
 	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, 0);
 
 	ret = btrfs_run_delayed_refs(trans, -1);
 	if (ret)
@@ -190,8 +190,7 @@ int btrfs_fix_block_accounting(struct btrfs_trans_handle *trans)
 	key.offset = 0;
 	key.objectid = 0;
 	key.type = BTRFS_EXTENT_ITEM_KEY;
-	ret = btrfs_search_slot(trans, root->fs_info->extent_root,
-				&key, &path, 0, 0);
+	ret = btrfs_search_slot(trans, root, &key, &path, 0, 0);
 	if (ret < 0)
 		return ret;
 	while(1) {
diff --git a/convert/main.c b/convert/main.c
index 7f33d4e1..0fae4e98 100644
--- a/convert/main.c
+++ b/convert/main.c
@@ -944,7 +944,6 @@ static int make_convert_data_block_groups(struct btrfs_trans_handle *trans,
 					  struct btrfs_mkfs_config *cfg,
 					  struct btrfs_convert_context *cctx)
 {
-	struct btrfs_root *extent_root = fs_info->extent_root;
 	struct cache_tree *data_chunks = &cctx->data_chunks;
 	struct cache_extent *cache;
 	u64 max_chunk_size;
@@ -956,8 +955,7 @@ static int make_convert_data_block_groups(struct btrfs_trans_handle *trans,
 	 */
 	max_chunk_size = cfg->num_bytes / 10;
 	max_chunk_size = min((u64)(SZ_1G), max_chunk_size);
-	max_chunk_size = round_down(max_chunk_size,
-				    extent_root->fs_info->sectorsize);
+	max_chunk_size = round_down(max_chunk_size, fs_info->sectorsize);
 
 	for (cache = first_cache_extent(data_chunks); cache;
 	     cache = next_cache_extent(cache)) {
diff --git a/image/main.c b/image/main.c
index 57e0cb6c..ab57ce4e 100644
--- a/image/main.c
+++ b/image/main.c
@@ -922,7 +922,7 @@ static int copy_from_extent_tree(struct metadump_struct *metadump,
 	u64 num_bytes;
 	int ret;
 
-	extent_root = metadump->root->fs_info->extent_root;
+	extent_root = btrfs_extent_root(metadump->root->fs_info, 0);
 	bytenr = BTRFS_SUPER_INFO_OFFSET + BTRFS_SUPER_INFO_SIZE;
 	key.objectid = bytenr;
 	key.type = BTRFS_EXTENT_ITEM_KEY;
diff --git a/kernel-shared/backref.c b/kernel-shared/backref.c
index c04d505e..42832c48 100644
--- a/kernel-shared/backref.c
+++ b/kernel-shared/backref.c
@@ -645,7 +645,7 @@ static int __add_keyed_refs(struct btrfs_fs_info *fs_info,
 			    struct btrfs_path *path, u64 bytenr,
 			    int info_level)
 {
-	struct btrfs_root *extent_root = fs_info->extent_root;
+	struct btrfs_root *extent_root = btrfs_extent_root(fs_info, bytenr);
 	int ret;
 	int slot;
 	struct extent_buffer *leaf;
@@ -734,6 +734,7 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
 			     u64 time_seq, struct ulist *refs,
 			     struct ulist *roots, const u64 *extent_item_pos)
 {
+	struct btrfs_root *extent_root = btrfs_extent_root(fs_info, bytenr);
 	struct btrfs_key key;
 	struct btrfs_path *path;
 	int info_level = 0;
@@ -756,7 +757,7 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
 	if (!path)
 		return -ENOMEM;
 
-	ret = btrfs_search_slot(trans, fs_info->extent_root, &key, path, 0, 0);
+	ret = btrfs_search_slot(trans, extent_root, &key, path, 0, 0);
 	if (ret < 0)
 		goto out;
 	BUG_ON(ret == 0);
@@ -1136,6 +1137,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;
@@ -1151,11 +1153,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;
diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h
index d2d1a006..23750156 100644
--- a/kernel-shared/ctree.h
+++ b/kernel-shared/ctree.h
@@ -1157,7 +1157,7 @@ struct btrfs_fs_info {
 	u8 chunk_tree_uuid[BTRFS_UUID_SIZE];
 	u8 *new_chunk_tree_uuid;
 	struct btrfs_root *fs_root;
-	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/kernel-shared/disk-io.c b/kernel-shared/disk-io.c
index c1d55692..b4c45719 100644
--- a/kernel-shared/disk-io.c
+++ b/kernel-shared/disk-io.c
@@ -750,6 +750,12 @@ struct btrfs_root *btrfs_csum_root(struct btrfs_fs_info *fs_info,
 	return fs_info->_csum_root;
 }
 
+struct btrfs_root *btrfs_extent_root(struct btrfs_fs_info *fs_info,
+				     u64 bytenr)
+{
+	return fs_info->_extent_root;
+}
+
 struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
 				      struct btrfs_key *location)
 {
@@ -761,7 +767,7 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
 	if (location->objectid == BTRFS_ROOT_TREE_OBJECTID)
 		return fs_info->tree_root;
 	if (location->objectid == BTRFS_EXTENT_TREE_OBJECTID)
-		return fs_info->extent_root;
+		return fs_info->_extent_root;
 	if (location->objectid == BTRFS_CHUNK_TREE_OBJECTID)
 		return fs_info->chunk_root;
 	if (location->objectid == BTRFS_DEV_TREE_OBJECTID)
@@ -800,7 +806,7 @@ void btrfs_free_fs_info(struct btrfs_fs_info *fs_info)
 		free(fs_info->quota_root);
 
 	free(fs_info->tree_root);
-	free(fs_info->extent_root);
+	free(fs_info->_extent_root);
 	free(fs_info->chunk_root);
 	free(fs_info->dev_root);
 	free(fs_info->_csum_root);
@@ -820,7 +826,7 @@ struct btrfs_fs_info *btrfs_new_fs_info(int writable, u64 sb_bytenr)
 		return NULL;
 
 	fs_info->tree_root = calloc(1, sizeof(struct btrfs_root));
-	fs_info->extent_root = calloc(1, sizeof(struct btrfs_root));
+	fs_info->_extent_root = calloc(1, sizeof(struct btrfs_root));
 	fs_info->chunk_root = calloc(1, sizeof(struct btrfs_root));
 	fs_info->dev_root = calloc(1, sizeof(struct btrfs_root));
 	fs_info->_csum_root = calloc(1, sizeof(struct btrfs_root));
@@ -829,7 +835,7 @@ struct btrfs_fs_info *btrfs_new_fs_info(int writable, u64 sb_bytenr)
 	fs_info->uuid_root = calloc(1, sizeof(struct btrfs_root));
 	fs_info->super_copy = calloc(1, BTRFS_SUPER_INFO_SIZE);
 
-	if (!fs_info->tree_root || !fs_info->extent_root ||
+	if (!fs_info->tree_root || !fs_info->_extent_root ||
 	    !fs_info->chunk_root || !fs_info->dev_root ||
 	    !fs_info->_csum_root || !fs_info->quota_root ||
 	    !fs_info->free_space_root || !fs_info->uuid_root ||
@@ -985,11 +991,11 @@ int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info, u64 root_tree_bytenr,
 		return -EIO;
 	}
 
-	ret = setup_root_or_create_block(fs_info, flags, fs_info->extent_root,
+	ret = setup_root_or_create_block(fs_info, flags, fs_info->_extent_root,
 					 BTRFS_EXTENT_TREE_OBJECTID, "extent");
 	if (ret)
 		return ret;
-	fs_info->extent_root->track_dirty = 1;
+	fs_info->_extent_root->track_dirty = 1;
 
 	ret = find_and_setup_root(root, fs_info, BTRFS_DEV_TREE_OBJECTID,
 				  fs_info->dev_root);
@@ -1047,7 +1053,7 @@ int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info, u64 root_tree_bytenr,
 
 	fs_info->generation = generation;
 	fs_info->last_trans_committed = generation;
-	if (extent_buffer_uptodate(fs_info->extent_root->node) &&
+	if (extent_buffer_uptodate(fs_info->_extent_root->node) &&
 	    !(flags & OPEN_CTREE_NO_BLOCK_GROUPS)) {
 		ret = btrfs_read_block_groups(fs_info);
 		/*
@@ -1082,8 +1088,8 @@ void btrfs_release_all_roots(struct btrfs_fs_info *fs_info)
 		free_extent_buffer(fs_info->_csum_root->node);
 	if (fs_info->dev_root)
 		free_extent_buffer(fs_info->dev_root->node);
-	if (fs_info->extent_root)
-		free_extent_buffer(fs_info->extent_root->node);
+	if (fs_info->_extent_root)
+		free_extent_buffer(fs_info->_extent_root->node);
 	if (fs_info->tree_root)
 		free_extent_buffer(fs_info->tree_root->node);
 	if (fs_info->log_root_tree)
@@ -1836,11 +1842,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, info->_extent_root->node->start);
 	btrfs_set_backup_extent_root_gen(root_backup,
-			       btrfs_header_generation(info->extent_root->node));
+			       btrfs_header_generation(info->_extent_root->node));
 	btrfs_set_backup_extent_root_level(root_backup,
-			       btrfs_header_level(info->extent_root->node));
+			       btrfs_header_level(info->_extent_root->node));
 	/*
 	 * we might commit during log recovery, which happens before we set
 	 * the fs_root.  Make sure it is valid before we fill it in.
diff --git a/kernel-shared/disk-io.h b/kernel-shared/disk-io.h
index 38abbca5..dc71cc2b 100644
--- a/kernel-shared/disk-io.h
+++ b/kernel-shared/disk-io.h
@@ -218,4 +218,5 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans,
 				     struct btrfs_fs_info *fs_info,
 				     u64 objectid);
 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_inf, u64 bytenr);
 #endif
diff --git a/kernel-shared/extent-tree.c b/kernel-shared/extent-tree.c
index 402904d1..3713452b 100644
--- a/kernel-shared/extent-tree.c
+++ b/kernel-shared/extent-tree.c
@@ -96,7 +96,7 @@ static int cache_block_group(struct btrfs_root *root,
 	if (!block_group)
 		return 0;
 
-	root = root->fs_info->extent_root;
+	root = btrfs_extent_root(root->fs_info, 0);
 	free_space_cache = &root->fs_info->free_space_cache;
 
 	if (block_group->cached)
@@ -1243,6 +1243,8 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
 			 u64 bytenr, u64 num_bytes, u64 parent,
 			 u64 root_objectid, u64 owner, u64 offset)
 {
+	struct btrfs_root *extent_root = btrfs_extent_root(root->fs_info,
+							   bytenr);
 	struct btrfs_path *path;
 	struct extent_buffer *leaf;
 	struct btrfs_extent_item *item;
@@ -1254,9 +1256,9 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
 	if (!path)
 		return -ENOMEM;
 
-	ret = insert_inline_extent_backref(trans, root->fs_info->extent_root,
-					   path, bytenr, num_bytes, parent,
-					   root_objectid, owner, offset, 1);
+	ret = insert_inline_extent_backref(trans, extent_root, path, bytenr,
+					   num_bytes, parent, root_objectid,
+					   owner, offset, 1);
 	if (ret == 0)
 		goto out;
 
@@ -1274,9 +1276,8 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
 	btrfs_release_path(path);
 
 	/* now insert the actual backref */
-	ret = insert_extent_backref(trans, root->fs_info->extent_root,
-				    path, bytenr, parent, root_objectid,
-				    owner, offset, 1);
+	ret = insert_extent_backref(trans, extent_root, path, bytenr, parent,
+				    root_objectid, owner, offset, 1);
 	if (ret)
 		err = ret;
 out:
@@ -1289,6 +1290,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 = btrfs_extent_root(fs_info, bytenr);
 	struct btrfs_path *path;
 	int ret;
 	struct btrfs_key key;
@@ -1315,7 +1317,7 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
 		key.type = BTRFS_EXTENT_ITEM_KEY;
 
 again:
-	ret = btrfs_search_slot(trans, fs_info->extent_root, &key, path, 0, 0);
+	ret = btrfs_search_slot(trans, extent_root, &key, path, 0, 0);
 	if (ret < 0)
 		goto out;
 
@@ -1374,6 +1376,7 @@ int btrfs_set_block_flags(struct btrfs_trans_handle *trans, u64 bytenr,
 			  int level, u64 flags)
 {
 	struct btrfs_fs_info *fs_info = trans->fs_info;
+	struct btrfs_root *extent_root = btrfs_extent_root(fs_info, bytenr);
 	struct btrfs_path *path;
 	int ret;
 	struct btrfs_key key;
@@ -1396,7 +1399,7 @@ int btrfs_set_block_flags(struct btrfs_trans_handle *trans, u64 bytenr,
 	}
 
 again:
-	ret = btrfs_search_slot(trans, fs_info->extent_root, &key, path, 0, 0);
+	ret = btrfs_search_slot(trans, extent_root, &key, path, 0, 0);
 	if (ret < 0)
 		goto out;
 
@@ -1537,7 +1540,7 @@ static int update_block_group_item(struct btrfs_trans_handle *trans,
 {
 	int ret;
 	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, 0);
 	unsigned long bi;
 	struct btrfs_block_group_item bgi;
 	struct extent_buffer *leaf;
@@ -1911,9 +1914,10 @@ static int __free_extent(struct btrfs_trans_handle *trans,
 			 u64 owner_offset, int refs_to_drop)
 {
 
+	struct btrfs_root *extent_root = btrfs_extent_root(trans->fs_info,
+							   bytenr);
 	struct btrfs_key key;
 	struct btrfs_path *path;
-	struct btrfs_root *extent_root = trans->fs_info->extent_root;
 	struct extent_buffer *leaf;
 	struct btrfs_extent_item *ei;
 	struct btrfs_extent_inline_ref *iref;
@@ -2181,7 +2185,7 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
 {
 	int ret;
 	u64 orig_search_start = search_start;
-	struct btrfs_root * root = orig_root->fs_info->extent_root;
+	struct btrfs_root *root = orig_root->fs_info->tree_root;
 	struct btrfs_fs_info *info = root->fs_info;
 	u64 total_needed = num_bytes;
 	struct btrfs_block_group *block_group;
@@ -2363,6 +2367,8 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
 				      struct btrfs_delayed_extent_op *extent_op)
 {
 
+	struct btrfs_root *extent_root = btrfs_extent_root(trans->fs_info,
+							   node->bytenr);
 	struct btrfs_delayed_tree_ref *ref = btrfs_delayed_node_to_tree_ref(node);
 	bool skinny_metadata = btrfs_fs_incompat(trans->fs_info, SKINNY_METADATA);
 	struct btrfs_fs_info *fs_info = trans->fs_info;
@@ -2403,8 +2409,7 @@ 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,
-				      &ins, size);
+	ret = btrfs_insert_empty_item(trans, extent_root, path, &ins, size);
 	if (ret)
 		return ret;
 
@@ -2726,7 +2731,7 @@ int btrfs_read_block_groups(struct btrfs_fs_info *fs_info)
 	int ret;
 	struct btrfs_key key;
 
-	root = fs_info->extent_root;
+	root = btrfs_extent_root(fs_info, 0);
 	key.objectid = 0;
 	key.offset = 0;
 	key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
@@ -2807,7 +2812,7 @@ static int insert_block_group_item(struct btrfs_trans_handle *trans,
 	key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
 	key.offset = block_group->length;
 
-	root = fs_info->extent_root;
+	root = btrfs_extent_root(fs_info, 0);
 	return btrfs_insert_item(trans, root, &key, &bgi, sizeof(bgi));
 }
 
@@ -2924,7 +2929,7 @@ static int remove_block_group_item(struct btrfs_trans_handle *trans,
 {
 	struct btrfs_fs_info *fs_info = trans->fs_info;
 	struct btrfs_key key;
-	struct btrfs_root *root = fs_info->extent_root;
+	struct btrfs_root *root = btrfs_extent_root(fs_info, 0);
 	int ret = 0;
 
 	key.objectid = block_group->start;
@@ -3247,7 +3252,6 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
 	return ret;
 }
 
-
 static void __get_extent_size(struct btrfs_root *root, struct btrfs_path *path,
 			      u64 *start, u64 *len)
 {
@@ -3319,7 +3323,7 @@ static int __btrfs_record_file_extent(struct btrfs_trans_handle *trans,
 {
 	int ret;
 	struct btrfs_fs_info *info = root->fs_info;
-	struct btrfs_root *extent_root = info->extent_root;
+	struct btrfs_root *extent_root = btrfs_extent_root(info, disk_bytenr);
 	struct extent_buffer *leaf;
 	struct btrfs_file_extent_item *fi;
 	struct btrfs_key ins_key;
diff --git a/kernel-shared/free-space-tree.c b/kernel-shared/free-space-tree.c
index 83a8520d..0434733d 100644
--- a/kernel-shared/free-space-tree.c
+++ b/kernel-shared/free-space-tree.c
@@ -1014,12 +1014,18 @@ out:
 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_fs_info *fs_info = trans->fs_info;
+	struct btrfs_root *extent_root;
 	struct btrfs_path *path, *path2;
 	struct btrfs_key key;
 	u64 start, end;
 	int ret;
 
+	if (btrfs_fs_incompat(fs_info, EXTENT_TREE_V2))
+		return -EINVAL;
+
+	extent_root = btrfs_extent_root(fs_info, 0);
+
 	path = btrfs_alloc_path();
 	if (!path)
 		return -ENOMEM;
diff --git a/kernel-shared/volumes.c b/kernel-shared/volumes.c
index 7d6fe8fd..4092c067 100644
--- a/kernel-shared/volumes.c
+++ b/kernel-shared/volumes.c
@@ -1348,7 +1348,6 @@ static int create_chunk(struct btrfs_trans_handle *trans,
 			struct btrfs_fs_info *info, struct alloc_chunk_ctl *ctl,
 			struct list_head *private_devs)
 {
-	struct btrfs_root *extent_root = info->extent_root;
 	struct btrfs_root *chunk_root = info->chunk_root;
 	struct btrfs_stripe *stripes;
 	struct btrfs_device *device = NULL;
@@ -1432,7 +1431,7 @@ static int create_chunk(struct btrfs_trans_handle *trans,
 
 	/* key was set above */
 	btrfs_set_stack_chunk_length(chunk, ctl->num_bytes);
-	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, BTRFS_STRIPE_LEN);
 	btrfs_set_stack_chunk_type(chunk, ctl->type);
 	btrfs_set_stack_chunk_num_stripes(chunk, ctl->num_stripes);
diff --git a/kernel-shared/zoned.c b/kernel-shared/zoned.c
index 776576bc..0164fe9f 100644
--- a/kernel-shared/zoned.c
+++ b/kernel-shared/zoned.c
@@ -757,7 +757,7 @@ static int calculate_alloc_pointer(struct btrfs_fs_info *fs_info,
 				   struct btrfs_block_group *cache,
 				   u64 *offset_ret)
 {
-	struct btrfs_root *root = fs_info->extent_root;
+	struct btrfs_root *root = btrfs_extent_root(fs_info, cache->start);
 	struct btrfs_path *path;
 	struct btrfs_key key;
 	struct btrfs_key found_key;
diff --git a/mkfs/main.c b/mkfs/main.c
index c6cc51e9..9647f12a 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -277,7 +277,7 @@ static int recow_roots(struct btrfs_trans_handle *trans,
 	ret = __recow_root(trans, info->tree_root);
 	if (ret)
 		return ret;
-	ret = __recow_root(trans, info->extent_root);
+	ret = __recow_root(trans, info->_extent_root);
 	if (ret)
 		return ret;
 	ret = __recow_root(trans, info->chunk_root);
@@ -588,7 +588,7 @@ static int cleanup_temp_chunks(struct btrfs_fs_info *fs_info,
 {
 	struct btrfs_trans_handle *trans = NULL;
 	struct btrfs_block_group_item *bgi;
-	struct btrfs_root *root = fs_info->extent_root;
+	struct btrfs_root *root = btrfs_extent_root(fs_info, 0);
 	struct btrfs_key key;
 	struct btrfs_key found_key;
 	struct btrfs_path path;
-- 
2.26.3


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

* [PATCH 14/20] btrfs-progs: stop accessing ->free_space_root directly
  2021-11-05 20:28 [PATCH 00/20] btrfs-progs: extent tree v2 global root support prep work Josef Bacik
                   ` (12 preceding siblings ...)
  2021-11-05 20:28 ` [PATCH 13/20] btrfs-progs: stop accessing ->extent_root directly Josef Bacik
@ 2021-11-05 20:28 ` Josef Bacik
  2021-11-06  0:44   ` Qu Wenruo
  2021-11-05 20:28 ` [PATCH 15/20] btrfs-progs: track csum, extent, and free space trees in a rb tree Josef Bacik
                   ` (6 subsequent siblings)
  20 siblings, 1 reply; 42+ messages in thread
From: Josef Bacik @ 2021-11-05 20:28 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

We're going to have multiple free space roots in the future, so access
it via a helper in most cases.  We will address the remaining direct
accesses in future patches.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 kernel-shared/ctree.h           |  2 +-
 kernel-shared/disk-io.c         | 24 ++++++++++-----------
 kernel-shared/free-space-tree.c | 37 +++++++++++++++++++++------------
 mkfs/main.c                     |  4 ++--
 4 files changed, 39 insertions(+), 28 deletions(-)

diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h
index 23750156..c263a3bb 100644
--- a/kernel-shared/ctree.h
+++ b/kernel-shared/ctree.h
@@ -1163,7 +1163,7 @@ struct btrfs_fs_info {
 	struct btrfs_root *dev_root;
 	struct btrfs_root *_csum_root;
 	struct btrfs_root *quota_root;
-	struct btrfs_root *free_space_root;
+	struct btrfs_root *_free_space_root;
 	struct btrfs_root *uuid_root;
 
 	struct rb_root fs_root_tree;
diff --git a/kernel-shared/disk-io.c b/kernel-shared/disk-io.c
index b4c45719..0e803db8 100644
--- a/kernel-shared/disk-io.c
+++ b/kernel-shared/disk-io.c
@@ -780,7 +780,7 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
 		return fs_info->quota_enabled ? fs_info->quota_root :
 				ERR_PTR(-ENOENT);
 	if (location->objectid == BTRFS_FREE_SPACE_TREE_OBJECTID)
-		return fs_info->free_space_root ? fs_info->free_space_root :
+		return fs_info->_free_space_root ? fs_info->_free_space_root :
 						ERR_PTR(-ENOENT);
 
 	BUG_ON(location->objectid == BTRFS_TREE_RELOC_OBJECTID);
@@ -810,7 +810,7 @@ void btrfs_free_fs_info(struct btrfs_fs_info *fs_info)
 	free(fs_info->chunk_root);
 	free(fs_info->dev_root);
 	free(fs_info->_csum_root);
-	free(fs_info->free_space_root);
+	free(fs_info->_free_space_root);
 	free(fs_info->uuid_root);
 	free(fs_info->super_copy);
 	free(fs_info->log_root_tree);
@@ -831,14 +831,14 @@ struct btrfs_fs_info *btrfs_new_fs_info(int writable, u64 sb_bytenr)
 	fs_info->dev_root = calloc(1, sizeof(struct btrfs_root));
 	fs_info->_csum_root = calloc(1, sizeof(struct btrfs_root));
 	fs_info->quota_root = calloc(1, sizeof(struct btrfs_root));
-	fs_info->free_space_root = calloc(1, sizeof(struct btrfs_root));
+	fs_info->_free_space_root = calloc(1, sizeof(struct btrfs_root));
 	fs_info->uuid_root = calloc(1, sizeof(struct btrfs_root));
 	fs_info->super_copy = calloc(1, BTRFS_SUPER_INFO_SIZE);
 
 	if (!fs_info->tree_root || !fs_info->_extent_root ||
 	    !fs_info->chunk_root || !fs_info->dev_root ||
 	    !fs_info->_csum_root || !fs_info->quota_root ||
-	    !fs_info->free_space_root || !fs_info->uuid_root ||
+	    !fs_info->_free_space_root || !fs_info->uuid_root ||
 	    !fs_info->super_copy)
 		goto free_all;
 
@@ -1031,17 +1031,17 @@ int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info, u64 root_tree_bytenr,
 
 	if (btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) {
 		ret = find_and_setup_root(root, fs_info, BTRFS_FREE_SPACE_TREE_OBJECTID,
-					  fs_info->free_space_root);
+					  fs_info->_free_space_root);
 		if (ret) {
-			free(fs_info->free_space_root);
-			fs_info->free_space_root = NULL;
+			free(fs_info->_free_space_root);
+			fs_info->_free_space_root = NULL;
 			printk("Couldn't read free space tree\n");
 			return -EIO;
 		}
-		fs_info->free_space_root->track_dirty = 1;
+		fs_info->_free_space_root->track_dirty = 1;
 	} else {
-		free(fs_info->free_space_root);
-		fs_info->free_space_root = NULL;
+		free(fs_info->_free_space_root);
+		fs_info->_free_space_root = NULL;
 	}
 
 	ret = find_and_setup_log_root(root, fs_info, sb);
@@ -1080,8 +1080,8 @@ int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info, u64 root_tree_bytenr,
 
 void btrfs_release_all_roots(struct btrfs_fs_info *fs_info)
 {
-	if (fs_info->free_space_root)
-		free_extent_buffer(fs_info->free_space_root->node);
+	if (fs_info->_free_space_root)
+		free_extent_buffer(fs_info->_free_space_root->node);
 	if (fs_info->quota_root)
 		free_extent_buffer(fs_info->quota_root->node);
 	if (fs_info->_csum_root)
diff --git a/kernel-shared/free-space-tree.c b/kernel-shared/free-space-tree.c
index 0434733d..70b3d62a 100644
--- a/kernel-shared/free-space-tree.c
+++ b/kernel-shared/free-space-tree.c
@@ -25,13 +25,19 @@
 #include "kernel-lib/bitops.h"
 #include "common/internal.h"
 
+static struct btrfs_root *btrfs_free_space_root(struct btrfs_fs_info *fs_info,
+						struct btrfs_block_group *block_group)
+{
+	return fs_info->_free_space_root;
+}
+
 static struct btrfs_free_space_info *
 search_free_space_info(struct btrfs_trans_handle *trans,
 		       struct btrfs_fs_info *fs_info,
 		       struct btrfs_block_group *block_group,
 		       struct btrfs_path *path, int cow)
 {
-	struct btrfs_root *root = fs_info->free_space_root;
+	struct btrfs_root *root = btrfs_free_space_root(fs_info, block_group);
 	struct btrfs_key key;
 	int ret;
 
@@ -103,7 +109,8 @@ 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_fs_info *fs_info = trans->fs_info;
+	struct btrfs_root *root = btrfs_free_space_root(fs_info, block_group);
 	struct btrfs_free_space_info *info;
 	struct btrfs_key key;
 	struct extent_buffer *leaf;
@@ -179,7 +186,7 @@ static 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(fs_info, block_group);
 	struct btrfs_free_space_info *info;
 	struct btrfs_key key, found_key;
 	struct extent_buffer *leaf;
@@ -318,7 +325,7 @@ static 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(fs_info, block_group);
 	struct btrfs_free_space_info *info;
 	struct btrfs_key key, found_key;
 	struct extent_buffer *leaf;
@@ -558,7 +565,8 @@ 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 = trans->fs_info->free_space_root;
+	struct btrfs_fs_info *fs_info = trans->fs_info;
+	struct btrfs_root *root = btrfs_free_space_root(fs_info, block_group);
 	struct btrfs_key key;
 	u64 end = start + size;
 	u64 cur_start, cur_size;
@@ -671,7 +679,8 @@ 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_fs_info *fs_info = trans->fs_info;
+	struct btrfs_root *root = btrfs_free_space_root(fs_info, block_group);
 	struct btrfs_key key;
 	u64 found_start, found_end;
 	u64 end = start + size;
@@ -811,7 +820,8 @@ 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_fs_info *fs_info = trans->fs_info;
+	struct btrfs_root *root = btrfs_free_space_root(fs_info, block_group);
 	struct btrfs_key key, new_key;
 	u64 found_start, found_end;
 	u64 end = start + size;
@@ -1107,7 +1117,8 @@ out:
 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_fs_info *fs_info = trans->fs_info;
+	struct btrfs_root *root = btrfs_free_space_root(fs_info, block_group);
 	struct btrfs_path *path;
 	struct btrfs_key key, found_key;
 	struct extent_buffer *leaf;
@@ -1215,7 +1226,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 = btrfs_free_space_root(fs_info, NULL);
 	int ret;
 	u64 features;
 
@@ -1227,7 +1238,7 @@ int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info)
 	features &= ~(BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID |
 		      BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE);
 	btrfs_set_super_compat_ro_flags(fs_info->super_copy, features);
-	fs_info->free_space_root = NULL;
+	fs_info->_free_space_root = NULL;
 
 	ret = clear_free_space_tree(trans, free_space_root);
 	if (ret)
@@ -1263,7 +1274,7 @@ static int load_free_space_bitmaps(struct btrfs_fs_info *fs_info,
 				   u32 expected_extent_count,
 				   int *errors)
 {
-	struct btrfs_root *root = fs_info->free_space_root;
+	struct btrfs_root *root = btrfs_free_space_root(fs_info, block_group);
 	struct btrfs_key key;
 	int prev_bit = 0, bit;
 	u64 extent_start = 0;
@@ -1343,7 +1354,7 @@ static int load_free_space_extents(struct btrfs_fs_info *fs_info,
 				   u32 expected_extent_count,
 				   int *errors)
 {
-	struct btrfs_root *root = fs_info->free_space_root;
+	struct btrfs_root *root = btrfs_free_space_root(fs_info, block_group);
 	struct btrfs_key key, prev_key;
 	int have_prev = 0;
 	u64 start, end;
@@ -1463,7 +1474,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;
 	add_root_to_dirty_list(free_space_root);
 
 	do {
diff --git a/mkfs/main.c b/mkfs/main.c
index 9647f12a..16f9ba19 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -289,8 +289,8 @@ static int recow_roots(struct btrfs_trans_handle *trans,
 	ret = __recow_root(trans, csum_root);
 	if (ret)
 		return ret;
-	if (info->free_space_root) {
-		ret = __recow_root(trans, info->free_space_root);
+	if (info->_free_space_root) {
+		ret = __recow_root(trans, info->_free_space_root);
 		if (ret)
 			return ret;
 	}
-- 
2.26.3


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

* [PATCH 15/20] btrfs-progs: track csum, extent, and free space trees in a rb tree
  2021-11-05 20:28 [PATCH 00/20] btrfs-progs: extent tree v2 global root support prep work Josef Bacik
                   ` (13 preceding siblings ...)
  2021-11-05 20:28 ` [PATCH 14/20] btrfs-progs: stop accessing ->free_space_root directly Josef Bacik
@ 2021-11-05 20:28 ` Josef Bacik
  2021-11-05 20:28 ` [PATCH 16/20] btrfs-progs: check: make reinit work per found root item Josef Bacik
                   ` (5 subsequent siblings)
  20 siblings, 0 replies; 42+ messages in thread
From: Josef Bacik @ 2021-11-05 20:28 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

We are going to have multiples of these trees with extent tree v2, so
add a rb tree to track them based on their root key value.  This works
for both v1 and v2, so we can remove the direct pointers to these roots
in our fs_info.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 kernel-shared/ctree.h           |   4 +-
 kernel-shared/disk-io.c         | 290 ++++++++++++++++++++++++--------
 kernel-shared/disk-io.h         |   5 +
 kernel-shared/free-space-tree.c |  15 +-
 mkfs/main.c                     |  28 +--
 5 files changed, 259 insertions(+), 83 deletions(-)

diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h
index c263a3bb..12a8165d 100644
--- a/kernel-shared/ctree.h
+++ b/kernel-shared/ctree.h
@@ -1157,15 +1157,13 @@ struct btrfs_fs_info {
 	u8 chunk_tree_uuid[BTRFS_UUID_SIZE];
 	u8 *new_chunk_tree_uuid;
 	struct btrfs_root *fs_root;
-	struct btrfs_root *_extent_root;
 	struct btrfs_root *tree_root;
 	struct btrfs_root *chunk_root;
 	struct btrfs_root *dev_root;
-	struct btrfs_root *_csum_root;
 	struct btrfs_root *quota_root;
-	struct btrfs_root *_free_space_root;
 	struct btrfs_root *uuid_root;
 
+	struct rb_root global_roots_tree;
 	struct rb_root fs_root_tree;
 
 	/* the log root tree is a directory of all the other log roots */
diff --git a/kernel-shared/disk-io.c b/kernel-shared/disk-io.c
index 0e803db8..981ac4f8 100644
--- a/kernel-shared/disk-io.c
+++ b/kernel-shared/disk-io.c
@@ -721,6 +721,23 @@ insert:
 	return root;
 }
 
+static int btrfs_global_roots_compare_keys(struct rb_node *node,
+					   void *data)
+{
+	struct btrfs_key *key = (struct btrfs_key *)data;
+	struct btrfs_root *root;
+
+	root = rb_entry(node, struct btrfs_root, rb_node);
+	return btrfs_comp_cpu_keys(key, &root->root_key);
+}
+
+static int btrfs_global_roots_compare(struct rb_node *node1,
+				      struct rb_node *node2)
+{
+	struct btrfs_root *root = rb_entry(node2, struct btrfs_root, rb_node);
+	return btrfs_global_roots_compare_keys(node1, &root->root_key);
+}
+
 static int btrfs_fs_roots_compare_objectids(struct rb_node *node,
 					    void *data)
 {
@@ -744,16 +761,54 @@ int btrfs_fs_roots_compare_roots(struct rb_node *node1, struct rb_node *node2)
 	return btrfs_fs_roots_compare_objectids(node1, (void *)&root->objectid);
 }
 
+int btrfs_global_root_insert(struct btrfs_fs_info *fs_info,
+			     struct btrfs_root *root)
+{
+	return rb_insert(&fs_info->global_roots_tree, &root->rb_node,
+			 btrfs_global_roots_compare);
+}
+
+struct btrfs_root *btrfs_global_root(struct btrfs_fs_info *fs_info,
+				     struct btrfs_key *key)
+{
+	struct rb_node *node;
+
+	/*
+	 * Some callers use the key->offset = (u64)-1 convention for looking up
+	 * roots, so set this to 0 if we ended up here from that.
+	 */
+	if (key->offset == (u64)-1)
+		key->offset = 0;
+
+	node = rb_search(&fs_info->global_roots_tree, (void *)key,
+			 btrfs_global_roots_compare_keys, NULL);
+	if (node)
+		return rb_entry(node, struct btrfs_root, rb_node);
+	return NULL;
+}
+
 struct btrfs_root *btrfs_csum_root(struct btrfs_fs_info *fs_info,
 				   u64 bytenr)
 {
-	return fs_info->_csum_root;
+	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)
 {
-	return fs_info->_extent_root;
+	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_read_fs_root(struct btrfs_fs_info *fs_info,
@@ -767,21 +822,22 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
 	if (location->objectid == BTRFS_ROOT_TREE_OBJECTID)
 		return fs_info->tree_root;
 	if (location->objectid == BTRFS_EXTENT_TREE_OBJECTID)
-		return fs_info->_extent_root;
+		return btrfs_global_root(fs_info, location);
 	if (location->objectid == BTRFS_CHUNK_TREE_OBJECTID)
 		return fs_info->chunk_root;
 	if (location->objectid == BTRFS_DEV_TREE_OBJECTID)
 		return fs_info->dev_root;
 	if (location->objectid == BTRFS_CSUM_TREE_OBJECTID)
-		return btrfs_csum_root(fs_info, location->offset);
+		return btrfs_global_root(fs_info, location);
 	if (location->objectid == BTRFS_UUID_TREE_OBJECTID)
 		return fs_info->uuid_root ? fs_info->uuid_root : ERR_PTR(-ENOENT);
 	if (location->objectid == BTRFS_QUOTA_TREE_OBJECTID)
 		return fs_info->quota_enabled ? fs_info->quota_root :
 				ERR_PTR(-ENOENT);
-	if (location->objectid == BTRFS_FREE_SPACE_TREE_OBJECTID)
-		return fs_info->_free_space_root ? fs_info->_free_space_root :
-						ERR_PTR(-ENOENT);
+	if (location->objectid == BTRFS_FREE_SPACE_TREE_OBJECTID) {
+		root = btrfs_global_root(fs_info, location);
+		return root ? root : ERR_PTR(-ENOENT);
+	}
 
 	BUG_ON(location->objectid == BTRFS_TREE_RELOC_OBJECTID);
 
@@ -800,17 +856,25 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
 	return root;
 }
 
+static void __free_global_root(struct rb_node *node)
+{
+	struct btrfs_root *root;
+
+	root = rb_entry(node, struct btrfs_root, rb_node);
+	kfree(root);
+}
+
+FREE_RB_BASED_TREE(global_roots, __free_global_root);
+
 void btrfs_free_fs_info(struct btrfs_fs_info *fs_info)
 {
 	if (fs_info->quota_root)
 		free(fs_info->quota_root);
 
+	free_global_roots_tree(&fs_info->global_roots_tree);
 	free(fs_info->tree_root);
-	free(fs_info->_extent_root);
 	free(fs_info->chunk_root);
 	free(fs_info->dev_root);
-	free(fs_info->_csum_root);
-	free(fs_info->_free_space_root);
 	free(fs_info->uuid_root);
 	free(fs_info->super_copy);
 	free(fs_info->log_root_tree);
@@ -826,20 +890,14 @@ struct btrfs_fs_info *btrfs_new_fs_info(int writable, u64 sb_bytenr)
 		return NULL;
 
 	fs_info->tree_root = calloc(1, sizeof(struct btrfs_root));
-	fs_info->_extent_root = calloc(1, sizeof(struct btrfs_root));
 	fs_info->chunk_root = calloc(1, sizeof(struct btrfs_root));
 	fs_info->dev_root = calloc(1, sizeof(struct btrfs_root));
-	fs_info->_csum_root = calloc(1, sizeof(struct btrfs_root));
 	fs_info->quota_root = calloc(1, sizeof(struct btrfs_root));
-	fs_info->_free_space_root = calloc(1, sizeof(struct btrfs_root));
 	fs_info->uuid_root = calloc(1, sizeof(struct btrfs_root));
 	fs_info->super_copy = calloc(1, BTRFS_SUPER_INFO_SIZE);
 
-	if (!fs_info->tree_root || !fs_info->_extent_root ||
-	    !fs_info->chunk_root || !fs_info->dev_root ||
-	    !fs_info->_csum_root || !fs_info->quota_root ||
-	    !fs_info->_free_space_root || !fs_info->uuid_root ||
-	    !fs_info->super_copy)
+	if (!fs_info->tree_root || !fs_info->chunk_root || !fs_info->dev_root ||
+	    !fs_info->quota_root || !fs_info->uuid_root || !fs_info->super_copy)
 		goto free_all;
 
 	extent_io_tree_init(&fs_info->extent_cache);
@@ -929,15 +987,13 @@ static int find_best_backup_root(struct btrfs_super_block *super)
 	return best_index;
 }
 
-static int setup_root_or_create_block(struct btrfs_fs_info *fs_info,
-				      unsigned flags,
-				      struct btrfs_root *info_root,
-				      u64 objectid, char *str)
+static int read_root_or_create_block(struct btrfs_fs_info *fs_info,
+				     struct btrfs_root *root, u64 bytenr,
+				     u64 gen, unsigned flags, char *str)
 {
-	struct btrfs_root *root = fs_info->tree_root;
 	int ret;
 
-	ret = find_and_setup_root(root, fs_info, objectid, info_root);
+	ret = read_root_node(fs_info, root, bytenr, gen);
 	if (ret) {
 		if (!(flags & OPEN_CTREE_PARTIAL)) {
 			error("could not setup %s tree", str);
@@ -948,16 +1004,127 @@ static int setup_root_or_create_block(struct btrfs_fs_info *fs_info,
 		 * Need a blank node here just so we don't screw up in the
 		 * million of places that assume a root has a valid ->node
 		 */
-		info_root->node =
-			btrfs_find_create_tree_block(fs_info, 0);
-		if (!info_root->node)
+		root->node = btrfs_find_create_tree_block(fs_info, 0);
+		if (!root->node)
 			return -ENOMEM;
-		clear_extent_buffer_uptodate(info_root->node);
+		clear_extent_buffer_uptodate(root->node);
 	}
 
 	return 0;
 }
 
+static inline bool maybe_load_block_groups(struct btrfs_fs_info *fs_info,
+					   u64 flags)
+{
+	struct btrfs_root *root = btrfs_extent_root(fs_info, 0);
+
+	if (flags & OPEN_CTREE_NO_BLOCK_GROUPS)
+		return false;
+
+	if (root && extent_buffer_uptodate(root->node))
+		return true;
+
+	return false;
+}
+
+
+static int load_global_roots_objectid(struct btrfs_fs_info *fs_info,
+				      struct btrfs_path *path, u64 objectid,
+				      unsigned flags, char *str)
+{
+	struct btrfs_root *tree_root = fs_info->tree_root;
+	struct btrfs_root *root;
+	int ret;
+	struct btrfs_key key = {
+		.objectid = objectid,
+		.type = BTRFS_ROOT_ITEM_KEY,
+		.offset = 0,
+	};
+
+
+	ret = btrfs_search_slot(NULL, tree_root, &key, path, 0, 0);
+	if (ret < 0) {
+		error("could not find %s tree", str);
+		return ret;
+	}
+	ret = 0;
+
+	while (1) {
+		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;
+			}
+		}
+		btrfs_item_key_to_cpu(path->nodes[0], &key,
+				      path->slots[0]);
+		if (key.objectid != objectid)
+			break;
+
+		root = calloc(1, sizeof(*root));
+		if (!root) {
+			ret = -ENOMEM;
+			break;
+		}
+
+		btrfs_setup_root(root, fs_info, objectid);
+		read_extent_buffer(path->nodes[0], &root->root_item,
+				   btrfs_item_ptr_offset(path->nodes[0],
+							 path->slots[0]),
+				   sizeof(root->root_item));
+		memcpy(&root->root_key, &key, sizeof(key));
+		ret = read_root_or_create_block(fs_info, root,
+				btrfs_root_bytenr(&root->root_item),
+				btrfs_root_generation(&root->root_item),
+				flags, str);
+		if (ret) {
+			free(root);
+			break;
+		}
+		root->track_dirty = 1;
+
+		ret = btrfs_global_root_insert(fs_info, root);
+		if (ret) {
+			free_extent_buffer(root->node);
+			free(root);
+			break;
+		}
+
+		path->slots[0]++;
+	}
+	btrfs_release_path(path);
+	return ret;
+}
+
+static int load_global_roots(struct btrfs_fs_info *fs_info, unsigned flags)
+{
+	struct btrfs_path *path;
+	int ret = 0;
+
+	path = btrfs_alloc_path();
+	if (!path)
+		return -ENOMEM;
+
+	ret = load_global_roots_objectid(fs_info, path,
+					 BTRFS_EXTENT_TREE_OBJECTID, flags,
+					 "extent");
+	if (ret)
+		goto out;
+	ret = load_global_roots_objectid(fs_info, path,
+					 BTRFS_CSUM_TREE_OBJECTID, flags,
+					 "csum");
+	if (ret)
+		goto out;
+	ret = load_global_roots_objectid(fs_info, path,
+					 BTRFS_FREE_SPACE_TREE_OBJECTID, flags,
+					 "free space");
+out:
+	btrfs_free_path(path);
+	return ret;
+}
+
 int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info, u64 root_tree_bytenr,
 			  unsigned flags)
 {
@@ -991,11 +1158,9 @@ int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info, u64 root_tree_bytenr,
 		return -EIO;
 	}
 
-	ret = setup_root_or_create_block(fs_info, flags, fs_info->_extent_root,
-					 BTRFS_EXTENT_TREE_OBJECTID, "extent");
+	ret = load_global_roots(fs_info, flags);
 	if (ret)
 		return ret;
-	fs_info->_extent_root->track_dirty = 1;
 
 	ret = find_and_setup_root(root, fs_info, BTRFS_DEV_TREE_OBJECTID,
 				  fs_info->dev_root);
@@ -1005,12 +1170,6 @@ int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info, u64 root_tree_bytenr,
 	}
 	fs_info->dev_root->track_dirty = 1;
 
-	ret = setup_root_or_create_block(fs_info, flags, fs_info->_csum_root,
-					 BTRFS_CSUM_TREE_OBJECTID, "csum");
-	if (ret)
-		return ret;
-	fs_info->_csum_root->track_dirty = 1;
-
 	ret = find_and_setup_root(root, fs_info, BTRFS_UUID_TREE_OBJECTID,
 				  fs_info->uuid_root);
 	if (ret) {
@@ -1029,21 +1188,6 @@ int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info, u64 root_tree_bytenr,
 		fs_info->quota_enabled = 1;
 	}
 
-	if (btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) {
-		ret = find_and_setup_root(root, fs_info, BTRFS_FREE_SPACE_TREE_OBJECTID,
-					  fs_info->_free_space_root);
-		if (ret) {
-			free(fs_info->_free_space_root);
-			fs_info->_free_space_root = NULL;
-			printk("Couldn't read free space tree\n");
-			return -EIO;
-		}
-		fs_info->_free_space_root->track_dirty = 1;
-	} else {
-		free(fs_info->_free_space_root);
-		fs_info->_free_space_root = NULL;
-	}
-
 	ret = find_and_setup_log_root(root, fs_info, sb);
 	if (ret) {
 		printk("Couldn't setup log root tree\n");
@@ -1053,8 +1197,7 @@ int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info, u64 root_tree_bytenr,
 
 	fs_info->generation = generation;
 	fs_info->last_trans_committed = generation;
-	if (extent_buffer_uptodate(fs_info->_extent_root->node) &&
-	    !(flags & OPEN_CTREE_NO_BLOCK_GROUPS)) {
+	if (maybe_load_block_groups(fs_info, flags)) {
 		ret = btrfs_read_block_groups(fs_info);
 		/*
 		 * If we don't find any blockgroups (ENOENT) we're either
@@ -1078,18 +1221,29 @@ int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info, u64 root_tree_bytenr,
 	return 0;
 }
 
+static void release_global_roots(struct btrfs_fs_info *fs_info)
+{
+	struct btrfs_root *root;
+	struct rb_node *n;
+
+	for (n = rb_first(&fs_info->global_roots_tree); n; n = rb_next(n)) {
+		root = rb_entry(n, struct btrfs_root, rb_node);
+		if (root->node)
+			free_extent_buffer(root->node);
+		if (root->commit_root)
+			free_extent_buffer(root->commit_root);
+		root->node = NULL;
+		root->commit_root = NULL;
+	}
+}
+
 void btrfs_release_all_roots(struct btrfs_fs_info *fs_info)
 {
-	if (fs_info->_free_space_root)
-		free_extent_buffer(fs_info->_free_space_root->node);
+	release_global_roots(fs_info);
 	if (fs_info->quota_root)
 		free_extent_buffer(fs_info->quota_root->node);
-	if (fs_info->_csum_root)
-		free_extent_buffer(fs_info->_csum_root->node);
 	if (fs_info->dev_root)
 		free_extent_buffer(fs_info->dev_root->node);
-	if (fs_info->_extent_root)
-		free_extent_buffer(fs_info->_extent_root->node);
 	if (fs_info->tree_root)
 		free_extent_buffer(fs_info->tree_root->node);
 	if (fs_info->log_root_tree)
@@ -1811,6 +1965,8 @@ static int write_dev_supers(struct btrfs_fs_info *fs_info,
 static void backup_super_roots(struct btrfs_fs_info *info)
 {
 	struct btrfs_root_backup *root_backup;
+	struct btrfs_root *csum_root = btrfs_csum_root(info, 0);
+	struct btrfs_root *extent_root = btrfs_extent_root(info, 0);
 	int next_backup;
 	int last_backup;
 
@@ -1842,11 +1998,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
 	 * the fs_root.  Make sure it is valid before we fill it in.
@@ -1866,11 +2022,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));
@@ -1878,7 +2034,7 @@ static void backup_super_roots(struct btrfs_fs_info *info)
 			     btrfs_super_bytes_used(info->super_copy));
 	btrfs_set_backup_num_devices(root_backup,
 			     btrfs_super_num_devices(info->super_copy));
-};
+}
 
 int write_all_supers(struct btrfs_fs_info *fs_info)
 {
diff --git a/kernel-shared/disk-io.h b/kernel-shared/disk-io.h
index dc71cc2b..0d2f505f 100644
--- a/kernel-shared/disk-io.h
+++ b/kernel-shared/disk-io.h
@@ -219,4 +219,9 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans,
 				     u64 objectid);
 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_inf, u64 bytenr);
+struct btrfs_root *btrfs_block_group_root(struct btrfs_fs_info *fs_info);
+struct btrfs_root *btrfs_global_root(struct btrfs_fs_info *fs_info,
+				     struct btrfs_key *key);
+int btrfs_global_root_insert(struct btrfs_fs_info *fs_info,
+			     struct btrfs_root *root);
 #endif
diff --git a/kernel-shared/free-space-tree.c b/kernel-shared/free-space-tree.c
index 70b3d62a..0fdf5004 100644
--- a/kernel-shared/free-space-tree.c
+++ b/kernel-shared/free-space-tree.c
@@ -28,7 +28,13 @@
 static struct btrfs_root *btrfs_free_space_root(struct btrfs_fs_info *fs_info,
 						struct btrfs_block_group *block_group)
 {
-	return 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(fs_info, &key);
 }
 
 static struct btrfs_free_space_info *
@@ -1238,7 +1244,6 @@ int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info)
 	features &= ~(BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID |
 		      BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE);
 	btrfs_set_super_compat_ro_flags(fs_info->super_copy, features);
-	fs_info->_free_space_root = NULL;
 
 	ret = clear_free_space_tree(trans, free_space_root);
 	if (ret)
@@ -1258,6 +1263,7 @@ int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info)
 	if (ret)
 		goto abort;
 
+	rb_erase(&free_space_root->rb_node, &fs_info->global_roots_tree);
 	free_extent_buffer(free_space_root->node);
 	free_extent_buffer(free_space_root->commit_root);
 	kfree(free_space_root);
@@ -1474,7 +1480,10 @@ 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(fs_info, free_space_root);
+	if (ret)
+		goto abort;
 	add_root_to_dirty_list(free_space_root);
 
 	do {
diff --git a/mkfs/main.c b/mkfs/main.c
index 16f9ba19..d0c863fd 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -264,20 +264,33 @@ out:
 	return ret;
 }
 
+static int recow_global_roots(struct btrfs_trans_handle *trans)
+{
+	struct btrfs_fs_info *fs_info = trans->fs_info;
+	struct btrfs_root *root;
+	struct rb_node *n;
+	int ret = 0;
+
+	for (n = rb_first(&fs_info->global_roots_tree); n; n = rb_next(n)) {
+		root = rb_entry(n, struct btrfs_root, rb_node);
+		ret = __recow_root(trans, root);
+		if (ret)
+			return ret;
+	}
+
+	return ret;
+}
+
 static int recow_roots(struct btrfs_trans_handle *trans,
 		       struct btrfs_root *root)
 {
 	struct btrfs_fs_info *info = root->fs_info;
-	struct btrfs_root *csum_root = btrfs_csum_root(info, 0);
 	int ret;
 
 	ret = __recow_root(trans, info->fs_root);
 	if (ret)
 		return ret;
 	ret = __recow_root(trans, info->tree_root);
-	if (ret)
-		return ret;
-	ret = __recow_root(trans, info->_extent_root);
 	if (ret)
 		return ret;
 	ret = __recow_root(trans, info->chunk_root);
@@ -286,14 +299,9 @@ static int recow_roots(struct btrfs_trans_handle *trans,
 	ret = __recow_root(trans, info->dev_root);
 	if (ret)
 		return ret;
-	ret = __recow_root(trans, csum_root);
+	ret = recow_global_roots(trans);
 	if (ret)
 		return ret;
-	if (info->_free_space_root) {
-		ret = __recow_root(trans, info->_free_space_root);
-		if (ret)
-			return ret;
-	}
 	return 0;
 }
 
-- 
2.26.3


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

* [PATCH 16/20] btrfs-progs: check: make reinit work per found root item
  2021-11-05 20:28 [PATCH 00/20] btrfs-progs: extent tree v2 global root support prep work Josef Bacik
                   ` (14 preceding siblings ...)
  2021-11-05 20:28 ` [PATCH 15/20] btrfs-progs: track csum, extent, and free space trees in a rb tree Josef Bacik
@ 2021-11-05 20:28 ` Josef Bacik
  2021-11-05 20:28 ` [PATCH 17/20] btrfs-progs: check: check the global roots for uptodate root nodes Josef Bacik
                   ` (4 subsequent siblings)
  20 siblings, 0 replies; 42+ messages in thread
From: Josef Bacik @ 2021-11-05 20:28 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

Instead of looking for the first extent root or csum root in memory,
scan through the tree root and re-init any root items that match the
given objectid.  This will allow reinit to work with both extent tree v1
and extent tree v2 global roots when using the --reinit option.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 check/main.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 49 insertions(+), 3 deletions(-)

diff --git a/check/main.c b/check/main.c
index e3e5a336..140cd427 100644
--- a/check/main.c
+++ b/check/main.c
@@ -9319,6 +9319,52 @@ out:
 	return ret;
 }
 
+static int reinit_global_roots(struct btrfs_trans_handle *trans, u64 objectid)
+{
+	struct btrfs_key key = {
+		.objectid = objectid,
+		.type = BTRFS_ROOT_ITEM_KEY,
+		.offset = 0,
+	};
+	struct btrfs_path path;
+	struct btrfs_root *tree_root = gfs_info->tree_root;
+	struct btrfs_root *root;
+	int ret;
+
+	btrfs_init_path(&path);
+	while (1) {
+		ret = btrfs_search_slot(NULL, tree_root, &key, &path, 0, 0);
+		if (ret) {
+			if (ret == 1) {
+				/* We should at least find the first one. */
+				if (key.offset == 0)
+					ret = -ENOENT;
+				else
+					ret = 0;
+			}
+			break;
+		}
+
+		btrfs_item_key_to_cpu(path.nodes[0], &key, path.slots[0]);
+		if (key.objectid != objectid)
+			break;
+		btrfs_release_path(&path);
+		root = btrfs_read_fs_root(gfs_info, &key);
+		if (IS_ERR(root)) {
+			error("Error reading global root [%llu %llu]",
+			      key.objectid, key.offset);
+			ret = PTR_ERR(root);
+			break;
+		}
+		ret = btrfs_fsck_reinit_root(trans, root);
+		if (ret)
+			break;
+		key.offset++;
+	}
+	btrfs_release_path(&path);
+	return ret;
+}
+
 static int reinit_extent_tree(struct btrfs_trans_handle *trans, bool pin)
 {
 	u64 start = 0;
@@ -9375,7 +9421,7 @@ again:
 	}
 
 	/* Ok we can allocate now, reinit the extent root */
-	ret = btrfs_fsck_reinit_root(trans, btrfs_extent_root(gfs_info, 0));
+	ret = reinit_global_roots(trans, BTRFS_EXTENT_TREE_OBJECTID);
 	if (ret) {
 		fprintf(stderr, "extent root initialization failed\n");
 		/*
@@ -10699,8 +10745,8 @@ static int cmd_check(const struct cmd_struct *cmd, int argc, char **argv)
 
 		if (init_csum_tree) {
 			printf("Reinitialize checksum tree\n");
-			ret = btrfs_fsck_reinit_root(trans,
-						btrfs_csum_root(gfs_info, 0));
+			ret = reinit_global_roots(trans,
+						  BTRFS_CSUM_TREE_OBJECTID);
 			if (ret) {
 				error("checksum tree initialization failed: %d",
 						ret);
-- 
2.26.3


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

* [PATCH 17/20] btrfs-progs: check: check the global roots for uptodate root nodes
  2021-11-05 20:28 [PATCH 00/20] btrfs-progs: extent tree v2 global root support prep work Josef Bacik
                   ` (15 preceding siblings ...)
  2021-11-05 20:28 ` [PATCH 16/20] btrfs-progs: check: make reinit work per found root item Josef Bacik
@ 2021-11-05 20:28 ` Josef Bacik
  2021-11-05 20:28 ` [PATCH 18/20] btrfs-progs: check: check all of the csum roots Josef Bacik
                   ` (3 subsequent siblings)
  20 siblings, 0 replies; 42+ messages in thread
From: Josef Bacik @ 2021-11-05 20:28 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

Instead of checking the csum and extent tree individually, walk through
the global roots and validate them all.  This will work properly if we
have extent tree v1 or extent tree v2.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 check/main.c | 30 +++++++++++++++++++-----------
 1 file changed, 19 insertions(+), 11 deletions(-)

diff --git a/check/main.c b/check/main.c
index 140cd427..6795e675 100644
--- a/check/main.c
+++ b/check/main.c
@@ -10379,6 +10379,23 @@ out:
 	return ret;
 }
 
+static int check_global_roots_uptodate(void)
+{
+	struct btrfs_root *root;
+	struct rb_node *n;
+
+	for (n = rb_first(&gfs_info->global_roots_tree); n; n = rb_next(n)) {
+		root = rb_entry(n, struct btrfs_root, rb_node);
+		if (!extent_buffer_uptodate(root->node)) {
+			error("chritical: global root [%llu %llu] not uptodate, unable to check the file system",
+			      root->root_key.objectid, root->root_key.offset);
+			return -EIO;
+		}
+	}
+
+	return 0;
+}
+
 static const char * const cmd_check_usage[] = {
 	"btrfs check [options] <device>",
 	"Check structural integrity of a filesystem (unmounted).",
@@ -10771,18 +10788,9 @@ static int cmd_check(const struct cmd_struct *cmd, int argc, char **argv)
 		if (ret)
 			goto close_out;
 	}
-	root = btrfs_extent_root(gfs_info, 0);
-	if (!extent_buffer_uptodate(root->node)) {
-		error("critical: extent_root, unable to check the filesystem");
-		ret = -EIO;
-		err |= !!ret;
-		goto close_out;
-	}
 
-	root = btrfs_csum_root(gfs_info, 0);
-	if (!extent_buffer_uptodate(root->node)) {
-		error("critical: csum_root, unable to check the filesystem");
-		ret = -EIO;
+	ret = check_global_roots_uptodate();
+	if (ret) {
 		err |= !!ret;
 		goto close_out;
 	}
-- 
2.26.3


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

* [PATCH 18/20] btrfs-progs: check: check all of the csum roots
  2021-11-05 20:28 [PATCH 00/20] btrfs-progs: extent tree v2 global root support prep work Josef Bacik
                   ` (16 preceding siblings ...)
  2021-11-05 20:28 ` [PATCH 17/20] btrfs-progs: check: check the global roots for uptodate root nodes Josef Bacik
@ 2021-11-05 20:28 ` Josef Bacik
  2021-11-05 20:28 ` [PATCH 19/20] btrfs-progs: check: fill csum root from all extent roots Josef Bacik
                   ` (2 subsequent siblings)
  20 siblings, 0 replies; 42+ messages in thread
From: Josef Bacik @ 2021-11-05 20:28 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

Use the global roots tree to find all of the csum roots in the system
and check all of them as appropriate.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 check/main.c | 26 +++++++++++++++++++++++---
 1 file changed, 23 insertions(+), 3 deletions(-)

diff --git a/check/main.c b/check/main.c
index 6795e675..175fe616 100644
--- a/check/main.c
+++ b/check/main.c
@@ -5977,7 +5977,7 @@ out:
 	return ret;
 }
 
-static int check_csums(struct btrfs_root *root)
+static int check_csum_root(struct btrfs_root *root)
 {
 	struct btrfs_path path;
 	struct extent_buffer *leaf;
@@ -5991,7 +5991,6 @@ static int check_csums(struct btrfs_root *root)
 	unsigned long leaf_offset;
 	bool verify_csum = !!check_data_csum;
 
-	root = btrfs_csum_root(gfs_info, 0);
 	if (!extent_buffer_uptodate(root->node)) {
 		fprintf(stderr, "No valid csum tree found\n");
 		return -ENOENT;
@@ -6087,6 +6086,27 @@ skip_csum_check:
 	return errors;
 }
 
+static int check_csums(void)
+{
+	struct rb_node *n;
+	struct btrfs_root *root;
+	int ret;
+
+	root = btrfs_csum_root(gfs_info, 0);
+	while (1) {
+		ret = check_csum_root(root);
+		if (ret)
+			break;
+		n = rb_next(&root->rb_node);
+		if (!n)
+			break;
+		root = rb_entry(n, struct btrfs_root, rb_node);
+		if (root->root_key.objectid != BTRFS_CSUM_TREE_OBJECTID)
+			break;
+	}
+	return ret;
+}
+
 static int is_dropped_key(struct btrfs_key *key,
 			  struct btrfs_key *drop_key)
 {
@@ -10899,7 +10919,7 @@ static int cmd_check(const struct cmd_struct *cmd, int argc, char **argv)
 		task_start(ctx.info, &ctx.start_time, &ctx.item_count);
 	}
 
-	ret = check_csums(root);
+	ret = check_csums();
 	task_stop(ctx.info);
 	/*
 	 * Data csum error is not fatal, and it may indicate more serious
-- 
2.26.3


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

* [PATCH 19/20] btrfs-progs: check: fill csum root from all extent roots
  2021-11-05 20:28 [PATCH 00/20] btrfs-progs: extent tree v2 global root support prep work Josef Bacik
                   ` (17 preceding siblings ...)
  2021-11-05 20:28 ` [PATCH 18/20] btrfs-progs: check: check all of the csum roots Josef Bacik
@ 2021-11-05 20:28 ` Josef Bacik
  2021-11-05 20:28 ` [PATCH 20/20] btrfs-progs: common: search all extent roots for marking used space Josef Bacik
  2021-11-06  0:55 ` [PATCH 00/20] btrfs-progs: extent tree v2 global root support prep work Qu Wenruo
  20 siblings, 0 replies; 42+ messages in thread
From: Josef Bacik @ 2021-11-05 20:28 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

We may have multiple extent roots, so cycle through all of the extent
roots and populate the csum tree based on the content of every extent
root we have in the file system.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 check/main.c | 24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/check/main.c b/check/main.c
index 175fe616..5fb28216 100644
--- a/check/main.c
+++ b/check/main.c
@@ -9690,9 +9690,9 @@ out:
 	return ret;
 }
 
-static int fill_csum_tree_from_extent(struct btrfs_trans_handle *trans)
+static int fill_csum_tree_from_extent(struct btrfs_trans_handle *trans,
+				      struct btrfs_root *extent_root)
 {
-	struct btrfs_root *extent_root = btrfs_extent_root(gfs_info, 0);
 	struct btrfs_root *csum_root;
 	struct btrfs_path path;
 	struct btrfs_extent_item *ei;
@@ -9766,10 +9766,26 @@ static int fill_csum_tree_from_extent(struct btrfs_trans_handle *trans)
 static int fill_csum_tree(struct btrfs_trans_handle *trans,
 			  int search_fs_tree)
 {
+	struct btrfs_root *root;
+	struct rb_node *n;
+	int ret;
+
 	if (search_fs_tree)
 		return fill_csum_tree_from_fs(trans);
-	else
-		return fill_csum_tree_from_extent(trans);
+
+	root = btrfs_extent_root(gfs_info, 0);
+	while (1) {
+		ret = fill_csum_tree_from_extent(trans, root);
+		if (ret)
+			break;
+		n = rb_next(&root->rb_node);
+		if (!n)
+			break;
+		root = rb_entry(n, struct btrfs_root, rb_node);
+		if (root->root_key.objectid != BTRFS_EXTENT_TREE_OBJECTID)
+			break;
+	}
+	return ret;
 }
 
 static void free_roots_info_cache(void)
-- 
2.26.3


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

* [PATCH 20/20] btrfs-progs: common: search all extent roots for marking used space
  2021-11-05 20:28 [PATCH 00/20] btrfs-progs: extent tree v2 global root support prep work Josef Bacik
                   ` (18 preceding siblings ...)
  2021-11-05 20:28 ` [PATCH 19/20] btrfs-progs: check: fill csum root from all extent roots Josef Bacik
@ 2021-11-05 20:28 ` Josef Bacik
  2021-11-06  0:55 ` [PATCH 00/20] btrfs-progs: extent tree v2 global root support prep work Qu Wenruo
  20 siblings, 0 replies; 42+ messages in thread
From: Josef Bacik @ 2021-11-05 20:28 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

We could have multiple extent roots, so add a helper to mark all the
used space in the FS based on any extent roots we find, and then use
this extent io tree to fixup the block group accounting.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 common/repair.c | 142 +++++++++++++++++++++++++++++++++---------------
 common/repair.h |   2 +
 2 files changed, 100 insertions(+), 44 deletions(-)

diff --git a/common/repair.c b/common/repair.c
index c8624eaa..0feaf6c3 100644
--- a/common/repair.c
+++ b/common/repair.c
@@ -153,47 +153,27 @@ int btrfs_mark_used_tree_blocks(struct btrfs_fs_info *fs_info,
 	return ret;
 }
 
-/*
- * Fixup block accounting. The initial block accounting created by
- * make_block_groups isn't accuracy in this case.
- */
-int btrfs_fix_block_accounting(struct btrfs_trans_handle *trans)
+static int populate_used_from_extent_root(struct btrfs_root *root,
+					  struct extent_io_tree *io_tree)
 {
-	int ret = 0;
-	int slot;
-	u64 start = 0;
-	u64 bytes_used = 0;
+	struct btrfs_fs_info *fs_info = root->fs_info;
+	struct extent_buffer *leaf;
 	struct btrfs_path path;
 	struct btrfs_key key;
-	struct extent_buffer *leaf;
-	struct btrfs_block_group *cache;
-	struct btrfs_fs_info *fs_info = trans->fs_info;
-	struct btrfs_root *root = btrfs_extent_root(fs_info, 0);
-
-	ret = btrfs_run_delayed_refs(trans, -1);
-	if (ret)
-		return ret;
-
-	while(1) {
-		cache = btrfs_lookup_first_block_group(fs_info, start);
-		if (!cache)
-			break;
-
-		start = cache->start + cache->length;
-		cache->used = 0;
-		cache->space_info->bytes_used = 0;
-		if (list_empty(&cache->dirty_list))
-			list_add_tail(&cache->dirty_list, &trans->dirty_bgs);
-	}
+	int slot;
+	int ret;
 
 	btrfs_init_path(&path);
 	key.offset = 0;
 	key.objectid = 0;
 	key.type = BTRFS_EXTENT_ITEM_KEY;
-	ret = btrfs_search_slot(trans, root, &key, &path, 0, 0);
+	ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0);
 	if (ret < 0)
 		return ret;
+
 	while(1) {
+		u64 start, end;
+
 		leaf = path.nodes[0];
 		slot = path.slots[0];
 		if (slot >= btrfs_header_nritems(leaf)) {
@@ -206,23 +186,97 @@ int btrfs_fix_block_accounting(struct btrfs_trans_handle *trans)
 			slot = path.slots[0];
 		}
 		btrfs_item_key_to_cpu(leaf, &key, slot);
-		if (key.type == BTRFS_EXTENT_ITEM_KEY) {
-			bytes_used += key.offset;
-			ret = btrfs_update_block_group(trans,
-				  key.objectid, key.offset, 1, 0);
-			BUG_ON(ret);
-		} else if (key.type == BTRFS_METADATA_ITEM_KEY) {
-			bytes_used += fs_info->nodesize;
-			ret = btrfs_update_block_group(trans,
-				  key.objectid, fs_info->nodesize, 1, 0);
-			if (ret)
-				goto out;
-		}
+		start = end = key.objectid;
+		if (key.type == BTRFS_EXTENT_ITEM_KEY)
+			end = start + key.offset - 1;
+		else if (key.type == BTRFS_METADATA_ITEM_KEY)
+			end = start + fs_info->nodesize - 1;
+
+		if (start != end)
+			set_extent_dirty(io_tree, start, end);
+
 		path.slots[0]++;
 	}
-	btrfs_set_super_bytes_used(root->fs_info->super_copy, bytes_used);
+	btrfs_release_path(&path);
+	return 0;
+}
+
+int btrfs_mark_used_blocks(struct btrfs_fs_info *fs_info,
+			   struct extent_io_tree *tree)
+{
+	struct btrfs_root *root;
+	struct rb_node *n;
+	int ret;
+
+	root = btrfs_extent_root(fs_info, 0);
+	while (1) {
+		ret = populate_used_from_extent_root(root, tree);
+		if (ret)
+			break;
+		n = rb_next(&root->rb_node);
+		if (!n)
+			break;
+		root = rb_entry(n, struct btrfs_root, rb_node);
+		if (root->root_key.objectid != BTRFS_EXTENT_TREE_OBJECTID)
+			break;
+	}
+
+	return ret;
+}
+
+/*
+ * Fixup block accounting. The initial block accounting created by
+ * make_block_groups isn't accuracy in this case.
+ */
+int btrfs_fix_block_accounting(struct btrfs_trans_handle *trans)
+{
+	struct extent_io_tree used;
+	struct btrfs_fs_info *fs_info = trans->fs_info;
+	struct btrfs_block_group *cache;
+	u64 start, end;
+	u64 bytes_used = 0;
+	int ret = 0;
+
+	ret = btrfs_run_delayed_refs(trans, -1);
+	if (ret)
+		return ret;
+
+	extent_io_tree_init(&used);
+
+	ret = btrfs_mark_used_blocks(fs_info, &used);
+	if (ret)
+		goto out;
+
+	start = 0;
+	while(1) {
+		cache = btrfs_lookup_first_block_group(fs_info, start);
+		if (!cache)
+			break;
+
+		start = cache->start + cache->length;
+		cache->used = 0;
+		cache->space_info->bytes_used = 0;
+		if (list_empty(&cache->dirty_list))
+			list_add_tail(&cache->dirty_list, &trans->dirty_bgs);
+	}
+
+	start = 0;
+	while (1) {
+		ret = find_first_extent_bit(&used, 0, &start, &end,
+					    EXTENT_DIRTY);
+		if (ret)
+			break;
+
+		bytes_used += end - start + 1;
+		ret = btrfs_update_block_group(trans, start, end - start + 1,
+					       1, 0);
+		if (ret)
+			goto out;
+		clear_extent_dirty(&used, start, end);
+	}
+	btrfs_set_super_bytes_used(fs_info->super_copy, bytes_used);
 	ret = 0;
 out:
-	btrfs_release_path(&path);
+	extent_io_tree_cleanup(&used);
 	return ret;
 }
diff --git a/common/repair.h b/common/repair.h
index 793ebcd2..1b19739d 100644
--- a/common/repair.h
+++ b/common/repair.h
@@ -35,5 +35,7 @@ int btrfs_add_corrupt_extent_record(struct btrfs_fs_info *info,
 int btrfs_fix_block_accounting(struct btrfs_trans_handle *trans);
 int btrfs_mark_used_tree_blocks(struct btrfs_fs_info *fs_info,
 				struct extent_io_tree *tree);
+int btrfs_mark_used_blocks(struct btrfs_fs_info *fs_info,
+			   struct extent_io_tree *tree);
 
 #endif
-- 
2.26.3


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

* Re: [PATCH 01/20] btrfs-progs: simplify btrfs_make_block_group
  2021-11-05 20:28 ` [PATCH 01/20] btrfs-progs: simplify btrfs_make_block_group Josef Bacik
@ 2021-11-06  0:14   ` Qu Wenruo
  2021-11-08 10:13   ` Anand Jain
  1 sibling, 0 replies; 42+ messages in thread
From: Qu Wenruo @ 2021-11-06  0:14 UTC (permalink / raw)
  To: Josef Bacik, linux-btrfs, kernel-team



On 2021/11/6 04:28, Josef Bacik wrote:
> This is doing the same work as insert_block_group_item, rework it to
> call the helper instead.
>
> Signed-off-by: Josef Bacik <josef@toxicpanda.com>

Reviewed-by: Qu Wenruo <wqu@suse.com>

Thanks,
Qu
> ---
>   kernel-shared/extent-tree.c | 43 ++++++++++++++-----------------------
>   1 file changed, 16 insertions(+), 27 deletions(-)
>
> diff --git a/kernel-shared/extent-tree.c b/kernel-shared/extent-tree.c
> index 8e0614e0..a918e5aa 100644
> --- a/kernel-shared/extent-tree.c
> +++ b/kernel-shared/extent-tree.c
> @@ -2791,33 +2791,6 @@ btrfs_add_block_group(struct btrfs_fs_info *fs_info, u64 bytes_used, u64 type,
>   	return cache;
>   }
>
> -int btrfs_make_block_group(struct btrfs_trans_handle *trans,
> -			   struct btrfs_fs_info *fs_info, u64 bytes_used,
> -			   u64 type, u64 chunk_offset, u64 size)
> -{
> -	int ret;
> -	struct btrfs_root *extent_root = fs_info->extent_root;
> -	struct btrfs_block_group *cache;
> -	struct btrfs_block_group_item bgi;
> -	struct btrfs_key key;
> -
> -	cache = btrfs_add_block_group(fs_info, bytes_used, type, chunk_offset,
> -				      size);
> -	btrfs_set_stack_block_group_used(&bgi, cache->used);
> -	btrfs_set_stack_block_group_flags(&bgi, cache->flags);
> -	btrfs_set_stack_block_group_chunk_objectid(&bgi,
> -			BTRFS_FIRST_CHUNK_TREE_OBJECTID);
> -	key.objectid = cache->start;
> -	key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
> -	key.offset = cache->length;
> -	ret = btrfs_insert_item(trans, extent_root, &key, &bgi, sizeof(bgi));
> -	BUG_ON(ret);
> -
> -	add_block_group_free_space(trans, cache);
> -
> -	return 0;
> -}
> -
>   static int insert_block_group_item(struct btrfs_trans_handle *trans,
>   				   struct btrfs_block_group *block_group)
>   {
> @@ -2838,6 +2811,22 @@ static int insert_block_group_item(struct btrfs_trans_handle *trans,
>   	return btrfs_insert_item(trans, root, &key, &bgi, sizeof(bgi));
>   }
>
> +int btrfs_make_block_group(struct btrfs_trans_handle *trans,
> +			   struct btrfs_fs_info *fs_info, u64 bytes_used,
> +			   u64 type, u64 chunk_offset, u64 size)
> +{
> +	struct btrfs_block_group *cache;
> +	int ret;
> +
> +	cache = btrfs_add_block_group(fs_info, bytes_used, type, chunk_offset,
> +				      size);
> +	ret = insert_block_group_item(trans, cache);
> +	if (ret)
> +		return ret;
> +	add_block_group_free_space(trans, cache);
> +	return 0;
> +}
> +
>   /*
>    * This is for converter use only.
>    *
>

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

* Re: [PATCH 02/20] btrfs-progs: check: don't walk down non fs-trees for qgroup check
  2021-11-05 20:28 ` [PATCH 02/20] btrfs-progs: check: don't walk down non fs-trees for qgroup check Josef Bacik
@ 2021-11-06  0:14   ` Qu Wenruo
  0 siblings, 0 replies; 42+ messages in thread
From: Qu Wenruo @ 2021-11-06  0:14 UTC (permalink / raw)
  To: Josef Bacik, linux-btrfs, kernel-team



On 2021/11/6 04:28, Josef Bacik wrote:
> We will lookup implied refs for every root id for every block that we
> find when verifying qgroups, but we don't need to worry about non
> fstrees, so skip them here.
>
> Signed-off-by: Josef Bacik <josef@toxicpanda.com>

Reviewed-by: Qu Wenruo <wqu@suse.com>

Thanks,
Qu

> ---
>   check/qgroup-verify.c | 4 ++++
>   1 file changed, 4 insertions(+)
>
> diff --git a/check/qgroup-verify.c b/check/qgroup-verify.c
> index 14645c85..a514fee1 100644
> --- a/check/qgroup-verify.c
> +++ b/check/qgroup-verify.c
> @@ -765,6 +765,10 @@ static int add_refs_for_implied(struct btrfs_fs_info *info, u64 bytenr,
>   	struct btrfs_root *root;
>   	struct btrfs_key key;
>
> +	/* If this is a global tree skip it. */
> +	if (!is_fstree(root_id))
> +		return 0;
> +
>   	/* Tree reloc tree doesn't contribute qgroup, skip it */
>   	if (root_id == BTRFS_TREE_RELOC_OBJECTID)
>   		return 0;
>

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

* Re: [PATCH 04/20] btrfs-progs: add a helper for setting up a root node
  2021-11-05 20:28 ` [PATCH 04/20] btrfs-progs: add a helper for setting up a root node Josef Bacik
@ 2021-11-06  0:18   ` Qu Wenruo
  0 siblings, 0 replies; 42+ messages in thread
From: Qu Wenruo @ 2021-11-06  0:18 UTC (permalink / raw)
  To: Josef Bacik, linux-btrfs, kernel-team



On 2021/11/6 04:28, Josef Bacik wrote:
> We use this pattern in a few places, and will use it more with different
> roots in the future.  Extract out this helper to read the root nodes.
>
> Signed-off-by: Josef Bacik <josef@toxicpanda.com>
> ---
>   kernel-shared/disk-io.c | 58 +++++++++++++++++++++--------------------
>   1 file changed, 30 insertions(+), 28 deletions(-)
>
> diff --git a/kernel-shared/disk-io.c b/kernel-shared/disk-io.c
> index 3b3c4523..1f940221 100644
> --- a/kernel-shared/disk-io.c
> +++ b/kernel-shared/disk-io.c
> @@ -578,12 +578,23 @@ void btrfs_setup_root(struct btrfs_root *root, struct btrfs_fs_info *fs_info,
>   	root->root_key.objectid = objectid;
>   }
>
> +static int read_root_node(struct btrfs_fs_info *fs_info,
> +			  struct btrfs_root *root, u64 bytenr, u64 gen)

Can we add "int level" to bring proper level check for this function and
read_tree_block()?

Thanks,
Qu

> +{
> +	root->node = read_tree_block(fs_info, bytenr, gen); > +	if (!extent_buffer_uptodate(root->node)) {
> +		free_extent_buffer(root->node);
> +		root->node = NULL;
> +		return -EIO;
> +	}
> +	return 0;
> +}
> +
>   static int find_and_setup_root(struct btrfs_root *tree_root,
>   			       struct btrfs_fs_info *fs_info,
>   			       u64 objectid, struct btrfs_root *root)
>   {
>   	int ret;
> -	u64 generation;
>
>   	btrfs_setup_root(root, fs_info, objectid);
>   	ret = btrfs_find_last_root(tree_root, objectid,
> @@ -591,13 +602,9 @@ static int find_and_setup_root(struct btrfs_root *tree_root,
>   	if (ret)
>   		return ret;
>
> -	generation = btrfs_root_generation(&root->root_item);
> -	root->node = read_tree_block(fs_info,
> -			btrfs_root_bytenr(&root->root_item), generation);
> -	if (!extent_buffer_uptodate(root->node))
> -		return -EIO;
> -
> -	return 0;
> +	return read_root_node(fs_info, root,
> +			      btrfs_root_bytenr(&root->root_item),
> +			      btrfs_root_generation(&root->root_item));
>   }
>
>   static int find_and_setup_log_root(struct btrfs_root *tree_root,
> @@ -606,6 +613,7 @@ static int find_and_setup_log_root(struct btrfs_root *tree_root,
>   {
>   	u64 blocknr = btrfs_super_log_root(disk_super);
>   	struct btrfs_root *log_root = malloc(sizeof(struct btrfs_root));
> +	int ret;
>
>   	if (!log_root)
>   		return -ENOMEM;
> @@ -615,20 +623,15 @@ static int find_and_setup_log_root(struct btrfs_root *tree_root,
>   		return 0;
>   	}
>
> -	btrfs_setup_root(log_root, fs_info,
> -			 BTRFS_TREE_LOG_OBJECTID);
> -
> -	log_root->node = read_tree_block(fs_info, blocknr,
> -				     btrfs_super_generation(disk_super) + 1);
> -
> -	fs_info->log_root_tree = log_root;
> -
> -	if (!extent_buffer_uptodate(log_root->node)) {
> -		free_extent_buffer(log_root->node);
> +	btrfs_setup_root(log_root, fs_info, BTRFS_TREE_LOG_OBJECTID);
> +	ret = read_root_node(fs_info, log_root, blocknr,
> +			     btrfs_super_generation(disk_super) + 1);
> +	if (ret) {
>   		free(log_root);
>   		fs_info->log_root_tree = NULL;
> -		return -EIO;
> +		return ret;
>   	}
> +	fs_info->log_root_tree = log_root;
>
>   	return 0;
>   }
> @@ -704,9 +707,9 @@ out:
>   		return ERR_PTR(ret);
>   	}
>   	generation = btrfs_root_generation(&root->root_item);
> -	root->node = read_tree_block(fs_info,
> -			btrfs_root_bytenr(&root->root_item), generation);
> -	if (!extent_buffer_uptodate(root->node)) {
> +	ret = read_root_node(fs_info, root,
> +			     btrfs_root_bytenr(&root->root_item), generation);
> +	if (ret) {
>   		free(root);
>   		return ERR_PTR(-EIO);
>   	}
> @@ -970,8 +973,8 @@ int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info, u64 root_tree_bytenr,
>   		generation = btrfs_backup_tree_root_gen(backup);
>   	}
>
> -	root->node = read_tree_block(fs_info, root_tree_bytenr, generation);
> -	if (!extent_buffer_uptodate(root->node)) {
> +	ret = read_root_node(fs_info, root, root_tree_bytenr, generation);
> +	if (ret) {
>   		fprintf(stderr, "Couldn't read tree root\n");
>   		return -EIO;
>   	}
> @@ -1179,10 +1182,9 @@ int btrfs_setup_chunk_tree_and_device_map(struct btrfs_fs_info *fs_info,
>   	else
>   		generation = 0;
>
> -	fs_info->chunk_root->node = read_tree_block(fs_info,
> -						    chunk_root_bytenr,
> -						    generation);
> -	if (!extent_buffer_uptodate(fs_info->chunk_root->node)) {
> +	ret = read_root_node(fs_info, fs_info->chunk_root, chunk_root_bytenr,
> +			     generation);
> +	if (ret) {
>   		if (fs_info->ignore_chunk_tree_error) {
>   			warning("cannot read chunk root, continue anyway");
>   			fs_info->chunk_root = NULL;
>

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

* Re: [PATCH 05/20] btrfs-progs: btrfs-shared: stop passing root to csum related functions
  2021-11-05 20:28 ` [PATCH 05/20] btrfs-progs: btrfs-shared: stop passing root to csum related functions Josef Bacik
@ 2021-11-06  0:20   ` Qu Wenruo
  0 siblings, 0 replies; 42+ messages in thread
From: Qu Wenruo @ 2021-11-06  0:20 UTC (permalink / raw)
  To: Josef Bacik, linux-btrfs, kernel-team



On 2021/11/6 04:28, Josef Bacik wrote:
> We are going to need to start looking up the csum root based on the
> bytenr with extent tree v2.  To that end stop passing the root to the
> csum related functions so that can be done in the helper functions
> themselves.
>
> There's an unrelated deletion of a function prototype that no longer
> exists, if desired I can break that out from this patch.
>
> Signed-off-by: Josef Bacik <josef@toxicpanda.com>

Yeah, any global available tree should not be in the parameter list, as
that would only provide a chance for caller to pass wrong root in.

Reviewed-by: Qu Wenruo <wqu@suse.com>

Thanks,
Qu
> ---
>   check/main.c              | 4 ++--
>   convert/main.c            | 1 -
>   kernel-shared/ctree.h     | 6 +-----
>   kernel-shared/file-item.c | 4 ++--
>   mkfs/rootdir.c            | 2 +-
>   5 files changed, 6 insertions(+), 11 deletions(-)
>
> diff --git a/check/main.c b/check/main.c
> index 235a9bab..08810c5f 100644
> --- a/check/main.c
> +++ b/check/main.c
> @@ -9484,8 +9484,8 @@ static int populate_csum(struct btrfs_trans_handle *trans,
>   				       &sectorsize, 0);
>   		if (ret)
>   			break;
> -		ret = btrfs_csum_file_block(trans, csum_root, start + len,
> -					    start + offset, buf, sectorsize);
> +		ret = btrfs_csum_file_block(trans, start + len, start + offset,
> +					    buf, sectorsize);
>   		if (ret)
>   			break;
>   		offset += sectorsize;
> diff --git a/convert/main.c b/convert/main.c
> index 223eebad..7f33d4e1 100644
> --- a/convert/main.c
> +++ b/convert/main.c
> @@ -187,7 +187,6 @@ static int csum_disk_extent(struct btrfs_trans_handle *trans,
>   		if (ret)
>   			break;
>   		ret = btrfs_csum_file_block(trans,
> -					    root->fs_info->csum_root,
>   					    disk_bytenr + num_bytes,
>   					    disk_bytenr + offset,
>   					    buffer, blocksize);
> diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h
> index 3c0743cc..73904255 100644
> --- a/kernel-shared/ctree.h
> +++ b/kernel-shared/ctree.h
> @@ -2847,12 +2847,8 @@ int btrfs_insert_file_extent(struct btrfs_trans_handle *trans,
>   int btrfs_insert_inline_extent(struct btrfs_trans_handle *trans,
>   				struct btrfs_root *root, u64 objectid,
>   				u64 offset, const char *buffer, size_t size);
> -int btrfs_csum_file_block(struct btrfs_trans_handle *trans,
> -			  struct btrfs_root *root, u64 alloc_end,
> +int btrfs_csum_file_block(struct btrfs_trans_handle *trans, u64 alloc_end,
>   			  u64 bytenr, char *data, size_t len);
> -int btrfs_csum_truncate(struct btrfs_trans_handle *trans,
> -			struct btrfs_root *root, struct btrfs_path *path,
> -			u64 isize);
>
>   /* uuid-tree.c, interface for mounted mounted filesystem */
>   int btrfs_lookup_uuid_subvol_item(int fd, const u8 *uuid, u64 *subvol_id);
> diff --git a/kernel-shared/file-item.c b/kernel-shared/file-item.c
> index c910e27e..5bf6aab4 100644
> --- a/kernel-shared/file-item.c
> +++ b/kernel-shared/file-item.c
> @@ -183,9 +183,9 @@ fail:
>   }
>
>   int btrfs_csum_file_block(struct btrfs_trans_handle *trans,
> -			  struct btrfs_root *root, u64 alloc_end,
> -			  u64 bytenr, char *data, size_t len)
> +			  u64 alloc_end, u64 bytenr, char *data, size_t len)
>   {
> +	struct btrfs_root *root = trans->fs_info->csum_root;
>   	int ret = 0;
>   	struct btrfs_key file_key;
>   	struct btrfs_key found_key;
> diff --git a/mkfs/rootdir.c b/mkfs/rootdir.c
> index 16ff257a..92be32ea 100644
> --- a/mkfs/rootdir.c
> +++ b/mkfs/rootdir.c
> @@ -403,7 +403,7 @@ again:
>   		 * we're doing the csum before we record the extent, but
>   		 * that's ok
>   		 */
> -		ret = btrfs_csum_file_block(trans, root->fs_info->csum_root,
> +		ret = btrfs_csum_file_block(trans,
>   				first_block + bytes_read + sectorsize,
>   				first_block + bytes_read,
>   				eb->data, sectorsize);
>

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

* Re: [PATCH 06/20] btrfs-progs: check: stop passing csum root around
  2021-11-05 20:28 ` [PATCH 06/20] btrfs-progs: check: stop passing csum root around Josef Bacik
@ 2021-11-06  0:21   ` Qu Wenruo
  0 siblings, 0 replies; 42+ messages in thread
From: Qu Wenruo @ 2021-11-06  0:21 UTC (permalink / raw)
  To: Josef Bacik, linux-btrfs, kernel-team



On 2021/11/6 04:28, Josef Bacik wrote:
> We pass the csum root from way high in the call chain in check down to
> where we actually need it.  However we can just get it from the fs_info
> in these places, so clean up the functions to skip passing around the
> csum root needlessly.
>
> Signed-off-by: Josef Bacik <josef@toxicpanda.com>

Reviewed-by: Qu Wenruo <wqu@suse.com>

Thanks,
Qu

> ---
>   check/main.c | 22 +++++++++-------------
>   1 file changed, 9 insertions(+), 13 deletions(-)
>
> diff --git a/check/main.c b/check/main.c
> index 08810c5f..22306cf4 100644
> --- a/check/main.c
> +++ b/check/main.c
> @@ -9494,9 +9494,9 @@ static int populate_csum(struct btrfs_trans_handle *trans,
>   }
>
>   static int fill_csum_tree_from_one_fs_root(struct btrfs_trans_handle *trans,
> -				      struct btrfs_root *csum_root,
> -				      struct btrfs_root *cur_root)
> +					   struct btrfs_root *cur_root)
>   {
> +	struct btrfs_root *csum_root = gfs_info->csum_root;
>   	struct btrfs_path path;
>   	struct btrfs_key key;
>   	struct extent_buffer *node;
> @@ -9557,8 +9557,7 @@ out:
>   	return ret;
>   }
>
> -static int fill_csum_tree_from_fs(struct btrfs_trans_handle *trans,
> -				  struct btrfs_root *csum_root)
> +static int fill_csum_tree_from_fs(struct btrfs_trans_handle *trans)
>   {
>   	struct btrfs_path path;
>   	struct btrfs_root *tree_root = gfs_info->tree_root;
> @@ -9598,8 +9597,7 @@ static int fill_csum_tree_from_fs(struct btrfs_trans_handle *trans,
>   				key.objectid);
>   			goto out;
>   		}
> -		ret = fill_csum_tree_from_one_fs_root(trans, csum_root,
> -				cur_root);
> +		ret = fill_csum_tree_from_one_fs_root(trans, cur_root);
>   		if (ret < 0)
>   			goto out;
>   next:
> @@ -9617,10 +9615,10 @@ out:
>   	return ret;
>   }
>
> -static int fill_csum_tree_from_extent(struct btrfs_trans_handle *trans,
> -				      struct btrfs_root *csum_root)
> +static int fill_csum_tree_from_extent(struct btrfs_trans_handle *trans)
>   {
>   	struct btrfs_root *extent_root = gfs_info->extent_root;
> +	struct btrfs_root *csum_root = gfs_info->csum_root;
>   	struct btrfs_path path;
>   	struct btrfs_extent_item *ei;
>   	struct extent_buffer *leaf;
> @@ -9690,13 +9688,12 @@ static int fill_csum_tree_from_extent(struct btrfs_trans_handle *trans,
>    * will use fs/subvol trees to init the csum tree.
>    */
>   static int fill_csum_tree(struct btrfs_trans_handle *trans,
> -			  struct btrfs_root *csum_root,
>   			  int search_fs_tree)
>   {
>   	if (search_fs_tree)
> -		return fill_csum_tree_from_fs(trans, csum_root);
> +		return fill_csum_tree_from_fs(trans);
>   	else
> -		return fill_csum_tree_from_extent(trans, csum_root);
> +		return fill_csum_tree_from_extent(trans);
>   }
>
>   static void free_roots_info_cache(void)
> @@ -10700,8 +10697,7 @@ static int cmd_check(const struct cmd_struct *cmd, int argc, char **argv)
>   				goto close_out;
>   			}
>
> -			ret = fill_csum_tree(trans, gfs_info->csum_root,
> -					     init_extent_tree);
> +			ret = fill_csum_tree(trans, init_extent_tree);
>   			err |= !!ret;
>   			if (ret) {
>   				error("checksum tree refilling failed: %d", ret);
>

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

* Re: [PATCH 07/20] btrfs-progs: stop accessing ->csum_root directly
  2021-11-05 20:28 ` [PATCH 07/20] btrfs-progs: stop accessing ->csum_root directly Josef Bacik
@ 2021-11-06  0:23   ` Qu Wenruo
  2021-11-08 19:19     ` Josef Bacik
  0 siblings, 1 reply; 42+ messages in thread
From: Qu Wenruo @ 2021-11-06  0:23 UTC (permalink / raw)
  To: Josef Bacik, linux-btrfs, kernel-team



On 2021/11/6 04:28, Josef Bacik wrote:
> With extent tree v2 we will have per-block group checksums,

I guess you mean per block group checksum tree?

> so add a
> helper to access the csum root and rename the fs_info csum_root to
> _csum_root to catch all the places that are accessing it directly.
> Convert everybody to use the helper except for internal things.
>
> Signed-off-by: Josef Bacik <josef@toxicpanda.com>

Currently a lot of locations are still passing 0 to btrfs_csum_root(),
which would need to be converted later.

Thus it doesn't look correct to be in the preparation patchset.

Mind to move this patch into the real extent-tree-v2 patchset?

Thanks,
Qu

> ---
>   btrfs-corrupt-block.c       |  2 +-
>   check/main.c                | 15 ++++++++++-----
>   check/mode-common.c         |  6 +++---
>   cmds/rescue-chunk-recover.c | 17 ++++++++---------
>   kernel-shared/ctree.h       |  2 +-
>   kernel-shared/disk-io.c     | 28 +++++++++++++++++-----------
>   kernel-shared/disk-io.h     |  2 +-
>   kernel-shared/file-item.c   |  4 ++--
>   mkfs/main.c                 |  3 ++-
>   9 files changed, 45 insertions(+), 34 deletions(-)
>
> diff --git a/btrfs-corrupt-block.c b/btrfs-corrupt-block.c
> index c1624ee1..d7904b6f 100644
> --- a/btrfs-corrupt-block.c
> +++ b/btrfs-corrupt-block.c
> @@ -1031,7 +1031,7 @@ static int delete_csum(struct btrfs_root *root, u64 bytenr, u64 bytes)
>   	struct btrfs_trans_handle *trans;
>   	int ret;
>
> -	root = root->fs_info->csum_root;
> +	root = btrfs_csum_root(root->fs_info, bytenr);
>   	trans = btrfs_start_transaction(root, 1);
>   	if (IS_ERR(trans)) {
>   		fprintf(stderr, "Couldn't start transaction %ld\n",
> diff --git a/check/main.c b/check/main.c
> index 22306cf4..632dfba0 100644
> --- a/check/main.c
> +++ b/check/main.c
> @@ -5988,7 +5988,7 @@ static int check_csums(struct btrfs_root *root)
>   	unsigned long leaf_offset;
>   	bool verify_csum = !!check_data_csum;
>
> -	root = gfs_info->csum_root;
> +	root = btrfs_csum_root(gfs_info, 0);
>   	if (!extent_buffer_uptodate(root->node)) {
>   		fprintf(stderr, "No valid csum tree found\n");
>   		return -ENOENT;
> @@ -9496,7 +9496,7 @@ static int populate_csum(struct btrfs_trans_handle *trans,
>   static int fill_csum_tree_from_one_fs_root(struct btrfs_trans_handle *trans,
>   					   struct btrfs_root *cur_root)
>   {
> -	struct btrfs_root *csum_root = gfs_info->csum_root;
> +	struct btrfs_root *csum_root;
>   	struct btrfs_path path;
>   	struct btrfs_key key;
>   	struct extent_buffer *node;
> @@ -9532,6 +9532,7 @@ static int fill_csum_tree_from_one_fs_root(struct btrfs_trans_handle *trans,
>   		start = btrfs_file_extent_disk_bytenr(node, fi);
>   		len = btrfs_file_extent_disk_num_bytes(node, fi);
>
> +		csum_root = btrfs_csum_root(gfs_info, start);
>   		ret = populate_csum(trans, csum_root, buf, start, len);
>   		if (ret == -EEXIST)
>   			ret = 0;
> @@ -9618,7 +9619,7 @@ out:
>   static int fill_csum_tree_from_extent(struct btrfs_trans_handle *trans)
>   {
>   	struct btrfs_root *extent_root = gfs_info->extent_root;
> -	struct btrfs_root *csum_root = gfs_info->csum_root;
> +	struct btrfs_root *csum_root;
>   	struct btrfs_path path;
>   	struct btrfs_extent_item *ei;
>   	struct extent_buffer *leaf;
> @@ -9668,6 +9669,7 @@ static int fill_csum_tree_from_extent(struct btrfs_trans_handle *trans)
>   			continue;
>   		}
>
> +		csum_root = btrfs_csum_root(gfs_info, key.objectid);
>   		ret = populate_csum(trans, csum_root, buf, key.objectid,
>   				    key.offset);
>   		if (ret)
> @@ -10688,7 +10690,8 @@ static int cmd_check(const struct cmd_struct *cmd, int argc, char **argv)
>
>   		if (init_csum_tree) {
>   			printf("Reinitialize checksum tree\n");
> -			ret = btrfs_fsck_reinit_root(trans, gfs_info->csum_root);
> +			ret = btrfs_fsck_reinit_root(trans,
> +						btrfs_csum_root(gfs_info, 0));
>   			if (ret) {
>   				error("checksum tree initialization failed: %d",
>   						ret);
> @@ -10719,7 +10722,9 @@ static int cmd_check(const struct cmd_struct *cmd, int argc, char **argv)
>   		err |= !!ret;
>   		goto close_out;
>   	}
> -	if (!extent_buffer_uptodate(gfs_info->csum_root->node)) {
> +
> +	root = btrfs_csum_root(gfs_info, 0);
> +	if (!extent_buffer_uptodate(root->node)) {
>   		error("critical: csum_root, unable to check the filesystem");
>   		ret = -EIO;
>   		err |= !!ret;
> diff --git a/check/mode-common.c b/check/mode-common.c
> index 0059672c..0c3bd38b 100644
> --- a/check/mode-common.c
> +++ b/check/mode-common.c
> @@ -287,6 +287,7 @@ out:
>    */
>   int count_csum_range(u64 start, u64 len, u64 *found)
>   {
> +	struct btrfs_root *csum_root = btrfs_csum_root(gfs_info, start);
>   	struct btrfs_key key;
>   	struct btrfs_path path;
>   	struct extent_buffer *leaf;
> @@ -302,8 +303,7 @@ int count_csum_range(u64 start, u64 len, u64 *found)
>   	key.offset = start;
>   	key.type = BTRFS_EXTENT_CSUM_KEY;
>
> -	ret = btrfs_search_slot(NULL, gfs_info->csum_root,
> -				&key, &path, 0, 0);
> +	ret = btrfs_search_slot(NULL, csum_root, &key, &path, 0, 0);
>   	if (ret < 0)
>   		goto out;
>   	if (ret > 0 && path.slots[0] > 0) {
> @@ -317,7 +317,7 @@ int count_csum_range(u64 start, u64 len, u64 *found)
>   	while (len > 0) {
>   		leaf = path.nodes[0];
>   		if (path.slots[0] >= btrfs_header_nritems(leaf)) {
> -			ret = btrfs_next_leaf(gfs_info->csum_root, &path);
> +			ret = btrfs_next_leaf(csum_root, &path);
>   			if (ret > 0)
>   				break;
>   			else if (ret < 0)
> diff --git a/cmds/rescue-chunk-recover.c b/cmds/rescue-chunk-recover.c
> index 03c7f48f..115d91d7 100644
> --- a/cmds/rescue-chunk-recover.c
> +++ b/cmds/rescue-chunk-recover.c
> @@ -1801,7 +1801,7 @@ static int btrfs_rebuild_chunk_stripes(struct recover_control *rc,
>   	return ret;
>   }
>
> -static int next_csum(struct btrfs_root *root,
> +static int next_csum(struct btrfs_root *csum_root,
>   		     struct extent_buffer **leaf,
>   		     struct btrfs_path *path,
>   		     int *slot,
> @@ -1811,10 +1811,9 @@ static int next_csum(struct btrfs_root *root,
>   		     struct btrfs_key *key)
>   {
>   	int ret = 0;
> -	struct btrfs_root *csum_root = root->fs_info->csum_root;
>   	struct btrfs_csum_item *csum_item;
> -	u32 blocksize = root->fs_info->sectorsize;
> -	u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
> +	u32 blocksize = csum_root->fs_info->sectorsize;
> +	u16 csum_size = btrfs_super_csum_size(csum_root->fs_info->super_copy);
>   	int csums_in_item = btrfs_item_size_nr(*leaf, *slot) / csum_size;
>
>   	if (*csum_offset >= csums_in_item) {
> @@ -1994,7 +1993,6 @@ static int rebuild_raid_data_chunk_stripes(struct recover_control *rc,
>   	LIST_HEAD(unordered);
>   	LIST_HEAD(candidates);
>
> -	csum_root = root->fs_info->csum_root;
>   	btrfs_init_path(&path);
>   	list_splice_init(&chunk->dextents, &candidates);
>   again:
> @@ -2005,6 +2003,7 @@ again:
>   	key.type = BTRFS_EXTENT_CSUM_KEY;
>   	key.offset = start;
>
> +	csum_root = btrfs_csum_root(root->fs_info, start);
>   	ret = btrfs_search_slot(NULL, csum_root, &key, &path, 0, 0);
>   	if (ret < 0) {
>   		fprintf(stderr, "Search csum failed(%d)\n", ret);
> @@ -2022,8 +2021,8 @@ again:
>   			} else if (ret > 0) {
>   				slot = btrfs_header_nritems(leaf) - 1;
>   				btrfs_item_key_to_cpu(leaf, &key, slot);
> -				if (item_end_offset(root, &key, leaf, slot)
> -								> start) {
> +				if (item_end_offset(csum_root, &key,
> +						    leaf, slot) > start) {
>   					csum_offset = start - key.offset;
>   					csum_offset /= blocksize;
>   					goto next_csum;
> @@ -2061,8 +2060,8 @@ again:
>   			goto out;
>   	}
>   next_csum:
> -	ret = next_csum(root, &leaf, &path, &slot, &csum_offset, &tree_csum,
> -			end, &key);
> +	ret = next_csum(csum_root, &leaf, &path, &slot, &csum_offset,
> +			&tree_csum, end, &key);
>   	if (ret < 0) {
>   		fprintf(stderr, "Fetch csum failed\n");
>   		goto fail_out;
> diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h
> index 73904255..d2d1a006 100644
> --- a/kernel-shared/ctree.h
> +++ b/kernel-shared/ctree.h
> @@ -1161,7 +1161,7 @@ struct btrfs_fs_info {
>   	struct btrfs_root *tree_root;
>   	struct btrfs_root *chunk_root;
>   	struct btrfs_root *dev_root;
> -	struct btrfs_root *csum_root;
> +	struct btrfs_root *_csum_root;
>   	struct btrfs_root *quota_root;
>   	struct btrfs_root *free_space_root;
>   	struct btrfs_root *uuid_root;
> diff --git a/kernel-shared/disk-io.c b/kernel-shared/disk-io.c
> index 1f940221..c1d55692 100644
> --- a/kernel-shared/disk-io.c
> +++ b/kernel-shared/disk-io.c
> @@ -744,6 +744,12 @@ int btrfs_fs_roots_compare_roots(struct rb_node *node1, struct rb_node *node2)
>   	return btrfs_fs_roots_compare_objectids(node1, (void *)&root->objectid);
>   }
>
> +struct btrfs_root *btrfs_csum_root(struct btrfs_fs_info *fs_info,
> +				   u64 bytenr)
> +{
> +	return fs_info->_csum_root;
> +}
> +
>   struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
>   				      struct btrfs_key *location)
>   {
> @@ -761,7 +767,7 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
>   	if (location->objectid == BTRFS_DEV_TREE_OBJECTID)
>   		return fs_info->dev_root;
>   	if (location->objectid == BTRFS_CSUM_TREE_OBJECTID)
> -		return fs_info->csum_root;
> +		return btrfs_csum_root(fs_info, location->offset);
>   	if (location->objectid == BTRFS_UUID_TREE_OBJECTID)
>   		return fs_info->uuid_root ? fs_info->uuid_root : ERR_PTR(-ENOENT);
>   	if (location->objectid == BTRFS_QUOTA_TREE_OBJECTID)
> @@ -797,7 +803,7 @@ void btrfs_free_fs_info(struct btrfs_fs_info *fs_info)
>   	free(fs_info->extent_root);
>   	free(fs_info->chunk_root);
>   	free(fs_info->dev_root);
> -	free(fs_info->csum_root);
> +	free(fs_info->_csum_root);
>   	free(fs_info->free_space_root);
>   	free(fs_info->uuid_root);
>   	free(fs_info->super_copy);
> @@ -817,7 +823,7 @@ struct btrfs_fs_info *btrfs_new_fs_info(int writable, u64 sb_bytenr)
>   	fs_info->extent_root = calloc(1, sizeof(struct btrfs_root));
>   	fs_info->chunk_root = calloc(1, sizeof(struct btrfs_root));
>   	fs_info->dev_root = calloc(1, sizeof(struct btrfs_root));
> -	fs_info->csum_root = calloc(1, sizeof(struct btrfs_root));
> +	fs_info->_csum_root = calloc(1, sizeof(struct btrfs_root));
>   	fs_info->quota_root = calloc(1, sizeof(struct btrfs_root));
>   	fs_info->free_space_root = calloc(1, sizeof(struct btrfs_root));
>   	fs_info->uuid_root = calloc(1, sizeof(struct btrfs_root));
> @@ -825,7 +831,7 @@ struct btrfs_fs_info *btrfs_new_fs_info(int writable, u64 sb_bytenr)
>
>   	if (!fs_info->tree_root || !fs_info->extent_root ||
>   	    !fs_info->chunk_root || !fs_info->dev_root ||
> -	    !fs_info->csum_root || !fs_info->quota_root ||
> +	    !fs_info->_csum_root || !fs_info->quota_root ||
>   	    !fs_info->free_space_root || !fs_info->uuid_root ||
>   	    !fs_info->super_copy)
>   		goto free_all;
> @@ -993,11 +999,11 @@ int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info, u64 root_tree_bytenr,
>   	}
>   	fs_info->dev_root->track_dirty = 1;
>
> -	ret = setup_root_or_create_block(fs_info, flags, fs_info->csum_root,
> +	ret = setup_root_or_create_block(fs_info, flags, fs_info->_csum_root,
>   					 BTRFS_CSUM_TREE_OBJECTID, "csum");
>   	if (ret)
>   		return ret;
> -	fs_info->csum_root->track_dirty = 1;
> +	fs_info->_csum_root->track_dirty = 1;
>
>   	ret = find_and_setup_root(root, fs_info, BTRFS_UUID_TREE_OBJECTID,
>   				  fs_info->uuid_root);
> @@ -1072,8 +1078,8 @@ void btrfs_release_all_roots(struct btrfs_fs_info *fs_info)
>   		free_extent_buffer(fs_info->free_space_root->node);
>   	if (fs_info->quota_root)
>   		free_extent_buffer(fs_info->quota_root->node);
> -	if (fs_info->csum_root)
> -		free_extent_buffer(fs_info->csum_root->node);
> +	if (fs_info->_csum_root)
> +		free_extent_buffer(fs_info->_csum_root->node);
>   	if (fs_info->dev_root)
>   		free_extent_buffer(fs_info->dev_root->node);
>   	if (fs_info->extent_root)
> @@ -1854,11 +1860,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, info->_csum_root->node->start);
>   	btrfs_set_backup_csum_root_gen(root_backup,
> -			       btrfs_header_generation(info->csum_root->node));
> +			       btrfs_header_generation(info->_csum_root->node));
>   	btrfs_set_backup_csum_root_level(root_backup,
> -			       btrfs_header_level(info->csum_root->node));
> +			       btrfs_header_level(info->_csum_root->node));
>
>   	btrfs_set_backup_total_bytes(root_backup,
>   			     btrfs_super_total_bytes(info->super_copy));
> diff --git a/kernel-shared/disk-io.h b/kernel-shared/disk-io.h
> index e113d842..38abbca5 100644
> --- a/kernel-shared/disk-io.h
> +++ b/kernel-shared/disk-io.h
> @@ -217,5 +217,5 @@ int btrfs_fs_roots_compare_roots(struct rb_node *node1, struct rb_node *node2);
>   struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans,
>   				     struct btrfs_fs_info *fs_info,
>   				     u64 objectid);
> -
> +struct btrfs_root *btrfs_csum_root(struct btrfs_fs_info *fs_info, u64 bytenr);
>   #endif
> diff --git a/kernel-shared/file-item.c b/kernel-shared/file-item.c
> index 5bf6aab4..12932e1d 100644
> --- a/kernel-shared/file-item.c
> +++ b/kernel-shared/file-item.c
> @@ -185,7 +185,7 @@ fail:
>   int btrfs_csum_file_block(struct btrfs_trans_handle *trans,
>   			  u64 alloc_end, u64 bytenr, char *data, size_t len)
>   {
> -	struct btrfs_root *root = trans->fs_info->csum_root;
> +	struct btrfs_root *root = btrfs_csum_root(trans->fs_info, bytenr);
>   	int ret = 0;
>   	struct btrfs_key file_key;
>   	struct btrfs_key found_key;
> @@ -401,7 +401,7 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans, u64 bytenr, u64 len)
>   	int ret;
>   	u16 csum_size = btrfs_super_csum_size(trans->fs_info->super_copy);
>   	int blocksize = trans->fs_info->sectorsize;
> -	struct btrfs_root *csum_root = trans->fs_info->csum_root;
> +	struct btrfs_root *csum_root = btrfs_csum_root(trans->fs_info, bytenr);
>
>
>   	path = btrfs_alloc_path();
> diff --git a/mkfs/main.c b/mkfs/main.c
> index ce86a0db..c6cc51e9 100644
> --- a/mkfs/main.c
> +++ b/mkfs/main.c
> @@ -268,6 +268,7 @@ static int recow_roots(struct btrfs_trans_handle *trans,
>   		       struct btrfs_root *root)
>   {
>   	struct btrfs_fs_info *info = root->fs_info;
> +	struct btrfs_root *csum_root = btrfs_csum_root(info, 0);
>   	int ret;
>
>   	ret = __recow_root(trans, info->fs_root);
> @@ -285,7 +286,7 @@ static int recow_roots(struct btrfs_trans_handle *trans,
>   	ret = __recow_root(trans, info->dev_root);
>   	if (ret)
>   		return ret;
> -	ret = __recow_root(trans, info->csum_root);
> +	ret = __recow_root(trans, csum_root);
>   	if (ret)
>   		return ret;
>   	if (info->free_space_root) {
>

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

* Re: [PATCH 08/20] btrfs-progs: image: keep track of seen blocks when walking trees
  2021-11-05 20:28 ` [PATCH 08/20] btrfs-progs: image: keep track of seen blocks when walking trees Josef Bacik
@ 2021-11-06  0:26   ` Qu Wenruo
  0 siblings, 0 replies; 42+ messages in thread
From: Qu Wenruo @ 2021-11-06  0:26 UTC (permalink / raw)
  To: Josef Bacik, linux-btrfs, kernel-team



On 2021/11/6 04:28, Josef Bacik wrote:
> Extent tree v2 no longer tracks all allocated blocks on the file system,
> so we'll have to default to walking trees to generate metadata images.
> There's an annoying drawback with walking trees with btrfs-image where
> we'll happily copy multiple blocks over and over again if there are
> snapshots.  Fix this by keeping track of blocks we've seen and simply
> skipping blocks that we've already queued up for copying.
>
> Signed-off-by: Josef Bacik <josef@toxicpanda.com>

It looks to me, as long as the misc-tests ran fine.

Reviewed-by: Qu Wenruo <wqu@suse.com>

Thanks,
Qu
> ---
>   image/main.c | 12 ++++++++++++
>   1 file changed, 12 insertions(+)
>
> diff --git a/image/main.c b/image/main.c
> index dbce17e7..57e0cb6c 100644
> --- a/image/main.c
> +++ b/image/main.c
> @@ -93,6 +93,8 @@ struct metadump_struct {
>   	pthread_cond_t cond;
>   	struct rb_root name_tree;
>
> +	struct extent_io_tree seen;
> +
>   	struct list_head list;
>   	struct list_head ordered;
>   	size_t num_items;
> @@ -461,6 +463,7 @@ static void metadump_destroy(struct metadump_struct *md, int num_threads)
>   		free(name->sub);
>   		free(name);
>   	}
> +	extent_io_tree_cleanup(&md->seen);
>   }
>
>   static int metadump_init(struct metadump_struct *md, struct btrfs_root *root,
> @@ -476,6 +479,7 @@ static int metadump_init(struct metadump_struct *md, struct btrfs_root *root,
>   	memset(md, 0, sizeof(*md));
>   	INIT_LIST_HEAD(&md->list);
>   	INIT_LIST_HEAD(&md->ordered);
> +	extent_io_tree_init(&md->seen);
>   	md->root = root;
>   	md->out = out;
>   	md->pending_start = (u64)-1;
> @@ -771,6 +775,14 @@ static int copy_tree_blocks(struct btrfs_root *root, struct extent_buffer *eb,
>   	int i = 0;
>   	int ret;
>
> +	bytenr = btrfs_header_bytenr(eb);
> +	if (test_range_bit(&metadump->seen, bytenr,
> +			   bytenr + fs_info->nodesize - 1, EXTENT_DIRTY, 1))
> +		return 0;
> +
> +	set_extent_dirty(&metadump->seen, bytenr,
> +			 bytenr + fs_info->nodesize - 1);
> +
>   	ret = add_extent(btrfs_header_bytenr(eb), fs_info->nodesize,
>   			 metadump, 0);
>   	if (ret) {
>

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

* Re: [PATCH 09/20] btrfs-progs: common: move btrfs_fix_block_accounting to repair.c
  2021-11-05 20:28 ` [PATCH 09/20] btrfs-progs: common: move btrfs_fix_block_accounting to repair.c Josef Bacik
@ 2021-11-06  0:30   ` Qu Wenruo
  0 siblings, 0 replies; 42+ messages in thread
From: Qu Wenruo @ 2021-11-06  0:30 UTC (permalink / raw)
  To: Josef Bacik, linux-btrfs, kernel-team



On 2021/11/6 04:28, Josef Bacik wrote:
> We have this helper sitting in extent-tree.c, but it's a repair
> function.  I'm going to need to make changes to this for extent-tree-v2
> and would rather this live outside of the code we need to share with the
> kernel.
>
> Signed-off-by: Josef Bacik <josef@toxicpanda.com>

A quick grep shows convert/main.c is also using this function.

But I didn't see convert/main.c including repair.h nor its .o.d shows
the header.

Is there anything missing or did I miss something?

Thanks,
Qu

> ---
>   common/repair.c             | 75 +++++++++++++++++++++++++++++++++++++
>   common/repair.h             |  1 +
>   kernel-shared/extent-tree.c | 74 ------------------------------------
>   3 files changed, 76 insertions(+), 74 deletions(-)
>
> diff --git a/common/repair.c b/common/repair.c
> index 6eed7cec..a5ba43e2 100644
> --- a/common/repair.c
> +++ b/common/repair.c
> @@ -17,6 +17,7 @@
>    */
>
>   #include "kernel-shared/ctree.h"
> +#include "kernel-shared/transaction.h"
>   #include "common/extent-cache.h"
>   #include "common/utils.h"
>   #include "common/repair.h"
> @@ -50,3 +51,77 @@ int btrfs_add_corrupt_extent_record(struct btrfs_fs_info *info,
>   	return ret;
>   }
>
> +/*
> + * Fixup block accounting. The initial block accounting created by
> + * make_block_groups isn't accuracy in this case.
> + */
> +int btrfs_fix_block_accounting(struct btrfs_trans_handle *trans)
> +{
> +	int ret = 0;
> +	int slot;
> +	u64 start = 0;
> +	u64 bytes_used = 0;
> +	struct btrfs_path path;
> +	struct btrfs_key key;
> +	struct extent_buffer *leaf;
> +	struct btrfs_block_group *cache;
> +	struct btrfs_fs_info *fs_info = trans->fs_info;
> +	struct btrfs_root *root = fs_info->extent_root;
> +
> +	ret = btrfs_run_delayed_refs(trans, -1);
> +	if (ret)
> +		return ret;
> +
> +	while(1) {
> +		cache = btrfs_lookup_first_block_group(fs_info, start);
> +		if (!cache)
> +			break;
> +
> +		start = cache->start + cache->length;
> +		cache->used = 0;
> +		cache->space_info->bytes_used = 0;
> +		if (list_empty(&cache->dirty_list))
> +			list_add_tail(&cache->dirty_list, &trans->dirty_bgs);
> +	}
> +
> +	btrfs_init_path(&path);
> +	key.offset = 0;
> +	key.objectid = 0;
> +	key.type = BTRFS_EXTENT_ITEM_KEY;
> +	ret = btrfs_search_slot(trans, root->fs_info->extent_root,
> +				&key, &path, 0, 0);
> +	if (ret < 0)
> +		return ret;
> +	while(1) {
> +		leaf = path.nodes[0];
> +		slot = path.slots[0];
> +		if (slot >= btrfs_header_nritems(leaf)) {
> +			ret = btrfs_next_leaf(root, &path);
> +			if (ret < 0)
> +				return ret;
> +			if (ret > 0)
> +				break;
> +			leaf = path.nodes[0];
> +			slot = path.slots[0];
> +		}
> +		btrfs_item_key_to_cpu(leaf, &key, slot);
> +		if (key.type == BTRFS_EXTENT_ITEM_KEY) {
> +			bytes_used += key.offset;
> +			ret = btrfs_update_block_group(trans,
> +				  key.objectid, key.offset, 1, 0);
> +			BUG_ON(ret);
> +		} else if (key.type == BTRFS_METADATA_ITEM_KEY) {
> +			bytes_used += fs_info->nodesize;
> +			ret = btrfs_update_block_group(trans,
> +				  key.objectid, fs_info->nodesize, 1, 0);
> +			if (ret)
> +				goto out;
> +		}
> +		path.slots[0]++;
> +	}
> +	btrfs_set_super_bytes_used(root->fs_info->super_copy, bytes_used);
> +	ret = 0;
> +out:
> +	btrfs_release_path(&path);
> +	return ret;
> +}
> diff --git a/common/repair.h b/common/repair.h
> index d1794610..4e1fa3e7 100644
> --- a/common/repair.h
> +++ b/common/repair.h
> @@ -32,5 +32,6 @@ struct btrfs_corrupt_block {
>   int btrfs_add_corrupt_extent_record(struct btrfs_fs_info *info,
>   				    struct btrfs_key *first_key,
>   				    u64 start, u64 len, int level);
> +int btrfs_fix_block_accounting(struct btrfs_trans_handle *trans);
>
>   #endif
> diff --git a/kernel-shared/extent-tree.c b/kernel-shared/extent-tree.c
> index a918e5aa..402904d1 100644
> --- a/kernel-shared/extent-tree.c
> +++ b/kernel-shared/extent-tree.c
> @@ -3247,80 +3247,6 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
>   	return ret;
>   }
>
> -/*
> - * Fixup block accounting. The initial block accounting created by
> - * make_block_groups isn't accuracy in this case.
> - */
> -int btrfs_fix_block_accounting(struct btrfs_trans_handle *trans)
> -{
> -	int ret = 0;
> -	int slot;
> -	u64 start = 0;
> -	u64 bytes_used = 0;
> -	struct btrfs_path path;
> -	struct btrfs_key key;
> -	struct extent_buffer *leaf;
> -	struct btrfs_block_group *cache;
> -	struct btrfs_fs_info *fs_info = trans->fs_info;
> -	struct btrfs_root *root = fs_info->extent_root;
> -
> -	ret = btrfs_run_delayed_refs(trans, -1);
> -	if (ret)
> -		return ret;
> -
> -	while(1) {
> -		cache = btrfs_lookup_first_block_group(fs_info, start);
> -		if (!cache)
> -			break;
> -
> -		start = cache->start + cache->length;
> -		cache->used = 0;
> -		cache->space_info->bytes_used = 0;
> -		if (list_empty(&cache->dirty_list))
> -			list_add_tail(&cache->dirty_list, &trans->dirty_bgs);
> -	}
> -
> -	btrfs_init_path(&path);
> -	key.offset = 0;
> -	key.objectid = 0;
> -	key.type = BTRFS_EXTENT_ITEM_KEY;
> -	ret = btrfs_search_slot(trans, root->fs_info->extent_root,
> -				&key, &path, 0, 0);
> -	if (ret < 0)
> -		return ret;
> -	while(1) {
> -		leaf = path.nodes[0];
> -		slot = path.slots[0];
> -		if (slot >= btrfs_header_nritems(leaf)) {
> -			ret = btrfs_next_leaf(root, &path);
> -			if (ret < 0)
> -				return ret;
> -			if (ret > 0)
> -				break;
> -			leaf = path.nodes[0];
> -			slot = path.slots[0];
> -		}
> -		btrfs_item_key_to_cpu(leaf, &key, slot);
> -		if (key.type == BTRFS_EXTENT_ITEM_KEY) {
> -			bytes_used += key.offset;
> -			ret = btrfs_update_block_group(trans,
> -				  key.objectid, key.offset, 1, 0);
> -			BUG_ON(ret);
> -		} else if (key.type == BTRFS_METADATA_ITEM_KEY) {
> -			bytes_used += fs_info->nodesize;
> -			ret = btrfs_update_block_group(trans,
> -				  key.objectid, fs_info->nodesize, 1, 0);
> -			if (ret)
> -				goto out;
> -		}
> -		path.slots[0]++;
> -	}
> -	btrfs_set_super_bytes_used(root->fs_info->super_copy, bytes_used);
> -	ret = 0;
> -out:
> -	btrfs_release_path(&path);
> -	return ret;
> -}
>
>   static void __get_extent_size(struct btrfs_root *root, struct btrfs_path *path,
>   			      u64 *start, u64 *len)
>

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

* Re: [PATCH 10/20] btrfs-progs: check: abstract out the used marking helpers
  2021-11-05 20:28 ` [PATCH 10/20] btrfs-progs: check: abstract out the used marking helpers Josef Bacik
@ 2021-11-06  0:37   ` Qu Wenruo
  0 siblings, 0 replies; 42+ messages in thread
From: Qu Wenruo @ 2021-11-06  0:37 UTC (permalink / raw)
  To: Josef Bacik, linux-btrfs, kernel-team



On 2021/11/6 04:28, Josef Bacik wrote:
> We will walk all referenced tree blocks during check in order to avoid
> writing over any referenced blocks during fsck.  However in the future
> we're going to need to do this for things like fixing block group
> accounting with extent tree v2.  This is because extent tree v2 will not
> refer to all of the allocated blocks in the extent tree.  Refactor the
> code some to allow us to send down an arbitrary extent_io_tree so we can
> use this helper for any case where we need to figure out where all the
> used space is on an extent tree v2 file system.

I guess in that case @tree parameter will be an per-block-group io-tree
then?

Then the refactor may be more suitable for the extent-tree-v2 patchset.

>
> Signed-off-by: Josef Bacik <josef@toxicpanda.com>
> ---
>   check/mode-common.c | 57 ++++++++++++++++++++-------------------------
>   1 file changed, 25 insertions(+), 32 deletions(-)
>
> diff --git a/check/mode-common.c b/check/mode-common.c
> index 0c3bd38b..a4a09714 100644
> --- a/check/mode-common.c
> +++ b/check/mode-common.c
> @@ -599,23 +599,21 @@ void reset_cached_block_groups()
>   	}
>   }
>
> -static int traverse_tree_blocks(struct extent_buffer *eb, int tree_root, int pin)
> +static int traverse_tree_blocks(struct btrfs_fs_info *fs_info,

fs_info can be extracted from eb->fs_info directly.

Thanks,
Qu

> +				struct extent_io_tree *tree,
> +				struct extent_buffer *eb, int tree_root)
>   {
>   	struct extent_buffer *tmp;
>   	struct btrfs_root_item *ri;
>   	struct btrfs_key key;
> -	struct extent_io_tree *tree;
>   	u64 bytenr;
>   	int level = btrfs_header_level(eb);
>   	int nritems;
>   	int ret;
>   	int i;
>   	u64 end = eb->start + eb->len;
> +	bool pin = tree == &fs_info->pinned_extents;
>
> -	if (pin)
> -		tree = &gfs_info->pinned_extents;
> -	else
> -		tree = gfs_info->excluded_extents;
>   	/*
>   	 * If we have pinned/excluded this block before, don't do it again.
>   	 * This can not only avoid forever loop with broken filesystem
> @@ -625,7 +623,7 @@ static int traverse_tree_blocks(struct extent_buffer *eb, int tree_root, int pin
>   		return 0;
>
>   	if (pin)
> -		btrfs_pin_extent(gfs_info, eb->start, eb->len);
> +		btrfs_pin_extent(fs_info, eb->start, eb->len);
>   	else
>   		set_extent_dirty(tree, eb->start, end - 1);
>
> @@ -654,12 +652,12 @@ static int traverse_tree_blocks(struct extent_buffer *eb, int tree_root, int pin
>   			 * in, but for now this doesn't actually use the root so
>   			 * just pass in extent_root.
>   			 */
> -			tmp = read_tree_block(gfs_info, bytenr, 0);
> +			tmp = read_tree_block(fs_info, bytenr, 0);
>   			if (!extent_buffer_uptodate(tmp)) {
>   				fprintf(stderr, "Error reading root block\n");
>   				return -EIO;
>   			}
> -			ret = traverse_tree_blocks(tmp, 0, pin);
> +			ret = traverse_tree_blocks(fs_info, tree, tmp, 0);
>   			free_extent_buffer(tmp);
>   			if (ret)
>   				return ret;
> @@ -669,20 +667,21 @@ static int traverse_tree_blocks(struct extent_buffer *eb, int tree_root, int pin
>   			/* If we aren't the tree root don't read the block */
>   			if (level == 1 && !tree_root) {
>   				if (pin)
> -					btrfs_pin_extent(gfs_info, bytenr,
> -							 gfs_info->nodesize);
> +					btrfs_pin_extent(fs_info, bytenr,
> +							 fs_info->nodesize);
>   				else
>   					set_extent_dirty(tree, bytenr,
> -							 gfs_info->nodesize);
> +							 fs_info->nodesize);
>   				continue;
>   			}
>
> -			tmp = read_tree_block(gfs_info, bytenr, 0);
> +			tmp = read_tree_block(fs_info, bytenr, 0);
>   			if (!extent_buffer_uptodate(tmp)) {
>   				fprintf(stderr, "Error reading tree block\n");
>   				return -EIO;
>   			}
> -			ret = traverse_tree_blocks(tmp, tree_root, pin);
> +			ret = traverse_tree_blocks(fs_info, tree, tmp,
> +						   tree_root);
>   			free_extent_buffer(tmp);
>   			if (ret)
>   				return ret;
> @@ -692,30 +691,27 @@ static int traverse_tree_blocks(struct extent_buffer *eb, int tree_root, int pin
>   	return 0;
>   }
>
> -static int pin_down_tree_blocks(struct extent_buffer *eb, int tree_root)
> -{
> -	return traverse_tree_blocks(eb, tree_root, 1);
> -}
> -
> -int pin_metadata_blocks(void)
> +int btrfs_mark_used_tree_blocks(struct btrfs_fs_info *fs_info,
> +				struct extent_io_tree *tree)
>   {
>   	int ret;
>
> -	ret = pin_down_tree_blocks(gfs_info->chunk_root->node, 0);
> -	if (ret)
> -		return ret;
> -
> -	return pin_down_tree_blocks(gfs_info->tree_root->node, 1);
> +	ret = traverse_tree_blocks(fs_info, tree,
> +				   fs_info->chunk_root->node, 0);
> +	if (!ret)
> +		ret = traverse_tree_blocks(fs_info, tree,
> +					   fs_info->tree_root->node, 1);
> +	return ret;
>   }
>
> -static int exclude_tree_blocks(struct extent_buffer *eb, int tree_root)
> +int pin_metadata_blocks(void)
>   {
> -	return traverse_tree_blocks(eb, tree_root, 0);
> +	return btrfs_mark_used_tree_blocks(gfs_info,
> +					   &gfs_info->pinned_extents);
>   }
>
>   int exclude_metadata_blocks(void)
>   {
> -	int ret;
>   	struct extent_io_tree *excluded_extents;
>
>   	excluded_extents = malloc(sizeof(*excluded_extents));
> @@ -724,10 +720,7 @@ int exclude_metadata_blocks(void)
>   	extent_io_tree_init(excluded_extents);
>   	gfs_info->excluded_extents = excluded_extents;
>
> -	ret = exclude_tree_blocks(gfs_info->chunk_root->node, 0);
> -	if (ret)
> -		return ret;
> -	return exclude_tree_blocks(gfs_info->tree_root->node, 1);
> +	return btrfs_mark_used_tree_blocks(gfs_info, excluded_extents);
>   }
>
>   void cleanup_excluded_extents(void)
>

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

* Re: [PATCH 12/20] btrfs-progs: mark reloc roots as used
  2021-11-05 20:28 ` [PATCH 12/20] btrfs-progs: mark reloc roots as used Josef Bacik
@ 2021-11-06  0:39   ` Qu Wenruo
  2021-11-08 19:14     ` Josef Bacik
  0 siblings, 1 reply; 42+ messages in thread
From: Qu Wenruo @ 2021-11-06  0:39 UTC (permalink / raw)
  To: Josef Bacik, linux-btrfs, kernel-team



On 2021/11/6 04:28, Josef Bacik wrote:
> btrfs_mark_used_tree_blocks skips the reloc roots for some reason, which
> causes problems because these blocks are in use, and we use this helper
> to determine if the block accounting is correct with extent tree v2.

Any idea on why it's skipped in the first place?

Thanks,
Qu

>
> Signed-off-by: Josef Bacik <josef@toxicpanda.com>
> ---
>   common/repair.c | 4 ----
>   1 file changed, 4 deletions(-)
>
> diff --git a/common/repair.c b/common/repair.c
> index 79519140..413c3e86 100644
> --- a/common/repair.c
> +++ b/common/repair.c
> @@ -87,10 +87,6 @@ static int traverse_tree_blocks(struct btrfs_fs_info *fs_info,
>   			btrfs_item_key_to_cpu(eb, &key, i);
>   			if (key.type != BTRFS_ROOT_ITEM_KEY)
>   				continue;
> -			/* Skip the extent root and reloc roots */
> -			if (key.objectid == BTRFS_TREE_RELOC_OBJECTID ||
> -			    key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID)
> -				continue;
>   			is_extent_root =
>   				key.objectid == BTRFS_EXTENT_TREE_OBJECTID;
>   			/* If pin, skip the extent root */
>

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

* Re: [PATCH 13/20] btrfs-progs: stop accessing ->extent_root directly
  2021-11-05 20:28 ` [PATCH 13/20] btrfs-progs: stop accessing ->extent_root directly Josef Bacik
@ 2021-11-06  0:41   ` Qu Wenruo
  0 siblings, 0 replies; 42+ messages in thread
From: Qu Wenruo @ 2021-11-06  0:41 UTC (permalink / raw)
  To: Josef Bacik, linux-btrfs, kernel-team



On 2021/11/6 04:28, Josef Bacik wrote:
> When we switch to multiple global trees we'll need to access the
> appropriate extent root depending on the block group or possibly root.
> To handle this, use a helper in most places and then the actual root in
> places where it is required.  We will whittle down the direct accessors
> with future patches, but this does the bulk of the preparatory work.
>
> Signed-off-by: Josef Bacik <josef@toxicpanda.com>
> ---
>   btrfs-corrupt-block.c           | 13 +++---
>   btrfs-map-logical.c             |  9 ++--
>   btrfstune.c                     |  2 +-
>   check/main.c                    | 78 +++++++++++++++++++--------------
>   check/mode-common.c             |  8 ++--
>   check/mode-lowmem.c             | 72 +++++++++++++++++-------------
>   check/qgroup-verify.c           |  2 +-
>   cmds/rescue-chunk-recover.c     | 18 ++++----
>   common/repair.c                 |  5 +--
>   convert/main.c                  |  4 +-
>   image/main.c                    |  2 +-
>   kernel-shared/backref.c         | 10 +++--
>   kernel-shared/ctree.h           |  2 +-
>   kernel-shared/disk-io.c         | 30 ++++++++-----
>   kernel-shared/disk-io.h         |  1 +
>   kernel-shared/extent-tree.c     | 42 ++++++++++--------
>   kernel-shared/free-space-tree.c |  8 +++-
>   kernel-shared/volumes.c         |  3 +-
>   kernel-shared/zoned.c           |  2 +-
>   mkfs/main.c                     |  4 +-
>   20 files changed, 179 insertions(+), 136 deletions(-)
>
> diff --git a/btrfs-corrupt-block.c b/btrfs-corrupt-block.c
> index d7904b6f..d976345c 100644
> --- a/btrfs-corrupt-block.c
> +++ b/btrfs-corrupt-block.c
> @@ -183,6 +183,7 @@ static int corrupt_keys_in_block(struct btrfs_fs_info *fs_info, u64 bytenr)
>   static int corrupt_extent(struct btrfs_trans_handle *trans,
>   			  struct btrfs_root *root, u64 bytenr)
>   {
> +	struct btrfs_root *extent_root;
>   	struct btrfs_key key;
>   	struct extent_buffer *leaf;
>   	u32 item_size;
> @@ -200,9 +201,9 @@ static int corrupt_extent(struct btrfs_trans_handle *trans,
>   	key.type = (u8)-1;
>   	key.offset = (u64)-1;
>
> +	extent_root = btrfs_extent_root(trans->fs_info, bytenr);
>   	while(1) {
> -		ret = btrfs_search_slot(trans, root->fs_info->extent_root,
> -					&key, path, -1, 1);
> +		ret = btrfs_search_slot(trans, extent_root, &key, path, -1, 1);
>   		if (ret < 0)
>   			break;
>
> @@ -472,7 +473,7 @@ static int corrupt_block_group(struct btrfs_root *root, u64 bg, char *field)
>   	u64 orig, bogus;
>   	int ret = 0;
>
> -	root = root->fs_info->extent_root;
> +	root = btrfs_extent_root(root->fs_info, 0);

The problem is the same as previous helper for csum root.

There are too many 0 as place holders, which may need extra refactor again.

Thus I prefer these helpers to be introduced before we really need them.

Thanks,
Qu

>
>   	corrupt_field = convert_block_group_field(field);
>   	if (corrupt_field == BTRFS_BLOCK_GROUP_ITEM_BAD) {
> @@ -1382,11 +1383,13 @@ int main(int argc, char **argv)
>   	}
>   	if (extent_tree) {
>   		struct btrfs_trans_handle *trans;
> +		struct btrfs_root *extent_root;
>
> +		extent_root = btrfs_extent_root(root->fs_info, 0);
>   		trans = btrfs_start_transaction(root, 1);
>   		BUG_ON(IS_ERR(trans));
> -		btrfs_corrupt_extent_tree(trans, root->fs_info->extent_root,
> -					  root->fs_info->extent_root->node);
> +		btrfs_corrupt_extent_tree(trans, extent_root,
> +					  extent_root->node);
>   		btrfs_commit_transaction(trans, root);
>   		goto out_close;
>   	}
> diff --git a/btrfs-map-logical.c b/btrfs-map-logical.c
> index 4ac644b4..b3a7526b 100644
> --- a/btrfs-map-logical.c
> +++ b/btrfs-map-logical.c
> @@ -42,6 +42,7 @@ static FILE *info_file;
>   static int map_one_extent(struct btrfs_fs_info *fs_info,
>   			  u64 *logical_ret, u64 *len_ret, int search_forward)
>   {
> +	struct btrfs_root *extent_root;
>   	struct btrfs_path *path;
>   	struct btrfs_key key;
>   	u64 logical;
> @@ -59,8 +60,8 @@ static int map_one_extent(struct btrfs_fs_info *fs_info,
>   	key.type = 0;
>   	key.offset = 0;
>
> -	ret = btrfs_search_slot(NULL, fs_info->extent_root, &key, path,
> -				0, 0);
> +	extent_root = btrfs_extent_root(fs_info, logical);
> +	ret = btrfs_search_slot(NULL, extent_root, &key, path, 0, 0);
>   	if (ret < 0)
>   		goto out;
>   	BUG_ON(ret == 0);
> @@ -73,10 +74,10 @@ again:
>   	    (key.type != BTRFS_EXTENT_ITEM_KEY &&
>   	     key.type != BTRFS_METADATA_ITEM_KEY)) {
>   		if (!search_forward)
> -			ret = btrfs_previous_extent_item(fs_info->extent_root,
> +			ret = btrfs_previous_extent_item(extent_root,
>   							 path, 0);
>   		else
> -			ret = btrfs_next_extent_item(fs_info->extent_root,
> +			ret = btrfs_next_extent_item(extent_root,
>   						     path, 0);
>   		if (ret)
>   			goto out;
> diff --git a/btrfstune.c b/btrfstune.c
> index d34d89c1..4f77cfc0 100644
> --- a/btrfstune.c
> +++ b/btrfstune.c
> @@ -233,7 +233,7 @@ static int change_buffer_header_uuid(struct extent_buffer *eb, uuid_t new_fsid)
>
>   static int change_extents_uuid(struct btrfs_fs_info *fs_info, uuid_t new_fsid)
>   {
> -	struct btrfs_root *root = fs_info->extent_root;
> +	struct btrfs_root *root = btrfs_extent_root(fs_info, 0);
>   	struct btrfs_path path;
>   	struct btrfs_key key = {0, 0, 0};
>   	int ret = 0;
> diff --git a/check/main.c b/check/main.c
> index 632dfba0..e3e5a336 100644
> --- a/check/main.c
> +++ b/check/main.c
> @@ -5619,7 +5619,7 @@ static int verify_space_cache(struct btrfs_root *root,
>   	u64 last;
>   	int ret = 0;
>
> -	root = gfs_info->extent_root;
> +	root = btrfs_extent_root(root->fs_info, cache->start);
>
>   	last = max_t(u64, cache->start, BTRFS_SUPER_INFO_OFFSET);
>
> @@ -5837,6 +5837,7 @@ out:
>   static int check_extent_exists(struct btrfs_root *root, u64 bytenr,
>   			       u64 num_bytes)
>   {
> +	struct btrfs_root *extent_root;
>   	struct btrfs_path path;
>   	struct extent_buffer *leaf;
>   	struct btrfs_key key;
> @@ -5848,7 +5849,8 @@ static int check_extent_exists(struct btrfs_root *root, u64 bytenr,
>   	key.offset = (u64)-1;
>
>   again:
> -	ret = btrfs_search_slot(NULL, gfs_info->extent_root, &key, &path,
> +	extent_root = btrfs_extent_root(gfs_info, key.objectid);
> +	ret = btrfs_search_slot(NULL, extent_root, &key, &path,
>   				0, 0);
>   	if (ret < 0) {
>   		fprintf(stderr, "Error looking up extent record %d\n", ret);
> @@ -5858,7 +5860,7 @@ again:
>   		if (path.slots[0] > 0) {
>   			path.slots[0]--;
>   		} else {
> -			ret = btrfs_prev_leaf(root, &path);
> +			ret = btrfs_prev_leaf(extent_root, &path);
>   			if (ret < 0) {
>   				goto out;
>   			} else if (ret > 0) {
> @@ -5882,7 +5884,7 @@ again:
>   		if (path.slots[0] > 0) {
>   			path.slots[0]--;
>   		} else {
> -			ret = btrfs_prev_leaf(root, &path);
> +			ret = btrfs_prev_leaf(extent_root, &path);
>   			if (ret < 0) {
>   				goto out;
>   			} else if (ret > 0) {
> @@ -5895,7 +5897,7 @@ again:
>
>   	while (num_bytes) {
>   		if (path.slots[0] >= btrfs_header_nritems(path.nodes[0])) {
> -			ret = btrfs_next_leaf(root, &path);
> +			ret = btrfs_next_leaf(extent_root, &path);
>   			if (ret < 0) {
>   				fprintf(stderr, "Error going to next leaf "
>   					"%d\n", ret);
> @@ -5946,7 +5948,8 @@ again:
>   				 * anyway just in case.
>   				 */
>   				btrfs_release_path(&path);
> -				ret = check_extent_exists(root, new_start,
> +				ret = check_extent_exists(extent_root,
> +							  new_start,
>   							  new_bytes);
>   				if (ret) {
>   					fprintf(stderr, "Right section didn't "
> @@ -6720,6 +6723,7 @@ static int delete_extent_records(struct btrfs_trans_handle *trans,
>   				 struct btrfs_path *path,
>   				 u64 bytenr)
>   {
> +	struct btrfs_root *extent_root = btrfs_extent_root(gfs_info, bytenr);
>   	struct btrfs_key key;
>   	struct btrfs_key found_key;
>   	struct extent_buffer *leaf;
> @@ -6732,7 +6736,7 @@ static int delete_extent_records(struct btrfs_trans_handle *trans,
>   	key.offset = (u64)-1;
>
>   	while (1) {
> -		ret = btrfs_search_slot(trans, gfs_info->extent_root, &key,
> +		ret = btrfs_search_slot(trans, extent_root, &key,
>   					path, 0, 1);
>   		if (ret < 0)
>   			break;
> @@ -6775,7 +6779,7 @@ static int delete_extent_records(struct btrfs_trans_handle *trans,
>   			"repair deleting extent record: key [%llu,%u,%llu]\n",
>   			found_key.objectid, found_key.type, found_key.offset);
>
> -		ret = btrfs_del_item(trans, gfs_info->extent_root, path);
> +		ret = btrfs_del_item(trans, extent_root, path);
>   		if (ret)
>   			break;
>   		btrfs_release_path(path);
> @@ -6807,7 +6811,8 @@ static int record_extent(struct btrfs_trans_handle *trans,
>   			 int allocated, u64 flags)
>   {
>   	int ret = 0;
> -	struct btrfs_root *extent_root = gfs_info->extent_root;
> +	struct btrfs_root *extent_root = btrfs_extent_root(gfs_info,
> +							   rec->start);
>   	struct extent_buffer *leaf;
>   	struct btrfs_key ins_key;
>   	struct btrfs_extent_item *ei;
> @@ -6888,7 +6893,7 @@ static int record_extent(struct btrfs_trans_handle *trans,
>   			 * just makes the backref allocator create a data
>   			 * backref
>   			 */
> -			ret = btrfs_inc_extent_ref(trans, gfs_info->extent_root,
> +			ret = btrfs_inc_extent_ref(trans, extent_root,
>   						   rec->start, rec->max_size,
>   						   parent,
>   						   dback->root,
> @@ -6917,7 +6922,7 @@ static int record_extent(struct btrfs_trans_handle *trans,
>   		else
>   			parent = 0;
>
> -		ret = btrfs_inc_extent_ref(trans, gfs_info->extent_root,
> +		ret = btrfs_inc_extent_ref(trans, extent_root,
>   					   rec->start, rec->max_size,
>   					   parent, tback->root, 0, 0);
>   		fprintf(stderr,
> @@ -7437,7 +7442,6 @@ static int delete_duplicate_records(struct btrfs_root *root,
>   		list_move_tail(&tmp->list, &delete_list);
>   	}
>
> -	root = gfs_info->extent_root;
>   	trans = btrfs_start_transaction(root, 1);
>   	if (IS_ERR(trans)) {
>   		ret = PTR_ERR(trans);
> @@ -7459,6 +7463,7 @@ static int delete_duplicate_records(struct btrfs_root *root,
>   			abort();
>   		}
>
> +		root = btrfs_extent_root(gfs_info, key.objectid);
>   		ret = btrfs_search_slot(trans, root, &key, &path, -1, 1);
>   		if (ret) {
>   			if (ret > 0)
> @@ -7697,7 +7702,7 @@ static int fixup_extent_refs(struct cache_tree *extent_cache,
>   	if (ret < 0)
>   		goto out;
>
> -	trans = btrfs_start_transaction(gfs_info->extent_root, 1);
> +	trans = btrfs_start_transaction(gfs_info->tree_root, 1);
>   	if (IS_ERR(trans)) {
>   		ret = PTR_ERR(trans);
>   		goto out;
> @@ -7736,7 +7741,7 @@ static int fixup_extent_refs(struct cache_tree *extent_cache,
>   	}
>   out:
>   	if (trans) {
> -		int err = btrfs_commit_transaction(trans, gfs_info->extent_root);
> +		int err = btrfs_commit_transaction(trans, gfs_info->tree_root);
>
>   		if (!ret)
>   			ret = err;
> @@ -7753,7 +7758,7 @@ out:
>   static int fixup_extent_flags(struct extent_record *rec)
>   {
>   	struct btrfs_trans_handle *trans;
> -	struct btrfs_root *root = gfs_info->extent_root;
> +	struct btrfs_root *root = btrfs_extent_root(gfs_info, rec->start);
>   	struct btrfs_path path;
>   	struct btrfs_extent_item *ei;
>   	struct btrfs_key key;
> @@ -7822,6 +7827,7 @@ retry:
>   static int prune_one_block(struct btrfs_trans_handle *trans,
>   			   struct btrfs_corrupt_block *corrupt)
>   {
> +	struct btrfs_root *extent_root;
>   	int ret;
>   	struct btrfs_path path;
>   	struct extent_buffer *eb;
> @@ -7832,11 +7838,12 @@ static int prune_one_block(struct btrfs_trans_handle *trans,
>
>   	btrfs_init_path(&path);
>   again:
> +	extent_root = btrfs_extent_root(gfs_info, corrupt->key.objectid);
>   	/* we want to stop at the parent to our busted block */
>   	path.lowest_level = level;
>
> -	ret = btrfs_search_slot(trans, gfs_info->extent_root,
> -				&corrupt->key, &path, -1, 1);
> +	ret = btrfs_search_slot(trans, extent_root, &corrupt->key, &path,
> +				-1, 1);
>
>   	if (ret < 0)
>   		goto out;
> @@ -7868,7 +7875,7 @@ again:
>   	 * We couldn't find the bad block.
>   	 * TODO: search all the nodes for pointers to this block
>   	 */
> -	if (eb == gfs_info->extent_root->node) {
> +	if (eb == extent_root->node) {
>   		ret = -ENOENT;
>   		goto out;
>   	} else {
> @@ -7879,7 +7886,7 @@ again:
>
>   del_ptr:
>   	printk("deleting pointer to block %llu\n", corrupt->cache.start);
> -	ret = btrfs_del_ptr(gfs_info->extent_root, &path, level, slot);
> +	ret = btrfs_del_ptr(extent_root, &path, level, slot);
>
>   out:
>   	btrfs_release_path(&path);
> @@ -7897,7 +7904,7 @@ static int prune_corrupt_blocks(void)
>   		if (!cache)
>   			break;
>   		if (!trans) {
> -			trans = btrfs_start_transaction(gfs_info->extent_root, 1);
> +			trans = btrfs_start_transaction(gfs_info->tree_root, 1);
>   			if (IS_ERR(trans))
>   				return PTR_ERR(trans);
>   		}
> @@ -7906,7 +7913,7 @@ static int prune_corrupt_blocks(void)
>   		remove_cache_extent(gfs_info->corrupt_blocks, cache);
>   	}
>   	if (trans)
> -		return btrfs_commit_transaction(trans, gfs_info->extent_root);
> +		return btrfs_commit_transaction(trans, gfs_info->tree_root);
>   	return 0;
>   }
>
> @@ -8011,7 +8018,8 @@ static int repair_extent_item_generation(struct extent_record *rec)
>   	struct btrfs_path path;
>   	struct btrfs_key key;
>   	struct btrfs_extent_item *ei;
> -	struct btrfs_root *extent_root = gfs_info->extent_root;
> +	struct btrfs_root *extent_root = btrfs_extent_root(gfs_info,
> +							   rec->start);
>   	u64 new_gen = 0;;
>   	int ret;
>
> @@ -8258,7 +8266,6 @@ repair_abort:
>   		} else if (!ret) {
>   			struct btrfs_trans_handle *trans;
>
> -			root = gfs_info->extent_root;
>   			trans = btrfs_start_transaction(root, 1);
>   			if (IS_ERR(trans)) {
>   				ret = PTR_ERR(trans);
> @@ -8714,7 +8721,7 @@ static int check_block_groups(struct block_group_tree *bg_cache)
>   	if (!repair || !ret)
>   		return ret;
>
> -	trans = btrfs_start_transaction(gfs_info->extent_root, 1);
> +	trans = btrfs_start_transaction(gfs_info->tree_root, 1);
>   	if (IS_ERR(trans)) {
>   		ret = PTR_ERR(trans);
>   		fprintf(stderr, "Failed to start a transaction\n");
> @@ -8722,7 +8729,7 @@ static int check_block_groups(struct block_group_tree *bg_cache)
>   	}
>
>   	ret = btrfs_fix_block_accounting(trans);
> -	btrfs_commit_transaction(trans, gfs_info->extent_root);
> +	btrfs_commit_transaction(trans, gfs_info->tree_root);
>   	return ret ? ret : -EAGAIN;
>   }
>
> @@ -9368,7 +9375,7 @@ again:
>   	}
>
>   	/* Ok we can allocate now, reinit the extent root */
> -	ret = btrfs_fsck_reinit_root(trans, gfs_info->extent_root);
> +	ret = btrfs_fsck_reinit_root(trans, btrfs_extent_root(gfs_info, 0));
>   	if (ret) {
>   		fprintf(stderr, "extent root initialization failed\n");
>   		/*
> @@ -9387,6 +9394,7 @@ again:
>   	while (1) {
>   		struct btrfs_block_group_item bgi;
>   		struct btrfs_block_group *cache;
> +		struct btrfs_root *extent_root = btrfs_extent_root(gfs_info, 0);
>   		struct btrfs_key key;
>
>   		cache = btrfs_lookup_first_block_group(gfs_info, start);
> @@ -9400,8 +9408,8 @@ again:
>   		key.objectid = cache->start;
>   		key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
>   		key.offset = cache->length;
> -		ret = btrfs_insert_item(trans, gfs_info->extent_root, &key,
> -					&bgi, sizeof(bgi));
> +		ret = btrfs_insert_item(trans, extent_root, &key, &bgi,
> +					sizeof(bgi));
>   		if (ret) {
>   			fprintf(stderr, "Error adding block group\n");
>   			return ret;
> @@ -9618,7 +9626,7 @@ out:
>
>   static int fill_csum_tree_from_extent(struct btrfs_trans_handle *trans)
>   {
> -	struct btrfs_root *extent_root = gfs_info->extent_root;
> +	struct btrfs_root *extent_root = btrfs_extent_root(gfs_info, 0);
>   	struct btrfs_root *csum_root;
>   	struct btrfs_path path;
>   	struct btrfs_extent_item *ei;
> @@ -9721,6 +9729,7 @@ static void free_roots_info_cache(void)
>
>   static int build_roots_info_cache(void)
>   {
> +	struct btrfs_root *extent_root = btrfs_extent_root(gfs_info, 0);
>   	int ret = 0;
>   	struct btrfs_key key;
>   	struct extent_buffer *leaf;
> @@ -9737,7 +9746,7 @@ static int build_roots_info_cache(void)
>   	key.objectid = 0;
>   	key.type = BTRFS_EXTENT_ITEM_KEY;
>   	key.offset = 0;
> -	ret = btrfs_search_slot(NULL, gfs_info->extent_root, &key, &path, 0, 0);
> +	ret = btrfs_search_slot(NULL, extent_root, &key, &path, 0, 0);
>   	if (ret < 0)
>   		goto out;
>   	leaf = path.nodes[0];
> @@ -9757,7 +9766,7 @@ static int build_roots_info_cache(void)
>
>   		ctx.item_count++;
>   		if (slot >= btrfs_header_nritems(leaf)) {
> -			ret = btrfs_next_leaf(gfs_info->extent_root, &path);
> +			ret = btrfs_next_leaf(extent_root, &path);
>   			if (ret < 0) {
>   				break;
>   			} else if (ret) {
> @@ -10670,7 +10679,7 @@ static int cmd_check(const struct cmd_struct *cmd, int argc, char **argv)
>   	if (init_extent_tree || init_csum_tree) {
>   		struct btrfs_trans_handle *trans;
>
> -		trans = btrfs_start_transaction(gfs_info->extent_root, 0);
> +		trans = btrfs_start_transaction(gfs_info->tree_root, 0);
>   		if (IS_ERR(trans)) {
>   			error("error starting transaction");
>   			ret = PTR_ERR(trans);
> @@ -10711,12 +10720,13 @@ static int cmd_check(const struct cmd_struct *cmd, int argc, char **argv)
>   		 * Ok now we commit and run the normal fsck, which will add
>   		 * extent entries for all of the items it finds.
>   		 */
> -		ret = btrfs_commit_transaction(trans, gfs_info->extent_root);
> +		ret = btrfs_commit_transaction(trans, gfs_info->tree_root);
>   		err |= !!ret;
>   		if (ret)
>   			goto close_out;
>   	}
> -	if (!extent_buffer_uptodate(gfs_info->extent_root->node)) {
> +	root = btrfs_extent_root(gfs_info, 0);
> +	if (!extent_buffer_uptodate(root->node)) {
>   		error("critical: extent_root, unable to check the filesystem");
>   		ret = -EIO;
>   		err |= !!ret;
> diff --git a/check/mode-common.c b/check/mode-common.c
> index 56377840..72fec47c 100644
> --- a/check/mode-common.c
> +++ b/check/mode-common.c
> @@ -176,6 +176,8 @@ static int check_prealloc_shared_data_ref(u64 parent, u64 disk_bytenr)
>    */
>   int check_prealloc_extent_written(u64 disk_bytenr, u64 num_bytes)
>   {
> +	struct btrfs_root *extent_root = btrfs_extent_root(gfs_info,
> +							   disk_bytenr);
>   	struct btrfs_path path;
>   	struct btrfs_key key;
>   	int ret;
> @@ -189,7 +191,7 @@ int check_prealloc_extent_written(u64 disk_bytenr, u64 num_bytes)
>   	key.offset = num_bytes;
>
>   	btrfs_init_path(&path);
> -	ret = btrfs_search_slot(NULL, gfs_info->extent_root, &key, &path, 0, 0);
> +	ret = btrfs_search_slot(NULL, extent_root, &key, &path, 0, 0);
>   	if (ret > 0) {
>   		fprintf(stderr,
>   	"Missing extent item in extent tree for disk_bytenr %llu, num_bytes %llu\n",
> @@ -240,7 +242,7 @@ int check_prealloc_extent_written(u64 disk_bytenr, u64 num_bytes)
>   	path.slots[0]++;
>   	while (true) {
>   		if (path.slots[0] >= btrfs_header_nritems(path.nodes[0])) {
> -			ret = btrfs_next_leaf(gfs_info->extent_root, &path);
> +			ret = btrfs_next_leaf(extent_root, &path);
>   			if (ret < 0)
>   				goto out;
>   			if (ret > 0) {
> @@ -1083,7 +1085,7 @@ int recow_extent_buffer(struct btrfs_root *root, struct extent_buffer *eb)
>    */
>   int get_extent_item_generation(u64 bytenr, u64 *gen_ret)
>   {
> -	struct btrfs_root *root = gfs_info->extent_root;
> +	struct btrfs_root *root = btrfs_extent_root(gfs_info, bytenr);
>   	struct btrfs_extent_item *ei;
>   	struct btrfs_path path;
>   	struct btrfs_key key;
> diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c
> index 696ad215..cc6773cd 100644
> --- a/check/mode-lowmem.c
> +++ b/check/mode-lowmem.c
> @@ -33,7 +33,7 @@ static u64 total_used = 0;
>   static int calc_extent_flag(struct btrfs_root *root, struct extent_buffer *eb,
>   			    u64 *flags_ret)
>   {
> -	struct btrfs_root *extent_root = gfs_info->extent_root;
> +	struct btrfs_root *extent_root;
>   	struct btrfs_root_item *ri = &root->root_item;
>   	struct btrfs_extent_inline_ref *iref;
>   	struct btrfs_extent_item *ei;
> @@ -73,6 +73,7 @@ static int calc_extent_flag(struct btrfs_root *root, struct extent_buffer *eb,
>   	key.type = (u8)-1;
>   	key.offset = (u64)-1;
>
> +	extent_root = btrfs_extent_root(gfs_info, key.objectid);
>   	ret = btrfs_search_slot(NULL, extent_root, &key, path, 0, 0);
>   	if (ret <= 0) {
>   		ret = -EIO;
> @@ -265,7 +266,7 @@ static int modify_block_group_cache(struct btrfs_block_group *block_group, int c
>    */
>   static int modify_block_groups_cache(u64 flags, int cache)
>   {
> -	struct btrfs_root *root = gfs_info->extent_root;
> +	struct btrfs_root *root = btrfs_extent_root(gfs_info, 0);
>   	struct btrfs_key key;
>   	struct btrfs_path path;
>   	struct btrfs_block_group *bg_cache;
> @@ -330,7 +331,7 @@ static int clear_block_groups_full(u64 flags)
>   static int create_chunk_and_block_group(u64 flags, u64 *start, u64 *nbytes)
>   {
>   	struct btrfs_trans_handle *trans;
> -	struct btrfs_root *root = gfs_info->extent_root;
> +	struct btrfs_root *root = btrfs_extent_root(gfs_info, 0);
>   	int ret;
>
>   	if ((flags & BTRFS_BLOCK_GROUP_TYPE_MASK) == 0)
> @@ -418,7 +419,7 @@ static int is_chunk_almost_full(u64 start)
>   {
>   	struct btrfs_path path;
>   	struct btrfs_key key;
> -	struct btrfs_root *root = gfs_info->extent_root;
> +	struct btrfs_root *root = btrfs_extent_root(gfs_info, 0);
>   	struct btrfs_block_group_item *bi;
>   	struct btrfs_block_group_item bg_item;
>   	struct extent_buffer *eb;
> @@ -594,10 +595,9 @@ out:
>   static int repair_block_accounting(void)
>   {
>   	struct btrfs_trans_handle *trans = NULL;
> -	struct btrfs_root *root = gfs_info->extent_root;
>   	int ret;
>
> -	trans = btrfs_start_transaction(root, 1);
> +	trans = btrfs_start_transaction(gfs_info->tree_root, 1);
>   	if (IS_ERR(trans)) {
>   		ret = PTR_ERR(trans);
>   		errno = -ret;
> @@ -606,7 +606,7 @@ static int repair_block_accounting(void)
>   	}
>
>   	ret = btrfs_fix_block_accounting(trans);
> -	btrfs_commit_transaction(trans, root);
> +	btrfs_commit_transaction(trans, gfs_info->tree_root);
>   	return ret;
>   }
>
> @@ -622,7 +622,7 @@ static int repair_tree_block_ref(struct btrfs_root *root,
>   				 struct node_refs *nrefs, int level, int err)
>   {
>   	struct btrfs_trans_handle *trans = NULL;
> -	struct btrfs_root *extent_root = gfs_info->extent_root;
> +	struct btrfs_root *extent_root;
>   	struct btrfs_path path;
>   	struct btrfs_extent_item *ei;
>   	struct btrfs_tree_block_info *bi;
> @@ -656,6 +656,7 @@ static int repair_tree_block_ref(struct btrfs_root *root,
>   	key.offset = (u64)-1;
>
>   	/* Search for the extent item */
> +	extent_root = btrfs_extent_root(gfs_info, bytenr);
>   	ret = btrfs_search_slot(NULL, extent_root, &key, &path, 0, 0);
>   	if (ret <= 0) {
>   		ret = -EIO;
> @@ -3001,7 +3002,7 @@ static int check_tree_block_ref(struct btrfs_root *root,
>   				int level, u64 owner, struct node_refs *nrefs)
>   {
>   	struct btrfs_key key;
> -	struct btrfs_root *extent_root = gfs_info->extent_root;
> +	struct btrfs_root *extent_root;
>   	struct btrfs_path path;
>   	struct btrfs_extent_item *ei;
>   	struct btrfs_extent_inline_ref *iref;
> @@ -3030,6 +3031,7 @@ static int check_tree_block_ref(struct btrfs_root *root,
>   	key.offset = (u64)-1;
>
>   	/* Search for the backref in extent tree */
> +	extent_root = btrfs_extent_root(gfs_info, bytenr);
>   	ret = btrfs_search_slot(NULL, extent_root, &key, &path, 0, 0);
>   	if (ret < 0) {
>   		err |= BACKREF_MISSING;
> @@ -3222,7 +3224,7 @@ static int repair_extent_data_item(struct btrfs_root *root,
>   	struct btrfs_key key;
>   	struct btrfs_extent_item *ei;
>   	struct btrfs_path path;
> -	struct btrfs_root *extent_root = gfs_info->extent_root;
> +	struct btrfs_root *extent_root;
>   	struct extent_buffer *eb;
>   	u64 size;
>   	u64 disk_bytenr;
> @@ -3274,6 +3276,7 @@ static int repair_extent_data_item(struct btrfs_root *root,
>   	key.offset = num_bytes;
>
>   	btrfs_init_path(&path);
> +	extent_root = btrfs_extent_root(gfs_info, key.objectid);
>   	ret = btrfs_search_slot(NULL, extent_root, &key, &path, 0, 0);
>   	if (ret < 0) {
>   		ret = -EIO;
> @@ -3356,7 +3359,7 @@ static int check_extent_data_item(struct btrfs_root *root,
>   	struct btrfs_file_extent_item *fi;
>   	struct extent_buffer *eb = pathp->nodes[0];
>   	struct btrfs_path path;
> -	struct btrfs_root *extent_root = gfs_info->extent_root;
> +	struct btrfs_root *extent_root;
>   	struct btrfs_key fi_key;
>   	struct btrfs_key dbref_key;
>   	struct extent_buffer *leaf;
> @@ -3426,6 +3429,7 @@ static int check_extent_data_item(struct btrfs_root *root,
>   	dbref_key.type = BTRFS_EXTENT_ITEM_KEY;
>   	dbref_key.offset = btrfs_file_extent_disk_num_bytes(eb, fi);
>
> +	extent_root = btrfs_extent_root(gfs_info, dbref_key.objectid);
>   	ret = btrfs_search_slot(NULL, extent_root, &dbref_key, &path, 0, 0);
>   	if (ret)
>   		goto out;
> @@ -3499,8 +3503,9 @@ static int check_extent_data_item(struct btrfs_root *root,
>   		dbref_key.offset = hash_extent_data_ref(owner, fi_key.objectid,
>   							fi_key.offset - offset);
>
> -		ret = btrfs_search_slot(NULL, gfs_info->extent_root,
> -					&dbref_key, &path, 0, 0);
> +		extent_root = btrfs_extent_root(gfs_info, dbref_key.objectid);
> +		ret = btrfs_search_slot(NULL, extent_root, &dbref_key, &path, 0,
> +					0);
>   		if (!ret) {
>   			found_dbackref = 1;
>   			goto out;
> @@ -3516,8 +3521,8 @@ static int check_extent_data_item(struct btrfs_root *root,
>   		dbref_key.type = BTRFS_SHARED_DATA_REF_KEY;
>   		dbref_key.offset = eb->start;
>
> -		ret = btrfs_search_slot(NULL, gfs_info->extent_root,
> -					&dbref_key, &path, 0, 0);
> +		ret = btrfs_search_slot(NULL, extent_root, &dbref_key, &path, 0,
> +					0);
>   		if (!ret) {
>   			found_dbackref = 1;
>   			goto out;
> @@ -3542,7 +3547,7 @@ out:
>    */
>   static int check_block_group_item(struct extent_buffer *eb, int slot)
>   {
> -	struct btrfs_root *extent_root = gfs_info->extent_root;
> +	struct btrfs_root *extent_root;
>   	struct btrfs_root *chunk_root = gfs_info->chunk_root;
>   	struct btrfs_block_group_item *bi;
>   	struct btrfs_block_group_item bg_item;
> @@ -3598,6 +3603,7 @@ static int check_block_group_item(struct extent_buffer *eb, int slot)
>   	extent_key.offset = 0;
>
>   	btrfs_init_path(&path);
> +	extent_root = btrfs_extent_root(gfs_info, extent_key.objectid);
>   	ret = btrfs_search_slot(NULL, extent_root, &extent_key, &path, 0, 0);
>   	if (ret < 0)
>   		goto out;
> @@ -3673,6 +3679,7 @@ out:
>    */
>   static int query_tree_block_level(u64 bytenr)
>   {
> +	struct btrfs_root *extent_root;
>   	struct extent_buffer *eb;
>   	struct btrfs_path path;
>   	struct btrfs_key key;
> @@ -3689,10 +3696,12 @@ static int query_tree_block_level(u64 bytenr)
>   	key.offset = (u64)-1;
>
>   	btrfs_init_path(&path);
> -	ret = btrfs_search_slot(NULL, gfs_info->extent_root, &key, &path, 0, 0);
> +
> +	extent_root = btrfs_extent_root(gfs_info, bytenr);
> +	ret = btrfs_search_slot(NULL, extent_root, &key, &path, 0, 0);
>   	if (ret < 0)
>   		goto release_out;
> -	ret = btrfs_previous_extent_item(gfs_info->extent_root, &path, bytenr);
> +	ret = btrfs_previous_extent_item(extent_root, &path, bytenr);
>   	if (ret < 0)
>   		goto release_out;
>   	if (ret > 0) {
> @@ -3920,7 +3929,7 @@ static int check_extent_data_backref(u64 root_id, u64 objectid, u64 offset,
>   				     u64 bytenr, u64 len, u32 count)
>   {
>   	struct btrfs_root *root;
> -	struct btrfs_root *extent_root = gfs_info->extent_root;
> +	struct btrfs_root *extent_root;
>   	struct btrfs_key key;
>   	struct btrfs_path path;
>   	struct extent_buffer *leaf;
> @@ -3935,6 +3944,7 @@ static int check_extent_data_backref(u64 root_id, u64 objectid, u64 offset,
>   		key.offset = (u64)-1;
>
>   		btrfs_init_path(&path);
> +		extent_root = btrfs_extent_root(gfs_info, bytenr);
>   		ret = btrfs_search_slot(NULL, extent_root, &key, &path, 0, 0);
>   		if (ret < 0)
>   			goto out;
> @@ -4084,13 +4094,13 @@ out:
>    * Returns >0   the backref was deleted but extent still exists
>    * Returns =0   the whole extent item was deleted
>    */
> -static int repair_extent_item(struct btrfs_root *root, struct btrfs_path *path,
> -		      u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid,
> -		      u64 owner, u64 offset)
> +static int repair_extent_item(struct btrfs_path *path, u64 bytenr, u64
> +			      num_bytes, u64 parent, u64 root_objectid, u64
> +			      owner, u64 offset)
>   {
>   	struct btrfs_trans_handle *trans;
> -	struct btrfs_root *extent_root = gfs_info->extent_root;
>   	struct btrfs_key old_key;
> +	struct btrfs_root *extent_root = btrfs_extent_root(gfs_info, bytenr);
>   	int ret;
>
>   	btrfs_item_key_to_cpu(path->nodes[0], &old_key, path->slots[0]);
> @@ -4121,7 +4131,7 @@ static int repair_extent_item(struct btrfs_root *root, struct btrfs_path *path,
>   	btrfs_commit_transaction(trans, extent_root);
>
>   	btrfs_release_path(path);
> -	ret = btrfs_search_slot(NULL, root, &old_key, path, 0, 0);
> +	ret = btrfs_search_slot(NULL, extent_root, &old_key, path, 0, 0);
>   	if (ret > 0) {
>   		/* odd, there must be one block group before at least */
>   		if (path->slots[0] == 0) {
> @@ -4159,7 +4169,7 @@ static int repair_extent_item_generation(struct btrfs_path *path)
>   	struct btrfs_trans_handle *trans;
>   	struct btrfs_key key;
>   	struct btrfs_extent_item *ei;
> -	struct btrfs_root *extent_root = gfs_info->extent_root;
> +	struct btrfs_root *extent_root;
>   	u64 new_gen = 0;;
>   	int ret;
>
> @@ -4172,6 +4182,7 @@ static int repair_extent_item_generation(struct btrfs_path *path)
>   	if (ret)
>   		return ret;
>   	btrfs_release_path(path);
> +	extent_root = btrfs_extent_root(gfs_info, key.objectid);
>   	trans = btrfs_start_transaction(extent_root, 1);
>   	if (IS_ERR(trans)) {
>   		ret = PTR_ERR(trans);
> @@ -4349,9 +4360,8 @@ next:
>
>   	if ((tmp_err & (REFERENCER_MISSING | REFERENCER_MISMATCH))
>   	    && repair) {
> -		ret = repair_extent_item(gfs_info->extent_root, path,
> -			 key.objectid, num_bytes, parent, root_objectid,
> -			 owner, owner_offset);
> +		ret = repair_extent_item(path, key.objectid, num_bytes, parent,
> +					 root_objectid, owner, owner_offset);
>   		if (ret < 0) {
>   			err |= tmp_err;
>   			err |= FATAL_ERROR;
> @@ -4581,6 +4591,7 @@ next:
>   static int find_block_group_item(struct btrfs_path *path, u64 bytenr, u64 len,
>   				 u64 type)
>   {
> +	struct btrfs_root *root = btrfs_extent_root(gfs_info, 0);
>   	struct btrfs_block_group_item bgi;
>   	struct btrfs_key key;
>   	int ret;
> @@ -4589,7 +4600,7 @@ static int find_block_group_item(struct btrfs_path *path, u64 bytenr, u64 len,
>   	key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
>   	key.offset = len;
>
> -	ret = btrfs_search_slot(NULL, gfs_info->extent_root, &key, path, 0, 0);
> +	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
>   	if (ret < 0)
>   		return ret;
>   	if (ret > 0) {
> @@ -4705,7 +4716,7 @@ static int repair_chunk_item(struct btrfs_root *chunk_root,
>   	struct btrfs_chunk *chunk;
>   	struct btrfs_key chunk_key;
>   	struct extent_buffer *eb = path->nodes[0];
> -	struct btrfs_root *extent_root = gfs_info->extent_root;
> +	struct btrfs_root *extent_root;
>   	struct btrfs_trans_handle *trans;
>   	u64 length;
>   	int slot = path->slots[0];
> @@ -4715,6 +4726,7 @@ static int repair_chunk_item(struct btrfs_root *chunk_root,
>   	btrfs_item_key_to_cpu(eb, &chunk_key, slot);
>   	if (chunk_key.type != BTRFS_CHUNK_ITEM_KEY)
>   		return err;
> +	extent_root = btrfs_extent_root(gfs_info, chunk_key.offset);
>   	chunk = btrfs_item_ptr(eb, slot, struct btrfs_chunk);
>   	type = btrfs_chunk_type(path->nodes[0], chunk);
>   	length = btrfs_chunk_length(eb, chunk);
> diff --git a/check/qgroup-verify.c b/check/qgroup-verify.c
> index a514fee1..0813b841 100644
> --- a/check/qgroup-verify.c
> +++ b/check/qgroup-verify.c
> @@ -1157,7 +1157,7 @@ static int scan_extents(struct btrfs_fs_info *info,
>   			u64 start, u64 end)
>   {
>   	int ret, i, nr, level;
> -	struct btrfs_root *root = info->extent_root;
> +	struct btrfs_root *root = btrfs_extent_root(info, start);
>   	struct btrfs_key key;
>   	struct btrfs_path path;
>   	struct btrfs_disk_key disk_key;
> diff --git a/cmds/rescue-chunk-recover.c b/cmds/rescue-chunk-recover.c
> index 115d91d7..3bf9c36c 100644
> --- a/cmds/rescue-chunk-recover.c
> +++ b/cmds/rescue-chunk-recover.c
> @@ -555,6 +555,7 @@ static int check_chunk_by_metadata(struct recover_control *rc,
>   				   struct btrfs_root *root,
>   				   struct chunk_record *chunk, int bg_only)
>   {
> +	struct btrfs_fs_info *fs_info = root->fs_info;
>   	int ret;
>   	int i;
>   	int slot;
> @@ -616,7 +617,8 @@ bg_check:
>   	key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
>   	key.offset = chunk->length;
>
> -	ret = btrfs_search_slot(NULL, root->fs_info->extent_root, &key, &path,
> +	root = btrfs_extent_root(fs_info, key.objectid);
> +	ret = btrfs_search_slot(NULL, root, &key, &path,
>   				0, 0);
>   	if (ret < 0) {
>   		fprintf(stderr, "Search block group failed(%d)\n", ret);
> @@ -997,7 +999,7 @@ static int block_group_remove_all_extent_items(struct btrfs_trans_handle *trans,
>   	int del_s, del_nr;
>
>   	btrfs_init_path(&path);
> -	root = root->fs_info->extent_root;
> +	root = btrfs_extent_root(fs_info, start);
>
>   	key.objectid = start;
>   	key.offset = 0;
> @@ -1382,6 +1384,7 @@ static int rebuild_block_group(struct btrfs_trans_handle *trans,
>   			       struct recover_control *rc,
>   			       struct btrfs_root *root)
>   {
> +	struct btrfs_fs_info *fs_info = root->fs_info;
>   	struct chunk_record *chunk_rec;
>   	struct btrfs_key search_key;
>   	struct btrfs_path path;
> @@ -1396,12 +1399,11 @@ static int rebuild_block_group(struct btrfs_trans_handle *trans,
>   		search_key.objectid = chunk_rec->offset;
>   		search_key.type = BTRFS_EXTENT_ITEM_KEY;
>   		search_key.offset = 0;
> -		ret = btrfs_search_slot(NULL, root->fs_info->extent_root,
> -					&search_key, &path, 0, 0);
> +		root = btrfs_extent_root(fs_info, chunk_rec->offset);
> +		ret = btrfs_search_slot(NULL, root, &search_key, &path, 0, 0);
>   		if (ret < 0)
>   			goto out;
> -		ret = calculate_bg_used(root->fs_info->extent_root,
> -					chunk_rec, &path, &used);
> +		ret = calculate_bg_used(root, chunk_rec, &path, &used);
>   		/*
>   		 * Extent tree is damaged, better to rebuild the whole extent
>   		 * tree. Currently, change the used to chunk's len to prevent
> @@ -1417,9 +1419,7 @@ static int rebuild_block_group(struct btrfs_trans_handle *trans,
>   			used = chunk_rec->length;
>   		}
>   		btrfs_release_path(&path);
> -		ret = __insert_block_group(trans, chunk_rec,
> -					   root->fs_info->extent_root,
> -					   used);
> +		ret = __insert_block_group(trans, chunk_rec, root, used);
>   		if (ret < 0)
>   			goto out;
>   	}
> diff --git a/common/repair.c b/common/repair.c
> index 413c3e86..c8624eaa 100644
> --- a/common/repair.c
> +++ b/common/repair.c
> @@ -168,7 +168,7 @@ int btrfs_fix_block_accounting(struct btrfs_trans_handle *trans)
>   	struct extent_buffer *leaf;
>   	struct btrfs_block_group *cache;
>   	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, 0);
>
>   	ret = btrfs_run_delayed_refs(trans, -1);
>   	if (ret)
> @@ -190,8 +190,7 @@ int btrfs_fix_block_accounting(struct btrfs_trans_handle *trans)
>   	key.offset = 0;
>   	key.objectid = 0;
>   	key.type = BTRFS_EXTENT_ITEM_KEY;
> -	ret = btrfs_search_slot(trans, root->fs_info->extent_root,
> -				&key, &path, 0, 0);
> +	ret = btrfs_search_slot(trans, root, &key, &path, 0, 0);
>   	if (ret < 0)
>   		return ret;
>   	while(1) {
> diff --git a/convert/main.c b/convert/main.c
> index 7f33d4e1..0fae4e98 100644
> --- a/convert/main.c
> +++ b/convert/main.c
> @@ -944,7 +944,6 @@ static int make_convert_data_block_groups(struct btrfs_trans_handle *trans,
>   					  struct btrfs_mkfs_config *cfg,
>   					  struct btrfs_convert_context *cctx)
>   {
> -	struct btrfs_root *extent_root = fs_info->extent_root;
>   	struct cache_tree *data_chunks = &cctx->data_chunks;
>   	struct cache_extent *cache;
>   	u64 max_chunk_size;
> @@ -956,8 +955,7 @@ static int make_convert_data_block_groups(struct btrfs_trans_handle *trans,
>   	 */
>   	max_chunk_size = cfg->num_bytes / 10;
>   	max_chunk_size = min((u64)(SZ_1G), max_chunk_size);
> -	max_chunk_size = round_down(max_chunk_size,
> -				    extent_root->fs_info->sectorsize);
> +	max_chunk_size = round_down(max_chunk_size, fs_info->sectorsize);
>
>   	for (cache = first_cache_extent(data_chunks); cache;
>   	     cache = next_cache_extent(cache)) {
> diff --git a/image/main.c b/image/main.c
> index 57e0cb6c..ab57ce4e 100644
> --- a/image/main.c
> +++ b/image/main.c
> @@ -922,7 +922,7 @@ static int copy_from_extent_tree(struct metadump_struct *metadump,
>   	u64 num_bytes;
>   	int ret;
>
> -	extent_root = metadump->root->fs_info->extent_root;
> +	extent_root = btrfs_extent_root(metadump->root->fs_info, 0);
>   	bytenr = BTRFS_SUPER_INFO_OFFSET + BTRFS_SUPER_INFO_SIZE;
>   	key.objectid = bytenr;
>   	key.type = BTRFS_EXTENT_ITEM_KEY;
> diff --git a/kernel-shared/backref.c b/kernel-shared/backref.c
> index c04d505e..42832c48 100644
> --- a/kernel-shared/backref.c
> +++ b/kernel-shared/backref.c
> @@ -645,7 +645,7 @@ static int __add_keyed_refs(struct btrfs_fs_info *fs_info,
>   			    struct btrfs_path *path, u64 bytenr,
>   			    int info_level)
>   {
> -	struct btrfs_root *extent_root = fs_info->extent_root;
> +	struct btrfs_root *extent_root = btrfs_extent_root(fs_info, bytenr);
>   	int ret;
>   	int slot;
>   	struct extent_buffer *leaf;
> @@ -734,6 +734,7 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
>   			     u64 time_seq, struct ulist *refs,
>   			     struct ulist *roots, const u64 *extent_item_pos)
>   {
> +	struct btrfs_root *extent_root = btrfs_extent_root(fs_info, bytenr);
>   	struct btrfs_key key;
>   	struct btrfs_path *path;
>   	int info_level = 0;
> @@ -756,7 +757,7 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
>   	if (!path)
>   		return -ENOMEM;
>
> -	ret = btrfs_search_slot(trans, fs_info->extent_root, &key, path, 0, 0);
> +	ret = btrfs_search_slot(trans, extent_root, &key, path, 0, 0);
>   	if (ret < 0)
>   		goto out;
>   	BUG_ON(ret == 0);
> @@ -1136,6 +1137,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;
> @@ -1151,11 +1153,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;
> diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h
> index d2d1a006..23750156 100644
> --- a/kernel-shared/ctree.h
> +++ b/kernel-shared/ctree.h
> @@ -1157,7 +1157,7 @@ struct btrfs_fs_info {
>   	u8 chunk_tree_uuid[BTRFS_UUID_SIZE];
>   	u8 *new_chunk_tree_uuid;
>   	struct btrfs_root *fs_root;
> -	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/kernel-shared/disk-io.c b/kernel-shared/disk-io.c
> index c1d55692..b4c45719 100644
> --- a/kernel-shared/disk-io.c
> +++ b/kernel-shared/disk-io.c
> @@ -750,6 +750,12 @@ struct btrfs_root *btrfs_csum_root(struct btrfs_fs_info *fs_info,
>   	return fs_info->_csum_root;
>   }
>
> +struct btrfs_root *btrfs_extent_root(struct btrfs_fs_info *fs_info,
> +				     u64 bytenr)
> +{
> +	return fs_info->_extent_root;
> +}
> +
>   struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
>   				      struct btrfs_key *location)
>   {
> @@ -761,7 +767,7 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
>   	if (location->objectid == BTRFS_ROOT_TREE_OBJECTID)
>   		return fs_info->tree_root;
>   	if (location->objectid == BTRFS_EXTENT_TREE_OBJECTID)
> -		return fs_info->extent_root;
> +		return fs_info->_extent_root;
>   	if (location->objectid == BTRFS_CHUNK_TREE_OBJECTID)
>   		return fs_info->chunk_root;
>   	if (location->objectid == BTRFS_DEV_TREE_OBJECTID)
> @@ -800,7 +806,7 @@ void btrfs_free_fs_info(struct btrfs_fs_info *fs_info)
>   		free(fs_info->quota_root);
>
>   	free(fs_info->tree_root);
> -	free(fs_info->extent_root);
> +	free(fs_info->_extent_root);
>   	free(fs_info->chunk_root);
>   	free(fs_info->dev_root);
>   	free(fs_info->_csum_root);
> @@ -820,7 +826,7 @@ struct btrfs_fs_info *btrfs_new_fs_info(int writable, u64 sb_bytenr)
>   		return NULL;
>
>   	fs_info->tree_root = calloc(1, sizeof(struct btrfs_root));
> -	fs_info->extent_root = calloc(1, sizeof(struct btrfs_root));
> +	fs_info->_extent_root = calloc(1, sizeof(struct btrfs_root));
>   	fs_info->chunk_root = calloc(1, sizeof(struct btrfs_root));
>   	fs_info->dev_root = calloc(1, sizeof(struct btrfs_root));
>   	fs_info->_csum_root = calloc(1, sizeof(struct btrfs_root));
> @@ -829,7 +835,7 @@ struct btrfs_fs_info *btrfs_new_fs_info(int writable, u64 sb_bytenr)
>   	fs_info->uuid_root = calloc(1, sizeof(struct btrfs_root));
>   	fs_info->super_copy = calloc(1, BTRFS_SUPER_INFO_SIZE);
>
> -	if (!fs_info->tree_root || !fs_info->extent_root ||
> +	if (!fs_info->tree_root || !fs_info->_extent_root ||
>   	    !fs_info->chunk_root || !fs_info->dev_root ||
>   	    !fs_info->_csum_root || !fs_info->quota_root ||
>   	    !fs_info->free_space_root || !fs_info->uuid_root ||
> @@ -985,11 +991,11 @@ int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info, u64 root_tree_bytenr,
>   		return -EIO;
>   	}
>
> -	ret = setup_root_or_create_block(fs_info, flags, fs_info->extent_root,
> +	ret = setup_root_or_create_block(fs_info, flags, fs_info->_extent_root,
>   					 BTRFS_EXTENT_TREE_OBJECTID, "extent");
>   	if (ret)
>   		return ret;
> -	fs_info->extent_root->track_dirty = 1;
> +	fs_info->_extent_root->track_dirty = 1;
>
>   	ret = find_and_setup_root(root, fs_info, BTRFS_DEV_TREE_OBJECTID,
>   				  fs_info->dev_root);
> @@ -1047,7 +1053,7 @@ int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info, u64 root_tree_bytenr,
>
>   	fs_info->generation = generation;
>   	fs_info->last_trans_committed = generation;
> -	if (extent_buffer_uptodate(fs_info->extent_root->node) &&
> +	if (extent_buffer_uptodate(fs_info->_extent_root->node) &&
>   	    !(flags & OPEN_CTREE_NO_BLOCK_GROUPS)) {
>   		ret = btrfs_read_block_groups(fs_info);
>   		/*
> @@ -1082,8 +1088,8 @@ void btrfs_release_all_roots(struct btrfs_fs_info *fs_info)
>   		free_extent_buffer(fs_info->_csum_root->node);
>   	if (fs_info->dev_root)
>   		free_extent_buffer(fs_info->dev_root->node);
> -	if (fs_info->extent_root)
> -		free_extent_buffer(fs_info->extent_root->node);
> +	if (fs_info->_extent_root)
> +		free_extent_buffer(fs_info->_extent_root->node);
>   	if (fs_info->tree_root)
>   		free_extent_buffer(fs_info->tree_root->node);
>   	if (fs_info->log_root_tree)
> @@ -1836,11 +1842,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, info->_extent_root->node->start);
>   	btrfs_set_backup_extent_root_gen(root_backup,
> -			       btrfs_header_generation(info->extent_root->node));
> +			       btrfs_header_generation(info->_extent_root->node));
>   	btrfs_set_backup_extent_root_level(root_backup,
> -			       btrfs_header_level(info->extent_root->node));
> +			       btrfs_header_level(info->_extent_root->node));
>   	/*
>   	 * we might commit during log recovery, which happens before we set
>   	 * the fs_root.  Make sure it is valid before we fill it in.
> diff --git a/kernel-shared/disk-io.h b/kernel-shared/disk-io.h
> index 38abbca5..dc71cc2b 100644
> --- a/kernel-shared/disk-io.h
> +++ b/kernel-shared/disk-io.h
> @@ -218,4 +218,5 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans,
>   				     struct btrfs_fs_info *fs_info,
>   				     u64 objectid);
>   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_inf, u64 bytenr);
>   #endif
> diff --git a/kernel-shared/extent-tree.c b/kernel-shared/extent-tree.c
> index 402904d1..3713452b 100644
> --- a/kernel-shared/extent-tree.c
> +++ b/kernel-shared/extent-tree.c
> @@ -96,7 +96,7 @@ static int cache_block_group(struct btrfs_root *root,
>   	if (!block_group)
>   		return 0;
>
> -	root = root->fs_info->extent_root;
> +	root = btrfs_extent_root(root->fs_info, 0);
>   	free_space_cache = &root->fs_info->free_space_cache;
>
>   	if (block_group->cached)
> @@ -1243,6 +1243,8 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
>   			 u64 bytenr, u64 num_bytes, u64 parent,
>   			 u64 root_objectid, u64 owner, u64 offset)
>   {
> +	struct btrfs_root *extent_root = btrfs_extent_root(root->fs_info,
> +							   bytenr);
>   	struct btrfs_path *path;
>   	struct extent_buffer *leaf;
>   	struct btrfs_extent_item *item;
> @@ -1254,9 +1256,9 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
>   	if (!path)
>   		return -ENOMEM;
>
> -	ret = insert_inline_extent_backref(trans, root->fs_info->extent_root,
> -					   path, bytenr, num_bytes, parent,
> -					   root_objectid, owner, offset, 1);
> +	ret = insert_inline_extent_backref(trans, extent_root, path, bytenr,
> +					   num_bytes, parent, root_objectid,
> +					   owner, offset, 1);
>   	if (ret == 0)
>   		goto out;
>
> @@ -1274,9 +1276,8 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
>   	btrfs_release_path(path);
>
>   	/* now insert the actual backref */
> -	ret = insert_extent_backref(trans, root->fs_info->extent_root,
> -				    path, bytenr, parent, root_objectid,
> -				    owner, offset, 1);
> +	ret = insert_extent_backref(trans, extent_root, path, bytenr, parent,
> +				    root_objectid, owner, offset, 1);
>   	if (ret)
>   		err = ret;
>   out:
> @@ -1289,6 +1290,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 = btrfs_extent_root(fs_info, bytenr);
>   	struct btrfs_path *path;
>   	int ret;
>   	struct btrfs_key key;
> @@ -1315,7 +1317,7 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
>   		key.type = BTRFS_EXTENT_ITEM_KEY;
>
>   again:
> -	ret = btrfs_search_slot(trans, fs_info->extent_root, &key, path, 0, 0);
> +	ret = btrfs_search_slot(trans, extent_root, &key, path, 0, 0);
>   	if (ret < 0)
>   		goto out;
>
> @@ -1374,6 +1376,7 @@ int btrfs_set_block_flags(struct btrfs_trans_handle *trans, u64 bytenr,
>   			  int level, u64 flags)
>   {
>   	struct btrfs_fs_info *fs_info = trans->fs_info;
> +	struct btrfs_root *extent_root = btrfs_extent_root(fs_info, bytenr);
>   	struct btrfs_path *path;
>   	int ret;
>   	struct btrfs_key key;
> @@ -1396,7 +1399,7 @@ int btrfs_set_block_flags(struct btrfs_trans_handle *trans, u64 bytenr,
>   	}
>
>   again:
> -	ret = btrfs_search_slot(trans, fs_info->extent_root, &key, path, 0, 0);
> +	ret = btrfs_search_slot(trans, extent_root, &key, path, 0, 0);
>   	if (ret < 0)
>   		goto out;
>
> @@ -1537,7 +1540,7 @@ static int update_block_group_item(struct btrfs_trans_handle *trans,
>   {
>   	int ret;
>   	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, 0);
>   	unsigned long bi;
>   	struct btrfs_block_group_item bgi;
>   	struct extent_buffer *leaf;
> @@ -1911,9 +1914,10 @@ static int __free_extent(struct btrfs_trans_handle *trans,
>   			 u64 owner_offset, int refs_to_drop)
>   {
>
> +	struct btrfs_root *extent_root = btrfs_extent_root(trans->fs_info,
> +							   bytenr);
>   	struct btrfs_key key;
>   	struct btrfs_path *path;
> -	struct btrfs_root *extent_root = trans->fs_info->extent_root;
>   	struct extent_buffer *leaf;
>   	struct btrfs_extent_item *ei;
>   	struct btrfs_extent_inline_ref *iref;
> @@ -2181,7 +2185,7 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans,
>   {
>   	int ret;
>   	u64 orig_search_start = search_start;
> -	struct btrfs_root * root = orig_root->fs_info->extent_root;
> +	struct btrfs_root *root = orig_root->fs_info->tree_root;
>   	struct btrfs_fs_info *info = root->fs_info;
>   	u64 total_needed = num_bytes;
>   	struct btrfs_block_group *block_group;
> @@ -2363,6 +2367,8 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
>   				      struct btrfs_delayed_extent_op *extent_op)
>   {
>
> +	struct btrfs_root *extent_root = btrfs_extent_root(trans->fs_info,
> +							   node->bytenr);
>   	struct btrfs_delayed_tree_ref *ref = btrfs_delayed_node_to_tree_ref(node);
>   	bool skinny_metadata = btrfs_fs_incompat(trans->fs_info, SKINNY_METADATA);
>   	struct btrfs_fs_info *fs_info = trans->fs_info;
> @@ -2403,8 +2409,7 @@ 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,
> -				      &ins, size);
> +	ret = btrfs_insert_empty_item(trans, extent_root, path, &ins, size);
>   	if (ret)
>   		return ret;
>
> @@ -2726,7 +2731,7 @@ int btrfs_read_block_groups(struct btrfs_fs_info *fs_info)
>   	int ret;
>   	struct btrfs_key key;
>
> -	root = fs_info->extent_root;
> +	root = btrfs_extent_root(fs_info, 0);
>   	key.objectid = 0;
>   	key.offset = 0;
>   	key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
> @@ -2807,7 +2812,7 @@ static int insert_block_group_item(struct btrfs_trans_handle *trans,
>   	key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
>   	key.offset = block_group->length;
>
> -	root = fs_info->extent_root;
> +	root = btrfs_extent_root(fs_info, 0);
>   	return btrfs_insert_item(trans, root, &key, &bgi, sizeof(bgi));
>   }
>
> @@ -2924,7 +2929,7 @@ static int remove_block_group_item(struct btrfs_trans_handle *trans,
>   {
>   	struct btrfs_fs_info *fs_info = trans->fs_info;
>   	struct btrfs_key key;
> -	struct btrfs_root *root = fs_info->extent_root;
> +	struct btrfs_root *root = btrfs_extent_root(fs_info, 0);
>   	int ret = 0;
>
>   	key.objectid = block_group->start;
> @@ -3247,7 +3252,6 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
>   	return ret;
>   }
>
> -
>   static void __get_extent_size(struct btrfs_root *root, struct btrfs_path *path,
>   			      u64 *start, u64 *len)
>   {
> @@ -3319,7 +3323,7 @@ static int __btrfs_record_file_extent(struct btrfs_trans_handle *trans,
>   {
>   	int ret;
>   	struct btrfs_fs_info *info = root->fs_info;
> -	struct btrfs_root *extent_root = info->extent_root;
> +	struct btrfs_root *extent_root = btrfs_extent_root(info, disk_bytenr);
>   	struct extent_buffer *leaf;
>   	struct btrfs_file_extent_item *fi;
>   	struct btrfs_key ins_key;
> diff --git a/kernel-shared/free-space-tree.c b/kernel-shared/free-space-tree.c
> index 83a8520d..0434733d 100644
> --- a/kernel-shared/free-space-tree.c
> +++ b/kernel-shared/free-space-tree.c
> @@ -1014,12 +1014,18 @@ out:
>   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_fs_info *fs_info = trans->fs_info;
> +	struct btrfs_root *extent_root;
>   	struct btrfs_path *path, *path2;
>   	struct btrfs_key key;
>   	u64 start, end;
>   	int ret;
>
> +	if (btrfs_fs_incompat(fs_info, EXTENT_TREE_V2))
> +		return -EINVAL;
> +
> +	extent_root = btrfs_extent_root(fs_info, 0);
> +
>   	path = btrfs_alloc_path();
>   	if (!path)
>   		return -ENOMEM;
> diff --git a/kernel-shared/volumes.c b/kernel-shared/volumes.c
> index 7d6fe8fd..4092c067 100644
> --- a/kernel-shared/volumes.c
> +++ b/kernel-shared/volumes.c
> @@ -1348,7 +1348,6 @@ static int create_chunk(struct btrfs_trans_handle *trans,
>   			struct btrfs_fs_info *info, struct alloc_chunk_ctl *ctl,
>   			struct list_head *private_devs)
>   {
> -	struct btrfs_root *extent_root = info->extent_root;
>   	struct btrfs_root *chunk_root = info->chunk_root;
>   	struct btrfs_stripe *stripes;
>   	struct btrfs_device *device = NULL;
> @@ -1432,7 +1431,7 @@ static int create_chunk(struct btrfs_trans_handle *trans,
>
>   	/* key was set above */
>   	btrfs_set_stack_chunk_length(chunk, ctl->num_bytes);
> -	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, BTRFS_STRIPE_LEN);
>   	btrfs_set_stack_chunk_type(chunk, ctl->type);
>   	btrfs_set_stack_chunk_num_stripes(chunk, ctl->num_stripes);
> diff --git a/kernel-shared/zoned.c b/kernel-shared/zoned.c
> index 776576bc..0164fe9f 100644
> --- a/kernel-shared/zoned.c
> +++ b/kernel-shared/zoned.c
> @@ -757,7 +757,7 @@ static int calculate_alloc_pointer(struct btrfs_fs_info *fs_info,
>   				   struct btrfs_block_group *cache,
>   				   u64 *offset_ret)
>   {
> -	struct btrfs_root *root = fs_info->extent_root;
> +	struct btrfs_root *root = btrfs_extent_root(fs_info, cache->start);
>   	struct btrfs_path *path;
>   	struct btrfs_key key;
>   	struct btrfs_key found_key;
> diff --git a/mkfs/main.c b/mkfs/main.c
> index c6cc51e9..9647f12a 100644
> --- a/mkfs/main.c
> +++ b/mkfs/main.c
> @@ -277,7 +277,7 @@ static int recow_roots(struct btrfs_trans_handle *trans,
>   	ret = __recow_root(trans, info->tree_root);
>   	if (ret)
>   		return ret;
> -	ret = __recow_root(trans, info->extent_root);
> +	ret = __recow_root(trans, info->_extent_root);
>   	if (ret)
>   		return ret;
>   	ret = __recow_root(trans, info->chunk_root);
> @@ -588,7 +588,7 @@ static int cleanup_temp_chunks(struct btrfs_fs_info *fs_info,
>   {
>   	struct btrfs_trans_handle *trans = NULL;
>   	struct btrfs_block_group_item *bgi;
> -	struct btrfs_root *root = fs_info->extent_root;
> +	struct btrfs_root *root = btrfs_extent_root(fs_info, 0);
>   	struct btrfs_key key;
>   	struct btrfs_key found_key;
>   	struct btrfs_path path;
>

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

* Re: [PATCH 14/20] btrfs-progs: stop accessing ->free_space_root directly
  2021-11-05 20:28 ` [PATCH 14/20] btrfs-progs: stop accessing ->free_space_root directly Josef Bacik
@ 2021-11-06  0:44   ` Qu Wenruo
  0 siblings, 0 replies; 42+ messages in thread
From: Qu Wenruo @ 2021-11-06  0:44 UTC (permalink / raw)
  To: Josef Bacik, linux-btrfs, kernel-team



On 2021/11/6 04:28, Josef Bacik wrote:
> We're going to have multiple free space roots in the future, so access
> it via a helper in most cases.  We will address the remaining direct
> accesses in future patches.
>
> Signed-off-by: Josef Bacik <josef@toxicpanda.com>

This is much better, there is no more place holder for
btrfs_free_pace_root() parameters.

But still, I'd prefer it to be in the extent-tree-v2 patchset other than
a dedicated preparation.

Thanks,
Qu
> ---
>   kernel-shared/ctree.h           |  2 +-
>   kernel-shared/disk-io.c         | 24 ++++++++++-----------
>   kernel-shared/free-space-tree.c | 37 +++++++++++++++++++++------------
>   mkfs/main.c                     |  4 ++--
>   4 files changed, 39 insertions(+), 28 deletions(-)
>
> diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h
> index 23750156..c263a3bb 100644
> --- a/kernel-shared/ctree.h
> +++ b/kernel-shared/ctree.h
> @@ -1163,7 +1163,7 @@ struct btrfs_fs_info {
>   	struct btrfs_root *dev_root;
>   	struct btrfs_root *_csum_root;
>   	struct btrfs_root *quota_root;
> -	struct btrfs_root *free_space_root;
> +	struct btrfs_root *_free_space_root;
>   	struct btrfs_root *uuid_root;
>
>   	struct rb_root fs_root_tree;
> diff --git a/kernel-shared/disk-io.c b/kernel-shared/disk-io.c
> index b4c45719..0e803db8 100644
> --- a/kernel-shared/disk-io.c
> +++ b/kernel-shared/disk-io.c
> @@ -780,7 +780,7 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
>   		return fs_info->quota_enabled ? fs_info->quota_root :
>   				ERR_PTR(-ENOENT);
>   	if (location->objectid == BTRFS_FREE_SPACE_TREE_OBJECTID)
> -		return fs_info->free_space_root ? fs_info->free_space_root :
> +		return fs_info->_free_space_root ? fs_info->_free_space_root :
>   						ERR_PTR(-ENOENT);
>
>   	BUG_ON(location->objectid == BTRFS_TREE_RELOC_OBJECTID);
> @@ -810,7 +810,7 @@ void btrfs_free_fs_info(struct btrfs_fs_info *fs_info)
>   	free(fs_info->chunk_root);
>   	free(fs_info->dev_root);
>   	free(fs_info->_csum_root);
> -	free(fs_info->free_space_root);
> +	free(fs_info->_free_space_root);
>   	free(fs_info->uuid_root);
>   	free(fs_info->super_copy);
>   	free(fs_info->log_root_tree);
> @@ -831,14 +831,14 @@ struct btrfs_fs_info *btrfs_new_fs_info(int writable, u64 sb_bytenr)
>   	fs_info->dev_root = calloc(1, sizeof(struct btrfs_root));
>   	fs_info->_csum_root = calloc(1, sizeof(struct btrfs_root));
>   	fs_info->quota_root = calloc(1, sizeof(struct btrfs_root));
> -	fs_info->free_space_root = calloc(1, sizeof(struct btrfs_root));
> +	fs_info->_free_space_root = calloc(1, sizeof(struct btrfs_root));
>   	fs_info->uuid_root = calloc(1, sizeof(struct btrfs_root));
>   	fs_info->super_copy = calloc(1, BTRFS_SUPER_INFO_SIZE);
>
>   	if (!fs_info->tree_root || !fs_info->_extent_root ||
>   	    !fs_info->chunk_root || !fs_info->dev_root ||
>   	    !fs_info->_csum_root || !fs_info->quota_root ||
> -	    !fs_info->free_space_root || !fs_info->uuid_root ||
> +	    !fs_info->_free_space_root || !fs_info->uuid_root ||
>   	    !fs_info->super_copy)
>   		goto free_all;
>
> @@ -1031,17 +1031,17 @@ int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info, u64 root_tree_bytenr,
>
>   	if (btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) {
>   		ret = find_and_setup_root(root, fs_info, BTRFS_FREE_SPACE_TREE_OBJECTID,
> -					  fs_info->free_space_root);
> +					  fs_info->_free_space_root);
>   		if (ret) {
> -			free(fs_info->free_space_root);
> -			fs_info->free_space_root = NULL;
> +			free(fs_info->_free_space_root);
> +			fs_info->_free_space_root = NULL;
>   			printk("Couldn't read free space tree\n");
>   			return -EIO;
>   		}
> -		fs_info->free_space_root->track_dirty = 1;
> +		fs_info->_free_space_root->track_dirty = 1;
>   	} else {
> -		free(fs_info->free_space_root);
> -		fs_info->free_space_root = NULL;
> +		free(fs_info->_free_space_root);
> +		fs_info->_free_space_root = NULL;
>   	}
>
>   	ret = find_and_setup_log_root(root, fs_info, sb);
> @@ -1080,8 +1080,8 @@ int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info, u64 root_tree_bytenr,
>
>   void btrfs_release_all_roots(struct btrfs_fs_info *fs_info)
>   {
> -	if (fs_info->free_space_root)
> -		free_extent_buffer(fs_info->free_space_root->node);
> +	if (fs_info->_free_space_root)
> +		free_extent_buffer(fs_info->_free_space_root->node);
>   	if (fs_info->quota_root)
>   		free_extent_buffer(fs_info->quota_root->node);
>   	if (fs_info->_csum_root)
> diff --git a/kernel-shared/free-space-tree.c b/kernel-shared/free-space-tree.c
> index 0434733d..70b3d62a 100644
> --- a/kernel-shared/free-space-tree.c
> +++ b/kernel-shared/free-space-tree.c
> @@ -25,13 +25,19 @@
>   #include "kernel-lib/bitops.h"
>   #include "common/internal.h"
>
> +static struct btrfs_root *btrfs_free_space_root(struct btrfs_fs_info *fs_info,
> +						struct btrfs_block_group *block_group)
> +{
> +	return fs_info->_free_space_root;
> +}
> +
>   static struct btrfs_free_space_info *
>   search_free_space_info(struct btrfs_trans_handle *trans,
>   		       struct btrfs_fs_info *fs_info,
>   		       struct btrfs_block_group *block_group,
>   		       struct btrfs_path *path, int cow)
>   {
> -	struct btrfs_root *root = fs_info->free_space_root;
> +	struct btrfs_root *root = btrfs_free_space_root(fs_info, block_group);
>   	struct btrfs_key key;
>   	int ret;
>
> @@ -103,7 +109,8 @@ 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_fs_info *fs_info = trans->fs_info;
> +	struct btrfs_root *root = btrfs_free_space_root(fs_info, block_group);
>   	struct btrfs_free_space_info *info;
>   	struct btrfs_key key;
>   	struct extent_buffer *leaf;
> @@ -179,7 +186,7 @@ static 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(fs_info, block_group);
>   	struct btrfs_free_space_info *info;
>   	struct btrfs_key key, found_key;
>   	struct extent_buffer *leaf;
> @@ -318,7 +325,7 @@ static 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(fs_info, block_group);
>   	struct btrfs_free_space_info *info;
>   	struct btrfs_key key, found_key;
>   	struct extent_buffer *leaf;
> @@ -558,7 +565,8 @@ 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 = trans->fs_info->free_space_root;
> +	struct btrfs_fs_info *fs_info = trans->fs_info;
> +	struct btrfs_root *root = btrfs_free_space_root(fs_info, block_group);
>   	struct btrfs_key key;
>   	u64 end = start + size;
>   	u64 cur_start, cur_size;
> @@ -671,7 +679,8 @@ 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_fs_info *fs_info = trans->fs_info;
> +	struct btrfs_root *root = btrfs_free_space_root(fs_info, block_group);
>   	struct btrfs_key key;
>   	u64 found_start, found_end;
>   	u64 end = start + size;
> @@ -811,7 +820,8 @@ 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_fs_info *fs_info = trans->fs_info;
> +	struct btrfs_root *root = btrfs_free_space_root(fs_info, block_group);
>   	struct btrfs_key key, new_key;
>   	u64 found_start, found_end;
>   	u64 end = start + size;
> @@ -1107,7 +1117,8 @@ out:
>   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_fs_info *fs_info = trans->fs_info;
> +	struct btrfs_root *root = btrfs_free_space_root(fs_info, block_group);
>   	struct btrfs_path *path;
>   	struct btrfs_key key, found_key;
>   	struct extent_buffer *leaf;
> @@ -1215,7 +1226,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 = btrfs_free_space_root(fs_info, NULL);
>   	int ret;
>   	u64 features;
>
> @@ -1227,7 +1238,7 @@ int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info)
>   	features &= ~(BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID |
>   		      BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE);
>   	btrfs_set_super_compat_ro_flags(fs_info->super_copy, features);
> -	fs_info->free_space_root = NULL;
> +	fs_info->_free_space_root = NULL;
>
>   	ret = clear_free_space_tree(trans, free_space_root);
>   	if (ret)
> @@ -1263,7 +1274,7 @@ static int load_free_space_bitmaps(struct btrfs_fs_info *fs_info,
>   				   u32 expected_extent_count,
>   				   int *errors)
>   {
> -	struct btrfs_root *root = fs_info->free_space_root;
> +	struct btrfs_root *root = btrfs_free_space_root(fs_info, block_group);
>   	struct btrfs_key key;
>   	int prev_bit = 0, bit;
>   	u64 extent_start = 0;
> @@ -1343,7 +1354,7 @@ static int load_free_space_extents(struct btrfs_fs_info *fs_info,
>   				   u32 expected_extent_count,
>   				   int *errors)
>   {
> -	struct btrfs_root *root = fs_info->free_space_root;
> +	struct btrfs_root *root = btrfs_free_space_root(fs_info, block_group);
>   	struct btrfs_key key, prev_key;
>   	int have_prev = 0;
>   	u64 start, end;
> @@ -1463,7 +1474,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;
>   	add_root_to_dirty_list(free_space_root);
>
>   	do {
> diff --git a/mkfs/main.c b/mkfs/main.c
> index 9647f12a..16f9ba19 100644
> --- a/mkfs/main.c
> +++ b/mkfs/main.c
> @@ -289,8 +289,8 @@ static int recow_roots(struct btrfs_trans_handle *trans,
>   	ret = __recow_root(trans, csum_root);
>   	if (ret)
>   		return ret;
> -	if (info->free_space_root) {
> -		ret = __recow_root(trans, info->free_space_root);
> +	if (info->_free_space_root) {
> +		ret = __recow_root(trans, info->_free_space_root);
>   		if (ret)
>   			return ret;
>   	}
>

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

* Re: [PATCH 00/20] btrfs-progs: extent tree v2 global root support prep work
  2021-11-05 20:28 [PATCH 00/20] btrfs-progs: extent tree v2 global root support prep work Josef Bacik
                   ` (19 preceding siblings ...)
  2021-11-05 20:28 ` [PATCH 20/20] btrfs-progs: common: search all extent roots for marking used space Josef Bacik
@ 2021-11-06  0:55 ` Qu Wenruo
  2021-11-06 20:17   ` Josef Bacik
  20 siblings, 1 reply; 42+ messages in thread
From: Qu Wenruo @ 2021-11-06  0:55 UTC (permalink / raw)
  To: Josef Bacik, linux-btrfs, kernel-team



On 2021/11/6 04:28, Josef Bacik wrote:
> Hello,
>
> This is a series of patches to do all the prep work needed to support extent
> tree v2.  These patches are independent of the actual extent tree v2 support,
> some of them are fixes,

First half are mostly good, as they are really fixes and independent
refactors.

> some of them are purely to pave the way for the global
> root support.  These patches are mostly around stopping direct access of
> ->extent_root/->csum_root/->free_space_root, putting these roots into a rb_tree,
> and changing the code to look up the roots in the rb_tree instead of accessing
> them directly.  There are a variety of fixes to help make this easier, mostly
> removing access to these roots that are strictly necessary.  Thanks,

But the later part for indirect access to previously global trees are
somewhat questionable.

The idea of rb-tree caching these trees are no problem, but the callers
are still passing place holder values to these helpers.

For current extent-tree, we can pass whatever values and get the root we
want, but that also means, we need another round of patches to fix all
the place holders to make them really extent-tree-v2 compatible.

Thus I'd prefer to see these helpers are called in a proper way in one
go, which is not really feasible to test in current preparation form.

Maybe it would be better to put these patches with the real
extent-tree-v2 code?

Thanks,
Qu

>
> Josef
>
> Josef Bacik (20):
>    btrfs-progs: simplify btrfs_make_block_group
>    btrfs-progs: check: don't walk down non fs-trees for qgroup check
>    btrfs-progs: filesystem-show: close ctree once we're done
>    btrfs-progs: add a helper for setting up a root node
>    btrfs-progs: btrfs-shared: stop passing root to csum related functions
>    btrfs-progs: check: stop passing csum root around
>    btrfs-progs: stop accessing ->csum_root directly
>    btrfs-progs: image: keep track of seen blocks when walking trees
>    btrfs-progs: common: move btrfs_fix_block_accounting to repair.c
>    btrfs-progs: check: abstract out the used marking helpers
>    btrfs-progs: check: move btrfs_mark_used_tree_blocks to common
>    btrfs-progs: mark reloc roots as used
>    btrfs-progs: stop accessing ->extent_root directly
>    btrfs-progs: stop accessing ->free_space_root directly
>    btrfs-progs: track csum, extent, and free space trees in a rb tree
>    btrfs-progs: check: make reinit work per found root item
>    btrfs-progs: check: check the global roots for uptodate root nodes
>    btrfs-progs: check: check all of the csum roots
>    btrfs-progs: check: fill csum root from all extent roots
>    btrfs-progs: common: search all extent roots for marking used space
>
>   btrfs-corrupt-block.c           |  15 +-
>   btrfs-map-logical.c             |   9 +-
>   btrfstune.c                     |   2 +-
>   check/main.c                    | 223 ++++++++++++++------
>   check/mode-common.c             | 132 +-----------
>   check/mode-lowmem.c             |  72 ++++---
>   check/qgroup-verify.c           |   6 +-
>   cmds/filesystem.c               |  19 +-
>   cmds/rescue-chunk-recover.c     |  35 ++--
>   common/repair.c                 | 230 +++++++++++++++++++++
>   common/repair.h                 |   5 +
>   convert/main.c                  |   5 +-
>   image/main.c                    |  14 +-
>   kernel-shared/backref.c         |  10 +-
>   kernel-shared/ctree.h           |  10 +-
>   kernel-shared/disk-io.c         | 356 +++++++++++++++++++++++---------
>   kernel-shared/disk-io.h         |   8 +-
>   kernel-shared/extent-tree.c     | 159 ++++----------
>   kernel-shared/file-item.c       |   6 +-
>   kernel-shared/free-space-tree.c |  54 +++--
>   kernel-shared/volumes.c         |   3 +-
>   kernel-shared/zoned.c           |   2 +-
>   mkfs/main.c                     |  29 ++-
>   mkfs/rootdir.c                  |   2 +-
>   24 files changed, 892 insertions(+), 514 deletions(-)
>

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

* Re: [PATCH 00/20] btrfs-progs: extent tree v2 global root support prep work
  2021-11-06  0:55 ` [PATCH 00/20] btrfs-progs: extent tree v2 global root support prep work Qu Wenruo
@ 2021-11-06 20:17   ` Josef Bacik
  0 siblings, 0 replies; 42+ messages in thread
From: Josef Bacik @ 2021-11-06 20:17 UTC (permalink / raw)
  To: Qu Wenruo; +Cc: linux-btrfs, kernel-team

On Sat, Nov 06, 2021 at 08:55:21AM +0800, Qu Wenruo wrote:
> 
> 
> On 2021/11/6 04:28, Josef Bacik wrote:
> > Hello,
> > 
> > This is a series of patches to do all the prep work needed to support extent
> > tree v2.  These patches are independent of the actual extent tree v2 support,
> > some of them are fixes,
> 
> First half are mostly good, as they are really fixes and independent
> refactors.
> 
> > some of them are purely to pave the way for the global
> > root support.  These patches are mostly around stopping direct access of
> > ->extent_root/->csum_root/->free_space_root, putting these roots into a rb_tree,
> > and changing the code to look up the roots in the rb_tree instead of accessing
> > them directly.  There are a variety of fixes to help make this easier, mostly
> > removing access to these roots that are strictly necessary.  Thanks,
> 
> But the later part for indirect access to previously global trees are
> somewhat questionable.
> 
> The idea of rb-tree caching these trees are no problem, but the callers
> are still passing place holder values to these helpers.
> 
> For current extent-tree, we can pass whatever values and get the root we
> want, but that also means, we need another round of patches to fix all
> the place holders to make them really extent-tree-v2 compatible.
> 
> Thus I'd prefer to see these helpers are called in a proper way in one
> go, which is not really feasible to test in current preparation form.
> 
> Maybe it would be better to put these patches with the real
> extent-tree-v2 code?
>

There's simply too much.  Basically anywhere btrfs_extent_root(fs_info, 0) needs
to be looked at to make sure it's compatible, and trust me I have a loooooot of
patches fixing up the different things that require special handling, and each
of them are beefy by themselves.

It makes it easier for reviewers to grok this way, there's no change for the
!extent_tree_v2 case, and then as the extent tree v2 stuff gets added I make the
necessary changes so they can be properly checked, because lord knows we
probalby fucked some of them up.  Thanks,

Josef 

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

* Re: [PATCH 01/20] btrfs-progs: simplify btrfs_make_block_group
  2021-11-05 20:28 ` [PATCH 01/20] btrfs-progs: simplify btrfs_make_block_group Josef Bacik
  2021-11-06  0:14   ` Qu Wenruo
@ 2021-11-08 10:13   ` Anand Jain
  1 sibling, 0 replies; 42+ messages in thread
From: Anand Jain @ 2021-11-08 10:13 UTC (permalink / raw)
  To: Josef Bacik, linux-btrfs, kernel-team

On 06/11/2021 04:28, Josef Bacik wrote:
> This is doing the same work as insert_block_group_item, rework it to
> call the helper instead.
> 

looks good.

Reviewed-by: Anand Jain <anand.jain@oracle.com>

Thanks, Anand

> Signed-off-by: Josef Bacik <josef@toxicpanda.com>
> ---
>   kernel-shared/extent-tree.c | 43 ++++++++++++++-----------------------
>   1 file changed, 16 insertions(+), 27 deletions(-)
> 
> diff --git a/kernel-shared/extent-tree.c b/kernel-shared/extent-tree.c
> index 8e0614e0..a918e5aa 100644
> --- a/kernel-shared/extent-tree.c
> +++ b/kernel-shared/extent-tree.c
> @@ -2791,33 +2791,6 @@ btrfs_add_block_group(struct btrfs_fs_info *fs_info, u64 bytes_used, u64 type,
>   	return cache;
>   }
>   
> -int btrfs_make_block_group(struct btrfs_trans_handle *trans,
> -			   struct btrfs_fs_info *fs_info, u64 bytes_used,
> -			   u64 type, u64 chunk_offset, u64 size)
> -{
> -	int ret;
> -	struct btrfs_root *extent_root = fs_info->extent_root;
> -	struct btrfs_block_group *cache;
> -	struct btrfs_block_group_item bgi;
> -	struct btrfs_key key;
> -
> -	cache = btrfs_add_block_group(fs_info, bytes_used, type, chunk_offset,
> -				      size);
> -	btrfs_set_stack_block_group_used(&bgi, cache->used);
> -	btrfs_set_stack_block_group_flags(&bgi, cache->flags);
> -	btrfs_set_stack_block_group_chunk_objectid(&bgi,
> -			BTRFS_FIRST_CHUNK_TREE_OBJECTID);
> -	key.objectid = cache->start;
> -	key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
> -	key.offset = cache->length;
> -	ret = btrfs_insert_item(trans, extent_root, &key, &bgi, sizeof(bgi));
> -	BUG_ON(ret);
> -
> -	add_block_group_free_space(trans, cache);
> -
> -	return 0;
> -}
> -
>   static int insert_block_group_item(struct btrfs_trans_handle *trans,
>   				   struct btrfs_block_group *block_group)
>   {
> @@ -2838,6 +2811,22 @@ static int insert_block_group_item(struct btrfs_trans_handle *trans,
>   	return btrfs_insert_item(trans, root, &key, &bgi, sizeof(bgi));
>   }
>   
> +int btrfs_make_block_group(struct btrfs_trans_handle *trans,
> +			   struct btrfs_fs_info *fs_info, u64 bytes_used,
> +			   u64 type, u64 chunk_offset, u64 size)
> +{
> +	struct btrfs_block_group *cache;
> +	int ret;
> +
> +	cache = btrfs_add_block_group(fs_info, bytes_used, type, chunk_offset,
> +				      size);
> +	ret = insert_block_group_item(trans, cache);
> +	if (ret)
> +		return ret;
> +	add_block_group_free_space(trans, cache);
> +	return 0;
> +}
> +
>   /*
>    * This is for converter use only.
>    *
> 


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

* Re: [PATCH 03/20] btrfs-progs: filesystem-show: close ctree once we're done
  2021-11-05 20:28 ` [PATCH 03/20] btrfs-progs: filesystem-show: close ctree once we're done Josef Bacik
@ 2021-11-08 10:23   ` Anand Jain
  0 siblings, 0 replies; 42+ messages in thread
From: Anand Jain @ 2021-11-08 10:23 UTC (permalink / raw)
  To: Josef Bacik, linux-btrfs, kernel-team

On 06/11/2021 04:28, Josef Bacik wrote:
> Running with ASAN we won't pass the self tests because we leak the whole
> fs_info with btrfs filesystem show.  Fix this by making sure we close
> out the fs_info and clean up all of the memory and such.
> 

Looks good.

Reviewed-by: Anand Jain <anand.jain@oracle.com>


> Signed-off-by: Josef Bacik <josef@toxicpanda.com>
> ---
>   cmds/filesystem.c | 19 +++++++++----------
>   1 file changed, 9 insertions(+), 10 deletions(-)
> 
> diff --git a/cmds/filesystem.c b/cmds/filesystem.c
> index 6a9e46d2..624d0288 100644
> --- a/cmds/filesystem.c
> +++ b/cmds/filesystem.c
> @@ -655,6 +655,7 @@ static int cmd_filesystem_show(const struct cmd_struct *cmd,
>   {
>   	LIST_HEAD(all_uuids);
>   	struct btrfs_fs_devices *fs_devices;
> +	struct btrfs_root *root = NULL;
>   	char *search = NULL;
>   	int ret;
>   	/* default, search both kernel and udev */
> @@ -753,12 +754,8 @@ static int cmd_filesystem_show(const struct cmd_struct *cmd,
>   
>   devs_only:
>   	if (type == BTRFS_ARG_REG) {
> -		/*
> -		 * Given input (search) is regular file.
> -		 * We don't close the fs_info because it will free the device,
> -		 * this is not a long-running process so it's fine
> -		 */
> -		if (open_ctree(search, btrfs_sb_offset(0), 0))
> +		root = open_ctree(search, btrfs_sb_offset(0), 0);
> +		if (root)
>   			ret = 0;
>   		else
>   			ret = 1;
> @@ -768,7 +765,7 @@ devs_only:
>   
>   	if (ret) {
>   		error("blkid device scan returned %d", ret);
> -		return 1;
> +		goto out;
>   	}
>   
>   	/*
> @@ -779,13 +776,13 @@ devs_only:
>   	ret = search_umounted_fs_uuids(&all_uuids, search, &found);
>   	if (ret < 0) {
>   		error("searching target device returned error %d", ret);
> -		return 1;
> +		goto out;
>   	}
>   
>   	ret = map_seed_devices(&all_uuids);
>   	if (ret) {
>   		error("mapping seed devices returned error %d", ret);
> -		return 1;
> +		goto out;
>   	}
>   
>   	list_for_each_entry(fs_devices, &all_uuids, list)
> @@ -801,8 +798,10 @@ devs_only:
>   		free_fs_devices(fs_devices);
>   	}
>   out:
> +	if (root)
> +		close_ctree(root);
>   	free_seen_fsid(seen_fsid_hash);
> -	return ret;
> +	return !!ret;
>   }
>   static DEFINE_SIMPLE_COMMAND(filesystem_show, "show");
>   
> 


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

* Re: [PATCH 12/20] btrfs-progs: mark reloc roots as used
  2021-11-06  0:39   ` Qu Wenruo
@ 2021-11-08 19:14     ` Josef Bacik
  2021-11-09  0:57       ` Qu Wenruo
  0 siblings, 1 reply; 42+ messages in thread
From: Josef Bacik @ 2021-11-08 19:14 UTC (permalink / raw)
  To: Qu Wenruo; +Cc: linux-btrfs, kernel-team

On Sat, Nov 06, 2021 at 08:39:23AM +0800, Qu Wenruo wrote:
> 
> 
> On 2021/11/6 04:28, Josef Bacik wrote:
> > btrfs_mark_used_tree_blocks skips the reloc roots for some reason, which
> > causes problems because these blocks are in use, and we use this helper
> > to determine if the block accounting is correct with extent tree v2.
> 
> Any idea on why it's skipped in the first place?
> 

Yeah I added it apparently in

439ce45e ("Btrfs-progs: add --init-extent-tree to btrfsck")

because at the time we didn't deal with the reloc tree properly and I was trying
to unfuck a users file system.  I'm going to say that isn't the case anymore.
Thanks,

Josef

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

* Re: [PATCH 07/20] btrfs-progs: stop accessing ->csum_root directly
  2021-11-06  0:23   ` Qu Wenruo
@ 2021-11-08 19:19     ` Josef Bacik
  2021-11-09  0:56       ` Qu Wenruo
  2021-11-09 15:12       ` David Sterba
  0 siblings, 2 replies; 42+ messages in thread
From: Josef Bacik @ 2021-11-08 19:19 UTC (permalink / raw)
  To: Qu Wenruo; +Cc: linux-btrfs, kernel-team

On Sat, Nov 06, 2021 at 08:23:46AM +0800, Qu Wenruo wrote:
> 
> 
> On 2021/11/6 04:28, Josef Bacik wrote:
> > With extent tree v2 we will have per-block group checksums,
> 
> I guess you mean per block group checksum tree?
> 
> > so add a
> > helper to access the csum root and rename the fs_info csum_root to
> > _csum_root to catch all the places that are accessing it directly.
> > Convert everybody to use the helper except for internal things.
> > 
> > Signed-off-by: Josef Bacik <josef@toxicpanda.com>
> 
> Currently a lot of locations are still passing 0 to btrfs_csum_root(),
> which would need to be converted later.
> 
> Thus it doesn't look correct to be in the preparation patchset.
> 
> Mind to move this patch into the real extent-tree-v2 patchset?
> 

I explained this in another reply, but I wanted to talk about this specific
style of request here as well.

I did it this way because it's changing a lot of callsites to use a helper.
This is kind of a complex change as a whole, because I'm taking us from having a
fs_info->extent_root to having a rb tree with the extent root, csum root, and
free space tree root.

Once I get to the actual extent tree v2 stuff there's going to be a whole host
of more complicated changes.

So, in order to make it easier to review, I've put this relatively large concept
in the prep patches.  It's easier to look at because its a clear
s/->whatever_root/btrfs_whatever_root/ change.  It's easy to spot check and wrap
your head around.

Then I do the work to actually load it into the rb-tree, and then change the
helpers to access the rb-tree.  Those two changes are contained and easy to wrap
your head around.

Then in the extent-tree-v2 series I actually change the helpers to do the new
crazy stuff, and then go through the places where we do
btrfs_whatever_root(fs_info, 0) and convert those to be compatible with the new
world order.  I do that because each of those spots is it's own deal to convert,
so they need to be reasoned within their context.

I could probably move this around, but we're at like 20 patches per groups of
series, so I did it this way to keep the logical separation as clean as
possible, and drastically reduce the amount of complex things you guys are
needing to look at individually.  Thanks,

Josef

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

* Re: [PATCH 07/20] btrfs-progs: stop accessing ->csum_root directly
  2021-11-08 19:19     ` Josef Bacik
@ 2021-11-09  0:56       ` Qu Wenruo
  2021-11-09 15:12       ` David Sterba
  1 sibling, 0 replies; 42+ messages in thread
From: Qu Wenruo @ 2021-11-09  0:56 UTC (permalink / raw)
  To: Josef Bacik, Qu Wenruo; +Cc: linux-btrfs, kernel-team



On 2021/11/9 03:19, Josef Bacik wrote:
> On Sat, Nov 06, 2021 at 08:23:46AM +0800, Qu Wenruo wrote:
>>
>>
>> On 2021/11/6 04:28, Josef Bacik wrote:
>>> With extent tree v2 we will have per-block group checksums,
>>
>> I guess you mean per block group checksum tree?
>>
>>> so add a
>>> helper to access the csum root and rename the fs_info csum_root to
>>> _csum_root to catch all the places that are accessing it directly.
>>> Convert everybody to use the helper except for internal things.
>>>
>>> Signed-off-by: Josef Bacik <josef@toxicpanda.com>
>>
>> Currently a lot of locations are still passing 0 to btrfs_csum_root(),
>> which would need to be converted later.
>>
>> Thus it doesn't look correct to be in the preparation patchset.
>>
>> Mind to move this patch into the real extent-tree-v2 patchset?
>>
> 
> I explained this in another reply, but I wanted to talk about this specific
> style of request here as well.
> 
> I did it this way because it's changing a lot of callsites to use a helper.
> This is kind of a complex change as a whole, because I'm taking us from having a
> fs_info->extent_root to having a rb tree with the extent root, csum root, and
> free space tree root.
> 
> Once I get to the actual extent tree v2 stuff there's going to be a whole host
> of more complicated changes.
> 
> So, in order to make it easier to review, I've put this relatively large concept
> in the prep patches.  It's easier to look at because its a clear
> s/->whatever_root/btrfs_whatever_root/ change.  It's easy to spot check and wrap
> your head around.
> 
> Then I do the work to actually load it into the rb-tree, and then change the
> helpers to access the rb-tree.  Those two changes are contained and easy to wrap
> your head around.
> 
> Then in the extent-tree-v2 series I actually change the helpers to do the new
> crazy stuff, and then go through the places where we do
> btrfs_whatever_root(fs_info, 0) and convert those to be compatible with the new
> world order.  I do that because each of those spots is it's own deal to convert,
> so they need to be reasoned within their context.

Oh my god, there would be crazier stuff?!

I guess I need to check the design doc more carefully then...

Then I guess although it's not ideal, but it would still be acceptable 
for now.

Thanks,
Qu

> 
> I could probably move this around, but we're at like 20 patches per groups of
> series, so I did it this way to keep the logical separation as clean as
> possible, and drastically reduce the amount of complex things you guys are
> needing to look at individually.  Thanks,
> 
> Josef
> 


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

* Re: [PATCH 12/20] btrfs-progs: mark reloc roots as used
  2021-11-08 19:14     ` Josef Bacik
@ 2021-11-09  0:57       ` Qu Wenruo
  0 siblings, 0 replies; 42+ messages in thread
From: Qu Wenruo @ 2021-11-09  0:57 UTC (permalink / raw)
  To: Josef Bacik, Qu Wenruo; +Cc: linux-btrfs, kernel-team



On 2021/11/9 03:14, Josef Bacik wrote:
> On Sat, Nov 06, 2021 at 08:39:23AM +0800, Qu Wenruo wrote:
>>
>>
>> On 2021/11/6 04:28, Josef Bacik wrote:
>>> btrfs_mark_used_tree_blocks skips the reloc roots for some reason, which
>>> causes problems because these blocks are in use, and we use this helper
>>> to determine if the block accounting is correct with extent tree v2.
>>
>> Any idea on why it's skipped in the first place?
>>
> 
> Yeah I added it apparently in
> 
> 439ce45e ("Btrfs-progs: add --init-extent-tree to btrfsck")
> 
> because at the time we didn't deal with the reloc tree properly and I was trying
> to unfuck a users file system.  I'm going to say that isn't the case anymore.
> Thanks,
> 
> Josef
> 
Then the patch looks fine to me.

Reviewed-by: Qu Wenruo <wqu@suse.com>

Thanks,
Qu


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

* Re: [PATCH 07/20] btrfs-progs: stop accessing ->csum_root directly
  2021-11-08 19:19     ` Josef Bacik
  2021-11-09  0:56       ` Qu Wenruo
@ 2021-11-09 15:12       ` David Sterba
  1 sibling, 0 replies; 42+ messages in thread
From: David Sterba @ 2021-11-09 15:12 UTC (permalink / raw)
  To: Josef Bacik; +Cc: Qu Wenruo, linux-btrfs, kernel-team

On Mon, Nov 08, 2021 at 02:19:38PM -0500, Josef Bacik wrote:
> On Sat, Nov 06, 2021 at 08:23:46AM +0800, Qu Wenruo wrote:
> > 
> > 
> > On 2021/11/6 04:28, Josef Bacik wrote:
> > > With extent tree v2 we will have per-block group checksums,
> > 
> > I guess you mean per block group checksum tree?
> > 
> > > so add a
> > > helper to access the csum root and rename the fs_info csum_root to
> > > _csum_root to catch all the places that are accessing it directly.
> > > Convert everybody to use the helper except for internal things.
> > > 
> > > Signed-off-by: Josef Bacik <josef@toxicpanda.com>
> > 
> > Currently a lot of locations are still passing 0 to btrfs_csum_root(),
> > which would need to be converted later.
> > 
> > Thus it doesn't look correct to be in the preparation patchset.
> > 
> > Mind to move this patch into the real extent-tree-v2 patchset?
> > 
> 
> I explained this in another reply, but I wanted to talk about this specific
> style of request here as well.
> 
> I did it this way because it's changing a lot of callsites to use a helper.
> This is kind of a complex change as a whole, because I'm taking us from having a
> fs_info->extent_root to having a rb tree with the extent root, csum root, and
> free space tree root.
> 
> Once I get to the actual extent tree v2 stuff there's going to be a whole host
> of more complicated changes.
> 
> So, in order to make it easier to review, I've put this relatively large concept
> in the prep patches.  It's easier to look at because its a clear
> s/->whatever_root/btrfs_whatever_root/ change.  It's easy to spot check and wrap
> your head around.
> 
> Then I do the work to actually load it into the rb-tree, and then change the
> helpers to access the rb-tree.  Those two changes are contained and easy to wrap
> your head around.
> 
> Then in the extent-tree-v2 series I actually change the helpers to do the new
> crazy stuff, and then go through the places where we do
> btrfs_whatever_root(fs_info, 0) and convert those to be compatible with the new
> world order.  I do that because each of those spots is it's own deal to convert,
> so they need to be reasoned within their context.
> 
> I could probably move this around, but we're at like 20 patches per groups of
> series, so I did it this way to keep the logical separation as clean as
> possible, and drastically reduce the amount of complex things you guys are
> needing to look at individually.  Thanks,

This approach works for me.

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

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

Thread overview: 42+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-05 20:28 [PATCH 00/20] btrfs-progs: extent tree v2 global root support prep work Josef Bacik
2021-11-05 20:28 ` [PATCH 01/20] btrfs-progs: simplify btrfs_make_block_group Josef Bacik
2021-11-06  0:14   ` Qu Wenruo
2021-11-08 10:13   ` Anand Jain
2021-11-05 20:28 ` [PATCH 02/20] btrfs-progs: check: don't walk down non fs-trees for qgroup check Josef Bacik
2021-11-06  0:14   ` Qu Wenruo
2021-11-05 20:28 ` [PATCH 03/20] btrfs-progs: filesystem-show: close ctree once we're done Josef Bacik
2021-11-08 10:23   ` Anand Jain
2021-11-05 20:28 ` [PATCH 04/20] btrfs-progs: add a helper for setting up a root node Josef Bacik
2021-11-06  0:18   ` Qu Wenruo
2021-11-05 20:28 ` [PATCH 05/20] btrfs-progs: btrfs-shared: stop passing root to csum related functions Josef Bacik
2021-11-06  0:20   ` Qu Wenruo
2021-11-05 20:28 ` [PATCH 06/20] btrfs-progs: check: stop passing csum root around Josef Bacik
2021-11-06  0:21   ` Qu Wenruo
2021-11-05 20:28 ` [PATCH 07/20] btrfs-progs: stop accessing ->csum_root directly Josef Bacik
2021-11-06  0:23   ` Qu Wenruo
2021-11-08 19:19     ` Josef Bacik
2021-11-09  0:56       ` Qu Wenruo
2021-11-09 15:12       ` David Sterba
2021-11-05 20:28 ` [PATCH 08/20] btrfs-progs: image: keep track of seen blocks when walking trees Josef Bacik
2021-11-06  0:26   ` Qu Wenruo
2021-11-05 20:28 ` [PATCH 09/20] btrfs-progs: common: move btrfs_fix_block_accounting to repair.c Josef Bacik
2021-11-06  0:30   ` Qu Wenruo
2021-11-05 20:28 ` [PATCH 10/20] btrfs-progs: check: abstract out the used marking helpers Josef Bacik
2021-11-06  0:37   ` Qu Wenruo
2021-11-05 20:28 ` [PATCH 11/20] btrfs-progs: check: move btrfs_mark_used_tree_blocks to common Josef Bacik
2021-11-05 20:28 ` [PATCH 12/20] btrfs-progs: mark reloc roots as used Josef Bacik
2021-11-06  0:39   ` Qu Wenruo
2021-11-08 19:14     ` Josef Bacik
2021-11-09  0:57       ` Qu Wenruo
2021-11-05 20:28 ` [PATCH 13/20] btrfs-progs: stop accessing ->extent_root directly Josef Bacik
2021-11-06  0:41   ` Qu Wenruo
2021-11-05 20:28 ` [PATCH 14/20] btrfs-progs: stop accessing ->free_space_root directly Josef Bacik
2021-11-06  0:44   ` Qu Wenruo
2021-11-05 20:28 ` [PATCH 15/20] btrfs-progs: track csum, extent, and free space trees in a rb tree Josef Bacik
2021-11-05 20:28 ` [PATCH 16/20] btrfs-progs: check: make reinit work per found root item Josef Bacik
2021-11-05 20:28 ` [PATCH 17/20] btrfs-progs: check: check the global roots for uptodate root nodes Josef Bacik
2021-11-05 20:28 ` [PATCH 18/20] btrfs-progs: check: check all of the csum roots Josef Bacik
2021-11-05 20:28 ` [PATCH 19/20] btrfs-progs: check: fill csum root from all extent roots Josef Bacik
2021-11-05 20:28 ` [PATCH 20/20] btrfs-progs: common: search all extent roots for marking used space Josef Bacik
2021-11-06  0:55 ` [PATCH 00/20] btrfs-progs: extent tree v2 global root support prep work Qu Wenruo
2021-11-06 20:17   ` Josef Bacik

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.