bcachefs: Inject transaction restarts in debug mode
authorKent Overstreet <kent.overstreet@gmail.com>
Mon, 18 Jul 2022 00:22:30 +0000 (20:22 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:37 +0000 (17:09 -0400)
In CONFIG_BCACHEFS_DEBUG mode, we'll now randomly issue transaction
restarts - with a decaying probability based on the number of restarts
we've already had, to ensure that transactions eventually make forward
progress. This should help shake out some bugs.

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/btree_iter.c
fs/bcachefs/trace.h

index db247c96298f401a3d1b487e4b26a4e0cca5dd0a..777e41a1224629fd39b5984cf5a9e418d5a30aee 100644 (file)
@@ -17,6 +17,7 @@
 #include "subvolume.h"
 #include "trace.h"
 
+#include <linux/random.h>
 #include <linux/prefetch.h>
 
 static inline void btree_path_list_remove(struct btree_trans *, struct btree_path *);
@@ -1660,6 +1661,16 @@ out:
 int __must_check bch2_btree_path_traverse(struct btree_trans *trans,
                                          struct btree_path *path, unsigned flags)
 {
+       if (IS_ENABLED(CONFIG_BCACHEFS_DEBUG)) {
+               unsigned restart_probability_bits = 4 << min(trans->restart_count, 32U);
+               u64 max = ~(~0ULL << restart_probability_bits);
+
+               if (!get_random_u32_below(max)) {
+                       trace_transaction_restart_injected(trans->fn, _RET_IP_);
+                       return btree_trans_restart(trans, BCH_ERR_transaction_restart_fault_inject);
+               }
+       }
+
        if (path->uptodate < BTREE_ITER_NEED_RELOCK)
                return 0;
 
index a52da91f279e6060a78cc00f105e82a17ba414ab..1e9e93161509cf9221b24b0bf1b67b99837706a2 100644 (file)
@@ -707,6 +707,12 @@ DEFINE_EVENT(transaction_event,    transaction_restart_ip,
        TP_ARGS(trans_fn, caller_ip)
 );
 
+DEFINE_EVENT(transaction_event,        transaction_restart_injected,
+       TP_PROTO(const char *trans_fn,
+                unsigned long caller_ip),
+       TP_ARGS(trans_fn, caller_ip)
+);
+
 DEFINE_EVENT(transaction_event,        trans_blocked_journal_reclaim,
        TP_PROTO(const char *trans_fn,
                 unsigned long caller_ip),