Commit 853960d0 authored by Kent Overstreet's avatar Kent Overstreet
Browse files

bcachefs: Simplify, fix bch2_backpointer_get_key()



 - backpointer_not_found() checks backpointers_no_use_write_buffer, no
   need to do it inbackpointer_get_key().

 - always use backpointer_get_node() for pointers to nodes:
   backpointer_get_key() was sometimes returning the key from the root
   node unlocked.

Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent daba90f2
Loading
Loading
Loading
Loading
+33 −44
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
#include "backpointers.h"
#include "btree_cache.h"
#include "btree_update.h"
#include "btree_update_interior.h"
#include "btree_write_buffer.h"
#include "error.h"

@@ -226,6 +227,11 @@ static void backpointer_not_found(struct btree_trans *trans,
	struct printbuf buf = PRINTBUF;
	struct bpos bucket = bp_pos_to_bucket(c, bp_pos);

	/*
	 * If we're using the btree write buffer, the backpointer we were
	 * looking at may have already been deleted - failure to find what it
	 * pointed to is not an error:
	 */
	if (likely(!bch2_backpointers_no_use_write_buffer))
		return;

@@ -256,16 +262,15 @@ struct bkey_s_c bch2_backpointer_get_key(struct btree_trans *trans,
					 struct bch_backpointer bp,
					 unsigned iter_flags)
{
	if (likely(!bp.level)) {
		struct bch_fs *c = trans->c;
	struct btree_root *r = bch2_btree_id_root(c, bp.btree_id);
		struct bpos bucket = bp_pos_to_bucket(c, bp_pos);
		struct bkey_s_c k;

		bch2_trans_node_iter_init(trans, iter,
					  bp.btree_id,
					  bp.pos,
				  0,
				  min(bp.level, r->level),
					  0, 0,
					  iter_flags);
		k = bch2_btree_iter_peek_slot(iter);
		if (bkey_err(k)) {
@@ -273,39 +278,21 @@ struct bkey_s_c bch2_backpointer_get_key(struct btree_trans *trans,
			return k;
		}

	if (bp.level == r->level + 1)
		k = bkey_i_to_s_c(&r->key);

		if (k.k && extent_matches_bp(c, bp.btree_id, bp.level, k, bucket, bp))
			return k;

		bch2_trans_iter_exit(trans, iter);
		backpointer_not_found(trans, bp_pos, bp, k);
		return bkey_s_c_null;
	} else {
		struct btree *b = bch2_backpointer_get_node(trans, iter, bp_pos, bp);

	if (unlikely(bch2_backpointers_no_use_write_buffer)) {
		if (bp.level) {
			struct btree *b;

			/*
			 * 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:
			 */
			b = bch2_backpointer_get_node(trans, iter, bp_pos, bp);
			if (!IS_ERR_OR_NULL(b))
				return bkey_i_to_s_c(&b->key);

		if (IS_ERR_OR_NULL(b)) {
			bch2_trans_iter_exit(trans, iter);

			if (IS_ERR(b))
				return bkey_s_c_err(PTR_ERR(b));
			return bkey_s_c_null;
			return IS_ERR(b) ? bkey_s_c_err(PTR_ERR(b)) : bkey_s_c_null;
		}

		backpointer_not_found(trans, bp_pos, bp, k);
		return bkey_i_to_s_c(&b->key);
	}

	return bkey_s_c_null;
}

struct btree *bch2_backpointer_get_node(struct btree_trans *trans,
@@ -329,6 +316,8 @@ struct btree *bch2_backpointer_get_node(struct btree_trans *trans,
	if (IS_ERR(b))
		goto err;

	BUG_ON(b->c.level != bp.level - 1);

	if (b && extent_matches_bp(c, bp.btree_id, bp.level,
				   bkey_i_to_s_c(&b->key),
				   bucket, bp))