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