aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2023-11-26 18:31:11 -0500
committerKent Overstreet <kent.overstreet@linux.dev>2023-11-28 17:18:24 -0500
commit5510a4af521c34df339fcceb0f26ace5b1090ad6 (patch)
treedb5de39978ef4d132df99892ea657897102ac292
parent03013bb0c6b157630018800a456a08646655ea97 (diff)
downloadlinux-xfs-5510a4af521c34df339fcceb0f26ace5b1090ad6.tar.gz
bcachefs: Fix split_race livelock
bch2_btree_update_start() calculates which nodes are going to have to be split/rewritten, so that we know how many nodes to reserve and how deep in the tree we have to take locks. But btree node merges require inserting two keys into the parent node, not just splits. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r--fs/bcachefs/btree_update_interior.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c
index d08efd6d958e87..d68fb01944b14c 100644
--- a/fs/bcachefs/btree_update_interior.c
+++ b/fs/bcachefs/btree_update_interior.c
@@ -1071,8 +1071,12 @@ bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path,
break;
}
+ /*
+ * Always check for space for two keys, even if we won't have to
+ * split at prior level - it might have been a merge instead:
+ */
if (bch2_btree_node_insert_fits(c, path->l[update_level].b,
- BKEY_BTREE_PTR_U64s_MAX * (1 + split)))
+ BKEY_BTREE_PTR_U64s_MAX * 2))
break;
split = path->l[update_level].b->nr.live_u64s > BTREE_SPLIT_THRESHOLD(c);