Skip to content

Commit b169138

Browse files
alanskindKent Overstreet
authored andcommitted
bcachefs: Only abort the transactions in the cycle
When the cycle doesn't involve the initiator of the cycle detection, we might choose a transaction that is not involved in the cycle to abort. It shouldn't be that since it won't break the cycle, this patch therefore chooses the transaction in the cycle to abort. Signed-off-by: Alan Huang <mmpgouride@gmail.com> Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
1 parent 6853a5e commit b169138

File tree

1 file changed

+14
-7
lines changed

1 file changed

+14
-7
lines changed

fs/bcachefs/btree_locking.c

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -130,11 +130,17 @@ static void lock_graph_down(struct lock_graph *g, struct btree_trans *trans)
130130
__lock_graph_down(g, trans);
131131
}
132132

133-
static bool lock_graph_remove_non_waiters(struct lock_graph *g)
133+
static bool lock_graph_remove_non_waiters(struct lock_graph *g,
134+
struct trans_waiting_for_lock *from)
134135
{
135136
struct trans_waiting_for_lock *i;
136137

137-
for (i = g->g + 1; i < g->g + g->nr; i++)
138+
if (from->trans->locking != from->node_want) {
139+
lock_graph_pop_from(g, from);
140+
return true;
141+
}
142+
143+
for (i = from + 1; i < g->g + g->nr; i++)
138144
if (i->trans->locking != i->node_want ||
139145
i->trans->locking_wait.start_time != i[-1].lock_start_time) {
140146
lock_graph_pop_from(g, i);
@@ -184,13 +190,14 @@ static int btree_trans_abort_preference(struct btree_trans *trans)
184190
return 3;
185191
}
186192

187-
static noinline int break_cycle(struct lock_graph *g, struct printbuf *cycle)
193+
static noinline int break_cycle(struct lock_graph *g, struct printbuf *cycle,
194+
struct trans_waiting_for_lock *from)
188195
{
189196
struct trans_waiting_for_lock *i, *abort = NULL;
190197
unsigned best = 0, pref;
191198
int ret;
192199

193-
if (lock_graph_remove_non_waiters(g))
200+
if (lock_graph_remove_non_waiters(g, from))
194201
return 0;
195202

196203
/* Only checking, for debugfs: */
@@ -200,7 +207,7 @@ static noinline int break_cycle(struct lock_graph *g, struct printbuf *cycle)
200207
goto out;
201208
}
202209

203-
for (i = g->g; i < g->g + g->nr; i++) {
210+
for (i = from; i < g->g + g->nr; i++) {
204211
pref = btree_trans_abort_preference(i->trans);
205212
if (pref > best) {
206213
abort = i;
@@ -247,7 +254,7 @@ static int lock_graph_descend(struct lock_graph *g, struct btree_trans *trans,
247254
for (i = g->g; i < g->g + g->nr; i++)
248255
if (i->trans == trans) {
249256
closure_put(&trans->ref);
250-
return break_cycle(g, cycle);
257+
return break_cycle(g, cycle, i);
251258
}
252259

253260
if (g->nr == ARRAY_SIZE(g->g)) {
@@ -339,7 +346,7 @@ int bch2_check_for_deadlock(struct btree_trans *trans, struct printbuf *cycle)
339346
* structures - which means it can't be blocked
340347
* waiting on a lock:
341348
*/
342-
if (!lock_graph_remove_non_waiters(&g)) {
349+
if (!lock_graph_remove_non_waiters(&g, g.g)) {
343350
/*
344351
* If lock_graph_remove_non_waiters()
345352
* didn't do anything, it must be

0 commit comments

Comments
 (0)