bcachefs: Kill FSCK_NEED_FSCK
authorKent Overstreet <kent.overstreet@linux.dev>
Tue, 29 Oct 2024 01:27:23 +0000 (21:27 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sat, 21 Dec 2024 06:36:17 +0000 (01:36 -0500)
If we find an error that indicates that we need to run fsck, we can
specify that directly with run_explicit_recovery_pass().

These are now log_fsck_err() calls: we're just logging in the superblock
that an error occurred - and possibly doing an emergency shutdown,
depending on policy.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/btree_update_interior.c
fs/bcachefs/buckets.c
fs/bcachefs/error.c
fs/bcachefs/error.h
fs/bcachefs/sb-errors_format.h

index c11babe31f54e12b89e68652e0b426f2e05c2839..faa2816e02a024cad53500e08311b0813c57a6ec 100644 (file)
@@ -62,7 +62,7 @@ int bch2_btree_node_check_topology(struct btree_trans *trans, struct btree *b)
                if (!bpos_eq(b->data->min_key, POS_MIN)) {
                        printbuf_reset(&buf);
                        bch2_bpos_to_text(&buf, b->data->min_key);
-                       need_fsck_err(trans, btree_root_bad_min_key,
+                       log_fsck_err(trans, btree_root_bad_min_key,
                                      "btree root with incorrect min_key: %s", buf.buf);
                        goto topology_repair;
                }
@@ -70,7 +70,7 @@ int bch2_btree_node_check_topology(struct btree_trans *trans, struct btree *b)
                if (!bpos_eq(b->data->max_key, SPOS_MAX)) {
                        printbuf_reset(&buf);
                        bch2_bpos_to_text(&buf, b->data->max_key);
-                       need_fsck_err(trans, btree_root_bad_max_key,
+                       log_fsck_err(trans, btree_root_bad_max_key,
                                      "btree root with incorrect max_key: %s", buf.buf);
                        goto topology_repair;
                }
@@ -106,7 +106,7 @@ int bch2_btree_node_check_topology(struct btree_trans *trans, struct btree *b)
                        prt_str(&buf, "\n  next ");
                        bch2_bkey_val_to_text(&buf, c, k);
 
-                       need_fsck_err(trans, btree_node_topology_bad_min_key, "%s", buf.buf);
+                       log_fsck_err(trans, btree_node_topology_bad_min_key, "%s", buf.buf);
                        goto topology_repair;
                }
 
@@ -123,7 +123,7 @@ int bch2_btree_node_check_topology(struct btree_trans *trans, struct btree *b)
                prt_str(&buf, " node ");
                bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&b->key));
 
-               need_fsck_err(trans, btree_node_topology_empty_interior_node, "%s", buf.buf);
+               log_fsck_err(trans, btree_node_topology_empty_interior_node, "%s", buf.buf);
                goto topology_repair;
        } else if (!bpos_eq(prev.k->k.p, b->key.k.p)) {
                bch2_topology_error(c);
@@ -136,7 +136,7 @@ int bch2_btree_node_check_topology(struct btree_trans *trans, struct btree *b)
                prt_str(&buf, "\n  last key ");
                bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(prev.k));
 
-               need_fsck_err(trans, btree_node_topology_bad_max_key, "%s", buf.buf);
+               log_fsck_err(trans, btree_node_topology_bad_max_key, "%s", buf.buf);
                goto topology_repair;
        }
 out:
@@ -146,13 +146,7 @@ fsck_err:
        printbuf_exit(&buf);
        return ret;
 topology_repair:
-       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;
-       } else {
-               ret = bch2_run_explicit_recovery_pass(c, BCH_RECOVERY_PASS_check_topology);
-       }
+       ret = bch2_topology_error(c);
        goto out;
 }
 
index c4123fa4f250b4c177df634e2aa2dfcf2d4dcfe2..5b42f0a7b0cb2edcbdc9d2257e902dac478eeba8 100644 (file)
@@ -20,6 +20,7 @@
 #include "movinggc.h"
 #include "rebalance.h"
 #include "recovery.h"
+#include "recovery_passes.h"
 #include "reflink.h"
 #include "replicas.h"
 #include "subvolume.h"
