fixup bcachefs: Deadlock cycle detector
authorKent Overstreet <kent.overstreet@linux.dev>
Fri, 20 Jan 2023 20:35:07 +0000 (15:35 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:43 +0000 (17:09 -0400)
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/btree_locking.c

index 922cfc7f545095f164fdacbdc0751c7f5e9885af..76a532f98c72c06dfec9096dcc171126aef6d0f8 100644 (file)
@@ -99,6 +99,12 @@ static void lock_graph_up(struct lock_graph *g)
        closure_put(&g->g[--g->nr].trans->ref);
 }
 
+static noinline void lock_graph_pop_all(struct lock_graph *g)
+{
+       while (g->nr)
+               lock_graph_up(g);
+}
+
 static void lock_graph_down(struct lock_graph *g, struct btree_trans *trans)
 {
        closure_get(&trans->ref);
@@ -274,8 +280,26 @@ next:
 
                        b = &READ_ONCE(path->l[top->level].b)->c;
 
-                       if (unlikely(IS_ERR_OR_NULL(b))) {
-                               BUG_ON(!lock_graph_remove_non_waiters(&g));
+                       if (IS_ERR_OR_NULL(b)) {
+                               /*
+                                * If we get here, it means we raced with the
+                                * other thread updating its btree_path
+                                * structures - which means it can't be blocked
+                                * waiting on a lock:
+                                */
+                               if (!lock_graph_remove_non_waiters(&g)) {
+                                       /*
+                                        * If lock_graph_remove_non_waiters()
+                                        * didn't do anything, it must be
+                                        * because we're being called by debugfs
+                                        * checking for lock cycles, which
+                                        * invokes us on btree_transactions that
+                                        * aren't actually waiting on anything.
+                                        * Just bail out:
+                                        */
+                                       lock_graph_pop_all(&g);
+                               }
+
                                goto next;
                        }