bcachefs: __btree_node_reclaim_checks()

Factor out a helper so we're not duplicating checks after locking the
btree node.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Kent Overstreet
2025-04-13 07:45:13 -04:00
parent 68aaeb7c8b
commit e50fe14c54

View File

@@ -344,6 +344,69 @@ static inline struct btree *btree_cache_find(struct btree_cache *bc,
return rhashtable_lookup_fast(&bc->table, &v, bch_btree_cache_params);
}
static int __btree_node_reclaim_checks(struct bch_fs *c, struct btree *b,
bool flush, bool locked)
{
struct btree_cache *bc = &c->btree_cache;
lockdep_assert_held(&bc->lock);
if (btree_node_noevict(b)) {
bc->not_freed[BCH_BTREE_CACHE_NOT_FREED_noevict]++;
return -BCH_ERR_ENOMEM_btree_node_reclaim;
}
if (btree_node_write_blocked(b)) {
bc->not_freed[BCH_BTREE_CACHE_NOT_FREED_write_blocked]++;
return -BCH_ERR_ENOMEM_btree_node_reclaim;
}
if (btree_node_will_make_reachable(b)) {
bc->not_freed[BCH_BTREE_CACHE_NOT_FREED_will_make_reachable]++;
return -BCH_ERR_ENOMEM_btree_node_reclaim;
}
if (btree_node_dirty(b)) {
if (!flush) {
bc->not_freed[BCH_BTREE_CACHE_NOT_FREED_dirty]++;
return -BCH_ERR_ENOMEM_btree_node_reclaim;
}
if (locked) {
/*
* Using the underscore version because we don't want to compact
* bsets after the write, since this node is about to be evicted
* - unless btree verify mode is enabled, since it runs out of
* the post write cleanup:
*/
if (bch2_verify_btree_ondisk)
bch2_btree_node_write(c, b, SIX_LOCK_intent,
BTREE_WRITE_cache_reclaim);
else
__bch2_btree_node_write(c, b,
BTREE_WRITE_cache_reclaim);
}
}
if (b->flags & ((1U << BTREE_NODE_read_in_flight)|
(1U << BTREE_NODE_write_in_flight))) {
if (!flush) {
if (btree_node_read_in_flight(b))
bc->not_freed[BCH_BTREE_CACHE_NOT_FREED_read_in_flight]++;
else if (btree_node_write_in_flight(b))
bc->not_freed[BCH_BTREE_CACHE_NOT_FREED_write_in_flight]++;
return -BCH_ERR_ENOMEM_btree_node_reclaim;
}
if (locked)
return -EINTR;
/* XXX: waiting on IO with btree cache lock held */
bch2_btree_node_wait_on_read(b);
bch2_btree_node_wait_on_write(b);
}
return 0;
}
/*
* this version is for btree nodes that have already been freed (we're not
* reaping a real btree node)
@@ -354,24 +417,10 @@ static int __btree_node_reclaim(struct bch_fs *c, struct btree *b, bool flush)
int ret = 0;
lockdep_assert_held(&bc->lock);
wait_on_io:
if (b->flags & ((1U << BTREE_NODE_dirty)|
(1U << BTREE_NODE_read_in_flight)|
(1U << BTREE_NODE_write_in_flight))) {
if (!flush) {
if (btree_node_dirty(b))
bc->not_freed[BCH_BTREE_CACHE_NOT_FREED_dirty]++;
else if (btree_node_read_in_flight(b))
bc->not_freed[BCH_BTREE_CACHE_NOT_FREED_read_in_flight]++;
else if (btree_node_write_in_flight(b))
bc->not_freed[BCH_BTREE_CACHE_NOT_FREED_write_in_flight]++;
return -BCH_ERR_ENOMEM_btree_node_reclaim;
}
/* XXX: waiting on IO with btree cache lock held */
bch2_btree_node_wait_on_read(b);
bch2_btree_node_wait_on_write(b);
}
retry_unlocked:
ret = __btree_node_reclaim_checks(c, b, flush, false);
if (ret)
return ret;
if (!six_trylock_intent(&b->c.lock)) {
bc->not_freed[BCH_BTREE_CACHE_NOT_FREED_lock_intent]++;
@@ -380,69 +429,23 @@ static int __btree_node_reclaim(struct bch_fs *c, struct btree *b, bool flush)
if (!six_trylock_write(&b->c.lock)) {
bc->not_freed[BCH_BTREE_CACHE_NOT_FREED_lock_write]++;
goto out_unlock_intent;
six_unlock_intent(&b->c.lock);
return -BCH_ERR_ENOMEM_btree_node_reclaim;
}
/* recheck under lock */
if (b->flags & ((1U << BTREE_NODE_read_in_flight)|
(1U << BTREE_NODE_write_in_flight))) {
if (!flush) {
if (btree_node_read_in_flight(b))
bc->not_freed[BCH_BTREE_CACHE_NOT_FREED_read_in_flight]++;
else if (btree_node_write_in_flight(b))
bc->not_freed[BCH_BTREE_CACHE_NOT_FREED_write_in_flight]++;
goto out_unlock;
}
ret = __btree_node_reclaim_checks(c, b, flush, true);
if (ret) {
six_unlock_write(&b->c.lock);
six_unlock_intent(&b->c.lock);
goto wait_on_io;
if (ret == -EINTR)
goto retry_unlocked;
return ret;
}
if (btree_node_noevict(b)) {
bc->not_freed[BCH_BTREE_CACHE_NOT_FREED_noevict]++;
goto out_unlock;
}
if (btree_node_write_blocked(b)) {
bc->not_freed[BCH_BTREE_CACHE_NOT_FREED_write_blocked]++;
goto out_unlock;
}
if (btree_node_will_make_reachable(b)) {
bc->not_freed[BCH_BTREE_CACHE_NOT_FREED_will_make_reachable]++;
goto out_unlock;
}
if (btree_node_dirty(b)) {
if (!flush) {
bc->not_freed[BCH_BTREE_CACHE_NOT_FREED_dirty]++;
goto out_unlock;
}
/*
* Using the underscore version because we don't want to compact
* bsets after the write, since this node is about to be evicted
* - unless btree verify mode is enabled, since it runs out of
* the post write cleanup:
*/
if (bch2_verify_btree_ondisk)
bch2_btree_node_write(c, b, SIX_LOCK_intent,
BTREE_WRITE_cache_reclaim);
else
__bch2_btree_node_write(c, b,
BTREE_WRITE_cache_reclaim);
six_unlock_write(&b->c.lock);
six_unlock_intent(&b->c.lock);
goto wait_on_io;
}
out:
if (b->hash_val && !ret)
trace_and_count(c, btree_cache_reap, c, b);
return ret;
out_unlock:
six_unlock_write(&b->c.lock);
out_unlock_intent:
six_unlock_intent(&b->c.lock);
ret = -BCH_ERR_ENOMEM_btree_node_reclaim;
goto out;
return 0;
}
static int btree_node_reclaim(struct bch_fs *c, struct btree *b)