diff options
Diffstat (limited to 'libbcachefs/btree_cache.c')
-rw-r--r-- | libbcachefs/btree_cache.c | 49 |
1 files changed, 47 insertions, 2 deletions
diff --git a/libbcachefs/btree_cache.c b/libbcachefs/btree_cache.c index c37c8959..bdbe21ac 100644 --- a/libbcachefs/btree_cache.c +++ b/libbcachefs/btree_cache.c @@ -163,10 +163,14 @@ static int __btree_node_reclaim(struct bch_fs *c, struct btree *b, bool flush) goto out_unlock; if (btree_node_dirty(b) || - btree_node_write_in_flight(b)) { + btree_node_write_in_flight(b) || + btree_node_read_in_flight(b)) { if (!flush) goto out_unlock; + wait_on_bit_io(&b->flags, BTREE_NODE_read_in_flight, + TASK_UNINTERRUPTIBLE); + /* * Using the underscore version because we don't want to compact * bsets after the write, since this node is about to be evicted @@ -582,7 +586,7 @@ static noinline struct btree *bch2_btree_node_fill(struct btree_iter *iter, if (btree_node_read_locked(iter, level + 1)) btree_node_unlock(iter, level + 1); - bch2_btree_node_read(c, b); + bch2_btree_node_read(c, b, true); six_unlock_write(&b->lock); if (lock_type == SIX_LOCK_read) @@ -673,6 +677,9 @@ retry: } } + wait_on_bit_io(&b->flags, BTREE_NODE_read_in_flight, + TASK_UNINTERRUPTIBLE); + prefetch(b->aux_data); for_each_bset(b, t) { @@ -700,6 +707,44 @@ retry: return b; } +void bch2_btree_node_prefetch(struct btree_iter *iter, + const struct bkey_i *k, unsigned level) +{ + struct bch_fs *c = iter->c; + struct btree *b; + + BUG_ON(level >= BTREE_MAX_DEPTH); + + rcu_read_lock(); + b = mca_find(c, k); + rcu_read_unlock(); + + if (b) + return; + + b = bch2_btree_node_mem_alloc(c); + if (IS_ERR(b)) + return; + + bkey_copy(&b->key, k); + if (bch2_btree_node_hash_insert(c, b, level, iter->btree_id)) { + /* raced with another fill: */ + + /* mark as unhashed... */ + bkey_i_to_extent(&b->key)->v._data[0] = 0; + + mutex_lock(&c->btree_cache_lock); + list_add(&b->list, &c->btree_cache_freeable); + mutex_unlock(&c->btree_cache_lock); + goto out; + } + + bch2_btree_node_read(c, b, false); +out: + six_unlock_write(&b->lock); + six_unlock_intent(&b->lock); +} + int bch2_print_btree_node(struct bch_fs *c, struct btree *b, char *buf, size_t len) { |