From aefaddd89769524f50eaf617a0579e0714b41f4a Mon Sep 17 00:00:00 2001 From: Vinayak Menon Date: Tue, 7 Jun 2016 15:23:29 +0530 Subject: [PATCH] mm: fix cma accounting in zone_watermark_ok Some cases were reported on 3.18 where atomic unmovable allocations of order 2 fails, but kswapd does not wakeup. And in such cases it was seen that, when zone_watermark_ok check is performed to decide whether to wake up kswapd, there were lot of CMA pages of order 2 and above. This makes the watermark check succeed resulting in kswapd not being woken up. But since these atomic unmovable allocations can't come from CMA region, further atomic allocations keeps failing, without kswapd trying to reclaim. Usually concurrent movable allocations result in reclaim and improves the situtation, but the case reported was from a network test which was resulting in only atomic skb allocations being attempted. On 3.18 this was fixed by adding a cma free page counter and accouting the cma free pages properly in watermark calculations. Later this issue was indirectly fixed by the commit "mm, page_alloc: only enforce watermarks for order-0 allocations". But the commit "mm: add cma pcp list" brought the problem back because it includes MIGRATE_CMA within MIGRATE_PCPTYPES, and thus watermark check erroneously returns success for !ALLOC_CMA by finding free pages in cma free list. Change-Id: Id0e48b5c2f9deea93c5875c10d5ec72bd360df5f Signed-off-by: Vinayak Menon Signed-off-by: Charan Teja Reddy [isaacm@codeaurora.org: resolve merge conflicts] Signed-off-by: Isaac J. Manjarres --- mm/page_alloc.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index ac548046c172..8e4a2b995a38 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -3549,6 +3549,14 @@ bool __zone_watermark_ok(struct zone *z, unsigned int order, unsigned long mark, continue; for (mt = 0; mt < MIGRATE_PCPTYPES; mt++) { +#ifdef CONFIG_CMA + /* + * Note that this check is needed only + * when MIGRATE_CMA < MIGRATE_PCPTYPES. + */ + if (mt == MIGRATE_CMA) + continue; +#endif if (!free_area_empty(area, mt)) return true; }