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