summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/bcachefs/btree_locking.c29
1 files changed, 20 insertions, 9 deletions
diff --git a/fs/bcachefs/btree_locking.c b/fs/bcachefs/btree_locking.c
index 9ece0f318e57..0a3090f8a633 100644
--- a/fs/bcachefs/btree_locking.c
+++ b/fs/bcachefs/btree_locking.c
@@ -87,23 +87,34 @@ static noinline void print_cycle(struct printbuf *out, struct lock_graph *g)
bch2_btree_trans_to_text(out, i->trans);
}
+static int abort_lock(struct lock_graph *g, struct trans_waiting_for_lock *i)
+{
+ if (i == g->g) {
+ trace_and_count(i->trans->c, trans_restart_would_deadlock, i->trans, _RET_IP_);
+ return btree_trans_restart(i->trans, BCH_ERR_transaction_restart_would_deadlock);
+ } else {
+ i->trans->lock_must_abort = true;
+ wake_up_process(i->trans->locking_wait.task);
+ return 1;
+ }
+}
+
static noinline int break_cycle(struct lock_graph *g)
{
- struct btree_trans *orig_trans = g->g->trans;
struct trans_waiting_for_lock *i;
for (i = g->g; i < g->g + g->nr; i++) {
- if (i->trans->lock_may_not_fail)
+ if (i->trans->lock_may_not_fail || i->trans->in_traverse_all)
continue;
- if (i == g->g) {
- trace_and_count(orig_trans->c, trans_restart_would_deadlock, orig_trans, _RET_IP_);
- return btree_trans_restart(orig_trans, BCH_ERR_transaction_restart_would_deadlock);
- }
+ return abort_lock(g, i);
+ }
- i->trans->lock_must_abort = true;
- wake_up_process(i->trans->locking_wait.task);
- return 1;
+ for (i = g->g; i < g->g + g->nr; i++) {
+ if (i->trans->lock_may_not_fail)
+ continue;
+
+ return abort_lock(g, i);
}
BUG();