735 lines · c
1// SPDX-License-Identifier: GPL-2.02 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 16const char * const bch2_error_actions[] = {17 BCH_ERROR_ACTIONS()18 NULL19};20 21const char * const bch2_fsck_fix_opts[] = {22 BCH_FIX_ERRORS_OPTS()23 NULL24};25 26const char * const bch2_version_upgrade_opts[] = {27 BCH_VERSION_UPGRADE_OPTS()28 NULL29};30 31const char * const bch2_sb_features[] = {32 BCH_SB_FEATURES()33 NULL34};35 36const char * const bch2_sb_compat[] = {37 BCH_SB_COMPAT()38 NULL39};40 41const char * const __bch2_btree_ids[] = {42 BCH_BTREE_IDS()43 NULL44};45 46static const char * const __bch2_csum_types[] = {47 BCH_CSUM_TYPES()48 NULL49};50 51const char * const bch2_csum_opts[] = {52 BCH_CSUM_OPTS()53 NULL54};55 56static const char * const __bch2_compression_types[] = {57 BCH_COMPRESSION_TYPES()58 NULL59};60 61const char * const bch2_compression_opts[] = {62 BCH_COMPRESSION_OPTS()63 NULL64};65 66const char * const __bch2_str_hash_types[] = {67 BCH_STR_HASH_TYPES()68 NULL69};70 71const char * const bch2_str_hash_opts[] = {72 BCH_STR_HASH_OPTS()73 NULL74};75 76const char * const __bch2_data_types[] = {77 BCH_DATA_TYPES()78 NULL79};80 81const char * const bch2_member_states[] = {82 BCH_MEMBER_STATES()83 NULL84};85 86static const char * const __bch2_jset_entry_types[] = {87 BCH_JSET_ENTRY_TYPES()88 NULL89};90 91static const char * const __bch2_fs_usage_types[] = {92 BCH_FS_USAGE_TYPES()93 NULL94};95 96#undef x97 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 else104 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);118PRT_STR_OPT_BOUNDSCHECKED(str_hash_type, enum bch_str_hash_type);119 120static int bch2_opt_fix_errors_parse(struct bch_fs *c, const char *val, u64 *res,121 struct printbuf *err)122{123 if (!val) {124 *res = FSCK_FIX_yes;125 } else {126 int ret = match_string(bch2_fsck_fix_opts, -1, val);127 128 if (ret < 0 && err)129 prt_str(err, "fix_errors: invalid selection");130 if (ret < 0)131 return ret;132 *res = ret;133 }134 135 return 0;136}137 138static void bch2_opt_fix_errors_to_text(struct printbuf *out,139 struct bch_fs *c,140 struct bch_sb *sb,141 u64 v)142{143 prt_str(out, bch2_fsck_fix_opts[v]);144}145 146#define bch2_opt_fix_errors (struct bch_opt_fn) { \147 .parse = bch2_opt_fix_errors_parse, \148 .to_text = bch2_opt_fix_errors_to_text, \149}150 151const char * const bch2_d_types[BCH_DT_MAX] = {152 [DT_UNKNOWN] = "unknown",153 [DT_FIFO] = "fifo",154 [DT_CHR] = "chr",155 [DT_DIR] = "dir",156 [DT_BLK] = "blk",157 [DT_REG] = "reg",158 [DT_LNK] = "lnk",159 [DT_SOCK] = "sock",160 [DT_WHT] = "whiteout",161 [DT_SUBVOL] = "subvol",162};163 164u64 BCH2_NO_SB_OPT(const struct bch_sb *sb)165{166 BUG();167}168 169void SET_BCH2_NO_SB_OPT(struct bch_sb *sb, u64 v)170{171 BUG();172}173 174void bch2_opts_apply(struct bch_opts *dst, struct bch_opts src)175{176#define x(_name, ...) \177 if (opt_defined(src, _name)) \178 opt_set(*dst, _name, src._name);179 180 BCH_OPTS()181#undef x182}183 184bool bch2_opt_defined_by_id(const struct bch_opts *opts, enum bch_opt_id id)185{186 switch (id) {187#define x(_name, ...) \188 case Opt_##_name: \189 return opt_defined(*opts, _name);190 BCH_OPTS()191#undef x192 default:193 BUG();194 }195}196 197u64 bch2_opt_get_by_id(const struct bch_opts *opts, enum bch_opt_id id)198{199 switch (id) {200#define x(_name, ...) \201 case Opt_##_name: \202 return opts->_name;203 BCH_OPTS()204#undef x205 default:206 BUG();207 }208}209 210void bch2_opt_set_by_id(struct bch_opts *opts, enum bch_opt_id id, u64 v)211{212 switch (id) {213#define x(_name, ...) \214 case Opt_##_name: \215 opt_set(*opts, _name, v); \216 break;217 BCH_OPTS()218#undef x219 default:220 BUG();221 }222}223 224const struct bch_option bch2_opt_table[] = {225#define OPT_BOOL() .type = BCH_OPT_BOOL, .min = 0, .max = 2226#define OPT_UINT(_min, _max) .type = BCH_OPT_UINT, \227 .min = _min, .max = _max228#define OPT_STR(_choices) .type = BCH_OPT_STR, \229 .min = 0, .max = ARRAY_SIZE(_choices) - 1, \230 .choices = _choices231#define OPT_STR_NOLIMIT(_choices) .type = BCH_OPT_STR, \232 .min = 0, .max = U64_MAX, \233 .choices = _choices234#define OPT_BITFIELD(_choices) .type = BCH_OPT_BITFIELD, \235 .choices = _choices236#define OPT_FN(_fn) .type = BCH_OPT_FN, .fn = _fn237 238#define x(_name, _bits, _flags, _type, _sb_opt, _default, _hint, _help) \239 [Opt_##_name] = { \240 .attr = { \241 .name = #_name, \242 .mode = (_flags) & OPT_RUNTIME ? 0644 : 0444, \243 }, \244 .flags = _flags, \245 .hint = _hint, \246 .help = _help, \247 .get_sb = _sb_opt, \248 .set_sb = SET_##_sb_opt, \249 _type \250 },251 252 BCH_OPTS()253#undef x254};255 256int bch2_opt_lookup(const char *name)257{258 const struct bch_option *i;259 260 for (i = bch2_opt_table;261 i < bch2_opt_table + ARRAY_SIZE(bch2_opt_table);262 i++)263 if (!strcmp(name, i->attr.name))264 return i - bch2_opt_table;265 266 return -1;267}268 269struct synonym {270 const char *s1, *s2;271};272 273static const struct synonym bch_opt_synonyms[] = {274 { "quota", "usrquota" },275};276 277static int bch2_mount_opt_lookup(const char *name)278{279 const struct synonym *i;280 281 for (i = bch_opt_synonyms;282 i < bch_opt_synonyms + ARRAY_SIZE(bch_opt_synonyms);283 i++)284 if (!strcmp(name, i->s1))285 name = i->s2;286 287 return bch2_opt_lookup(name);288}289 290int bch2_opt_validate(const struct bch_option *opt, u64 v, struct printbuf *err)291{292 if (v < opt->min) {293 if (err)294 prt_printf(err, "%s: too small (min %llu)",295 opt->attr.name, opt->min);296 return -BCH_ERR_ERANGE_option_too_small;297 }298 299 if (opt->max && v >= opt->max) {300 if (err)301 prt_printf(err, "%s: too big (max %llu)",302 opt->attr.name, opt->max);303 return -BCH_ERR_ERANGE_option_too_big;304 }305 306 if ((opt->flags & OPT_SB_FIELD_SECTORS) && (v & 511)) {307 if (err)308 prt_printf(err, "%s: not a multiple of 512",309 opt->attr.name);310 return -BCH_ERR_opt_parse_error;311 }312 313 if ((opt->flags & OPT_MUST_BE_POW_2) && !is_power_of_2(v)) {314 if (err)315 prt_printf(err, "%s: must be a power of two",316 opt->attr.name);317 return -BCH_ERR_opt_parse_error;318 }319 320 if (opt->fn.validate)321 return opt->fn.validate(v, err);322 323 return 0;324}325 326int bch2_opt_parse(struct bch_fs *c,327 const struct bch_option *opt,328 const char *val, u64 *res,329 struct printbuf *err)330{331 ssize_t ret;332 333 switch (opt->type) {334 case BCH_OPT_BOOL:335 if (val) {336 ret = kstrtou64(val, 10, res);337 } else {338 ret = 0;339 *res = 1;340 }341 342 if (ret < 0 || (*res != 0 && *res != 1)) {343 if (err)344 prt_printf(err, "%s: must be bool", opt->attr.name);345 return ret < 0 ? ret : -BCH_ERR_option_not_bool;346 }347 break;348 case BCH_OPT_UINT:349 if (!val) {350 prt_printf(err, "%s: required value",351 opt->attr.name);352 return -EINVAL;353 }354 355 ret = opt->flags & OPT_HUMAN_READABLE356 ? bch2_strtou64_h(val, res)357 : kstrtou64(val, 10, res);358 if (ret < 0) {359 if (err)360 prt_printf(err, "%s: must be a number",361 opt->attr.name);362 return ret;363 }364 break;365 case BCH_OPT_STR:366 if (!val) {367 prt_printf(err, "%s: required value",368 opt->attr.name);369 return -EINVAL;370 }371 372 ret = match_string(opt->choices, -1, val);373 if (ret < 0) {374 if (err)375 prt_printf(err, "%s: invalid selection",376 opt->attr.name);377 return ret;378 }379 380 *res = ret;381 break;382 case BCH_OPT_BITFIELD: {383 s64 v = bch2_read_flag_list(val, opt->choices);384 if (v < 0)385 return v;386 *res = v;387 break;388 }389 case BCH_OPT_FN:390 ret = opt->fn.parse(c, val, res, err);391 392 if (ret == -BCH_ERR_option_needs_open_fs)393 return ret;394 395 if (ret < 0) {396 if (err)397 prt_printf(err, "%s: parse error",398 opt->attr.name);399 return ret;400 }401 }402 403 return bch2_opt_validate(opt, *res, err);404}405 406void bch2_opt_to_text(struct printbuf *out,407 struct bch_fs *c, struct bch_sb *sb,408 const struct bch_option *opt, u64 v,409 unsigned flags)410{411 if (flags & OPT_SHOW_MOUNT_STYLE) {412 if (opt->type == BCH_OPT_BOOL) {413 prt_printf(out, "%s%s",414 v ? "" : "no",415 opt->attr.name);416 return;417 }418 419 prt_printf(out, "%s=", opt->attr.name);420 }421 422 switch (opt->type) {423 case BCH_OPT_BOOL:424 case BCH_OPT_UINT:425 if (opt->flags & OPT_HUMAN_READABLE)426 prt_human_readable_u64(out, v);427 else428 prt_printf(out, "%lli", v);429 break;430 case BCH_OPT_STR:431 if (v < opt->min || v >= opt->max)432 prt_printf(out, "(invalid option %lli)", v);433 else if (flags & OPT_SHOW_FULL_LIST)434 prt_string_option(out, opt->choices, v);435 else436 prt_str(out, opt->choices[v]);437 break;438 case BCH_OPT_BITFIELD:439 prt_bitflags(out, opt->choices, v);440 break;441 case BCH_OPT_FN:442 opt->fn.to_text(out, c, sb, v);443 break;444 default:445 BUG();446 }447}448 449void bch2_opts_to_text(struct printbuf *out,450 struct bch_opts opts,451 struct bch_fs *c, struct bch_sb *sb,452 unsigned show_mask, unsigned hide_mask,453 unsigned flags)454{455 bool first = true;456 457 for (enum bch_opt_id i = 0; i < bch2_opts_nr; i++) {458 const struct bch_option *opt = &bch2_opt_table[i];459 460 if ((opt->flags & hide_mask) || !(opt->flags & show_mask))461 continue;462 463 u64 v = bch2_opt_get_by_id(&opts, i);464 if (v == bch2_opt_get_by_id(&bch2_opts_default, i))465 continue;466 467 if (!first)468 prt_char(out, ',');469 first = false;470 471 bch2_opt_to_text(out, c, sb, opt, v, flags);472 }473}474 475int bch2_opt_check_may_set(struct bch_fs *c, int id, u64 v)476{477 int ret = 0;478 479 switch (id) {480 case Opt_compression:481 case Opt_background_compression:482 ret = bch2_check_set_has_compressed_data(c, v);483 break;484 case Opt_erasure_code:485 if (v)486 bch2_check_set_feature(c, BCH_FEATURE_ec);487 break;488 }489 490 return ret;491}492 493int bch2_opts_check_may_set(struct bch_fs *c)494{495 unsigned i;496 int ret;497 498 for (i = 0; i < bch2_opts_nr; i++) {499 ret = bch2_opt_check_may_set(c, i,500 bch2_opt_get_by_id(&c->opts, i));501 if (ret)502 return ret;503 }504 505 return 0;506}507 508int bch2_parse_one_mount_opt(struct bch_fs *c, struct bch_opts *opts,509 struct printbuf *parse_later,510 const char *name, const char *val)511{512 struct printbuf err = PRINTBUF;513 u64 v;514 int ret, id;515 516 id = bch2_mount_opt_lookup(name);517 518 /* Check for the form "noopt", negation of a boolean opt: */519 if (id < 0 &&520 !val &&521 !strncmp("no", name, 2)) {522 id = bch2_mount_opt_lookup(name + 2);523 val = "0";524 }525 526 /* Unknown options are ignored: */527 if (id < 0)528 return 0;529 530 if (!(bch2_opt_table[id].flags & OPT_MOUNT))531 goto bad_opt;532 533 if (id == Opt_acl &&534 !IS_ENABLED(CONFIG_BCACHEFS_POSIX_ACL))535 goto bad_opt;536 537 if ((id == Opt_usrquota ||538 id == Opt_grpquota) &&539 !IS_ENABLED(CONFIG_BCACHEFS_QUOTA))540 goto bad_opt;541 542 ret = bch2_opt_parse(c, &bch2_opt_table[id], val, &v, &err);543 if (ret == -BCH_ERR_option_needs_open_fs && parse_later) {544 prt_printf(parse_later, "%s=%s,", name, val);545 if (parse_later->allocation_failure) {546 ret = -ENOMEM;547 goto out;548 }549 550 ret = 0;551 goto out;552 }553 554 if (ret < 0)555 goto bad_val;556 557 if (opts)558 bch2_opt_set_by_id(opts, id, v);559 560 ret = 0;561 goto out;562 563bad_opt:564 pr_err("Bad mount option %s", name);565 ret = -BCH_ERR_option_name;566 goto out;567 568bad_val:569 pr_err("Invalid mount option %s", err.buf);570 ret = -BCH_ERR_option_value;571 572out:573 printbuf_exit(&err);574 return ret;575}576 577int bch2_parse_mount_opts(struct bch_fs *c, struct bch_opts *opts,578 struct printbuf *parse_later, char *options)579{580 char *copied_opts, *copied_opts_start;581 char *opt, *name, *val;582 int ret;583 584 if (!options)585 return 0;586 587 /*588 * sys_fsconfig() is now occasionally providing us with option lists589 * starting with a comma - weird.590 */591 if (*options == ',')592 options++;593 594 copied_opts = kstrdup(options, GFP_KERNEL);595 if (!copied_opts)596 return -ENOMEM;597 copied_opts_start = copied_opts;598 599 while ((opt = strsep(&copied_opts, ",")) != NULL) {600 if (!*opt)601 continue;602 603 name = strsep(&opt, "=");604 val = opt;605 606 ret = bch2_parse_one_mount_opt(c, opts, parse_later, name, val);607 if (ret < 0)608 goto out;609 }610 611 ret = 0;612 goto out;613 614out:615 kfree(copied_opts_start);616 return ret;617}618 619u64 bch2_opt_from_sb(struct bch_sb *sb, enum bch_opt_id id)620{621 const struct bch_option *opt = bch2_opt_table + id;622 u64 v;623 624 v = opt->get_sb(sb);625 626 if (opt->flags & OPT_SB_FIELD_ILOG2)627 v = 1ULL << v;628 629 if (opt->flags & OPT_SB_FIELD_SECTORS)630 v <<= 9;631 632 return v;633}634 635/*636 * Initial options from superblock - here we don't want any options undefined,637 * any options the superblock doesn't specify are set to 0:638 */639int bch2_opts_from_sb(struct bch_opts *opts, struct bch_sb *sb)640{641 unsigned id;642 643 for (id = 0; id < bch2_opts_nr; id++) {644 const struct bch_option *opt = bch2_opt_table + id;645 646 if (opt->get_sb == BCH2_NO_SB_OPT)647 continue;648 649 bch2_opt_set_by_id(opts, id, bch2_opt_from_sb(sb, id));650 }651 652 return 0;653}654 655struct bch_dev_sb_opt_set {656 void (*set_sb)(struct bch_member *, u64);657};658 659static const struct bch_dev_sb_opt_set bch2_dev_sb_opt_setters [] = {660#define x(n, set) [Opt_##n] = { .set_sb = SET_##set },661 BCH_DEV_OPT_SETTERS()662#undef x663};664 665void __bch2_opt_set_sb(struct bch_sb *sb, int dev_idx,666 const struct bch_option *opt, u64 v)667{668 enum bch_opt_id id = opt - bch2_opt_table;669 670 if (opt->flags & OPT_SB_FIELD_SECTORS)671 v >>= 9;672 673 if (opt->flags & OPT_SB_FIELD_ILOG2)674 v = ilog2(v);675 676 if (opt->flags & OPT_SB_FIELD_ONE_BIAS)677 v++;678 679 if (opt->flags & OPT_FS) {680 if (opt->set_sb != SET_BCH2_NO_SB_OPT)681 opt->set_sb(sb, v);682 }683 684 if ((opt->flags & OPT_DEVICE) && dev_idx >= 0) {685 if (WARN(!bch2_member_exists(sb, dev_idx),686 "tried to set device option %s on nonexistent device %i",687 opt->attr.name, dev_idx))688 return;689 690 struct bch_member *m = bch2_members_v2_get_mut(sb, dev_idx);691 692 const struct bch_dev_sb_opt_set *set = bch2_dev_sb_opt_setters + id;693 if (set->set_sb)694 set->set_sb(m, v);695 else696 pr_err("option %s cannot be set via opt_set_sb()", opt->attr.name);697 }698}699 700void bch2_opt_set_sb(struct bch_fs *c, struct bch_dev *ca,701 const struct bch_option *opt, u64 v)702{703 mutex_lock(&c->sb_lock);704 __bch2_opt_set_sb(c->disk_sb.sb, ca ? ca->dev_idx : -1, opt, v);705 bch2_write_super(c);706 mutex_unlock(&c->sb_lock);707}708 709/* io opts: */710 711struct bch_io_opts bch2_opts_to_inode_opts(struct bch_opts src)712{713 return (struct bch_io_opts) {714#define x(_name, _bits) ._name = src._name,715 BCH_INODE_OPTS()716#undef x717 };718}719 720bool bch2_opt_is_inode_opt(enum bch_opt_id id)721{722 static const enum bch_opt_id inode_opt_list[] = {723#define x(_name, _bits) Opt_##_name,724 BCH_INODE_OPTS()725#undef x726 };727 unsigned i;728 729 for (i = 0; i < ARRAY_SIZE(inode_opt_list); i++)730 if (inode_opt_list[i] == id)731 return true;732 733 return false;734}735