diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 514fd8008114..822babd808fe 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2301,7 +2301,7 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order, { struct zone *last_compact_zone = NULL; unsigned long compact_result; - + struct page *page; if (!order) return NULL; @@ -2313,50 +2313,56 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order, &last_compact_zone); current->flags &= ~PF_MEMALLOC; - if (compact_result > COMPACT_DEFERRED) - count_vm_event(COMPACTSTALL); - else + switch (compact_result) { + case COMPACT_DEFERRED: *deferred_compaction = true; - - if (compact_result > COMPACT_SKIPPED) { - struct page *page; - - /* Page migration frees to the PCP lists but we want merging */ - drain_pages(get_cpu()); - put_cpu(); - - page = get_page_from_freelist(gfp_mask, nodemask, - order, zonelist, high_zoneidx, - alloc_flags & ~ALLOC_NO_WATERMARKS, - preferred_zone, classzone_idx, migratetype); - - if (page) { - struct zone *zone = page_zone(page); - - zone->compact_blockskip_flush = false; - compaction_defer_reset(zone, order, true); - count_vm_event(COMPACTSUCCESS); - return page; - } - - /* - * last_compact_zone is where try_to_compact_pages thought - * allocation should succeed, so it did not defer compaction. - * But now we know that it didn't succeed, so we do the defer. - */ - if (last_compact_zone && mode != MIGRATE_ASYNC) - defer_compaction(last_compact_zone, order); - - /* - * It's bad if compaction run occurs and fails. - * The most likely reason is that pages exist, - * but not enough to satisfy watermarks. - */ - count_vm_event(COMPACTFAIL); - - cond_resched(); + /* fall-through */ + case COMPACT_SKIPPED: + return NULL; + default: + break; } + /* + * At least in one zone compaction wasn't deferred or skipped, so let's + * count a compaction stall + */ + count_vm_event(COMPACTSTALL); + + /* Page migration frees to the PCP lists but we want merging */ + drain_pages(get_cpu()); + put_cpu(); + + page = get_page_from_freelist(gfp_mask, nodemask, + order, zonelist, high_zoneidx, + alloc_flags & ~ALLOC_NO_WATERMARKS, + preferred_zone, classzone_idx, migratetype); + + if (page) { + struct zone *zone = page_zone(page); + + zone->compact_blockskip_flush = false; + compaction_defer_reset(zone, order, true); + count_vm_event(COMPACTSUCCESS); + return page; + } + + /* + * last_compact_zone is where try_to_compact_pages thought allocation + * should succeed, so it did not defer compaction. But here we know + * that it didn't succeed, so we do the defer. + */ + if (last_compact_zone && mode != MIGRATE_ASYNC) + defer_compaction(last_compact_zone, order); + + /* + * It's bad if compaction run occurs and fails. The most likely reason + * is that pages exist, but not enough to satisfy watermarks. + */ + count_vm_event(COMPACTFAIL); + + cond_resched(); + return NULL; } #else