From 7fcd8c796f2da57da4ddda6b30e34813c4c43898 Mon Sep 17 00:00:00 2001 From: Charan Teja Reddy Date: Wed, 13 Nov 2019 20:12:10 +0530 Subject: [PATCH 1/4] mm: ignore the boosting of watermark under lowmemory When low on free memory and a fragmentation event at the same time will cause the zone watermarks to be offsetted by watermark_boost which in default is 150% of high watermark. The side effects of this is the time taken by the reclaim to reach that level and thus the subsequent reset of the watermark_boost can be higher and hence killing of the FG tasks can happen in that time frame despite the free memory is above zone->_watermark[WMARK_HIGH]. Ignore boosting of watermark under this condition and thus we can create more memory headroom. Change-Id: Ia1fa5d766eee851ad3456f41b4b2d623cf4eeee3 Signed-off-by: Charan Teja Reddy --- mm/page_alloc.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 642e8d221319..b25748c7963f 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2373,11 +2373,37 @@ static bool can_steal_fallback(unsigned int order, int start_mt) return false; } +static bool boost_eligible(struct zone *z) +{ + unsigned long high_wmark, threshold; + unsigned long reclaim_eligible, free_pages; + + high_wmark = z->_watermark[WMARK_HIGH]; + reclaim_eligible = zone_page_state_snapshot(z, NR_ZONE_INACTIVE_FILE) + + zone_page_state_snapshot(z, NR_ZONE_ACTIVE_FILE); + free_pages = zone_page_state(z, NR_FREE_PAGES); + threshold = high_wmark + (2 * mult_frac(high_wmark, + watermark_boost_factor, 10000)); + + /* + * Don't boost watermark If we are already low on memory where the + * boosting can simply put the watermarks at higher levels for a + * longer duration of time and thus the other users relied on the + * watermarks are forced to choose unintended decissions. If memory + * is so low, kswapd in normal mode should help. + */ + + if (reclaim_eligible < threshold && free_pages < threshold) + return false; + + return true; +} + static inline void boost_watermark(struct zone *zone) { unsigned long max_boost; - if (!watermark_boost_factor) + if (!watermark_boost_factor || !boost_eligible(zone)) return; max_boost = mult_frac(zone->_watermark[WMARK_HIGH], From 05ebc8f08cf404c3f3de2b95a7a577b722fbf23e Mon Sep 17 00:00:00 2001 From: Charan Teja Reddy Date: Thu, 14 Nov 2019 11:57:11 +0530 Subject: [PATCH 2/4] mm: ignore boosting for min watermark Ignore boosting for min watermark for __GFP_ATOMIC, ALLOC_HIGH and ALLOC_HARDER allocation requests. Of the others, this helps in avoiding the atomic allocation failures. Change-Id: I41dcc71ed37b7a1d2093d13f40e82c7750642e39 Signed-off-by: Charan Teja Reddy --- mm/page_alloc.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index b25748c7963f..92b50a496444 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -3770,6 +3770,20 @@ retry: } mark = wmark_pages(zone, alloc_flags & ALLOC_WMARK_MASK); + /* + * Allow high, atomic, harder order-0 allocation requests + * to skip the ->watermark_boost for min watermark check. + * In doing so, check for: + * 1) ALLOC_WMARK_MIN - Allow to wake up kswapd in the + * slow path. + * 2) ALLOC_HIGH - Allow high priority requests. + * 3) ALLOC_HARDER - Allow (__GFP_ATOMIC && !__GFP_NOMEMALLOC), + * of the others. + */ + if (unlikely(!order && (alloc_flags & ALLOC_WMARK_MIN) && + (alloc_flags & (ALLOC_HARDER | ALLOC_HIGH)))) { + mark = zone->_watermark[WMARK_MIN]; + } if (!zone_watermark_fast(zone, order, mark, ac_classzone_idx(ac), alloc_flags)) { int ret; From 2f2da11aecc46c7411105cbb8c1afa636798ac13 Mon Sep 17 00:00:00 2001 From: Charan Teja Reddy Date: Wed, 20 Nov 2019 12:54:27 +0530 Subject: [PATCH 3/4] mm: discard free cma pages in boost_eligible calculations Considering the free cma pages in boost_eligible can give wrong results. Subtract them. Change-Id: I5dd3e408bcaf109d51066323686d8d1930093e3b Fixes: 09d35acf52cb ("mm: ignore boosting for min watermark") Signed-off-by: Charan Teja Reddy --- mm/page_alloc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 92b50a496444..47a10f488b66 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2381,7 +2381,8 @@ static bool boost_eligible(struct zone *z) high_wmark = z->_watermark[WMARK_HIGH]; reclaim_eligible = zone_page_state_snapshot(z, NR_ZONE_INACTIVE_FILE) + zone_page_state_snapshot(z, NR_ZONE_ACTIVE_FILE); - free_pages = zone_page_state(z, NR_FREE_PAGES); + free_pages = zone_page_state(z, NR_FREE_PAGES) - + zone_page_state(z, NR_FREE_CMA_PAGES); threshold = high_wmark + (2 * mult_frac(high_wmark, watermark_boost_factor, 10000)); From 0a475ab309bacffc7d2c6ac9bcd480ba77666872 Mon Sep 17 00:00:00 2001 From: Charan Teja Reddy Date: Wed, 27 Nov 2019 18:32:48 +0530 Subject: [PATCH 4/4] mm: correct ALLOC_WMARK_MIN flag check for atomic allocations ALLOC_WMARK_[MIN|LOW|HIGH] are the indexes into the zones->_watermark array. Use ALLOC_WMARK_MASK to get a particular water mark alloc flag. Correct this logic for atomic order-0 allocations watermark check. Change-Id: I5a74abd579df2ddcca63fdd99a090ca83ccd481c Fixes: 6b274863bca8 ("mm: ignore boosting for min watermark") Signed-off-by: Charan Teja Reddy --- mm/page_alloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 47a10f488b66..2f756ca4eb3c 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -3781,7 +3781,7 @@ retry: * 3) ALLOC_HARDER - Allow (__GFP_ATOMIC && !__GFP_NOMEMALLOC), * of the others. */ - if (unlikely(!order && (alloc_flags & ALLOC_WMARK_MIN) && + if (unlikely(!order && !(alloc_flags & ALLOC_WMARK_MASK) && (alloc_flags & (ALLOC_HARDER | ALLOC_HIGH)))) { mark = zone->_watermark[WMARK_MIN]; }