Blob Blame History Raw
From: Vlastimil Babka <vbabka@suse.cz>
Subject: pagecache limit: fix wrong nr_reclaimed count
Patch-mainline: never, SUSE specific
References: FATE#309111, bnc#924701

During development of tracepoints for pagecache limit reclaim, it was found out
that the total accumulated nr_reclaimed count in __shrink_page_cache() stored
in variable "ret" can be higher than the real value when more than one
shrink_all_zones() passes are performed during the reclaim. This happens
because shrink_all_zones() uses sc.nr_reclaimed to accumulate work from all
passes, but __shrink_page_cache() assumes the value corresponds to a single
pass and performs own accumulation in the "ret" variable. This may result in
multiple accumulation and thus premature exits from __shrink_page_cache()
instead of retrying with higher priority as intended.

The issue is limited in practice, as the number of pages to reclaim is
capped at 8*SWAP_CLUSTER_MAX anyway. However, the implementation should work
as intended, and we want to report the accumulated count in a tracepoint, so
it should be corrected also to allow proper performance analysis.

The patch fixes the issue by removing the accumulation in shrink_all_zones()
and leaving it only __shrink_page_cache() where it is needed. After the patch
shrink_all_zones() will set sc->nr_reclaimed according to how much was
reclaimed during a single call of the function.

Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
Acked-by: Michal Hocko <mhocko@suse.cz>

---
 mm/vmscan.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -3851,8 +3851,8 @@ static int shrink_all_nodes(unsigned lon
 
 out_wakeup:
 	wake_up_interruptible(&pagecache_reclaim_wq);
-	sc->nr_reclaimed += nr_reclaimed;
 out:
+	sc->nr_reclaimed = nr_reclaimed;
 	return nr_locked_zones;
 }