From db3710af8b80866fcbfa9ae4a9843c1f3c8fe51a Mon Sep 17 00:00:00 2001 From: Sultan Alsawaf Date: Fri, 28 Feb 2020 12:57:20 -0800 Subject: [PATCH] mm: vmpressure: Don't cache the window size Caching the window size can result in delayed or inaccurate pressure reports. Since calculating a fresh window size is cheap, do so all the time instead of relying on a stale, cached value. Signed-off-by: Sultan Alsawaf --- mm/vmpressure.c | 123 +----------------------------------------------- 1 file changed, 1 insertion(+), 122 deletions(-) diff --git a/mm/vmpressure.c b/mm/vmpressure.c index c3dfaecc9c88..41feba964d5b 100755 --- a/mm/vmpressure.c +++ b/mm/vmpressure.c @@ -27,22 +27,6 @@ #include #include -/* - * The window size (vmpressure_win) is the number of scanned pages before - * we try to analyze scanned/reclaimed ratio. So the window is used as a - * rate-limit tunable for the "low" level notification, and also for - * averaging the ratio for medium/critical levels. Using small window - * sizes can cause lot of false positives, but too big window size will - * delay the notifications. - * - * As the vmscan reclaimer logic works with chunks which are multiple of - * SWAP_CLUSTER_MAX, it makes sense to use it for the window size as well. - * - * TODO: Make the window size depend on machine size, as we do for vmstat - * thresholds. Currently we set it to 512 pages (2MB for 4KB pages). - */ -static unsigned long vmpressure_win = SWAP_CLUSTER_MAX * 16; - /* * These thresholds are used when we account memory pressure through * scanned/reclaimed ratio. The current values were chosen empirically. In @@ -416,107 +400,6 @@ static void __vmpressure(gfp_t gfp, struct mem_cgroup *memcg, bool critical, vmpressure_memcg(gfp, memcg, critical, tree, scanned, reclaimed); } -/** - * vmpressure() - Account memory pressure through scanned/reclaimed ratio - * @gfp: reclaimer's gfp mask - * @memcg: cgroup memory controller handle - * @tree: legacy subtree mode - * @scanned: number of pages scanned - * @reclaimed: number of pages reclaimed - * - * This function should be called from the vmscan reclaim path to account - * "instantaneous" memory pressure (scanned/reclaimed ratio). The raw - * pressure index is then further refined and averaged over time. - * - * If @tree is set, vmpressure is in traditional userspace reporting - * mode: @memcg is considered the pressure root and userspace is - * notified of the entire subtree's reclaim efficiency. - * - * If @tree is not set, reclaim efficiency is recorded for @memcg, and - * only in-kernel users are notified. - * - * This function does not return any value. - */ -void vmpressure(gfp_t gfp, struct mem_cgroup *memcg, bool tree, - unsigned long scanned, unsigned long reclaimed, int order) -{ - if (order > PAGE_ALLOC_COSTLY_ORDER) - return; - - __vmpressure(gfp, memcg, false, tree, scanned, reclaimed); -} -#else -static void vmpressure_memcg(gfp_t gfp, struct mem_cgroup *memcg, bool tree, - unsigned long scanned, unsigned long reclaimed) -{ -} -#endif - -static void calculate_vmpressure_win(void) -{ - long x; - - x = global_node_page_state(NR_FILE_PAGES) - - global_node_page_state(NR_SHMEM) - - total_swapcache_pages() + - global_zone_page_state(NR_FREE_PAGES); - if (x < 1) - x = 1; - /* - * For low (free + cached), vmpressure window should be - * small, and high for higher values of (free + cached). - * But it should not be linear as well. This ensures - * timely vmpressure notifications when system is under - * memory pressure, and optimal number of events when - * cached is high. The sqaure root function is empirically - * found to serve the purpose. - */ - x = int_sqrt(x); - vmpressure_win = x; -} - -static void vmpressure_global(gfp_t gfp, unsigned long scanned, - unsigned long reclaimed) -{ - struct vmpressure *vmpr = &global_vmpressure; - unsigned long pressure; - unsigned long stall; - - if (scanned) { - spin_lock(&vmpr->sr_lock); - if (!vmpr->scanned) - calculate_vmpressure_win(); - - vmpr->scanned += scanned; - vmpr->reclaimed += reclaimed; - - if (!current_is_kswapd()) - vmpr->stall += scanned; - - stall = vmpr->stall; - scanned = vmpr->scanned; - reclaimed = vmpr->reclaimed; - spin_unlock(&vmpr->sr_lock); - - if (scanned < vmpressure_win) - return; - } - - spin_lock(&vmpr->sr_lock); - vmpr->scanned = 0; - vmpr->reclaimed = 0; - vmpr->stall = 0; - spin_unlock(&vmpr->sr_lock); - - if (scanned) { - pressure = vmpressure_calc_pressure(scanned, reclaimed); - pressure = vmpressure_account_stall(pressure, stall, scanned); - } else { - pressure = 100; - } - vmpressure_notify(pressure); -} - /** * vmpressure() - Account memory pressure through scanned/reclaimed ratio * @gfp: reclaimer's gfp mask @@ -541,11 +424,7 @@ static void vmpressure_global(gfp_t gfp, unsigned long scanned, void vmpressure(gfp_t gfp, struct mem_cgroup *memcg, bool tree, unsigned long scanned, unsigned long reclaimed) { - if (!memcg && tree) - vmpressure_global(gfp, scanned, reclaimed); - - if (IS_ENABLED(CONFIG_MEMCG)) - vmpressure_memcg(gfp, memcg, tree, scanned, reclaimed); + __vmpressure(gfp, memcg, false, tree, scanned, reclaimed); } /**