diff options
Diffstat (limited to 'mm')
| -rw-r--r-- | mm/page_alloc.c | 75 |
1 files changed, 35 insertions, 40 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 5d12d156a..2c12348ac 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1312,32 +1312,20 @@ static int preferred_mt = MIGRATE_MOVABLE; #endif /* - * When we are falling back to another migratetype during allocation, try to - * steal extra free pages from the same pageblocks to satisfy further - * allocations, instead of polluting multiple pageblocks. - * - * If we are stealing a relatively large buddy page, it is likely there will - * be more free pages in the pageblock, so try to steal them all. For - * reclaimable and unmovable allocations, we steal regardless of page size, - * as fragmentation caused by those allocations polluting movable pageblocks - * is worse than movable allocations stealing from unmovable and reclaimable - * pageblocks. - * - * If we claim more than half of the pageblock, change pageblock's migratetype - * as well. + * If breaking a large block of pages, move all free pages to the preferred + * allocation list. If falling back for a reclaimable kernel allocation, be + * more aggressive about taking ownership of free pages. If we claim more than + * half of the pageblock, change pageblock's migratetype as well. */ -static int try_to_steal_freepages(struct zone *zone, struct page *page, +static void try_to_steal_freepages(struct zone *zone, struct page *page, int start_type, int fallback_type) { int current_order = page_order(page); - if (is_migrate_cma(fallback_type)) - return fallback_type; - /* Take ownership for orders >= pageblock_order */ if (current_order >= pageblock_order) { change_pageblock_range(page, current_order, start_type); - return start_type; + return; } if (current_order >= pageblock_order / 2 || @@ -1353,12 +1341,8 @@ static int try_to_steal_freepages(struct zone *zone, struct page *page, page_group_by_mobility_disabled) { set_pageblock_migratetype(page, start_type); - return start_type; } - } - - return fallback_type; } /* Remove an element from the buddy allocator from the fallback list */ @@ -1368,13 +1352,15 @@ __rmqueue_fallback(struct zone *zone, int order, int start_migratetype) struct free_area * area; int current_order; struct page *page; - int migratetype, new_type, i; /* Find the largest possible block of pages in the other list */ - for (current_order = MAX_ORDER-1; current_order >= order; - --current_order) { + for (current_order = MAX_ORDER-1; + current_order >= order && current_order <= MAX_ORDER-1; + --current_order) { + int i; for (i = 0;; i++) { - migratetype = fallbacks[start_migratetype][i]; + int migratetype = fallbacks[start_migratetype][i]; + int buddy_type = start_migratetype; /* MIGRATE_RESERVE handled later if necessary */ if (migratetype == MIGRATE_RESERVE) @@ -1420,9 +1406,19 @@ __rmqueue_fallback(struct zone *zone, int order, int start_migratetype) goto no_move; } - new_type = try_to_steal_freepages(zone, page, - start_migratetype, - migratetype); + if (!is_migrate_cma(migratetype)) { + try_to_steal_freepages(zone, page, + start_migratetype, + migratetype); + } else { + /* + * When borrowing from MIGRATE_CMA, we need to + * release the excess buddy pages to CMA + * itself, and we do not try to steal extra + * free pages. + */ + buddy_type = migratetype; + } /* Remove the page from the freelists */ list_del(&page->lru); @@ -1438,21 +1434,20 @@ no_move: * the excess buddy pages to CMA itself. */ expand(zone, page, order, current_order, area, -#if !defined(CONFIG_CMA) || !defined(CONFIG_MTK_SVP) // SVP 16 - (is_migrate_cma(migratetype) || is_migrate_mtkpasr(start_migratetype) || is_migrate_mtkpasr(migratetype)) -#else - (is_migrate_mtkpasr(start_migratetype) || is_migrate_mtkpasr(migratetype)) -#endif - ? migratetype : start_migratetype); - /* The freepage_migratetype may differ from pageblock's + buddy_type); + + /* + * The freepage_migratetype may differ from pageblock's * migratetype depending on the decisions in - * try_to_steal_freepages. This is OK as long as it does - * not differ for MIGRATE_CMA type. + * try_to_steal_freepages(). This is OK as long as it + * does not differ for MIGRATE_CMA pageblocks. For CMA + * we need to make sure unallocated pages flushed from + * pcp lists are returned to the correct freelist. */ - set_freepage_migratetype(page, new_type); + set_freepage_migratetype(page, buddy_type); trace_mm_page_alloc_extfrag(page, order, current_order, - start_migratetype, new_type); + start_migratetype, migratetype); return page; } |
