We're ramping up on checking transaction restart handling correctness -
so, in debug mode we now save a backtrace for where the restart was
emitted, which makes it much easier to track down the incorrect
handling.

Signed-off-by: Kent Overstreet <[email protected]>
---
 fs/bcachefs/btree_iter.c  | 12 ++++++++++++
 fs/bcachefs/btree_iter.h  |  4 ++++
 fs/bcachefs/btree_types.h |  3 +++
 3 files changed, 19 insertions(+)

diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c
index b36ee4e511fa..15ac72b1af51 100644
--- a/fs/bcachefs/btree_iter.c
+++ b/fs/bcachefs/btree_iter.c
@@ -1414,9 +1414,17 @@ void __noreturn bch2_trans_restart_error(struct 
btree_trans *trans, u32 restart_
 
 void __noreturn bch2_trans_in_restart_error(struct btree_trans *trans)
 {
+#ifdef CONFIG_BCACHEFS_DEBUG
+       struct printbuf buf = PRINTBUF;
+       bch2_prt_backtrace(&buf, &trans->last_restarted_trace);
+       panic("in transaction restart: %s, last restarted by\n%s",
+             bch2_err_str(trans->restarted),
+             buf.buf);
+#else
        panic("in transaction restart: %s, last restarted by %pS\n",
              bch2_err_str(trans->restarted),
              (void *) trans->last_restarted_ip);
+#endif
 }
 
 void __noreturn bch2_trans_unlocked_error(struct btree_trans *trans)
@@ -3274,6 +3282,10 @@ void bch2_trans_put(struct btree_trans *trans)
        closure_return_sync(&trans->ref);
        trans->locking_wait.task = NULL;
 
+#ifdef CONFIG_BCACHEFS_DEBUG
+       darray_exit(&trans->last_restarted_trace);
+#endif
+
        unsigned long *paths_allocated = trans->paths_allocated;
        trans->paths_allocated  = NULL;
        trans->paths            = NULL;
diff --git a/fs/bcachefs/btree_iter.h b/fs/bcachefs/btree_iter.h
index dda07a320488..36899c6b134e 100644
--- a/fs/bcachefs/btree_iter.h
+++ b/fs/bcachefs/btree_iter.h
@@ -350,6 +350,10 @@ static int btree_trans_restart_ip(struct btree_trans 
*trans, int err, unsigned l
 
        trans->restarted = err;
        trans->last_restarted_ip = ip;
+#ifdef CONFIG_BCACHEFS_DEBUG
+       darray_exit(&trans->last_restarted_trace);
+       bch2_save_backtrace(&trans->last_restarted_trace, current, 0, 
GFP_NOWAIT);
+#endif
        return -err;
 }
 
diff --git a/fs/bcachefs/btree_types.h b/fs/bcachefs/btree_types.h
index 4568a41fefaf..baab5288ecc9 100644
--- a/fs/bcachefs/btree_types.h
+++ b/fs/bcachefs/btree_types.h
@@ -513,6 +513,9 @@ struct btree_trans {
        u64                     last_begin_time;
        unsigned long           last_begin_ip;
        unsigned long           last_restarted_ip;
+#ifdef CONFIG_BCACHEFS_DEBUG
+       bch_stacktrace          last_restarted_trace;
+#endif
        unsigned long           last_unlock_ip;
        unsigned long           srcu_lock_time;
 
-- 
2.45.2


Reply via email to