Commit c80f33b7 authored by Kent Overstreet's avatar Kent Overstreet
Browse files

bcachefs: New backpointers helpers



- bch2_backpointer_del()
- bch2_backpointer_maybe_flush()

Kill a bit of open coding and make sure we're properly handling the
btree write buffer.

Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 1ab00b6c
Loading
Loading
Loading
Loading
+45 −13
Original line number Diff line number Diff line
@@ -199,6 +199,22 @@ int bch2_bucket_backpointer_mod_nowritebuffer(struct btree_trans *trans,
	return ret;
}

static int bch2_backpointer_del(struct btree_trans *trans, struct bpos pos)
{
	return likely(!bch2_backpointers_no_use_write_buffer)
	       ? bch2_btree_delete_at_buffered(trans, BTREE_ID_backpointers, pos)
	       : bch2_btree_delete(trans, BTREE_ID_backpointers, pos, 0);
}

static int bch2_backpointers_maybe_flush(struct btree_trans *trans,
					 struct bkey_s_c visiting_k,
					 struct bkey_buf *last_flushed)
{
	return likely(!bch2_backpointers_no_use_write_buffer)
		? bch2_btree_write_buffer_maybe_flush(trans, visiting_k, last_flushed)
		: 0;
}

static void backpointer_target_not_found(struct btree_trans *trans,
					 struct bkey_s_c_backpointer bp,
					 struct bkey_s_c target_k)
@@ -300,9 +316,12 @@ struct btree *bch2_backpointer_get_node(struct btree_trans *trans,
	return b;
}

static int bch2_check_btree_backpointer(struct btree_trans *trans, struct btree_iter *bp_iter,
					struct bkey_s_c k)
static int bch2_check_backpointer_has_valid_bucket(struct btree_trans *trans, struct bkey_s_c k,
						   struct bkey_buf *last_flushed)
{
	if (k.k->type != KEY_TYPE_backpointer)
		return 0;

	struct bch_fs *c = trans->c;
	struct btree_iter alloc_iter = { NULL };
	struct bkey_s_c alloc_k;
@@ -311,10 +330,14 @@ static int bch2_check_btree_backpointer(struct btree_trans *trans, struct btree_

	struct bpos bucket;
	if (!bp_pos_to_bucket_nodev_noerror(c, k.k->p, &bucket)) {
		ret = bch2_backpointers_maybe_flush(trans, k, last_flushed);
		if (ret)
			goto out;

		if (fsck_err(trans, backpointer_to_missing_device,
			     "backpointer for missing device:\n%s",
			     (bch2_bkey_val_to_text(&buf, c, k), buf.buf)))
			ret = bch2_btree_delete_at(trans, bp_iter, 0);
			ret = bch2_backpointer_del(trans, k.k->p);
		goto out;
	}

@@ -323,13 +346,16 @@ static int bch2_check_btree_backpointer(struct btree_trans *trans, struct btree_
	if (ret)
		goto out;

	if (fsck_err_on(alloc_k.k->type != KEY_TYPE_alloc_v4,
			trans, backpointer_to_missing_alloc,
	if (alloc_k.k->type != KEY_TYPE_alloc_v4) {
		ret = bch2_backpointers_maybe_flush(trans, k, last_flushed);
		if (ret)
			goto out;

		if (fsck_err(trans, backpointer_to_missing_alloc,
			     "backpointer for nonexistent alloc key: %llu:%llu:0\n%s",
			     alloc_iter.pos.inode, alloc_iter.pos.offset,
			(bch2_bkey_val_to_text(&buf, c, k), buf.buf))) {
		ret = bch2_btree_delete_at(trans, bp_iter, 0);
		goto out;
			     (bch2_bkey_val_to_text(&buf, c, k), buf.buf)))
			ret = bch2_backpointer_del(trans, k.k->p);
	}
out:
fsck_err:
@@ -341,11 +367,17 @@ static int bch2_check_btree_backpointer(struct btree_trans *trans, struct btree_
/* verify that every backpointer has a corresponding alloc key */
int bch2_check_btree_backpointers(struct bch_fs *c)
{
	struct bkey_buf last_flushed;
	bch2_bkey_buf_init(&last_flushed);
	bkey_init(&last_flushed.k->k);

	int ret = bch2_trans_run(c,
		for_each_btree_key_commit(trans, iter,
			BTREE_ID_backpointers, POS_MIN, 0, k,
			NULL, NULL, BCH_TRANS_COMMIT_no_enospc,
		  bch2_check_btree_backpointer(trans, &iter, k)));
		  bch2_check_backpointer_has_valid_bucket(trans, k, &last_flushed)));

	bch2_bkey_buf_exit(&last_flushed, c);
	bch_err_fn(c, ret);
	return ret;
}
@@ -874,7 +906,7 @@ static int check_one_backpointer(struct btree_trans *trans,
		return ret;

	if (!k.k) {
		ret = bch2_btree_write_buffer_maybe_flush(trans, bp.s_c, last_flushed);
		ret = bch2_backpointers_maybe_flush(trans, bp.s_c, last_flushed);
		if (ret)
			goto out;

@@ -882,7 +914,7 @@ static int check_one_backpointer(struct btree_trans *trans,
			     "backpointer for missing %s\n  %s",
			     bp.v->level ? "btree node" : "extent",
			     (bch2_bkey_val_to_text(&buf, c, bp.s_c), buf.buf))) {
			ret = bch2_btree_delete_at_buffered(trans, BTREE_ID_backpointers, bp.k->p);
			ret = bch2_backpointer_del(trans, bp.k->p);
			goto out;
		}
	}