diff --git a/include/linux/compaction.h b/include/linux/compaction.h index 34bce35c808d..fbc43d5af1ba 100644 --- a/include/linux/compaction.h +++ b/include/linux/compaction.h @@ -180,6 +180,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) @@ -225,6 +227,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 6bfd989204ab..08af8f6ec69e 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -1096,6 +1096,7 @@ 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); /** * for_each_online_pgdat - helper macro to iterate over all online nodes diff --git a/mm/compaction.c b/mm/compaction.c index bfc93da1c2c7..a3c8ce474f71 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -758,6 +758,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 1852d787e6ab..c5974fff3395 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -168,6 +168,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 @@ -1601,6 +1602,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 c9a9b38f224c..368a58b117f4 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -496,6 +496,24 @@ unsigned long get_pfnblock_flags_mask(const struct page *page, { 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(const struct page *page, unsigned long pfn)