]> git.sesse.net Git - bcachefs-tools-debian/blob - cmd_format.c
Update for new superblock options; makefile 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 "libbcachefs.h"
26 #include "crypto.h"
27 #include "opts.h"
28 #include "util.h"
29
30 #define OPTS                                                                    \
31 t("bcachefs format - create a new bcachefs filesystem on one or more devices")  \
32 t("Usage: bcachefs 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('L',  label,                  "label",                NULL)                   \
45 x('U',  uuid,                   "uuid",                 NULL)                   \
46 x('f',  force,                  NULL,                   NULL)                   \
47 t("")                                                                           \
48 t("Device specific options:")                                                   \
49 x(0,    fs_size,                "size",                 "Size of filesystem on device")\
50 x(0,    bucket_size,            "size",                 "Bucket size")          \
51 x('t',  tier,                   "#",                    "Higher tier indicates slower devices")\
52 x(0,    discard,                NULL,                   NULL)                   \
53 x(0,    data_allowed,           "journal,btree,data",   "Allowed types of data on this device")\
54 t("Device specific options must come before corresponding devices, e.g.")       \
55 t("  bcachefs format --tier 0 /dev/sdb --tier 1 /dev/sdc")                      \
56 t("")                                                                           \
57 x('q',  quiet,                  NULL,                   "Only print errors")    \
58 x('h',  help,                   NULL,                   "Display this help and exit")
59
60 static void usage(void)
61 {
62 #define t(text)                         puts(text "\n")
63 #define x(shortopt, longopt, arg, help) do {                            \
64         OPTS
65 #undef x
66 #undef t
67
68         puts("bcachefs format - create a new bcachefs filesystem on one or more devices\n"
69              "Usage: bcachefs format [OPTION]... <devices>\n"
70              "\n"
71              "Options:\n"
72              "  -b, --block=size\n"
73              "      --btree_node=size       Btree node size, default 256k\n"
74              "      --metadata_checksum_type=(none|crc32c|crc64)\n"
75              "      --data_checksum_type=(none|crc32c|crc64)\n"
76              "      --compression_type=(none|lz4|gzip)\n"
77              "      --data_replicas=#       Number of data replicas\n"
78              "      --metadata_replicas=#   Number of metadata replicas\n"
79              "      --encrypted             Enable whole filesystem encryption (chacha20/poly1305)\n"
80              "      --no_passphrase         Don't encrypt master encryption key\n"
81              "      --error_action=(continue|readonly|panic)\n"
82              "                              Action to take on filesystem error\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              "  -q, --quiet                 Only print errors\n"
94              "  -h, --help                  Display this help and exit\n"
95              "\n"
96              "Device specific options must come before corresponding devices, e.g.\n"
97              "  bcachefs format --tier 0 /dev/sdb --tier 1 /dev/sdc\n"
98              "\n"
99              "Report bugs to <linux-bcache@vger.kernel.org>");
100 }
101
102 enum {
103         O_no_opt = 1,
104 #define t(text)
105 #define x(shortopt, longopt, arg, help) O_##longopt,
106         OPTS
107 #undef x
108 #undef t
109 };
110
111 static const struct option format_opts[] = {
112 #define t(text)
113 #define x(shortopt, longopt, arg, help) {                               \
114         .name           = #longopt,                                     \
115         .has_arg        = arg ? required_argument : no_argument,        \
116         .flag           = NULL,                                         \
117         .val            = O_##longopt,                                  \
118 },
119         OPTS
120 #undef x
121 #undef t
122         { NULL }
123 };
124
125 u64 read_flag_list_or_die(char *opt, const char * const list[],
126                           const char *msg)
127 {
128         u64 v = bch2_read_flag_list(opt, list);
129         if (v == (u64) -1)
130                 die("Bad %s %s", msg, opt);
131
132         return v;
133 }
134
135 int cmd_format(int argc, char *argv[])
136 {
137         darray(struct dev_opts) devices;
138         struct format_opts opts = format_opts_default();
139         struct dev_opts dev_opts = dev_opts_default(), *dev;
140         bool force = false, no_passphrase = false, quiet = false;
141         int opt;
142
143         darray_init(devices);
144
145         while ((opt = getopt_long(argc, argv,
146                                   "-b:e:L:U:ft:qh",
147                                   format_opts,
148                                   NULL)) != -1)
149                 switch (opt) {
150                 case O_block_size:
151                 case 'b':
152                         opts.block_size =
153                                 hatoi_validate(optarg, "block size");
154                         break;
155                 case O_btree_node_size:
156                         opts.btree_node_size =
157                                 hatoi_validate(optarg, "btree node size");
158                         break;
159                 case O_metadata_checksum_type:
160                         opts.meta_csum_type =
161                                 read_string_list_or_die(optarg,
162                                                 bch2_csum_types, "checksum type");
163                         break;
164                 case O_data_checksum_type:
165                         opts.data_csum_type =
166                                 read_string_list_or_die(optarg,
167                                                 bch2_csum_types, "checksum type");
168                         break;
169                 case O_compression_type:
170                         opts.compression_type =
171                                 read_string_list_or_die(optarg,
172                                                 bch2_compression_types,
173                                                 "compression type");
174                         break;
175                 case O_data_replicas:
176                         if (kstrtouint(optarg, 10, &opts.data_replicas) ||
177                             dev_opts.tier >= BCH_REPLICAS_MAX)
178                                 die("invalid replicas");
179                         break;
180                 case O_metadata_replicas:
181                         if (kstrtouint(optarg, 10, &opts.meta_replicas) ||
182                             dev_opts.tier >= BCH_REPLICAS_MAX)
183                                 die("invalid replicas");
184                         break;
185                 case O_encrypted:
186                         opts.encrypted = true;
187                         break;
188                 case O_no_passphrase:
189                         no_passphrase = true;
190                         break;
191                 case O_error_action:
192                 case 'e':
193                         opts.on_error_action =
194                                 read_string_list_or_die(optarg,
195                                                 bch2_error_actions, "error action");
196                         break;
197                 case O_label:
198                 case 'L':
199                         opts.label = strdup(optarg);
200                         break;
201                 case O_uuid:
202                 case 'U':
203                         if (uuid_parse(optarg, opts.uuid.b))
204                                 die("Bad uuid");
205                         break;
206                 case O_force:
207                 case 'f':
208                         force = true;
209                         break;
210                 case O_fs_size:
211                         if (bch2_strtoull_h(optarg, &dev_opts.size))
212                                 die("invalid filesystem size");
213
214                         dev_opts.size >>= 9;
215                         break;
216                 case O_bucket_size:
217                         dev_opts.bucket_size =
218                                 hatoi_validate(optarg, "bucket size");
219                         break;
220                 case O_tier:
221                 case 't':
222                         if (kstrtouint(optarg, 10, &dev_opts.tier) ||
223                             dev_opts.tier >= BCH_TIER_MAX)
224                                 die("invalid tier");
225                         break;
226                 case O_discard:
227                         dev_opts.discard = true;
228                         break;
229                 case O_data_allowed:
230                         dev_opts.data_allowed =
231                                 read_flag_list_or_die(optarg,
232                                         bch2_data_types, "data type");
233                         break;
234                 case O_no_opt:
235                         dev_opts.path = strdup(optarg);
236                         darray_append(devices, dev_opts);
237                         dev_opts.size = 0;
238                         break;
239                 case O_quiet:
240                 case 'q':
241                         quiet = true;
242                         break;
243                 case O_help:
244                 case 'h':
245                         usage();
246                         exit(EXIT_SUCCESS);
247                         break;
248                 }
249
250         if (!darray_size(devices))
251                 die("Please supply a device");
252
253         if (opts.encrypted && !no_passphrase) {
254                 opts.passphrase = read_passphrase("Enter passphrase: ");
255
256                 if (isatty(STDIN_FILENO)) {
257                         char *pass2 =
258                                 read_passphrase("Enter same passphrase again: ");
259
260                         if (strcmp(opts.passphrase, pass2)) {
261                                 memzero_explicit(opts.passphrase,
262                                                  strlen(opts.passphrase));
263                                 memzero_explicit(pass2, strlen(pass2));
264                                 die("Passphrases do not match");
265                         }
266
267                         memzero_explicit(pass2, strlen(pass2));
268                         free(pass2);
269                 }
270         }
271
272         darray_foreach(dev, devices)
273                 dev->fd = open_for_format(dev->path, force);
274
275         struct bch_sb *sb =
276                 bch2_format(opts, devices.item, darray_size(devices));
277
278         if (!quiet)
279                 bch2_super_print(sb, HUMAN_READABLE);
280         free(sb);
281
282         if (opts.passphrase) {
283                 memzero_explicit(opts.passphrase, strlen(opts.passphrase));
284                 free(opts.passphrase);
285         }
286
287         return 0;
288 }
289
290 int cmd_show_super(int argc, char *argv[])
291 {
292         struct bch_sb *sb;
293
294         if (argc != 2)
295                 die("please supply a single device");
296
297         sb = bch2_super_read(argv[1]);
298         bch2_super_print(sb, HUMAN_READABLE);
299         return 0;
300 }