b1cf88905b816edf424cd5c0d1ab3745b7a87339
[linux-block.git] / fs / bcachefs / opts.c
1 // SPDX-License-Identifier: GPL-2.0
2
3 #include <linux/kernel.h>
4 #include <linux/fs_parser.h>
5
6 #include "bcachefs.h"
7 #include "compress.h"
8 #include "disk_groups.h"
9 #include "error.h"
10 #include "movinggc.h"
11 #include "opts.h"
12 #include "rebalance.h"
13 #include "recovery_passes.h"
14 #include "super-io.h"
15 #include "util.h"
16
17 #define x(t, n, ...) [n] = #t,
18
19 const char * const bch2_error_actions[] = {
20         BCH_ERROR_ACTIONS()
21         NULL
22 };
23
24 const char * const bch2_degraded_actions[] = {
25         BCH_DEGRADED_ACTIONS()
26         NULL
27 };
28
29 const char * const bch2_fsck_fix_opts[] = {
30         BCH_FIX_ERRORS_OPTS()
31         NULL
32 };
33
34 const char * const bch2_version_upgrade_opts[] = {
35         BCH_VERSION_UPGRADE_OPTS()
36         NULL
37 };
38
39 const char * const bch2_sb_features[] = {
40         BCH_SB_FEATURES()
41         NULL
42 };
43
44 const char * const bch2_sb_compat[] = {
45         BCH_SB_COMPAT()
46         NULL
47 };
48
49 const char * const __bch2_btree_ids[] = {
50         BCH_BTREE_IDS()
51         NULL
52 };
53
54 const char * const __bch2_csum_types[] = {
55         BCH_CSUM_TYPES()
56         NULL
57 };
58
59 const char * const __bch2_csum_opts[] = {
60         BCH_CSUM_OPTS()
61         NULL
62 };
63
64 const char * const __bch2_compression_types[] = {
65         BCH_COMPRESSION_TYPES()
66         NULL
67 };
68
69 const char * const bch2_compression_opts[] = {
70         BCH_COMPRESSION_OPTS()
71         NULL
72 };
73
74 const char * const __bch2_str_hash_types[] = {
75         BCH_STR_HASH_TYPES()
76         NULL
77 };
78
79 const char * const bch2_str_hash_opts[] = {
80         BCH_STR_HASH_OPTS()
81         NULL
82 };
83
84 const char * const __bch2_data_types[] = {
85         BCH_DATA_TYPES()
86         NULL
87 };
88
89 const char * const bch2_member_states[] = {
90         BCH_MEMBER_STATES()
91         NULL
92 };
93
94 static const char * const __bch2_jset_entry_types[] = {
95         BCH_JSET_ENTRY_TYPES()
96         NULL
97 };
98
99 static const char * const __bch2_fs_usage_types[] = {
100         BCH_FS_USAGE_TYPES()
101         NULL
102 };
103
104 #undef x
105
106 static void prt_str_opt_boundscheck(struct printbuf *out, const char * const opts[],
107                                     unsigned nr, const char *type, unsigned idx)
108 {
109         if (idx < nr)
110                 prt_str(out, opts[idx]);
111         else
112                 prt_printf(out, "(unknown %s %u)", type, idx);
113 }
114
115 #define PRT_STR_OPT_BOUNDSCHECKED(name, type)                                   \
116 void bch2_prt_##name(struct printbuf *out, type t)                              \
117 {                                                                               \
118         prt_str_opt_boundscheck(out, __bch2_##name##s, ARRAY_SIZE(__bch2_##name##s) - 1, #name, t);\
119 }
120
121 PRT_STR_OPT_BOUNDSCHECKED(jset_entry_type,      enum bch_jset_entry_type);
122 PRT_STR_OPT_BOUNDSCHECKED(fs_usage_type,        enum bch_fs_usage_type);
123 PRT_STR_OPT_BOUNDSCHECKED(data_type,            enum bch_data_type);
124 PRT_STR_OPT_BOUNDSCHECKED(csum_opt,             enum bch_csum_opt);
125 PRT_STR_OPT_BOUNDSCHECKED(csum_type,            enum bch_csum_type);
126 PRT_STR_OPT_BOUNDSCHECKED(compression_type,     enum bch_compression_type);
127 PRT_STR_OPT_BOUNDSCHECKED(str_hash_type,        enum bch_str_hash_type);
128
129 static int bch2_opt_fix_errors_parse(struct bch_fs *c, const char *val, u64 *res,
130                                      struct printbuf *err)
131 {
132         if (!val) {
133                 *res = FSCK_FIX_yes;
134         } else {
135                 int ret = match_string(bch2_fsck_fix_opts, -1, val);
136
137                 if (ret < 0 && err)
138                         prt_str(err, "fix_errors: invalid selection");
139                 if (ret < 0)
140                         return ret;
141                 *res = ret;
142         }
143
144         return 0;
145 }
146
147 static void bch2_opt_fix_errors_to_text(struct printbuf *out,
148                                         struct bch_fs *c,
149                                         struct bch_sb *sb,
150                                         u64 v)
151 {
152         prt_str(out, bch2_fsck_fix_opts[v]);
153 }
154
155 #define bch2_opt_fix_errors (struct bch_opt_fn) {       \
156         .parse = bch2_opt_fix_errors_parse,             \
157         .to_text = bch2_opt_fix_errors_to_text,         \
158 }
159
160 const char * const bch2_d_types[BCH_DT_MAX] = {
161         [DT_UNKNOWN]    = "unknown",
162         [DT_FIFO]       = "fifo",
163         [DT_CHR]        = "chr",
164         [DT_DIR]        = "dir",
165         [DT_BLK]        = "blk",
166         [DT_REG]        = "reg",
167         [DT_LNK]        = "lnk",
168         [DT_SOCK]       = "sock",
169         [DT_WHT]        = "whiteout",
170         [DT_SUBVOL]     = "subvol",
171 };
172
173 void bch2_opts_apply(struct bch_opts *dst, struct bch_opts src)
174 {
175 #define x(_name, ...)                                           \
176         if (opt_defined(src, _name))                                    \
177                 opt_set(*dst, _name, src._name);
178
179         BCH_OPTS()
180 #undef x
181 }
182
183 bool bch2_opt_defined_by_id(const struct bch_opts *opts, enum bch_opt_id id)
184 {
185         switch (id) {
186 #define x(_name, ...)                                           \
187         case Opt_##_name:                                               \
188                 return opt_defined(*opts, _name);
189         BCH_OPTS()
190 #undef x
191         default:
192                 BUG();
193         }
194 }
195
196 u64 bch2_opt_get_by_id(const struct bch_opts *opts, enum bch_opt_id id)
197 {
198         switch (id) {
199 #define x(_name, ...)                                           \
200         case Opt_##_name:                                               \
201                 return opts->_name;
202         BCH_OPTS()
203 #undef x
204         default:
205                 BUG();
206         }
207 }
208
209 void bch2_opt_set_by_id(struct bch_opts *opts, enum bch_opt_id id, u64 v)
210 {
211         switch (id) {
212 #define x(_name, ...)                                           \
213         case Opt_##_name:                                               \
214                 opt_set(*opts, _name, v);                               \
215                 break;
216         BCH_OPTS()
217 #undef x
218         default:
219                 BUG();
220         }
221 }
222
223 /* dummy option, for options that aren't stored in the superblock */
224 typedef u64 (*sb_opt_get_fn)(const struct bch_sb *);
225 typedef void (*sb_opt_set_fn)(struct bch_sb *, u64);
226 typedef u64 (*member_opt_get_fn)(const struct bch_member *);
227 typedef void (*member_opt_set_fn)(struct bch_member *, u64);
228
229 __maybe_unused static const sb_opt_get_fn       BCH2_NO_SB_OPT = NULL;
230 __maybe_unused static const sb_opt_set_fn       SET_BCH2_NO_SB_OPT = NULL;
231 __maybe_unused static const member_opt_get_fn   BCH2_NO_MEMBER_OPT = NULL;
232 __maybe_unused static const member_opt_set_fn   SET_BCH2_NO_MEMBER_OPT = NULL;
233
234 #define type_compatible_or_null(_p, _type)                              \
235         __builtin_choose_expr(                                          \
236                 __builtin_types_compatible_p(typeof(_p), typeof(_type)), _p, NULL)
237
238 const struct bch_option bch2_opt_table[] = {
239 #define OPT_BOOL()              .type = BCH_OPT_BOOL, .min = 0, .max = 2
240 #define OPT_UINT(_min, _max)    .type = BCH_OPT_UINT,                   \
241                                 .min = _min, .max = _max
242 #define OPT_STR(_choices)       .type = BCH_OPT_STR,                    \
243                                 .min = 0, .max = ARRAY_SIZE(_choices) - 1, \
244                                 .choices = _choices
245 #define OPT_STR_NOLIMIT(_choices)       .type = BCH_OPT_STR,            \
246                                 .min = 0, .max = U64_MAX,               \
247                                 .choices = _choices
248 #define OPT_BITFIELD(_choices)  .type = BCH_OPT_BITFIELD,               \
249                                 .choices = _choices
250 #define OPT_FN(_fn)             .type = BCH_OPT_FN, .fn = _fn
251
252 #define x(_name, _bits, _flags, _type, _sb_opt, _default, _hint, _help) \
253         [Opt_##_name] = {                                               \
254                 .attr.name      = #_name,                               \
255                 .attr.mode      = (_flags) & OPT_RUNTIME ? 0644 : 0444, \
256                 .flags          = _flags,                               \
257                 .hint           = _hint,                                \
258                 .help           = _help,                                \
259                 .get_sb         = type_compatible_or_null(_sb_opt,      *BCH2_NO_SB_OPT),       \
260                 .set_sb         = type_compatible_or_null(SET_##_sb_opt,*SET_BCH2_NO_SB_OPT),   \
261                 .get_member     = type_compatible_or_null(_sb_opt,      *BCH2_NO_MEMBER_OPT),   \
262                 .set_member     = type_compatible_or_null(SET_##_sb_opt,*SET_BCH2_NO_MEMBER_OPT),\
263                 _type                                                   \
264         },
265
266         BCH_OPTS()
267 #undef x
268 };
269
270 int bch2_opt_lookup(const char *name)
271 {
272         const struct bch_option *i;
273
274         for (i = bch2_opt_table;
275              i < bch2_opt_table + ARRAY_SIZE(bch2_opt_table);
276              i++)
277                 if (!strcmp(name, i->attr.name))
278                         return i - bch2_opt_table;
279
280         return -1;
281 }
282
283 struct opt_synonym {
284         const char      *s1, *s2;
285 };
286
287 static const struct opt_synonym bch2_opt_synonyms[] = {
288         { "quota",      "usrquota" },
289 };
290
291 static int bch2_mount_opt_lookup(const char *name)
292 {
293         const struct opt_synonym *i;
294
295         for (i = bch2_opt_synonyms;
296              i < bch2_opt_synonyms + ARRAY_SIZE(bch2_opt_synonyms);
297              i++)
298                 if (!strcmp(name, i->s1))
299                         name = i->s2;
300
301         return bch2_opt_lookup(name);
302 }
303
304 struct opt_val_synonym {
305         const char      *opt, *v1, *v2;
306 };
307
308 static const struct opt_val_synonym bch2_opt_val_synonyms[] = {
309         { "degraded",   "true",         "yes" },
310         { "degraded",   "false",        "no"  },
311         { "degraded",   "1",            "yes" },
312         { "degraded",   "0",            "no"  },
313 };
314
315 static const char *bch2_opt_val_synonym_lookup(const char *opt, const char *val)
316 {
317         const struct opt_val_synonym *i;
318
319         for (i = bch2_opt_val_synonyms;
320              i < bch2_opt_val_synonyms + ARRAY_SIZE(bch2_opt_val_synonyms);
321              i++)
322                 if (!strcmp(opt, i->opt) && !strcmp(val, i->v1))
323                         return i->v2;
324
325         return val;
326 }
327
328 int bch2_opt_validate(const struct bch_option *opt, u64 v, struct printbuf *err)
329 {
330         if (v < opt->min) {
331                 if (err)
332                         prt_printf(err, "%s: too small (min %llu)",
333                                opt->attr.name, opt->min);
334                 return -BCH_ERR_ERANGE_option_too_small;
335         }
336
337         if (opt->max && v >= opt->max) {
338                 if (err)
339                         prt_printf(err, "%s: too big (max %llu)",
340                                opt->attr.name, opt->max);
341                 return -BCH_ERR_ERANGE_option_too_big;
342         }
343
344         if ((opt->flags & OPT_SB_FIELD_SECTORS) && (v & 511)) {
345                 if (err)
346                         prt_printf(err, "%s: not a multiple of 512",
347                                opt->attr.name);
348                 return -BCH_ERR_opt_parse_error;
349         }
350
351         if ((opt->flags & OPT_MUST_BE_POW_2) && !is_power_of_2(v)) {
352                 if (err)
353                         prt_printf(err, "%s: must be a power of two",
354                                opt->attr.name);
355                 return -BCH_ERR_opt_parse_error;
356         }
357
358         if (opt->fn.validate)
359                 return opt->fn.validate(v, err);
360
361         return 0;
362 }
363
364 int bch2_opt_parse(struct bch_fs *c,
365                    const struct bch_option *opt,
366                    const char *val, u64 *res,
367                    struct printbuf *err)
368 {
369         ssize_t ret;
370
371         if (err)
372                 printbuf_indent_add_nextline(err, 2);
373
374         switch (opt->type) {
375         case BCH_OPT_BOOL:
376                 if (!val)
377                         val = "1";
378
379                 ret = lookup_constant(bool_names, val, -BCH_ERR_option_not_bool);
380                 if (ret != -BCH_ERR_option_not_bool) {
381                         *res = ret;
382                 } else {
383                         if (err)
384                                 prt_printf(err, "%s: must be bool", opt->attr.name);
385                         return ret;
386                 }
387                 break;
388         case BCH_OPT_UINT:
389                 if (!val) {
390                         prt_printf(err, "%s: required value",
391                                    opt->attr.name);
392                         return -EINVAL;
393                 }
394
395                 if (*val != '-') {
396                         ret = opt->flags & OPT_HUMAN_READABLE
397                             ? bch2_strtou64_h(val, res)
398                             : kstrtou64(val, 10, res);
399                 } else {
400                         prt_printf(err, "%s: must be a non-negative number", opt->attr.name);
401                         return -BCH_ERR_option_negative;
402                 }
403
404                 if (ret < 0) {
405                         if (err)
406                                 prt_printf(err, "%s: must be a number",
407                                            opt->attr.name);
408                         return ret;
409                 }
410                 break;
411         case BCH_OPT_STR:
412                 if (!val) {
413                         prt_printf(err, "%s: required value",
414                                    opt->attr.name);
415                         return -EINVAL;
416                 }
417
418                 ret = match_string(opt->choices, -1, val);
419                 if (ret < 0) {
420                         if (err)
421                                 prt_printf(err, "%s: invalid selection",
422                                            opt->attr.name);
423                         return ret;
424                 }
425
426                 *res = ret;
427                 break;
428         case BCH_OPT_BITFIELD: {
429                 s64 v = bch2_read_flag_list(val, opt->choices);
430                 if (v < 0)
431                         return v;
432                 *res = v;
433                 break;
434         }
435         case BCH_OPT_FN:
436                 ret = opt->fn.parse(c, val, res, err);
437
438                 if (ret == -BCH_ERR_option_needs_open_fs)
439                         return ret;
440
441                 if (ret < 0) {
442                         if (err)
443                                 prt_printf(err, "%s: parse error",
444                                            opt->attr.name);
445                         return ret;
446                 }
447         }
448
449         return bch2_opt_validate(opt, *res, err);
450 }
451
452 void bch2_opt_to_text(struct printbuf *out,
453                       struct bch_fs *c, struct bch_sb *sb,
454                       const struct bch_option *opt, u64 v,
455                       unsigned flags)
456 {
457         if (flags & OPT_SHOW_MOUNT_STYLE) {
458                 if (opt->type == BCH_OPT_BOOL) {
459                         prt_printf(out, "%s%s",
460                                v ? "" : "no",
461                                opt->attr.name);
462                         return;
463                 }
464
465                 prt_printf(out, "%s=", opt->attr.name);
466         }
467
468         switch (opt->type) {
469         case BCH_OPT_BOOL:
470         case BCH_OPT_UINT:
471                 if (opt->flags & OPT_HUMAN_READABLE)
472                         prt_human_readable_u64(out, v);
473                 else
474                         prt_printf(out, "%lli", v);
475                 break;
476         case BCH_OPT_STR:
477                 if (v < opt->min || v >= opt->max)
478                         prt_printf(out, "(invalid option %lli)", v);
479                 else if (flags & OPT_SHOW_FULL_LIST)
480                         prt_string_option(out, opt->choices, v);
481                 else
482                         prt_str(out, opt->choices[v]);
483                 break;
484         case BCH_OPT_BITFIELD:
485                 prt_bitflags(out, opt->choices, v);
486                 break;
487         case BCH_OPT_FN:
488                 opt->fn.to_text(out, c, sb, v);
489                 break;
490         default:
491                 BUG();
492         }
493 }
494
495 void bch2_opts_to_text(struct printbuf *out,
496                        struct bch_opts opts,
497                        struct bch_fs *c, struct bch_sb *sb,
498                        unsigned show_mask, unsigned hide_mask,
499                        unsigned flags)
500 {
501         bool first = true;
502
503         for (enum bch_opt_id i = 0; i < bch2_opts_nr; i++) {
504                 const struct bch_option *opt = &bch2_opt_table[i];
505
506                 if ((opt->flags & hide_mask) || !(opt->flags & show_mask))
507                         continue;
508
509                 u64 v = bch2_opt_get_by_id(&opts, i);
510                 if (v == bch2_opt_get_by_id(&bch2_opts_default, i))
511                         continue;
512
513                 if (!first)
514                         prt_char(out, ',');
515                 first = false;
516
517                 bch2_opt_to_text(out, c, sb, opt, v, flags);
518         }
519 }
520
521 int bch2_opt_hook_pre_set(struct bch_fs *c, struct bch_dev *ca, enum bch_opt_id id, u64 v)
522 {
523         int ret = 0;
524
525         switch (id) {
526         case Opt_state:
527                 if (ca)
528                         return bch2_dev_set_state(c, ca, v, BCH_FORCE_IF_DEGRADED);
529                 break;
530
531         case Opt_compression:
532         case Opt_background_compression:
533                 ret = bch2_check_set_has_compressed_data(c, v);
534                 break;
535         case Opt_erasure_code:
536                 if (v)
537                         bch2_check_set_feature(c, BCH_FEATURE_ec);
538                 break;
539         default:
540                 break;
541         }
542
543         return ret;
544 }
545
546 int bch2_opts_hooks_pre_set(struct bch_fs *c)
547 {
548         for (unsigned i = 0; i < bch2_opts_nr; i++) {
549                 int ret = bch2_opt_hook_pre_set(c, NULL, i, bch2_opt_get_by_id(&c->opts, i));
550                 if (ret)
551                         return ret;
552         }
553
554         return 0;
555 }
556
557 void bch2_opt_hook_post_set(struct bch_fs *c, struct bch_dev *ca, u64 inum,
558                             struct bch_opts *new_opts, enum bch_opt_id id)
559 {
560         switch (id) {
561         case Opt_foreground_target:
562                 if (new_opts->foreground_target &&
563                     !new_opts->background_target)
564                         bch2_set_rebalance_needs_scan(c, inum);
565                 break;
566         case Opt_compression:
567                 if (new_opts->compression &&
568                     !new_opts->background_compression)
569                         bch2_set_rebalance_needs_scan(c, inum);
570                 break;
571         case Opt_background_target:
572                 if (new_opts->background_target)
573                         bch2_set_rebalance_needs_scan(c, inum);
574                 break;
575         case Opt_background_compression:
576                 if (new_opts->background_compression)
577                         bch2_set_rebalance_needs_scan(c, inum);
578                 break;
579         case Opt_rebalance_enabled:
580                 bch2_rebalance_wakeup(c);
581                 break;
582         case Opt_copygc_enabled:
583                 bch2_copygc_wakeup(c);
584                 break;
585         case Opt_discard:
586                 if (!ca) {
587                         mutex_lock(&c->sb_lock);
588                         for_each_member_device(c, ca) {
589                                 struct bch_member *m =
590                                         bch2_members_v2_get_mut(ca->disk_sb.sb, ca->dev_idx);
591                                 SET_BCH_MEMBER_DISCARD(m, c->opts.discard);
592                         }
593
594                         bch2_write_super(c);
595                         mutex_unlock(&c->sb_lock);
596                 }
597                 break;
598         case Opt_version_upgrade:
599                 /*
600                  * XXX: in the future we'll likely want to do compatible
601                  * upgrades at runtime as well, but right now there's nothing
602                  * that does that:
603                  */
604                 if (new_opts->version_upgrade == BCH_VERSION_UPGRADE_incompatible)
605                         bch2_sb_upgrade_incompat(c);
606                 break;
607         default:
608                 break;
609         }
610 }
611
612 int bch2_parse_one_mount_opt(struct bch_fs *c, struct bch_opts *opts,
613                              struct printbuf *parse_later,
614                              const char *name, const char *val)
615 {
616         struct printbuf err = PRINTBUF;
617         u64 v;
618         int ret, id;
619
620         id = bch2_mount_opt_lookup(name);
621
622         /* Check for the form "noopt", negation of a boolean opt: */
623         if (id < 0 &&
624             !val &&
625             !strncmp("no", name, 2)) {
626                 id = bch2_mount_opt_lookup(name + 2);
627                 val = "0";
628         }
629
630         /* Unknown options are ignored: */
631         if (id < 0)
632                 return 0;
633
634         /* must have a value for synonym lookup - but OPT_FN is weird */
635         if (!val && bch2_opt_table[id].type != BCH_OPT_FN)
636                 val = "1";
637
638         val = bch2_opt_val_synonym_lookup(name, val);
639
640         if (!(bch2_opt_table[id].flags & OPT_MOUNT))
641                 goto bad_opt;
642
643         if (id == Opt_acl &&
644             !IS_ENABLED(CONFIG_BCACHEFS_POSIX_ACL))
645                 goto bad_opt;
646
647         if ((id == Opt_usrquota ||
648              id == Opt_grpquota) &&
649             !IS_ENABLED(CONFIG_BCACHEFS_QUOTA))
650                 goto bad_opt;
651
652         ret = bch2_opt_parse(c, &bch2_opt_table[id], val, &v, &err);
653         if (ret == -BCH_ERR_option_needs_open_fs) {
654                 ret = 0;
655
656                 if (parse_later) {
657                         prt_printf(parse_later, "%s=%s,", name, val);
658                         if (parse_later->allocation_failure)
659                                 ret = -ENOMEM;
660                 }
661
662                 goto out;
663         }
664
665         if (ret < 0)
666                 goto bad_val;
667
668         if (opts)
669                 bch2_opt_set_by_id(opts, id, v);
670
671         ret = 0;
672 out:
673         printbuf_exit(&err);
674         return ret;
675 bad_opt:
676         ret = -BCH_ERR_option_name;
677         goto out;
678 bad_val:
679         ret = -BCH_ERR_option_value;
680         goto out;
681 }
682
683 int bch2_parse_mount_opts(struct bch_fs *c, struct bch_opts *opts,
684                           struct printbuf *parse_later, char *options,
685                           bool ignore_unknown)
686 {
687         char *copied_opts, *copied_opts_start;
688         char *opt, *name, *val;
689         int ret = 0;
690
691         if (!options)
692                 return 0;
693
694         /*
695          * sys_fsconfig() is now occasionally providing us with option lists
696          * starting with a comma - weird.
697          */
698         if (*options == ',')
699                 options++;
700
701         copied_opts = kstrdup(options, GFP_KERNEL);
702         if (!copied_opts)
703                 return -ENOMEM;
704         copied_opts_start = copied_opts;
705
706         while ((opt = strsep(&copied_opts, ",")) != NULL) {
707                 if (!*opt)
708                         continue;
709
710                 name    = strsep(&opt, "=");
711                 val     = opt;
712
713                 ret = bch2_parse_one_mount_opt(c, opts, parse_later, name, val);
714                 if (ret == -BCH_ERR_option_name && ignore_unknown)
715                         ret = 0;
716                 if (ret) {
717                         pr_err("Error parsing option %s: %s", name, bch2_err_str(ret));
718                         break;
719                 }
720         }
721
722         kfree(copied_opts_start);
723         return ret;
724 }
725
726 u64 bch2_opt_from_sb(struct bch_sb *sb, enum bch_opt_id id, int dev_idx)
727 {
728         const struct bch_option *opt = bch2_opt_table + id;
729         u64 v;
730
731         if (dev_idx < 0) {
732                 v = opt->get_sb(sb);
733         } else {
734                 if (WARN(!bch2_member_exists(sb, dev_idx),
735                          "tried to set device option %s on nonexistent device %i",
736                          opt->attr.name, dev_idx))
737                         return 0;
738
739                 struct bch_member m = bch2_sb_member_get(sb, dev_idx);
740                 v = opt->get_member(&m);
741         }
742
743         if (opt->flags & OPT_SB_FIELD_ONE_BIAS)
744                 --v;
745
746         if (opt->flags & OPT_SB_FIELD_ILOG2)
747                 v = 1ULL << v;
748
749         if (opt->flags & OPT_SB_FIELD_SECTORS)
750                 v <<= 9;
751
752         return v;
753 }
754
755 /*
756  * Initial options from superblock - here we don't want any options undefined,
757  * any options the superblock doesn't specify are set to 0:
758  */
759 int bch2_opts_from_sb(struct bch_opts *opts, struct bch_sb *sb)
760 {
761         for (unsigned id = 0; id < bch2_opts_nr; id++) {
762                 const struct bch_option *opt = bch2_opt_table + id;
763
764                 if (opt->get_sb)
765                         bch2_opt_set_by_id(opts, id, bch2_opt_from_sb(sb, id, -1));
766         }
767
768         return 0;
769 }
770
771 bool __bch2_opt_set_sb(struct bch_sb *sb, int dev_idx,
772                        const struct bch_option *opt, u64 v)
773 {
774         bool changed = false;
775
776         if (opt->flags & OPT_SB_FIELD_SECTORS)
777                 v >>= 9;
778
779         if (opt->flags & OPT_SB_FIELD_ILOG2)
780                 v = ilog2(v);
781
782         if (opt->flags & OPT_SB_FIELD_ONE_BIAS)
783                 v++;
784
785         if ((opt->flags & OPT_FS) && opt->set_sb && dev_idx < 0) {
786                 changed = v != opt->get_sb(sb);
787
788                 opt->set_sb(sb, v);
789         }
790
791         if ((opt->flags & OPT_DEVICE) && opt->set_member && dev_idx >= 0) {
792                 if (WARN(!bch2_member_exists(sb, dev_idx),
793                          "tried to set device option %s on nonexistent device %i",
794                          opt->attr.name, dev_idx))
795                         return false;
796
797                 struct bch_member *m = bch2_members_v2_get_mut(sb, dev_idx);
798                 changed = v != opt->get_member(m);
799                 opt->set_member(m, v);
800         }
801
802         return changed;
803 }
804
805 bool bch2_opt_set_sb(struct bch_fs *c, struct bch_dev *ca,
806                      const struct bch_option *opt, u64 v)
807 {
808         mutex_lock(&c->sb_lock);
809         bool changed = __bch2_opt_set_sb(c->disk_sb.sb, ca ? ca->dev_idx : -1, opt, v);
810         if (changed)
811                 bch2_write_super(c);
812         mutex_unlock(&c->sb_lock);
813         return changed;
814 }
815
816 /* io opts: */
817
818 struct bch_io_opts bch2_opts_to_inode_opts(struct bch_opts src)
819 {
820         struct bch_io_opts opts = {
821 #define x(_name, _bits) ._name = src._name,
822         BCH_INODE_OPTS()
823 #undef x
824         };
825
826         bch2_io_opts_fixups(&opts);
827         return opts;
828 }
829
830 bool bch2_opt_is_inode_opt(enum bch_opt_id id)
831 {
832         static const enum bch_opt_id inode_opt_list[] = {
833 #define x(_name, _bits) Opt_##_name,
834         BCH_INODE_OPTS()
835 #undef x
836         };
837         unsigned i;
838
839         for (i = 0; i < ARRAY_SIZE(inode_opt_list); i++)
840                 if (inode_opt_list[i] == id)
841                         return true;
842
843         return false;
844 }