mirror of
https://github.com/torvalds/linux.git
synced 2026-07-31 19:47:08 +02:00
bcachefs: Improve opts.degraded
Kill 'opts.very_degraded', and make 'opts.degraded' a persistent option, stored in the superblock. It's now an enum, with available choices ask/yes/very/no. "ask" mode will be handled by the mount helper, for prompting the user (on a machine used interactively) for whether to do a degraded mount. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
2758c28aca
commit
ef8dd631f7
|
|
@ -867,6 +867,7 @@ LE64_BITMASK(BCH_SB_VERSION_INCOMPAT_ALLOWED,
|
|||
LE64_BITMASK(BCH_SB_SHARD_INUMS_NBITS, struct bch_sb, flags[6], 0, 4);
|
||||
LE64_BITMASK(BCH_SB_WRITE_ERROR_TIMEOUT,struct bch_sb, flags[6], 4, 14);
|
||||
LE64_BITMASK(BCH_SB_CSUM_ERR_RETRY_NR, struct bch_sb, flags[6], 14, 20);
|
||||
LE64_BITMASK(BCH_SB_DEGRADED_ACTION, struct bch_sb, flags[6], 20, 22);
|
||||
LE64_BITMASK(BCH_SB_CASEFOLD, struct bch_sb, flags[6], 22, 23);
|
||||
|
||||
static inline __u64 BCH_SB_COMPRESSION_TYPE(const struct bch_sb *sb)
|
||||
|
|
@ -989,6 +990,19 @@ enum bch_error_actions {
|
|||
BCH_ON_ERROR_NR
|
||||
};
|
||||
|
||||
#define BCH_DEGRADED_ACTIONS() \
|
||||
x(ask, 0) \
|
||||
x(yes, 1) \
|
||||
x(very, 2) \
|
||||
x(no, 3)
|
||||
|
||||
enum bch_degraded_actions {
|
||||
#define x(t, n) BCH_DEGRADED_##t = n,
|
||||
BCH_DEGRADED_ACTIONS()
|
||||
#undef x
|
||||
BCH_DEGRADED_ACTIONS_NR
|
||||
};
|
||||
|
||||
#define BCH_STR_HASH_TYPES() \
|
||||
x(crc32c, 0) \
|
||||
x(crc64, 1) \
|
||||
|
|
|
|||
|
|
@ -19,6 +19,11 @@ const char * const bch2_error_actions[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
const char * const bch2_degraded_actions[] = {
|
||||
BCH_DEGRADED_ACTIONS()
|
||||
NULL
|
||||
};
|
||||
|
||||
const char * const bch2_fsck_fix_opts[] = {
|
||||
BCH_FIX_ERRORS_OPTS()
|
||||
NULL
|
||||
|
|
@ -273,20 +278,20 @@ int bch2_opt_lookup(const char *name)
|
|||
return -1;
|
||||
}
|
||||
|
||||
struct synonym {
|
||||
struct opt_synonym {
|
||||
const char *s1, *s2;
|
||||
};
|
||||
|
||||
static const struct synonym bch_opt_synonyms[] = {
|
||||
static const struct opt_synonym bch2_opt_synonyms[] = {
|
||||
{ "quota", "usrquota" },
|
||||
};
|
||||
|
||||
static int bch2_mount_opt_lookup(const char *name)
|
||||
{
|
||||
const struct synonym *i;
|
||||
const struct opt_synonym *i;
|
||||
|
||||
for (i = bch_opt_synonyms;
|
||||
i < bch_opt_synonyms + ARRAY_SIZE(bch_opt_synonyms);
|
||||
for (i = bch2_opt_synonyms;
|
||||
i < bch2_opt_synonyms + ARRAY_SIZE(bch2_opt_synonyms);
|
||||
i++)
|
||||
if (!strcmp(name, i->s1))
|
||||
name = i->s2;
|
||||
|
|
@ -294,6 +299,30 @@ static int bch2_mount_opt_lookup(const char *name)
|
|||
return bch2_opt_lookup(name);
|
||||
}
|
||||
|
||||
struct opt_val_synonym {
|
||||
const char *opt, *v1, *v2;
|
||||
};
|
||||
|
||||
static const struct opt_val_synonym bch2_opt_val_synonyms[] = {
|
||||
{ "degraded", "true", "yes" },
|
||||
{ "degraded", "false", "no" },
|
||||
{ "degraded", "1", "yes" },
|
||||
{ "degraded", "0", "no" },
|
||||
};
|
||||
|
||||
static const char *bch2_opt_val_synonym_lookup(const char *opt, const char *val)
|
||||
{
|
||||
const struct opt_val_synonym *i;
|
||||
|
||||
for (i = bch2_opt_val_synonyms;
|
||||
i < bch2_opt_val_synonyms + ARRAY_SIZE(bch2_opt_val_synonyms);
|
||||
i++)
|
||||
if (!strcmp(opt, i->opt) && !strcmp(val, i->v1))
|
||||
return i->v2;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
int bch2_opt_validate(const struct bch_option *opt, u64 v, struct printbuf *err)
|
||||
{
|
||||
if (v < opt->min) {
|
||||
|
|
@ -342,19 +371,17 @@ int bch2_opt_parse(struct bch_fs *c,
|
|||
|
||||
switch (opt->type) {
|
||||
case BCH_OPT_BOOL:
|
||||
if (val) {
|
||||
ret = lookup_constant(bool_names, val, -BCH_ERR_option_not_bool);
|
||||
if (ret != -BCH_ERR_option_not_bool) {
|
||||
*res = ret;
|
||||
} else {
|
||||
if (err)
|
||||
prt_printf(err, "%s: must be bool", opt->attr.name);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
*res = 1;
|
||||
}
|
||||
if (!val)
|
||||
val = "1";
|
||||
|
||||
ret = lookup_constant(bool_names, val, -BCH_ERR_option_not_bool);
|
||||
if (ret != -BCH_ERR_option_not_bool) {
|
||||
*res = ret;
|
||||
} else {
|
||||
if (err)
|
||||
prt_printf(err, "%s: must be bool", opt->attr.name);
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
case BCH_OPT_UINT:
|
||||
if (!val) {
|
||||
|
|
@ -545,6 +572,12 @@ int bch2_parse_one_mount_opt(struct bch_fs *c, struct bch_opts *opts,
|
|||
if (id < 0)
|
||||
return 0;
|
||||
|
||||
/* must have a value for synonym lookup - but OPT_FN is weird */
|
||||
if (!val && bch2_opt_table[id].type != BCH_OPT_FN)
|
||||
val = "1";
|
||||
|
||||
val = bch2_opt_val_synonym_lookup(name, val);
|
||||
|
||||
if (!(bch2_opt_table[id].flags & OPT_MOUNT))
|
||||
goto bad_opt;
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
struct bch_fs;
|
||||
|
||||
extern const char * const bch2_error_actions[];
|
||||
extern const char * const bch2_degraded_actions[];
|
||||
extern const char * const bch2_fsck_fix_opts[];
|
||||
extern const char * const bch2_version_upgrade_opts[];
|
||||
extern const char * const bch2_sb_features[];
|
||||
|
|
@ -307,14 +308,9 @@ enum fsck_err_opts {
|
|||
NULL, "Enable project quotas") \
|
||||
x(degraded, u8, \
|
||||
OPT_FS|OPT_MOUNT, \
|
||||
OPT_BOOL(), \
|
||||
BCH2_NO_SB_OPT, false, \
|
||||
OPT_STR(bch2_degraded_actions), \
|
||||
BCH_SB_DEGRADED_ACTION, BCH_DEGRADED_ask, \
|
||||
NULL, "Allow mounting in degraded mode") \
|
||||
x(very_degraded, u8, \
|
||||
OPT_FS|OPT_MOUNT, \
|
||||
OPT_BOOL(), \
|
||||
BCH2_NO_SB_OPT, false, \
|
||||
NULL, "Allow mounting in when data will be missing") \
|
||||
x(no_splitbrain_check, u8, \
|
||||
OPT_FS|OPT_MOUNT, \
|
||||
OPT_BOOL(), \
|
||||
|
|
|
|||
|
|
@ -1022,7 +1022,7 @@ int bch2_write_super(struct bch_fs *c)
|
|||
|
||||
trace_and_count(c, write_super, c, _RET_IP_);
|
||||
|
||||
if (c->opts.very_degraded)
|
||||
if (c->opts.degraded == BCH_DEGRADED_very)
|
||||
degraded_flags |= BCH_FORCE_IF_LOST;
|
||||
|
||||
lockdep_assert_held(&c->sb_lock);
|
||||
|
|
|
|||
|
|
@ -1040,19 +1040,18 @@ static void print_mount_opts(struct bch_fs *c)
|
|||
static bool bch2_fs_may_start(struct bch_fs *c)
|
||||
{
|
||||
struct bch_dev *ca;
|
||||
unsigned i, flags = 0;
|
||||
unsigned flags = 0;
|
||||
|
||||
if (c->opts.very_degraded)
|
||||
switch (c->opts.degraded) {
|
||||
case BCH_DEGRADED_very:
|
||||
flags |= BCH_FORCE_IF_DEGRADED|BCH_FORCE_IF_LOST;
|
||||
|
||||
if (c->opts.degraded)
|
||||
break;
|
||||
case BCH_DEGRADED_yes:
|
||||
flags |= BCH_FORCE_IF_DEGRADED;
|
||||
|
||||
if (!c->opts.degraded &&
|
||||
!c->opts.very_degraded) {
|
||||
break;
|
||||
default:
|
||||
mutex_lock(&c->sb_lock);
|
||||
|
||||
for (i = 0; i < c->disk_sb.sb->nr_devices; i++) {
|
||||
for (unsigned i = 0; i < c->disk_sb.sb->nr_devices; i++) {
|
||||
if (!bch2_member_exists(c->disk_sb.sb, i))
|
||||
continue;
|
||||
|
||||
|
|
@ -1066,6 +1065,7 @@ static bool bch2_fs_may_start(struct bch_fs *c)
|
|||
}
|
||||
}
|
||||
mutex_unlock(&c->sb_lock);
|
||||
break;
|
||||
}
|
||||
|
||||
return bch2_have_enough_devs(c, bch2_online_devs(c), flags, true);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user