diff mbox series

[v5,18/19] btrfs-progs: mkfs: create the global root's

Message ID 7cadc40e9f8510b8df5679e15881f2c0de70363a.1646690972.git.josef@toxicpanda.com (mailing list archive)
State New, archived
Headers show
Series btrfs-progs: extent tree v2 support, global roots | expand

Commit Message

Josef Bacik March 7, 2022, 10:11 p.m. UTC
Now that we have all of the supporting code, add the ability to create
all of the global roots for an extent tree v2 fs.  This will default to
nr_cpu's, but also allow the user to specify how many global roots they
would like.

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

Comments

David Sterba March 9, 2022, 6:35 p.m. UTC | #1
On Mon, Mar 07, 2022 at 05:11:03PM -0500, Josef Bacik wrote:
> Now that we have all of the supporting code, add the ability to create
> all of the global roots for an extent tree v2 fs.  This will default to
> nr_cpu's, but also allow the user to specify how many global roots they
> would like.

Why is number of online cpus a good default? Or how a user should know
what's a good number? It resembles the allocation groups on xfs that
are set at mkfs time and once the filesystem is grown the size remains
but the number explodes and becomes problematic if the the old/new sizes
are disproportionate. We have more flexibility in btrfs with the resize
so we could afford to set the intial number based rather on the device
size and then a rebalance after resize can adjust that again. Maybe
there's something in kernel taking care of that, I don't know.
Josef Bacik March 9, 2022, 9:21 p.m. UTC | #2
On Wed, Mar 09, 2022 at 07:35:34PM +0100, David Sterba wrote:
> On Mon, Mar 07, 2022 at 05:11:03PM -0500, Josef Bacik wrote:
> > Now that we have all of the supporting code, add the ability to create
> > all of the global roots for an extent tree v2 fs.  This will default to
> > nr_cpu's, but also allow the user to specify how many global roots they
> > would like.
> 
> Why is number of online cpus a good default? Or how a user should know
> what's a good number? It resembles the allocation groups on xfs that
> are set at mkfs time and once the filesystem is grown the size remains
> but the number explodes and becomes problematic if the the old/new sizes
> are disproportionate. We have more flexibility in btrfs with the resize
> so we could afford to set the intial number based rather on the device
> size and then a rebalance after resize can adjust that again. Maybe
> there's something in kernel taking care of that, I don't know.

Right now I have no idea what a good number is, so I'm defaulting to NR_CPUS.  I
*think* this is a good idea because generally we want to spread the locking
pain, so hopefully NR_CPU's is good enough for most people?

We allow setting your own number if a user does the benchmarking to find their
ideal global roots number (*cough*Zygo*cough*).  And it'll be easy enough to add
new global roots since we tie the block group to the global root at create time.
Thanks,

Josef
diff mbox series

Patch

diff --git a/mkfs/main.c b/mkfs/main.c
index 19535604..a603ec58 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -810,6 +810,53 @@  out:
 	return ret;
 }
 
+static int create_global_root(struct btrfs_trans_handle *trans, u64 objectid,
+			      int root_id)
+{
+	struct btrfs_fs_info *fs_info = trans->fs_info;
+	struct btrfs_root *root;
+	struct btrfs_key key = {
+		.objectid = objectid,
+		.type = BTRFS_ROOT_ITEM_KEY,
+		.offset = root_id,
+	};
+	int ret = 0;
+
+	root = btrfs_create_tree(trans, fs_info, &key);
+	if (IS_ERR(root)) {
+		ret = PTR_ERR(root);
+		goto out;
+	}
+	ret = btrfs_global_root_insert(fs_info, root);
+out:
+	if (ret)
+		btrfs_abort_transaction(trans, ret);
+	return ret;
+}
+
+static int create_global_roots(struct btrfs_trans_handle *trans,
+			       int nr_global_roots)
+{
+	int ret, i;
+
+	for (i = 1; i < nr_global_roots; i++) {
+		ret = create_global_root(trans, BTRFS_EXTENT_TREE_OBJECTID, i);
+		if (ret)
+			return ret;
+		ret = create_global_root(trans, BTRFS_CSUM_TREE_OBJECTID, i);
+		if (ret)
+			return ret;
+		ret = create_global_root(trans, BTRFS_FREE_SPACE_TREE_OBJECTID, i);
+		if (ret)
+			return ret;
+	}
+
+	btrfs_set_super_nr_global_roots(trans->fs_info->super_copy,
+					nr_global_roots);
+
+	return 0;
+}
+
 static int insert_qgroup_items(struct btrfs_trans_handle *trans,
 			       struct btrfs_fs_info *fs_info,
 			       u64 qgroupid)
