bcachefs: Options for recovery_passes, recovery_passes_exclude
authorKent Overstreet <kent.overstreet@linux.dev>
Mon, 2 Sep 2024 02:39:42 +0000 (22:39 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sat, 21 Sep 2024 15:39:48 +0000 (11:39 -0400)
This adds mount options for specifying recovery passes to run, or
exclude; the immediate need for this is that backpointers fsck is having
trouble completing, so we need a way to skip it.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/bcachefs.h
fs/bcachefs/btree_io.c
fs/bcachefs/btree_update_interior.c
fs/bcachefs/opts.c
fs/bcachefs/opts.h
fs/bcachefs/recovery.c
fs/bcachefs/recovery_passes.c
fs/bcachefs/util.c

index ad4df0ad26eb957e4f1a02bd8123d98fa9f9c804..b2475b9555ac4e3f283a19693cfb0790a15bb4dd 100644 (file)
@@ -1045,8 +1045,6 @@ struct bch_fs {
         * for signaling to the toplevel code which pass we want to run now.
         */
        enum bch_recovery_pass  curr_recovery_pass;
-       /* bitmap of explicitly enabled recovery passes: */
-       u64                     recovery_passes_explicit;
        /* bitmask of recovery passes that we actually ran */
        u64                     recovery_passes_complete;
        /* never rewinds version of curr_recovery_pass */
index 56ea9a77cd4afdfb2c72e8878d60e068c291494a..18cff98650ded7ae327450d2790d3f51510cef59 100644 (file)
@@ -1666,7 +1666,7 @@ void bch2_btree_node_read(struct btree_trans *trans, struct btree *b,
                bch2_btree_pos_to_text(&buf, c, b);
                bch_err_ratelimited(c, "%s", buf.buf);
 
-               if (c->recovery_passes_explicit & BIT_ULL(BCH_RECOVERY_PASS_check_topology) &&
+               if (c->opts.recovery_passes & BIT_ULL(BCH_RECOVERY_PASS_check_topology) &&
                    c->curr_recovery_pass > BCH_RECOVERY_PASS_check_topology)
                        bch2_fatal_error(c);
 
index 35e49197bc57054e4ec4e611728630dd74fb2b38..24e445574ab828e1b1f674a0bb987f70a6ebb10c 100644 (file)
@@ -146,7 +146,7 @@ fsck_err:
        printbuf_exit(&buf);
        return ret;
 topology_repair:
-       if ((c->recovery_passes_explicit & BIT_ULL(BCH_RECOVERY_PASS_check_topology)) &&
+       if ((c->opts.recovery_passes & BIT_ULL(BCH_RECOVERY_PASS_check_topology)) &&
            c->curr_recovery_pass > BCH_RECOVERY_PASS_check_topology) {
                bch2_inconsistent_error(c);
                ret = -BCH_ERR_btree_need_topology_repair;
index 0770aebef6d8b73d1d2850c2a1af966527d785d0..9cb9b05db6d17404da57d0dc9bbbe0a0fe67c1c2 100644 (file)
@@ -432,6 +432,9 @@ void bch2_opt_to_text(struct printbuf *out,
                else
                        prt_str(out, opt->choices[v]);
                break;
+       case BCH_OPT_BITFIELD:
+               prt_bitflags(out, opt->choices, v);
+               break;
        case BCH_OPT_FN:
                opt->fn.to_text(out, c, sb, v);
                break;
index 3d83bcdca69d9a9a7cdf99c4331f4a302a6ac989..f2ae13f0fbadeb7c5c5859621e569de794394f3c 100644 (file)
@@ -373,6 +373,16 @@ enum fsck_err_opts {
          OPT_BOOL(),                                                   \
          BCH2_NO_SB_OPT,               false,                          \
          NULL,         "Exit recovery immediately prior to journal replay")\
+       x(recovery_passes,              u64,                            \
+         OPT_FS|OPT_MOUNT,                                             \
+         OPT_BITFIELD(bch2_recovery_passes),                           \
+         BCH2_NO_SB_OPT,               0,                              \
+         NULL,         "Recovery passes to run explicitly")            \
+       x(recovery_passes_exclude,      u64,                            \
+         OPT_FS|OPT_MOUNT,                                             \
+         OPT_BITFIELD(bch2_recovery_passes),                           \
+         BCH2_NO_SB_OPT,               0,                              \
+         NULL,         "Recovery passes to exclude")                   \
        x(recovery_pass_last,           u8,                             \
          OPT_FS|OPT_MOUNT,                                             \
          OPT_STR_NOLIMIT(bch2_recovery_passes),                        \
index 36de1c6fe8c36e4ebc4c14af1eaf6f44a727e4a6..be1e7ca4362fd87b8ba2e2616505a0ab9b3565dc 100644 (file)
@@ -97,7 +97,7 @@ static void bch2_reconstruct_alloc(struct bch_fs *c)
        bch2_write_super(c);
        mutex_unlock(&c->sb_lock);
 
-       c->recovery_passes_explicit |= bch2_recovery_passes_from_stable(le64_to_cpu(ext->recovery_passes_required[0]));
+       c->opts.recovery_passes |= bch2_recovery_passes_from_stable(le64_to_cpu(ext->recovery_passes_required[0]));
 
 
        bch2_shoot_down_journal_keys(c, BTREE_ID_alloc,
@@ -525,17 +525,17 @@ static int read_btree_roots(struct bch_fs *c)
                                        "error reading btree root %s l=%u: %s",
                                        bch2_btree_id_str(i), r->level, bch2_err_str(ret))) {
                        if (btree_id_is_alloc(i)) {
-                               c->recovery_passes_explicit |= BIT_ULL(BCH_RECOVERY_PASS_check_allocations);
-                               c->recovery_passes_explicit |= BIT_ULL(BCH_RECOVERY_PASS_check_alloc_info);
-                               c->recovery_passes_explicit |= BIT_ULL(BCH_RECOVERY_PASS_check_lrus);
-                               c->recovery_passes_explicit |= BIT_ULL(BCH_RECOVERY_PASS_check_extents_to_backpointers);
-                               c->recovery_passes_explicit |= BIT_ULL(BCH_RECOVERY_PASS_check_alloc_to_lru_refs);
+                               c->opts.recovery_passes |= BIT_ULL(BCH_RECOVERY_PASS_check_allocations);
+                               c->opts.recovery_passes |= BIT_ULL(BCH_RECOVERY_PASS_check_alloc_info);
+                               c->opts.recovery_passes |= BIT_ULL(BCH_RECOVERY_PASS_check_lrus);
+                               c->opts.recovery_passes |= BIT_ULL(BCH_RECOVERY_PASS_check_extents_to_backpointers);
+                               c->opts.recovery_passes |= BIT_ULL(BCH_RECOVERY_PASS_check_alloc_to_lru_refs);
                                c->sb.compat &= ~(1ULL << BCH_COMPAT_alloc_info);
                                r->error = 0;
-                       } else if (!(c->recovery_passes_explicit & BIT_ULL(BCH_RECOVERY_PASS_scan_for_btree_nodes))) {
+                       } else if (!(c->opts.recovery_passes & BIT_ULL(BCH_RECOVERY_PASS_scan_for_btree_nodes))) {
                                bch_info(c, "will run btree node scan");
-                               c->recovery_passes_explicit |= BIT_ULL(BCH_RECOVERY_PASS_scan_for_btree_nodes);
-                               c->recovery_passes_explicit |= BIT_ULL(BCH_RECOVERY_PASS_check_topology);
+                               c->opts.recovery_passes |= BIT_ULL(BCH_RECOVERY_PASS_scan_for_btree_nodes);
+                               c->opts.recovery_passes |= BIT_ULL(BCH_RECOVERY_PASS_check_topology);
                        }
 
                        ret = 0;
@@ -706,14 +706,14 @@ int bch2_fs_recovery(struct bch_fs *c)
        if (check_version_upgrade(c))
                write_sb = true;
 
-       c->recovery_passes_explicit |= bch2_recovery_passes_from_stable(le64_to_cpu(ext->recovery_passes_required[0]));
+       c->opts.recovery_passes |= bch2_recovery_passes_from_stable(le64_to_cpu(ext->recovery_passes_required[0]));
 
        if (write_sb)
                bch2_write_super(c);
        mutex_unlock(&c->sb_lock);
 
        if (c->opts.fsck && IS_ENABLED(CONFIG_BCACHEFS_DEBUG))
-               c->recovery_passes_explicit |= BIT_ULL(BCH_RECOVERY_PASS_check_topology);
+               c->opts.recovery_passes |= BIT_ULL(BCH_RECOVERY_PASS_check_topology);
 
        if (c->opts.fsck)
                set_bit(BCH_FS_fsck_running, &c->flags);
index 73339a0a31111f032518a0ada76f6e5c1c6c0942..735b8adc8f9d95835c4037ef869623e04ce44af7 100644 (file)
@@ -40,7 +40,7 @@ static int bch2_set_may_go_rw(struct bch_fs *c)
 
        set_bit(BCH_FS_may_go_rw, &c->flags);
 
-       if (keys->nr || c->opts.fsck || !c->sb.clean || c->recovery_passes_explicit)
+       if (keys->nr || c->opts.fsck || !c->sb.clean || c->opts.recovery_passes)
                return bch2_fs_read_write_early(c);
        return 0;
 }
@@ -97,14 +97,14 @@ u64 bch2_recovery_passes_from_stable(u64 v)
 int bch2_run_explicit_recovery_pass(struct bch_fs *c,
                                    enum bch_recovery_pass pass)
 {
-       if (c->recovery_passes_explicit & BIT_ULL(pass))
+       if (c->opts.recovery_passes & BIT_ULL(pass))
                return 0;
 
        bch_info(c, "running explicit recovery pass %s (%u), currently at %s (%u)",
                 bch2_recovery_passes[pass], pass,
                 bch2_recovery_passes[c->curr_recovery_pass], c->curr_recovery_pass);
 
-       c->recovery_passes_explicit |= BIT_ULL(pass);
+       c->opts.recovery_passes |= BIT_ULL(pass);
 
        if (c->curr_recovery_pass >= pass) {
                c->curr_recovery_pass = pass;
@@ -161,7 +161,9 @@ static bool should_run_recovery_pass(struct bch_fs *c, enum bch_recovery_pass pa
 {
        struct recovery_pass_fn *p = recovery_pass_fns + pass;
 
-       if (c->recovery_passes_explicit & BIT_ULL(pass))
+       if (c->opts.recovery_passes_exclude & BIT_ULL(pass))
+               return false;
+       if (c->opts.recovery_passes & BIT_ULL(pass))
                return true;
        if ((p->when & PASS_FSCK) && c->opts.fsck)
                return true;
index 8b4e8395a908884519d506c3b2b3fcf9146a2187..42f565c76181715e5e0b24e5a5df2dd14758b0b4 100644 (file)
@@ -214,7 +214,7 @@ u64 bch2_read_flag_list(const char *opt, const char * const list[])
 
        s = strim(d);
 
-       while ((p = strsep(&s, ","))) {
+       while ((p = strsep(&s, ",;"))) {
                int flag = match_string(list, -1, p);
 
                if (flag < 0) {