forked from mirrors/linux
		
	memory hotplug: alloc page from other node in memory online
To initialize hotadded node, some pages are allocated. At that time, the node hasn't memory, this makes the allocation always fail. In such case, let's allocate pages from other nodes. Signed-off-by: Shaohua Li <shaohua.li@intel.com> Signed-off-by: Yakui Zhao <yakui.zhao@intel.com> Cc: Mel Gorman <mel@csn.ul.ie> Cc: Christoph Lameter <cl@linux-foundation.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
		
							parent
							
								
									8e7e40d965
								
							
						
					
					
						commit
						f52407ce2d
					
				
					 3 changed files with 22 additions and 7 deletions
				
			
		|  | @ -116,10 +116,16 @@ static int __init_refok init_section_page_cgroup(unsigned long pfn) | ||||||
| 		nid = page_to_nid(pfn_to_page(pfn)); | 		nid = page_to_nid(pfn_to_page(pfn)); | ||||||
| 		table_size = sizeof(struct page_cgroup) * PAGES_PER_SECTION; | 		table_size = sizeof(struct page_cgroup) * PAGES_PER_SECTION; | ||||||
| 		VM_BUG_ON(!slab_is_available()); | 		VM_BUG_ON(!slab_is_available()); | ||||||
| 		base = kmalloc_node(table_size, | 		if (node_state(nid, N_HIGH_MEMORY)) { | ||||||
|  | 			base = kmalloc_node(table_size, | ||||||
| 				GFP_KERNEL | __GFP_NOWARN, nid); | 				GFP_KERNEL | __GFP_NOWARN, nid); | ||||||
| 		if (!base) | 			if (!base) | ||||||
| 			base = vmalloc_node(table_size, nid); | 				base = vmalloc_node(table_size, nid); | ||||||
|  | 		} else { | ||||||
|  | 			base = kmalloc(table_size, GFP_KERNEL | __GFP_NOWARN); | ||||||
|  | 			if (!base) | ||||||
|  | 				base = vmalloc(table_size); | ||||||
|  | 		} | ||||||
| 	} else { | 	} else { | ||||||
| 		/*
 | 		/*
 | ||||||
|  		 * We don't have to allocate page_cgroup again, but |  		 * We don't have to allocate page_cgroup again, but | ||||||
|  |  | ||||||
|  | @ -48,8 +48,14 @@ void * __meminit vmemmap_alloc_block(unsigned long size, int node) | ||||||
| { | { | ||||||
| 	/* If the main allocator is up use that, fallback to bootmem. */ | 	/* If the main allocator is up use that, fallback to bootmem. */ | ||||||
| 	if (slab_is_available()) { | 	if (slab_is_available()) { | ||||||
| 		struct page *page = alloc_pages_node(node, | 		struct page *page; | ||||||
|  | 
 | ||||||
|  | 		if (node_state(node, N_HIGH_MEMORY)) | ||||||
|  | 			page = alloc_pages_node(node, | ||||||
| 				GFP_KERNEL | __GFP_ZERO, get_order(size)); | 				GFP_KERNEL | __GFP_ZERO, get_order(size)); | ||||||
|  | 		else | ||||||
|  | 			page = alloc_pages(GFP_KERNEL | __GFP_ZERO, | ||||||
|  | 				get_order(size)); | ||||||
| 		if (page) | 		if (page) | ||||||
| 			return page_address(page); | 			return page_address(page); | ||||||
| 		return NULL; | 		return NULL; | ||||||
|  |  | ||||||
|  | @ -62,9 +62,12 @@ static struct mem_section noinline __init_refok *sparse_index_alloc(int nid) | ||||||
| 	unsigned long array_size = SECTIONS_PER_ROOT * | 	unsigned long array_size = SECTIONS_PER_ROOT * | ||||||
| 				   sizeof(struct mem_section); | 				   sizeof(struct mem_section); | ||||||
| 
 | 
 | ||||||
| 	if (slab_is_available()) | 	if (slab_is_available()) { | ||||||
| 		section = kmalloc_node(array_size, GFP_KERNEL, nid); | 		if (node_state(nid, N_HIGH_MEMORY)) | ||||||
| 	else | 			section = kmalloc_node(array_size, GFP_KERNEL, nid); | ||||||
|  | 		else | ||||||
|  | 			section = kmalloc(array_size, GFP_KERNEL); | ||||||
|  | 	} else | ||||||
| 		section = alloc_bootmem_node(NODE_DATA(nid), array_size); | 		section = alloc_bootmem_node(NODE_DATA(nid), array_size); | ||||||
| 
 | 
 | ||||||
| 	if (section) | 	if (section) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Shaohua Li
						Shaohua Li