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