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@xxxxxxxxx> --- include/linux/shrinker.h | 3 +++ mm/vmscan.c | 16 +++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/include/linux/shrinker.h b/include/linux/shrinker.h index b5f411768b..12967748f9 100644 --- a/include/linux/shrinker.h +++ b/include/linux/shrinker.h @@ -79,6 +79,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 905bc23800..12562546a7 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -711,16 +711,22 @@ void shrinker_to_text(struct printbuf *out, struct shrinker *shrinker) pr_buf(out, "%s", shrinker->name); else pr_buf(out, "%ps:", shrinker->scan_objects); + pr_newline(out); + pr_indent_push(out, 2); - pr_buf(out, " objects: %lu", shrinker->count_objects(shrinker, &sc)); + pr_buf(out, "objects: %lu", shrinker->count_objects(shrinker, &sc)); + pr_newline(out); + pr_buf(out, "requested to free: %lu", atomic_long_read(&shrinker->objects_requested_to_free)); + pr_newline(out); + pr_buf(out, "objects freed: %lu", atomic_long_read(&shrinker->objects_freed)); pr_newline(out); if (shrinker->to_text) { - pr_indent_push(out, 2); shrinker->to_text(out, shrinker); - pr_indent_pop(out, 2); pr_newline(out); } + + pr_indent_pop(out, 2); } /** @@ -846,12 +852,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; -- 2.35.2