bcachefs: Change where merging of interior btree nodes is trigger from
authorKent Overstreet <kent.overstreet@gmail.com>
Wed, 31 Mar 2021 19:39:16 +0000 (15:39 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:08:58 +0000 (17:08 -0400)
Previously, we were doing btree node merging from
bch2_btree_insert_node() - but this is called from the split path, when
we're in the middle of creating new nodes and deleting new nodes and the
iterators are in a weird state.

Also, this means we're starting a new btree_update while in the middle
of an existing one, and that's asking for deadlocks.

Much simpler and saner to trigger btree node merging _after_ the whole
btree node split path is finished.

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

index b8e37de19d06e723beacb514dd377c9fea82f1db..fddb0c3e716709176d1ae0d04fbdfce9aefcf099 100644 (file)
@@ -1505,14 +1505,6 @@ void bch2_btree_insert_node(struct btree_update *as, struct btree *b,
        bch2_btree_node_unlock_write(b, iter);
 
        btree_node_interior_verify(c, b);
-
-       /*
-        * when called from the btree_split path the new nodes aren't added to
-        * the btree iterator yet, so the merge path's unlock/wait/relock dance
-        * won't work:
-        */
-       bch2_foreground_maybe_merge(c, iter, b->c.level,
-                                   flags|BTREE_INSERT_NOUNLOCK);
        return;
 split:
        btree_split(as, b, iter, keys, flags);
@@ -1523,6 +1515,8 @@ int bch2_btree_split_leaf(struct bch_fs *c, struct btree_iter *iter,
 {
        struct btree *b = iter_l(iter)->b;
        struct btree_update *as;
+       unsigned l;
+       int ret = 0;
 
        as = bch2_btree_update_start(iter, iter->level,
                btree_update_reserve_required(c, b), flags);
@@ -1531,7 +1525,11 @@ int bch2_btree_split_leaf(struct bch_fs *c, struct btree_iter *iter,
 
        btree_split(as, b, iter, NULL, flags);
        bch2_btree_update_done(as);
-       return 0;
+
+       for (l = iter->level + 1; btree_iter_node(iter, l) && !ret; l++)
+               bch2_foreground_maybe_merge(c, iter, l, flags);
+
+       return ret;
 }
 
 void __bch2_foreground_maybe_merge(struct bch_fs *c,