]> git.sesse.net Git - bcachefs-tools-debian/blob - bcache-format.c
bcache in userspace; userspace fsck
[bcachefs-tools-debian] / bcache-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 <blkid.h>
21 #include <uuid/uuid.h>
22
23 #include "ccan/darray/darray.h"
24
25 #include "bcache-cmds.h"
26 #include "libbcache.h"
27
28 /* Open a block device, do magic blkid stuff: */
29 static int open_for_format(const char *dev, bool force)
30 {
31         blkid_probe pr;
32         const char *fs_type = NULL, *fs_label = NULL;
33         size_t fs_type_len, fs_label_len;
34         int fd;
35
36         if ((fd = open(dev, O_RDWR|O_EXCL)) == -1)
37                 die("Can't open dev %s: %s\n", dev, strerror(errno));
38
39         if (force)
40                 return fd;
41
42         if (!(pr = blkid_new_probe()))
43                 die("blkid error 1");
44         if (blkid_probe_set_device(pr, fd, 0, 0))
45                 die("blkid error 2");
46         if (blkid_probe_enable_partitions(pr, true))
47                 die("blkid error 3");
48         if (blkid_do_fullprobe(pr) < 0)
49                 die("blkid error 4");
50
51         blkid_probe_lookup_value(pr, "TYPE", &fs_type, &fs_type_len);
52         blkid_probe_lookup_value(pr, "LABEL", &fs_label, &fs_label_len);
53
54         if (fs_type) {
55                 if (fs_label)
56                         printf("%s contains a %s filesystem labelled '%s'\n",
57                                dev, fs_type, fs_label);
58                 else
59                         printf("%s contains a %s filesystem\n",
60                                dev, fs_type);
61                 if (!ask_proceed())
62                         exit(EXIT_FAILURE);
63         }
64
65         blkid_free_probe(pr);
66         return fd;
67 }
68
69 static void usage(void)
70 {
71         puts("bcache format - create a new bcache filesystem on one or more devices\n"
72              "Usage: bcache format [OPTION]... <devices>\n"
73              "\n"
74              "Options:\n"
75              "  -b, --block=size\n"
76              "      --btree_node=size       Btree node size, default 256k\n"
77              "      --metadata_checksum_type=(none|crc32c|crc64)\n"
78              "      --data_checksum_type=(none|crc32c|crc64)\n"
79              "      --compression_type=(none|lz4|gzip)\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=#                tier of subsequent 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         exit(EXIT_SUCCESS);
100 }
101
102 #define OPTS                                                            \
103         OPT('b',        block_size,             required_argument)      \
104         OPT(0,          btree_node_size,        required_argument)      \
105         OPT(0,          metadata_checksum_type, required_argument)      \
106         OPT(0,          data_checksum_type,     required_argument)      \
107         OPT(0,          compression_type,       required_argument)      \
108         OPT('e',        error_action,           required_argument)      \
109         OPT(0,          max_journal_entry_size, required_argument)      \
110         OPT('L',        label,                  required_argument)      \
111         OPT('U',        uuid,                   required_argument)      \
112         OPT('f',        force,                  no_argument)            \
113         OPT(0,          fs_size,                required_argument)      \
114         OPT(0,          bucket_size,            required_argument)      \
115         OPT('t',        tier,                   required_argument)      \
116         OPT(0,          discard,                no_argument)            \
117         OPT('h',        help,                   no_argument)
118
119 enum {
120         Opt_no_opt = 1,
121 #define OPT(shortopt, longopt, has_arg) Opt_##longopt,
122         OPTS
123 #undef OPT
124 };
125
126 static const struct option format_opts[] = {
127 #define OPT(shortopt, longopt, has_arg) {                               \
128                 #longopt,  has_arg, NULL, Opt_##longopt                 \
129         },
130         OPTS
131 #undef OPT
132         { NULL }
133 };
134
135 int cmd_format(int argc, char *argv[])
136 {
137         darray(struct dev_opts) devices;
138         struct dev_opts *dev;
139         unsigned block_size = 0;
140         unsigned btree_node_size = 0;
141         unsigned meta_csum_type = BCH_CSUM_CRC32C;
142         unsigned data_csum_type = BCH_CSUM_CRC32C;
143         unsigned compression_type = BCH_COMPRESSION_NONE;
144         unsigned on_error_action = BCH_ON_ERROR_RO;
145         char *label = NULL;
146         uuid_le uuid;
147         bool force = false;
148
149         /* Device specific options: */
150         u64 filesystem_size = 0;
151         unsigned bucket_size = 0;
152         unsigned tier = 0;
153         bool discard = false;
154         unsigned max_journal_entry_size = 0;
155         char *passphrase = NULL;
156         int opt;
157
158         darray_init(devices);
159         uuid_clear(uuid.b);
160
161         while ((opt = getopt_long(argc, argv,
162                                   "-b:e:L:U:ft:h",
163                                   format_opts,
164                                   NULL)) != -1)
165                 switch (opt) {
166                 case Opt_block_size:
167                 case 'b':
168                         block_size = hatoi_validate(optarg,
169                                                 "block size");
170                         break;
171                 case Opt_btree_node_size:
172                         btree_node_size = hatoi_validate(optarg,
173                                                 "btree node size");
174                         break;
175                 case Opt_metadata_checksum_type:
176                         meta_csum_type = read_string_list_or_die(optarg,
177                                                 csum_types, "checksum type");
178                         break;
179                 case Opt_data_checksum_type:
180                         data_csum_type = read_string_list_or_die(optarg,
181                                                 csum_types, "checksum type");
182                         break;
183                 case Opt_compression_type:
184                         compression_type = read_string_list_or_die(optarg,
185                                                 compression_types, "compression type");
186                         break;
187                 case Opt_error_action:
188                 case 'e':
189                         on_error_action = read_string_list_or_die(optarg,
190                                                 error_actions, "error action");
191                         break;
192                 case Opt_max_journal_entry_size:
193                         max_journal_entry_size = hatoi_validate(optarg,
194                                                 "journal entry size");
195                         break;
196                 case Opt_label:
197                 case 'L':
198                         label = strdup(optarg);
199                         break;
200                 case Opt_uuid:
201                 case 'U':
202                         if (uuid_parse(optarg, uuid.b))
203                                 die("Bad uuid");
204                         break;
205                 case Opt_force:
206                 case 'f':
207                         force = true;
208                         break;
209                 case Opt_fs_size:
210                         filesystem_size = hatoi(optarg) >> 9;
211                         break;
212                 case Opt_bucket_size:
213                         bucket_size = hatoi_validate(optarg, "bucket size");
214                         break;
215                 case Opt_tier:
216                 case 't':
217                         tier = strtoul_or_die(optarg, CACHE_TIERS, "tier");
218                         break;
219                 case Opt_discard:
220                         discard = true;
221                         break;
222                 case Opt_no_opt:
223                         darray_append(devices, (struct dev_opts) {
224                                 .path                   = strdup(optarg),
225                                 .size                   = filesystem_size,
226                                 .bucket_size            = bucket_size,
227                                 .tier                   = tier,
228                                 .discard                = discard,
229                         });
230                         break;
231                 case Opt_help:
232                 case 'h':
233                         usage();
234                         break;
235                 }
236
237         if (!darray_size(devices))
238                 die("Please supply a device");
239
240         if (uuid_is_null(uuid.b))
241                 uuid_generate(uuid.b);
242
243         darray_foreach(dev, devices)
244                 dev->fd = open_for_format(dev->path, force);
245
246         bcache_format(devices.item, darray_size(devices),
247                       block_size,
248                       btree_node_size,
249                       meta_csum_type,
250                       data_csum_type,
251                       compression_type,
252                       1,
253                       1,
254                       on_error_action,
255                       max_journal_entry_size,
256                       label,
257                       uuid);
258
259         if (passphrase) {
260                 memzero_explicit(passphrase, strlen(passphrase));
261                 free(passphrase);
262         }
263
264         return 0;
265 }