aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Weiner <hannes@cmpxchg.org>2015-06-24 19:57:21 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-06-24 20:49:43 -0400
commit9083905a2a13dec4093a9c35a9b7f60037b87672 (patch)
tree8f1400ca04d102e6b489053b2595247e24aa7094
parentdc56401fc9f25e8f93899991ec858c98a331d88c (diff)
mm: page_alloc: inline should_alloc_retry()
The should_alloc_retry() function was meant to encapsulate retry conditions of the allocator slowpath, but there are still checks remaining in the main function, and much of how the retrying is performed also depends on the OOM killer progress. The physical separation of those conditions make the code hard to follow. Inline the should_alloc_retry() checks. Notes: - The __GFP_NOFAIL check is already done in __alloc_pages_may_oom(), replace it with looping on OOM killer progress - The pm_suspended_storage() check is meant to skip the OOM killer when reclaim has no IO available, move to __alloc_pages_may_oom() - The order <= PAGE_ALLOC_COSTLY order is re-united with its original counterpart of checking whether reclaim actually made any progress Signed-off-by: Johannes Weiner <hannes@cmpxchg.org> Acked-by: Michal Hocko <mhocko@suse.cz> Cc: David Rientjes <rientjes@google.com> Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Cc: Andrea Arcangeli <aarcange@redhat.com> Cc: Dave Chinner <david@fromorbit.com> Cc: Vlastimil Babka <vbabka@suse.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--mm/page_alloc.c104
1 files changed, 32 insertions, 72 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index cae21dc9d54e..2880f6f61d05 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -2309,48 +2309,6 @@ void warn_alloc_failed(gfp_t gfp_mask, int order, const char *fmt, ...)
2309 show_mem(filter); 2309 show_mem(filter);
2310} 2310}
2311 2311
2312static inline int
2313should_alloc_retry(gfp_t gfp_mask, unsigned int order,
2314 unsigned long did_some_progress,
2315 unsigned long pages_reclaimed)
2316{
2317 /* Do not loop if specifically requested */
2318 if (gfp_mask & __GFP_NORETRY)
2319 return 0;
2320
2321 /* Always retry if specifically requested */
2322 if (gfp_mask & __GFP_NOFAIL)
2323 return 1;
2324
2325 /*
2326 * Suspend converts GFP_KERNEL to __GFP_WAIT which can prevent reclaim
2327 * making forward progress without invoking OOM. Suspend also disables
2328 * storage devices so kswapd will not help. Bail if we are suspending.
2329 */
2330 if (!did_some_progress && pm_suspended_storage())
2331 return 0;
2332
2333 /*
2334 * In this implementation, order <= PAGE_ALLOC_COSTLY_ORDER
2335 * means __GFP_NOFAIL, but that may not be true in other
2336 * implementations.
2337 */
2338 if (order <= PAGE_ALLOC_COSTLY_ORDER)
2339 return 1;
2340
2341 /*
2342 * For order > PAGE_ALLOC_COSTLY_ORDER, if __GFP_REPEAT is
2343 * specified, then we retry until we no longer reclaim any pages
2344 * (above), or we've reclaimed an order of pages at least as
2345 * large as the allocation's order. In both cases, if the
2346 * allocation still fails, we stop retrying.
2347 */
2348 if (gfp_mask & __GFP_REPEAT && pages_reclaimed < (1 << order))
2349 return 1;
2350
2351 return 0;
2352}
2353
2354static inline struct page * 2312static inline struct page *
2355__alloc_pages_may_oom(gfp_t gfp_mask, unsigned int order, 2313__alloc_pages_may_oom(gfp_t gfp_mask, unsigned int order,
2356 const struct alloc_context *ac, unsigned long *did_some_progress) 2314 const struct alloc_context *ac, unsigned long *did_some_progress)
@@ -2389,16 +2347,18 @@ __alloc_pages_may_oom(gfp_t gfp_mask, unsigned int order,
2389 /* The OOM killer does not needlessly kill tasks for lowmem */ 2347 /* The OOM killer does not needlessly kill tasks for lowmem */
2390 if (ac->high_zoneidx < ZONE_NORMAL) 2348 if (ac->high_zoneidx < ZONE_NORMAL)
2391 goto out; 2349 goto out;
2392 /* The OOM killer does not compensate for light reclaim */ 2350 /* The OOM killer does not compensate for IO-less reclaim */
2393 if (!(gfp_mask & __GFP_FS)) { 2351 if (!(gfp_mask & __GFP_FS)) {
2394 /* 2352 /*
2395 * XXX: Page reclaim didn't yield anything, 2353 * XXX: Page reclaim didn't yield anything,
2396 * and the OOM killer can't be invoked, but 2354 * and the OOM killer can't be invoked, but
2397 * keep looping as per should_alloc_retry(). 2355 * keep looping as per tradition.
2398 */ 2356 */
2399 *did_some_progress = 1; 2357 *did_some_progress = 1;
2400 goto out; 2358 goto out;
2401 } 2359 }
2360 if (pm_suspended_storage())
2361 goto out;
2402 /* The OOM killer may not free memory on a specific node */ 2362 /* The OOM killer may not free memory on a specific node */
2403 if (gfp_mask & __GFP_THISNODE) 2363 if (gfp_mask & __GFP_THISNODE)
2404 goto out; 2364 goto out;
@@ -2781,40 +2741,40 @@ retry:
2781 if (page) 2741 if (page)
2782 goto got_pg; 2742 goto got_pg;
2783 2743
2784 /* Check if we should retry the allocation */ 2744 /* Do not loop if specifically requested */
2745 if (gfp_mask & __GFP_NORETRY)
2746 goto noretry;
2747
2748 /* Keep reclaiming pages as long as there is reasonable progress */
2785 pages_reclaimed += did_some_progress; 2749 pages_reclaimed += did_some_progress;
2786 if (should_alloc_retry(gfp_mask, order, did_some_progress, 2750 if ((did_some_progress && order <= PAGE_ALLOC_COSTLY_ORDER) ||
2787 pages_reclaimed)) { 2751 ((gfp_mask & __GFP_REPEAT) && pages_reclaimed < (1 << order))) {
2788 /*
2789 * If we fail to make progress by freeing individual
2790 * pages, but the allocation wants us to keep going,
2791 * start OOM killing tasks.
2792 */
2793 if (!did_some_progress) {
2794 page = __alloc_pages_may_oom(gfp_mask, order, ac,
2795 &did_some_progress);
2796 if (page)
2797 goto got_pg;
2798 if (!did_some_progress)
2799 goto nopage;
2800 }
2801 /* Wait for some write requests to complete then retry */ 2752 /* Wait for some write requests to complete then retry */
2802 wait_iff_congested(ac->preferred_zone, BLK_RW_ASYNC, HZ/50); 2753 wait_iff_congested(ac->preferred_zone, BLK_RW_ASYNC, HZ/50);
2803 goto retry; 2754 goto retry;
2804 } else {
2805 /*
2806 * High-order allocations do not necessarily loop after
2807 * direct reclaim and reclaim/compaction depends on compaction
2808 * being called after reclaim so call directly if necessary
2809 */
2810 page = __alloc_pages_direct_compact(gfp_mask, order,
2811 alloc_flags, ac, migration_mode,
2812 &contended_compaction,
2813 &deferred_compaction);
2814 if (page)
2815 goto got_pg;
2816 } 2755 }
2817 2756
2757 /* Reclaim has failed us, start killing things */
2758 page = __alloc_pages_may_oom(gfp_mask, order, ac, &did_some_progress);
2759 if (page)
2760 goto got_pg;
2761
2762 /* Retry as long as the OOM killer is making progress */
2763 if (did_some_progress)
2764 goto retry;
2765
2766noretry:
2767 /*
2768 * High-order allocations do not necessarily loop after
2769 * direct reclaim and reclaim/compaction depends on compaction
2770 * being called after reclaim so call directly if necessary
2771 */
2772 page = __alloc_pages_direct_compact(gfp_mask, order, alloc_flags,
2773 ac, migration_mode,
2774 &contended_compaction,
2775 &deferred_compaction);
2776 if (page)
2777 goto got_pg;
2818nopage: 2778nopage:
2819 warn_alloc_failed(gfp_mask, order, NULL); 2779 warn_alloc_failed(gfp_mask, order, NULL);
2820got_pg: 2780got_pg: