xref: /linux/fs/bcachefs/opts.c (revision b7df4cc3a088a8ce6973c96731bc792dbf54ce28)
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 "recovery_passes.h"
11 #include "super-io.h"
12 #include "util.h"
13 
14 #define x(t, n, ...) [n] = #t,
15 
16 const char * const bch2_error_actions[] = {
17 	BCH_ERROR_ACTIONS()
18 	NULL
19 };
20 
21 const char * const bch2_fsck_fix_opts[] = {
22 	BCH_FIX_ERRORS_OPTS()
23 	NULL
24 };
25 
26 const char * const bch2_version_upgrade_opts[] = {
27 	BCH_VERSION_UPGRADE_OPTS()
28 	NULL
29 };
30 
31 const char * const bch2_sb_features[] = {
32 	BCH_SB_FEATURES()
33 	NULL
34 };
35 
36 const char * const bch2_sb_compat[] = {
37 	BCH_SB_COMPAT()
38 	NULL
39 };
40 
41 const char * const __bch2_btree_ids[] = {
42 	BCH_BTREE_IDS()
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_STR_NOLIMIT(_choices)	.type = BCH_OPT_STR,		\
210 				.min = 0, .max = U64_MAX,		\
211 				.choices = _choices
212 #define OPT_FN(_fn)		.type = BCH_OPT_FN, .fn	= _fn
213 
214 #define x(_name, _bits, _flags, _type, _sb_opt, _default, _hint, _help)	\
215 	[Opt_##_name] = {						\
216 		.attr	= {						\
217 			.name	= #_name,				\
218 			.mode = (_flags) & OPT_RUNTIME ? 0644 : 0444,	\
219 		},							\
220 		.flags	= _flags,					\
221 		.hint	= _hint,					\
222 		.help	= _help,					\
223 		.get_sb = _sb_opt,					\
224 		.set_sb	= SET_##_sb_opt,				\
225 		_type							\
226 	},
227 
228 	BCH_OPTS()
229 #undef x
230 };
231 
232 int bch2_opt_lookup(const char *name)
233 {
234 	const struct bch_option *i;
235 
236 	for (i = bch2_opt_table;
237 	     i < bch2_opt_table + ARRAY_SIZE(bch2_opt_table);
238 	     i++)
239 		if (!strcmp(name, i->attr.name))
240 			return i - bch2_opt_table;
241 
242 	return -1;
243 }
244 
245 struct synonym {
246 	const char	*s1, *s2;
247 };
248 
249 static const struct synonym bch_opt_synonyms[] = {
250 	{ "quota",	"usrquota" },
251 };
252 
253 static int bch2_mount_opt_lookup(const char *name)
254 {
255 	const struct synonym *i;
256 
257 	for (i = bch_opt_synonyms;
258 	     i < bch_opt_synonyms + ARRAY_SIZE(bch_opt_synonyms);
259 	     i++)
260 		if (!strcmp(name, i->s1))
261 			name = i->s2;
262 
263 	return bch2_opt_lookup(name);
264 }
265 
266 int bch2_opt_validate(const struct bch_option *opt, u64 v, struct printbuf *err)
267 {
268 	if (v < opt->min) {
269 		if (err)
270 			prt_printf(err, "%s: too small (min %llu)",
271 			       opt->attr.name, opt->min);
272 		return -BCH_ERR_ERANGE_option_too_small;
273 	}
274 
275 	if (opt->max && v >= opt->max) {
276 		if (err)
277 			prt_printf(err, "%s: too big (max %llu)",
278 			       opt->attr.name, opt->max);
279 		return -BCH_ERR_ERANGE_option_too_big;
280 	}
281 
282 	if ((opt->flags & OPT_SB_FIELD_SECTORS) && (v & 511)) {
283 		if (err)
284 			prt_printf(err, "%s: not a multiple of 512",
285 			       opt->attr.name);
286 		return -BCH_ERR_opt_parse_error;
287 	}
288 
289 	if ((opt->flags & OPT_MUST_BE_POW_2) && !is_power_of_2(v)) {
290 		if (err)
291 			prt_printf(err, "%s: must be a power of two",
292 			       opt->attr.name);
293 		return -BCH_ERR_opt_parse_error;
294 	}
295 
296 	if (opt->fn.validate)
297 		return opt->fn.validate(v, err);
298 
299 	return 0;
300 }
301 
302 int bch2_opt_parse(struct bch_fs *c,
303 		   const struct bch_option *opt,
304 		   const char *val, u64 *res,
305 		   struct printbuf *err)
306 {
307 	ssize_t ret;
308 
309 	switch (opt->type) {
310 	case BCH_OPT_BOOL:
311 		if (val) {
312 			ret = kstrtou64(val, 10, res);
313 		} else {
314 			ret = 0;
315 			*res = 1;
316 		}
317 
318 		if (ret < 0 || (*res != 0 && *res != 1)) {
319 			if (err)
320 				prt_printf(err, "%s: must be bool", opt->attr.name);
321 			return ret < 0 ? ret : -BCH_ERR_option_not_bool;
322 		}
323 		break;
324 	case BCH_OPT_UINT:
325 		if (!val) {
326 			prt_printf(err, "%s: required value",
327 				   opt->attr.name);
328 			return -EINVAL;
329 		}
330 
331 		ret = opt->flags & OPT_HUMAN_READABLE
332 			? bch2_strtou64_h(val, res)
333 			: kstrtou64(val, 10, res);
334 		if (ret < 0) {
335 			if (err)
336 				prt_printf(err, "%s: must be a number",
337 					   opt->attr.name);
338 			return ret;
339 		}
340 		break;
341 	case BCH_OPT_STR:
342 		if (!val) {
343 			prt_printf(err, "%s: required value",
344 				   opt->attr.name);
345 			return -EINVAL;
346 		}
347 
348 		ret = match_string(opt->choices, -1, val);
349 		if (ret < 0) {
350 			if (err)
351 				prt_printf(err, "%s: invalid selection",
352 					   opt->attr.name);
353 			return ret;
354 		}
355 
356 		*res = ret;
357 		break;
358 	case BCH_OPT_FN:
359 		ret = opt->fn.parse(c, val, res, err);
360 		if (ret < 0) {
361 			if (err)
362 				prt_printf(err, "%s: parse error",
363 					   opt->attr.name);
364 			return ret;
365 		}
366 	}
367 
368 	return bch2_opt_validate(opt, *res, err);
369 }
370 
371 void bch2_opt_to_text(struct printbuf *out,
372 		      struct bch_fs *c, struct bch_sb *sb,
373 		      const struct bch_option *opt, u64 v,
374 		      unsigned flags)
375 {
376 	if (flags & OPT_SHOW_MOUNT_STYLE) {
377 		if (opt->type == BCH_OPT_BOOL) {
378 			prt_printf(out, "%s%s",
379 			       v ? "" : "no",
380 			       opt->attr.name);
381 			return;
382 		}
383 
384 		prt_printf(out, "%s=", opt->attr.name);
385 	}
386 
387 	switch (opt->type) {
388 	case BCH_OPT_BOOL:
389 	case BCH_OPT_UINT:
390 		if (opt->flags & OPT_HUMAN_READABLE)
391 			prt_human_readable_u64(out, v);
392 		else
393 			prt_printf(out, "%lli", v);
394 		break;
395 	case BCH_OPT_STR:
396 		if (flags & OPT_SHOW_FULL_LIST)
397 			prt_string_option(out, opt->choices, v);
398 		else
399 			prt_str(out, opt->choices[v]);
400 		break;
401 	case BCH_OPT_FN:
402 		opt->fn.to_text(out, c, sb, v);
403 		break;
404 	default:
405 		BUG();
406 	}
407 }
408 
409 int bch2_opt_check_may_set(struct bch_fs *c, int id, u64 v)
410 {
411 	int ret = 0;
412 
413 	switch (id) {
414 	case Opt_compression:
415 	case Opt_background_compression:
416 		ret = bch2_check_set_has_compressed_data(c, v);
417 		break;
418 	case Opt_erasure_code:
419 		if (v)
420 			bch2_check_set_feature(c, BCH_FEATURE_ec);
421 		break;
422 	}
423 
424 	return ret;
425 }
426 
427 int bch2_opts_check_may_set(struct bch_fs *c)
428 {
429 	unsigned i;
430 	int ret;
431 
432 	for (i = 0; i < bch2_opts_nr; i++) {
433 		ret = bch2_opt_check_may_set(c, i,
434 				bch2_opt_get_by_id(&c->opts, i));
435 		if (ret)
436 			return ret;
437 	}
438 
439 	return 0;
440 }
441 
442 int bch2_parse_mount_opts(struct bch_fs *c, struct bch_opts *opts,
443 			  char *options)
444 {
445 	char *copied_opts, *copied_opts_start;
446 	char *opt, *name, *val;
447 	int ret, id;
448 	struct printbuf err = PRINTBUF;
449 	u64 v;
450 
451 	if (!options)
452 		return 0;
453 
454 	/*
455 	 * sys_fsconfig() is now occasionally providing us with option lists
456 	 * starting with a comma - weird.
457 	 */
458 	if (*options == ',')
459 		options++;
460 
461 	copied_opts = kstrdup(options, GFP_KERNEL);
462 	if (!copied_opts)
463 		return -ENOMEM;
464 	copied_opts_start = copied_opts;
465 
466 	while ((opt = strsep(&copied_opts, ",")) != NULL) {
467 		name	= strsep(&opt, "=");
468 		val	= opt;
469 
470 		id = bch2_mount_opt_lookup(name);
471 
472 		/* Check for the form "noopt", negation of a boolean opt: */
473 		if (id < 0 &&
474 		    !val &&
475 		    !strncmp("no", name, 2)) {
476 			id = bch2_mount_opt_lookup(name + 2);
477 			val = "0";
478 		}
479 
480 		/* Unknown options are ignored: */
481 		if (id < 0)
482 			continue;
483 
484 		if (!(bch2_opt_table[id].flags & OPT_MOUNT))
485 			goto bad_opt;
486 
487 		if (id == Opt_acl &&
488 		    !IS_ENABLED(CONFIG_BCACHEFS_POSIX_ACL))
489 			goto bad_opt;
490 
491 		if ((id == Opt_usrquota ||
492 		     id == Opt_grpquota) &&
493 		    !IS_ENABLED(CONFIG_BCACHEFS_QUOTA))
494 			goto bad_opt;
495 
496 		ret = bch2_opt_parse(c, &bch2_opt_table[id], val, &v, &err);
497 		if (ret < 0)
498 			goto bad_val;
499 
500 		bch2_opt_set_by_id(opts, id, v);
501 	}
502 
503 	ret = 0;
504 	goto out;
505 
506 bad_opt:
507 	pr_err("Bad mount option %s", name);
508 	ret = -BCH_ERR_option_name;
509 	goto out;
510 bad_val:
511 	pr_err("Invalid mount option %s", err.buf);
512 	ret = -BCH_ERR_option_value;
513 	goto out;
514 out:
515 	kfree(copied_opts_start);
516 	printbuf_exit(&err);
517 	return ret;
518 }
519 
520 u64 bch2_opt_from_sb(struct bch_sb *sb, enum bch_opt_id id)
521 {
522 	const struct bch_option *opt = bch2_opt_table + id;
523 	u64 v;
524 
525 	v = opt->get_sb(sb);
526 
527 	if (opt->flags & OPT_SB_FIELD_ILOG2)
528 		v = 1ULL << v;
529 
530 	if (opt->flags & OPT_SB_FIELD_SECTORS)
531 		v <<= 9;
532 
533 	return v;
534 }
535 
536 /*
537  * Initial options from superblock - here we don't want any options undefined,
538  * any options the superblock doesn't specify are set to 0:
539  */
540 int bch2_opts_from_sb(struct bch_opts *opts, struct bch_sb *sb)
541 {
542 	unsigned id;
543 
544 	for (id = 0; id < bch2_opts_nr; id++) {
545 		const struct bch_option *opt = bch2_opt_table + id;
546 
547 		if (opt->get_sb == BCH2_NO_SB_OPT)
548 			continue;
549 
550 		bch2_opt_set_by_id(opts, id, bch2_opt_from_sb(sb, id));
551 	}
552 
553 	return 0;
554 }
555 
556 void __bch2_opt_set_sb(struct bch_sb *sb, const struct bch_option *opt, u64 v)
557 {
558 	if (opt->set_sb == SET_BCH2_NO_SB_OPT)
559 		return;
560 
561 	if (opt->flags & OPT_SB_FIELD_SECTORS)
562 		v >>= 9;
563 
564 	if (opt->flags & OPT_SB_FIELD_ILOG2)
565 		v = ilog2(v);
566 
567 	opt->set_sb(sb, v);
568 }
569 
570 void bch2_opt_set_sb(struct bch_fs *c, const struct bch_option *opt, u64 v)
571 {
572 	if (opt->set_sb == SET_BCH2_NO_SB_OPT)
573 		return;
574 
575 	mutex_lock(&c->sb_lock);
576 	__bch2_opt_set_sb(c->disk_sb.sb, opt, v);
577 	bch2_write_super(c);
578 	mutex_unlock(&c->sb_lock);
579 }
580 
581 /* io opts: */
582 
583 struct bch_io_opts bch2_opts_to_inode_opts(struct bch_opts src)
584 {
585 	return (struct bch_io_opts) {
586 #define x(_name, _bits)	._name = src._name,
587 	BCH_INODE_OPTS()
588 #undef x
589 	};
590 }
591 
592 bool bch2_opt_is_inode_opt(enum bch_opt_id id)
593 {
594 	static const enum bch_opt_id inode_opt_list[] = {
595 #define x(_name, _bits)	Opt_##_name,
596 	BCH_INODE_OPTS()
597 #undef x
598 	};
599 	unsigned i;
600 
601 	for (i = 0; i < ARRAY_SIZE(inode_opt_list); i++)
602 		if (inode_opt_list[i] == id)
603 			return true;
604 
605 	return false;
606 }
607