bcachefs: fix_errors option is now a proper enum
Before, it was parsed as a bool but internally it was really an enum: this lets us pass in all the possible values. But we special case the option parsing: no supplied value is parsed as FSCK_FIX_yes, to match the previous behaviour. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
9f343e24f5
commit
a0f8faea5f
@ -1808,7 +1808,7 @@ again:
|
||||
if (IS_ENABLED(CONFIG_BCACHEFS_DEBUG) ||
|
||||
(BCH_SB_HAS_TOPOLOGY_ERRORS(c->disk_sb.sb) &&
|
||||
c->curr_recovery_pass <= BCH_RECOVERY_PASS_check_allocations &&
|
||||
c->opts.fix_errors != FSCK_OPT_NO)) {
|
||||
c->opts.fix_errors != FSCK_FIX_no)) {
|
||||
bch_info(c, "Starting topology repair pass");
|
||||
ret = bch2_repair_topology(c);
|
||||
if (ret)
|
||||
|
@ -204,7 +204,7 @@ int bch2_fsck_err(struct bch_fs *c, unsigned flags, const char *fmt, ...)
|
||||
prt_str(out, ", continuing");
|
||||
ret = -BCH_ERR_fsck_ignore;
|
||||
}
|
||||
} else if (c->opts.fix_errors == FSCK_OPT_EXIT) {
|
||||
} else if (c->opts.fix_errors == FSCK_FIX_exit) {
|
||||
prt_str(out, ", exiting");
|
||||
ret = -BCH_ERR_fsck_errors_not_fixed;
|
||||
} else if (flags & FSCK_CAN_FIX) {
|
||||
@ -212,7 +212,7 @@ int bch2_fsck_err(struct bch_fs *c, unsigned flags, const char *fmt, ...)
|
||||
? s->fix
|
||||
: c->opts.fix_errors;
|
||||
|
||||
if (fix == FSCK_OPT_ASK) {
|
||||
if (fix == FSCK_FIX_ask) {
|
||||
int ask;
|
||||
|
||||
prt_str(out, ": fix?");
|
||||
@ -223,13 +223,13 @@ int bch2_fsck_err(struct bch_fs *c, unsigned flags, const char *fmt, ...)
|
||||
|
||||
if (ask >= YN_ALLNO && s)
|
||||
s->fix = ask == YN_ALLNO
|
||||
? FSCK_OPT_NO
|
||||
: FSCK_OPT_YES;
|
||||
? FSCK_FIX_no
|
||||
: FSCK_FIX_yes;
|
||||
|
||||
ret = ask & 1
|
||||
? -BCH_ERR_fsck_fix
|
||||
: -BCH_ERR_fsck_ignore;
|
||||
} else if (fix == FSCK_OPT_YES ||
|
||||
} else if (fix == FSCK_FIX_yes ||
|
||||
(c->opts.nochanges &&
|
||||
!(flags & FSCK_CAN_IGNORE))) {
|
||||
prt_str(out, ", fixing");
|
||||
@ -244,7 +244,7 @@ int bch2_fsck_err(struct bch_fs *c, unsigned flags, const char *fmt, ...)
|
||||
}
|
||||
|
||||
if (ret == -BCH_ERR_fsck_ignore &&
|
||||
(c->opts.fix_errors == FSCK_OPT_EXIT ||
|
||||
(c->opts.fix_errors == FSCK_FIX_exit ||
|
||||
!(flags & FSCK_CAN_IGNORE)))
|
||||
ret = -BCH_ERR_fsck_errors_not_fixed;
|
||||
|
||||
|
@ -91,13 +91,6 @@ do { \
|
||||
* be able to repair:
|
||||
*/
|
||||
|
||||
enum fsck_err_opts {
|
||||
FSCK_OPT_EXIT,
|
||||
FSCK_OPT_YES,
|
||||
FSCK_OPT_NO,
|
||||
FSCK_OPT_ASK,
|
||||
};
|
||||
|
||||
struct fsck_err_state {
|
||||
struct list_head list;
|
||||
const char *fmt;
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "bcachefs.h"
|
||||
#include "compress.h"
|
||||
#include "disk_groups.h"
|
||||
#include "error.h"
|
||||
#include "opts.h"
|
||||
#include "super-io.h"
|
||||
#include "util.h"
|
||||
@ -16,6 +17,11 @@ const char * const bch2_error_actions[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
const char * const bch2_fsck_fix_opts[] = {
|
||||
BCH_FIX_ERRORS_OPTS()
|
||||
NULL
|
||||
};
|
||||
|
||||
const char * const bch2_version_upgrade_opts[] = {
|
||||
BCH_VERSION_UPGRADE_OPTS()
|
||||
NULL
|
||||
@ -89,6 +95,37 @@ const char * const bch2_fs_usage_types[] = {
|
||||
|
||||
#undef x
|
||||
|
||||
static int bch2_opt_fix_errors_parse(struct bch_fs *c, const char *val, u64 *res,
|
||||
struct printbuf *err)
|
||||
{
|
||||
if (!val) {
|
||||
*res = FSCK_FIX_yes;
|
||||
} else {
|
||||
int ret = match_string(bch2_fsck_fix_opts, -1, val);
|
||||
|
||||
if (ret < 0 && err)
|
||||
prt_str(err, "fix_errors: invalid selection");
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*res = ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bch2_opt_fix_errors_to_text(struct printbuf *out,
|
||||
struct bch_fs *c,
|
||||
struct bch_sb *sb,
|
||||
u64 v)
|
||||
{
|
||||
prt_str(out, bch2_fsck_fix_opts[v]);
|
||||
}
|
||||
|
||||
static const struct bch_opt_fn bch2_opt_fix_errors = {
|
||||
.parse = bch2_opt_fix_errors_parse,
|
||||
.to_text = bch2_opt_fix_errors_to_text,
|
||||
};
|
||||
|
||||
const char * const bch2_d_types[BCH_DT_MAX] = {
|
||||
[DT_UNKNOWN] = "unknown",
|
||||
[DT_FIFO] = "fifo",
|
||||
@ -265,15 +302,26 @@ int bch2_opt_parse(struct bch_fs *c,
|
||||
|
||||
switch (opt->type) {
|
||||
case BCH_OPT_BOOL:
|
||||
ret = kstrtou64(val, 10, res);
|
||||
if (val) {
|
||||
ret = kstrtou64(val, 10, res);
|
||||
} else {
|
||||
ret = 0;
|
||||
*res = 1;
|
||||
}
|
||||
|
||||
if (ret < 0 || (*res != 0 && *res != 1)) {
|
||||
if (err)
|
||||
prt_printf(err, "%s: must be bool",
|
||||
opt->attr.name);
|
||||
prt_printf(err, "%s: must be bool", opt->attr.name);
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
case BCH_OPT_UINT:
|
||||
if (!val) {
|
||||
prt_printf(err, "%s: required value",
|
||||
opt->attr.name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = opt->flags & OPT_HUMAN_READABLE
|
||||
? bch2_strtou64_h(val, res)
|
||||
: kstrtou64(val, 10, res);
|
||||
@ -285,6 +333,12 @@ int bch2_opt_parse(struct bch_fs *c,
|
||||
}
|
||||
break;
|
||||
case BCH_OPT_STR:
|
||||
if (!val) {
|
||||
prt_printf(err, "%s: required value",
|
||||
opt->attr.name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = match_string(opt->choices, -1, val);
|
||||
if (ret < 0) {
|
||||
if (err)
|
||||
@ -336,7 +390,7 @@ void bch2_opt_to_text(struct printbuf *out,
|
||||
if (flags & OPT_SHOW_FULL_LIST)
|
||||
prt_string_option(out, opt->choices, v);
|
||||
else
|
||||
prt_printf(out, "%s", opt->choices[v]);
|
||||
prt_str(out, opt->choices[v]);
|
||||
break;
|
||||
case BCH_OPT_FN:
|
||||
opt->fn.to_text(out, c, sb, v);
|
||||
@ -400,31 +454,19 @@ int bch2_parse_mount_opts(struct bch_fs *c, struct bch_opts *opts,
|
||||
name = strsep(&opt, "=");
|
||||
val = opt;
|
||||
|
||||
if (val) {
|
||||
id = bch2_mount_opt_lookup(name);
|
||||
if (id < 0)
|
||||
goto bad_opt;
|
||||
id = bch2_mount_opt_lookup(name);
|
||||
|
||||
ret = bch2_opt_parse(c, &bch2_opt_table[id], val, &v, &err);
|
||||
if (ret < 0)
|
||||
goto bad_val;
|
||||
} else {
|
||||
id = bch2_mount_opt_lookup(name);
|
||||
v = 1;
|
||||
|
||||
if (id < 0 &&
|
||||
!strncmp("no", name, 2)) {
|
||||
id = bch2_mount_opt_lookup(name + 2);
|
||||
v = 0;
|
||||
}
|
||||
|
||||
if (id < 0)
|
||||
goto bad_opt;
|
||||
|
||||
if (bch2_opt_table[id].type != BCH_OPT_BOOL)
|
||||
goto no_val;
|
||||
/* Check for the form "noopt", negation of a boolean opt: */
|
||||
if (id < 0 &&
|
||||
!val &&
|
||||
!strncmp("no", name, 2)) {
|
||||
id = bch2_mount_opt_lookup(name + 2);
|
||||
val = "0";
|
||||
}
|
||||
|
||||
if (id < 0)
|
||||
goto bad_opt;
|
||||
|
||||
if (!(bch2_opt_table[id].flags & OPT_MOUNT))
|
||||
goto bad_opt;
|
||||
|
||||
@ -437,6 +479,10 @@ int bch2_parse_mount_opts(struct bch_fs *c, struct bch_opts *opts,
|
||||
!IS_ENABLED(CONFIG_BCACHEFS_QUOTA))
|
||||
goto bad_opt;
|
||||
|
||||
ret = bch2_opt_parse(c, &bch2_opt_table[id], val, &v, &err);
|
||||
if (ret < 0)
|
||||
goto bad_val;
|
||||
|
||||
bch2_opt_set_by_id(opts, id, v);
|
||||
}
|
||||
|
||||
@ -451,10 +497,6 @@ bad_val:
|
||||
pr_err("Invalid mount option %s", err.buf);
|
||||
ret = -1;
|
||||
goto out;
|
||||
no_val:
|
||||
pr_err("Mount option %s requires a value", name);
|
||||
ret = -1;
|
||||
goto out;
|
||||
out:
|
||||
kfree(copied_opts_start);
|
||||
printbuf_exit(&err);
|
||||
|
@ -11,6 +11,7 @@
|
||||
struct bch_fs;
|
||||
|
||||
extern const char * const bch2_error_actions[];
|
||||
extern const char * const bch2_fsck_fix_opts[];
|
||||
extern const char * const bch2_version_upgrade_opts[];
|
||||
extern const char * const bch2_sb_features[];
|
||||
extern const char * const bch2_sb_compat[];
|
||||
@ -105,6 +106,18 @@ struct bch_opt_fn {
|
||||
#define BCACHEFS_VERBOSE_DEFAULT false
|
||||
#endif
|
||||
|
||||
#define BCH_FIX_ERRORS_OPTS() \
|
||||
x(exit, 0) \
|
||||
x(yes, 1) \
|
||||
x(no, 2) \
|
||||
x(ask, 3)
|
||||
|
||||
enum fsck_err_opts {
|
||||
#define x(t, n) FSCK_FIX_##t,
|
||||
BCH_FIX_ERRORS_OPTS()
|
||||
#undef x
|
||||
};
|
||||
|
||||
#define BCH_OPTS() \
|
||||
x(block_size, u16, \
|
||||
OPT_FS|OPT_FORMAT| \
|
||||
@ -325,8 +338,8 @@ struct bch_opt_fn {
|
||||
NULL, "Run fsck on mount") \
|
||||
x(fix_errors, u8, \
|
||||
OPT_FS|OPT_MOUNT, \
|
||||
OPT_BOOL(), \
|
||||
BCH2_NO_SB_OPT, false, \
|
||||
OPT_FN(bch2_opt_fix_errors), \
|
||||
BCH2_NO_SB_OPT, FSCK_FIX_exit, \
|
||||
NULL, "Fix errors during fsck without asking") \
|
||||
x(ratelimit_errors, u8, \
|
||||
OPT_FS|OPT_MOUNT, \
|
||||
|
@ -1175,7 +1175,7 @@ static void check_version_upgrade(struct bch_fs *c)
|
||||
prt_str(&buf, "fsck required");
|
||||
|
||||
c->recovery_passes_explicit |= recovery_passes;
|
||||
c->opts.fix_errors = FSCK_OPT_YES;
|
||||
c->opts.fix_errors = FSCK_FIX_yes;
|
||||
}
|
||||
|
||||
bch_info(c, "%s", buf.buf);
|
||||
|
Loading…
Reference in New Issue
Block a user