mirror of
https://github.com/koverstreet/bcachefs-tools.git
synced 2025-03-27 00:00:04 +03:00
More device option work
More work to regularize device options, with common command line parsing - like other options. This fixes an assortment of little nits: buggyness with the discard option, device state (and others) can now be specied at device add time, and is a decent cleanup. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
e6aecdd3b8
commit
846f3398a2
@ -47,11 +47,11 @@ static void device_add_usage(void)
|
||||
puts("bcachefs device add - add a device to an existing filesystem\n"
|
||||
"Usage: bcachefs device add [OPTION]... filesystem device\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" -S, --fs_size=size Size of filesystem on device\n"
|
||||
" -B, --bucket=size Bucket size\n"
|
||||
" -D, --discard Enable discards\n"
|
||||
" -l, --label=label Disk label\n"
|
||||
"Options:\n");
|
||||
|
||||
bch2_opts_usage(OPT_FORMAT|OPT_DEVICE);
|
||||
|
||||
puts(" -l, --label=label Disk label\n"
|
||||
" -f, --force Use device even if it appears to already be formatted\n"
|
||||
" -h, --help Display this help and exit\n"
|
||||
"\n"
|
||||
@ -61,9 +61,6 @@ static void device_add_usage(void)
|
||||
int cmd_device_add(int argc, char *argv[])
|
||||
{
|
||||
static const struct option longopts[] = {
|
||||
{ "fs_size", required_argument, NULL, 'S' },
|
||||
{ "bucket", required_argument, NULL, 'B' },
|
||||
{ "discard", no_argument, NULL, 'D' },
|
||||
{ "label", required_argument, NULL, 'l' },
|
||||
{ "force", no_argument, NULL, 'f' },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
@ -72,22 +69,31 @@ int cmd_device_add(int argc, char *argv[])
|
||||
struct format_opts format_opts = format_opts_default();
|
||||
struct dev_opts dev_opts = dev_opts_default();
|
||||
bool force = false;
|
||||
int opt;
|
||||
|
||||
while ((opt = getopt_long(argc, argv, "S:B:Dl:fh",
|
||||
longopts, NULL)) != -1)
|
||||
switch (opt) {
|
||||
case 'S':
|
||||
if (bch2_strtoull_h(optarg, &dev_opts.size))
|
||||
die("invalid filesystem size");
|
||||
break;
|
||||
case 'B':
|
||||
if (bch2_strtoull_h(optarg, &dev_opts.bucket_size))
|
||||
die("bad bucket_size %s", optarg);
|
||||
break;
|
||||
case 'D':
|
||||
dev_opts.discard = true;
|
||||
while (true) {
|
||||
const struct bch_option *opt =
|
||||
bch2_cmdline_opt_parse(argc, argv, OPT_FORMAT|OPT_DEVICE);
|
||||
if (opt) {
|
||||
unsigned id = opt - bch2_opt_table;
|
||||
u64 v;
|
||||
struct printbuf err = PRINTBUF;
|
||||
int ret = bch2_opt_parse(NULL, opt, optarg, &v, &err);
|
||||
if (ret)
|
||||
die("invalid %s: %s", opt->attr.name, err.buf);
|
||||
|
||||
if (opt->flags & OPT_DEVICE)
|
||||
bch2_opt_set_by_id(&dev_opts.opts, id, v);
|
||||
else
|
||||
die("got bch_opt of wrong type %s", opt->attr.name);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
int optid = getopt_long(argc, argv, "S:B:Dl:fh", longopts, NULL);
|
||||
if (optid == -1)
|
||||
break;
|
||||
|
||||
switch (optid) {
|
||||
case 'l':
|
||||
dev_opts.label = strdup(optarg);
|
||||
break;
|
||||
@ -97,7 +103,11 @@ int cmd_device_add(int argc, char *argv[])
|
||||
case 'h':
|
||||
device_add_usage();
|
||||
exit(EXIT_SUCCESS);
|
||||
case '?':
|
||||
exit(EXIT_FAILURE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
args_shift(optind);
|
||||
|
||||
char *fs_path = arg_pop();
|
||||
|
@ -39,11 +39,7 @@ x('L', fs_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('l', label, required_argument) \
|
||||
x(0, discard, no_argument) \
|
||||
x(0, data_allowed, required_argument) \
|
||||
x(0, durability, required_argument) \
|
||||
x(0, version, required_argument) \
|
||||
x(0, no_initialize, no_argument) \
|
||||
x(0, source, required_argument) \
|
||||
@ -52,17 +48,16 @@ x('q', quiet, no_argument) \
|
||||
x('v', verbose, no_argument) \
|
||||
x('h', help, no_argument)
|
||||
|
||||
static void usage(void)
|
||||
static void format_usage(void)
|
||||
{
|
||||
puts("bcachefs format - create a new bcachefs filesystem on one or more devices\n"
|
||||
"Usage: bcachefs format [OPTION]... <devices>\n"
|
||||
"\n"
|
||||
"Options:");
|
||||
|
||||
bch2_opts_usage(OPT_FORMAT);
|
||||
bch2_opts_usage(OPT_FORMAT|OPT_FS);
|
||||
|
||||
puts(
|
||||
" --replicas=# Sets both data and metadata replicas\n"
|
||||
puts(" --replicas=# Sets both data and metadata replicas\n"
|
||||
" --encrypted Enable whole filesystem encryption (chacha20/poly1305)\n"
|
||||
" --no_passphrase Don't encrypt master encryption key\n"
|
||||
" -L, --fs_label=label\n"
|
||||
@ -72,9 +67,10 @@ static void usage(void)
|
||||
"\n"
|
||||
"Device specific options:");
|
||||
|
||||
bch2_opts_usage(OPT_DEVICE);
|
||||
bch2_opts_usage(OPT_FORMAT|OPT_DEVICE);
|
||||
|
||||
puts(" -l, --label=label Disk label\n"
|
||||
puts(" --fs_size=size Size of filesystem on device\n"
|
||||
" -l, --label=label Disk label\n"
|
||||
"\n"
|
||||
" -f, --force\n"
|
||||
" -q, --quiet Only print errors\n"
|
||||
@ -137,20 +133,48 @@ int cmd_format(int argc, char *argv[])
|
||||
bool force = false, no_passphrase = false, quiet = false, initialize = true, verbose = false;
|
||||
bool unconsumed_dev_option = false;
|
||||
unsigned v;
|
||||
int opt;
|
||||
|
||||
struct bch_opt_strs fs_opt_strs =
|
||||
bch2_cmdline_opts_get(&argc, argv, OPT_FORMAT);
|
||||
struct bch_opts fs_opts = bch2_parse_opts(fs_opt_strs);
|
||||
struct bch_opt_strs fs_opt_strs = {};
|
||||
struct bch_opts fs_opts = bch2_opts_empty();
|
||||
|
||||
if (getenv("BCACHEFS_KERNEL_ONLY"))
|
||||
initialize = false;
|
||||
|
||||
while ((opt = getopt_long(argc, argv,
|
||||
"-L:l:U:g:fqhv",
|
||||
format_opts,
|
||||
NULL)) != -1)
|
||||
switch (opt) {
|
||||
while (true) {
|
||||
const struct bch_option *opt =
|
||||
bch2_cmdline_opt_parse(argc, argv, OPT_FORMAT|OPT_FS|OPT_DEVICE);
|
||||
if (opt) {
|
||||
unsigned id = opt - bch2_opt_table;
|
||||
u64 v;
|
||||
struct printbuf err = PRINTBUF;
|
||||
int ret = bch2_opt_parse(NULL, opt, optarg, &v, &err);
|
||||
if (ret == -BCH_ERR_option_needs_open_fs) {
|
||||
fs_opt_strs.by_id[id] = strdup(optarg);
|
||||
continue;
|
||||
}
|
||||
if (ret)
|
||||
die("invalid option: %s", err.buf);
|
||||
|
||||
if (opt->flags & OPT_DEVICE) {
|
||||
bch2_opt_set_by_id(&dev_opts.opts, id, v);
|
||||
unconsumed_dev_option = true;
|
||||
} else if (opt->flags & OPT_FS) {
|
||||
bch2_opt_set_by_id(&fs_opts, id, v);
|
||||
} else {
|
||||
die("got bch_opt of wrong type %s", opt->attr.name);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
int optid = getopt_long(argc, argv,
|
||||
"-L:l:U:g:fqhv",
|
||||
format_opts,
|
||||
NULL);
|
||||
if (optid == -1)
|
||||
break;
|
||||
|
||||
switch (optid) {
|
||||
case O_replicas:
|
||||
if (kstrtouint(optarg, 10, &v) ||
|
||||
!v ||
|
||||
@ -183,8 +207,9 @@ int cmd_format(int argc, char *argv[])
|
||||
force = true;
|
||||
break;
|
||||
case O_fs_size:
|
||||
if (bch2_strtoull_h(optarg, &dev_opts.size))
|
||||
if (bch2_strtoull_h(optarg, &dev_opts.opts.fs_size))
|
||||
die("invalid filesystem size");
|
||||
dev_opts.opts.fs_size_defined = true;
|
||||
unconsumed_dev_option = true;
|
||||
break;
|
||||
case O_superblock_size:
|
||||
@ -193,32 +218,11 @@ int cmd_format(int argc, char *argv[])
|
||||
|
||||
opts.superblock_size >>= 9;
|
||||
break;
|
||||
case O_bucket_size:
|
||||
if (bch2_strtoull_h(optarg, &dev_opts.bucket_size))
|
||||
die("bad bucket_size %s", optarg);
|
||||
unconsumed_dev_option = true;
|
||||
break;
|
||||
case O_label:
|
||||
case 'l':
|
||||
dev_opts.label = optarg;
|
||||
unconsumed_dev_option = true;
|
||||
break;
|
||||
case O_discard:
|
||||
dev_opts.discard = true;
|
||||
unconsumed_dev_option = true;
|
||||
break;
|
||||
case O_data_allowed:
|
||||
dev_opts.data_allowed =
|
||||
read_flag_list_or_die(optarg,
|
||||
__bch2_data_types, "data type");
|
||||
unconsumed_dev_option = true;
|
||||
break;
|
||||
case O_durability:
|
||||
if (kstrtouint(optarg, 10, &dev_opts.durability) ||
|
||||
dev_opts.durability > BCH_REPLICAS_MAX)
|
||||
die("invalid durability");
|
||||
unconsumed_dev_option = true;
|
||||
break;
|
||||
case O_version:
|
||||
opts.version = version_parse(optarg);
|
||||
break;
|
||||
@ -229,7 +233,8 @@ int cmd_format(int argc, char *argv[])
|
||||
darray_push(&device_paths, optarg);
|
||||
dev_opts.path = optarg;
|
||||
darray_push(&devices, dev_opts);
|
||||
dev_opts.size = 0;
|
||||
dev_opts.opts.fs_size = 0;
|
||||
dev_opts.opts.fs_size_defined = 0;
|
||||
unconsumed_dev_option = false;
|
||||
break;
|
||||
case O_quiet:
|
||||
@ -241,13 +246,16 @@ int cmd_format(int argc, char *argv[])
|
||||
break;
|
||||
case O_help:
|
||||
case 'h':
|
||||
usage();
|
||||
format_usage();
|
||||
exit(EXIT_SUCCESS);
|
||||
break;
|
||||
case '?':
|
||||
exit(EXIT_FAILURE);
|
||||
break;
|
||||
default:
|
||||
die("getopt ret %i %c", optid, optid);
|
||||
}
|
||||
}
|
||||
|
||||
if (unconsumed_dev_option)
|
||||
die("Options for devices apply to subsequent devices; got a device option with no device");
|
||||
|
@ -159,9 +159,9 @@ static void find_superblock_space(ranges extents,
|
||||
{
|
||||
darray_for_each(extents, i) {
|
||||
u64 start = round_up(max(256ULL << 10, i->start),
|
||||
dev->bucket_size << 9);
|
||||
dev->opts.bucket_size << 9);
|
||||
u64 end = round_down(i->end,
|
||||
dev->bucket_size << 9);
|
||||
dev->opts.bucket_size << 9);
|
||||
|
||||
/* Need space for two superblocks: */
|
||||
if (start + (opts.superblock_size << 9) * 2 <= end) {
|
||||
@ -225,9 +225,9 @@ static int migrate_fs(const char *fs_path,
|
||||
printf("Creating new filesystem on %s in space reserved at %s\n",
|
||||
dev.path, file_path);
|
||||
|
||||
dev.size = get_size(dev.bdev->bd_fd);
|
||||
dev.bucket_size = bch2_pick_bucket_size(fs_opts, &dev);
|
||||
dev.nbuckets = dev.size / dev.bucket_size;
|
||||
dev.opts.fs_size = get_size(dev.bdev->bd_fd);
|
||||
dev.opts.bucket_size = bch2_pick_bucket_size(fs_opts, &dev);
|
||||
dev.nbuckets = dev.opts.fs_size / dev.opts.bucket_size;
|
||||
|
||||
bch2_check_bucket_size(fs_opts, &dev);
|
||||
|
||||
|
@ -30,7 +30,7 @@ static void set_option_usage(void)
|
||||
"Usage: bcachefs set-fs-option [OPTION].. device\n"
|
||||
"\n"
|
||||
"Options:\n");
|
||||
bch2_opts_usage(OPT_MOUNT);
|
||||
bch2_opts_usage(OPT_MOUNT|OPT_RUNTIME);
|
||||
puts(" -d, --dev-idx index for device specific options\n"
|
||||
" -h, --help display this help and exit\n"
|
||||
"Report bugs to <linux-bcachefs@vger.kernel.org>");
|
||||
|
@ -68,26 +68,23 @@ static u64 min_size(unsigned bucket_size)
|
||||
|
||||
u64 bch2_pick_bucket_size(struct bch_opts opts, struct dev_opts *dev)
|
||||
{
|
||||
u64 bucket_size;
|
||||
|
||||
if (dev->size < min_size(opts.block_size))
|
||||
if (dev->opts.fs_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));
|
||||
dev->path, dev->opts.fs_size, min_size(opts.block_size));
|
||||
|
||||
/* Bucket size must be >= block size: */
|
||||
bucket_size = opts.block_size;
|
||||
u64 bucket_size = opts.block_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);
|
||||
bucket_size = max_t(unsigned, bucket_size, opts.btree_node_size);
|
||||
|
||||
/* Want a bucket size of at least 128k, if possible: */
|
||||
bucket_size = max(bucket_size, 128ULL << 10);
|
||||
|
||||
if (dev->size >= min_size(bucket_size)) {
|
||||
if (dev->opts.fs_size >= min_size(bucket_size)) {
|
||||
unsigned scale = max(1,
|
||||
ilog2(dev->size / min_size(bucket_size)) / 4);
|
||||
ilog2(dev->opts.fs_size / min_size(bucket_size)) / 4);
|
||||
|
||||
scale = rounddown_pow_of_two(scale);
|
||||
|
||||
@ -96,7 +93,7 @@ u64 bch2_pick_bucket_size(struct bch_opts opts, struct dev_opts *dev)
|
||||
} else {
|
||||
do {
|
||||
bucket_size /= 2;
|
||||
} while (dev->size < min_size(bucket_size));
|
||||
} while (dev->opts.fs_size < min_size(bucket_size));
|
||||
}
|
||||
|
||||
return bucket_size;
|
||||
@ -104,22 +101,18 @@ u64 bch2_pick_bucket_size(struct bch_opts opts, struct dev_opts *dev)
|
||||
|
||||
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);
|
||||
if (dev->opts.bucket_size < opts.block_size)
|
||||
die("Bucket size (%u) cannot be smaller than block size (%u)",
|
||||
dev->opts.bucket_size, opts.block_size);
|
||||
|
||||
if (opt_defined(opts, btree_node_size) &&
|
||||
dev->bucket_size < opts.btree_node_size)
|
||||
die("Bucket size (%llu) cannot be smaller than btree node size (%u)",
|
||||
dev->bucket_size, opts.btree_node_size);
|
||||
dev->opts.bucket_size < opts.btree_node_size)
|
||||
die("Bucket size (%u) cannot be smaller than btree node size (%u)",
|
||||
dev->opts.bucket_size, opts.btree_node_size);
|
||||
|
||||
if (dev->nbuckets < BCH_MIN_NR_NBUCKETS)
|
||||
die("Not enough buckets: %llu, need %u (bucket size %llu)",
|
||||
dev->nbuckets, BCH_MIN_NR_NBUCKETS, dev->bucket_size);
|
||||
|
||||
if (dev->bucket_size > (u32) U16_MAX << 9)
|
||||
die("Bucket size (%llu) too big (max %u)",
|
||||
dev->bucket_size, (u32) U16_MAX << 9);
|
||||
die("Not enough buckets: %llu, need %u (bucket size %u)",
|
||||
dev->nbuckets, BCH_MIN_NR_NBUCKETS, dev->opts.bucket_size);
|
||||
}
|
||||
|
||||
static unsigned parse_target(struct bch_sb_handle *sb,
|
||||
@ -144,6 +137,17 @@ static unsigned parse_target(struct bch_sb_handle *sb,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bch2_opt_set_sb_all(struct bch_sb *sb, int dev_idx, struct bch_opts *opts)
|
||||
{
|
||||
for (unsigned id = 0; id < bch2_opts_nr; id++) {
|
||||
u64 v = bch2_opt_defined_by_id(opts, id)
|
||||
? bch2_opt_get_by_id(opts, id)
|
||||
: bch2_opt_get_by_id(&bch2_opts_default, id);
|
||||
|
||||
__bch2_opt_set_sb(sb, dev_idx, &bch2_opt_table[id], v);
|
||||
}
|
||||
}
|
||||
|
||||
struct bch_sb *bch2_format(struct bch_opt_strs fs_opt_strs,
|
||||
struct bch_opts fs_opts,
|
||||
struct format_opts opts,
|
||||
@ -153,47 +157,45 @@ struct bch_sb *bch2_format(struct bch_opt_strs fs_opt_strs,
|
||||
struct bch_sb_handle sb = { NULL };
|
||||
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_fd));
|
||||
|
||||
/* calculate block size: */
|
||||
if (!opt_defined(fs_opts, block_size)) {
|
||||
if (!opt_defined(fs_opts, block_size))
|
||||
opt_set(fs_opts, block_size, max_dev_block_size);
|
||||
} else if (fs_opts.block_size < max_dev_block_size)
|
||||
|
||||
if (fs_opts.block_size < max_dev_block_size)
|
||||
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_fd);
|
||||
if (!opt_defined(i->opts, fs_size))
|
||||
opt_set(i->opts, fs_size, get_size(i->bdev->bd_fd));
|
||||
|
||||
/* calculate bucket sizes: */
|
||||
for (i = devs; i < devs + nr_devs; i++)
|
||||
min_bucket_size = min(min_bucket_size,
|
||||
i->bucket_size ?: bch2_pick_bucket_size(fs_opts, i));
|
||||
i->opts.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;
|
||||
if (!opt_defined(i->opts, bucket_size))
|
||||
opt_set(i->opts, bucket_size, min_bucket_size);
|
||||
|
||||
for (i = devs; i < devs + nr_devs; i++) {
|
||||
i->nbuckets = i->size / i->bucket_size;
|
||||
i->nbuckets = i->opts.fs_size / i->opts.bucket_size;
|
||||
bch2_check_bucket_size(fs_opts, i);
|
||||
}
|
||||
|
||||
/* calculate btree node size: */
|
||||
if (!opt_defined(fs_opts, btree_node_size)) {
|
||||
/* 256k default btree node size */
|
||||
opt_set(fs_opts, btree_node_size, 256 << 10);
|
||||
unsigned s = bch2_opts_default.btree_node_size;
|
||||
|
||||
for (i = devs; i < devs + nr_devs; i++)
|
||||
fs_opts.btree_node_size =
|
||||
min_t(unsigned, fs_opts.btree_node_size,
|
||||
i->bucket_size);
|
||||
s = min(s, i->opts.bucket_size);
|
||||
opt_set(fs_opts, btree_node_size, s);
|
||||
}
|
||||
|
||||
if (uuid_is_null(opts.uuid.b))
|
||||
@ -219,17 +221,7 @@ struct bch_sb *bch2_format(struct bch_opt_strs fs_opt_strs,
|
||||
opts.label,
|
||||
min(strlen(opts.label), sizeof(sb.sb->label)));
|
||||
|
||||
for (opt_id = 0;
|
||||
opt_id < bch2_opts_nr;
|
||||
opt_id++) {
|
||||
u64 v;
|
||||
|
||||
v = bch2_opt_defined_by_id(&fs_opts, opt_id)
|
||||
? bch2_opt_get_by_id(&fs_opts, opt_id)
|
||||
: bch2_opt_get_by_id(&bch2_opts_default, opt_id);
|
||||
|
||||
__bch2_opt_set_sb(sb.sb, -1, &bch2_opt_table[opt_id], v);
|
||||
}
|
||||
bch2_opt_set_sb_all(sb.sb, -1, &fs_opts);
|
||||
|
||||
struct timespec now;
|
||||
if (clock_gettime(CLOCK_REALTIME, &now))
|
||||
@ -245,16 +237,13 @@ struct bch_sb *bch2_format(struct bch_opt_strs fs_opt_strs,
|
||||
nr_devs) / sizeof(u64));
|
||||
mi->member_bytes = cpu_to_le16(sizeof(struct bch_member));
|
||||
for (i = devs; i < devs + nr_devs; i++) {
|
||||
struct bch_member *m = bch2_members_v2_get_mut(sb.sb, (i - devs));
|
||||
unsigned idx = i - devs;
|
||||
struct bch_member *m = bch2_members_v2_get_mut(sb.sb, idx);
|
||||
|
||||
uuid_generate(m->uuid.b);
|
||||
m->nbuckets = cpu_to_le64(i->nbuckets);
|
||||
m->first_bucket = 0;
|
||||
m->bucket_size = cpu_to_le16(i->bucket_size >> 9);
|
||||
|
||||
SET_BCH_MEMBER_DISCARD(m, i->discard);
|
||||
SET_BCH_MEMBER_DATA_ALLOWED(m, i->data_allowed);
|
||||
SET_BCH_MEMBER_DURABILITY(m, i->durability + 1);
|
||||
bch2_opt_set_sb_all(sb.sb, idx, &i->opts);
|
||||
}
|
||||
|
||||
/* Disk labels*/
|
||||
@ -298,7 +287,7 @@ struct bch_sb *bch2_format(struct bch_opt_strs fs_opt_strs,
|
||||
bch2_sb_members_cpy_v2_v1(&sb);
|
||||
|
||||
for (i = devs; i < devs + nr_devs; i++) {
|
||||
u64 size_sectors = i->size >> 9;
|
||||
u64 size_sectors = i->opts.fs_size >> 9;
|
||||
|
||||
sb.sb->dev_idx = i - devs;
|
||||
|
||||
@ -322,7 +311,7 @@ struct bch_sb *bch2_format(struct bch_opt_strs fs_opt_strs,
|
||||
struct bch_sb_layout *l = &sb.sb->layout;
|
||||
u64 backup_sb = size_sectors - (1 << l->sb_max_size_bits);
|
||||
|
||||
backup_sb = rounddown(backup_sb, i->bucket_size >> 9);
|
||||
backup_sb = rounddown(backup_sb, i->opts.bucket_size >> 9);
|
||||
l->sb_offset[l->nr_superblocks++] = cpu_to_le64(backup_sb);
|
||||
}
|
||||
|
||||
@ -619,6 +608,8 @@ int bchu_data(struct bchfs_handle fs, struct bch_ioctl_data cmd)
|
||||
|
||||
/* option parsing */
|
||||
|
||||
#include <getopt.h>
|
||||
|
||||
void bch2_opt_strs_free(struct bch_opt_strs *opts)
|
||||
{
|
||||
unsigned i;
|
||||
@ -629,6 +620,64 @@ void bch2_opt_strs_free(struct bch_opt_strs *opts)
|
||||
}
|
||||
}
|
||||
|
||||
static bool opt_type_filter(const struct bch_option *opt, unsigned opt_types)
|
||||
{
|
||||
if (!(opt->flags & opt_types))
|
||||
return false;
|
||||
|
||||
if ((opt_types & OPT_FORMAT) &&
|
||||
!opt->set_sb && !opt->set_member)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const struct bch_option *bch2_cmdline_opt_parse(int argc, char *argv[],
|
||||
unsigned opt_types)
|
||||
{
|
||||
if (optind >= argc)
|
||||
return NULL;
|
||||
|
||||
if (argv[optind][0] != '-' ||
|
||||
argv[optind][1] != '-')
|
||||
return NULL;
|
||||
|
||||
char *optstr = strdup(argv[optind] + 2);
|
||||
optarg = argv[optind + 1];
|
||||
|
||||
char *eq = strchr(optstr, '=');
|
||||
if (eq) {
|
||||
*eq = '\0';
|
||||
optarg = eq + 1;
|
||||
}
|
||||
|
||||
if (!optarg)
|
||||
optarg = "1";
|
||||
|
||||
|
||||
int optid = bch2_opt_lookup(optstr);
|
||||
if (optid < 0)
|
||||
goto noopt;
|
||||
|
||||
const struct bch_option *opt = bch2_opt_table + optid;
|
||||
if (!opt_type_filter(opt, opt_types))
|
||||
goto noopt;
|
||||
|
||||
optind++;
|
||||
|
||||
if (opt->type != BCH_OPT_BOOL) {
|
||||
if (optarg == argv[optind])
|
||||
optind++;
|
||||
} else {
|
||||
optarg = NULL;
|
||||
}
|
||||
|
||||
return opt;
|
||||
noopt:
|
||||
free(optstr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct bch_opt_strs bch2_cmdline_opts_get(int *argc, char *argv[],
|
||||
unsigned opt_types)
|
||||
{
|
||||
@ -716,19 +765,17 @@ struct bch_opts bch2_parse_opts(struct bch_opt_strs strs)
|
||||
#define newline(c) \
|
||||
do { \
|
||||
printf("\n"); \
|
||||
c = 0; \
|
||||
c = 0; \
|
||||
} while(0)
|
||||
void bch2_opts_usage(unsigned opt_types)
|
||||
{
|
||||
const struct bch_option *opt;
|
||||
unsigned i, c = 0, helpcol = 30;
|
||||
|
||||
|
||||
|
||||
for (opt = bch2_opt_table;
|
||||
opt < bch2_opt_table + bch2_opts_nr;
|
||||
opt++) {
|
||||
if (!(opt->flags & opt_types))
|
||||
if (!opt_type_filter(opt, opt_types))
|
||||
continue;
|
||||
|
||||
c += printf(" --%s", opt->attr.name);
|
||||
|
@ -28,6 +28,9 @@ struct {
|
||||
};
|
||||
|
||||
void bch2_opt_strs_free(struct bch_opt_strs *);
|
||||
|
||||
const struct bch_option *bch2_cmdline_opt_parse(int argc, char *argv[],
|
||||
unsigned opt_types);
|
||||
struct bch_opt_strs bch2_cmdline_opts_get(int *, char *[], unsigned);
|
||||
struct bch_opts bch2_parse_opts(struct bch_opt_strs);
|
||||
void bch2_opts_usage(unsigned);
|
||||
@ -58,25 +61,20 @@ struct dev_opts {
|
||||
struct file *file;
|
||||
struct block_device *bdev;
|
||||
char *path;
|
||||
u64 size; /* bytes*/
|
||||
u64 bucket_size; /* bytes */
|
||||
const char *label;
|
||||
unsigned data_allowed;
|
||||
unsigned durability;
|
||||
bool discard;
|
||||
|
||||
u64 nbuckets;
|
||||
|
||||
u64 sb_offset;
|
||||
u64 sb_end;
|
||||
|
||||
u64 nbuckets;
|
||||
|
||||
const char *label; /* make this a bch_opt */
|
||||
|
||||
struct bch_opts opts;
|
||||
};
|
||||
|
||||
static inline struct dev_opts dev_opts_default()
|
||||
{
|
||||
return (struct dev_opts) {
|
||||
.data_allowed = ~0U << 2,
|
||||
.durability = 1,
|
||||
};
|
||||
return (struct dev_opts) { .opts = bch2_opts_empty() };
|
||||
}
|
||||
|
||||
void bch2_sb_layout_init(struct bch_sb_layout *,
|
||||
|
@ -684,12 +684,10 @@ void __bch2_opt_set_sb(struct bch_sb *sb, int dev_idx,
|
||||
if (opt->flags & OPT_SB_FIELD_ONE_BIAS)
|
||||
v++;
|
||||
|
||||
if ((opt->flags & OPT_FS) && opt->set_sb)
|
||||
if ((opt->flags & OPT_FS) && opt->set_sb && dev_idx < 0)
|
||||
opt->set_sb(sb, v);
|
||||
|
||||
if ((opt->flags & OPT_DEVICE) &&
|
||||
opt->set_member &&
|
||||
dev_idx >= 0) {
|
||||
if ((opt->flags & OPT_DEVICE) && opt->set_member && dev_idx >= 0) {
|
||||
if (WARN(!bch2_member_exists(sb, dev_idx),
|
||||
"tried to set device option %s on nonexistent device %i",
|
||||
opt->attr.name, dev_idx))
|
||||
|
@ -128,13 +128,13 @@ enum fsck_err_opts {
|
||||
OPT_FS|OPT_FORMAT| \
|
||||
OPT_HUMAN_READABLE|OPT_MUST_BE_POW_2|OPT_SB_FIELD_SECTORS, \
|
||||
OPT_UINT(512, 1U << 16), \
|
||||
BCH_SB_BLOCK_SIZE, 8, \
|
||||
BCH_SB_BLOCK_SIZE, 4 << 10, \
|
||||
"size", NULL) \
|
||||
x(btree_node_size, u32, \
|
||||
OPT_FS|OPT_FORMAT| \
|
||||
OPT_HUMAN_READABLE|OPT_MUST_BE_POW_2|OPT_SB_FIELD_SECTORS, \
|
||||
OPT_UINT(512, 1U << 20), \
|
||||
BCH_SB_BTREE_NODE_SIZE, 512, \
|
||||
BCH_SB_BTREE_NODE_SIZE, 256 << 10, \
|
||||
"size", "Btree node size, default 256k") \
|
||||
x(errors, u8, \
|
||||
OPT_FS|OPT_FORMAT|OPT_MOUNT|OPT_RUNTIME, \
|
||||
|
Loading…
Reference in New Issue
Block a user