@@ -402,8 +403,8 @@ int bch2_bucket_ref_update(struct btree_trans *trans, struct bch_dev *ca,
        BUG_ON(!sectors);
 
        if (gen_after(ptr->gen, b_gen)) {
-               bch2_fsck_err(trans, FSCK_CAN_IGNORE|FSCK_NEED_FSCK,
-                             ptr_gen_newer_than_bucket_gen,
+               bch2_run_explicit_recovery_pass(c, BCH_RECOVERY_PASS_check_allocations);
+               log_fsck_err(trans, ptr_gen_newer_than_bucket_gen,
                        "bucket %u:%zu gen %u data type %s: ptr gen %u newer than bucket gen\n"
                        "while marking %s",
                        ptr->dev, bucket_nr, b_gen,
@@ -416,8 +417,8 @@ int bch2_bucket_ref_update(struct btree_trans *trans, struct bch_dev *ca,
        }
 
        if (gen_cmp(b_gen, ptr->gen) > BUCKET_GC_GEN_MAX) {
-               bch2_fsck_err(trans, FSCK_CAN_IGNORE|FSCK_NEED_FSCK,
-                             ptr_too_stale,
+               bch2_run_explicit_recovery_pass(c, BCH_RECOVERY_PASS_check_allocations);
+               log_fsck_err(trans, ptr_too_stale,
                        "bucket %u:%zu gen %u data type %s: ptr gen %u too stale\n"
                        "while marking %s",
                        ptr->dev, bucket_nr, b_gen,
@@ -436,8 +437,8 @@ int bch2_bucket_ref_update(struct btree_trans *trans, struct bch_dev *ca,
        }
 
        if (b_gen != ptr->gen) {
-               bch2_fsck_err(trans, FSCK_CAN_IGNORE|FSCK_NEED_FSCK,
-                             stale_dirty_ptr,
+               bch2_run_explicit_recovery_pass(c, BCH_RECOVERY_PASS_check_allocations);
+               log_fsck_err(trans, stale_dirty_ptr,
                        "bucket %u:%zu gen %u (mem gen %u) data type %s: stale dirty ptr (gen %u)\n"
                        "while marking %s",
                        ptr->dev, bucket_nr, b_gen,
@@ -452,8 +453,8 @@ int bch2_bucket_ref_update(struct btree_trans *trans, struct bch_dev *ca,
        }
 
        if (bucket_data_type_mismatch(bucket_data_type, ptr_data_type)) {
-               bch2_fsck_err(trans, FSCK_CAN_IGNORE|FSCK_NEED_FSCK,
-                             ptr_bucket_data_type_mismatch,
+               bch2_run_explicit_recovery_pass(c, BCH_RECOVERY_PASS_check_allocations);
+               log_fsck_err(trans, ptr_bucket_data_type_mismatch,
                        "bucket %u:%zu gen %u different types of data in same bucket: %s, %s\n"
                        "while marking %s",
                        ptr->dev, bucket_nr, b_gen,
@@ -467,8 +468,8 @@ int bch2_bucket_ref_update(struct btree_trans *trans, struct bch_dev *ca,
        }
 
        if ((u64) *bucket_sectors + sectors > U32_MAX) {
-               bch2_fsck_err(trans, FSCK_CAN_IGNORE|FSCK_NEED_FSCK,
-                             bucket_sector_count_overflow,
+               bch2_run_explicit_recovery_pass(c, BCH_RECOVERY_PASS_check_allocations);
+               log_fsck_err(trans, bucket_sector_count_overflow,
                        "bucket %u:%zu gen %u data type %s sector count overflow: %u + %lli > U32_MAX\n"
                        "while marking %s",
                        ptr->dev, bucket_nr, b_gen,
@@ -486,7 +487,9 @@ out:
        printbuf_exit(&buf);
        return ret;
 err:
+fsck_err:
        bch2_dump_trans_updates(trans);
+       bch2_inconsistent_error(c);
        ret = -BCH_ERR_bucket_ref_update;
        goto out;
 }
@@ -952,6 +955,7 @@ static int __bch2_trans_mark_metadata_bucket(struct btree_trans *trans,
                                    enum bch_data_type type,
                                    unsigned sectors)
 {
+       struct bch_fs *c = trans->c;
        struct btree_iter iter;
        int ret = 0;
 
@@ -961,8 +965,8 @@ static int __bch2_trans_mark_metadata_bucket(struct btree_trans *trans,
                return PTR_ERR(a);
 
        if (a->v.data_type && type && a->v.data_type != type) {
-               bch2_fsck_err(trans, FSCK_CAN_IGNORE|FSCK_NEED_FSCK,
-                             bucket_metadata_type_mismatch,
+               bch2_run_explicit_recovery_pass(c, BCH_RECOVERY_PASS_check_allocations);
+               log_fsck_err(trans, bucket_metadata_type_mismatch,
                        "bucket %llu:%llu gen %u different types of data in same bucket: %s, %s\n"
                        "while marking %s",
                        iter.pos.inode, iter.pos.offset, a->v.gen,
@@ -980,6 +984,7 @@ static int __bch2_trans_mark_metadata_bucket(struct btree_trans *trans,
                ret = bch2_trans_update(trans, &iter, &a->k_i, 0);
        }
 err:
+fsck_err:
        bch2_trans_iter_exit(trans, &iter);
        return ret;
 }
index b679def8fb98c7c94b70bb18b43b1b1600df1f4d..22b0fa405a39ece959d3176b32a05dc06dfc723f 100644 (file)
@@ -385,9 +385,7 @@ int __bch2_fsck_err(struct bch_fs *c,
                        prt_str(out, ", not ");
                        prt_actioning(out, action);
                }
-       } else if (flags & FSCK_NEED_FSCK) {
-               prt_str(out, " (run fsck to correct)");
-       } else {
+       } else if (!(flags & FSCK_CAN_IGNORE)) {
                prt_str(out, " (repair unimplemented)");
        }
 
@@ -424,11 +422,18 @@ int __bch2_fsck_err(struct bch_fs *c,
        if (inconsistent)
                bch2_inconsistent_error(c);
 
-       if (ret == -BCH_ERR_fsck_fix) {
-               set_bit(BCH_FS_errors_fixed, &c->flags);
-       } else {
-               set_bit(BCH_FS_errors_not_fixed, &c->flags);
-               set_bit(BCH_FS_error, &c->flags);
+       /*
+        * We don't yet track whether the filesystem currently has errors, for
+        * log_fsck_err()s: that would require us to track for every error type
+        * which recovery pass corrects it, to get the fsck exit status correct:
+        */
+       if (flags & FSCK_CAN_FIX) {
+               if (ret == -BCH_ERR_fsck_fix) {
+                       set_bit(BCH_FS_errors_fixed, &c->flags);
+               } else {
+                       set_bit(BCH_FS_errors_not_fixed, &c->flags);
+                       set_bit(BCH_FS_error, &c->flags);
+               }
        }
 err:
        if (action != action_orig)
index 81af0b8ddb5209d3e4091ef00017aa9aacfd49df..24c41a9994df86cb511578a87a080b47bdd50dbf 100644 (file)
@@ -129,12 +129,6 @@ void bch2_flush_fsck_errs(struct bch_fs *);
        (unlikely(cond) ? __fsck_err(c, _flags, _err_type, __VA_ARGS__) : false);\
 })
 
-#define need_fsck_err_on(cond, c, _err_type, ...)                              \
-       __fsck_err_on(cond, c, FSCK_CAN_IGNORE|FSCK_NEED_FSCK, _err_type, __VA_ARGS__)
-
-#define need_fsck_err(c, _err_type, ...)                               \
-       __fsck_err(c, FSCK_CAN_IGNORE|FSCK_NEED_FSCK, _err_type, __VA_ARGS__)
-
 #define mustfix_fsck_err(c, _err_type, ...)                            \
        __fsck_err(c, FSCK_CAN_FIX, _err_type, __VA_ARGS__)
 
@@ -147,6 +141,12 @@ void bch2_flush_fsck_errs(struct bch_fs *);
 #define fsck_err_on(cond, c, _err_type, ...)                           \
        __fsck_err_on(cond, c, FSCK_CAN_FIX|FSCK_CAN_IGNORE, _err_type, __VA_ARGS__)
 
+#define log_fsck_err(c, _err_type, ...)                                        \
+       __fsck_err(c, FSCK_CAN_IGNORE, _err_type, __VA_ARGS__)
+
+#define log_fsck_err_on(cond, c, _err_type, ...)                               \
+       __fsck_err_on(cond, c, FSCK_CAN_IGNORE, _err_type, __VA_ARGS__)
+
 enum bch_validate_flags;
 __printf(5, 6)
 int __bch2_bkey_fsck_err(struct bch_fs *,
index 9feb6739f77a1c869686715557703f80f55c7d57..f2b38493356df03fecb0dcd11a1270bd2090e8ea 100644 (file)
@@ -5,9 +5,8 @@
 enum bch_fsck_flags {
        FSCK_CAN_FIX            = 1 << 0,
        FSCK_CAN_IGNORE         = 1 << 1,
-       FSCK_NEED_FSCK          = 1 << 2,
-       FSCK_NO_RATELIMIT       = 1 << 3,
-       FSCK_AUTOFIX            = 1 << 4,
+       FSCK_NO_RATELIMIT       = 1 << 2,
+       FSCK_AUTOFIX            = 1 << 3,
 };
 
 #define BCH_SB_ERRS()                                                                  \