This patch is borrowed from commit b4b382238ed2 ("mm/migrate: move
migration helper from .h to .c"), and commit 19fc7bed252c
("mm/migrate: introduce a standard migration target allocation function"),
to introduce a new migration allocation function to help to do page
demotion.
Signed-off-by: Baolin Wang <baolin.wang(a)linux.alibaba.com>
---
mm/internal.h | 1 +
mm/migrate.c | 41 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 42 insertions(+)
diff --git a/mm/internal.h b/mm/internal.h
index c10af5e..a1e34ed 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -584,4 +584,5 @@ static inline bool is_migrate_highatomic_page(struct page *page)
void setup_zone_pageset(struct zone *zone);
extern struct page *alloc_new_node_page(struct page *page, unsigned long node);
+extern struct page *alloc_migration_target(struct page *page, unsigned long node);
#endif /* __MM_INTERNAL_H */
diff --git a/mm/migrate.c b/mm/migrate.c
index 7663035..b987231 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -1572,6 +1572,47 @@ int migrate_pages(struct list_head *from, new_page_t get_new_page,
return rc;
}
+struct page *alloc_migration_target(struct page *page, unsigned long node)
+{
+ gfp_t gfp_mask;
+ unsigned int order = 0;
+ struct page *new_page = NULL;
+ int nid = node;
+ int zidx;
+
+ gfp_mask = (GFP_HIGHUSER_MOVABLE & ~__GFP_RECLAIM) |
+ __GFP_THISNODE | __GFP_NOWARN |
+ __GFP_NOMEMALLOC | GFP_NOWAIT;
+ if (nid == NUMA_NO_NODE)
+ nid = page_to_nid(page);
+
+ if (PageHuge(page)) {
+ struct hstate *h = page_hstate(compound_head(page));
+ return alloc_huge_page_nodemask(h, nid, NULL);
+ }
+
+ if (PageTransHuge(page)) {
+ /*
+ * clear __GFP_RECLAIM to make the migration callback
+ * consistent with regular THP allocations.
+ */
+ gfp_mask &= ~__GFP_RECLAIM;
+ gfp_mask |= GFP_TRANSHUGE;
+ order = HPAGE_PMD_ORDER;
+ }
+
+ zidx = zone_idx(page_zone(page));
+ if (is_highmem_idx(zidx) || zidx == ZONE_MOVABLE)
+ gfp_mask |= __GFP_HIGHMEM;
+
+ new_page = __alloc_pages_nodemask(gfp_mask, order, nid, NULL);
+
+ if (new_page && PageTransHuge(new_page))
+ prep_transhuge_page(new_page);
+
+ return new_page;
+}
+
#ifdef CONFIG_NUMA
static int store_status(int __user *status, int start, int value, int nr)
--
1.8.3.1