cpu/mem hotplug: add try_online_node() for cpu_up()

cpu_up() has #ifdef CONFIG_MEMORY_HOTPLUG code blocks, which call
mem_online_node() to put its node online if offlined and then call
build_all_zonelists() to initialize the zone list.

These steps are specific to memory hotplug, and should be managed in
mm/memory_hotplug.c.  lock_memory_hotplug() should also be held for the
whole steps.

For this reason, this patch replaces mem_online_node() with
try_online_node(), which performs the whole steps with
lock_memory_hotplug() held.  try_online_node() is named after
try_offline_node() as they have similar purpose.

There is no functional change in this patch.

Signed-off-by: Toshi Kani <toshi.kani@hp.com>
Reviewed-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Toshi Kani 2013-11-12 15:07:25 -08:00 committed by Linus Torvalds
parent 309d0b3917
commit 01b0f19707
3 changed files with 24 additions and 29 deletions

View File

@ -94,6 +94,8 @@ extern void __online_page_set_limits(struct page *page);
extern void __online_page_increment_counters(struct page *page); extern void __online_page_increment_counters(struct page *page);
extern void __online_page_free(struct page *page); extern void __online_page_free(struct page *page);
extern int try_online_node(int nid);
#ifdef CONFIG_MEMORY_HOTREMOVE #ifdef CONFIG_MEMORY_HOTREMOVE
extern bool is_pageblock_removable_nolock(struct page *page); extern bool is_pageblock_removable_nolock(struct page *page);
extern int arch_remove_memory(u64 start, u64 size); extern int arch_remove_memory(u64 start, u64 size);
@ -225,6 +227,11 @@ static inline void register_page_bootmem_info_node(struct pglist_data *pgdat)
{ {
} }
static inline int try_online_node(int nid)
{
return 0;
}
static inline void lock_memory_hotplug(void) {} static inline void lock_memory_hotplug(void) {}
static inline void unlock_memory_hotplug(void) {} static inline void unlock_memory_hotplug(void) {}
@ -256,7 +263,6 @@ static inline void remove_memory(int nid, u64 start, u64 size) {}
extern int walk_memory_range(unsigned long start_pfn, unsigned long end_pfn, extern int walk_memory_range(unsigned long start_pfn, unsigned long end_pfn,
void *arg, int (*func)(struct memory_block *, void *)); void *arg, int (*func)(struct memory_block *, void *));
extern int mem_online_node(int nid);
extern int add_memory(int nid, u64 start, u64 size); extern int add_memory(int nid, u64 start, u64 size);
extern int arch_add_memory(int nid, u64 start, u64 size); extern int arch_add_memory(int nid, u64 start, u64 size);
extern int offline_pages(unsigned long start_pfn, unsigned long nr_pages); extern int offline_pages(unsigned long start_pfn, unsigned long nr_pages);

View File

@ -437,11 +437,6 @@ int cpu_up(unsigned int cpu)
{ {
int err = 0; int err = 0;
#ifdef CONFIG_MEMORY_HOTPLUG
int nid;
pg_data_t *pgdat;
#endif
if (!cpu_possible(cpu)) { if (!cpu_possible(cpu)) {
printk(KERN_ERR "can't online cpu %d because it is not " printk(KERN_ERR "can't online cpu %d because it is not "
"configured as may-hotadd at boot time\n", cpu); "configured as may-hotadd at boot time\n", cpu);
@ -452,27 +447,9 @@ int cpu_up(unsigned int cpu)
return -EINVAL; return -EINVAL;
} }
#ifdef CONFIG_MEMORY_HOTPLUG err = try_online_node(cpu_to_node(cpu));
nid = cpu_to_node(cpu);
if (!node_online(nid)) {
err = mem_online_node(nid);
if (err) if (err)
return err; return err;
}
pgdat = NODE_DATA(nid);
if (!pgdat) {
printk(KERN_ERR
"Can't online cpu %d due to NULL pgdat\n", cpu);
return -ENOMEM;
}
if (pgdat->node_zonelists->_zonerefs->zone == NULL) {
mutex_lock(&zonelists_mutex);
build_all_zonelists(NULL, NULL);
mutex_unlock(&zonelists_mutex);
}
#endif
cpu_maps_update_begin(); cpu_maps_update_begin();

View File

@ -1043,17 +1043,23 @@ static void rollback_node_hotadd(int nid, pg_data_t *pgdat)
} }
/* /**
* try_online_node - online a node if offlined
*
* called by cpu_up() to online a node without onlined memory. * called by cpu_up() to online a node without onlined memory.
*/ */
int mem_online_node(int nid) int try_online_node(int nid)
{ {
pg_data_t *pgdat; pg_data_t *pgdat;
int ret; int ret;
if (node_online(nid))
return 0;
lock_memory_hotplug(); lock_memory_hotplug();
pgdat = hotadd_new_pgdat(nid, 0); pgdat = hotadd_new_pgdat(nid, 0);
if (!pgdat) { if (!pgdat) {
pr_err("Cannot online node %d due to NULL pgdat\n", nid);
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
} }
@ -1061,6 +1067,12 @@ int mem_online_node(int nid)
ret = register_one_node(nid); ret = register_one_node(nid);
BUG_ON(ret); BUG_ON(ret);
if (pgdat->node_zonelists->_zonerefs->zone == NULL) {
mutex_lock(&zonelists_mutex);
build_all_zonelists(NULL, NULL);
mutex_unlock(&zonelists_mutex);
}
out: out:
unlock_memory_hotplug(); unlock_memory_hotplug();
return ret; return ret;