]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bcachefs: Don't call bch2_btree_interior_update_will_free_node() until after update...
authorKent Overstreet <kent.overstreet@linux.dev>
Thu, 5 Dec 2024 01:43:01 +0000 (20:43 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sat, 21 Dec 2024 06:36:22 +0000 (01:36 -0500)
Originally, btree splits always succeeded once we got to the point of
recursing to the btree_insert_node() call.

But that changed when we switched to not taking intent locks all the way
up to the root, and that introduced a bug, because
bch2_btree_interior_update_will_free_node() cancels paending writes and
reparents a node that's going to be made visible on disk by another
btree update to the current btree update.

This was discovered in recent backpointers work, because
bch2_btree_interior_update_will_free_node() also clears the
will_make_reachable flag, causing backpointer target lookup to
spuriously thing it had found a dangling backpointer (when the
backpointer just hadn't been created yet by
btree_update_nodes_written()).

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

index f2a1d5d3d8d5d0ea26955dcde1cd8f72f8906701..7d9dab95bdcfded293664b83476c46c776016fef 100644 (file)
@@ -1607,8 +1607,6 @@ static int btree_split(struct btree_update *as, struct btree_trans *trans,
        if (ret)
                return ret;
 
-       bch2_btree_interior_update_will_free_node(as, b);
-
        if (b->nr.live_u64s > BTREE_SPLIT_THRESHOLD(c)) {
                struct btree *n[2];
 
@@ -1707,6 +1705,8 @@ static int btree_split(struct btree_update *as, struct btree_trans *trans,
        if (ret)
                goto err;
 
+       bch2_btree_interior_update_will_free_node(as, b);
+
        if (n3) {
                bch2_btree_update_get_open_buckets(as, n3);
                bch2_btree_node_write(c, n3, SIX_LOCK_intent, 0);
@@ -2063,9 +2063,6 @@ int __bch2_foreground_maybe_merge(struct btree_trans *trans,
 
        trace_and_count(c, btree_node_merge, trans, b);
 
-       bch2_btree_interior_update_will_free_node(as, b);
-       bch2_btree_interior_update_will_free_node(as, m);
-
        n = bch2_btree_node_alloc(as, trans, b->c.level);
 
        SET_BTREE_NODE_SEQ(n->data,
@@ -2101,6 +2098,9 @@ int __bch2_foreground_maybe_merge(struct btree_trans *trans,
        if (ret)
                goto err_free_update;
 
+       bch2_btree_interior_update_will_free_node(as, b);
+       bch2_btree_interior_update_will_free_node(as, m);
+
        bch2_trans_verify_paths(trans);
 
        bch2_btree_update_get_open_buckets(as, n);
@@ -2155,8 +2155,6 @@ int bch2_btree_node_rewrite(struct btree_trans *trans,
        if (ret)
                goto out;
 
-       bch2_btree_interior_update_will_free_node(as, b);
-
        n = bch2_btree_node_alloc_replacement(as, trans, b);
 
        bch2_btree_build_aux_trees(n);
@@ -2180,6 +2178,8 @@ int bch2_btree_node_rewrite(struct btree_trans *trans,
        if (ret)
                goto err;
 
+       bch2_btree_interior_update_will_free_node(as, b);
+
        bch2_btree_update_get_open_buckets(as, n);
        bch2_btree_node_write(c, n, SIX_LOCK_intent, 0);