1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <linux/kernel.h> 4 #include <linux/fs_parser.h> 5 6 #include "bcachefs.h" 7 #include "compress.h" 8 #include "disk_groups.h" 9 #include "error.h" 10 #include "movinggc.h" 11 #include "opts.h" 12 #include "rebalance.h" 13 #include "recovery_passes.h" 14 #include "super-io.h" 15 #include "util.h" 16 17 #define x(t, n, ...) [n] = #t, 18 19 const char * const bch2_error_actions[] = { 20 BCH_ERROR_ACTIONS() 21 NULL 22 }; 23 24 const char * const bch2_degraded_actions[] = { 25 BCH_DEGRADED_ACTIONS() 26 NULL 27 }; 28 29 const char * const bch2_fsck_fix_opts[] = { 30 BCH_FIX_ERRORS_OPTS() 31 NULL 32 }; 33 34 const char * const bch2_version_upgrade_opts[] = { 35 BCH_VERSION_UPGRADE_OPTS() 36 NULL 37 }; 38 39 const char * const bch2_sb_features[] = { 40 BCH_SB_FEATURES() 41 NULL 42 }; 43 44 const char * const bch2_sb_compat[] = { 45 BCH_SB_COMPAT() 46 NULL 47 }; 48 49 const char * const __bch2_btree_ids[] = { 50 BCH_BTREE_IDS() 51 NULL 52 }; 53 54 const char * const __bch2_csum_types[] = { 55 BCH_CSUM_TYPES() 56 NULL 57 }; 58 59 const char * const __bch2_csum_opts[] = { 60 BCH_CSUM_OPTS() 61 NULL 62 }; 63 64 const char * const __bch2_compression_types[] = { 65 BCH_COMPRESSION_TYPES() 66 NULL 67 }; 68 69 const char * const bch2_compression_opts[] = { 70 BCH_COMPRESSION_OPTS() 71 NULL 72 }; 73 74 const char * const __bch2_str_hash_types[] = { 75 BCH_STR_HASH_TYPES() 76 NULL 77 }; 78 79 const char * const bch2_str_hash_opts[] = { 80 BCH_STR_HASH_OPTS() 81 NULL 82 }; 83 84 const char * const __bch2_data_types[] = { 85 BCH_DATA_TYPES() 86 NULL 87 }; 88 89 const char * const bch2_member_states[] = { 90 BCH_MEMBER_STATES() 91 NULL 92 }; 93 94 static const char * const __bch2_jset_entry_types[] = { 95 BCH_JSET_ENTRY_TYPES() 96 NULL 97 }; 98 99 static const char * const __bch2_fs_usage_types[] = { 100 BCH_FS_USAGE_TYPES() 101 NULL 102 }; 103 104 #undef x 105 106 static void prt_str_opt_boundscheck(struct printbuf *out, const char * const opts[], 107 unsigned nr, const char *type, unsigned idx) 108 { 109 if (idx < nr) 110 prt_str(out, opts[idx]); 111 else 112 prt_printf(out, "(unknown %s %u)", type, idx); 113 } 114 115 #define PRT_STR_OPT_BOUNDSCHECKED(name, type) \ 116 void bch2_prt_##name(struct printbuf *out, type t) \ 117 { \ 118 prt_str_opt_boundscheck(out, __bch2_##name##s, ARRAY_SIZE(__bch2_##name##s) - 1, #name, t);\ 119 } 120 121 PRT_STR_OPT_BOUNDSCHECKED(jset_entry_type, enum bch_jset_entry_type); 122 PRT_STR_OPT_BOUNDSCHECKED(fs_usage_type, enum bch_fs_usage_type); 123 PRT_STR_OPT_BOUNDSCHECKED(data_type, enum bch_data_type); 124 PRT_STR_OPT_BOUNDSCHECKED(csum_opt, enum bch_csum_opt); 125 PRT_STR_OPT_BOUNDSCHECKED(csum_type, enum bch_csum_type); 126 PRT_STR_OPT_BOUNDSCHECKED(compression_type, enum bch_compression_type); 127 PRT_STR_OPT_BOUNDSCHECKED(str_hash_type, enum bch_str_hash_type); 128 129 static int bch2_opt_fix_errors_parse(struct bch_fs *c, const char *val, u64 *res, 130 struct printbuf *err) 131 { 132 if (!val) { 133 *res = FSCK_FIX_yes; 134 } else { 135 int ret = match_string(bch2_fsck_fix_opts, -1, val); 136 137 if (ret < 0 && err) 138 prt_str(err, "fix_errors: invalid selection"); 139 if (ret < 0) 140 return ret; 141 *res = ret; 142 } 143 144 return 0; 145 } 146 147 static void bch2_opt_fix_errors_to_text(struct printbuf *out, 148 struct bch_fs *c, 149 struct bch_sb *sb, 150 u64 v) 151 { 152 prt_str(out, bch2_fsck_fix_opts[v]); 153 } 154 155 #define bch2_opt_fix_errors (struct bch_opt_fn) { \ 156 .parse = bch2_opt_fix_errors_parse, \ 157 .to_text = bch2_opt_fix_errors_to_text, \ 158 } 159 160 const char * const bch2_d_types[BCH_DT_MAX] = { 161 [DT_UNKNOWN] = "unknown", 162 [DT_FIFO] = "fifo", 163 [DT_CHR] = "chr", 164 [DT_DIR] = "dir", 165 [DT_BLK] = "blk", 166 [DT_REG] = "reg", 167 [DT_LNK] = "lnk", 168 [DT_SOCK] = "sock", 169 [DT_WHT] = "whiteout", 170 [DT_SUBVOL] = "subvol", 171 }; 172 173 void bch2_opts_apply(struct bch_opts *dst, struct bch_opts src) 174 { 175 #define x(_name, ...) \ 176 if (opt_defined(src, _name)) \ 177 opt_set(*dst, _name, src._name); 178 179 BCH_OPTS() 180 #undef x 181 } 182 183 bool bch2_opt_defined_by_id(const struct bch_opts *opts, enum bch_opt_id id) 184 { 185 switch (id) { 186 #define x(_name, ...) \ 187 case Opt_##_name: \ 188 return opt_defined(*opts, _name); 189 BCH_OPTS() 190 #undef x 191 default: 192 BUG(); 193 } 194 } 195 196 u64 bch2_opt_get_by_id(const struct bch_opts *opts, enum bch_opt_id id) 197 { 198 switch (id) { 199 #define x(_name, ...) \ 200 case Opt_##_name: \ 201 return opts->_name; 202 BCH_OPTS() 203 #undef x 204 default: 205 BUG(); 206 } 207 } 208 209 void bch2_opt_set_by_id(struct bch_opts *opts, enum bch_opt_id id, u64 v) 210 { 211 switch (id) { 212 #define x(_name, ...) \ 213 case Opt_##_name: \ 214 opt_set(*opts, _name, v); \ 215 break; 216 BCH_OPTS() 217 #undef x 218 default: 219 BUG(); 220 } 221 } 222 223 /* dummy option, for options that aren't stored in the superblock */ 224 typedef u64 (*sb_opt_get_fn)(const struct bch_sb *); 225 typedef void (*sb_opt_set_fn)(struct bch_sb *, u64); 226 typedef u64 (*member_opt_get_fn)(const struct bch_member *); 227 typedef void (*member_opt_set_fn)(struct bch_member *, u64); 228 229 __maybe_unused static const sb_opt_get_fn BCH2_NO_SB_OPT = NULL; 230 __maybe_unused static const sb_opt_set_fn SET_BCH2_NO_SB_OPT = NULL; 231 __maybe_unused static const member_opt_get_fn BCH2_NO_MEMBER_OPT = NULL; 232 __maybe_unused static const member_opt_set_fn SET_BCH2_NO_MEMBER_OPT = NULL; 233 234 #define type_compatible_or_null(_p, _type) \ 235 __builtin_choose_expr( \ 236 __builtin_types_compatible_p(typeof(_p), typeof(_type)), _p, NULL) 237 238 const struct bch_option bch2_opt_table[] = { 239 #define OPT_BOOL() .type = BCH_OPT_BOOL, .min = 0, .max = 2 240 #define OPT_UINT(_min, _max) .type = BCH_OPT_UINT, \ 241 .min = _min, .max = _max 242 #define OPT_STR(_choices) .type = BCH_OPT_STR, \ 243 .min = 0, .max = ARRAY_SIZE(_choices) - 1, \ 244 .choices = _choices 245 #define OPT_STR_NOLIMIT(_choices) .type = BCH_OPT_STR, \ 246 .min = 0, .max = U64_MAX, \ 247 .choices = _choices 248 #define OPT_BITFIELD(_choices) .type = BCH_OPT_BITFIELD, \ 249 .choices = _choices 250 #define OPT_FN(_fn) .type = BCH_OPT_FN, .fn = _fn 251 252 #define x(_name, _bits, _flags, _type, _sb_opt, _default, _hint, _help) \ 253 [Opt_##_name] = { \ 254 .attr.name = #_name, \ 255 .attr.mode = (_flags) & OPT_RUNTIME ? 0644 : 0444, \ 256 .flags = _flags, \ 257 .hint = _hint, \ 258 .help = _help, \ 259 .get_sb = type_compatible_or_null(_sb_opt, *BCH2_NO_SB_OPT), \ 260 .set_sb = type_compatible_or_null(SET_##_sb_opt,*SET_BCH2_NO_SB_OPT), \ 261 .get_member = type_compatible_or_null(_sb_opt, *BCH2_NO_MEMBER_OPT), \ 262 .set_member = type_compatible_or_null(SET_##_sb_opt,*SET_BCH2_NO_MEMBER_OPT),\ 263 _type \ 264 }, 265 266 BCH_OPTS() 267 #undef x 268 }; 269 270 int bch2_opt_lookup(const char *name) 271 { 272 const struct bch_option *i; 273 274 for (i = bch2_opt_table; 275 i < bch2_opt_table + ARRAY_SIZE(bch2_opt_table); 276 i++) 277 if (!strcmp(name, i->attr.name)) 278 return i - bch2_opt_table; 279 280 return -1; 281 } 282 283 struct opt_synonym { 284 const char *s1, *s2; 285 }; 286 287 static const struct opt_synonym bch2_opt_synonyms[] = { 288 { "quota", "usrquota" }, 289 }; 290 291 static int bch2_mount_opt_lookup(const char *name) 292 { 293 const struct opt_synonym *i; 294 295 for (i = bch2_opt_synonyms; 296 i < bch2_opt_synonyms + ARRAY_SIZE(bch2_opt_synonyms); 297 i++) 298 if (!strcmp(name, i->s1)) 299 name = i->s2; 300 301 return bch2_opt_lookup(name); 302 } 303 304 struct opt_val_synonym { 305 const char *opt, *v1, *v2; 306 }; 307 308 static const struct opt_val_synonym bch2_opt_val_synonyms[] = { 309 { "degraded", "true", "yes" }, 310 { "degraded", "false", "no" }, 311 { "degraded", "1", "yes" }, 312 { "degraded", "0", "no" }, 313 }; 314 315 static const char *bch2_opt_val_synonym_lookup(const char *opt, const char *val) 316 { 317 const struct opt_val_synonym *i; 318 319 for (i = bch2_opt_val_synonyms; 320 i < bch2_opt_val_synonyms + ARRAY_SIZE(bch2_opt_val_synonyms); 321 i++) 322 if (!strcmp(opt, i->opt) && !strcmp(val, i->v1)) 323 return i->v2; 324 325 return val; 326 } 327 328 int bch2_opt_validate(const struct bch_option *opt, u64 v, struct printbuf *err) 329 { 330 if (v < opt->min) { 331 if (err) 332 prt_printf(err, "%s: too small (min %llu)", 333 opt->attr.name, opt->min); 334 return -BCH_ERR_ERANGE_option_too_small; 335 } 336 337 if (opt->max && v >= opt->max) { 338 if (err) 339 prt_printf(err, "%s: too big (max %llu)", 340 opt->attr.name, opt->max); 341 return -BCH_ERR_ERANGE_option_too_big; 342 } 343 344 if ((opt->flags & OPT_SB_FIELD_SECTORS) && (v & 511)) { 345 if (err) 346 prt_printf(err, "%s: not a multiple of 512", 347 opt->attr.name); 348 return -BCH_ERR_opt_parse_error; 349 } 350 351 if ((opt->flags & OPT_MUST_BE_POW_2) && !is_power_of_2(v)) { 352 if (err) 353 prt_printf(err, "%s: must be a power of two", 354 opt->attr.name); 355 return -BCH_ERR_opt_parse_error; 356 } 357 358 if (opt->fn.validate) 359 return opt->fn.validate(v, err); 360 361 return 0; 362 } 363 364 int bch2_opt_parse(struct bch_fs *c, 365 const struct bch_option *opt, 366 const char *val, u64 *res, 367 struct printbuf *err) 368 { 369 ssize_t ret; 370 371 if (err) 372 printbuf_indent_add_nextline(err, 2); 373 374 switch (opt->type) { 375 case BCH_OPT_BOOL: 376 if (!val) 377 val = "1"; 378 379 ret = lookup_constant(bool_names, val, -BCH_ERR_option_not_bool); 380 if (ret != -BCH_ERR_option_not_bool) { 381 *res = ret; 382 } else { 383 if (err) 384 prt_printf(err, "%s: must be bool", opt->attr.name); 385 return ret; 386 } 387 break; 388 case BCH_OPT_UINT: 389 if (!val) { 390 prt_printf(err, "%s: required value", 391 opt->attr.name); 392 return -EINVAL; 393 } 394 395 if (*val != '-') { 396 ret = opt->flags & OPT_HUMAN_READABLE 397 ? bch2_strtou64_h(val, res) 398 : kstrtou64(val, 10, res); 399 } else { 400 prt_printf(err, "%s: must be a non-negative number", opt->attr.name); 401 return -BCH_ERR_option_negative; 402 } 403 404 if (ret < 0) { 405 if (err) 406 prt_printf(err, "%s: must be a number", 407 opt->attr.name); 408 return ret; 409 } 410 break; 411 case BCH_OPT_STR: 412 if (!val) { 413 prt_printf(err, "%s: required value", 414 opt->attr.name); 415 return -EINVAL; 416 } 417 418 ret = match_string(opt->choices, -1, val); 419 if (ret < 0) { 420 if (err) 421 prt_printf(err, "%s: invalid selection", 422 opt->attr.name); 423 return ret; 424 } 425 426 *res = ret; 427 break; 428 case BCH_OPT_BITFIELD: { 429 s64 v = bch2_read_flag_list(val, opt->choices); 430 if (v < 0) 431 return v; 432 *res = v; 433 break; 434 } 435 case BCH_OPT_FN: 436 ret = opt->fn.parse(c, val, res, err); 437 438 if (ret == -BCH_ERR_option_needs_open_fs) 439 return ret; 440 441 if (ret < 0) { 442 if (err) 443 prt_printf(err, "%s: parse error", 444 opt->attr.name); 445 return ret; 446 } 447 } 448 449 return bch2_opt_validate(opt, *res, err); 450 } 451 452 void bch2_opt_to_text(struct printbuf *out, 453 struct bch_fs *c, struct bch_sb *sb, 454 const struct bch_option *opt, u64 v, 455 unsigned flags) 456 { 457 if (flags & OPT_SHOW_MOUNT_STYLE) { 458 if (opt->type == BCH_OPT_BOOL) { 459 prt_printf(out, "%s%s", 460 v ? "" : "no", 461 opt->attr.name); 462 return; 463 } 464 465 prt_printf(out, "%s=", opt->attr.name); 466 } 467 468 switch (opt->type) { 469 case BCH_OPT_BOOL: 470 case BCH_OPT_UINT: 471 if (opt->flags & OPT_HUMAN_READABLE) 472 prt_human_readable_u64(out, v); 473 else 474 prt_printf(out, "%lli", v); 475 break; 476 case BCH_OPT_STR: 477 if (v < opt->min || v >= opt->max) 478 prt_printf(out, "(invalid option %lli)", v); 479 else if (flags & OPT_SHOW_FULL_LIST) 480 prt_string_option(out, opt->choices, v); 481 else 482 prt_str(out, opt->choices[v]); 483 break; 484 case BCH_OPT_BITFIELD: 485 prt_bitflags(out, opt->choices, v); 486 break; 487 case BCH_OPT_FN: 488 opt->fn.to_text(out, c, sb, v); 489 break; 490 default: 491 BUG(); 492 } 493 } 494 495 void bch2_opts_to_text(struct printbuf *out, 496 struct bch_opts opts, 497 struct bch_fs *c, struct bch_sb *sb, 498 unsigned show_mask, unsigned hide_mask, 499 unsigned flags) 500 { 501 bool first = true; 502 503 for (enum bch_opt_id i = 0; i < bch2_opts_nr; i++) { 504 const struct bch_option *opt = &bch2_opt_table[i]; 505 506 if ((opt->flags & hide_mask) || !(opt->flags & show_mask)) 507 continue; 508 509 u64 v = bch2_opt_get_by_id(&opts, i); 510 if (v == bch2_opt_get_by_id(&bch2_opts_default, i)) 511 continue; 512 513 if (!first) 514 prt_char(out, ','); 515 first = false; 516 517 bch2_opt_to_text(out, c, sb, opt, v, flags); 518 } 519 } 520 521 int bch2_opt_hook_pre_set(struct bch_fs *c, struct bch_dev *ca, enum bch_opt_id id, u64 v) 522 { 523 int ret = 0; 524 525 switch (id) { 526 case Opt_state: 527 if (ca) 528 return bch2_dev_set_state(c, ca, v, BCH_FORCE_IF_DEGRADED); 529 break; 530 531 case Opt_compression: 532 case Opt_background_compression: 533 ret = bch2_check_set_has_compressed_data(c, v); 534 break; 535 case Opt_erasure_code: 536 if (v) 537 bch2_check_set_feature(c, BCH_FEATURE_ec); 538 break; 539 default: 540 break; 541 } 542 543 return ret; 544 } 545 546 int bch2_opts_hooks_pre_set(struct bch_fs *c) 547 { 548 for (unsigned i = 0; i < bch2_opts_nr; i++) { 549 int ret = bch2_opt_hook_pre_set(c, NULL, i, bch2_opt_get_by_id(&c->opts, i)); 550 if (ret) 551 return ret; 552 } 553 554 return 0; 555 } 556 557 void bch2_opt_hook_post_set(struct bch_fs *c, struct bch_dev *ca, u64 inum, 558 struct bch_opts *new_opts, enum bch_opt_id id) 559 { 560 switch (id) { 561 case Opt_foreground_target: 562 if (new_opts->foreground_target && 563 !new_opts->background_target) 564 bch2_set_rebalance_needs_scan(c, inum); 565 break; 566 case Opt_compression: 567 if (new_opts->compression && 568 !new_opts->background_compression) 569 bch2_set_rebalance_needs_scan(c, inum); 570 break; 571 case Opt_background_target: 572 if (new_opts->background_target) 573 bch2_set_rebalance_needs_scan(c, inum); 574 break; 575 case Opt_background_compression: 576 if (new_opts->background_compression) 577 bch2_set_rebalance_needs_scan(c, inum); 578 break; 579 case Opt_rebalance_enabled: 580 bch2_rebalance_wakeup(c); 581 break; 582 case Opt_copygc_enabled: 583 bch2_copygc_wakeup(c); 584 break; 585 case Opt_discard: 586 if (!ca) { 587 mutex_lock(&c->sb_lock); 588 for_each_member_device(c, ca) { 589 struct bch_member *m = 590 bch2_members_v2_get_mut(ca->disk_sb.sb, ca->dev_idx); 591 SET_BCH_MEMBER_DISCARD(m, c->opts.discard); 592 } 593 594 bch2_write_super(c); 595 mutex_unlock(&c->sb_lock); 596 } 597 break; 598 case Opt_version_upgrade: 599 /* 600 * XXX: in the future we'll likely want to do compatible 601 * upgrades at runtime as well, but right now there's nothing 602 * that does that: 603 */ 604 if (new_opts->version_upgrade == BCH_VERSION_UPGRADE_incompatible) 605 bch2_sb_upgrade_incompat(c); 606 break; 607 default: 608 break; 609 } 610 } 611 612 int bch2_parse_one_mount_opt(struct bch_fs *c, struct bch_opts *opts, 613 struct printbuf *parse_later, 614 const char *name, const char *val) 615 { 616 struct printbuf err = PRINTBUF; 617 u64 v; 618 int ret, id; 619 620 id = bch2_mount_opt_lookup(name); 621 622 /* Check for the form "noopt", negation of a boolean opt: */ 623 if (id < 0 && 624 !val && 625 !strncmp("no", name, 2)) { 626 id = bch2_mount_opt_lookup(name + 2); 627 val = "0"; 628 } 629 630 /* Unknown options are ignored: */ 631 if (id < 0) 632 return 0; 633 634 /* must have a value for synonym lookup - but OPT_FN is weird */ 635 if (!val && bch2_opt_table[id].type != BCH_OPT_FN) 636 val = "1"; 637 638 val = bch2_opt_val_synonym_lookup(name, val); 639 640 if (!(bch2_opt_table[id].flags & OPT_MOUNT)) 641 goto bad_opt; 642 643 if (id == Opt_acl && 644 !IS_ENABLED(CONFIG_BCACHEFS_POSIX_ACL)) 645 goto bad_opt; 646 647 if ((id == Opt_usrquota || 648 id == Opt_grpquota) && 649 !IS_ENABLED(CONFIG_BCACHEFS_QUOTA)) 650 goto bad_opt; 651 652 ret = bch2_opt_parse(c, &bch2_opt_table[id], val, &v, &err); 653 if (ret == -BCH_ERR_option_needs_open_fs) { 654 ret = 0; 655 656 if (parse_later) { 657 prt_printf(parse_later, "%s=%s,", name, val); 658 if (parse_later->allocation_failure) 659 ret = -ENOMEM; 660 } 661 662 goto out; 663 } 664 665 if (ret < 0) 666 goto bad_val; 667 668 if (opts) 669 bch2_opt_set_by_id(opts, id, v); 670 671 ret = 0; 672 out: 673 printbuf_exit(&err); 674 return ret; 675 bad_opt: 676 ret = -BCH_ERR_option_name; 677 goto out; 678 bad_val: 679 ret = -BCH_ERR_option_value; 680 goto out; 681 } 682 683 int bch2_parse_mount_opts(struct bch_fs *c, struct bch_opts *opts, 684 struct printbuf *parse_later, char *options, 685 bool ignore_unknown) 686 { 687 char *copied_opts, *copied_opts_start; 688 char *opt, *name, *val; 689 int ret = 0; 690 691 if (!options) 692 return 0; 693 694 /* 695 * sys_fsconfig() is now occasionally providing us with option lists 696 * starting with a comma - weird. 697 */ 698 if (*options == ',') 699 options++; 700 701 copied_opts = kstrdup(options, GFP_KERNEL); 702 if (!copied_opts) 703 return -ENOMEM; 704 copied_opts_start = copied_opts; 705 706 while ((opt = strsep(&copied_opts, ",")) != NULL) { 707 if (!*opt) 708 continue; 709 710 name = strsep(&opt, "="); 711 val = opt; 712 713 ret = bch2_parse_one_mount_opt(c, opts, parse_later, name, val); 714 if (ret == -BCH_ERR_option_name && ignore_unknown) 715 ret = 0; 716 if (ret) { 717 pr_err("Error parsing option %s: %s", name, bch2_err_str(ret)); 718 break; 719 } 720 } 721 722 kfree(copied_opts_start); 723 return ret; 724 } 725 726 u64 bch2_opt_from_sb(struct bch_sb *sb, enum bch_opt_id id, int dev_idx) 727 { 728 const struct bch_option *opt = bch2_opt_table + id; 729 u64 v; 730 731 if (dev_idx < 0) { 732 v = opt->get_sb(sb); 733 } else { 734 if (WARN(!bch2_member_exists(sb, dev_idx), 735 "tried to set device option %s on nonexistent device %i", 736 opt->attr.name, dev_idx)) 737 return 0; 738 739 struct bch_member m = bch2_sb_member_get(sb, dev_idx); 740 v = opt->get_member(&m); 741 } 742 743 if (opt->flags & OPT_SB_FIELD_ONE_BIAS) 744 --v; 745 746 if (opt->flags & OPT_SB_FIELD_ILOG2) 747 v = 1ULL << v; 748 749 if (opt->flags & OPT_SB_FIELD_SECTORS) 750 v <<= 9; 751 752 return v; 753 } 754 755 /* 756 * Initial options from superblock - here we don't want any options undefined, 757 * any options the superblock doesn't specify are set to 0: 758 */ 759 int bch2_opts_from_sb(struct bch_opts *opts, struct bch_sb *sb) 760 { 761 for (unsigned id = 0; id < bch2_opts_nr; id++) { 762 const struct bch_option *opt = bch2_opt_table + id; 763 764 if (opt->get_sb) 765 bch2_opt_set_by_id(opts, id, bch2_opt_from_sb(sb, id, -1)); 766 } 767 768 return 0; 769 } 770 771 bool __bch2_opt_set_sb(struct bch_sb *sb, int dev_idx, 772 const struct bch_option *opt, u64 v) 773 { 774 bool changed = false; 775 776 if (opt->flags & OPT_SB_FIELD_SECTORS) 777 v >>= 9; 778 779 if (opt->flags & OPT_SB_FIELD_ILOG2) 780 v = ilog2(v); 781 782 if (opt->flags & OPT_SB_FIELD_ONE_BIAS) 783 v++; 784 785 if ((opt->flags & OPT_FS) && opt->set_sb && dev_idx < 0) { 786 changed = v != opt->get_sb(sb); 787 788 opt->set_sb(sb, v); 789 } 790 791 if ((opt->flags & OPT_DEVICE) && opt->set_member && dev_idx >= 0) { 792 if (WARN(!bch2_member_exists(sb, dev_idx), 793 "tried to set device option %s on nonexistent device %i", 794 opt->attr.name, dev_idx)) 795 return false; 796 797 struct bch_member *m = bch2_members_v2_get_mut(sb, dev_idx); 798 changed = v != opt->get_member(m); 799 opt->set_member(m, v); 800 } 801 802 return changed; 803 } 804 805 bool bch2_opt_set_sb(struct bch_fs *c, struct bch_dev *ca, 806 const struct bch_option *opt, u64 v) 807 { 808 mutex_lock(&c->sb_lock); 809 bool changed = __bch2_opt_set_sb(c->disk_sb.sb, ca ? ca->dev_idx : -1, opt, v); 810 if (changed) 811 bch2_write_super(c); 812 mutex_unlock(&c->sb_lock); 813 return changed; 814 } 815 816 /* io opts: */ 817 818 struct bch_io_opts bch2_opts_to_inode_opts(struct bch_opts src) 819 { 820 struct bch_io_opts opts = { 821 #define x(_name, _bits) ._name = src._name, 822 BCH_INODE_OPTS() 823 #undef x 824 }; 825 826 bch2_io_opts_fixups(&opts); 827 return opts; 828 } 829 830 bool bch2_opt_is_inode_opt(enum bch_opt_id id) 831 { 832 static const enum bch_opt_id inode_opt_list[] = { 833 #define x(_name, _bits) Opt_##_name, 834 BCH_INODE_OPTS() 835 #undef x 836 }; 837 unsigned i; 838 839 for (i = 0; i < ARRAY_SIZE(inode_opt_list); i++) 840 if (inode_opt_list[i] == id) 841 return true; 842 843 return false; 844 } 845