diff --git a/fs/bcachefs/btree_cache.c b/fs/bcachefs/btree_cache.c index 55aaa3e4aa84..bb88ce1415c8 100644 --- a/fs/bcachefs/btree_cache.c +++ b/fs/bcachefs/btree_cache.c @@ -734,6 +734,8 @@ retry: goto retry; trans_restart(); + trace_trans_restart_btree_node_reused(c, + iter->trans->ip); return ERR_PTR(-EINTR); } } diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c index 6b9af53a3e77..4bdbdd22b437 100644 --- a/fs/bcachefs/btree_iter.c +++ b/fs/bcachefs/btree_iter.c @@ -252,12 +252,15 @@ bool __bch2_btree_node_lock(struct btree *b, struct bpos pos, } } - if (ret) - __btree_node_lock_type(iter->trans->c, b, type); - else + if (unlikely(!ret)) { trans_restart(); + trace_trans_restart_would_deadlock(iter->trans->c, + iter->trans->ip); + return false; + } - return ret; + __btree_node_lock_type(iter->trans->c, b, type); + return true; } /* Btree iterator locking: */ @@ -1695,6 +1698,7 @@ success: if (trans->iters_live) { trans_restart(); + trace_trans_restart_iters_realloced(trans->c, trans->ip); return -EINTR; } @@ -1863,6 +1867,7 @@ void *bch2_trans_kmalloc(struct btree_trans *trans, if (old_bytes) { trans_restart(); + trace_trans_restart_mem_realloced(trans->c, trans->ip); return ERR_PTR(-EINTR); } } @@ -1939,6 +1944,7 @@ void bch2_trans_init(struct btree_trans *trans, struct bch_fs *c) memset(trans, 0, offsetof(struct btree_trans, iters_onstack)); trans->c = c; + trans->ip = _RET_IP_; trans->size = ARRAY_SIZE(trans->iters_onstack); trans->iters = trans->iters_onstack; trans->updates = trans->updates_onstack; diff --git a/fs/bcachefs/btree_types.h b/fs/bcachefs/btree_types.h index 8c6f5fe6998e..dd4fa2f595ec 100644 --- a/fs/bcachefs/btree_types.h +++ b/fs/bcachefs/btree_types.h @@ -267,6 +267,7 @@ struct btree_insert_entry { struct btree_trans { struct bch_fs *c; + unsigned long ip; size_t nr_restarts; u64 commit_start; diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c index 2633a5452b13..a9d7905f3373 100644 --- a/fs/bcachefs/btree_update_leaf.c +++ b/fs/bcachefs/btree_update_leaf.c @@ -440,6 +440,7 @@ static int bch2_trans_journal_preres_get(struct btree_trans *trans) if (!bch2_btree_trans_relock(trans)) { trans_restart(" (iter relock after journal preres get blocked)"); + trace_trans_restart_journal_preres_get(c, trans->ip); return -EINTR; } @@ -564,6 +565,7 @@ static inline int do_btree_insert_at(struct btree_trans *trans, if (race_fault()) { ret = -EINTR; trans_restart(" (race)"); + trace_trans_restart_fault_inject(c, trans->ip); goto out; } @@ -680,6 +682,7 @@ int bch2_trans_commit_error(struct btree_trans *trans, */ if (!ret || (flags & BTREE_INSERT_NOUNLOCK)) { trans_restart(" (split)"); + trace_trans_restart_btree_node_split(c, trans->ip); ret = -EINTR; } break; @@ -699,6 +702,7 @@ int bch2_trans_commit_error(struct btree_trans *trans, return 0; trans_restart(" (iter relock after marking replicas)"); + trace_trans_restart_mark_replicas(c, trans->ip); ret = -EINTR; break; case BTREE_INSERT_NEED_JOURNAL_RES: @@ -712,6 +716,7 @@ int bch2_trans_commit_error(struct btree_trans *trans, return 0; trans_restart(" (iter relock after journal res get blocked)"); + trace_trans_restart_journal_res_get(c, trans->ip); ret = -EINTR; break; default: @@ -724,6 +729,7 @@ int bch2_trans_commit_error(struct btree_trans *trans, if (ret2) { trans_restart(" (traverse)"); + trace_trans_restart_traverse(c, trans->ip); return ret2; } @@ -735,6 +741,7 @@ int bch2_trans_commit_error(struct btree_trans *trans, return 0; trans_restart(" (atomic)"); + trace_trans_restart_atomic(c, trans->ip); } return ret; diff --git a/fs/bcachefs/trace.h b/fs/bcachefs/trace.h index 1aa6ac05d50e..2864a72938ce 100644 --- a/fs/bcachefs/trace.h +++ b/fs/bcachefs/trace.h @@ -499,6 +499,78 @@ TRACE_EVENT(copygc, __entry->buckets_moved, __entry->buckets_not_moved) ); +DECLARE_EVENT_CLASS(transaction_restart, + TP_PROTO(struct bch_fs *c, unsigned long ip), + TP_ARGS(c, ip), + + TP_STRUCT__entry( + __array(char, name, 16) + __field(unsigned long, ip ) + ), + + TP_fast_assign( + memcpy(__entry->name, c->name, 16); + __entry->ip = ip; + ), + + TP_printk("%pS", (void *) __entry->ip) +); + +DEFINE_EVENT(transaction_restart, trans_restart_btree_node_reused, + TP_PROTO(struct bch_fs *c, unsigned long ip), + TP_ARGS(c, ip) +); + +DEFINE_EVENT(transaction_restart, trans_restart_would_deadlock, + TP_PROTO(struct bch_fs *c, unsigned long ip), + TP_ARGS(c, ip) +); + +DEFINE_EVENT(transaction_restart, trans_restart_iters_realloced, + TP_PROTO(struct bch_fs *c, unsigned long ip), + TP_ARGS(c, ip) +); + +DEFINE_EVENT(transaction_restart, trans_restart_mem_realloced, + TP_PROTO(struct bch_fs *c, unsigned long ip), + TP_ARGS(c, ip) +); + +DEFINE_EVENT(transaction_restart, trans_restart_journal_res_get, + TP_PROTO(struct bch_fs *c, unsigned long ip), + TP_ARGS(c, ip) +); + +DEFINE_EVENT(transaction_restart, trans_restart_journal_preres_get, + TP_PROTO(struct bch_fs *c, unsigned long ip), + TP_ARGS(c, ip) +); + +DEFINE_EVENT(transaction_restart, trans_restart_mark_replicas, + TP_PROTO(struct bch_fs *c, unsigned long ip), + TP_ARGS(c, ip) +); + +DEFINE_EVENT(transaction_restart, trans_restart_fault_inject, + TP_PROTO(struct bch_fs *c, unsigned long ip), + TP_ARGS(c, ip) +); + +DEFINE_EVENT(transaction_restart, trans_restart_btree_node_split, + TP_PROTO(struct bch_fs *c, unsigned long ip), + TP_ARGS(c, ip) +); + +DEFINE_EVENT(transaction_restart, trans_restart_traverse, + TP_PROTO(struct bch_fs *c, unsigned long ip), + TP_ARGS(c, ip) +); + +DEFINE_EVENT(transaction_restart, trans_restart_atomic, + TP_PROTO(struct bch_fs *c, unsigned long ip), + TP_ARGS(c, ip) +); + #endif /* _TRACE_BCACHEFS_H */ /* This part must be outside protection */