]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
bcachefs: Disable merges from interior update path
authorKent Overstreet <kent.overstreet@linux.dev>
Sat, 13 Apr 2024 22:39:03 +0000 (18:39 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 14 Apr 2024 02:49:25 +0000 (22:49 -0400)
There's been a bug in the btree write buffer where it wasn't triggering
btree node merges - and leaving behind a bunch of nearly empty btree
nodes.

Then during journal replay, when updates to the backpointers btree
aren't using the btree write buffer (because we require synchronization
with journal replay), we end up doing those merges all at once.

Then if it's the interior update path running them, we deadlock because
those run with the highest watermark.

There's no real need for the interior update path to be doing btree node
merges; other code paths can handle that at lower watermarks.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/btree_update_interior.c

index 1a7537ee432971df5f78520de08acb7e88477f46..82ac00aa0f7b0d8410b70bbe9b9ae4ce2d485d76 100644 (file)
@@ -1926,6 +1926,16 @@ int __bch2_foreground_maybe_merge(struct btree_trans *trans,
        BUG_ON(!trans->paths[path].should_be_locked);
        BUG_ON(!btree_node_locked(&trans->paths[path], level));
 
+       /*
+        * Work around a deadlock caused by the btree write buffer not doing
+        * merges and leaving tons of merges for us to do - we really don't need
+        * to be doing merges at all from the interior update path, and if the
+        * interior update path is generating too many new interior updates we
+        * deadlock:
+        */
+       if ((flags & BCH_WATERMARK_MASK) == BCH_WATERMARK_interior_updates)
+               return 0;
+
        flags &= ~BCH_WATERMARK_MASK;
 
        b = trans->paths[path].l[level].b;