From f4b5d78d60082b49879fceb6d3a7cb4b75e7c60b Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Mon, 24 Oct 2011 16:33:42 -0700 Subject: mm: avoid livelock on !__GFP_FS allocations Under the following conditions, __alloc_pages_slowpath can loop forever: gfp_mask & __GFP_WAIT is true gfp_mask & __GFP_FS is false reclaim and compaction make no progress order <= PAGE_ALLOC_COSTLY_ORDER The gfp conditions are normally invalid, because !__GFP_FS disables most of the reclaim methods that __GFP_WAIT would wait for. However, these conditions happen very often during suspend and resume, when pm_restrict_gfp_mask() effectively converts all GFP_KERNEL allocations into __GFP_WAIT. The oom killer is not run because gfp_mask & __GFP_FS is false, but should_alloc_retry will always return true when order is less than PAGE_ALLOC_COSTLY_ORDER. __alloc_pages_slowpath will loop forever between the rebalance label and should_alloc_retry, unless another thread happens to release enough pages to satisfy the allocation. Add a check to detect when PM has disabled __GFP_FS, and do not retry if reclaim is not making any progress. [taken from patch on lkml by Mel Gorman, commit message by ccross] Change-Id: I864a24e9d9fd98bd0e3d6e9c1e85b6c1b766850e Signed-off-by: Colin Cross --- mm/page_alloc.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'mm') diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 41253539b32a..75cd8d74a1a5 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -127,6 +127,20 @@ void pm_restrict_gfp_mask(void) saved_gfp_mask = gfp_allowed_mask; gfp_allowed_mask &= ~GFP_IOFS; } + +static bool pm_suspending(void) +{ + if ((gfp_allowed_mask & GFP_IOFS) == GFP_IOFS) + return false; + return true; +} + +#else + +static bool pm_suspending(void) +{ + return false; +} #endif /* CONFIG_PM_SLEEP */ #ifdef CONFIG_HUGETLB_PAGE_SIZE_VARIABLE @@ -2208,6 +2222,14 @@ rebalance: goto restart; } + + /* + * Suspend converts GFP_KERNEL to __GFP_WAIT which can + * prevent reclaim making forward progress without + * invoking OOM. Bail if we are suspending + */ + if (pm_suspending()) + goto nopage; } /* Check if we should retry the allocation */ -- cgit v1.2.3