diff options
Diffstat (limited to 'mm/memory_hotplug.c')
| -rw-r--r-- | mm/memory_hotplug.c | 37 | 
1 files changed, 24 insertions, 13 deletions
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index ac6961abaa10..e9d5ab5d3ca0 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -350,6 +350,16 @@ int __ref __add_pages(int nid, unsigned long pfn, unsigned long nr_pages,  	return err;  } +#ifdef CONFIG_NUMA +int __weak memory_add_physaddr_to_nid(u64 start) +{ +	pr_info_once("Unknown target node for memory at 0x%llx, assuming node 0\n", +			start); +	return 0; +} +EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid); +#endif +  /* find the smallest valid pfn in the range [start_pfn, end_pfn) */  static unsigned long find_smallest_section_pfn(int nid, struct zone *zone,  				     unsigned long start_pfn, @@ -844,8 +854,7 @@ int __ref online_pages(unsigned long pfn, unsigned long nr_pages,  	node_states_set_node(nid, &arg);  	if (need_zonelists_rebuild)  		build_all_zonelists(NULL); -	else -		zone_pcp_update(zone); +	zone_pcp_update(zone);  	init_per_zone_wmark_min(); @@ -1267,26 +1276,30 @@ found:  static struct page *new_node_page(struct page *page, unsigned long private)  { -	int nid = page_to_nid(page);  	nodemask_t nmask = node_states[N_MEMORY]; +	struct migration_target_control mtc = { +		.nid = page_to_nid(page), +		.nmask = &nmask, +		.gfp_mask = GFP_USER | __GFP_MOVABLE | __GFP_RETRY_MAYFAIL, +	};  	/*  	 * try to allocate from a different node but reuse this node if there  	 * are no other online nodes to be used (e.g. we are offlining a part  	 * of the only existing node)  	 */ -	node_clear(nid, nmask); +	node_clear(mtc.nid, nmask);  	if (nodes_empty(nmask)) -		node_set(nid, nmask); +		node_set(mtc.nid, nmask); -	return new_page_nodemask(page, nid, &nmask); +	return alloc_migration_target(page, (unsigned long)&mtc);  }  static int  do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)  {  	unsigned long pfn; -	struct page *page; +	struct page *page, *head;  	int ret = 0;  	LIST_HEAD(source); @@ -1294,15 +1307,14 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)  		if (!pfn_valid(pfn))  			continue;  		page = pfn_to_page(pfn); +		head = compound_head(page);  		if (PageHuge(page)) { -			struct page *head = compound_head(page);  			pfn = page_to_pfn(head) + compound_nr(head) - 1;  			isolate_huge_page(head, &source);  			continue;  		} else if (PageTransHuge(page)) -			pfn = page_to_pfn(compound_head(page)) -				+ hpage_nr_pages(page) - 1; +			pfn = page_to_pfn(head) + thp_nr_pages(page) - 1;  		/*  		 * HWPoison pages have elevated reference counts so the migration would @@ -1747,7 +1759,7 @@ static int __ref try_remove_memory(int nid, u64 start, u64 size)  	 */  	rc = walk_memory_blocks(start, size, NULL, check_memblock_offlined_cb);  	if (rc) -		goto done; +		return rc;  	/* remove memmap entry */  	firmware_map_remove(start, start + size, "System RAM"); @@ -1771,9 +1783,8 @@ static int __ref try_remove_memory(int nid, u64 start, u64 size)  	try_offline_node(nid); -done:  	mem_hotplug_done(); -	return rc; +	return 0;  }  /**  |