@@ -966,13 +1013,18 @@  int BOX_MAIN(mkfs)(int argc, char **argv)
 	struct btrfs_mkfs_config mkfs_cfg;
 	enum btrfs_csum_type csum_type = BTRFS_CSUM_TYPE_CRC32;
 	u64 system_group_size;
+	int nr_global_roots = sysconf(_SC_NPROCESSORS_ONLN);
 
 	crc32c_optimization_init();
 	btrfs_config_init();
 
 	while(1) {
 		int c;
-		enum { GETOPT_VAL_SHRINK = 257, GETOPT_VAL_CHECKSUM };
+		enum {
+			GETOPT_VAL_SHRINK = 257,
+			GETOPT_VAL_CHECKSUM,
+			GETOPT_VAL_GLOBAL_ROOTS,
+		};
 		static const struct option long_options[] = {
 			{ "byte-count", required_argument, NULL, 'b' },
 			{ "csum", required_argument, NULL,
@@ -996,6 +1048,9 @@  int BOX_MAIN(mkfs)(int argc, char **argv)
 			{ "quiet", 0, NULL, 'q' },
 			{ "verbose", 0, NULL, 'v' },
 			{ "shrink", no_argument, NULL, GETOPT_VAL_SHRINK },
+#if EXPERIMENTAL
+			{ "num-global-roots", required_argument, NULL, GETOPT_VAL_GLOBAL_ROOTS },
+#endif
 			{ "help", no_argument, NULL, GETOPT_VAL_HELP },
 			{ NULL, 0, NULL, 0}
 		};
@@ -1100,6 +1155,9 @@  int BOX_MAIN(mkfs)(int argc, char **argv)
 			case GETOPT_VAL_CHECKSUM:
 				csum_type = parse_csum_type(optarg);
 				break;
+			case GETOPT_VAL_GLOBAL_ROOTS:
+				nr_global_roots = (int)arg_strtou64(optarg);
+				break;
 			case GETOPT_VAL_HELP:
 			default:
 				print_usage(c != GETOPT_VAL_HELP);
@@ -1239,6 +1297,11 @@  int BOX_MAIN(mkfs)(int argc, char **argv)
 	if (features & BTRFS_FEATURE_INCOMPAT_EXTENT_TREE_V2) {
 		features |= BTRFS_FEATURE_INCOMPAT_NO_HOLES;
 		runtime_features |= BTRFS_RUNTIME_FEATURE_FREE_SPACE_TREE;
+
+		if (!nr_global_roots) {
+			error("you must set a non-zero num-global-roots value");
+			exit(1);
+		}
 	}
 
 	if (zoned) {
@@ -1467,6 +1530,14 @@  int BOX_MAIN(mkfs)(int argc, char **argv)
 		goto error;
 	}
 
+	if (features & BTRFS_FEATURE_INCOMPAT_EXTENT_TREE_V2) {
+		ret = create_global_roots(trans, nr_global_roots);
+		if (ret) {
+			error("failed to create global roots: %d", ret);
+			goto error;
+		}
+	}
+
 	ret = make_root_dir(trans, root);
 	if (ret) {
 		error("failed to setup the root directory: %d", ret);