aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2024-04-10 12:53:28 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2024-04-10 22:28:36 -0400
commitbeccf29114886f1604e26f739cd108f048878ca8 (patch)
treec19ba70cae534c4c88cc8c746472a4c00ac138fd
parent9b31152fd74eeb10a20345909e542fef6f1d98e2 (diff)
downloadlinux-beccf29114886f1604e26f739cd108f048878ca8.tar.gz
bcachefs: Fix a race in btree_update_nodes_written()
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>
-rw-r--r--fs/bcachefs/btree_update_interior.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c
index a4a63e363047db..c4a5e83a56a436 100644
--- a/fs/bcachefs/btree_update_interior.c
+++ b/fs/bcachefs/btree_update_interior.c
@@ -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;