From bb36a12921e5fc76f3b26a80ab0217d3dc62a473 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Tue, 15 Apr 2025 13:45:39 -0400 Subject: [PATCH] bcachefs: bch2_run_explicit_recovery_pass_printbuf() We prefer helpers that emit log messages to printbufs rather than printing them directly; that way, we can ensure that different log messages from the same event are grouped together and formatted appropriately in the dmesg log. Signed-off-by: Kent Overstreet --- fs/bcachefs/buckets.c | 33 +++++++++++++++++++++--------- fs/bcachefs/error.c | 2 +- fs/bcachefs/recovery_passes.c | 38 +++++++++++++++++++++++++++-------- fs/bcachefs/recovery_passes.h | 3 +++ 4 files changed, 57 insertions(+), 19 deletions(-) diff --git a/fs/bcachefs/buckets.c b/fs/bcachefs/buckets.c index 31fbc2716d8b..ffe957602cca 100644 --- a/fs/bcachefs/buckets.c +++ b/fs/bcachefs/buckets.c @@ -400,7 +400,8 @@ static int bucket_ref_update_err(struct btree_trans *trans, struct printbuf *buf __bch2_count_fsck_err(c, id, buf->buf, &repeat, &print, &suppress); - int ret = bch2_run_explicit_recovery_pass(c, BCH_RECOVERY_PASS_check_allocations); + int ret = bch2_run_explicit_recovery_pass_printbuf(c, buf, + BCH_RECOVERY_PASS_check_allocations); if (insert) { print = true; @@ -966,14 +967,27 @@ 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_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, - bch2_data_type_str(a->v.data_type), - bch2_data_type_str(type), - bch2_data_type_str(type)); + struct printbuf buf = PRINTBUF; + bch2_log_msg_start(c, &buf); + prt_printf(&buf, "bucket %llu:%llu gen %u different types of data in same bucket: %s, %s\n" + "while marking %s\n", + iter.pos.inode, iter.pos.offset, a->v.gen, + bch2_data_type_str(a->v.data_type), + bch2_data_type_str(type), + bch2_data_type_str(type)); + + bool repeat = false, print = true, suppress = false; + bch2_count_fsck_err(c, bucket_metadata_type_mismatch, buf.buf, + &repeat, &print, &suppress); + + bch2_run_explicit_recovery_pass_printbuf(c, &buf, + BCH_RECOVERY_PASS_check_allocations); + + if (suppress) + prt_printf(&buf, "Ratelimiting new instances of previous error\n"); + if (print) + bch2_print_string_as_lines(KERN_ERR, buf.buf); + printbuf_exit(&buf); ret = -BCH_ERR_metadata_bucket_inconsistency; goto err; } @@ -985,7 +999,6 @@ 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 6b8695b1349c..faeadffa1103 100644 --- a/fs/bcachefs/error.c +++ b/fs/bcachefs/error.c @@ -104,7 +104,7 @@ int __bch2_topology_error(struct bch_fs *c, struct printbuf *out) __bch2_inconsistent_error(c, out); return -BCH_ERR_btree_need_topology_repair; } else { - return bch2_run_explicit_recovery_pass(c, BCH_RECOVERY_PASS_check_topology) ?: + return bch2_run_explicit_recovery_pass_printbuf(c, out, BCH_RECOVERY_PASS_check_topology) ?: -BCH_ERR_btree_node_read_validate_error; } } diff --git a/fs/bcachefs/recovery_passes.c b/fs/bcachefs/recovery_passes.c index 22f72bb5b853..946428daeecc 100644 --- a/fs/bcachefs/recovery_passes.c +++ b/fs/bcachefs/recovery_passes.c @@ -101,7 +101,8 @@ u64 bch2_recovery_passes_from_stable(u64 v) /* * For when we need to rewind recovery passes and run a pass we skipped: */ -static int __bch2_run_explicit_recovery_pass(struct bch_fs *c, +static int __bch2_run_explicit_recovery_pass(struct printbuf *out, + struct bch_fs *c, enum bch_recovery_pass pass) { if (c->curr_recovery_pass == ARRAY_SIZE(recovery_pass_fns)) @@ -115,15 +116,15 @@ static int __bch2_run_explicit_recovery_pass(struct bch_fs *c, if (pass < BCH_RECOVERY_PASS_set_may_go_rw && c->curr_recovery_pass >= BCH_RECOVERY_PASS_set_may_go_rw) { if (print) - bch_info(c, "need recovery pass %s (%u), but already rw", - bch2_recovery_passes[pass], pass); + prt_printf(out, "need recovery pass %s (%u), but already rw", + bch2_recovery_passes[pass], pass); return -BCH_ERR_cannot_rewind_recovery; } if (print) - 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); + prt_printf(out, "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->opts.recovery_passes |= BIT_ULL(pass); @@ -136,13 +137,34 @@ static int __bch2_run_explicit_recovery_pass(struct bch_fs *c, } } -int bch2_run_explicit_recovery_pass(struct bch_fs *c, +int bch2_run_explicit_recovery_pass_printbuf(struct bch_fs *c, + struct printbuf *out, enum bch_recovery_pass pass) { + bch2_printbuf_make_room(out, 1024); + out->atomic++; + unsigned long flags; spin_lock_irqsave(&c->recovery_pass_lock, flags); - int ret = __bch2_run_explicit_recovery_pass(c, pass); + int ret = __bch2_run_explicit_recovery_pass(out, c, pass); spin_unlock_irqrestore(&c->recovery_pass_lock, flags); + + --out->atomic; + return ret; +} + +int bch2_run_explicit_recovery_pass(struct bch_fs *c, + enum bch_recovery_pass pass) +{ + struct printbuf buf = PRINTBUF; + bch2_log_msg_start(c, &buf); + unsigned len = buf.pos; + + int ret = bch2_run_explicit_recovery_pass_printbuf(c, &buf, pass); + + if (len != buf.pos) + bch2_print_string_as_lines(KERN_NOTICE, buf.buf); + printbuf_exit(&buf); return ret; } diff --git a/fs/bcachefs/recovery_passes.h b/fs/bcachefs/recovery_passes.h index 7d7339c8fa29..e19a8aaba2f8 100644 --- a/fs/bcachefs/recovery_passes.h +++ b/fs/bcachefs/recovery_passes.h @@ -8,6 +8,9 @@ u64 bch2_recovery_passes_from_stable(u64 v); u64 bch2_fsck_recovery_passes(void); +int bch2_run_explicit_recovery_pass_printbuf(struct bch_fs *, + struct printbuf *, + enum bch_recovery_pass); int bch2_run_explicit_recovery_pass(struct bch_fs *, enum bch_recovery_pass); int bch2_run_explicit_recovery_pass_persistent_locked(struct bch_fs *, enum bch_recovery_pass); int bch2_run_explicit_recovery_pass_persistent(struct bch_fs *, enum bch_recovery_pass); -- 2.50.1