forked from mirrors/linux
		
	mem-hotplug: introduce {un}lock_memory_hotplug()
Presently hwpoison is using lock_system_sleep() to prevent a race with memory hotplug. However lock_system_sleep() is a no-op if CONFIG_HIBERNATION=n. Therefore we need a new lock. Signed-off-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Cc: Andi Kleen <andi@firstfloor.org> Cc: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Suggested-by: Hugh Dickins <hughd@google.com> Acked-by: Hugh Dickins <hughd@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
		
							parent
							
								
									4fe65cab84
								
							
						
					
					
						commit
						20d6c96b5f
					
				
					 3 changed files with 34 additions and 11 deletions
				
			
		|  | @ -161,6 +161,9 @@ extern void register_page_bootmem_info_node(struct pglist_data *pgdat); | ||||||
| extern void put_page_bootmem(struct page *page); | extern void put_page_bootmem(struct page *page); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | void lock_memory_hotplug(void); | ||||||
|  | void unlock_memory_hotplug(void); | ||||||
|  | 
 | ||||||
| #else /* ! CONFIG_MEMORY_HOTPLUG */ | #else /* ! CONFIG_MEMORY_HOTPLUG */ | ||||||
| /*
 | /*
 | ||||||
|  * Stub functions for when hotplug is off |  * Stub functions for when hotplug is off | ||||||
|  | @ -192,6 +195,9 @@ static inline void register_page_bootmem_info_node(struct pglist_data *pgdat) | ||||||
| { | { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static inline void lock_memory_hotplug(void) {} | ||||||
|  | static inline void unlock_memory_hotplug(void) {} | ||||||
|  | 
 | ||||||
| #endif /* ! CONFIG_MEMORY_HOTPLUG */ | #endif /* ! CONFIG_MEMORY_HOTPLUG */ | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_MEMORY_HOTREMOVE | #ifdef CONFIG_MEMORY_HOTREMOVE | ||||||
|  |  | ||||||
|  | @ -51,6 +51,7 @@ | ||||||
| #include <linux/slab.h> | #include <linux/slab.h> | ||||||
| #include <linux/swapops.h> | #include <linux/swapops.h> | ||||||
| #include <linux/hugetlb.h> | #include <linux/hugetlb.h> | ||||||
|  | #include <linux/memory_hotplug.h> | ||||||
| #include "internal.h" | #include "internal.h" | ||||||
| 
 | 
 | ||||||
| int sysctl_memory_failure_early_kill __read_mostly = 0; | int sysctl_memory_failure_early_kill __read_mostly = 0; | ||||||
|  | @ -1230,11 +1231,10 @@ static int get_any_page(struct page *p, unsigned long pfn, int flags) | ||||||
| 		return 1; | 		return 1; | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * The lock_system_sleep prevents a race with memory hotplug, | 	 * The lock_memory_hotplug prevents a race with memory hotplug. | ||||||
| 	 * because the isolation assumes there's only a single user. |  | ||||||
| 	 * This is a big hammer, a better would be nicer. | 	 * This is a big hammer, a better would be nicer. | ||||||
| 	 */ | 	 */ | ||||||
| 	lock_system_sleep(); | 	lock_memory_hotplug(); | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * Isolate the page, so that it doesn't get reallocated if it | 	 * Isolate the page, so that it doesn't get reallocated if it | ||||||
|  | @ -1264,7 +1264,7 @@ static int get_any_page(struct page *p, unsigned long pfn, int flags) | ||||||
| 		ret = 1; | 		ret = 1; | ||||||
| 	} | 	} | ||||||
| 	unset_migratetype_isolate(p); | 	unset_migratetype_isolate(p); | ||||||
| 	unlock_system_sleep(); | 	unlock_memory_hotplug(); | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -34,6 +34,23 @@ | ||||||
| 
 | 
 | ||||||
| #include "internal.h" | #include "internal.h" | ||||||
| 
 | 
 | ||||||
|  | DEFINE_MUTEX(mem_hotplug_mutex); | ||||||
|  | 
 | ||||||
