bcachefs: Online fsck can now fix errors
authorKent Overstreet <kent.overstreet@linux.dev>
Mon, 1 Jan 2024 00:41:45 +0000 (19:41 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sat, 6 Jan 2024 04:24:20 +0000 (23:24 -0500)
BCH_FS_fsck_done -> BCH_FS_fsck_running; set when we might be fixing
fsck errors. Also; set fix_errors to ask by default when fsck is
running.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/bcachefs.h
fs/bcachefs/chardev.c
fs/bcachefs/error.c
fs/bcachefs/recovery.c

index ffef6182a477b14a1449d765c864de1246d2f573..c7ed097e41a781430ac16e52eb654d3fdb71e6e5 100644 (file)
@@ -602,9 +602,6 @@ struct bch_dev {
 };
 
 /*
- * fsck_done - kill?
- *
- * replace with something more general from enumated fsck passes/errors:
  * initial_gc_unfixed
  * error
  * topology error
@@ -620,7 +617,7 @@ struct bch_dev {
        x(going_ro)                     \
        x(write_disable_complete)       \
        x(clean_shutdown)               \
-       x(fsck_done)                    \
+       x(fsck_running)                 \
        x(initial_gc_unfixed)           \
        x(need_another_gc)              \
        x(need_delete_dead_snapshots)   \
index 46db563e0497bcb5ac172dbe56bfb2da71bedf58..226b39c176673a374f50ab06ad5f6d3e0a4858d8 100644 (file)
@@ -774,15 +774,24 @@ static int bch2_fsck_online_thread_fn(void *arg)
        /*
         * XXX: can we figure out a way to do this without mucking with c->opts?
         */
+       unsigned old_fix_errors = c->opts.fix_errors;
        if (opt_defined(thr->opts, fix_errors))
                c->opts.fix_errors = thr->opts.fix_errors;
+       else
+               c->opts.fix_errors = FSCK_FIX_ask;
+
        c->opts.fsck = true;
+       set_bit(BCH_FS_fsck_running, &c->flags);
 
        c->curr_recovery_pass = BCH_RECOVERY_PASS_check_alloc_info;
-       bch2_run_online_recovery_passes(c);
+       int ret = bch2_run_online_recovery_passes(c);
+
+       clear_bit(BCH_FS_fsck_running, &c->flags);
+       bch_err_fn(c, ret);
 
        c->stdio = NULL;
        c->stdio_filter = NULL;
+       c->opts.fix_errors = old_fix_errors;
 
        thread_with_stdio_done(&thr->thr);
 
index 8a8bcbcdff2a6918640cc4f0a6c4bf83246700f3..e8200cad3ab8097187a1a29b7854f9d523568e37 100644 (file)
@@ -28,7 +28,7 @@ bool bch2_inconsistent_error(struct bch_fs *c)
 void bch2_topology_error(struct bch_fs *c)
 {
        set_bit(BCH_FS_topology_error, &c->flags);
-       if (test_bit(BCH_FS_fsck_done, &c->flags))
+       if (!test_bit(BCH_FS_fsck_running, &c->flags))
                bch2_inconsistent_error(c);
 }
 
@@ -141,7 +141,7 @@ static struct fsck_err_state *fsck_err_get(struct bch_fs *c, const char *fmt)
 {
        struct fsck_err_state *s;
 
-       if (test_bit(BCH_FS_fsck_done, &c->flags))
+       if (!test_bit(BCH_FS_fsck_running, &c->flags))
                return NULL;
 
        list_for_each_entry(s, &c->fsck_error_msgs, list)
@@ -223,7 +223,7 @@ int bch2_fsck_err(struct bch_fs *c,
                prt_printf(out, bch2_log_msg(c, ""));
 #endif
 
-       if (test_bit(BCH_FS_fsck_done, &c->flags)) {
+       if (!test_bit(BCH_FS_fsck_running, &c->flags)) {
                if (c->opts.errors != BCH_ON_ERROR_continue ||
                    !(flags & (FSCK_CAN_FIX|FSCK_CAN_IGNORE))) {
                        prt_str(out, ", shutting down");
@@ -290,7 +290,7 @@ int bch2_fsck_err(struct bch_fs *c,
                        bch2_print_string_as_lines(KERN_ERR, out->buf);
        }
 
-       if (!test_bit(BCH_FS_fsck_done, &c->flags) &&
+       if (test_bit(BCH_FS_fsck_running, &c->flags) &&
            (ret != -BCH_ERR_fsck_fix &&
             ret != -BCH_ERR_fsck_ignore))
                bch_err(c, "Unable to continue, halting");
index 066aef6f3c745a99c1047e2e237531b7ab4f2689..6c0af6502ce95de812b984ac50adafa9a3c97a86 100644 (file)
@@ -832,6 +832,9 @@ int bch2_fs_recovery(struct bch_fs *c)
        if (c->opts.fsck && IS_ENABLED(CONFIG_BCACHEFS_DEBUG))
                c->recovery_passes_explicit |= BIT_ULL(BCH_RECOVERY_PASS_check_topology);
 
+       if (c->opts.fsck)
+               set_bit(BCH_FS_fsck_running, &c->flags);
+
        ret = bch2_blacklist_table_initialize(c);
        if (ret) {
                bch_err(c, "error initializing blacklist table");
@@ -972,6 +975,8 @@ use_clean:
        if (ret)
                goto err;
 
+       clear_bit(BCH_FS_fsck_running, &c->flags);
+
        /* If we fixed errors, verify that fs is actually clean now: */
        if (IS_ENABLED(CONFIG_BCACHEFS_DEBUG) &&
            test_bit(BCH_FS_errors_fixed, &c->flags) &&
@@ -1066,7 +1071,6 @@ use_clean:
 
        ret = 0;
 out:
-       set_bit(BCH_FS_fsck_done, &c->flags);
        bch2_flush_fsck_errs(c);
 
        if (!c->opts.keep_journal &&
@@ -1113,7 +1117,6 @@ int bch2_fs_initialize(struct bch_fs *c)
 
        c->curr_recovery_pass = ARRAY_SIZE(recovery_pass_fns);
        set_bit(BCH_FS_may_go_rw, &c->flags);
-       set_bit(BCH_FS_fsck_done, &c->flags);
 
        for (unsigned i = 0; i < BTREE_ID_NR; i++)
                bch2_btree_root_alloc(c, i);