summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2022-04-21 15:25:07 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2023-06-21 03:32:17 -0400
commit4bcd243a12545f1e48f4d2328dc7943085055403 (patch)
treed20e9ea87f9a0cc9f4e64911c554ea7fa6884cb1
parent4e09c1a9e752c08f2e944d3ef2de211a7239b2e2 (diff)
mm: Count requests to free & nr freed per shrinker
The next step in this patch series for improving debugging of shrinker related issues: keep counts of number of objects we request to free vs. actually freed, and prints them in shrinker_to_text(). Shrinkers won't necessarily free all objects requested for a variety of reasons, but if the two counts are wildly different something is likely amiss. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r--include/linux/shrinker.h3
-rw-r--r--mm/vmscan.c10
2 files changed, 12 insertions, 1 deletions
diff --git a/include/linux/shrinker.h b/include/linux/shrinker.h
index c9d24d39462e..7c146ac8878f 100644
--- a/include/linux/shrinker.h
+++ b/include/linux/shrinker.h
@@ -86,6 +86,9 @@ struct shrinker {
#endif
/* objs pending delete, per node */
atomic_long_t *nr_deferred;
+
+ atomic_long_t objects_requested_to_free;
+ atomic_long_t objects_freed;
};
#define DEFAULT_SEEKS 2 /* A good number if you don't know better. */
diff --git a/mm/vmscan.c b/mm/vmscan.c
index ce93194e73dd..34ec91b44f90 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -773,7 +773,11 @@ void shrinker_to_text(struct seq_buf *out, struct shrinker *shrinker)
struct shrink_control sc = { .gfp_mask = GFP_KERNEL, };
seq_buf_puts(out, shrinker->name);
- seq_buf_printf(out, " objects: %lu\n", shrinker->count_objects(shrinker, &sc));
+ seq_buf_putc(out, '\n');
+
+ seq_buf_printf(out, "objects: %lu\n", shrinker->count_objects(shrinker, &sc));
+ seq_buf_printf(out, "requested to free: %lu\n", atomic_long_read(&shrinker->objects_requested_to_free));
+ seq_buf_printf(out, "objects freed: %lu\n", atomic_long_read(&shrinker->objects_freed));
if (shrinker->to_text) {
shrinker->to_text(out, shrinker);
@@ -904,12 +908,16 @@ static unsigned long do_shrink_slab(struct shrink_control *shrinkctl,
unsigned long ret;
unsigned long nr_to_scan = min(batch_size, total_scan);
+ atomic_long_add(nr_to_scan, &shrinker->objects_requested_to_free);
+
shrinkctl->nr_to_scan = nr_to_scan;
shrinkctl->nr_scanned = nr_to_scan;
ret = shrinker->scan_objects(shrinker, shrinkctl);
if (ret == SHRINK_STOP)
break;
+
freed += ret;
+ atomic_long_add(ret, &shrinker->objects_freed);
count_vm_events(SLABS_SCANNED, shrinkctl->nr_scanned);
total_scan -= shrinkctl->nr_scanned;