mirror of
https://github.com/koverstreet/bcachefs-tools.git
synced 2025-02-23 00:00:02 +03:00
Avoiding picking different bucket sizes for different devices
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>
This commit is contained in:
parent
a0371350ef
commit
469e8eb008
@ -677,7 +677,11 @@ static int migrate_fs(const char *fs_path,
|
|||||||
printf("Creating new filesystem on %s in space reserved at %s\n",
|
printf("Creating new filesystem on %s in space reserved at %s\n",
|
||||||
dev.path, file_path);
|
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;
|
u64 bcachefs_inum;
|
||||||
ranges extents = reserve_new_fs_space(file_path,
|
ranges extents = reserve_new_fs_space(file_path,
|
||||||
|
@ -64,44 +64,44 @@ static u64 min_size(unsigned bucket_size)
|
|||||||
return BCH_MIN_NR_NBUCKETS * 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)
|
u64 bucket_size;
|
||||||
dev->size = get_size(dev->bdev->bd_buffered_fd);
|
|
||||||
|
|
||||||
if (!dev->bucket_size) {
|
if (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)",
|
||||||
die("cannot format %s, too small (%llu bytes, min %llu)",
|
dev->path, dev->size, min_size(opts.block_size));
|
||||||
dev->path, dev->size, min_size(opts.block_size));
|
|
||||||
|
|
||||||
/* Bucket size must be >= block size: */
|
/* Bucket size must be >= block size: */
|
||||||
dev->bucket_size = opts.block_size;
|
bucket_size = opts.block_size;
|
||||||
|
|
||||||
/* Bucket size must be >= btree node size: */
|
/* Bucket size must be >= btree node size: */
|
||||||
if (opt_defined(opts, btree_node_size))
|
if (opt_defined(opts, btree_node_size))
|
||||||
dev->bucket_size = max_t(unsigned, dev->bucket_size,
|
bucket_size = max_t(unsigned, bucket_size,
|
||||||
opts.btree_node_size);
|
opts.btree_node_size);
|
||||||
|
|
||||||
/* Want a bucket size of at least 128k, if possible: */
|
/* Want a bucket size of at least 128k, if possible: */
|
||||||
dev->bucket_size = max(dev->bucket_size, 128ULL << 10);
|
bucket_size = max(bucket_size, 128ULL << 10);
|
||||||
|
|
||||||
if (dev->size >= min_size(dev->bucket_size)) {
|
if (dev->size >= min_size(bucket_size)) {
|
||||||
unsigned scale = max(1,
|
unsigned scale = max(1,
|
||||||
ilog2(dev->size / min_size(dev->bucket_size)) / 4);
|
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 */
|
/* max bucket size 1 mb */
|
||||||
dev->bucket_size = min(dev->bucket_size * scale, 1ULL << 20);
|
bucket_size = min(bucket_size * scale, 1ULL << 20);
|
||||||
} else {
|
} else {
|
||||||
do {
|
do {
|
||||||
dev->bucket_size /= 2;
|
bucket_size /= 2;
|
||||||
} while (dev->size < min_size(dev->bucket_size));
|
} 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)
|
if (dev->bucket_size < opts.block_size)
|
||||||
die("Bucket size (%llu) cannot be smaller than block size (%u)",
|
die("Bucket size (%llu) cannot be smaller than block size (%u)",
|
||||||
dev->bucket_size, opts.block_size);
|
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;
|
struct dev_opts *i;
|
||||||
unsigned max_dev_block_size = 0;
|
unsigned max_dev_block_size = 0;
|
||||||
unsigned opt_id;
|
unsigned opt_id;
|
||||||
|
u64 min_bucket_size = U64_MAX;
|
||||||
|
|
||||||
for (i = devs; i < devs + nr_devs; i++)
|
for (i = devs; i < devs + nr_devs; i++)
|
||||||
max_dev_block_size = max(max_dev_block_size, get_blocksize(i->bdev->bd_buffered_fd));
|
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",
|
die("blocksize too small: %u, must be greater than device blocksize %u",
|
||||||
fs_opts.block_size, max_dev_block_size);
|
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: */
|
/* calculate bucket sizes: */
|
||||||
for (i = devs; i < devs + nr_devs; i++)
|
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: */
|
/* calculate btree node size: */
|
||||||
if (!opt_defined(fs_opts, btree_node_size)) {
|
if (!opt_defined(fs_opts, btree_node_size)) {
|
||||||
|
@ -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_sb *bch2_format(struct bch_opt_strs,
|
||||||
struct bch_opts,
|
struct bch_opts,
|
||||||
struct format_opts, struct dev_opts *, size_t);
|
struct format_opts, struct dev_opts *, size_t);
|
||||||
|
Loading…
Reference in New Issue
Block a user