X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=bcache-format.c;h=a7aabc3b1dccd238c68ed850df78c06d7ebc010d;hb=379520ee87b92c51f1db1e5c19379d738a7c207a;hp=e80ebed639ad4078f7a80a478ff2f03e7a21166a;hpb=b0f08fc1e30daafb274181234dae3408fb2eb69b;p=bcachefs-tools-debian diff --git a/bcache-format.c b/bcache-format.c index e80ebed..a7aabc3 100644 --- a/bcache-format.c +++ b/bcache-format.c @@ -5,227 +5,254 @@ * * GPLv2 */ - #include +#include +#include #include #include #include #include #include +#include #include #include +#include #include -#include -#include - #include "ccan/darray/darray.h" -#include "bcache.h" +#include "bcache-cmds.h" #include "libbcache.h" -#include "bcache-format.h" -#include "crypto.h" - -/* All in units of 512 byte sectors */ - -static darray(struct dev_opts) cache_devices; - -static unsigned block_size, btree_node_size; -static unsigned meta_csum_type = BCH_CSUM_CRC32C; -static unsigned data_csum_type = BCH_CSUM_CRC32C; -static unsigned compression_type = BCH_COMPRESSION_NONE; -static int encrypted; -static unsigned meta_replicas = 1, data_replicas = 1; -static unsigned on_error_action; -static char *label = NULL; -static uuid_le uuid; - -/* Device specific options: */ -static u64 filesystem_size; -static unsigned bucket_size; -static unsigned tier; -static unsigned replacement_policy; -static int discard; - -static int set_cache(NihOption *option, const char *arg) -{ - darray_append(cache_devices, (struct dev_opts) { - .fd = dev_open(arg), - .dev = strdup(arg), - .size = filesystem_size, - .bucket_size = bucket_size, - .tier = tier, - .replacement_policy = replacement_policy, - .discard = discard, - }); - return 0; -} - -static int set_uuid(NihOption *option, const char *arg) -{ - if (uuid_parse(arg, uuid.b)) - die("Bad uuid"); - return 0; -} - -static int set_block_size(NihOption *option, const char *arg) -{ - block_size = hatoi_validate(arg, "block size"); - return 0; -} -static int set_bucket_sizes(NihOption *option, const char *arg) +/* Open a block device, do magic blkid stuff: */ +static int open_for_format(const char *dev, bool force) { - bucket_size = hatoi_validate(arg, "bucket size"); - return 0; -} - -static int set_btree_node_size(NihOption *option, const char *arg) -{ - btree_node_size = hatoi_validate(arg, "btree node size"); - return 0; -} - -static int set_filesystem_size(NihOption *option, const char *arg) -{ - filesystem_size = hatoi(arg) >> 9; - return 0; -} - -static int set_replacement_policy(NihOption *option, const char *arg) -{ - replacement_policy = read_string_list_or_die(arg, replacement_policies, - "replacement policy"); - return 0; -} - -static int set_csum_type(NihOption *option, const char *arg) -{ - unsigned *csum_type = option->value; - - *csum_type = read_string_list_or_die(arg, csum_types, "checksum type"); - return 0; -} + blkid_probe pr; + const char *fs_type = NULL, *fs_label = NULL; + size_t fs_type_len, fs_label_len; + int fd; + + if ((fd = open(dev, O_RDWR|O_EXCL)) == -1) + die("Can't open dev %s: %s\n", dev, strerror(errno)); + + if (force) + return fd; + + if (!(pr = blkid_new_probe())) + die("blkid error 1"); + if (blkid_probe_set_device(pr, fd, 0, 0)) + die("blkid error 2"); + if (blkid_probe_enable_partitions(pr, true)) + die("blkid error 3"); + if (blkid_do_fullprobe(pr) < 0) + die("blkid error 4"); + + blkid_probe_lookup_value(pr, "TYPE", &fs_type, &fs_type_len); + blkid_probe_lookup_value(pr, "LABEL", &fs_label, &fs_label_len); + + if (fs_type) { + if (fs_label) + printf("%s contains a %s filesystem labelled '%s'\n", + dev, fs_type, fs_label); + else + printf("%s contains a %s filesystem\n", + dev, fs_type); + if (!ask_proceed()) + exit(EXIT_FAILURE); + } -static int set_compression_type(NihOption *option, const char *arg) -{ - compression_type = read_string_list_or_die(arg, compression_types, - "compression type"); - return 0; + blkid_free_probe(pr); + return fd; } -static int set_on_error_action(NihOption *option, const char *arg) +static void usage(void) { - on_error_action = read_string_list_or_die(arg, error_actions, - "error action"); - return 0; + puts("bcache format - create a new bcache filesystem on one or more devices\n" + "Usage: bcache format [OPTION]... \n" + "\n" + "Options:\n" + " -b, --block=size\n" + " --btree_node=size Btree node size, default 256k\n" + " --metadata_checksum_type=(none|crc32c|crc64)\n" + " --data_checksum_type=(none|crc32c|crc64)\n" + " --compression_type=(none|lz4|gzip)\n" + " --error_action=(continue|readonly|panic)\n" + " Action to take on filesystem error\n" + " --max_journal_entry_size=size\n" + " -l, --label=label\n" + " --uuid=uuid\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" + " -t, --tier=# tier of subsequent devices\n" + "\n" + " -h, --help display this help and exit\n" + "\n" + "Device specific options must come before corresponding devices, e.g.\n" + " bcache format --tier 0 /dev/sdb --tier 1 /dev/sdc\n" + "\n" + "Report bugs to "); + exit(EXIT_SUCCESS); } -static int set_tier(NihOption *option, const char *arg) -{ - tier = strtoul_or_die(arg, CACHE_TIERS, "tier"); - return 0; -} +#define OPTS \ + OPT('b', block_size, required_argument) \ + OPT(0, btree_node_size, required_argument) \ + OPT(0, metadata_checksum_type, required_argument) \ + OPT(0, data_checksum_type, required_argument) \ + OPT(0, compression_type, required_argument) \ + OPT('e', error_action, required_argument) \ + OPT(0, max_journal_entry_size, required_argument) \ + OPT('L', label, required_argument) \ + OPT('U', uuid, required_argument) \ + OPT('f', force, no_argument) \ + OPT(0, fs_size, required_argument) \ + OPT(0, bucket_size, required_argument) \ + OPT('t', tier, required_argument) \ + OPT(0, discard, no_argument) \ + OPT('h', help, no_argument) + +enum { + Opt_no_opt = 1, +#define OPT(shortopt, longopt, has_arg) Opt_##longopt, + OPTS +#undef OPT +}; -static int set_meta_replicas(NihOption *option, const char *arg) -{ - meta_replicas = strtoul_or_die(arg, CACHE_SET_META_REPLICAS_WANT_MAX, - "meta_replicas"); - return 0; -} +static const struct option format_opts[] = { +#define OPT(shortopt, longopt, has_arg) { \ + #longopt, has_arg, NULL, Opt_##longopt \ + }, + OPTS +#undef OPT + { NULL } +}; -static int set_data_replicas(NihOption *option, const char *arg) +int cmd_format(int argc, char *argv[]) { - data_replicas = strtoul_or_die(arg, CACHE_SET_DATA_REPLICAS_WANT_MAX, - "data_replicas"); - return 0; -} - -NihOption opts_format[] = { -// { int shortoption, char *longoption, char *help, NihOptionGroup, char *argname, void *value, NihOptionSetter} - - { 'C', "cache", N_("Format a cache device"), - NULL, "dev", NULL, set_cache }, - - { 'w', "block", N_("block size"), - NULL, "size", NULL, set_block_size }, - { 'n', "btree_node", N_("Btree node size, default 256k"), - NULL, "size", NULL, set_btree_node_size }, - - { 0, "metadata_csum_type", N_("Checksum type"), - NULL, "(none|crc32c|crc64)", &meta_csum_type, set_csum_type }, - { 0, "data_csum_type", N_("Checksum type"), - NULL, "(none|crc32c|crc64)", &data_csum_type, set_csum_type }, - { 0, "compression_type", N_("Compression type"), - NULL, "(none|gzip)", NULL, set_compression_type }, - { 0, "encrypted", N_("enable encryption"), - NULL, NULL, &encrypted, NULL }, - - { 0, "meta_replicas", N_("number of metadata replicas"), - NULL, "#", NULL, set_meta_replicas }, - { 0, "data_replicas", N_("number of data replicas"), - NULL, "#", NULL, set_data_replicas }, - - { 0, "error_action", N_("Action to take on filesystem error"), - NULL, "(continue|readonly|panic)", NULL, set_on_error_action }, - - { 'l', "label", N_("label"), - NULL, "label", &label, NULL}, - { 0, "uuid", N_("filesystem UUID"), - NULL, "uuid", NULL, set_uuid }, + darray(struct dev_opts) devices; + struct dev_opts *dev; + unsigned block_size = 0; + unsigned btree_node_size = 0; + unsigned meta_csum_type = BCH_CSUM_CRC32C; + unsigned data_csum_type = BCH_CSUM_CRC32C; + unsigned compression_type = BCH_COMPRESSION_NONE; + unsigned on_error_action = BCH_ON_ERROR_RO; + char *label = NULL; + uuid_le uuid; + bool force = false; /* Device specific options: */ - { 0, "fs_size", N_("Size of filesystem on device" ), - NULL, "size", NULL, set_filesystem_size }, - { 'b', "bucket", N_("bucket size"), - NULL, "size", NULL, set_bucket_sizes }, - { 't', "tier", N_("tier of subsequent devices"), - NULL, "#", NULL, set_tier }, - { 'p', "cache_replacement_policy", NULL, - NULL, "(lru|fifo|random)", NULL, set_replacement_policy }, - { 0, "discard", N_("Enable discards"), - NULL, NULL, &discard, NULL }, - - NIH_OPTION_LAST -}; - -int cmd_format(NihCommand *command, char * const *args) -{ + u64 filesystem_size = 0; + unsigned bucket_size = 0; + unsigned tier = 0; + bool discard = false; + unsigned max_journal_entry_size = 0; char *passphrase = NULL; + int opt; + + darray_init(devices); + uuid_clear(uuid.b); + + while ((opt = getopt_long(argc, argv, + "-b:e:L:U:ft:h", + format_opts, + NULL)) != -1) + switch (opt) { + case Opt_block_size: + case 'b': + block_size = hatoi_validate(optarg, + "block size"); + break; + case Opt_btree_node_size: + btree_node_size = hatoi_validate(optarg, + "btree node size"); + break; + case Opt_metadata_checksum_type: + meta_csum_type = read_string_list_or_die(optarg, + csum_types, "checksum type"); + break; + case Opt_data_checksum_type: + data_csum_type = read_string_list_or_die(optarg, + csum_types, "checksum type"); + break; + case Opt_compression_type: + compression_type = read_string_list_or_die(optarg, + compression_types, "compression type"); + break; + case Opt_error_action: + case 'e': + on_error_action = read_string_list_or_die(optarg, + error_actions, "error action"); + break; + case Opt_max_journal_entry_size: + max_journal_entry_size = hatoi_validate(optarg, + "journal entry size"); + break; + case Opt_label: + case 'L': + label = strdup(optarg); + break; + case Opt_uuid: + case 'U': + if (uuid_parse(optarg, uuid.b)) + die("Bad uuid"); + break; + case Opt_force: + case 'f': + force = true; + break; + case Opt_fs_size: + filesystem_size = hatoi(optarg) >> 9; + break; + case Opt_bucket_size: + bucket_size = hatoi_validate(optarg, "bucket size"); + break; + case Opt_tier: + case 't': + tier = strtoul_or_die(optarg, CACHE_TIERS, "tier"); + break; + case Opt_discard: + discard = true; + break; + case Opt_no_opt: + darray_append(devices, (struct dev_opts) { + .path = strdup(optarg), + .size = filesystem_size, + .bucket_size = bucket_size, + .tier = tier, + .discard = discard, + }); + break; + case Opt_help: + case 'h': + usage(); + break; + } - if (!darray_size(cache_devices)) + if (!darray_size(devices)) die("Please supply a device"); if (uuid_is_null(uuid.b)) uuid_generate(uuid.b); - if (encrypted) { - char *pass2; - - passphrase = read_passphrase("Enter passphrase: "); - pass2 = read_passphrase("Enter same passphrase again: "); - - if (strcmp(passphrase, pass2)) { - memzero_explicit(passphrase, strlen(passphrase)); - memzero_explicit(pass2, strlen(pass2)); - die("Passphrases do not match"); - } - - memzero_explicit(pass2, strlen(pass2)); - free(pass2); - } + darray_foreach(dev, devices) + dev->fd = open_for_format(dev->path, force); - bcache_format(cache_devices.item, darray_size(cache_devices), + bcache_format(devices.item, darray_size(devices), block_size, btree_node_size, meta_csum_type, data_csum_type, compression_type, - passphrase, - meta_replicas, - data_replicas, + 1, + 1, on_error_action, + max_journal_entry_size, label, uuid);