x('L', label, required_argument) \
x('U', uuid, required_argument) \
x(0, fs_size, required_argument) \
+x(0, superblock_size, required_argument) \
x(0, bucket_size, required_argument) \
x('g', group, required_argument) \
x(0, discard, no_argument) \
" --no_passphrase Don't encrypt master encryption key\n"
" -L, --label=label\n"
" -U, --uuid=uuid\n"
+ " --superblock_size=size\n"
"\n"
"Device specific options:");
dev_opts.size >>= 9;
break;
+ case O_superblock_size:
+ if (bch2_strtouint_h(optarg, &opts.superblock_size))
+ die("invalid filesystem size");
+
+ opts.superblock_size >>= 9;
+ break;
case O_bucket_size:
dev_opts.bucket_size =
hatoi_validate(optarg, "bucket size");
bch2_alloc_write(c, false);
}
-static void find_superblock_space(ranges extents, struct dev_opts *dev)
+static void find_superblock_space(ranges extents,
+ struct format_opts opts,
+ struct dev_opts *dev)
{
struct range *i;
u64 end = round_down(i->end,
dev->bucket_size << 9);
- if (start + (128 << 10) <= end) {
+ /* Need space for two superblocks: */
+ if (start + (opts.superblock_size << 9) * 2 <= end) {
dev->sb_offset = start >> 9;
- dev->sb_end = dev->sb_offset + 256;
+ dev->sb_end = dev->sb_offset + opts.superblock_size * 2;
return;
}
}
get_size(dev.path, dev.fd) / 5,
&bcachefs_inum, stat.st_dev, force);
- find_superblock_space(extents, &dev);
+ find_superblock_space(extents, format_opts, &dev);
struct bch_sb *sb = bch2_format(fs_opt_strs,
fs_opts,format_opts, &dev, 1);
return BCH_MIN_NR_NBUCKETS * bucket_size;
}
-static void init_layout(struct bch_sb_layout *l, unsigned block_size,
+static void init_layout(struct bch_sb_layout *l,
+ unsigned block_size,
+ unsigned sb_size,
u64 start, u64 end)
{
- unsigned sb_size;
- u64 backup; /* offset of 2nd sb */
+ unsigned i;
memset(l, 0, sizeof(*l));
- if (start != BCH_SB_SECTOR)
- start = round_up(start, block_size);
- end = round_down(end, block_size);
-
- if (start >= end)
- die("insufficient space for superblocks");
-
- /*
- * Create two superblocks in the allowed range: reserve a maximum of 64k
- */
- sb_size = min_t(u64, 128, end - start / 2);
-
- backup = start + sb_size;
- backup = round_up(backup, block_size);
-
- backup = min(backup, end);
-
- sb_size = min(end - backup, backup- start);
- sb_size = rounddown_pow_of_two(sb_size);
-
- if (sb_size < 8)
- die("insufficient space for superblocks");
-
l->magic = BCACHE_MAGIC;
l->layout_type = 0;
l->nr_superblocks = 2;
l->sb_max_size_bits = ilog2(sb_size);
- l->sb_offset[0] = cpu_to_le64(start);
- l->sb_offset[1] = cpu_to_le64(backup);
+
+ /* Create two superblocks in the allowed range: */
+ for (i = 0; i < l->nr_superblocks; i++) {
+ if (start != BCH_SB_SECTOR)
+ start = round_up(start, block_size);
+
+ l->sb_offset[i] = cpu_to_le64(start);
+ start += sb_size;
+ }
+
+ if (start >= end)
+ die("insufficient space for superblocks");
}
void bch2_pick_bucket_size(struct bch_opts opts, struct dev_opts *dev)
{
- if (!dev->sb_offset) {
- dev->sb_offset = BCH_SB_SECTOR;
- dev->sb_end = BCH_SB_SECTOR + 256;
- }
-
if (!dev->size)
dev->size = get_size(dev->path, dev->fd) >> 9;
for (i = devs; i < devs + nr_devs; i++) {
sb.sb->dev_idx = i - devs;
+ if (!i->sb_offset) {
+ i->sb_offset = BCH_SB_SECTOR;
+ i->sb_end = i->size;
+ }
+
init_layout(&sb.sb->layout, fs_opts.block_size,
+ opts.superblock_size,
i->sb_offset, i->sb_end);
if (i->sb_offset == BCH_SB_SECTOR) {
/* option parsing */
+#define SUPERBLOCK_SIZE_DEFAULT 2048 /* 1 MB */
+
struct bch_opt_strs {
union {
char *by_id[bch2_opts_nr];
char *label;
uuid_le uuid;
unsigned version;
-
+ unsigned superblock_size;
unsigned encoded_extent_max;
-
bool encrypted;
char *passphrase;
};
{
return (struct format_opts) {
.version = bcachefs_metadata_version_current,
+ .superblock_size = SUPERBLOCK_SIZE_DEFAULT,
.encoded_extent_max = 128,
};
}