]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
bcachefs: Fix a race in btree_update_nodes_written()
authorKent Overstreet <kent.overstreet@linux.dev>
Wed, 10 Apr 2024 16:53:28 +0000 (12:53 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Thu, 11 Apr 2024 02:28:36 +0000 (22:28 -0400)
One btree update might have terminated in a node update, and then while
it is in flight another btree update might free that original node.

This race has to be handled in btree_update_nodes_written() - we were
missing a READ_ONCE().

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

index a4a63e363047dbe66a1bcb6d0b83799c1e030cae..c4a5e83a56a436548263445e3b7a329644757cc7 100644 (file)
@@ -704,9 +704,13 @@ static void btree_update_nodes_written(struct btree_update *as)
        bch2_fs_fatal_err_on(ret && !bch2_journal_error(&c->journal), c,
                             "%s", bch2_err_str(ret));
 err:
-       if (as->b) {
-
-               b = as->b;
+       /*
+        * We have to be careful because another thread might be getting ready
+        * to free as->b and calling btree_update_reparent() on us - we'll
+        * recheck under btree_update_lock below:
+        */
+       b = READ_ONCE(as->b);
+       if (b) {
                btree_path_idx_t path_idx = get_unlocked_mut_path(trans,
                                                as->btree_id, b->c.level, b->key.k.p);
                struct btree_path *path = trans->paths + path_idx;