]> git.sesse.net Git - bcachefs-tools-debian/blob - cmd_format.c
cmd_device_add improvements
[bcachefs-tools-debian] / cmd_format.c
1 /*
2  * Authors: Kent Overstreet <kent.overstreet@gmail.com>
3  *          Gabriel de Perthuis <g2p.code@gmail.com>
4  *          Jacob Malevich <jam@datera.io>
5  *
6  * GPLv2
7  */
8 #include <errno.h>
9 #include <fcntl.h>
10 #include <getopt.h>
11 #include <stdbool.h>
12 #include <stdint.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <sys/stat.h>
17 #include <sys/types.h>
18 #include <unistd.h>
19
20 #include <uuid/uuid.h>
21
22 #include "ccan/darray/darray.h"
23
24 #include "cmds.h"
25 #include "libbcache.h"
26 #include "crypto.h"
27 #include "opts.h"
28 #include "util.h"
29
30 #define OPTS                                                                    \
31 t("bcache format - create a new bcache filesystem on one or more devices")      \
32 t("Usage: bcache format [OPTION]... <devices>")                                 \
33 t("")                                                                           \
34 x('b',  block_size,             "size",                 NULL)                   \
35 x(0,    btree_node_size,        "size",                 "Default 256k")         \
36 x(0,    metadata_checksum_type, "(none|crc32c|crc64)",  NULL)                   \
37 x(0,    data_checksum_type,     "(none|crc32c|crc64)",  NULL)                   \
38 x(0,    compression_type,       "(none|lz4|gzip)",      NULL)                   \
39 x(0,    data_replicas,          "#",                    NULL)                   \
40 x(0,    metadata_replicas,      "#",                    NULL)                   \
41 x(0,    encrypted,              NULL,                   "Enable whole filesystem encryption (chacha20/poly1305)")\
42 x(0,    no_passphrase,          NULL,                   "Don't encrypt master encryption key")\
43 x('e',  error_action,           "(continue|readonly|panic)", NULL)              \
44 x(0,    max_journal_entry_size, "size",                 NULL)                   \
45 x('L',  label,                  "label",                NULL)                   \
46 x('U',  uuid,                   "uuid",                 NULL)                   \
47 x('f',  force,                  NULL,                   NULL)                   \
48 t("")                                                                           \
49 t("Device specific options:")                                                   \
50 x(0,    fs_size,                "size",                 "Size of filesystem on device")\
51 x(0,    bucket_size,            "size",                 "Bucket size")          \
52 x('t',  tier,                   "#",                    "Higher tier indicates slower devices")\
53 x(0,    discard,                NULL,                   NULL)                   \
54 t("Device specific options must come before corresponding devices, e.g.")       \
55 t("  bcache format --tier 0 /dev/sdb --tier 1 /dev/sdc")                        \
56 t("")                                                                           \
57 x('h',  help,                   NULL,                   "display this help and exit")
58
59 static void usage(void)
60 {
61 #define t(text)                         puts(text "\n")
62 #define x(shortopt, longopt, arg, help) do {                            \
63         OPTS
64 #undef x
65 #undef t
66
67         puts("bcache format - create a new bcache filesystem on one or more devices\n"
68              "Usage: bcache format [OPTION]... <devices>\n"
69              "\n"
70              "Options:\n"
71              "  -b, --block=size\n"
72              "      --btree_node=size       Btree node size, default 256k\n"
73              "      --metadata_checksum_type=(none|crc32c|crc64)\n"
74              "      --data_checksum_type=(none|crc32c|crc64)\n"
75              "      --compression_type=(none|lz4|gzip)\n"
76              "      --data_replicas=#       Number of data replicas\n"
77              "      --metadata_replicas=#   Number of metadata replicas\n"
78              "      --encrypted             Enable whole filesystem encryption (chacha20/poly1305)\n"
79              "      --no_passphrase         Don't encrypt master encryption key\n"
80              "      --error_action=(continue|readonly|panic)\n"
81              "                              Action to take on filesystem error\n"
82              "      --max_journal_entry_size=size\n"
83              "  -l, --label=label\n"
84              "      --uuid=uuid\n"
85              "  -f, --force\n"
86              "\n"
87              "Device specific options:\n"
88              "      --fs_size=size          Size of filesystem on device\n"
89              "      --bucket=size           Bucket size\n"
90              "      --discard               Enable discards\n"
91              "  -t, --tier=#                Higher tier (e.g. 1) indicates slower devices\n"
92              "\n"
93              "  -h, --help                  Display this help and exit\n"
94              "\n"
95              "Device specific options must come before corresponding devices, e.g.\n"
96              "  bcache format --tier 0 /dev/sdb --tier 1 /dev/sdc\n"
97              "\n"
98              "Report bugs to <linux-bcache@vger.kernel.org>");
99 }
100
101 enum {
102         O_no_opt = 1,
103 #define t(text)
104 #define x(shortopt, longopt, arg, help) O_##longopt,
105         OPTS
106 #undef x
107 #undef t
108 };
109
110 static const struct option format_opts[] = {
111 #define t(text)
112 #define x(shortopt, longopt, arg, help) {                               \
113         .name           = #longopt,                                     \
114         .has_arg        = arg ? required_argument : no_argument,        \
115         .flag           = NULL,                                         \
116         .val            = O_##longopt,                                  \
117 },
118         OPTS
119 #undef x
120 #undef t
121         { NULL }
122 };
123
124 int cmd_format(int argc, char *argv[])
125 {
126         darray(struct dev_opts) devices;
127         struct format_opts opts = format_opts_default();
128         struct dev_opts dev_opts = { 0 }, *dev;
129         bool force = false, no_passphrase = false;
130         int opt;
131
132         darray_init(devices);
133
134         while ((opt = getopt_long(argc, argv,
135                                   "-b:e:L:U:ft:h",
136                                   format_opts,
137                                   NULL)) != -1)
138                 switch (opt) {
139                 case O_block_size:
140                 case 'b':
141                         opts.block_size =
142                                 hatoi_validate(optarg, "block size");
143                         break;
144                 case O_btree_node_size:
145                         opts.btree_node_size =
146                                 hatoi_validate(optarg, "btree node size");
147                         break;
148                 case O_metadata_checksum_type:
149                         opts.meta_csum_type =
150                                 read_string_list_or_die(optarg,
151                                                 bch_csum_types, "checksum type");
152                         break;
153                 case O_data_checksum_type:
154                         opts.data_csum_type =
155                                 read_string_list_or_die(optarg,
156                                                 bch_csum_types, "checksum type");
157                         break;
158                 case O_compression_type:
159                         opts.compression_type =
160                                 read_string_list_or_die(optarg,
161                                                 bch_compression_types,
162                                                 "compression type");
163                         break;
164                 case O_data_replicas:
165                         if (kstrtouint(optarg, 10, &opts.data_replicas) ||
166                             dev_opts.tier >= BCH_REPLICAS_MAX)
167                                 die("invalid replicas");
168                         break;
169                 case O_metadata_replicas:
170                         if (kstrtouint(optarg, 10, &opts.meta_replicas) ||
171                             dev_opts.tier >= BCH_REPLICAS_MAX)
172                                 die("invalid replicas");
173                         break;
174                 case O_encrypted:
175                         opts.encrypted = true;
176                         break;
177                 case O_no_passphrase:
178                         no_passphrase = true;
179                         break;
180                 case O_error_action:
181                 case 'e':
182                         opts.on_error_action =
183                                 read_string_list_or_die(optarg,
184                                                 bch_error_actions, "error action");
185                         break;
186                 case O_max_journal_entry_size:
187                         opts.max_journal_entry_size =
188                                 hatoi_validate(optarg, "journal entry size");
189                         break;
190                 case O_label:
191                 case 'L':
192                         opts.label = strdup(optarg);
193                         break;
194                 case O_uuid:
195                 case 'U':
196                         if (uuid_parse(optarg, opts.uuid.b))
197                                 die("Bad uuid");
198                         break;
199                 case O_force:
200                 case 'f':
201                         force = true;
202                         break;
203                 case O_fs_size:
204                         if (bch_strtoull_h(optarg, &dev_opts.size))
205                                 die("invalid filesystem size");
206
207                         dev_opts.size >>= 9;
208                         break;
209                 case O_bucket_size:
210                         dev_opts.bucket_size =
211                                 hatoi_validate(optarg, "bucket size");
212                         break;
213                 case O_tier:
214                 case 't':
215                         if (kstrtouint(optarg, 10, &dev_opts.tier) ||
216                             dev_opts.tier >= BCH_TIER_MAX)
217                                 die("invalid tier");
218                         break;
219                 case O_discard:
220                         dev_opts.discard = true;
221                         break;
222                 case O_no_opt:
223                         dev_opts.path = strdup(optarg);
224                         darray_append(devices, dev_opts);
225                         dev_opts.size = 0;
226                         break;
227                 case O_help:
228                 case 'h':
229                         usage();
230                         exit(EXIT_SUCCESS);
231                         break;
232                 }
233
234         if (!darray_size(devices))
235                 die("Please supply a device");
236
237         if (opts.encrypted && !no_passphrase) {
238                 opts.passphrase = read_passphrase("Enter passphrase: ");
239
240                 if (isatty(STDIN_FILENO)) {
241                         char *pass2 =
242                                 read_passphrase("Enter same passphrase again: ");
243
244                         if (strcmp(opts.passphrase, pass2)) {
245                                 memzero_explicit(opts.passphrase,
246                                                  strlen(opts.passphrase));
247                                 memzero_explicit(pass2, strlen(pass2));
248                                 die("Passphrases do not match");
249                         }
250
251                         memzero_explicit(pass2, strlen(pass2));
252                         free(pass2);
253                 }
254         }
255
256         darray_foreach(dev, devices)
257                 dev->fd = open_for_format(dev->path, force);
258
259         struct bch_sb *sb =
260                 bcache_format(opts, devices.item, darray_size(devices));
261         bcache_super_print(sb, HUMAN_READABLE);
262         free(sb);
263
264         if (opts.passphrase) {
265                 memzero_explicit(opts.passphrase, strlen(opts.passphrase));
266                 free(opts.passphrase);
267         }
268
269         return 0;
270 }