From: Alexander Duyck alexander.h.duyck@linux.intel.com
mainline inclusion from mainline-v5.7-rc1 commit 624f58d8f4639676d2fa1238425ab0148d501c4a category: feature bugzilla: 182882 CVE: NA
-----------------------------------------------
There are cases where we would benefit from avoiding having to go through the allocation and free cycle to return an isolated page.
Examples for this might include page poisoning in which we isolate a page and then put it back in the free list without ever having actually allocated it.
This will enable us to also avoid notifiers for the future free page reporting which will need to avoid retriggering page reporting when returning pages that have been reported on.
Signed-off-by: Alexander Duyck alexander.h.duyck@linux.intel.com Signed-off-by: Andrew Morton akpm@linux-foundation.org Acked-by: David Hildenbrand david@redhat.com Acked-by: Mel Gorman mgorman@techsingularity.net Cc: Andrea Arcangeli aarcange@redhat.com Cc: Dan Williams dan.j.williams@intel.com Cc: Dave Hansen dave.hansen@intel.com Cc: Konrad Rzeszutek Wilk konrad.wilk@oracle.com Cc: Luiz Capitulino lcapitulino@redhat.com Cc: Matthew Wilcox willy@infradead.org Cc: Michael S. Tsirkin mst@redhat.com Cc: Michal Hocko mhocko@kernel.org Cc: Nitesh Narayan Lal nitesh@redhat.com Cc: Oscar Salvador osalvador@suse.de Cc: Pankaj Gupta pagupta@redhat.com Cc: Paolo Bonzini pbonzini@redhat.com Cc: Rik van Riel riel@surriel.com Cc: Vlastimil Babka vbabka@suse.cz Cc: Wei Wang wei.w.wang@intel.com Cc: Yang Zhang yang.zhang.wz@gmail.com Cc: wei qi weiqi4@huawei.com Link: http://lkml.kernel.org/r/20200211224624.29318.89287.stgit@localhost.localdom... Signed-off-by: Linus Torvalds torvalds@linux-foundation.org Conflicts: mm/internal.h [Peng Liu: cherry-pick from 624f58d8f4639676d2fa1238425ab0148d501c4a] Signed-off-by: Peng Liu liupeng256@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- mm/internal.h | 2 ++ mm/page_alloc.c | 19 +++++++++++++++++++ mm/page_isolation.c | 6 ++---- 3 files changed, 23 insertions(+), 4 deletions(-)
diff --git a/mm/internal.h b/mm/internal.h index 415a6a326bb4d..5a142fa64908d 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -163,6 +163,8 @@ static inline struct page *pageblock_pfn_to_page(unsigned long start_pfn, extern int __isolate_free_page(struct page *page, unsigned int order); extern void __free_pages_bootmem(struct page *page, unsigned long pfn, unsigned int order); +extern void __putback_isolated_page(struct page *page, unsigned int order, + int mt); extern void __free_pages_core(struct page *page, unsigned int order); extern void prep_compound_page(struct page *page, unsigned int order); extern void post_alloc_hook(struct page *page, unsigned int order, diff --git a/mm/page_alloc.c b/mm/page_alloc.c index e0002e5c3d06d..de362e070e461 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2993,6 +2993,25 @@ int __isolate_free_page(struct page *page, unsigned int order) return 1UL << order; }
+/** + * __putback_isolated_page - Return a now-isolated page back where we got it + * @page: Page that was isolated + * @order: Order of the isolated page + * + * This function is meant to return a page pulled from the free lists via + * __isolate_free_page back to the free lists they were pulled from. + */ +void __putback_isolated_page(struct page *page, unsigned int order, int mt) +{ + struct zone *zone = page_zone(page); + + /* zone lock should be held when this function is called */ + lockdep_assert_held(&zone->lock); + + /* Return isolated page to tail of freelist. */ + __free_one_page(page, page_to_pfn(page), zone, order, mt); +} + /* * Update NUMA hit/miss statistics * diff --git a/mm/page_isolation.c b/mm/page_isolation.c index cdc33cd2203d1..88b635279e032 100644 --- a/mm/page_isolation.c +++ b/mm/page_isolation.c @@ -134,13 +134,11 @@ static void unset_migratetype_isolate(struct page *page, unsigned migratetype) __mod_zone_freepage_state(zone, nr_pages, migratetype); } set_pageblock_migratetype(page, migratetype); + if (isolated_page) + __putback_isolated_page(page, order, migratetype); zone->nr_isolate_pageblock--; out: spin_unlock_irqrestore(&zone->lock, flags); - if (isolated_page) { - post_alloc_hook(page, order, __GFP_MOVABLE); - __free_pages(page, order); - } }
static inline struct page *