diff options
Diffstat (limited to 'mm/memory_hotplug.c')
| -rw-r--r-- | mm/memory_hotplug.c | 24 | 
1 files changed, 19 insertions, 5 deletions
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 821dee59637..2047465cd27 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -26,6 +26,7 @@  #include <linux/migrate.h>  #include <linux/page-isolation.h>  #include <linux/pfn.h> +#include <linux/suspend.h>  #include <asm/tlbflush.h> @@ -447,7 +448,8 @@ int online_pages(unsigned long pfn, unsigned long nr_pages)  }  #endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */ -static pg_data_t *hotadd_new_pgdat(int nid, u64 start) +/* we are OK calling __meminit stuff here - we have CONFIG_MEMORY_HOTPLUG */ +static pg_data_t __ref *hotadd_new_pgdat(int nid, u64 start)  {  	struct pglist_data *pgdat;  	unsigned long zones_size[MAX_NR_ZONES] = {0}; @@ -484,14 +486,18 @@ int __ref add_memory(int nid, u64 start, u64 size)  	struct resource *res;  	int ret; +	lock_system_sleep(); +  	res = register_memory_resource(start, size); +	ret = -EEXIST;  	if (!res) -		return -EEXIST; +		goto out;  	if (!node_online(nid)) {  		pgdat = hotadd_new_pgdat(nid, start); +		ret = -ENOMEM;  		if (!pgdat) -			return -ENOMEM; +			goto out;  		new_pgdat = 1;  	} @@ -514,7 +520,8 @@ int __ref add_memory(int nid, u64 start, u64 size)  		BUG_ON(ret);  	} -	return ret; +	goto out; +  error:  	/* rollback pgdat allocation and others */  	if (new_pgdat) @@ -522,6 +529,8 @@ error:  	if (res)  		release_memory_resource(res); +out: +	unlock_system_sleep();  	return ret;  }  EXPORT_SYMBOL_GPL(add_memory); @@ -758,6 +767,8 @@ int offline_pages(unsigned long start_pfn,  	if (!test_pages_in_a_zone(start_pfn, end_pfn))  		return -EINVAL; +	lock_system_sleep(); +  	zone = page_zone(pfn_to_page(start_pfn));  	node = zone_to_nid(zone);  	nr_pages = end_pfn - start_pfn; @@ -765,7 +776,7 @@ int offline_pages(unsigned long start_pfn,  	/* set above range as isolated */  	ret = start_isolate_page_range(start_pfn, end_pfn);  	if (ret) -		return ret; +		goto out;  	arg.start_pfn = start_pfn;  	arg.nr_pages = nr_pages; @@ -843,6 +854,7 @@ repeat:  	writeback_set_ratelimit();  	memory_notify(MEM_OFFLINE, &arg); +	unlock_system_sleep();  	return 0;  failed_removal: @@ -852,6 +864,8 @@ failed_removal:  	/* pushback to free area */  	undo_isolate_page_range(start_pfn, end_pfn); +out: +	unlock_system_sleep();  	return ret;  }  |