Some shrinkers may free more than the requested nr_to_scan of pages in one invocation of scan_objects, and some may free less than that. Currently shrinkers can either return the actual number of pages that have been freed via the return value of scan_objects or track that actual number in shrinkctl->nr_scanned. But do_shrink_slab works on an assumption that the actual number is always tracked via shrinkctl->nr_scanned, which is not true. Having checked the shrinkers used in the kernel, they basically return the actual number of freed pages via the return value of scan_objects, and most of them leave shrinkctl->nr_scanned unchanged after scan_objects is called. So this patch adjusts shrinkctl->nr_scanned to the actual freed number after scan_objects is called. Signed-off-by: Wei Wang <wei.w.wang@xxxxxxxxx> Cc: Michal Hocko <mhocko@xxxxxxxxxx> Cc: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> Cc: Tetsuo Handa <penguin-kernel@xxxxxxxxxxxxxxxxxxx> Cc: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx> Cc: Michael S. Tsirkin <mst@xxxxxxxxxx> --- mm/vmscan.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index 03822f8..78a75b9 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -447,9 +447,13 @@ static unsigned long do_shrink_slab(struct shrink_control *shrinkctl, if (ret == SHRINK_STOP) break; freed += ret; + shrinkctl->nr_scanned = ret; count_vm_events(SLABS_SCANNED, shrinkctl->nr_scanned); - total_scan -= shrinkctl->nr_scanned; + if (total_scan > shrinkctl->nr_scanned) + total_scan -= shrinkctl->nr_scanned; + else + total_scan = 0; scanned += shrinkctl->nr_scanned; cond_resched(); -- 2.7.4