diff options
Diffstat (limited to 'libbcachefs/backpointers.c')
-rw-r--r-- | libbcachefs/backpointers.c | 41 |
1 files changed, 28 insertions, 13 deletions
diff --git a/libbcachefs/backpointers.c b/libbcachefs/backpointers.c index 5a46b25b..029b1ec1 100644 --- a/libbcachefs/backpointers.c +++ b/libbcachefs/backpointers.c @@ -492,7 +492,7 @@ static void backpointer_not_found(struct btree_trans *trans, prt_printf(&buf, "\n "); bch2_bkey_val_to_text(&buf, c, k); if (!test_bit(BCH_FS_CHECK_BACKPOINTERS_DONE, &c->flags)) - bch_err(c, "%s", buf.buf); + bch_err_ratelimited(c, "%s", buf.buf); else bch2_trans_inconsistent(trans, "%s", buf.buf); @@ -526,9 +526,21 @@ struct bkey_s_c bch2_backpointer_get_key(struct btree_trans *trans, if (extent_matches_bp(c, bp.btree_id, bp.level, k, bucket, bp)) return k; - backpointer_not_found(trans, bucket, bp_offset, bp, k, "extent"); - bch2_trans_iter_exit(trans, iter); + + if (bp.level) { + /* + * If a backpointer for a btree node wasn't found, it may be + * because it was overwritten by a new btree node that hasn't + * been written out yet - backpointer_get_node() checks for + * this: + */ + bch2_backpointer_get_node(trans, iter, bucket, bp_offset, bp); + bch2_trans_iter_exit(trans, iter); + return bkey_s_c_null; + } + + backpointer_not_found(trans, bucket, bp_offset, bp, k, "extent"); return bkey_s_c_null; } @@ -540,7 +552,6 @@ struct btree *bch2_backpointer_get_node(struct btree_trans *trans, { struct bch_fs *c = trans->c; struct btree *b; - struct bkey_s_c k; BUG_ON(!bp.level); @@ -551,22 +562,24 @@ struct btree *bch2_backpointer_get_node(struct btree_trans *trans, bp.level - 1, 0); b = bch2_btree_iter_peek_node(iter); - if (IS_ERR(b)) { - bch2_trans_iter_exit(trans, iter); - return b; - } + if (IS_ERR(b)) + goto err; if (extent_matches_bp(c, bp.btree_id, bp.level, bkey_i_to_s_c(&b->key), bucket, bp)) return b; - if (!btree_node_will_make_reachable(b)) - backpointer_not_found(trans, bucket, bp_offset, - bp, k, "btree node"); - + if (btree_node_will_make_reachable(b)) { + b = ERR_PTR(-BCH_ERR_backpointer_to_overwritten_btree_node); + } else { + backpointer_not_found(trans, bucket, bp_offset, bp, + bkey_i_to_s_c(&b->key), "btree node"); + b = NULL; + } +err: bch2_trans_iter_exit(trans, iter); - return NULL; + return b; } static int bch2_check_btree_backpointer(struct btree_trans *trans, struct btree_iter *bp_iter, @@ -829,6 +842,8 @@ static int check_one_backpointer(struct btree_trans *trans, k = bch2_backpointer_get_key(trans, &iter, bucket, *bp_offset, bp); ret = bkey_err(k); + if (ret == -BCH_ERR_backpointer_to_overwritten_btree_node) + return 0; if (ret) return ret; |