xref: /linux/fs/bcachefs/opts.c (revision 72bea132f3680ee51e7ed2cee62892b6f5121909)
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 
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 
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 
141 u64 BCH2_NO_SB_OPT(const struct bch_sb *sb)
142 {
143 	BUG();
144 }
145 
146 void SET_BCH2_NO_SB_OPT(struct bch_sb *sb, u64 v)
147 {
148 	BUG();
149 }
150 
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 
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 
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 
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 
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 
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 
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 
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 < 0 ? ret : -BCH_ERR_option_not_bool;
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 
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 
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 
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 
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 -ENOMEM;
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 = -BCH_ERR_option_name;
505 	goto out;
506 bad_val:
507 	pr_err("Invalid mount option %s", err.buf);
508 	ret = -BCH_ERR_option_value;
509 	goto out;
510 out:
511 	kfree(copied_opts_start);
512 	printbuf_exit(&err);
513 	return ret;
514 }
515 
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  */
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 
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 
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 
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 
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