Some counters to keep track of what is causing us to skip over some entries causing potential leaks.
Signed-off-by: Daniel Hill <[email protected]> --- fs/bcachefs/btree_key_cache.c | 40 +++++++++++++++++++++++++---- fs/bcachefs/btree_key_cache_types.h | 4 +++ 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/fs/bcachefs/btree_key_cache.c b/fs/bcachefs/btree_key_cache.c index 74e52fd28abe..bed209a625cb 100644 --- a/fs/bcachefs/btree_key_cache.c +++ b/fs/bcachefs/btree_key_cache.c @@ -827,6 +827,7 @@ static unsigned long bch2_btree_key_cache_scan(struct shrinker *shrink, struct bucket_table *tbl; struct bkey_cached *ck, *t; size_t scanned = 0, freed = 0, nr = sc->nr_to_scan; + long shrinker_skipped = 0; unsigned start, flags; int srcu_idx; @@ -854,7 +855,7 @@ static unsigned long bch2_btree_key_cache_scan(struct shrinker *shrink, } if (scanned >= nr) - goto out; + goto freed_out; scanned += bc->nr_freed_pcpu; @@ -871,6 +872,9 @@ static unsigned long bch2_btree_key_cache_scan(struct shrinker *shrink, bc->nr_freed_pcpu--; } +freed_out: + atomic_long_add(freed > scanned ? 0 : scanned - freed, &bc->shrinker_srcu_skipped); + if (scanned >= nr) goto out; @@ -889,15 +893,21 @@ static unsigned long bch2_btree_key_cache_scan(struct shrinker *shrink, next = rht_dereference_bucket_rcu(pos->next, tbl, bc->shrink_iter); ck = container_of(pos, struct bkey_cached, hash); - if (test_bit(BKEY_CACHED_DIRTY, &ck->flags)) + if (test_bit(BKEY_CACHED_DIRTY, &ck->flags)) { + shrinker_skipped++; goto next; + } - if (test_bit(BKEY_CACHED_ACCESSED, &ck->flags)) + if (test_bit(BKEY_CACHED_ACCESSED, &ck->flags)) { clear_bit(BKEY_CACHED_ACCESSED, &ck->flags); + shrinker_skipped++; + } else if (bkey_cached_lock_for_evict(ck)) { bkey_cached_evict(bc, ck); bkey_cached_free(bc, ck); - } + + } else + shrinker_skipped++; scanned++; if (scanned >= nr) @@ -913,6 +923,9 @@ static unsigned long bch2_btree_key_cache_scan(struct shrinker *shrink, rcu_read_unlock(); out: + atomic_long_inc(&bc->shrinker_count); + atomic_long_add(nr, &bc->shrinker_to_scan); + atomic_long_add(shrinker_skipped, &bc->shrinker_skipped); memalloc_nofs_restore(flags); srcu_read_unlock(&c->btree_trans_barrier, srcu_idx); mutex_unlock(&bc->lock); @@ -1044,12 +1057,29 @@ int bch2_fs_btree_key_cache_init(struct btree_key_cache *bc) void bch2_btree_key_cache_to_text(struct printbuf *out, struct btree_key_cache *c) { - prt_printf(out, "nr_freed:\t%lu", atomic_long_read(&c->nr_freed)); + long scanned = atomic_long_read(&c->shrinker_to_scan); + long freed = atomic_long_read(&c->nr_freed); + + prt_printf(out, "nr_freed:\t%lu", freed); prt_newline(out); prt_printf(out, "nr_keys:\t%lu", atomic_long_read(&c->nr_keys)); prt_newline(out); prt_printf(out, "nr_dirty:\t%lu", atomic_long_read(&c->nr_dirty)); prt_newline(out); + prt_printf(out, "shrinker_count:\t%lu", atomic_long_read(&c->shrinker_count)); + prt_newline(out); + prt_printf(out, "shrinker_to_scan:\t\t%lu", scanned); + prt_newline(out); + prt_printf(out, "shrinker_skipped:\t\t%lu", + atomic_long_read(&c->shrinker_skipped)); + prt_newline(out); + prt_printf(out, "shrinker_srcu_skipped:\t\t%lu", + atomic_long_read(&c->shrinker_srcu_skipped)); + prt_newline(out); + prt_printf(out, "freed/scanned: "); + bch2_prt_percent_rational_u64(out, freed, scanned, 100); + prt_newline(out); + } void bch2_btree_key_cache_exit(void) diff --git a/fs/bcachefs/btree_key_cache_types.h b/fs/bcachefs/btree_key_cache_types.h index 290e4e57df5b..ba5dd263b2e4 100644 --- a/fs/bcachefs/btree_key_cache_types.h +++ b/fs/bcachefs/btree_key_cache_types.h @@ -24,6 +24,10 @@ struct btree_key_cache { atomic_long_t nr_freed; atomic_long_t nr_keys; atomic_long_t nr_dirty; + atomic_long_t shrinker_count; + atomic_long_t shrinker_to_scan; + atomic_long_t shrinker_skipped; + atomic_long_t shrinker_srcu_skipped; }; struct bkey_cached_key { -- 2.43.0
