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