bcachefs: Consistent indentation of multiline fsck errors

Add the new helper printbuf_indent_add_nextline(), and use it in
__bch2_fsck_err() to centralize setting the indentation of multiline
fsck errors.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Kent Overstreet 2025-03-26 13:21:11 -04:00
parent a7cdf2276e
commit 1ece53237e
20 changed files with 113 additions and 94 deletions

View file

@ -676,8 +676,7 @@ static int __need_discard_or_freespace_err(struct btree_trans *trans,
bch2_bkey_val_to_text(&buf, c, alloc_k); bch2_bkey_val_to_text(&buf, c, alloc_k);
int ret = __bch2_fsck_err(NULL, trans, flags, err_id, int ret = __bch2_fsck_err(NULL, trans, flags, err_id,
"bucket incorrectly %sset in %s btree\n" "bucket incorrectly %sset in %s btree\n%s",
" %s",
set ? "" : "un", set ? "" : "un",
bch2_btree_id_str(btree), bch2_btree_id_str(btree),
buf.buf); buf.buf);
@ -1030,7 +1029,7 @@ int bch2_trigger_alloc(struct btree_trans *trans,
bch2_dev_put(ca); bch2_dev_put(ca);
return ret; return ret;
invalid_bucket: invalid_bucket:
bch2_fs_inconsistent(c, "reference to invalid bucket\n %s", bch2_fs_inconsistent(c, "reference to invalid bucket\n%s",
(bch2_bkey_val_to_text(&buf, c, new.s_c), buf.buf)); (bch2_bkey_val_to_text(&buf, c, new.s_c), buf.buf));
ret = -BCH_ERR_trigger_alloc; ret = -BCH_ERR_trigger_alloc;
goto err; goto err;
@ -1204,8 +1203,7 @@ int bch2_check_alloc_key(struct btree_trans *trans,
if (fsck_err_on(a->gen != alloc_gen(k, gens_offset), if (fsck_err_on(a->gen != alloc_gen(k, gens_offset),
trans, bucket_gens_key_wrong, trans, bucket_gens_key_wrong,
"incorrect gen in bucket_gens btree (got %u should be %u)\n" "incorrect gen in bucket_gens btree (got %u should be %u)\n%s",
" %s",
alloc_gen(k, gens_offset), a->gen, alloc_gen(k, gens_offset), a->gen,
(printbuf_reset(&buf), (printbuf_reset(&buf),
bch2_bkey_val_to_text(&buf, c, alloc_k), buf.buf))) { bch2_bkey_val_to_text(&buf, c, alloc_k), buf.buf))) {
@ -1263,7 +1261,7 @@ int bch2_check_alloc_hole_freespace(struct btree_trans *trans,
if (fsck_err_on(k.k->type != KEY_TYPE_set, if (fsck_err_on(k.k->type != KEY_TYPE_set,
trans, freespace_hole_missing, trans, freespace_hole_missing,
"hole in alloc btree missing in freespace btree\n" "hole in alloc btree missing in freespace btree\n"
" device %llu buckets %llu-%llu", "device %llu buckets %llu-%llu",
freespace_iter->pos.inode, freespace_iter->pos.inode,
freespace_iter->pos.offset, freespace_iter->pos.offset,
end->offset)) { end->offset)) {
@ -1422,7 +1420,7 @@ int bch2_check_discard_freespace_key(struct btree_trans *trans, struct btree_ite
(state == BCH_DATA_free && (state == BCH_DATA_free &&
genbits != alloc_freespace_genbits(*a))) { genbits != alloc_freespace_genbits(*a))) {
if (fsck_err(trans, need_discard_freespace_key_bad, if (fsck_err(trans, need_discard_freespace_key_bad,
"%s\n incorrectly set at %s:%llu:%llu:0 (free %u, genbits %llu should be %llu)", "%s\nincorrectly set at %s:%llu:%llu:0 (free %u, genbits %llu should be %llu)",
(bch2_bkey_val_to_text(&buf, c, alloc_k), buf.buf), (bch2_bkey_val_to_text(&buf, c, alloc_k), buf.buf),
bch2_btree_id_str(iter->btree_id), bch2_btree_id_str(iter->btree_id),
iter->pos.inode, iter->pos.inode,
@ -1503,7 +1501,7 @@ int bch2_check_bucket_gens_key(struct btree_trans *trans,
struct bch_dev *ca = bch2_dev_tryget_noerror(c, k.k->p.inode); struct bch_dev *ca = bch2_dev_tryget_noerror(c, k.k->p.inode);
if (!ca) { if (!ca) {
if (fsck_err(trans, bucket_gens_to_invalid_dev, if (fsck_err(trans, bucket_gens_to_invalid_dev,
"bucket_gens key for invalid device:\n %s", "bucket_gens key for invalid device:\n%s",
(bch2_bkey_val_to_text(&buf, c, k), buf.buf))) (bch2_bkey_val_to_text(&buf, c, k), buf.buf)))
ret = bch2_btree_delete_at(trans, iter, 0); ret = bch2_btree_delete_at(trans, iter, 0);
goto out; goto out;
@ -1512,7 +1510,7 @@ int bch2_check_bucket_gens_key(struct btree_trans *trans,
if (fsck_err_on(end <= ca->mi.first_bucket || if (fsck_err_on(end <= ca->mi.first_bucket ||
start >= ca->mi.nbuckets, start >= ca->mi.nbuckets,
trans, bucket_gens_to_invalid_buckets, trans, bucket_gens_to_invalid_buckets,
"bucket_gens key for invalid buckets:\n %s", "bucket_gens key for invalid buckets:\n%s",
(bch2_bkey_val_to_text(&buf, c, k), buf.buf))) { (bch2_bkey_val_to_text(&buf, c, k), buf.buf))) {
ret = bch2_btree_delete_at(trans, iter, 0); ret = bch2_btree_delete_at(trans, iter, 0);
goto out; goto out;
@ -1715,8 +1713,7 @@ static int bch2_check_alloc_to_lru_ref(struct btree_trans *trans,
if (fsck_err_on(!a->io_time[READ], if (fsck_err_on(!a->io_time[READ],
trans, alloc_key_cached_but_read_time_zero, trans, alloc_key_cached_but_read_time_zero,
"cached bucket with read_time 0\n" "cached bucket with read_time 0\n%s",
" %s",
(printbuf_reset(&buf), (printbuf_reset(&buf),
bch2_bkey_val_to_text(&buf, c, alloc_k), buf.buf))) { bch2_bkey_val_to_text(&buf, c, alloc_k), buf.buf))) {
struct bkey_i_alloc_v4 *a_mut = struct bkey_i_alloc_v4 *a_mut =

View file

@ -210,11 +210,11 @@ static int backpointer_target_not_found(struct btree_trans *trans,
if (ret) if (ret)
return ret; return ret;
prt_printf(&buf, "backpointer doesn't match %s it points to:\n ", prt_printf(&buf, "backpointer doesn't match %s it points to:\n",
bp.v->level ? "btree node" : "extent"); bp.v->level ? "btree node" : "extent");
bch2_bkey_val_to_text(&buf, c, bp.s_c); bch2_bkey_val_to_text(&buf, c, bp.s_c);
prt_printf(&buf, "\n "); prt_newline(&buf);
bch2_bkey_val_to_text(&buf, c, target_k); bch2_bkey_val_to_text(&buf, c, target_k);
struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(target_k); struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(target_k);
@ -222,7 +222,7 @@ static int backpointer_target_not_found(struct btree_trans *trans,
struct extent_ptr_decoded p; struct extent_ptr_decoded p;
bkey_for_each_ptr_decode(target_k.k, ptrs, p, entry) bkey_for_each_ptr_decode(target_k.k, ptrs, p, entry)
if (p.ptr.dev == bp.k->p.inode) { if (p.ptr.dev == bp.k->p.inode) {
prt_printf(&buf, "\n "); prt_newline(&buf);
struct bkey_i_backpointer bp2; struct bkey_i_backpointer bp2;
bch2_extent_ptr_to_bp(c, bp.v->btree_id, bp.v->level, target_k, p, entry, &bp2); bch2_extent_ptr_to_bp(c, bp.v->btree_id, bp.v->level, target_k, p, entry, &bp2);
bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&bp2.k_i)); bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&bp2.k_i));
@ -443,12 +443,11 @@ static int check_extent_checksum(struct btree_trans *trans,
if (ret) if (ret)
goto err; goto err;
prt_str(&buf, "extents pointing to same space, but first extent checksum bad:"); prt_printf(&buf, "extents pointing to same space, but first extent checksum bad:\n");
prt_printf(&buf, "\n ");
bch2_btree_id_to_text(&buf, btree); bch2_btree_id_to_text(&buf, btree);
prt_str(&buf, " "); prt_str(&buf, " ");
bch2_bkey_val_to_text(&buf, c, extent); bch2_bkey_val_to_text(&buf, c, extent);
prt_printf(&buf, "\n "); prt_newline(&buf);
bch2_btree_id_to_text(&buf, o_btree); bch2_btree_id_to_text(&buf, o_btree);
prt_str(&buf, " "); prt_str(&buf, " ");
bch2_bkey_val_to_text(&buf, c, extent2); bch2_bkey_val_to_text(&buf, c, extent2);
@ -539,9 +538,9 @@ static int check_bp_exists(struct btree_trans *trans,
if (bch2_extents_match(orig_k, other_extent)) { if (bch2_extents_match(orig_k, other_extent)) {
printbuf_reset(&buf); printbuf_reset(&buf);
prt_printf(&buf, "duplicate versions of same extent, deleting smaller\n "); prt_printf(&buf, "duplicate versions of same extent, deleting smaller\n");
bch2_bkey_val_to_text(&buf, c, orig_k); bch2_bkey_val_to_text(&buf, c, orig_k);
prt_str(&buf, "\n "); prt_newline(&buf);
bch2_bkey_val_to_text(&buf, c, other_extent); bch2_bkey_val_to_text(&buf, c, other_extent);
bch_err(c, "%s", buf.buf); bch_err(c, "%s", buf.buf);
@ -580,20 +579,20 @@ static int check_bp_exists(struct btree_trans *trans,
} }
printbuf_reset(&buf); printbuf_reset(&buf);
prt_printf(&buf, "duplicate extents pointing to same space on dev %llu\n ", bp->k.p.inode); prt_printf(&buf, "duplicate extents pointing to same space on dev %llu\n", bp->k.p.inode);
bch2_bkey_val_to_text(&buf, c, orig_k); bch2_bkey_val_to_text(&buf, c, orig_k);
prt_str(&buf, "\n "); prt_newline(&buf);
bch2_bkey_val_to_text(&buf, c, other_extent); bch2_bkey_val_to_text(&buf, c, other_extent);
bch_err(c, "%s", buf.buf); bch_err(c, "%s", buf.buf);
ret = -BCH_ERR_fsck_repair_unimplemented; ret = -BCH_ERR_fsck_repair_unimplemented;
goto err; goto err;
missing: missing:
printbuf_reset(&buf); printbuf_reset(&buf);
prt_str(&buf, "missing backpointer\n for: "); prt_str(&buf, "missing backpointer\nfor: ");
bch2_bkey_val_to_text(&buf, c, orig_k); bch2_bkey_val_to_text(&buf, c, orig_k);
prt_printf(&buf, "\n want: "); prt_printf(&buf, "\nwant: ");
bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&bp->k_i)); bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&bp->k_i));
prt_printf(&buf, "\n got: "); prt_printf(&buf, "\ngot: ");
bch2_bkey_val_to_text(&buf, c, bp_k); bch2_bkey_val_to_text(&buf, c, bp_k);
if (fsck_err(trans, ptr_to_missing_backpointer, "%s", buf.buf)) if (fsck_err(trans, ptr_to_missing_backpointer, "%s", buf.buf))

View file

@ -1417,7 +1417,7 @@ void __bch2_btree_pos_to_text(struct printbuf *out, struct bch_fs *c,
prt_printf(out, "%u", r->level); prt_printf(out, "%u", r->level);
else else
prt_printf(out, "(unknown)"); prt_printf(out, "(unknown)");
prt_printf(out, "\n "); prt_newline(out);
bch2_bkey_val_to_text(out, c, k); bch2_bkey_val_to_text(out, c, k);
} }

View file

@ -213,15 +213,15 @@ static int btree_check_node_boundaries(struct btree_trans *trans, struct btree *
prt_printf(&buf, " at "); prt_printf(&buf, " at ");
bch2_btree_id_level_to_text(&buf, b->c.btree_id, b->c.level); bch2_btree_id_level_to_text(&buf, b->c.btree_id, b->c.level);
prt_printf(&buf, ":\n parent: "); prt_printf(&buf, ":\nparent: ");
bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&b->key)); bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&b->key));
if (prev) { if (prev) {
prt_printf(&buf, "\n prev: "); prt_printf(&buf, "\nprev: ");
bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&prev->key)); bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&prev->key));
} }
prt_str(&buf, "\n next: "); prt_str(&buf, "\nnext: ");
bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&cur->key)); bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&cur->key));
if (bpos_lt(expected_start, cur->data->min_key)) { /* gap */ if (bpos_lt(expected_start, cur->data->min_key)) { /* gap */
@ -280,12 +280,12 @@ static int btree_repair_node_end(struct btree_trans *trans, struct btree *b,
if (bpos_eq(child->key.k.p, b->key.k.p)) if (bpos_eq(child->key.k.p, b->key.k.p))
return 0; return 0;
prt_printf(&buf, " at "); prt_printf(&buf, "\nat: ");
bch2_btree_id_level_to_text(&buf, b->c.btree_id, b->c.level); bch2_btree_id_level_to_text(&buf, b->c.btree_id, b->c.level);
prt_printf(&buf, ":\n parent: "); prt_printf(&buf, "\nparent: ");
bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&b->key)); bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&b->key));
prt_str(&buf, "\n child: "); prt_str(&buf, "\nchild: ");
bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&child->key)); bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&child->key));
if (mustfix_fsck_err(trans, btree_node_topology_bad_max_key, if (mustfix_fsck_err(trans, btree_node_topology_bad_max_key,
@ -351,8 +351,7 @@ static int bch2_btree_repair_topology_recurse(struct btree_trans *trans, struct
if (mustfix_fsck_err_on(bch2_err_matches(ret, EIO), if (mustfix_fsck_err_on(bch2_err_matches(ret, EIO),
trans, btree_node_read_error, trans, btree_node_read_error,
"Topology repair: unreadable btree node at\n" "Topology repair: unreadable btree node at\n%s",
" %s",
buf.buf)) { buf.buf)) {
bch2_btree_node_evict(trans, cur_k.k); bch2_btree_node_evict(trans, cur_k.k);
cur = NULL; cur = NULL;
@ -612,7 +611,7 @@ static int bch2_gc_mark_key(struct btree_trans *trans, enum btree_id btree_id,
if (fsck_err_on(btree_id != BTREE_ID_accounting && if (fsck_err_on(btree_id != BTREE_ID_accounting &&
k.k->bversion.lo > atomic64_read(&c->key_version), k.k->bversion.lo > atomic64_read(&c->key_version),
trans, bkey_version_in_future, trans, bkey_version_in_future,
"key version number higher than recorded %llu\n %s", "key version number higher than recorded %llu\n%s",
atomic64_read(&c->key_version), atomic64_read(&c->key_version),
(bch2_bkey_val_to_text(&buf, c, k), buf.buf))) (bch2_bkey_val_to_text(&buf, c, k), buf.buf)))
atomic64_set(&c->key_version, k.k->bversion.lo); atomic64_set(&c->key_version, k.k->bversion.lo);
@ -620,7 +619,7 @@ static int bch2_gc_mark_key(struct btree_trans *trans, enum btree_id btree_id,
if (mustfix_fsck_err_on(level && !bch2_dev_btree_bitmap_marked(c, k), if (mustfix_fsck_err_on(level && !bch2_dev_btree_bitmap_marked(c, k),
trans, btree_bitmap_not_marked, trans, btree_bitmap_not_marked,
"btree ptr not marked in member info btree allocated bitmap\n %s", "btree ptr not marked in member info btree allocated bitmap\n%s",
(printbuf_reset(&buf), (printbuf_reset(&buf),
bch2_bkey_val_to_text(&buf, c, k), bch2_bkey_val_to_text(&buf, c, k),
buf.buf))) { buf.buf))) {

View file

@ -525,8 +525,6 @@ static void btree_err_msg(struct printbuf *out, struct bch_fs *c,
prt_printf(out, "at btree "); prt_printf(out, "at btree ");
bch2_btree_pos_to_text(out, c, b); bch2_btree_pos_to_text(out, c, b);
printbuf_indent_add(out, 2);
prt_printf(out, "\nnode offset %u/%u", prt_printf(out, "\nnode offset %u/%u",
b->written, btree_ptr_sectors_written(bkey_i_to_s_c(&b->key))); b->written, btree_ptr_sectors_written(bkey_i_to_s_c(&b->key)));
if (i) if (i)
@ -817,7 +815,7 @@ static int validate_bset(struct bch_fs *c, struct bch_dev *ca,
-BCH_ERR_btree_node_read_err_bad_node, -BCH_ERR_btree_node_read_err_bad_node,
c, ca, b, i, NULL, c, ca, b, i, NULL,
btree_node_bad_format, btree_node_bad_format,
"invalid bkey format: %s\n %s", buf1.buf, "invalid bkey format: %s\n%s", buf1.buf,
(printbuf_reset(&buf2), (printbuf_reset(&buf2),
bch2_bkey_format_to_text(&buf2, &bn->format), buf2.buf)); bch2_bkey_format_to_text(&buf2, &bn->format), buf2.buf));
printbuf_reset(&buf1); printbuf_reset(&buf1);

View file

@ -97,13 +97,13 @@ int bch2_btree_node_check_topology(struct btree_trans *trans, struct btree *b)
bch2_topology_error(c); bch2_topology_error(c);
printbuf_reset(&buf); printbuf_reset(&buf);
prt_str(&buf, "end of prev node doesn't match start of next node\n in "); prt_str(&buf, "end of prev node doesn't match start of next node\nin ");
bch2_btree_id_level_to_text(&buf, b->c.btree_id, b->c.level); bch2_btree_id_level_to_text(&buf, b->c.btree_id, b->c.level);
prt_str(&buf, " node "); prt_str(&buf, " node ");
bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&b->key)); bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&b->key));
prt_str(&buf, "\n prev "); prt_str(&buf, "\nprev ");
bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(prev.k)); bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(prev.k));
prt_str(&buf, "\n next "); prt_str(&buf, "\nnext ");
bch2_bkey_val_to_text(&buf, c, k); bch2_bkey_val_to_text(&buf, c, k);
log_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);
@ -118,7 +118,7 @@ int bch2_btree_node_check_topology(struct btree_trans *trans, struct btree *b)
bch2_topology_error(c); bch2_topology_error(c);
printbuf_reset(&buf); printbuf_reset(&buf);
prt_str(&buf, "empty interior node\n in "); prt_str(&buf, "empty interior node\nin ");
bch2_btree_id_level_to_text(&buf, b->c.btree_id, b->c.level); bch2_btree_id_level_to_text(&buf, b->c.btree_id, b->c.level);
prt_str(&buf, " node "); prt_str(&buf, " node ");
bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&b->key)); bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&b->key));
@ -129,11 +129,11 @@ int bch2_btree_node_check_topology(struct btree_trans *trans, struct btree *b)
bch2_topology_error(c); bch2_topology_error(c);
printbuf_reset(&buf); printbuf_reset(&buf);
prt_str(&buf, "last child node doesn't end at end of parent node\n in "); prt_str(&buf, "last child node doesn't end at end of parent node\nin ");
bch2_btree_id_level_to_text(&buf, b->c.btree_id, b->c.level); bch2_btree_id_level_to_text(&buf, b->c.btree_id, b->c.level);
prt_str(&buf, " node "); prt_str(&buf, " node ");
bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&b->key)); bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&b->key));
prt_str(&buf, "\n last key "); prt_str(&buf, "\nlast key ");
bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(prev.k)); bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(prev.k));
log_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);

