From 5023292623e8f1dedc138a20daabbcc4772a0d86 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sun, 20 Jul 2025 22:48:44 -0400 Subject: bcachefs: Fixes for bucket size calculations Make sure bucket size >= btree_node_size when adding a device, and cmd_image_update needs to make sure the metadata device is big enough for the minimum number of buckets. Signed-off-by: Kent Overstreet --- c_src/cmd_image.c | 5 ++++- c_src/libbcachefs.c | 11 ++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/c_src/cmd_image.c b/c_src/cmd_image.c index d00d85cf..467378b0 100644 --- a/c_src/cmd_image.c +++ b/c_src/cmd_image.c @@ -665,7 +665,10 @@ static int image_update(const char *src_path, const char *dst_image, goto err; } - if (ftruncate(dev_opts.bdev->bd_fd, input_bytes)) { + u64 metadata_dev_size = max(input_bytes, + c->opts.btree_node_size * BCH_MIN_NR_NBUCKETS); + + if (ftruncate(dev_opts.bdev->bd_fd, metadata_dev_size)) { fprintf(stderr, "ftruncate error: %m"); goto err; } diff --git a/c_src/libbcachefs.c b/c_src/libbcachefs.c index 935b13ce..6b31d56f 100644 --- a/c_src/libbcachefs.c +++ b/c_src/libbcachefs.c @@ -79,9 +79,14 @@ void bch2_sb_layout_init(struct bch_sb_layout *l, } } -static u64 dev_max_bucket_size(u64 dev_size) +static u64 dev_max_bucket_size(struct bch_opts fs_opts, u64 dev_size) { - return rounddown_pow_of_two(dev_size / (BCH_MIN_NR_NBUCKETS * 4)); + u64 size = rounddown_pow_of_two(dev_size / (BCH_MIN_NR_NBUCKETS * 4)); + if (opt_defined(fs_opts, btree_node_size)) + size = max(size, fs_opts.btree_node_size); + if (size * BCH_MIN_NR_NBUCKETS > dev_size) + die("bucket size %llu too big for device size", size); + return size; } u64 bch2_pick_bucket_size(struct bch_opts opts, dev_opts_list devs) @@ -209,7 +214,7 @@ struct bch_sb *bch2_format(struct bch_opt_strs fs_opt_strs, darray_for_each(devs, i) if (!opt_defined(i->opts, bucket_size)) opt_set(i->opts, bucket_size, - min(fs_bucket_size, dev_max_bucket_size(i->fs_size))); + min(fs_bucket_size, dev_max_bucket_size(fs_opts, i->fs_size))); darray_for_each(devs, i) { i->nbuckets = i->fs_size / i->opts.bucket_size; -- cgit v1.2.3