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