Commit 968feb85 authored by Kent Overstreet's avatar Kent Overstreet
Browse files

bcachefs: Convert for_each_btree_node() to lockrestart_do()



for_each_btree_node() now works similarly to for_each_btree_key(), where
the loop body is passed as an argument to be passed to lockrestart_do().

This now calls trans_begin() on every loop iteration - which fixes an
SRCU warning in backpointers fsck.

Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 48d6cc1b
Loading
Loading
Loading
Loading
+5 −10
Original line number Diff line number Diff line
@@ -763,27 +763,22 @@ static int bch2_get_btree_in_memory_pos(struct btree_trans *trans,
	     btree < BTREE_ID_NR && !ret;
	     btree++) {
		unsigned depth = (BIT_ULL(btree) & btree_leaf_mask) ? 0 : 1;
		struct btree_iter iter;
		struct btree *b;

		if (!(BIT_ULL(btree) & btree_leaf_mask) &&
		    !(BIT_ULL(btree) & btree_interior_mask))
			continue;

		bch2_trans_begin(trans);

		__for_each_btree_node(trans, iter, btree,
		ret = __for_each_btree_node(trans, iter, btree,
				      btree == start.btree ? start.pos : POS_MIN,
				      0, depth, BTREE_ITER_prefetch, b, ret) {
				      0, depth, BTREE_ITER_prefetch, b, ({
			mem_may_pin -= btree_buf_bytes(b);
			if (mem_may_pin <= 0) {
				c->btree_cache.pinned_nodes_end = *end =
					BBPOS(btree, b->key.k.p);
				bch2_trans_iter_exit(trans, &iter);
				return 0;
			}
				break;
			}
		bch2_trans_iter_exit(trans, &iter);
			0;
		}));
	}

	return ret;
+1 −0
Original line number Diff line number Diff line
@@ -1900,6 +1900,7 @@ struct btree *bch2_btree_iter_peek_node(struct btree_iter *iter)
	goto out;
}

/* Only kept for -tools */
struct btree *bch2_btree_iter_peek_node_and_restart(struct btree_iter *iter)
{
	struct btree *b;
+27 −15
Original line number Diff line number Diff line
@@ -600,23 +600,35 @@ void bch2_trans_srcu_unlock(struct btree_trans *);

u32 bch2_trans_begin(struct btree_trans *);

/*
 * XXX
 * this does not handle transaction restarts from bch2_btree_iter_next_node()
 * correctly
 */
#define __for_each_btree_node(_trans, _iter, _btree_id, _start,			\
			      _locks_want, _depth, _flags, _b, _ret)	\
	for (bch2_trans_node_iter_init((_trans), &(_iter), (_btree_id),	\
			      _locks_want, _depth, _flags, _b, _do)		\
({										\
	bch2_trans_begin((_trans));						\
										\
	struct btree_iter _iter;						\
	bch2_trans_node_iter_init((_trans), &_iter, (_btree_id),		\
				  _start, _locks_want, _depth, _flags);		\
	     (_b) = bch2_btree_iter_peek_node_and_restart(&(_iter)),	\
	     !((_ret) = PTR_ERR_OR_ZERO(_b)) && (_b);			\
	     (_b) = bch2_btree_iter_next_node(&(_iter)))
	int _ret3 = 0;								\
	do {									\
		_ret3 = lockrestart_do((_trans), ({				\
			struct btree *_b = bch2_btree_iter_peek_node(&_iter);	\
			if (!_b)						\
				break;						\
										\
			PTR_ERR_OR_ZERO(_b) ?: (_do);				\
		})) ?:								\
		lockrestart_do((_trans),					\
			PTR_ERR_OR_ZERO(bch2_btree_iter_next_node(&_iter)));	\
	} while (!_ret3);							\
										\
	bch2_trans_iter_exit((_trans), &(_iter));				\
	_ret3;									\
})

#define for_each_btree_node(_trans, _iter, _btree_id, _start,		\
			    _flags, _b, _ret)				\
			    _flags, _b, _do)				\
	__for_each_btree_node(_trans, _iter, _btree_id, _start,	\
			      0, 0, _flags, _b, _ret)
			      0, 0, _flags, _b, _do)

static inline struct bkey_s_c bch2_btree_iter_peek_prev_type(struct btree_iter *iter,
							     unsigned flags)
+9 −29
Original line number Diff line number Diff line
@@ -397,47 +397,27 @@ static ssize_t bch2_read_btree_formats(struct file *file, char __user *buf,
				       size_t size, loff_t *ppos)
{
	struct dump_iter *i = file->private_data;
	struct btree_trans *trans;
	struct btree_iter iter;
	struct btree *b;
	ssize_t ret;

	i->ubuf = buf;
	i->size	= size;
	i->ret	= 0;

	ret = flush_buf(i);
	ssize_t ret = flush_buf(i);
	if (ret)
		return ret;

	if (bpos_eq(SPOS_MAX, i->from))
		return i->ret;

	trans = bch2_trans_get(i->c);
retry:
	bch2_trans_begin(trans);

	for_each_btree_node(trans, iter, i->id, i->from, 0, b, ret) {
	return bch2_trans_run(i->c,
		for_each_btree_node(trans, iter, i->id, i->from, 0, b, ({
			bch2_btree_node_to_text(&i->buf, i->c, b);
			i->from = !bpos_eq(SPOS_MAX, b->key.k.p)
				? bpos_successor(b->key.k.p)
				: b->key.k.p;

		ret = drop_locks_do(trans, flush_buf(i));
		if (ret)
			break;
	}
	bch2_trans_iter_exit(trans, &iter);

	if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
		goto retry;

	bch2_trans_put(trans);

	if (!ret)
		ret = flush_buf(i);

	return ret ?: i->ret;
			drop_locks_do(trans, flush_buf(i));
		}))) ?: i->ret;
}

static const struct file_operations btree_format_debug_ops = {