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