From: Alexander Duyck <alexander.h.duyck@xxxxxxxxxxxxxxx> This patch is adding support for flagging pages as "Treated" within the buddy allocator. If memory aeration is not enabled then the value will always be treated as false and the set/clear operations will have no effect. Signed-off-by: Alexander Duyck <alexander.h.duyck@xxxxxxxxxxxxxxx> --- include/linux/mmzone.h | 1 + include/linux/page-flags.h | 32 ++++++++++++++++++++++++++++++++ mm/page_alloc.c | 5 +++++ 3 files changed, 38 insertions(+) diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 297edb45071a..0263d5bf0b84 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -127,6 +127,7 @@ static inline void del_page_from_free_area(struct page *page, { list_del(&page->lru); __ClearPageBuddy(page); + __ResetPageTreated(page); set_page_private(page, 0); area->nr_free--; } diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index 9f8712a4b1a5..1f8ccb98dd69 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -722,12 +722,32 @@ static inline int page_has_type(struct page *page) VM_BUG_ON_PAGE(!PageType(page, 0), page); \ page->page_type &= ~PG_##lname; \ } \ +static __always_inline void __ResetPage##uname(struct page *page) \ +{ \ + VM_BUG_ON_PAGE(!PageType(page, 0), page); \ + page->page_type |= PG_##lname; \ +} \ static __always_inline void __ClearPage##uname(struct page *page) \ { \ VM_BUG_ON_PAGE(!Page##uname(page), page); \ page->page_type |= PG_##lname; \ } +#define PAGE_TYPE_OPS_DISABLED(uname) \ +static __always_inline int Page##uname(struct page *page) \ +{ \ + return false; \ +} \ +static __always_inline void __SetPage##uname(struct page *page) \ +{ \ +} \ +static __always_inline void __ResetPage##uname(struct page *page) \ +{ \ +} \ +static __always_inline void __ClearPage##uname(struct page *page) \ +{ \ +} + /* * PageBuddy() indicates that the page is free and in the buddy system * (see mm/page_alloc.c). @@ -744,6 +764,18 @@ static inline int page_has_type(struct page *page) PAGE_TYPE_OPS(Offline, offline) /* + * PageTreated() is an alias for Offline, however it is not meant to be an + * exclusive value. It should be combined with PageBuddy() when seen as it + * is meant to indicate that the page has been scrubbed while waiting in + * the buddy system. + */ +#ifdef CONFIG_AERATION +PAGE_TYPE_OPS(Treated, offline) +#else +PAGE_TYPE_OPS_DISABLED(Treated) +#endif + +/* * If kmemcg is enabled, the buddy allocator will set PageKmemcg() on * pages allocated with __GFP_ACCOUNT. It gets cleared on page free. */ diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 2fa5bbb372bb..2894990862bd 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -942,6 +942,11 @@ static inline void __free_one_page(struct page *page, goto done_merging; if (!page_is_buddy(page, buddy, order)) goto done_merging; + + /* If buddy is not treated, then do not mark page treated */ + if (!PageTreated(buddy)) + __ResetPageTreated(page); + /* * Our buddy is free or it is CONFIG_DEBUG_PAGEALLOC guard page, * merge with it and move up one order.