diff --git a/include/linux/compaction.h b/include/linux/compaction.h index 1de5a1151ee7..8d14563808d5 100644 --- a/include/linux/compaction.h +++ b/include/linux/compaction.h @@ -182,6 +182,8 @@ bool compaction_zonelist_suitable(struct alloc_context *ac, int order, extern int kcompactd_run(int nid); extern void kcompactd_stop(int nid); extern void wakeup_kcompactd(pg_data_t *pgdat, int order, int highest_zoneidx); +extern unsigned long isolate_and_split_free_page(struct page *page, + struct list_head *list); #else static inline void reset_isolation_suitable(pg_data_t *pgdat) @@ -236,6 +238,12 @@ static inline void wakeup_kcompactd(pg_data_t *pgdat, { } +static unsigned long isolate_and_split_free_page(struct page *page, + struct list_head *list) +{ + return 0; +} + #endif /* CONFIG_COMPACTION */ struct node; diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index ec041358dba6..b002e9b4abc0 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -1014,6 +1014,7 @@ extern struct pglist_data contig_page_data; 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); /** * for_each_online_pgdat - helper macro to iterate over all online nodes diff --git a/mm/compaction.c b/mm/compaction.c index 34d99d7d1a6a..c42a2f0ff965 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -763,6 +763,29 @@ isolate_freepages_range(struct compact_control *cc, return pfn; } +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); + + split_map_pages(list); + + return isolated; +} +EXPORT_SYMBOL_GPL(isolate_and_split_free_page); + /* Similar to reclaim, but different enough that they don't share logic */ static bool too_many_isolated(pg_data_t *pgdat) { diff --git a/mm/migrate.c b/mm/migrate.c index 2275cf150cc8..ac6eb9db4df8 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -172,6 +172,7 @@ void putback_movable_pages(struct list_head *l) } } } +EXPORT_SYMBOL_GPL(putback_movable_pages); /* * Restore a potential migration pte to a working pte entry @@ -1509,6 +1510,7 @@ out: return rc; } +EXPORT_SYMBOL_GPL(migrate_pages); struct page *alloc_migration_target(struct page *page, unsigned long private) { diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 62a27290e81b..a276c3a8541d 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -537,6 +537,24 @@ unsigned long get_pfnblock_flags_mask(struct page *page, unsigned long pfn, { return __get_pfnblock_flags_mask(page, pfn, mask); } +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 = isolate_lru_page(page); + put_page(page); + + return ret; +} +EXPORT_SYMBOL_GPL(isolate_anon_lru_page); static __always_inline int get_pfnblock_migratetype(struct page *page, unsigned long pfn) {