]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bcachefs: Improve opts.degraded
authorKent Overstreet <kent.overstreet@linux.dev>
Sun, 6 Apr 2025 17:50:20 +0000 (13:50 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Thu, 22 May 2025 00:14:12 +0000 (20:14 -0400)
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>
fs/bcachefs/bcachefs_format.h
fs/bcachefs/opts.c
fs/bcachefs/opts.h
fs/bcachefs/super-io.c
fs/bcachefs/super.c

index d6e4a496f02b64a950b6de4188faa98691fb25c6..6cbc267445b7ba22b2de44273acc06e05c99d907 100644 (file)
@@ -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)      \
index ed2e2850c1d1b9469af761ff1141defb55d19623..b3fcffc91d6fa92b62b1d702007a68b7ee2114d5 100644 (file)
@@ -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;
-                       }
+               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 {
-                       *res = 1;
+                       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;
 
index dfb14810124c7c3e94c55288259816b6e5b35100..cbb13e91789df29e8804be4a5808de33767287e8 100644 (file)
@@ -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(),                                                   \
index cb5d960aed92a6d3d25e745b3a7de0401b34a783..adfcd8a92b9305cd73037d7bc4909628101f61e0 100644 (file)
@@ -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);
index 834ba091e84f65963ad75ba487a34cec24572066..027e10766185e97a1e847558f184b2b4df3051b3 100644 (file)
@@ -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);