diff --git a/c_src/cmd_device.c b/c_src/cmd_device.c index c86fb7f1..a1e78e25 100644 --- a/c_src/cmd_device.c +++ b/c_src/cmd_device.c @@ -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(); diff --git a/c_src/cmd_format.c b/c_src/cmd_format.c index b103d2bd..4fbf3a4b 100644 --- a/c_src/cmd_format.c +++ b/c_src/cmd_format.c @@ -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"); diff --git a/c_src/cmd_migrate.c b/c_src/cmd_migrate.c index bce115b7..698cfd55 100644 --- a/c_src/cmd_migrate.c +++ b/c_src/cmd_migrate.c @@ -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); diff --git a/c_src/cmd_option.c b/c_src/cmd_option.c index 99e397b9..02faca07 100644 --- a/c_src/cmd_option.c +++ b/c_src/cmd_option.c @@ -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>"); diff --git a/c_src/libbcachefs.c b/c_src/libbcachefs.c index c3af991b..d212b6ef 100644 --- a/c_src/libbcachefs.c +++ b/c_src/libbcachefs.c @@ -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); diff --git a/c_src/libbcachefs.h b/c_src/libbcachefs.h index 026a3def..05ba1069 100644 --- a/c_src/libbcachefs.h +++ b/c_src/libbcachefs.h @@ -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 *, diff --git a/libbcachefs/opts.c b/libbcachefs/opts.c index a980b38b..24a46103 100644 --- a/libbcachefs/opts.c +++ b/libbcachefs/opts.c @@ -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)) diff --git a/libbcachefs/opts.h b/libbcachefs/opts.h index 0bf39e4b..8d1dc881 100644 --- a/libbcachefs/opts.h +++ b/libbcachefs/opts.h @@ -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, \