bcachefs: Tweak btree cache helpers for use by btree node scan
authorKent Overstreet <kent.overstreet@linux.dev>
Thu, 3 Jul 2025 22:50:18 +0000 (18:50 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sat, 5 Jul 2025 03:17:07 +0000 (23:17 -0400)
btree node scan needs to not use the btree node cache: that causes
interference from prior failed reads and parallel workers.

Instead we need to allocate btree nodes that don't live in the btree
cache, so that we can call bch2_btree_node_read_done() directly.

This patch tweaks the low level helpers so they don't touch the btree
cache lists.

Cc: Nikita Ofitserov <himikof@gmail.com>
Reviewed-by: Nikita Ofitserov <himikof@gmail.com>
Reported-and-tested-by: Edoardo Codeglia <bcachefs@404.blue>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/btree_cache.c
fs/bcachefs/btree_cache.h
fs/bcachefs/debug.c

index 91e0aa796e6b692122a0f4e88f349528585c5e9b..83c9860e6b82cbc7b98c1988512625992d267e97 100644 (file)
@@ -85,7 +85,7 @@ void bch2_btree_node_to_freelist(struct bch_fs *c, struct btree *b)
        six_unlock_intent(&b->c.lock);
 }
 
-static void __btree_node_data_free(struct btree_cache *bc, struct btree *b)
+void __btree_node_data_free(struct btree *b)
 {
        BUG_ON(!list_empty(&b->list));
        BUG_ON(btree_node_hashed(b));
@@ -112,16 +112,17 @@ static void __btree_node_data_free(struct btree_cache *bc, struct btree *b)
        munmap(b->aux_data, btree_aux_data_bytes(b));
 #endif
        b->aux_data = NULL;
-
-       btree_node_to_freedlist(bc, b);
 }
 
 static void btree_node_data_free(struct btree_cache *bc, struct btree *b)
 {
        BUG_ON(list_empty(&b->list));
        list_del_init(&b->list);
+
+       __btree_node_data_free(b);
+
        --bc->nr_freeable;
-       __btree_node_data_free(bc, b);
+       btree_node_to_freedlist(bc, b);
 }
 
 static int bch2_btree_cache_cmp_fn(struct rhashtable_compare_arg *arg,
@@ -185,10 +186,7 @@ static struct btree *__btree_node_mem_alloc(struct bch_fs *c, gfp_t gfp)
 
 struct btree *__bch2_btree_node_mem_alloc(struct bch_fs *c)
 {
-       struct btree_cache *bc = &c->btree_cache;
-       struct btree *b;
-
-       b = __btree_node_mem_alloc(c, GFP_KERNEL);
+       struct btree *b = __btree_node_mem_alloc(c, GFP_KERNEL);
        if (!b)
                return NULL;
 
@@ -198,8 +196,6 @@ struct btree *__bch2_btree_node_mem_alloc(struct bch_fs *c)
        }
 
        bch2_btree_lock_init(&b->c, 0, GFP_KERNEL);
-
-       __bch2_btree_node_to_freelist(bc, b);
        return b;
 }
 
@@ -524,7 +520,8 @@ restart:
                        --touched;;
                } else if (!btree_node_reclaim(c, b)) {
                        __bch2_btree_node_hash_remove(bc, b);
-                       __btree_node_data_free(bc, b);
+                       __btree_node_data_free(b);
+                       btree_node_to_freedlist(bc, b);
 
                        freed++;
                        bc->nr_freed++;
@@ -652,9 +649,12 @@ int bch2_fs_btree_cache_init(struct bch_fs *c)
 
        bch2_recalc_btree_reserve(c);
 
-       for (i = 0; i < bc->nr_reserve; i++)
-               if (!__bch2_btree_node_mem_alloc(c))
+       for (i = 0; i < bc->nr_reserve; i++) {
+               struct btree *b = __bch2_btree_node_mem_alloc(c);
+               if (!b)
                        goto err;
+               __bch2_btree_node_to_freelist(bc, b);
+       }
 
        list_splice_init(&bc->live[0].list, &bc->freeable);
 
index ca3c1b145330e73c4ba3c5c452ce187732f81bab..be275f87a60e042577420936603a44fe29dc09e2 100644 (file)
@@ -30,6 +30,7 @@ void bch2_btree_node_update_key_early(struct btree_trans *, enum btree_id, unsig
 void bch2_btree_cache_cannibalize_unlock(struct btree_trans *);
 int bch2_btree_cache_cannibalize_lock(struct btree_trans *, struct closure *);
 
+void __btree_node_data_free(struct btree *);
 struct btree *__bch2_btree_node_mem_alloc(struct bch_fs *);
 struct btree *bch2_btree_node_mem_alloc(struct btree_trans *, bool);
 
index 901f643ead83ddb6260d4a57e4d2fd45291ab220..79d64052215c97253438deb443f107b5cd3b1b96 100644 (file)
@@ -153,8 +153,6 @@ void __bch2_btree_verify(struct bch_fs *c, struct btree *b)
                c->verify_data = __bch2_btree_node_mem_alloc(c);
                if (!c->verify_data)
                        goto out;
-
-               list_del_init(&c->verify_data->list);
        }
 
        BUG_ON(b->nsets != 1);