|  | void lock_memory_hotplug(void) | ||||||
|  | { | ||||||
|  | 	mutex_lock(&mem_hotplug_mutex); | ||||||
|  | 
 | ||||||
|  | 	/* for exclusive hibernation if CONFIG_HIBERNATION=y */ | ||||||
|  | 	lock_system_sleep(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void unlock_memory_hotplug(void) | ||||||
|  | { | ||||||
|  | 	unlock_system_sleep(); | ||||||
|  | 	mutex_unlock(&mem_hotplug_mutex); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| /* add this memory to iomem resource */ | /* add this memory to iomem resource */ | ||||||
| static struct resource *register_memory_resource(u64 start, u64 size) | static struct resource *register_memory_resource(u64 start, u64 size) | ||||||
| { | { | ||||||
|  | @ -493,7 +510,7 @@ int mem_online_node(int nid) | ||||||
| 	pg_data_t	*pgdat; | 	pg_data_t	*pgdat; | ||||||
| 	int	ret; | 	int	ret; | ||||||
| 
 | 
 | ||||||
| 	lock_system_sleep(); | 	lock_memory_hotplug(); | ||||||
| 	pgdat = hotadd_new_pgdat(nid, 0); | 	pgdat = hotadd_new_pgdat(nid, 0); | ||||||
| 	if (pgdat) { | 	if (pgdat) { | ||||||
| 		ret = -ENOMEM; | 		ret = -ENOMEM; | ||||||
|  | @ -504,7 +521,7 @@ int mem_online_node(int nid) | ||||||
| 	BUG_ON(ret); | 	BUG_ON(ret); | ||||||
| 
 | 
 | ||||||
| out: | out: | ||||||
| 	unlock_system_sleep(); | 	unlock_memory_hotplug(); | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -516,7 +533,7 @@ int __ref add_memory(int nid, u64 start, u64 size) | ||||||
| 	struct resource *res; | 	struct resource *res; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	lock_system_sleep(); | 	lock_memory_hotplug(); | ||||||
| 
 | 
 | ||||||
| 	res = register_memory_resource(start, size); | 	res = register_memory_resource(start, size); | ||||||
| 	ret = -EEXIST; | 	ret = -EEXIST; | ||||||
|  | @ -563,7 +580,7 @@ int __ref add_memory(int nid, u64 start, u64 size) | ||||||
| 		release_memory_resource(res); | 		release_memory_resource(res); | ||||||
| 
 | 
 | ||||||
| out: | out: | ||||||
| 	unlock_system_sleep(); | 	unlock_memory_hotplug(); | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| EXPORT_SYMBOL_GPL(add_memory); | EXPORT_SYMBOL_GPL(add_memory); | ||||||
|  | @ -791,7 +808,7 @@ static int offline_pages(unsigned long start_pfn, | ||||||
| 	if (!test_pages_in_a_zone(start_pfn, end_pfn)) | 	if (!test_pages_in_a_zone(start_pfn, end_pfn)) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 
 | 
 | ||||||
| 	lock_system_sleep(); | 	lock_memory_hotplug(); | ||||||
| 
 | 
 | ||||||
| 	zone = page_zone(pfn_to_page(start_pfn)); | 	zone = page_zone(pfn_to_page(start_pfn)); | ||||||
| 	node = zone_to_nid(zone); | 	node = zone_to_nid(zone); | ||||||
|  | @ -880,7 +897,7 @@ static int offline_pages(unsigned long start_pfn, | ||||||
| 	writeback_set_ratelimit(); | 	writeback_set_ratelimit(); | ||||||
| 
 | 
 | ||||||
| 	memory_notify(MEM_OFFLINE, &arg); | 	memory_notify(MEM_OFFLINE, &arg); | ||||||
| 	unlock_system_sleep(); | 	unlock_memory_hotplug(); | ||||||
| 	return 0; | 	return 0; | ||||||
| 
 | 
 | ||||||
| failed_removal: | failed_removal: | ||||||
|  | @ -891,7 +908,7 @@ static int offline_pages(unsigned long start_pfn, | ||||||
| 	undo_isolate_page_range(start_pfn, end_pfn); | 	undo_isolate_page_range(start_pfn, end_pfn); | ||||||
| 
 | 
 | ||||||
| out: | out: | ||||||
| 	unlock_system_sleep(); | 	unlock_memory_hotplug(); | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 KOSAKI Motohiro
						KOSAKI Motohiro