mem-hotplug: use GFP_HIGHUSER_MOVABLE and alloc from next node in alloc_migrate_target()
Subsystems (2)
PATCH 1/1 mem-hotplug: use GFP_HIGHUSER_MOVABLE and alloc from next node in alloc_migrate_target()
alloc_migrate_target() is called from migrate_pages(), and the page is always from user space, so we can add __GFP_HIGHMEM directly.
Second, when we offline a node, the new page should alloced from other nodes instead of the current node, because re-migrate is a waste of time.
--- mm/page_isolation.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-)
mm/page_isolation.c +6 -10
@@ -282,20 +282,16 @@ int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn,struct page *alloc_migrate_target (struct page *page,unsigned long private,int **resultp) { -gfp_t gfp_mask =GFP_USER | __GFP_MOVABLE; -/* -* TODO: allocate a destination hugepage from a nearest neighbor node, +* TODO: allocate a destination page from a nearest neighbor node, * accordance with memory policy of the user process if possible. For * now as a simple work-around, we use the next node for destination. */ +int nid =next_node_in (page_to_nid (page), node_online_map); +if (PageHuge (page))return alloc_huge_page_node (page_hstate (compound_head (page)), -next_node_in (page_to_nid (page), - node_online_map)); - -if (PageHighMem (page)) - gfp_mask |= __GFP_HIGHMEM; - -return alloc_page (gfp_mask); + nid); +else +return __alloc_pages_node (nid,GFP_HIGHUSER_MOVABLE ,0 ); }
Signature · 1 line
1.8.3.1
Quoted 7 lines · Xishi Qiu
alloc_migrate_target()is called frommigrate_pages(), and the page is always from user space, so we can add__GFP_HIGHMEMdirectly.Second, when we offline a node, the new page should alloced from other nodes instead of the current node, because re-migrate is a waste of time.
alloc_migrate_target() is not only used from memory hotplug, it is also used for CMA: we won't be isolating PageHuge() pages in isolate_migratepages_range(), so this would cause a regression where we'd be migrating memory to a remote NUMA node rather than preferring to allocate locally.
You may find it useful to use the 'private' field of the migrate_pages() callback to specify the node the page should preferably be migrated to.
Quoted 25 lines
Signed-off-by Xishi Qiu <[email protected]>--- mm/page_isolation.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-)mm/page_isolation.c +3
-3@@ -282,20 +282,16 @@ int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn,struct page *alloc_migrate_target (struct page *page,unsigned long private,int **resultp) { -gfp_t gfp_mask =GFP_USER | __GFP_MOVABLE; -/* -* TODO: allocate a destination hugepage from a nearest neighbor node, +* TODO: allocate a destination page from a nearest neighbor node, * accordance with memory policy of the user process if possible. For * now as a simple work-around, we use the next node for destination. */ +int nid =next_node_in (page_to_nid (page), node_online_map); +if (PageHuge (page)) return alloc_huge_page_node(page_hstate(compound_head(page)),
mm/page_isolation.c int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn, · line 296
Quoted 10 lines
mm/page_isolation.c +3
-7-next_node_in (page_to_nid (page), - node_online_map)); - -if (PageHighMem (page)) - gfp_mask |= __GFP_HIGHMEM; - -return alloc_page (gfp_mask); + nid); + else + return __alloc_pages_node(nid, GFP_HIGHUSER_MOVABLE, 0);
I don't think this __alloc_pages_node() does what you think it does, it only prefers nid here and will readily fallback to other nodes if necessary. That is different than alloc_huge_page_node() which does no fallback. So there's two issues with this change: (1) inconsistency between PageHuge() and !PageHuge() behavior, and (2) the use of __alloc_pages_node() does not match the commit description which states "re-migrate is a waste of time."
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 17 lines · David Rientjes
Quoted 7 lines · Xishi Qiu
alloc_migrate_target()is called frommigrate_pages(), and the page is always from user space, so we can add__GFP_HIGHMEMdirectly.Second, when we offline a node, the new page should alloced from other nodes instead of the current node, because re-migrate is a waste of time.
alloc_migrate_target()is not only used from memory hotplug, it is also used for CMA: we won't be isolatingPageHuge()pages inisolate_migratepages_range(), so this would cause a regression where we'd be migrating memory to a remote NUMA node rather than preferring to allocate locally.
Quoted 3 lines
You may find it useful to use the 'private' field of the
migrate_pages()callback to specify the node the page should preferably be migrated to.
OK, I know, I'll rewrite v2.
Quoted 36 lines
Quoted 25 lines
Signed-off-by Xishi Qiu <[email protected]>--- mm/page_isolation.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-)mm/page_isolation.c +3
-3@@ -282,20 +282,16 @@ int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn,struct page *alloc_migrate_target (struct page *page,unsigned long private,int **resultp) { -gfp_t gfp_mask =GFP_USER | __GFP_MOVABLE; -/* -* TODO: allocate a destination hugepage from a nearest neighbor node, +* TODO: allocate a destination page from a nearest neighbor node, * accordance with memory policy of the user process if possible. For * now as a simple work-around, we use the next node for destination. */ +int nid =next_node_in (page_to_nid (page), node_online_map); +if (PageHuge (page)) return alloc_huge_page_node(page_hstate(compound_head(page)),mm/page_isolation.c int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn, · line 296
Quoted 10 lines
mm/page_isolation.c +3
-7-next_node_in (page_to_nid (page), - node_online_map)); - -if (PageHighMem (page)) - gfp_mask |= __GFP_HIGHMEM; - -return alloc_page (gfp_mask); + nid); + else + return __alloc_pages_node(nid, GFP_HIGHUSER_MOVABLE, 0);
Quoted 8 lines
I don't think this
__alloc_pages_node()does what you think it does, it only prefers nid here and will readily fallback to other nodes if necessary. That is different thanalloc_huge_page_node()which does no fallback. So there's two issues with this change: (1) inconsistency betweenPageHuge()and !PageHuge() behavior, and (2) the use of__alloc_pages_node()does not match the commit description which states "re-migrate is a waste of time."
Yes, you are right, how about change the changelog, one is membind, the other is prefer?
Thanks,
Xishi Qiu
Quoted 2 lines
.