From: Alexander Duyck <alexander.h.duyck@xxxxxxxxxxxxxxx> When we are going to call "expand" to split a page into subpages we should mark those subpages as being "Treated" if the parent page was a "Treated" page. By doing this we can avoid potentially providing hints on a page that was already hinted at a larger page size as being unused. Signed-off-by: Alexander Duyck <alexander.h.duyck@xxxxxxxxxxxxxxx> --- include/linux/mmzone.h | 8 ++++++-- mm/page_alloc.c | 18 +++++++++++++++--- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 988c3094b686..a55fe6d2f63c 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -97,16 +97,20 @@ struct free_area { static inline void add_to_free_area(struct page *page, struct free_area *area, int migratetype) { + if (PageTreated(page)) + area->nr_free_treated++; + else + area->nr_free_raw++; + list_add(&page->lru, &area->free_list[migratetype]); - area->nr_free_raw++; } /* Used for pages not on another list */ static inline void add_to_free_area_tail(struct page *page, struct free_area *area, int migratetype) { - list_add_tail(&page->lru, &area->free_list[migratetype]); area->nr_free_raw++; + list_add_tail(&page->lru, &area->free_list[migratetype]); } /* Used for pages which are on another list */ diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 10eaea762627..f6c067c6c784 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1965,7 +1965,7 @@ void __init init_cma_reserved_pageblock(struct page *page) */ static inline void expand(struct zone *zone, struct page *page, int low, int high, struct free_area *area, - int migratetype) + int migratetype, bool treated) { unsigned long size = 1 << high; @@ -1984,8 +1984,17 @@ static inline void expand(struct zone *zone, struct page *page, if (set_page_guard(zone, &page[size], high, migratetype)) continue; - add_to_free_area(&page[size], area, migratetype); set_page_order(&page[size], high); + if (treated) + __SetPageTreated(&page[size]); + + /* + * The list we are placing this page in should be empty + * so it should be safe to place it here without worrying + * about creating a block of raw pages floating in between + * two blocks of treated pages. + */ + add_to_free_area(&page[size], area, migratetype); } } @@ -2122,6 +2131,7 @@ struct page *__rmqueue_smallest(struct zone *zone, unsigned int order, unsigned int current_order; struct free_area *area; struct page *page; + bool treated; /* Find a page of the appropriate size in the preferred list */ for (current_order = order; current_order < MAX_ORDER; ++current_order) { @@ -2129,8 +2139,10 @@ struct page *__rmqueue_smallest(struct zone *zone, unsigned int order, page = get_page_from_free_area(area, migratetype); if (!page) continue; + treated = PageTreated(page); del_page_from_free_area(page, area); - expand(zone, page, order, current_order, area, migratetype); + expand(zone, page, order, current_order, area, migratetype, + treated); set_pcppage_migratetype(page, migratetype); return page; }