mm: track actual nr_scanned during shrink_slab()
authorChris Wilson <chris@chris-wilson.co.uk>
Wed, 6 Sep 2017 23:19:26 +0000 (16:19 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 7 Sep 2017 00:27:24 +0000 (17:27 -0700)
Some shrinkers may only be able to free a bunch of objects at a time,
and so free more than the requested nr_to_scan in one pass.

Whilst other shrinkers may find themselves even unable to scan as many
objects as they counted, and so underreport.  Account for the extra
freed/scanned objects against the total number of objects we intend to
scan, otherwise we may end up penalising the slab far more than
intended.  Similarly, we want to add the underperforming scan to the
deferred pass so that we try harder and harder in future passes.

Link: http://lkml.kernel.org/r/20170822135325.9191-1-chris@chris-wilson.co.uk
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Hillf Danton <hillf.zj@alibaba-inc.com>
Cc: Minchan Kim <minchan@kernel.org>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Mel Gorman <mgorman@techsingularity.net>
Cc: Shaohua Li <shli@fb.com>
Cc: Christoph Lameter <cl@linux.com>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: David Rientjes <rientjes@google.com>
Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
include/linux/shrinker.h
mm/vmscan.c

index 4fcacd915d45adaf914c770f7d04f8b12b2a504a..51d189615bdaac321e32a6966ad689b7c37b78ce 100644 (file)
@@ -18,6 +18,13 @@ struct shrink_control {
         */
        unsigned long nr_to_scan;
 
+       /*
+        * How many objects did scan_objects process?
+        * This defaults to nr_to_scan before every call, but the callee
+        * should track its actual progress.
+        */
+       unsigned long nr_scanned;
+
        /* current node being shrunk (for NUMA aware shrinkers) */
        int nid;
 
index f957afe900ec2f86b1b4dc5d3de5518ea29e553f..095817820a56157031f4cc2235affeec4c252188 100644 (file)
@@ -393,14 +393,15 @@ static unsigned long do_shrink_slab(struct shrink_control *shrinkctl,
                unsigned long nr_to_scan = min(batch_size, total_scan);
 
                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;
 
-               count_vm_events(SLABS_SCANNED, nr_to_scan);
-               total_scan -= nr_to_scan;
-               scanned += nr_to_scan;
+               count_vm_events(SLABS_SCANNED, shrinkctl->nr_scanned);
+               total_scan -= shrinkctl->nr_scanned;
+               scanned += shrinkctl->nr_scanned;
 
                cond_resched();
        }