]> git.sesse.net Git - bcachefs-tools-debian/commitdiff
Avoiding picking different bucket sizes for different devices
authorKent Overstreet <kent.overstreet@linux.dev>
Tue, 7 Nov 2023 01:47:48 +0000 (20:47 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Tue, 7 Nov 2023 01:47:48 +0000 (20:47 -0500)
Erasure coding can't create stripes across devices with different bucket
sizes - therefore, format shouldn't pick different bucket sizes for
different devices.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
cmd_migrate.c
libbcachefs.c
libbcachefs.h

index f82dd6185ee51f54d67f45ee2523c6aad88cc1d8..cde1fce4397c725baafa3326d10d54799b65ed5f 100644 (file)
@@ -677,7 +677,11 @@ static int migrate_fs(const char           *fs_path,
        printf("Creating new filesystem on %s in space reserved at %s\n",
               dev.path, file_path);
 
-       bch2_pick_bucket_size(fs_opts, &dev);
+       dev.size        = get_size(dev.bdev->bd_buffered_fd);
+       dev.bucket_size = bch2_pick_bucket_size(fs_opts, &dev);
+       dev.nbuckets    = dev.size / dev.bucket_size;
+
+       bch2_check_bucket_size(fs_opts, &dev);
 
        u64 bcachefs_inum;
        ranges extents = reserve_new_fs_space(file_path,
index c4a327e33a36911fbb7fb1a5c80c66db93f0c899..123109f8dcbefaa695b560638d065c1f1c4c7ad5 100644 (file)
@@ -64,44 +64,44 @@ static u64 min_size(unsigned bucket_size)
        return BCH_MIN_NR_NBUCKETS * bucket_size;
 }
 
-void bch2_pick_bucket_size(struct bch_opts opts, struct dev_opts *dev)
+u64 bch2_pick_bucket_size(struct bch_opts opts, struct dev_opts *dev)
 {
-       if (!dev->size)
-               dev->size = get_size(dev->bdev->bd_buffered_fd);
+       u64 bucket_size;
 
-       if (!dev->bucket_size) {
-               if (dev->size < min_size(opts.block_size))
-                       die("cannot format %s, too small (%llu bytes, min %llu)",
-                           dev->path, dev->size, min_size(opts.block_size));
+       if (dev->size < min_size(opts.block_size))
+               die("cannot format %s, too small (%llu bytes, min %llu)",
+                   dev->path, dev->size, min_size(opts.block_size));
 
-               /* Bucket size must be >= block size: */
-               dev->bucket_size = opts.block_size;
+       /* Bucket size must be >= block size: */
+       bucket_size = opts.block_size;
 
-               /* Bucket size must be >= btree node size: */
-               if (opt_defined(opts, btree_node_size))
-                       dev->bucket_size = max_t(unsigned, dev->bucket_size,
-                                                opts.btree_node_size);
+       /* Bucket size must be >= btree node size: */
+       if (opt_defined(opts, btree_node_size))
+               bucket_size = max_t(unsigned, bucket_size,
+                                        opts.btree_node_size);
 
-               /* Want a bucket size of at least 128k, if possible: */
-               dev->bucket_size = max(dev->bucket_size, 128ULL << 10);
+       /* Want a bucket size of at least 128k, if possible: */
+       bucket_size = max(bucket_size, 128ULL << 10);
 
-               if (dev->size >= min_size(dev->bucket_size)) {
-                       unsigned scale = max(1,
-                               ilog2(dev->size / min_size(dev->bucket_size)) / 4);
+       if (dev->size >= min_size(bucket_size)) {
+               unsigned scale = max(1,
+                       ilog2(dev->size / min_size(bucket_size)) / 4);
 
-                       scale = rounddown_pow_of_two(scale);
+               scale = rounddown_pow_of_two(scale);
 
-                       /* max bucket size 1 mb */
-                       dev->bucket_size = min(dev->bucket_size * scale, 1ULL << 20);
-               } else {
-                       do {
-                               dev->bucket_size /= 2;
-                       } while (dev->size < min_size(dev->bucket_size));
-               }
+               /* max bucket size 1 mb */
+               bucket_size = min(bucket_size * scale, 1ULL << 20);
+       } else {
+               do {
+                       bucket_size /= 2;
+               } while (dev->size < min_size(bucket_size));
        }
 
-       dev->nbuckets = dev->size / dev->bucket_size;
+       return bucket_size;
+}
 
+void bch2_check_bucket_size(struct bch_opts opts, struct dev_opts *dev)
+{
        if (dev->bucket_size < opts.block_size)
                die("Bucket size (%llu) cannot be smaller than block size (%u)",
                    dev->bucket_size, opts.block_size);
@@ -152,6 +152,7 @@ struct bch_sb *bch2_format(struct bch_opt_strs      fs_opt_strs,
        struct dev_opts *i;
        unsigned max_dev_block_size = 0;
        unsigned opt_id;
+       u64 min_bucket_size = U64_MAX;
 
        for (i = devs; i < devs + nr_devs; i++)
                max_dev_block_size = max(max_dev_block_size, get_blocksize(i->bdev->bd_buffered_fd));
@@ -163,9 +164,24 @@ struct bch_sb *bch2_format(struct bch_opt_strs     fs_opt_strs,
                die("blocksize too small: %u, must be greater than device blocksize %u",
                    fs_opts.block_size, max_dev_block_size);
 
+       /* get device size, if it wasn't specified: */
+       for (i = devs; i < devs + nr_devs; i++)
+               if (!i->size)
+                       i->size = get_size(i->bdev->bd_buffered_fd);
+
        /* calculate bucket sizes: */
        for (i = devs; i < devs + nr_devs; i++)
-               bch2_pick_bucket_size(fs_opts, i);
+               min_bucket_size = min(min_bucket_size,
+                       i->bucket_size ?: bch2_pick_bucket_size(fs_opts, i));
+
+       for (i = devs; i < devs + nr_devs; i++)
+               if (!i->bucket_size)
+                       i->bucket_size = min_bucket_size;
+
+       for (i = devs; i < devs + nr_devs; i++) {
+               i->nbuckets = i->size / i->bucket_size;
+               bch2_check_bucket_size(fs_opts, i);
+       }
 
        /* calculate btree node size: */
        if (!opt_defined(fs_opts, btree_node_size)) {
index 6322d55e7f8bf5f45d80d30f48ab6bf79167fbf5..a16ae8669bdf331d697f31ec6c05a1a6670dccc2 100644 (file)
@@ -75,7 +75,9 @@ static inline struct dev_opts dev_opts_default()
        };
 }
 
-void bch2_pick_bucket_size(struct bch_opts, struct dev_opts *);
+u64 bch2_pick_bucket_size(struct bch_opts, struct dev_opts *);
+void bch2_check_bucket_size(struct bch_opts, struct dev_opts *);
+
 struct bch_sb *bch2_format(struct bch_opt_strs,
                           struct bch_opts,
                           struct format_opts, struct dev_opts *, size_t);