diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 540432972d5a..959fb83ab6cc 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -1622,6 +1622,18 @@ static inline struct pglist_data *NODE_DATA(int nid) extern struct pglist_data *first_online_pgdat(void); extern struct pglist_data *next_online_pgdat(struct pglist_data *pgdat); extern struct zone *next_zone(struct zone *zone); +extern int isolate_anon_lru_page(struct page *page); + +#ifdef CONFIG_COMPACTION +extern unsigned long isolate_and_split_free_page(struct page *page, + struct list_head *list); +#else +static inline unsigned long isolate_and_split_free_page(struct page *page, + struct list_head *list) +{ + return 0; +} +#endif /* CONFIG_COMPACTION */ /** * for_each_online_pgdat - helper macro to iterate over all online nodes diff --git a/mm/migrate.c b/mm/migrate.c index b6a874bc7f6a..972ee53353cb 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -174,6 +174,7 @@ void putback_movable_pages(struct list_head *l) } } } +EXPORT_SYMBOL_GPL(putback_movable_pages); /* Must be called with an elevated refcount on the non-hugetlb folio */ bool isolate_folio_to_list(struct folio *folio, struct list_head *list) @@ -2127,6 +2128,7 @@ out: return rc_gather; } +EXPORT_SYMBOL_GPL(migrate_pages); struct folio *alloc_migration_target(struct folio *src, unsigned long private) { diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 459c254c2fe7..78b1eb367c6a 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -452,6 +452,23 @@ unsigned long get_pfnblock_flags_mask(const struct page *page, } EXPORT_SYMBOL_GPL(get_pfnblock_flags_mask); +int isolate_anon_lru_page(struct page *page) +{ + int ret; + + if (!PageLRU(page) || !PageAnon(page)) + return -EINVAL; + + if (!get_page_unless_zero(page)) + return -EINVAL; + + ret = folio_isolate_lru(page_folio(page)); + put_page(page); + + return ret; +} +EXPORT_SYMBOL_GPL(isolate_anon_lru_page); + static __always_inline int get_pfnblock_migratetype(const struct page *page, unsigned long pfn) { @@ -6919,6 +6936,31 @@ static void split_free_pages(struct list_head *list) } } +#ifdef CONFIG_COMPACTION +unsigned long isolate_and_split_free_page(struct page *page, + struct list_head *list) +{ + unsigned long isolated; + unsigned int order; + + if (!PageBuddy(page)) + return 0; + + order = buddy_order(page); + isolated = __isolate_free_page(page, order); + if (!isolated) + return 0; + + set_page_private(page, order); + list_add(&page->lru, &list[order]); + + split_free_pages(list); + + return isolated; +} +EXPORT_SYMBOL_GPL(isolate_and_split_free_page); +#endif + /** * alloc_contig_range() -- tries to allocate given range of pages * @start: start PFN to allocate