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


Reply via email to