|
@@ -1125,33 +1125,18 @@ static void change_pageblock_range(struct page *pageblock_page,
|
|
|
/*
|
|
|
* 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.
|
|
|
- *
|
|
|
- * On the other hand, never change migration type of MIGRATE_CMA pageblocks
|
|
|
- * nor move CMA pages to different free lists. We don't want unmovable pages
|
|
|
- * to be allocated from MIGRATE_CMA areas.
|
|
|
- *
|
|
|
- * Returns the allocation migratetype if free pages were stolen, or the
|
|
|
- * fallback migratetype if it was decided not to steal.
|
|
|
+ * 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);
|
|
|
|
|
|
- /*
|
|
|
- * When borrowing from MIGRATE_CMA, we need to release the excess
|
|
|
- * buddy pages to CMA itself. We also ensure the freepage_migratetype
|
|
|
- * is set to CMA so it is returned to the correct freelist in case
|
|
|
- * the page ends up being not actually allocated from the pcp lists.
|
|
|
- */
|
|
|
- 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 ||
|
|
@@ -1165,11 +1150,7 @@ static int try_to_steal_freepages(struct zone *zone, struct page *page,
|
|
|
if (pages >= (1 << (pageblock_order-1)) ||
|
|
|
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 */
|
|
@@ -1179,14 +1160,15 @@ __rmqueue_fallback(struct zone *zone, unsigned int order, int start_migratetype)
|
|
|
struct free_area *area;
|
|
|
unsigned 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 <= 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)
|
|
@@ -1200,22 +1182,36 @@ __rmqueue_fallback(struct zone *zone, unsigned int order, int start_migratetype)
|
|
|
struct page, lru);
|
|
|
area->nr_free--;
|
|
|
|
|
|
- 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);
|
|
|
rmv_page_order(page);
|
|
|
|
|
|
expand(zone, page, order, current_order, area,
|
|
|
- new_type);
|
|
|
- /* 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, migratetype);
|