281 lines
10 KiB
Diff
281 lines
10 KiB
Diff
From 4a370320dcb4ea925e38a852baf85724baf9711a Mon Sep 17 00:00:00 2001
|
|
From: Kent Overstreet <kent.overstreet@linux.dev>
|
|
Date: Mon, 28 Oct 2024 21:27:23 -0400
|
|
Subject: [PATCH 080/233] bcachefs: Kill FSCK_NEED_FSCK
|
|
Content-Type: text/plain; charset="utf-8"
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
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>
|
|
Signed-off-by: Alexander Miroshnichenko <alex@millerson.name>
|
|
---
|
|
fs/bcachefs/btree_update_interior.c | 18 ++++++------------
|
|
fs/bcachefs/buckets.c | 29 +++++++++++++++++------------
|
|
fs/bcachefs/error.c | 21 +++++++++++++--------
|
|
fs/bcachefs/error.h | 12 ++++++------
|
|
fs/bcachefs/sb-errors_format.h | 5 ++---
|
|
5 files changed, 44 insertions(+), 41 deletions(-)
|
|
|
|
diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c
|
|
index c11babe31f54..faa2816e02a0 100644
|
|
--- a/fs/bcachefs/btree_update_interior.c
|
|
+++ b/fs/bcachefs/btree_update_interior.c
|
|
@@ -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 @@ int bch2_btree_node_check_topology(struct btree_trans *trans, struct btree *b)
|
|
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;
|
|
}
|
|
|
|
diff --git a/fs/bcachefs/buckets.c b/fs/bcachefs/buckets.c
|
|
index c4123fa4f250..5b42f0a7b0cb 100644
|
|
--- a/fs/bcachefs/buckets.c
|
|
+++ b/fs/bcachefs/buckets.c
|
|
@@ -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 @@ int bch2_bucket_ref_update(struct btree_trans *trans, struct bch_dev *ca,
|
|
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;
|
|
}
|
|
diff --git a/fs/bcachefs/error.c b/fs/bcachefs/error.c
|
|
index b679def8fb98..22b0fa405a39 100644
|
|
--- a/fs/bcachefs/error.c
|
|
+++ b/fs/bcachefs/error.c
|
|
@@ -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)
|
|
diff --git a/fs/bcachefs/error.h b/fs/bcachefs/error.h
|
|
index 81af0b8ddb52..24c41a9994df 100644
|
|
--- a/fs/bcachefs/error.h
|
|
+++ b/fs/bcachefs/error.h
|
|
@@ -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 *,
|
|
diff --git a/fs/bcachefs/sb-errors_format.h b/fs/bcachefs/sb-errors_format.h
|
|
index 9feb6739f77a..f2b38493356d 100644
|
|
--- a/fs/bcachefs/sb-errors_format.h
|
|
+++ b/fs/bcachefs/sb-errors_format.h
|
|
@@ -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() \
|
|
--
|
|
2.45.2
|
|
|