View file

@ -646,7 +646,7 @@ static int bch2_disk_accounting_validate_late(struct btree_trans *trans,
if (fsck_err_on(!bch2_replicas_marked_locked(c, &r.e), if (fsck_err_on(!bch2_replicas_marked_locked(c, &r.e),
trans, accounting_replicas_not_marked, trans, accounting_replicas_not_marked,
"accounting not marked in superblock replicas\n %s", "accounting not marked in superblock replicas\n%s",
(printbuf_reset(&buf), (printbuf_reset(&buf),
bch2_accounting_key_to_text(&buf, &acc), bch2_accounting_key_to_text(&buf, &acc),
buf.buf))) { buf.buf))) {
@ -676,7 +676,7 @@ static int bch2_disk_accounting_validate_late(struct btree_trans *trans,
return ret; return ret;
invalid_device: invalid_device:
if (fsck_err(trans, accounting_to_invalid_device, if (fsck_err(trans, accounting_to_invalid_device,
"accounting entry points to invalid device %i\n %s", "accounting entry points to invalid device %i\n%s",
invalid_dev, invalid_dev,
(printbuf_reset(&buf), (printbuf_reset(&buf),
bch2_accounting_key_to_text(&buf, &acc), bch2_accounting_key_to_text(&buf, &acc),

View file

@ -320,7 +320,7 @@ static int mark_stripe_bucket(struct btree_trans *trans,
if (flags & BTREE_TRIGGER_gc) { if (flags & BTREE_TRIGGER_gc) {
struct bucket *g = gc_bucket(ca, bucket.offset); struct bucket *g = gc_bucket(ca, bucket.offset);
if (bch2_fs_inconsistent_on(!g, c, "reference to invalid bucket on device %u\n %s", if (bch2_fs_inconsistent_on(!g, c, "reference to invalid bucket on device %u\n%s",
ptr->dev, ptr->dev,
(bch2_bkey_val_to_text(&buf, c, s.s_c), buf.buf))) { (bch2_bkey_val_to_text(&buf, c, s.s_c), buf.buf))) {
ret = -BCH_ERR_mark_stripe; ret = -BCH_ERR_mark_stripe;

View file

@ -305,6 +305,13 @@ int __bch2_fsck_err(struct bch_fs *c,
bch2_sb_error_count(c, err); bch2_sb_error_count(c, err);
printbuf_indent_add_nextline(out, 2);
#ifdef BCACHEFS_LOG_PREFIX
if (strncmp(fmt, "bcachefs", 8))
prt_printf(out, bch2_log_msg(c, ""));
#endif
va_start(args, fmt); va_start(args, fmt);
prt_vprintf(out, fmt, args); prt_vprintf(out, fmt, args);
va_end(args); va_end(args);
@ -354,11 +361,6 @@ int __bch2_fsck_err(struct bch_fs *c,
s->nr++; s->nr++;
} }
#ifdef BCACHEFS_LOG_PREFIX
if (!strncmp(fmt, "bcachefs:", 9))
prt_printf(out, bch2_log_msg(c, ""));
#endif
if ((flags & FSCK_AUTOFIX) && if ((flags & FSCK_AUTOFIX) &&
(c->opts.errors == BCH_ON_ERROR_continue || (c->opts.errors == BCH_ON_ERROR_continue ||
c->opts.errors == BCH_ON_ERROR_fix_safe)) { c->opts.errors == BCH_ON_ERROR_fix_safe)) {
@ -435,6 +437,15 @@ int __bch2_fsck_err(struct bch_fs *c,
print = true; print = true;
} }
print: print:
prt_newline(out);
if (inconsistent)
bch2_inconsistent_error(c);
else if (exiting)
prt_printf(out, "Unable to continue, halting\n");
else if (suppressing)
prt_printf(out, "Ratelimiting new instances of previous error\n");
if (print) { if (print) {
if (bch2_fs_stdio_redirect(c)) if (bch2_fs_stdio_redirect(c))
bch2_print(c, "%s\n", out->buf); bch2_print(c, "%s\n", out->buf);
@ -442,11 +453,6 @@ int __bch2_fsck_err(struct bch_fs *c,
bch2_print_string_as_lines(KERN_ERR, out->buf); bch2_print_string_as_lines(KERN_ERR, out->buf);
} }
if (exiting)
bch_err(c, "Unable to continue, halting");
else if (suppressing)
bch_err(c, "Ratelimiting new instances of previous error");
if (s) if (s)
s->ret = ret; s->ret = ret;
@ -514,7 +520,7 @@ int __bch2_bkey_fsck_err(struct bch_fs *c,
prt_printf(&buf, " level=%u: ", from.level); prt_printf(&buf, " level=%u: ", from.level);
bch2_bkey_val_to_text(&buf, c, k); bch2_bkey_val_to_text(&buf, c, k);
prt_str(&buf, "\n "); prt_newline(&buf);
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
@ -536,7 +542,7 @@ void bch2_flush_fsck_errs(struct bch_fs *c)
list_for_each_entry_safe(s, n, &c->fsck_error_msgs, list) { list_for_each_entry_safe(s, n, &c->fsck_error_msgs, list) {
if (s->ratelimited && s->last_msg) if (s->ratelimited && s->last_msg)
bch_err(c, "Saw %llu errors like:\n %s", s->nr, s->last_msg); bch_err(c, "Saw %llu errors like:\n %s", s->nr, s->last_msg);
list_del(&s->list); list_del(&s->list);
kfree(s->last_msg); kfree(s->last_msg);

View file

@ -673,7 +673,7 @@ static struct bch_inode_info *bch2_lookup_trans(struct btree_trans *trans,
* back to this dirent * back to this dirent
*/ */
bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT), bch2_fs_inconsistent_on(bch2_err_matches(ret, ENOENT),
c, "dirent to missing inode:\n %s", c, "dirent to missing inode:\n%s",
(bch2_bkey_val_to_text(&buf, c, d.s_c), buf.buf)); (bch2_bkey_val_to_text(&buf, c, d.s_c), buf.buf));
if (ret) if (ret)
goto err; goto err;

View file

@ -1421,14 +1421,14 @@ static int check_key_has_inode(struct btree_trans *trans,
if (fsck_err_on(!i, if (fsck_err_on(!i,
trans, key_in_missing_inode, trans, key_in_missing_inode,
"key in missing inode:\n %s", "key in missing inode:\n%s",
(printbuf_reset(&buf), (printbuf_reset(&buf),
bch2_bkey_val_to_text(&buf, c, k), buf.buf))) bch2_bkey_val_to_text(&buf, c, k), buf.buf)))
goto delete; goto delete;
if (fsck_err_on(i && !btree_matches_i_mode(iter->btree_id, i->inode.bi_mode), if (fsck_err_on(i && !btree_matches_i_mode(iter->btree_id, i->inode.bi_mode),
trans, key_in_wrong_inode_type, trans, key_in_wrong_inode_type,
"key for wrong inode mode %o:\n %s", "key for wrong inode mode %o:\n%s",
i->inode.bi_mode, i->inode.bi_mode,
(printbuf_reset(&buf), (printbuf_reset(&buf),
bch2_bkey_val_to_text(&buf, c, k), buf.buf))) bch2_bkey_val_to_text(&buf, c, k), buf.buf)))
@ -1571,13 +1571,13 @@ static int overlapping_extents_found(struct btree_trans *trans,
if (ret) if (ret)
goto err; goto err;
prt_str(&buf, "\n "); prt_newline(&buf);
bch2_bkey_val_to_text(&buf, c, k1); bch2_bkey_val_to_text(&buf, c, k1);
if (!bpos_eq(pos1, k1.k->p)) { if (!bpos_eq(pos1, k1.k->p)) {
prt_str(&buf, "\n wanted\n "); prt_str(&buf, "\nwanted\n ");
bch2_bpos_to_text(&buf, pos1); bch2_bpos_to_text(&buf, pos1);
prt_str(&buf, "\n "); prt_str(&buf, "\n");
bch2_bkey_to_text(&buf, &pos2); bch2_bkey_to_text(&buf, &pos2);
bch_err(c, "%s: error finding first overlapping extent when repairing, got%s", bch_err(c, "%s: error finding first overlapping extent when repairing, got%s",
@ -1600,7 +1600,7 @@ static int overlapping_extents_found(struct btree_trans *trans,
break; break;
} }
prt_str(&buf, "\n "); prt_newline(&buf);
bch2_bkey_val_to_text(&buf, c, k2); bch2_bkey_val_to_text(&buf, c, k2);
if (bpos_gt(k2.k->p, pos2.p) || if (bpos_gt(k2.k->p, pos2.p) ||
@ -1611,7 +1611,7 @@ static int overlapping_extents_found(struct btree_trans *trans,
goto err; goto err;
} }
prt_printf(&buf, "\n overwriting %s extent", prt_printf(&buf, "\noverwriting %s extent",
pos1.snapshot >= pos2.p.snapshot ? "first" : "second"); pos1.snapshot >= pos2.p.snapshot ? "first" : "second");
if (fsck_err(trans, extent_overlapping, if (fsck_err(trans, extent_overlapping,
@ -1784,7 +1784,7 @@ static int check_extent(struct btree_trans *trans, struct btree_iter *iter,
if (fsck_err_on(k.k->p.offset > round_up(i->inode.bi_size, block_bytes(c)) >> 9 && if (fsck_err_on(k.k->p.offset > round_up(i->inode.bi_size, block_bytes(c)) >> 9 &&
!bkey_extent_is_reservation(k), !bkey_extent_is_reservation(k),
trans, extent_past_end_of_inode, trans, extent_past_end_of_inode,
"extent type past end of inode %llu:%u, i_size %llu\n %s", "extent type past end of inode %llu:%u, i_size %llu\n%s",
i->inode.bi_inum, i->snapshot, i->inode.bi_size, i->inode.bi_inum, i->snapshot, i->inode.bi_size,
(bch2_bkey_val_to_text(&buf, c, k), buf.buf))) { (bch2_bkey_val_to_text(&buf, c, k), buf.buf))) {
struct btree_iter iter2; struct btree_iter iter2;

View file

@ -214,12 +214,12 @@ static int journal_entry_add(struct bch_fs *c, struct bch_dev *ca,
fsck_err_on(same_device, fsck_err_on(same_device,
c, journal_entry_dup_same_device, c, journal_entry_dup_same_device,
"duplicate journal entry on same device\n %s", "duplicate journal entry on same device\n%s",
buf.buf); buf.buf);
fsck_err_on(not_identical, fsck_err_on(not_identical,
c, journal_entry_replicas_data_mismatch, c, journal_entry_replicas_data_mismatch,
"found duplicate but non identical journal entries\n %s", "found duplicate but non identical journal entries\n%s",
buf.buf); buf.buf);
if (entry_ptr.csum_good && !identical) if (entry_ptr.csum_good && !identical)
@ -1371,8 +1371,8 @@ int bch2_journal_read(struct bch_fs *c,
missing_end = seq - 1; missing_end = seq - 1;
fsck_err(c, journal_entries_missing, fsck_err(c, journal_entries_missing,
"journal entries %llu-%llu missing! (replaying %llu-%llu)\n" "journal entries %llu-%llu missing! (replaying %llu-%llu)\n"
" prev at %s\n" "prev at %s\n"
" next at %s, continue?", "next at %s, continue?",
missing_start, missing_end, missing_start, missing_end,
*last_seq, *blacklist_seq - 1, *last_seq, *blacklist_seq - 1,
buf1.buf, buf2.buf); buf1.buf, buf2.buf);
@ -1426,7 +1426,7 @@ int bch2_journal_read(struct bch_fs *c,
!bch2_replicas_marked(c, &replicas.e) && !bch2_replicas_marked(c, &replicas.e) &&
(le64_to_cpu(i->j.seq) == *last_seq || (le64_to_cpu(i->j.seq) == *last_seq ||
fsck_err(c, journal_entry_replicas_not_marked, fsck_err(c, journal_entry_replicas_not_marked,
"superblock not marked as containing replicas for journal entry %llu\n %s", "superblock not marked as containing replicas for journal entry %llu\n%s",
le64_to_cpu(i->j.seq), buf.buf))) { le64_to_cpu(i->j.seq), buf.buf))) {
ret = bch2_mark_replicas(c, &replicas.e); ret = bch2_mark_replicas(c, &replicas.e);
if (ret) if (ret)

View file

@ -101,8 +101,7 @@ int bch2_lru_check_set(struct btree_trans *trans,
goto err; goto err;
if (fsck_err(trans, alloc_key_to_missing_lru_entry, if (fsck_err(trans, alloc_key_to_missing_lru_entry,
"missing %s lru entry\n" "missing %s lru entry\n%s",
" %s",
bch2_lru_types[lru_type(lru_k)], bch2_lru_types[lru_type(lru_k)],
(bch2_bkey_val_to_text(&buf, c, referring_k), buf.buf))) { (bch2_bkey_val_to_text(&buf, c, referring_k), buf.buf))) {
ret = bch2_lru_set(trans, lru_id, dev_bucket, time); ret = bch2_lru_set(trans, lru_id, dev_bucket, time);
@ -190,8 +189,8 @@ static int bch2_check_lru_key(struct btree_trans *trans,
if (fsck_err(trans, lru_entry_bad, if (fsck_err(trans, lru_entry_bad,
"incorrect lru entry: lru %s time %llu\n" "incorrect lru entry: lru %s time %llu\n"
" %s\n" "%s\n"
" for %s", "for %s",
bch2_lru_types[type], bch2_lru_types[type],
lru_pos_time(lru_k.k->p), lru_pos_time(lru_k.k->p),
(bch2_bkey_val_to_text(&buf1, c, lru_k), buf1.buf), (bch2_bkey_val_to_text(&buf1, c, lru_k), buf1.buf),

View file

@ -700,9 +700,9 @@ static int bch2_check_dirent_inode_dirent(struct btree_trans *trans,
if (bch2_inode_should_have_single_bp(target) && if (bch2_inode_should_have_single_bp(target) &&
!fsck_err(trans, inode_wrong_backpointer, !fsck_err(trans, inode_wrong_backpointer,
"dirent points to inode that does not point back:\n %s", "dirent points to inode that does not point back:\n%s",
(bch2_bkey_val_to_text(&buf, c, d.s_c), (bch2_bkey_val_to_text(&buf, c, d.s_c),
prt_printf(&buf, "\n "), prt_newline(&buf),
bch2_inode_unpacked_to_text(&buf, target), bch2_inode_unpacked_to_text(&buf, target),
buf.buf))) buf.buf)))
goto err; goto err;

View file

@ -276,6 +276,25 @@ void bch2_printbuf_indent_add(struct printbuf *buf, unsigned spaces)
buf->has_indent_or_tabstops = true; buf->has_indent_or_tabstops = true;
} }
/**
* bch2_printbuf_indent_add_nextline() - add to the current indent level for
* subsequent lines
*
* @buf: printbuf to control
* @spaces: number of spaces to add to the current indent level
*
* Subsequent lines - not the current line - will be indented by @spaces more
* spaces.
*/
void bch2_printbuf_indent_add_nextline(struct printbuf *buf, unsigned spaces)
{
if (WARN_ON_ONCE(buf->indent + spaces < buf->indent))
spaces = 0;
buf->indent += spaces;
buf->has_indent_or_tabstops = true;
}
/** /**
* bch2_printbuf_indent_sub() - subtract from the current indent level * bch2_printbuf_indent_sub() - subtract from the current indent level
* *

View file

@ -112,6 +112,7 @@ void bch2_printbuf_tabstop_pop(struct printbuf *);
int bch2_printbuf_tabstop_push(struct printbuf *, unsigned); int bch2_printbuf_tabstop_push(struct printbuf *, unsigned);
void bch2_printbuf_indent_add(struct printbuf *, unsigned); void bch2_printbuf_indent_add(struct printbuf *, unsigned);
void bch2_printbuf_indent_add_nextline(struct printbuf *, unsigned);
void bch2_printbuf_indent_sub(struct printbuf *, unsigned); void bch2_printbuf_indent_sub(struct printbuf *, unsigned);
void bch2_prt_newline(struct printbuf *); void bch2_prt_newline(struct printbuf *);

View file

@ -193,10 +193,10 @@ static int bch2_indirect_extent_missing_error(struct btree_trans *trans,
if (ret) if (ret)
goto err; goto err;
prt_printf(&buf, "-%llu\n ", (missing_pos.offset + (missing_end - missing_start)) << 9); prt_printf(&buf, "-%llu\n", (missing_pos.offset + (missing_end - missing_start)) << 9);
bch2_bkey_val_to_text(&buf, c, p.s_c); bch2_bkey_val_to_text(&buf, c, p.s_c);
prt_printf(&buf, "\n missing reflink btree range %llu-%llu", prt_printf(&buf, "\nmissing reflink btree range %llu-%llu",
missing_start, missing_end); missing_start, missing_end);
if (fsck_err(trans, reflink_p_to_missing_reflink_v, "%s", buf.buf)) { if (fsck_err(trans, reflink_p_to_missing_reflink_v, "%s", buf.buf)) {
@ -323,10 +323,10 @@ static int trans_trigger_reflink_p_segment(struct btree_trans *trans,
__le64 *refcount = bkey_refcount(bkey_i_to_s(new)); __le64 *refcount = bkey_refcount(bkey_i_to_s(new));
if (!*refcount && (flags & BTREE_TRIGGER_overwrite)) { if (!*refcount && (flags & BTREE_TRIGGER_overwrite)) {
bch2_bkey_val_to_text(&buf, c, p.s_c); bch2_bkey_val_to_text(&buf, c, p.s_c);
prt_printf(&buf, "\n "); prt_newline(&buf);
bch2_bkey_val_to_text(&buf, c, k); bch2_bkey_val_to_text(&buf, c, k);
log_fsck_err(trans, reflink_refcount_underflow, log_fsck_err(trans, reflink_refcount_underflow,
"indirect extent refcount underflow while marking\n %s", "indirect extent refcount underflow while marking\n%s",
buf.buf); buf.buf);
goto next; goto next;
} }
@ -795,8 +795,8 @@ static int bch2_gc_write_reflink_key(struct btree_trans *trans,
if (fsck_err_on(r->refcount != le64_to_cpu(*refcount), if (fsck_err_on(r->refcount != le64_to_cpu(*refcount),
trans, reflink_v_refcount_wrong, trans, reflink_v_refcount_wrong,
"reflink key has wrong refcount:\n" "reflink key has wrong refcount:\n"
" %s\n" "%s\n"
" should be %u", "should be %u",
(bch2_bkey_val_to_text(&buf, c, k), buf.buf), (bch2_bkey_val_to_text(&buf, c, k), buf.buf),
r->refcount)) { r->refcount)) {
struct bkey_i *new = bch2_bkey_make_mut_noupdate(trans, k); struct bkey_i *new = bch2_bkey_make_mut_noupdate(trans, k);

View file

@ -485,7 +485,7 @@ static int check_snapshot_tree(struct btree_trans *trans,
root_id != bch2_snapshot_root(c, root_id) || root_id != bch2_snapshot_root(c, root_id) ||
st.k->p.offset != le32_to_cpu(s.tree), st.k->p.offset != le32_to_cpu(s.tree),
trans, snapshot_tree_to_missing_snapshot, trans, snapshot_tree_to_missing_snapshot,
"snapshot tree points to missing/incorrect snapshot:\n %s", "snapshot tree points to missing/incorrect snapshot:\n%s",
(bch2_bkey_val_to_text(&buf, c, st.s_c), (bch2_bkey_val_to_text(&buf, c, st.s_c),
prt_newline(&buf), prt_newline(&buf),
ret ret
@ -505,19 +505,19 @@ static int check_snapshot_tree(struct btree_trans *trans,
if (fsck_err_on(ret, if (fsck_err_on(ret,
trans, snapshot_tree_to_missing_subvol, trans, snapshot_tree_to_missing_subvol,
"snapshot tree points to missing subvolume:\n %s", "snapshot tree points to missing subvolume:\n%s",
(printbuf_reset(&buf), (printbuf_reset(&buf),
bch2_bkey_val_to_text(&buf, c, st.s_c), buf.buf)) || bch2_bkey_val_to_text(&buf, c, st.s_c), buf.buf)) ||
fsck_err_on(!bch2_snapshot_is_ancestor(c, fsck_err_on(!bch2_snapshot_is_ancestor(c,
le32_to_cpu(subvol.snapshot), le32_to_cpu(subvol.snapshot),
root_id), root_id),
trans, snapshot_tree_to_wrong_subvol, trans, snapshot_tree_to_wrong_subvol,
"snapshot tree points to subvolume that does not point to snapshot in this tree:\n %s", "snapshot tree points to subvolume that does not point to snapshot in this tree:\n%s",
(printbuf_reset(&buf), (printbuf_reset(&buf),
bch2_bkey_val_to_text(&buf, c, st.s_c), buf.buf)) || bch2_bkey_val_to_text(&buf, c, st.s_c), buf.buf)) ||
fsck_err_on(BCH_SUBVOLUME_SNAP(&subvol), fsck_err_on(BCH_SUBVOLUME_SNAP(&subvol),
trans, snapshot_tree_to_snapshot_subvol, trans, snapshot_tree_to_snapshot_subvol,
"snapshot tree points to snapshot subvolume:\n %s", "snapshot tree points to snapshot subvolume:\n%s",
(printbuf_reset(&buf), (printbuf_reset(&buf),
bch2_bkey_val_to_text(&buf, c, st.s_c), buf.buf))) { bch2_bkey_val_to_text(&buf, c, st.s_c), buf.buf))) {
struct bkey_i_snapshot_tree *u; struct bkey_i_snapshot_tree *u;
@ -756,7 +756,7 @@ static int check_snapshot(struct btree_trans *trans,
} else { } else {
if (fsck_err_on(s.subvol, if (fsck_err_on(s.subvol,
trans, snapshot_should_not_have_subvol, trans, snapshot_should_not_have_subvol,
"snapshot should not point to subvol:\n %s", "snapshot should not point to subvol:\n%s",
(bch2_bkey_val_to_text(&buf, c, k), buf.buf))) { (bch2_bkey_val_to_text(&buf, c, k), buf.buf))) {
u = bch2_bkey_make_mut_typed(trans, iter, &k, 0, snapshot); u = bch2_bkey_make_mut_typed(trans, iter, &k, 0, snapshot);
ret = PTR_ERR_OR_ZERO(u); ret = PTR_ERR_OR_ZERO(u);
@ -774,7 +774,7 @@ static int check_snapshot(struct btree_trans *trans,
if (fsck_err_on(!ret, if (fsck_err_on(!ret,
trans, snapshot_to_bad_snapshot_tree, trans, snapshot_to_bad_snapshot_tree,
"snapshot points to missing/incorrect tree:\n %s", "snapshot points to missing/incorrect tree:\n%s",
(bch2_bkey_val_to_text(&buf, c, k), buf.buf))) { (bch2_bkey_val_to_text(&buf, c, k), buf.buf))) {
ret = snapshot_tree_ptr_repair(trans, iter, k, &s); ret = snapshot_tree_ptr_repair(trans, iter, k, &s);
if (ret) if (ret)
@ -786,7 +786,7 @@ static int check_snapshot(struct btree_trans *trans,
if (fsck_err_on(le32_to_cpu(s.depth) != real_depth, if (fsck_err_on(le32_to_cpu(s.depth) != real_depth,
trans, snapshot_bad_depth, trans, snapshot_bad_depth,
"snapshot with incorrect depth field, should be %u:\n %s", "snapshot with incorrect depth field, should be %u:\n%s",
real_depth, (bch2_bkey_val_to_text(&buf, c, k), buf.buf))) { real_depth, (bch2_bkey_val_to_text(&buf, c, k), buf.buf))) {
u = bch2_bkey_make_mut_typed(trans, iter, &k, 0, snapshot); u = bch2_bkey_make_mut_typed(trans, iter, &k, 0, snapshot);
ret = PTR_ERR_OR_ZERO(u); ret = PTR_ERR_OR_ZERO(u);
@ -803,7 +803,7 @@ static int check_snapshot(struct btree_trans *trans,
if (fsck_err_on(!ret, if (fsck_err_on(!ret,
trans, snapshot_bad_skiplist, trans, snapshot_bad_skiplist,
"snapshot with bad skiplist field:\n %s", "snapshot with bad skiplist field:\n%s",
(bch2_bkey_val_to_text(&buf, c, k), buf.buf))) { (bch2_bkey_val_to_text(&buf, c, k), buf.buf))) {
u = bch2_bkey_make_mut_typed(trans, iter, &k, 0, snapshot); u = bch2_bkey_make_mut_typed(trans, iter, &k, 0, snapshot);
ret = PTR_ERR_OR_ZERO(u); ret = PTR_ERR_OR_ZERO(u);

View file

@ -232,7 +232,7 @@ int __bch2_str_hash_check_key(struct btree_trans *trans,
goto out; goto out;
if (fsck_err(trans, hash_table_key_wrong_offset, if (fsck_err(trans, hash_table_key_wrong_offset,
"hash table key at wrong offset: btree %s inode %llu offset %llu, hashed to %llu\n %s", "hash table key at wrong offset: btree %s inode %llu offset %llu, hashed to %llu\n%s",
bch2_btree_id_str(desc->btree_id), hash_k.k->p.inode, hash_k.k->p.offset, hash, bch2_btree_id_str(desc->btree_id), hash_k.k->p.inode, hash_k.k->p.offset, hash,
(printbuf_reset(&buf), (printbuf_reset(&buf),
bch2_bkey_val_to_text(&buf, c, hash_k), buf.buf))) { bch2_bkey_val_to_text(&buf, c, hash_k), buf.buf))) {

View file

@ -94,6 +94,7 @@ do { \
#define printbuf_tabstop_push(_buf, _n) bch2_printbuf_tabstop_push(_buf, _n) #define printbuf_tabstop_push(_buf, _n) bch2_printbuf_tabstop_push(_buf, _n)
#define printbuf_indent_add(_out, _n) bch2_printbuf_indent_add(_out, _n) #define printbuf_indent_add(_out, _n) bch2_printbuf_indent_add(_out, _n)
#define printbuf_indent_add_nextline(_out, _n) bch2_printbuf_indent_add_nextline(_out, _n)
#define printbuf_indent_sub(_out, _n) bch2_printbuf_indent_sub(_out, _n) #define printbuf_indent_sub(_out, _n) bch2_printbuf_indent_sub(_out, _n)
#define prt_newline(_out) bch2_prt_newline(_out) #define prt_newline(_out) bch2_prt_newline(_out)