mirror of
https://github.com/koverstreet/bcachefs-tools.git
synced 2025-02-23 00:00:02 +03:00
Use opts.h for format options
This commit is contained in:
parent
99ccaf73a8
commit
0e9822571c
18
cmd_device.c
18
cmd_device.c
@ -95,12 +95,20 @@ int cmd_device_add(int argc, char *argv[])
|
|||||||
dev_opts.path = dev_path;
|
dev_opts.path = dev_path;
|
||||||
dev_opts.fd = open_for_format(dev_opts.path, force);
|
dev_opts.fd = open_for_format(dev_opts.path, force);
|
||||||
|
|
||||||
format_opts.block_size =
|
struct bch_opt_strs fs_opt_strs;
|
||||||
read_file_u64(fs.sysfs_fd, "block_size") >> 9;
|
memset(&fs_opt_strs, 0, sizeof(fs_opt_strs));
|
||||||
format_opts.btree_node_size =
|
|
||||||
read_file_u64(fs.sysfs_fd, "btree_node_size") >> 9;
|
|
||||||
|
|
||||||
struct bch_sb *sb = bch2_format(format_opts, &dev_opts, 1);
|
struct bch_opts fs_opts = bch2_parse_opts(fs_opt_strs);
|
||||||
|
|
||||||
|
opt_set(fs_opts, block_size,
|
||||||
|
read_file_u64(fs.sysfs_fd, "block_size") >> 9);
|
||||||
|
opt_set(fs_opts, btree_node_size,
|
||||||
|
read_file_u64(fs.sysfs_fd, "btree_node_size") >> 9);
|
||||||
|
|
||||||
|
struct bch_sb *sb = bch2_format(fs_opt_strs,
|
||||||
|
fs_opts,
|
||||||
|
format_opts,
|
||||||
|
&dev_opts, 1);
|
||||||
free(sb);
|
free(sb);
|
||||||
fsync(dev_opts.fd);
|
fsync(dev_opts.fd);
|
||||||
close(dev_opts.fd);
|
close(dev_opts.fd);
|
||||||
|
193
cmd_format.c
193
cmd_format.c
@ -5,6 +5,7 @@
|
|||||||
*
|
*
|
||||||
* GPLv2
|
* GPLv2
|
||||||
*/
|
*/
|
||||||
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
@ -28,109 +29,72 @@
|
|||||||
#include "libbcachefs/super-io.h"
|
#include "libbcachefs/super-io.h"
|
||||||
#include "libbcachefs/util.h"
|
#include "libbcachefs/util.h"
|
||||||
|
|
||||||
#define OPTS \
|
#define OPTS \
|
||||||
t("bcachefs format - create a new bcachefs filesystem on one or more devices") \
|
x(0, replicas, required_argument) \
|
||||||
t("Usage: bcachefs format [OPTION]... <devices>") \
|
x(0, encrypted, no_argument) \
|
||||||
t("") \
|
x(0, no_passphrase, no_argument) \
|
||||||
x('b', block_size, "size", NULL) \
|
x('L', label, required_argument) \
|
||||||
x(0, btree_node_size, "size", "Default 256k") \
|
x('U', uuid, required_argument) \
|
||||||
x(0, metadata_checksum_type, "(none|crc32c|crc64)", NULL) \
|
x(0, fs_size, required_argument) \
|
||||||
x(0, data_checksum_type, "(none|crc32c|crc64)", NULL) \
|
x(0, bucket_size, required_argument) \
|
||||||
x(0, compression_type, "(none|lz4|gzip)", NULL) \
|
x('g', group, required_argument) \
|
||||||
x(0, background_compression_type, "(none|lz4|gzip)", NULL) \
|
x(0, discard, no_argument) \
|
||||||
x(0, replicas, "#", NULL) \
|
x(0, data_allowed, required_argument) \
|
||||||
x(0, data_replicas, "#", NULL) \
|
x(0, durability, required_argument) \
|
||||||
x(0, metadata_replicas, "#", NULL) \
|
x('f', force, no_argument) \
|
||||||
x(0, foreground_target, "target", NULL) \
|
x('q', quiet, no_argument) \
|
||||||
x(0, background_target, "target", NULL) \
|
x('h', help, no_argument)
|
||||||
x(0, promote_target, "target", NULL) \
|
|
||||||
x(0, encrypted, NULL, "Enable whole filesystem encryption (chacha20/poly1305)")\
|
|
||||||
x(0, no_passphrase, NULL, "Don't encrypt master encryption key")\
|
|
||||||
x('e', error_action, "(continue|remount-ro|panic)", NULL) \
|
|
||||||
x('L', label, "label", NULL) \
|
|
||||||
x('U', uuid, "uuid", NULL) \
|
|
||||||
x('f', force, NULL, NULL) \
|
|
||||||
t("") \
|
|
||||||
t("Device specific options:") \
|
|
||||||
x(0, fs_size, "size", "Size of filesystem on device")\
|
|
||||||
x(0, bucket_size, "size", "Bucket size") \
|
|
||||||
x('g', group, "label", "Disk group")\
|
|
||||||
x(0, discard, NULL, NULL) \
|
|
||||||
x(0, data_allowed, "journal,btree,data", "Allowed types of data on this device")\
|
|
||||||
x(0, durability, "#", "Number of times data written to this device will have been considered replicated")\
|
|
||||||
t("Device specific options must come before corresponding devices, e.g.") \
|
|
||||||
t(" bcachefs format --group cache /dev/sdb --tier 1 /dev/sdc") \
|
|
||||||
t("") \
|
|
||||||
x('q', quiet, NULL, "Only print errors") \
|
|
||||||
x('h', help, NULL, "Display this help and exit")
|
|
||||||
|
|
||||||
static void usage(void)
|
static void usage(void)
|
||||||
{
|
{
|
||||||
#define t(text) puts(text "\n")
|
|
||||||
#define x(shortopt, longopt, arg, help) do { \
|
|
||||||
OPTS
|
|
||||||
#undef x
|
|
||||||
#undef t
|
|
||||||
|
|
||||||
puts("bcachefs format - create a new bcachefs filesystem on one or more devices\n"
|
puts("bcachefs format - create a new bcachefs filesystem on one or more devices\n"
|
||||||
"Usage: bcachefs format [OPTION]... <devices>\n"
|
"Usage: bcachefs format [OPTION]... <devices>\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Options:\n"
|
"Options:");
|
||||||
" -b, --block=size\n"
|
|
||||||
" --btree_node=size Btree node size, default 256k\n"
|
bch2_opts_usage(OPT_FORMAT);
|
||||||
" --metadata_checksum_type=(none|crc32c|crc64)\n"
|
|
||||||
" --data_checksum_type=(none|crc32c|crc64)\n"
|
puts(
|
||||||
" --compression_type=(none|lz4|gzip|zstd)\n"
|
|
||||||
" --background_compression_type=(none|lz4|gzip|zstd)\n"
|
|
||||||
" --data_replicas=# Number of data replicas\n"
|
|
||||||
" --metadata_replicas=# Number of metadata replicas\n"
|
|
||||||
" --replicas=# Sets both data and metadata replicas\n"
|
" --replicas=# Sets both data and metadata replicas\n"
|
||||||
" --encrypted Enable whole filesystem encryption (chacha20/poly1305)\n"
|
" --encrypted Enable whole filesystem encryption (chacha20/poly1305)\n"
|
||||||
" --no_passphrase Don't encrypt master encryption key\n"
|
" --no_passphrase Don't encrypt master encryption key\n"
|
||||||
" -e, --error_action=(continue|remount-ro|panic)\n"
|
|
||||||
" Action to take on filesystem error\n"
|
|
||||||
" -L, --label=label\n"
|
" -L, --label=label\n"
|
||||||
" -U, --uuid=uuid\n"
|
" -U, --uuid=uuid\n"
|
||||||
|
"\n"
|
||||||
|
"Device specific options:");
|
||||||
|
|
||||||
|
bch2_opts_usage(OPT_DEVICE);
|
||||||
|
|
||||||
|
puts(" -g, --group=label Disk group\n"
|
||||||
|
"\n"
|
||||||
" -f, --force\n"
|
" -f, --force\n"
|
||||||
"\n"
|
|
||||||
"Device specific options:\n"
|
|
||||||
" --fs_size=size Size of filesystem on device\n"
|
|
||||||
" --bucket=size Bucket size\n"
|
|
||||||
" --discard Enable discards\n"
|
|
||||||
" --durability=# Device durability (0-4)\n"
|
|
||||||
" -g, --group=label Disk group\n"
|
|
||||||
"\n"
|
|
||||||
" -q, --quiet Only print errors\n"
|
" -q, --quiet Only print errors\n"
|
||||||
" -h, --help Display this help and exit\n"
|
" -h, --help Display this help and exit\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Device specific options must come before corresponding devices, e.g.\n"
|
"Device specific options must come before corresponding devices, e.g.\n"
|
||||||
" bcachefs format --group cache /dev/sdb --tier 1 /dev/sdc\n"
|
" bcachefs format --group cache /dev/sdb /dev/sdc\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Report bugs to <linux-bcache@vger.kernel.org>");
|
"Report bugs to <linux-bcache@vger.kernel.org>");
|
||||||
}
|
}
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
O_no_opt = 1,
|
O_no_opt = 1,
|
||||||
#define t(text)
|
#define x(shortopt, longopt, arg) O_##longopt,
|
||||||
#define x(shortopt, longopt, arg, help) O_##longopt,
|
|
||||||
OPTS
|
OPTS
|
||||||
#undef x
|
#undef x
|
||||||
#undef t
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct option format_opts[] = {
|
#define x(shortopt, longopt, arg) { \
|
||||||
#define t(text)
|
.name = #longopt, \
|
||||||
#define x(shortopt, longopt, arg, help) { \
|
.has_arg = arg, \
|
||||||
.name = #longopt, \
|
.flag = NULL, \
|
||||||
.has_arg = arg ? required_argument : no_argument, \
|
.val = O_##longopt, \
|
||||||
.flag = NULL, \
|
|
||||||
.val = O_##longopt, \
|
|
||||||
},
|
},
|
||||||
|
static const struct option format_opts[] = {
|
||||||
OPTS
|
OPTS
|
||||||
#undef x
|
|
||||||
#undef t
|
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
#undef x
|
||||||
|
|
||||||
u64 read_flag_list_or_die(char *opt, const char * const list[],
|
u64 read_flag_list_or_die(char *opt, const char * const list[],
|
||||||
const char *msg)
|
const char *msg)
|
||||||
@ -148,73 +112,28 @@ int cmd_format(int argc, char *argv[])
|
|||||||
struct format_opts opts = format_opts_default();
|
struct format_opts opts = format_opts_default();
|
||||||
struct dev_opts dev_opts = dev_opts_default(), *dev;
|
struct dev_opts dev_opts = dev_opts_default(), *dev;
|
||||||
bool force = false, no_passphrase = false, quiet = false;
|
bool force = false, no_passphrase = false, quiet = false;
|
||||||
|
unsigned v;
|
||||||
int opt;
|
int opt;
|
||||||
|
|
||||||
darray_init(devices);
|
darray_init(devices);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
while ((opt = getopt_long(argc, argv,
|
while ((opt = getopt_long(argc, argv,
|
||||||
"-b:e:g:L:U:fqh",
|
"-L:U:fh",
|
||||||
format_opts,
|
format_opts,
|
||||||
NULL)) != -1)
|
NULL)) != -1)
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case O_block_size:
|
|
||||||
case 'b':
|
|
||||||
opts.block_size =
|
|
||||||
hatoi_validate(optarg, "block size");
|
|
||||||
break;
|
|
||||||
case O_btree_node_size:
|
|
||||||
opts.btree_node_size =
|
|
||||||
hatoi_validate(optarg, "btree node size");
|
|
||||||
break;
|
|
||||||
case O_metadata_checksum_type:
|
|
||||||
opts.meta_csum_type =
|
|
||||||
read_string_list_or_die(optarg,
|
|
||||||
bch2_csum_types, "checksum type");
|
|
||||||
break;
|
|
||||||
case O_data_checksum_type:
|
|
||||||
opts.data_csum_type =
|
|
||||||
read_string_list_or_die(optarg,
|
|
||||||
bch2_csum_types, "checksum type");
|
|
||||||
break;
|
|
||||||
case O_compression_type:
|
|
||||||
opts.compression_type =
|
|
||||||
read_string_list_or_die(optarg,
|
|
||||||
bch2_compression_types,
|
|
||||||
"compression type");
|
|
||||||
break;
|
|
||||||
case O_background_compression_type:
|
|
||||||
opts.background_compression_type =
|
|
||||||
read_string_list_or_die(optarg,
|
|
||||||
bch2_compression_types,
|
|
||||||
"compression type");
|
|
||||||
break;
|
|
||||||
case O_data_replicas:
|
|
||||||
if (kstrtouint(optarg, 10, &opts.data_replicas) ||
|
|
||||||
!opts.data_replicas ||
|
|
||||||
opts.data_replicas > BCH_REPLICAS_MAX)
|
|
||||||
die("invalid replicas");
|
|
||||||
break;
|
|
||||||
case O_metadata_replicas:
|
|
||||||
if (kstrtouint(optarg, 10, &opts.meta_replicas) ||
|
|
||||||
!opts.meta_replicas ||
|
|
||||||
opts.meta_replicas > BCH_REPLICAS_MAX)
|
|
||||||
die("invalid replicas");
|
|
||||||
break;
|
|
||||||
case O_replicas:
|
case O_replicas:
|
||||||
if (kstrtouint(optarg, 10, &opts.data_replicas) ||
|
if (kstrtouint(optarg, 10, &v) ||
|
||||||
!opts.data_replicas ||
|
!v ||
|
||||||
opts.data_replicas > BCH_REPLICAS_MAX)
|
v > BCH_REPLICAS_MAX)
|
||||||
die("invalid replicas");
|
die("invalid replicas");
|
||||||
opts.meta_replicas = opts.data_replicas;
|
|
||||||
break;
|
opt_set(fs_opts, metadata_replicas, v);
|
||||||
case O_foreground_target:
|
opt_set(fs_opts, data_replicas, v);
|
||||||
opts.foreground_target = optarg;
|
|
||||||
break;
|
|
||||||
case O_background_target:
|
|
||||||
opts.background_target = optarg;
|
|
||||||
break;
|
|
||||||
case O_promote_target:
|
|
||||||
opts.promote_target = optarg;
|
|
||||||
break;
|
break;
|
||||||
case O_encrypted:
|
case O_encrypted:
|
||||||
opts.encrypted = true;
|
opts.encrypted = true;
|
||||||
@ -222,12 +141,6 @@ int cmd_format(int argc, char *argv[])
|
|||||||
case O_no_passphrase:
|
case O_no_passphrase:
|
||||||
no_passphrase = true;
|
no_passphrase = true;
|
||||||
break;
|
break;
|
||||||
case O_error_action:
|
|
||||||
case 'e':
|
|
||||||
opts.on_error_action =
|
|
||||||
read_string_list_or_die(optarg,
|
|
||||||
bch2_error_actions, "error action");
|
|
||||||
break;
|
|
||||||
case O_label:
|
case O_label:
|
||||||
case 'L':
|
case 'L':
|
||||||
opts.label = optarg;
|
opts.label = optarg;
|
||||||
@ -282,6 +195,9 @@ int cmd_format(int argc, char *argv[])
|
|||||||
usage();
|
usage();
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
break;
|
break;
|
||||||
|
case '?':
|
||||||
|
die("unrecognized option %s", optarg);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (darray_empty(devices))
|
if (darray_empty(devices))
|
||||||
@ -294,7 +210,10 @@ int cmd_format(int argc, char *argv[])
|
|||||||
dev->fd = open_for_format(dev->path, force);
|
dev->fd = open_for_format(dev->path, force);
|
||||||
|
|
||||||
struct bch_sb *sb =
|
struct bch_sb *sb =
|
||||||
bch2_format(opts, devices.item, darray_size(devices));
|
bch2_format(fs_opt_strs,
|
||||||
|
fs_opts,
|
||||||
|
opts,
|
||||||
|
devices.item, darray_size(devices));
|
||||||
|
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
bch2_sb_print(sb, false, 1 << BCH_SB_FIELD_members, HUMAN_READABLE);
|
bch2_sb_print(sb, false, 1 << BCH_SB_FIELD_members, HUMAN_READABLE);
|
||||||
|
@ -185,13 +185,13 @@ static struct bch_inode_unpacked create_file(struct bch_fs *c,
|
|||||||
(handler) != NULL; \
|
(handler) != NULL; \
|
||||||
(handler) = *(handlers)++)
|
(handler) = *(handlers)++)
|
||||||
|
|
||||||
static const struct xattr_handler *xattr_resolve_name(const char **name)
|
static const struct xattr_handler *xattr_resolve_name(char **name)
|
||||||
{
|
{
|
||||||
const struct xattr_handler **handlers = bch2_xattr_handlers;
|
const struct xattr_handler **handlers = bch2_xattr_handlers;
|
||||||
const struct xattr_handler *handler;
|
const struct xattr_handler *handler;
|
||||||
|
|
||||||
for_each_xattr_handler(handlers, handler) {
|
for_each_xattr_handler(handlers, handler) {
|
||||||
const char *n;
|
char *n;
|
||||||
|
|
||||||
n = strcmp_prefix(*name, xattr_prefix(handler));
|
n = strcmp_prefix(*name, xattr_prefix(handler));
|
||||||
if (n) {
|
if (n) {
|
||||||
@ -225,7 +225,7 @@ static void copy_xattrs(struct bch_fs *c, struct bch_inode_unpacked *dst,
|
|||||||
if (attrs_size < 0)
|
if (attrs_size < 0)
|
||||||
die("listxattr error: %m");
|
die("listxattr error: %m");
|
||||||
|
|
||||||
const char *next, *attr;
|
char *next, *attr;
|
||||||
for (attr = attrs;
|
for (attr = attrs;
|
||||||
attr < attrs + attrs_size;
|
attr < attrs + attrs_size;
|
||||||
attr = next) {
|
attr = next) {
|
||||||
@ -657,8 +657,10 @@ static const struct option migrate_opts[] = {
|
|||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
static int migrate_fs(const char *fs_path,
|
static int migrate_fs(const char *fs_path,
|
||||||
struct format_opts format_opts,
|
struct bch_opt_strs fs_opt_strs,
|
||||||
|
struct bch_opts fs_opts,
|
||||||
|
struct format_opts format_opts,
|
||||||
bool force)
|
bool force)
|
||||||
{
|
{
|
||||||
if (!path_is_fs_root(fs_path))
|
if (!path_is_fs_root(fs_path))
|
||||||
@ -675,25 +677,24 @@ static int migrate_fs(const char *fs_path,
|
|||||||
dev.path = dev_t_to_path(stat.st_dev);
|
dev.path = dev_t_to_path(stat.st_dev);
|
||||||
dev.fd = xopen(dev.path, O_RDWR);
|
dev.fd = xopen(dev.path, O_RDWR);
|
||||||
|
|
||||||
unsigned block_size = get_blocksize(dev.path, dev.fd) << 9;
|
opt_set(fs_opts, block_size, get_blocksize(dev.path, dev.fd));
|
||||||
BUG_ON(!is_power_of_2(block_size) || block_size < 512);
|
|
||||||
format_opts.block_size = block_size >> 9;
|
|
||||||
|
|
||||||
char *file_path = mprintf("%s/bcachefs", fs_path);
|
char *file_path = mprintf("%s/bcachefs", 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(format_opts, &dev);
|
bch2_pick_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,
|
||||||
format_opts.block_size << 9,
|
fs_opts.block_size << 9,
|
||||||
get_size(dev.path, dev.fd) / 5,
|
get_size(dev.path, dev.fd) / 5,
|
||||||
&bcachefs_inum, stat.st_dev, force);
|
&bcachefs_inum, stat.st_dev, force);
|
||||||
|
|
||||||
find_superblock_space(extents, &dev);
|
find_superblock_space(extents, &dev);
|
||||||
|
|
||||||
struct bch_sb *sb = bch2_format(format_opts, &dev, 1);
|
struct bch_sb *sb = bch2_format(fs_opt_strs,
|
||||||
|
fs_opts,format_opts, &dev, 1);
|
||||||
u64 sb_offset = le64_to_cpu(sb->layout.sb_offset[0]);
|
u64 sb_offset = le64_to_cpu(sb->layout.sb_offset[0]);
|
||||||
|
|
||||||
if (format_opts.passphrase)
|
if (format_opts.passphrase)
|
||||||
@ -757,6 +758,10 @@ int cmd_migrate(int argc, char *argv[])
|
|||||||
bool no_passphrase = false, force = false;
|
bool no_passphrase = false, force = false;
|
||||||
int opt;
|
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);
|
||||||
|
|
||||||
while ((opt = getopt_long(argc, argv, "f:Fh",
|
while ((opt = getopt_long(argc, argv, "f:Fh",
|
||||||
migrate_opts, NULL)) != -1)
|
migrate_opts, NULL)) != -1)
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
@ -783,7 +788,10 @@ int cmd_migrate(int argc, char *argv[])
|
|||||||
if (format_opts.encrypted && !no_passphrase)
|
if (format_opts.encrypted && !no_passphrase)
|
||||||
format_opts.passphrase = read_passphrase_twice("Enter passphrase: ");
|
format_opts.passphrase = read_passphrase_twice("Enter passphrase: ");
|
||||||
|
|
||||||
return migrate_fs(fs_path, format_opts, force);
|
return migrate_fs(fs_path,
|
||||||
|
fs_opt_strs,
|
||||||
|
fs_opts,
|
||||||
|
format_opts, force);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void migrate_superblock_usage(void)
|
static void migrate_superblock_usage(void)
|
||||||
|
237
libbcachefs.c
237
libbcachefs.c
@ -23,6 +23,7 @@
|
|||||||
#include "libbcachefs/opts.h"
|
#include "libbcachefs/opts.h"
|
||||||
#include "libbcachefs/replicas.h"
|
#include "libbcachefs/replicas.h"
|
||||||
#include "libbcachefs/super-io.h"
|
#include "libbcachefs/super-io.h"
|
||||||
|
#include "tools-util.h"
|
||||||
|
|
||||||
#define NSEC_PER_SEC 1000000000L
|
#define NSEC_PER_SEC 1000000000L
|
||||||
|
|
||||||
@ -71,7 +72,7 @@ static void init_layout(struct bch_sb_layout *l, unsigned block_size,
|
|||||||
l->sb_offset[1] = cpu_to_le64(backup);
|
l->sb_offset[1] = cpu_to_le64(backup);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bch2_pick_bucket_size(struct format_opts opts, struct dev_opts *dev)
|
void bch2_pick_bucket_size(struct bch_opts opts, struct dev_opts *dev)
|
||||||
{
|
{
|
||||||
if (!dev->sb_offset) {
|
if (!dev->sb_offset) {
|
||||||
dev->sb_offset = BCH_SB_SECTOR;
|
dev->sb_offset = BCH_SB_SECTOR;
|
||||||
@ -90,7 +91,9 @@ void bch2_pick_bucket_size(struct format_opts opts, struct dev_opts *dev)
|
|||||||
dev->bucket_size = opts.block_size;
|
dev->bucket_size = opts.block_size;
|
||||||
|
|
||||||
/* Bucket size must be >= btree node size: */
|
/* Bucket size must be >= btree node size: */
|
||||||
dev->bucket_size = max(dev->bucket_size, opts.btree_node_size);
|
if (opt_defined(opts, btree_node_size))
|
||||||
|
dev->bucket_size = max_t(unsigned, dev->bucket_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, 256U);
|
dev->bucket_size = max(dev->bucket_size, 256U);
|
||||||
@ -115,7 +118,8 @@ void bch2_pick_bucket_size(struct format_opts opts, struct dev_opts *dev)
|
|||||||
if (dev->bucket_size < opts.block_size)
|
if (dev->bucket_size < opts.block_size)
|
||||||
die("Bucket size cannot be smaller than block size");
|
die("Bucket size cannot be smaller than block size");
|
||||||
|
|
||||||
if (dev->bucket_size < opts.btree_node_size)
|
if (opt_defined(opts, btree_node_size) &&
|
||||||
|
dev->bucket_size < opts.btree_node_size)
|
||||||
die("Bucket size cannot be smaller than btree node size");
|
die("Bucket size cannot be smaller than btree node size");
|
||||||
|
|
||||||
if (dev->nbuckets < BCH_MIN_NR_NBUCKETS)
|
if (dev->nbuckets < BCH_MIN_NR_NBUCKETS)
|
||||||
@ -146,37 +150,48 @@ static unsigned parse_target(struct bch_sb_handle *sb,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct bch_sb *bch2_format(struct format_opts opts,
|
struct bch_sb *bch2_format(struct bch_opt_strs fs_opt_strs,
|
||||||
struct dev_opts *devs, size_t nr_devs)
|
struct bch_opts fs_opts,
|
||||||
|
struct format_opts opts,
|
||||||
|
struct dev_opts *devs,
|
||||||
|
size_t nr_devs)
|
||||||
{
|
{
|
||||||
struct bch_sb_handle sb = { NULL };
|
struct bch_sb_handle sb = { NULL };
|
||||||
struct dev_opts *i;
|
struct dev_opts *i;
|
||||||
struct bch_sb_field_members *mi;
|
struct bch_sb_field_members *mi;
|
||||||
|
unsigned max_dev_block_size = 0;
|
||||||
|
unsigned opt_id;
|
||||||
|
|
||||||
|
for (i = devs; i < devs + nr_devs; i++)
|
||||||
|
max_dev_block_size = max(max_dev_block_size,
|
||||||
|
get_blocksize(i->path, i->fd));
|
||||||
|
|
||||||
/* calculate block size: */
|
/* calculate block size: */
|
||||||
if (!opts.block_size)
|
if (!opt_defined(fs_opts, block_size)) {
|
||||||
for (i = devs; i < devs + nr_devs; i++)
|
opt_set(fs_opts, block_size, max_dev_block_size);
|
||||||
opts.block_size = max(opts.block_size,
|
} else if (fs_opts.block_size < max_dev_block_size)
|
||||||
get_blocksize(i->path, i->fd));
|
die("blocksize too small: %u, must be greater than device blocksize %u",
|
||||||
|
fs_opts.block_size, max_dev_block_size);
|
||||||
|
|
||||||
/* 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(opts, i);
|
bch2_pick_bucket_size(fs_opts, i);
|
||||||
|
|
||||||
/* calculate btree node size: */
|
/* calculate btree node size: */
|
||||||
if (!opts.btree_node_size) {
|
if (!opt_defined(fs_opts, btree_node_size)) {
|
||||||
/* 256k default btree node size */
|
/* 256k default btree node size */
|
||||||
opts.btree_node_size = 512;
|
opt_set(fs_opts, btree_node_size, 512);
|
||||||
|
|
||||||
for (i = devs; i < devs + nr_devs; i++)
|
for (i = devs; i < devs + nr_devs; i++)
|
||||||
opts.btree_node_size =
|
fs_opts.btree_node_size =
|
||||||
min(opts.btree_node_size, i->bucket_size);
|
min_t(unsigned, fs_opts.btree_node_size,
|
||||||
|
i->bucket_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_power_of_2(opts.block_size))
|
if (!is_power_of_2(fs_opts.block_size))
|
||||||
die("block size must be power of 2");
|
die("block size must be power of 2");
|
||||||
|
|
||||||
if (!is_power_of_2(opts.btree_node_size))
|
if (!is_power_of_2(fs_opts.btree_node_size))
|
||||||
die("btree node size must be power of 2");
|
die("btree node size must be power of 2");
|
||||||
|
|
||||||
if (uuid_is_null(opts.uuid.b))
|
if (uuid_is_null(opts.uuid.b))
|
||||||
@ -188,7 +203,7 @@ struct bch_sb *bch2_format(struct format_opts opts,
|
|||||||
sb.sb->version = le16_to_cpu(bcachefs_metadata_version_current);
|
sb.sb->version = le16_to_cpu(bcachefs_metadata_version_current);
|
||||||
sb.sb->version_min = le16_to_cpu(bcachefs_metadata_version_current);
|
sb.sb->version_min = le16_to_cpu(bcachefs_metadata_version_current);
|
||||||
sb.sb->magic = BCACHE_MAGIC;
|
sb.sb->magic = BCACHE_MAGIC;
|
||||||
sb.sb->block_size = cpu_to_le16(opts.block_size);
|
sb.sb->block_size = cpu_to_le16(fs_opts.block_size);
|
||||||
sb.sb->user_uuid = opts.uuid;
|
sb.sb->user_uuid = opts.uuid;
|
||||||
sb.sb->nr_devices = nr_devs;
|
sb.sb->nr_devices = nr_devs;
|
||||||
|
|
||||||
@ -199,24 +214,24 @@ struct bch_sb *bch2_format(struct format_opts opts,
|
|||||||
opts.label,
|
opts.label,
|
||||||
min(strlen(opts.label), sizeof(sb.sb->label)));
|
min(strlen(opts.label), sizeof(sb.sb->label)));
|
||||||
|
|
||||||
SET_BCH_SB_CSUM_TYPE(sb.sb, opts.meta_csum_type);
|
for (opt_id = 0;
|
||||||
SET_BCH_SB_META_CSUM_TYPE(sb.sb, opts.meta_csum_type);
|
opt_id < bch2_opts_nr;
|
||||||
SET_BCH_SB_DATA_CSUM_TYPE(sb.sb, opts.data_csum_type);
|
opt_id++) {
|
||||||
SET_BCH_SB_COMPRESSION_TYPE(sb.sb, opts.compression_type);
|
const struct bch_option *opt = &bch2_opt_table[opt_id];
|
||||||
SET_BCH_SB_BACKGROUND_COMPRESSION_TYPE(sb.sb,
|
u64 v;
|
||||||
opts.background_compression_type);
|
|
||||||
|
|
||||||
SET_BCH_SB_BTREE_NODE_SIZE(sb.sb, opts.btree_node_size);
|
if (opt->set_sb == SET_NO_SB_OPT)
|
||||||
SET_BCH_SB_GC_RESERVE(sb.sb, 8);
|
continue;
|
||||||
SET_BCH_SB_META_REPLICAS_WANT(sb.sb, opts.meta_replicas);
|
|
||||||
SET_BCH_SB_META_REPLICAS_REQ(sb.sb, opts.meta_replicas_required);
|
|
||||||
SET_BCH_SB_DATA_REPLICAS_WANT(sb.sb, opts.data_replicas);
|
|
||||||
SET_BCH_SB_DATA_REPLICAS_REQ(sb.sb, opts.data_replicas_required);
|
|
||||||
SET_BCH_SB_ERROR_ACTION(sb.sb, opts.on_error_action);
|
|
||||||
SET_BCH_SB_STR_HASH_TYPE(sb.sb, BCH_STR_HASH_SIPHASH);
|
|
||||||
SET_BCH_SB_ENCODED_EXTENT_MAX_BITS(sb.sb,ilog2(opts.encoded_extent_max));
|
|
||||||
|
|
||||||
SET_BCH_SB_POSIX_ACL(sb.sb, 1);
|
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);
|
||||||
|
|
||||||
|
opt->set_sb(sb.sb, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
SET_BCH_SB_ENCODED_EXTENT_MAX_BITS(sb.sb,
|
||||||
|
ilog2(opts.encoded_extent_max));
|
||||||
|
|
||||||
struct timespec now;
|
struct timespec now;
|
||||||
if (clock_gettime(CLOCK_REALTIME, &now))
|
if (clock_gettime(CLOCK_REALTIME, &now))
|
||||||
@ -260,11 +275,11 @@ struct bch_sb *bch2_format(struct format_opts opts,
|
|||||||
}
|
}
|
||||||
|
|
||||||
SET_BCH_SB_FOREGROUND_TARGET(sb.sb,
|
SET_BCH_SB_FOREGROUND_TARGET(sb.sb,
|
||||||
parse_target(&sb, devs, nr_devs, opts.foreground_target));
|
parse_target(&sb, devs, nr_devs, fs_opt_strs.foreground_target));
|
||||||
SET_BCH_SB_BACKGROUND_TARGET(sb.sb,
|
SET_BCH_SB_BACKGROUND_TARGET(sb.sb,
|
||||||
parse_target(&sb, devs, nr_devs, opts.background_target));
|
parse_target(&sb, devs, nr_devs, fs_opt_strs.background_target));
|
||||||
SET_BCH_SB_PROMOTE_TARGET(sb.sb,
|
SET_BCH_SB_PROMOTE_TARGET(sb.sb,
|
||||||
parse_target(&sb, devs, nr_devs, opts.promote_target));
|
parse_target(&sb, devs, nr_devs, fs_opt_strs.promote_target));
|
||||||
|
|
||||||
/* Crypt: */
|
/* Crypt: */
|
||||||
if (opts.encrypted) {
|
if (opts.encrypted) {
|
||||||
@ -278,7 +293,7 @@ struct bch_sb *bch2_format(struct format_opts opts,
|
|||||||
for (i = devs; i < devs + nr_devs; i++) {
|
for (i = devs; i < devs + nr_devs; i++) {
|
||||||
sb.sb->dev_idx = i - devs;
|
sb.sb->dev_idx = i - devs;
|
||||||
|
|
||||||
init_layout(&sb.sb->layout, opts.block_size,
|
init_layout(&sb.sb->layout, fs_opts.block_size,
|
||||||
i->sb_offset, i->sb_end);
|
i->sb_offset, i->sb_end);
|
||||||
|
|
||||||
if (i->sb_offset == BCH_SB_SECTOR) {
|
if (i->sb_offset == BCH_SB_SECTOR) {
|
||||||
@ -931,3 +946,151 @@ int bchu_data(struct bchfs_handle fs, struct bch_ioctl_data cmd)
|
|||||||
close(progress_fd);
|
close(progress_fd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* option parsing */
|
||||||
|
|
||||||
|
struct bch_opt_strs bch2_cmdline_opts_get(int *argc, char *argv[],
|
||||||
|
unsigned opt_types)
|
||||||
|
{
|
||||||
|
struct bch_opt_strs opts;
|
||||||
|
unsigned i = 1;
|
||||||
|
|
||||||
|
memset(&opts, 0, sizeof(opts));
|
||||||
|
|
||||||
|
while (i < *argc) {
|
||||||
|
char *optstr = strcmp_prefix(argv[i], "--");
|
||||||
|
char *valstr = NULL, *p;
|
||||||
|
int optid, nr_args = 1;
|
||||||
|
|
||||||
|
if (!optstr) {
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
optstr = strdup(optstr);
|
||||||
|
|
||||||
|
p = optstr;
|
||||||
|
while (isalpha(*p) || *p == '_')
|
||||||
|
p++;
|
||||||
|
|
||||||
|
if (*p == '=') {
|
||||||
|
*p = '\0';
|
||||||
|
valstr = p + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
optid = bch2_opt_lookup(optstr);
|
||||||
|
if (optid < 0 ||
|
||||||
|
!(bch2_opt_table[optid].mode & opt_types)) {
|
||||||
|
free(optstr);
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!valstr &&
|
||||||
|
bch2_opt_table[optid].type != BCH_OPT_BOOL) {
|
||||||
|
nr_args = 2;
|
||||||
|
valstr = argv[i + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!valstr)
|
||||||
|
valstr = "1";
|
||||||
|
|
||||||
|
opts.by_id[optid] = valstr;
|
||||||
|
|
||||||
|
*argc -= nr_args;
|
||||||
|
memmove(&argv[i],
|
||||||
|
&argv[i + nr_args],
|
||||||
|
sizeof(char *) * (*argc - i));
|
||||||
|
argv[*argc] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return opts;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct bch_opts bch2_parse_opts(struct bch_opt_strs strs)
|
||||||
|
{
|
||||||
|
struct bch_opts opts = bch2_opts_empty();
|
||||||
|
unsigned i;
|
||||||
|
int ret;
|
||||||
|
u64 v;
|
||||||
|
|
||||||
|
for (i = 0; i < bch2_opts_nr; i++) {
|
||||||
|
if (!strs.by_id[i] ||
|
||||||
|
bch2_opt_table[i].type == BCH_OPT_FN)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ret = bch2_opt_parse(NULL, &bch2_opt_table[i],
|
||||||
|
strs.by_id[i], &v);
|
||||||
|
if (ret < 0)
|
||||||
|
die("Invalid %s: %s", strs.by_id[i], strerror(-ret));
|
||||||
|
|
||||||
|
bch2_opt_set_by_id(&opts, i, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
return opts;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bch2_opts_usage(unsigned opt_types)
|
||||||
|
{
|
||||||
|
const struct bch_option *opt;
|
||||||
|
unsigned i, c = 0, helpcol = 30;
|
||||||
|
|
||||||
|
void tabalign() {
|
||||||
|
while (c < helpcol) {
|
||||||
|
putchar(' ');
|
||||||
|
c++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void newline() {
|
||||||
|
printf("\n");
|
||||||
|
c = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (opt = bch2_opt_table;
|
||||||
|
opt < bch2_opt_table + bch2_opts_nr;
|
||||||
|
opt++) {
|
||||||
|
if (!(opt->mode & opt_types))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
c += printf(" --%s", opt->attr.name);
|
||||||
|
|
||||||
|
switch (opt->type) {
|
||||||
|
case BCH_OPT_BOOL:
|
||||||
|
break;
|
||||||
|
case BCH_OPT_STR:
|
||||||
|
c += printf("=(");
|
||||||
|
for (i = 0; opt->choices[i]; i++) {
|
||||||
|
if (i)
|
||||||
|
c += printf("|");
|
||||||
|
c += printf("%s", opt->choices[i]);
|
||||||
|
}
|
||||||
|
c += printf(")");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
c += printf("=%s", opt->hint);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opt->help) {
|
||||||
|
const char *l = opt->help;
|
||||||
|
|
||||||
|
if (c >= helpcol)
|
||||||
|
newline();
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
const char *n = strchrnul(l, '\n');
|
||||||
|
|
||||||
|
tabalign();
|
||||||
|
printf("%.*s", (int) (n - l), l);
|
||||||
|
newline();
|
||||||
|
|
||||||
|
if (!*n)
|
||||||
|
break;
|
||||||
|
l = n + 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
newline();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -6,34 +6,33 @@
|
|||||||
|
|
||||||
#include "libbcachefs/bcachefs_format.h"
|
#include "libbcachefs/bcachefs_format.h"
|
||||||
#include "libbcachefs/bcachefs_ioctl.h"
|
#include "libbcachefs/bcachefs_ioctl.h"
|
||||||
#include "tools-util.h"
|
#include "libbcachefs/opts.h"
|
||||||
#include "libbcachefs/vstructs.h"
|
#include "libbcachefs/vstructs.h"
|
||||||
|
#include "tools-util.h"
|
||||||
|
|
||||||
|
/* option parsing */
|
||||||
|
|
||||||
|
struct bch_opt_strs {
|
||||||
|
union {
|
||||||
|
char *by_id[bch2_opts_nr];
|
||||||
|
};
|
||||||
|
struct {
|
||||||
|
#define x(_name, ...) char *_name;
|
||||||
|
BCH_OPTS()
|
||||||
|
#undef x
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
struct format_opts {
|
struct format_opts {
|
||||||
char *label;
|
char *label;
|
||||||
uuid_le uuid;
|
uuid_le uuid;
|
||||||
|
|
||||||
unsigned on_error_action;
|
|
||||||
|
|
||||||
unsigned block_size;
|
|
||||||
unsigned btree_node_size;
|
|
||||||
unsigned encoded_extent_max;
|
unsigned encoded_extent_max;
|
||||||
|
|
||||||
unsigned meta_replicas;
|
|
||||||
unsigned data_replicas;
|
|
||||||
|
|
||||||
unsigned meta_replicas_required;
|
|
||||||
unsigned data_replicas_required;
|
|
||||||
|
|
||||||
const char *foreground_target;
|
|
||||||
const char *background_target;
|
|
||||||
const char *promote_target;
|
|
||||||
|
|
||||||
unsigned meta_csum_type;
|
|
||||||
unsigned data_csum_type;
|
|
||||||
unsigned compression_type;
|
|
||||||
unsigned background_compression_type;
|
|
||||||
|
|
||||||
bool encrypted;
|
bool encrypted;
|
||||||
char *passphrase;
|
char *passphrase;
|
||||||
};
|
};
|
||||||
@ -41,14 +40,7 @@ struct format_opts {
|
|||||||
static inline struct format_opts format_opts_default()
|
static inline struct format_opts format_opts_default()
|
||||||
{
|
{
|
||||||
return (struct format_opts) {
|
return (struct format_opts) {
|
||||||
.on_error_action = BCH_ON_ERROR_RO,
|
|
||||||
.encoded_extent_max = 128,
|
.encoded_extent_max = 128,
|
||||||
.meta_csum_type = BCH_CSUM_OPT_CRC32C,
|
|
||||||
.data_csum_type = BCH_CSUM_OPT_CRC32C,
|
|
||||||
.meta_replicas = 1,
|
|
||||||
.data_replicas = 1,
|
|
||||||
.meta_replicas_required = 1,
|
|
||||||
.data_replicas_required = 1,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,8 +68,10 @@ static inline struct dev_opts dev_opts_default()
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void bch2_pick_bucket_size(struct format_opts, struct dev_opts *);
|
void bch2_pick_bucket_size(struct bch_opts, struct dev_opts *);
|
||||||
struct bch_sb *bch2_format(struct format_opts, struct dev_opts *, size_t);
|
struct bch_sb *bch2_format(struct bch_opt_strs,
|
||||||
|
struct bch_opts,
|
||||||
|
struct format_opts, struct dev_opts *, size_t);
|
||||||
|
|
||||||
void bch2_super_write(int, struct bch_sb *);
|
void bch2_super_write(int, struct bch_sb *);
|
||||||
struct bch_sb *__bch2_super_read(int, u64);
|
struct bch_sb *__bch2_super_read(int, u64);
|
||||||
|
@ -386,7 +386,7 @@ struct fiemap_extent fiemap_iter_next(struct fiemap_iter *iter)
|
|||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *strcmp_prefix(const char *a, const char *a_prefix)
|
char *strcmp_prefix(char *a, const char *a_prefix)
|
||||||
{
|
{
|
||||||
while (*a_prefix && *a == *a_prefix) {
|
while (*a_prefix && *a == *a_prefix) {
|
||||||
a++;
|
a++;
|
||||||
|
@ -145,7 +145,7 @@ struct fiemap_extent fiemap_iter_next(struct fiemap_iter *);
|
|||||||
for (fiemap_iter_init(&iter, fd); \
|
for (fiemap_iter_init(&iter, fd); \
|
||||||
(extent = fiemap_iter_next(&iter)).fe_length;)
|
(extent = fiemap_iter_next(&iter)).fe_length;)
|
||||||
|
|
||||||
const char *strcmp_prefix(const char *, const char *);
|
char *strcmp_prefix(char *, const char *);
|
||||||
|
|
||||||
unsigned hatoi_validate(const char *, const char *);
|
unsigned hatoi_validate(const char *, const char *);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user