2 * Authors: Kent Overstreet <kent.overstreet@gmail.com>
3 * Gabriel de Perthuis <g2p.code@gmail.com>
4 * Jacob Malevich <jam@datera.io>
17 #include <sys/types.h>
21 #include <uuid/uuid.h>
23 #include "ccan/darray/darray.h"
26 #include "libbcache.h"
31 /* Open a block device, do magic blkid stuff: */
32 static int open_for_format(const char *dev, bool force)
35 const char *fs_type = NULL, *fs_label = NULL;
36 size_t fs_type_len, fs_label_len;
38 int fd = xopen(dev, O_RDWR|O_EXCL);
43 if (!(pr = blkid_new_probe()))
45 if (blkid_probe_set_device(pr, fd, 0, 0))
47 if (blkid_probe_enable_partitions(pr, true))
49 if (blkid_do_fullprobe(pr) < 0)
52 blkid_probe_lookup_value(pr, "TYPE", &fs_type, &fs_type_len);
53 blkid_probe_lookup_value(pr, "LABEL", &fs_label, &fs_label_len);
57 printf("%s contains a %s filesystem labelled '%s'\n",
58 dev, fs_type, fs_label);
60 printf("%s contains a %s filesystem\n",
62 fputs("Proceed anyway?", stdout);
72 t("bcache format - create a new bcache filesystem on one or more devices") \
73 t("Usage: bcache format [OPTION]... <devices>") \
75 x('b', block_size, "size", NULL) \
76 x(0, btree_node_size, "size", "Default 256k") \
77 x(0, metadata_checksum_type, "(none|crc32c|crc64)", NULL) \
78 x(0, data_checksum_type, "(none|crc32c|crc64)", NULL) \
79 x(0, compression_type, "(none|lz4|gzip)", NULL) \
80 x(0, encrypted, NULL, "Enable whole filesystem encryption (chacha20/poly1305)")\
81 x(0, no_passphrase, NULL, "Don't encrypt master encryption key")\
82 x('e', error_action, "(continue|readonly|panic)", NULL) \
83 x(0, max_journal_entry_size, "size", NULL) \
84 x('L', label, "label", NULL) \
85 x('U', uuid, "uuid", NULL) \
86 x('f', force, NULL, NULL) \
88 t("Device specific options:") \
89 x(0, fs_size, "size", "Size of filesystem on device")\
90 x(0, bucket_size, "size", "Bucket size") \
91 x('t', tier, "#", "Higher tier indicates slower devices")\
92 x(0, discard, NULL, NULL) \
93 t("Device specific options must come before corresponding devices, e.g.") \
94 t(" bcache format --tier 0 /dev/sdb --tier 1 /dev/sdc") \
96 x('h', help, NULL, "display this help and exit")
98 static void usage(void)
100 #define t(text) puts(text "\n")
101 #define x(shortopt, longopt, arg, help) do { \
106 puts("bcache format - create a new bcache filesystem on one or more devices\n"
107 "Usage: bcache format [OPTION]... <devices>\n"
110 " -b, --block=size\n"
111 " --btree_node=size Btree node size, default 256k\n"
112 " --metadata_checksum_type=(none|crc32c|crc64)\n"
113 " --data_checksum_type=(none|crc32c|crc64)\n"
114 " --compression_type=(none|lz4|gzip)\n"
115 " --encrypted Enable whole filesystem encryption (chacha20/poly1305)\n"
116 " --no_passphrase Don't encrypt master encryption key\n"
117 " --error_action=(continue|readonly|panic)\n"
118 " Action to take on filesystem error\n"
119 " --max_journal_entry_size=size\n"
120 " -l, --label=label\n"
124 "Device specific options:\n"
125 " --fs_size=size Size of filesystem on device\n"
126 " --bucket=size bucket size\n"
127 " --discard Enable discards\n"
128 " -t, --tier=# tier of subsequent devices\n"
130 " -h, --help display this help and exit\n"
132 "Device specific options must come before corresponding devices, e.g.\n"
133 " bcache format --tier 0 /dev/sdb --tier 1 /dev/sdc\n"
135 "Report bugs to <linux-bcache@vger.kernel.org>");
141 #define x(shortopt, longopt, arg, help) Opt_##longopt,
147 static const struct option format_opts[] = {
149 #define x(shortopt, longopt, arg, help) { \
151 .has_arg = arg ? required_argument : no_argument, \
153 .val = Opt_##longopt, \
161 static unsigned hatoi_validate(const char *s, const char *msg)
165 if (bch_strtoull_h(s, &v))
166 die("bad %s %s", msg, s);
169 die("%s must be a power of two", msg);
174 die("%s too large\n", msg);
177 die("%s too small\n", msg);
182 int cmd_format(int argc, char *argv[])
184 darray(struct dev_opts) devices;
185 struct format_opts opts = format_opts_default();
186 struct dev_opts dev_opts = { 0 }, *dev;
187 bool force = false, no_passphrase = false;
190 darray_init(devices);
192 while ((opt = getopt_long(argc, argv,
200 hatoi_validate(optarg, "block size");
202 case Opt_btree_node_size:
203 opts.btree_node_size =
204 hatoi_validate(optarg, "btree node size");
206 case Opt_metadata_checksum_type:
207 opts.meta_csum_type =
208 read_string_list_or_die(optarg,
209 bch_csum_types, "checksum type");
211 case Opt_data_checksum_type:
212 opts.data_csum_type =
213 read_string_list_or_die(optarg,
214 bch_csum_types, "checksum type");
216 case Opt_compression_type:
217 opts.compression_type =
218 read_string_list_or_die(optarg,
219 bch_compression_types,
223 opts.encrypted = true;
225 case Opt_no_passphrase:
226 no_passphrase = true;
228 case Opt_error_action:
230 opts.on_error_action =
231 read_string_list_or_die(optarg,
232 bch_error_actions, "error action");
234 case Opt_max_journal_entry_size:
235 opts.max_journal_entry_size =
236 hatoi_validate(optarg, "journal entry size");
240 opts.label = strdup(optarg);
244 if (uuid_parse(optarg, opts.uuid.b))
252 if (bch_strtoull_h(optarg, &dev_opts.size))
253 die("invalid filesystem size");
257 case Opt_bucket_size:
258 dev_opts.bucket_size =
259 hatoi_validate(optarg, "bucket size");
263 if (kstrtouint(optarg, 10, &dev_opts.tier) ||
264 dev_opts.tier >= BCH_TIER_MAX)
268 dev_opts.discard = true;
271 dev_opts.path = strdup(optarg);
272 darray_append(devices, dev_opts);
282 if (!darray_size(devices))
283 die("Please supply a device");
285 if (opts.encrypted && !no_passphrase) {
286 opts.passphrase = read_passphrase("Enter passphrase: ");
288 if (isatty(STDIN_FILENO)) {
290 read_passphrase("Enter same passphrase again: ");
292 if (strcmp(opts.passphrase, pass2)) {
293 memzero_explicit(opts.passphrase,
294 strlen(opts.passphrase));
295 memzero_explicit(pass2, strlen(pass2));
296 die("Passphrases do not match");
299 memzero_explicit(pass2, strlen(pass2));
304 darray_foreach(dev, devices)
305 dev->fd = open_for_format(dev->path, force);
308 bcache_format(opts, devices.item, darray_size(devices));
309 bcache_super_print(sb, HUMAN_READABLE);
312 if (opts.passphrase) {
313 memzero_explicit(opts.passphrase, strlen(opts.passphrase));
314 free(opts.passphrase);