Commit 1854c7f7 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'bcachefs-2025-02-12' of git://evilpiepirate.org/bcachefs

Pull bcachefs fixes from Kent Overstreet:
 "Just small stuff.

  As a general announcement, on disk format is now frozen in my master
  branch - future on disk format changes will be optional, not required.

   - More fixes for going read-only: the previous fix was insufficient,
     but with more work on ordering journal reclaim flushing (and a
     btree node accounting fix so we don't split until we have to) the
     tiering_replication test now consistently goes read-only in less
     than a second.

   - fix for fsck when we have reflink pointers to missing indirect
     extents

   - some transaction restart handling fixes from Alan; the "Pass
     _orig_restart_count to trans_was_restarted" likely fixes some rare
     undefined behaviour heisenbugs"

* tag 'bcachefs-2025-02-12' of git://evilpiepirate.org/bcachefs:
  bcachefs: Reuse transaction
  bcachefs: Pass _orig_restart_count to trans_was_restarted
  bcachefs: CONFIG_BCACHEFS_INJECT_TRANSACTION_RESTARTS
  bcachefs: Fix want_new_bset() so we write until the end of the btree node
  bcachefs: Split out journal pins by btree level
  bcachefs: Fix use after free
  bcachefs: Fix marking reflink pointers to missing indirect extents
parents ab68d7eb 406e445b
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -61,6 +61,13 @@ config BCACHEFS_DEBUG
	The resulting code will be significantly slower than normal; you
	probably shouldn't select this option unless you're a developer.

config BCACHEFS_INJECT_TRANSACTION_RESTARTS
	bool "Randomly inject transaction restarts"
	depends on BCACHEFS_DEBUG
	help
	Randomly inject transaction restarts in a few core paths - may have a
	significant performance penalty

config BCACHEFS_TESTS
	bool "bcachefs unit and performance tests"
	depends on BCACHEFS_FS
+32 −1
Original line number Diff line number Diff line
@@ -2357,6 +2357,12 @@ struct bkey_s_c bch2_btree_iter_peek_max(struct btree_iter *iter, struct bpos en
	bch2_btree_iter_verify_entry_exit(iter);
	EBUG_ON((iter->flags & BTREE_ITER_filter_snapshots) && bkey_eq(end, POS_MAX));

	ret = trans_maybe_inject_restart(trans, _RET_IP_);
	if (unlikely(ret)) {
		k = bkey_s_c_err(ret);
		goto out_no_locked;
	}

	if (iter->update_path) {
		bch2_path_put_nokeep(trans, iter->update_path,
				     iter->flags & BTREE_ITER_intent);
@@ -2622,6 +2628,12 @@ struct bkey_s_c bch2_btree_iter_peek_prev_min(struct btree_iter *iter, struct bp
	bch2_btree_iter_verify_entry_exit(iter);
	EBUG_ON((iter->flags & BTREE_ITER_filter_snapshots) && bpos_eq(end, POS_MIN));

	int ret = trans_maybe_inject_restart(trans, _RET_IP_);
	if (unlikely(ret)) {
		k = bkey_s_c_err(ret);
		goto out_no_locked;
	}

	while (1) {
		k = __bch2_btree_iter_peek_prev(iter, search_key);
		if (unlikely(!k.k))
@@ -2749,6 +2761,12 @@ struct bkey_s_c bch2_btree_iter_peek_slot(struct btree_iter *iter)
	bch2_btree_iter_verify_entry_exit(iter);
	EBUG_ON(btree_iter_path(trans, iter)->level && (iter->flags & BTREE_ITER_with_key_cache));

	ret = trans_maybe_inject_restart(trans, _RET_IP_);
	if (unlikely(ret)) {
		k = bkey_s_c_err(ret);
		goto out_no_locked;
	}

	/* extents can't span inode numbers: */
	if ((iter->flags & BTREE_ITER_is_extents) &&
	    unlikely(iter->pos.offset == KEY_OFFSET_MAX)) {
@@ -3106,6 +3124,10 @@ void *__bch2_trans_kmalloc(struct btree_trans *trans, size_t size)

	WARN_ON_ONCE(new_bytes > BTREE_TRANS_MEM_MAX);

	ret = trans_maybe_inject_restart(trans, _RET_IP_);
	if (ret)
		return ERR_PTR(ret);

	struct btree_transaction_stats *s = btree_trans_stats(trans);
	s->max_mem = max(s->max_mem, new_bytes);

@@ -3163,7 +3185,8 @@ void *__bch2_trans_kmalloc(struct btree_trans *trans, size_t size)

	if (old_bytes) {
		trace_and_count(c, trans_restart_mem_realloced, trans, _RET_IP_, new_bytes);
		return ERR_PTR(btree_trans_restart(trans, BCH_ERR_transaction_restart_mem_realloced));
		return ERR_PTR(btree_trans_restart_ip(trans,
					BCH_ERR_transaction_restart_mem_realloced, _RET_IP_));
	}
out_change_top:
	p = trans->mem + trans->mem_top;
@@ -3271,6 +3294,14 @@ u32 bch2_trans_begin(struct btree_trans *trans)

	trans->last_begin_ip = _RET_IP_;

#ifdef CONFIG_BCACHEFS_INJECT_TRANSACTION_RESTARTS
	if (trans->restarted) {
		trans->restart_count_this_trans++;
	} else {
		trans->restart_count_this_trans = 0;
	}
#endif

	trans_set_locked(trans, false);

	if (trans->restarted) {
+13 −1
Original line number Diff line number Diff line
@@ -355,6 +355,18 @@ static int btree_trans_restart(struct btree_trans *trans, int err)
	return btree_trans_restart_ip(trans, err, _THIS_IP_);
}

static inline int trans_maybe_inject_restart(struct btree_trans *trans, unsigned long ip)
{
#ifdef CONFIG_BCACHEFS_INJECT_TRANSACTION_RESTARTS
	if (!(ktime_get_ns() & ~(~0ULL << min(63, (10 + trans->restart_count_this_trans))))) {
		trace_and_count(trans->c, trans_restart_injected, trans, ip);
		return btree_trans_restart_ip(trans,
					BCH_ERR_transaction_restart_fault_inject, ip);
	}
#endif
	return 0;
}

bool bch2_btree_node_upgrade(struct btree_trans *,
			     struct btree_path *, unsigned);

@@ -739,7 +751,7 @@ transaction_restart: \
	if (!_ret2)							\
		bch2_trans_verify_not_restarted(_trans, _restart_count);\
									\
	_ret2 ?: trans_was_restarted(_trans, _restart_count);		\
	_ret2 ?: trans_was_restarted(_trans, _orig_restart_count);		\
})

#define for_each_btree_key_max_continue(_trans, _iter,			\
+4 −0
Original line number Diff line number Diff line
@@ -999,6 +999,10 @@ int __bch2_trans_commit(struct btree_trans *trans, unsigned flags)

	bch2_trans_verify_not_unlocked_or_in_restart(trans);

	ret = trans_maybe_inject_restart(trans, _RET_IP_);
	if (unlikely(ret))
		goto out_reset;

	if (!trans->nr_updates &&
	    !trans->journal_entries_u64s)
		goto out_reset;
+3 −0
Original line number Diff line number Diff line
@@ -509,6 +509,9 @@ struct btree_trans {
	bool			notrace_relock_fail:1;
	enum bch_errcode	restarted:16;
	u32			restart_count;
#ifdef CONFIG_BCACHEFS_INJECT_TRANSACTION_RESTARTS
	u32			restart_count_this_trans;
#endif

	u64			last_begin_time;
	unsigned long		last_begin_ip;
Loading