]> git.sesse.net Git - bcachefs-tools-debian/blob - libbcachefs/opts.c
Update bcachefs sources to fd6fb298aa bcachefs: Make sure hash info gets initialized...
[bcachefs-tools-debian] / libbcachefs / opts.c
1 // SPDX-License-Identifier: GPL-2.0
2
3 #include <linux/kernel.h>
4
5 #include "bcachefs.h"
6 #include "compress.h"
7 #include "disk_groups.h"
8 #include "opts.h"
9 #include "super-io.h"
10 #include "util.h"
11
12 #define x(t, n) [n] = #t,
13
14 const char * const bch2_metadata_versions[] = {
15         BCH_METADATA_VERSIONS()
16         NULL
17 };
18
19 const char * const bch2_error_actions[] = {
20         BCH_ERROR_ACTIONS()
21         NULL
22 };
23
24 const char * const bch2_sb_features[] = {
25         BCH_SB_FEATURES()
26         NULL
27 };
28
29 const char * const bch2_sb_compat[] = {
30         BCH_SB_COMPAT()
31         NULL
32 };
33
34 const char * const bch2_btree_ids[] = {
35         BCH_BTREE_IDS()
36         "interior btree node",
37         NULL
38 };
39
40 const char * const bch2_csum_types[] = {
41         BCH_CSUM_TYPES()
42         NULL
43 };
44
45 const char * const bch2_csum_opts[] = {
46         BCH_CSUM_OPTS()
47         NULL
48 };
49
50 const char * const bch2_compression_types[] = {
51         BCH_COMPRESSION_TYPES()
52         NULL
53 };
54
55 const char * const bch2_compression_opts[] = {
56         BCH_COMPRESSION_OPTS()
57         NULL
58 };
59
60 const char * const bch2_str_hash_types[] = {
61         BCH_STR_HASH_TYPES()
62         NULL
63 };
64
65 const char * const bch2_str_hash_opts[] = {
66         BCH_STR_HASH_OPTS()
67         NULL
68 };
69
70 const char * const bch2_data_types[] = {
71         BCH_DATA_TYPES()
72         NULL
73 };
74
75 const char * const bch2_member_states[] = {
76         BCH_MEMBER_STATES()
77         NULL
78 };
79
80 const char * const bch2_jset_entry_types[] = {
81         BCH_JSET_ENTRY_TYPES()
82         NULL
83 };
84
85 const char * const bch2_fs_usage_types[] = {
86         BCH_FS_USAGE_TYPES()
87         NULL
88 };
89
90 #undef x
91
92 const char * const bch2_d_types[BCH_DT_MAX] = {
93         [DT_UNKNOWN]    = "unknown",
94         [DT_FIFO]       = "fifo",
95         [DT_CHR]        = "chr",
96         [DT_DIR]        = "dir",
97         [DT_BLK]        = "blk",
98         [DT_REG]        = "reg",
99         [DT_LNK]        = "lnk",
100         [DT_SOCK]       = "sock",
101         [DT_WHT]        = "whiteout",
102         [DT_SUBVOL]     = "subvol",
103 };
104
105 u64 BCH2_NO_SB_OPT(const struct bch_sb *sb)
106 {
107         BUG();
108 }
109
110 void SET_BCH2_NO_SB_OPT(struct bch_sb *sb, u64 v)
111 {
112         BUG();
113 }
114
115 void bch2_opts_apply(struct bch_opts *dst, struct bch_opts src)
116 {
117 #define x(_name, ...)                                           \
118         if (opt_defined(src, _name))                                    \
119                 opt_set(*dst, _name, src._name);
120
121         BCH_OPTS()
122 #undef x
123 }
124
125 bool bch2_opt_defined_by_id(const struct bch_opts *opts, enum bch_opt_id id)
126 {
127         switch (id) {
128 #define x(_name, ...)                                           \
129         case Opt_##_name:                                               \
130                 return opt_defined(*opts, _name);
131         BCH_OPTS()
132 #undef x
133         default:
134                 BUG();
135         }
136 }
137
138 u64 bch2_opt_get_by_id(const struct bch_opts *opts, enum bch_opt_id id)
139 {
140         switch (id) {
141 #define x(_name, ...)                                           \
142         case Opt_##_name:                                               \
143                 return opts->_name;
144         BCH_OPTS()
145 #undef x
146         default:
147                 BUG();
148         }
149 }
150
151 void bch2_opt_set_by_id(struct bch_opts *opts, enum bch_opt_id id, u64 v)
152 {
153         switch (id) {
154 #define x(_name, ...)                                           \
155         case Opt_##_name:                                               \
156                 opt_set(*opts, _name, v);                               \
157                 break;
158         BCH_OPTS()
159 #undef x
160         default:
161                 BUG();
162         }
163 }
164
165 const struct bch_option bch2_opt_table[] = {
166 #define OPT_BOOL()              .type = BCH_OPT_BOOL, .min = 0, .max = 2
167 #define OPT_UINT(_min, _max)    .type = BCH_OPT_UINT,                   \
168                                 .min = _min, .max = _max
169 #define OPT_STR(_choices)       .type = BCH_OPT_STR,                    \
170                                 .min = 0, .max = ARRAY_SIZE(_choices),\
171                                 .choices = _choices
172 #define OPT_FN(_fn)             .type = BCH_OPT_FN,                     \
173                                 .parse = _fn##_parse,                   \
174                                 .to_text = _fn##_to_text
175
176 #define x(_name, _bits, _flags, _type, _sb_opt, _default, _hint, _help) \
177         [Opt_##_name] = {                                               \
178                 .attr   = {                                             \
179                         .name   = #_name,                               \
180                         .mode = (_flags) & OPT_RUNTIME ? 0644 : 0444,   \
181                 },                                                      \
182                 .flags  = _flags,                                       \
183                 .hint   = _hint,                                        \
184                 .help   = _help,                                        \
185                 .get_sb = _sb_opt,                                      \
186                 .set_sb = SET_##_sb_opt,                                \
187                 _type                                                   \
188         },
189
190         BCH_OPTS()
191 #undef x
192 };
193
194 int bch2_opt_lookup(const char *name)
195 {
196         const struct bch_option *i;
197
198         for (i = bch2_opt_table;
199              i < bch2_opt_table + ARRAY_SIZE(bch2_opt_table);
200              i++)
201                 if (!strcmp(name, i->attr.name))
202                         return i - bch2_opt_table;
203
204         return -1;
205 }
206
207 struct synonym {
208         const char      *s1, *s2;
209 };
210
211 static const struct synonym bch_opt_synonyms[] = {
212         { "quota",      "usrquota" },
213 };
214
215 static int bch2_mount_opt_lookup(const char *name)
216 {
217         const struct synonym *i;
218
219         for (i = bch_opt_synonyms;
220              i < bch_opt_synonyms + ARRAY_SIZE(bch_opt_synonyms);
221              i++)
222                 if (!strcmp(name, i->s1))
223                         name = i->s2;
224
225         return bch2_opt_lookup(name);
226 }
227
228 int bch2_opt_validate(const struct bch_option *opt, u64 v, struct printbuf *err)
229 {
230         if (v < opt->min) {
231                 if (err)
232                         prt_printf(err, "%s: too small (min %llu)",
233                                opt->attr.name, opt->min);
234                 return -ERANGE;
235         }
236
237         if (opt->max && v >= opt->max) {
238                 if (err)
239                         prt_printf(err, "%s: too big (max %llu)",
240                                opt->attr.name, opt->max);
241                 return -ERANGE;
242         }
243
244         if ((opt->flags & OPT_SB_FIELD_SECTORS) && (v & 511)) {
245                 if (err)
246                         prt_printf(err, "%s: not a multiple of 512",
247                                opt->attr.name);
248                 return -EINVAL;
249         }
250
251         if ((opt->flags & OPT_MUST_BE_POW_2) && !is_power_of_2(v)) {
252                 if (err)
253                         prt_printf(err, "%s: must be a power of two",
254                                opt->attr.name);
255                 return -EINVAL;
256         }
257
258         return 0;
259 }
260
261 int bch2_opt_parse(struct bch_fs *c,
262                    const struct bch_option *opt,
263                    const char *val, u64 *res,
264                    struct printbuf *err)
265 {
266         ssize_t ret;
267
268         switch (opt->type) {
269         case BCH_OPT_BOOL:
270                 ret = kstrtou64(val, 10, res);
271                 if (ret < 0 || (*res != 0 && *res != 1)) {
272                         if (err)
273                                 prt_printf(err, "%s: must be bool",
274                                            opt->attr.name);
275                         return ret;
276                 }
277                 break;
278         case BCH_OPT_UINT:
279                 ret = opt->flags & OPT_HUMAN_READABLE
280                         ? bch2_strtou64_h(val, res)
281                         : kstrtou64(val, 10, res);
282                 if (ret < 0) {
283                         if (err)
284                                 prt_printf(err, "%s: must be a number",
285                                            opt->attr.name);
286                         return ret;
287                 }
288                 break;
289         case BCH_OPT_STR:
290                 ret = match_string(opt->choices, -1, val);
291                 if (ret < 0) {
292                         if (err)
293                                 prt_printf(err, "%s: invalid selection",
294                                            opt->attr.name);
295                         return ret;
296                 }
297
298                 *res = ret;
299                 break;
300         case BCH_OPT_FN:
301                 if (!c)
302                         return 0;
303
304                 ret = opt->parse(c, val, res);
305                 if (ret < 0) {
306                         if (err)
307                                 prt_printf(err, "%s: parse error",
308                                            opt->attr.name);
309                         return ret;
310                 }
311         }
312
313         return bch2_opt_validate(opt, *res, err);
314 }
315
316 void bch2_opt_to_text(struct printbuf *out,
317                       struct bch_fs *c, struct bch_sb *sb,
318                       const struct bch_option *opt, u64 v,
319                       unsigned flags)
320 {
321         if (flags & OPT_SHOW_MOUNT_STYLE) {
322                 if (opt->type == BCH_OPT_BOOL) {
323                         prt_printf(out, "%s%s",
324                                v ? "" : "no",
325                                opt->attr.name);
326                         return;
327                 }
328
329                 prt_printf(out, "%s=", opt->attr.name);
330         }
331
332         switch (opt->type) {
333         case BCH_OPT_BOOL:
334         case BCH_OPT_UINT:
335                 if (opt->flags & OPT_HUMAN_READABLE)
336                         prt_human_readable_u64(out, v);
337                 else
338                         prt_printf(out, "%lli", v);
339                 break;
340         case BCH_OPT_STR:
341                 if (flags & OPT_SHOW_FULL_LIST)
342                         prt_string_option(out, opt->choices, v);
343                 else
344                         prt_printf(out, "%s", opt->choices[v]);
345                 break;
346         case BCH_OPT_FN:
347                 opt->to_text(out, c, sb, v);
348                 break;
349         default:
350                 BUG();
351         }
352 }
353
354 int bch2_opt_check_may_set(struct bch_fs *c, int id, u64 v)
355 {
356         int ret = 0;
357
358         switch (id) {
359         case Opt_compression:
360         case Opt_background_compression:
361                 ret = bch2_check_set_has_compressed_data(c, v);
362                 break;
363         case Opt_erasure_code:
364                 if (v)
365                         bch2_check_set_feature(c, BCH_FEATURE_ec);
366                 break;
367         }
368
369         return ret;
370 }
371
372 int bch2_opts_check_may_set(struct bch_fs *c)
373 {
374         unsigned i;
375         int ret;
376
377         for (i = 0; i < bch2_opts_nr; i++) {
378                 ret = bch2_opt_check_may_set(c, i,
379                                 bch2_opt_get_by_id(&c->opts, i));
380                 if (ret)
381                         return ret;
382         }
383
384         return 0;
385 }
386
387 int bch2_parse_mount_opts(struct bch_fs *c, struct bch_opts *opts,
388                           char *options)
389 {
390         char *copied_opts, *copied_opts_start;
391         char *opt, *name, *val;
392         int ret, id;
393         struct printbuf err = PRINTBUF;
394         u64 v;
395
396         if (!options)
397                 return 0;
398
399         copied_opts = kstrdup(options, GFP_KERNEL);
400         if (!copied_opts)
401                 return -1;
402         copied_opts_start = copied_opts;
403
404         while ((opt = strsep(&copied_opts, ",")) != NULL) {
405                 name    = strsep(&opt, "=");
406                 val     = opt;
407
408                 if (val) {
409                         id = bch2_mount_opt_lookup(name);
410                         if (id < 0)
411                                 goto bad_opt;
412
413                         ret = bch2_opt_parse(c, &bch2_opt_table[id], val, &v, &err);
414                         if (ret < 0)
415                                 goto bad_val;
416                 } else {
417                         id = bch2_mount_opt_lookup(name);
418                         v = 1;
419
420                         if (id < 0 &&
421                             !strncmp("no", name, 2)) {
422                                 id = bch2_mount_opt_lookup(name + 2);
423                                 v = 0;
424                         }
425
426                         if (id < 0)
427                                 goto bad_opt;
428
429                         if (bch2_opt_table[id].type != BCH_OPT_BOOL)
430                                 goto no_val;
431                 }
432
433                 if (!(bch2_opt_table[id].flags & OPT_MOUNT))
434                         goto bad_opt;
435
436                 if (id == Opt_acl &&
437                     !IS_ENABLED(CONFIG_BCACHEFS_POSIX_ACL))
438                         goto bad_opt;
439
440                 if ((id == Opt_usrquota ||
441                      id == Opt_grpquota) &&
442                     !IS_ENABLED(CONFIG_BCACHEFS_QUOTA))
443                         goto bad_opt;
444
445                 bch2_opt_set_by_id(opts, id, v);
446         }
447
448         ret = 0;
449         goto out;
450
451 bad_opt:
452         pr_err("Bad mount option %s", name);
453         ret = -1;
454         goto out;
455 bad_val:
456         pr_err("Invalid mount option %s", err.buf);
457         ret = -1;
458         goto out;
459 no_val:
460         pr_err("Mount option %s requires a value", name);
461         ret = -1;
462         goto out;
463 out:
464         kfree(copied_opts_start);
465         printbuf_exit(&err);
466         return ret;
467 }
468
469 u64 bch2_opt_from_sb(struct bch_sb *sb, enum bch_opt_id id)
470 {
471         const struct bch_option *opt = bch2_opt_table + id;
472         u64 v;
473
474         v = opt->get_sb(sb);
475
476         if (opt->flags & OPT_SB_FIELD_ILOG2)
477                 v = 1ULL << v;
478
479         if (opt->flags & OPT_SB_FIELD_SECTORS)
480                 v <<= 9;
481
482         return v;
483 }
484
485 /*
486  * Initial options from superblock - here we don't want any options undefined,
487  * any options the superblock doesn't specify are set to 0:
488  */
489 int bch2_opts_from_sb(struct bch_opts *opts, struct bch_sb *sb)
490 {
491         unsigned id;
492
493         for (id = 0; id < bch2_opts_nr; id++) {
494                 const struct bch_option *opt = bch2_opt_table + id;
495
496                 if (opt->get_sb == BCH2_NO_SB_OPT)
497                         continue;
498
499                 bch2_opt_set_by_id(opts, id, bch2_opt_from_sb(sb, id));
500         }
501
502         return 0;
503 }
504
505 void __bch2_opt_set_sb(struct bch_sb *sb, const struct bch_option *opt, u64 v)
506 {
507         if (opt->set_sb == SET_BCH2_NO_SB_OPT)
508                 return;
509
510         if (opt->flags & OPT_SB_FIELD_SECTORS)
511                 v >>= 9;
512
513         if (opt->flags & OPT_SB_FIELD_ILOG2)
514                 v = ilog2(v);
515
516         opt->set_sb(sb, v);
517 }
518
519 void bch2_opt_set_sb(struct bch_fs *c, const struct bch_option *opt, u64 v)
520 {
521         if (opt->set_sb == SET_BCH2_NO_SB_OPT)
522                 return;
523
524         mutex_lock(&c->sb_lock);
525         __bch2_opt_set_sb(c->disk_sb.sb, opt, v);
526         bch2_write_super(c);
527         mutex_unlock(&c->sb_lock);
528 }
529
530 /* io opts: */
531
532 struct bch_io_opts bch2_opts_to_inode_opts(struct bch_opts src)
533 {
534         return (struct bch_io_opts) {
535 #define x(_name, _bits) ._name = src._name,
536         BCH_INODE_OPTS()
537 #undef x
538         };
539 }
540
541 bool bch2_opt_is_inode_opt(enum bch_opt_id id)
542 {
543         static const enum bch_opt_id inode_opt_list[] = {
544 #define x(_name, _bits) Opt_##_name,
545         BCH_INODE_OPTS()
546 #undef x
547         };
548         unsigned i;
549
550         for (i = 0; i < ARRAY_SIZE(inode_opt_list); i++)
551                 if (inode_opt_list[i] == id)
552                         return true;
553
554         return false;
555 }