Skip to content

Commit

Permalink
memory-hotplug: do not allocate pgdat if it was not freed when offline.
Browse files Browse the repository at this point in the history
Since there is no way to guarentee the address of pgdat/zone is not on
stack of any kernel threads or used by other kernel objects without
reference counting or other symchronizing method, we cannot reset
node_data and free pgdat when offlining a node.  Just reset pgdat to 0
and reuse the memory when the node is online again.

The problem is suggested by Kamezawa Hiroyuki.  The idea is from Wen
Congyang.

NOTE: If we don't reset pgdat to 0, the WARN_ON in free_area_init_node()
      will be triggered.

[akpm@linux-foundation.org: fix warning when CONFIG_NEED_MULTIPLE_NODES=n]
[akpm@linux-foundation.org: fix the warning again again]
Signed-off-by: Tang Chen <tangchen@cn.fujitsu.com>
Reviewed-by: Wen Congyang <wency@cn.fujitsu.com>
Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Cc: Jiang Liu <jiang.liu@huawei.com>
Cc: Jianguo Wu <wujianguo@huawei.com>
Cc: Kamezawa Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Lai Jiangshan <laijs@cn.fujitsu.com>
Cc: Wu Jianguo <wujianguo@huawei.com>
Cc: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
tang-chen authored and torvalds committed Feb 24, 2013
1 parent d822b86 commit a1e565a
Showing 1 changed file with 16 additions and 8 deletions.
24 changes: 16 additions & 8 deletions mm/memory_hotplug.c
Original file line number Diff line number Diff line change
Expand Up @@ -1017,11 +1017,14 @@ static pg_data_t __ref *hotadd_new_pgdat(int nid, u64 start)
unsigned long zholes_size[MAX_NR_ZONES] = {0};
unsigned long start_pfn = start >> PAGE_SHIFT;

pgdat = arch_alloc_nodedata(nid);
if (!pgdat)
return NULL;
pgdat = NODE_DATA(nid);
if (!pgdat) {
pgdat = arch_alloc_nodedata(nid);
if (!pgdat)
return NULL;

arch_refresh_nodedata(nid, pgdat);
arch_refresh_nodedata(nid, pgdat);
}

/* we can use NODE_DATA(nid) from here */

Expand Down Expand Up @@ -1074,7 +1077,8 @@ int mem_online_node(int nid)
int __ref add_memory(int nid, u64 start, u64 size)
{
pg_data_t *pgdat = NULL;
int new_pgdat = 0;
bool new_pgdat;
bool new_node;
struct resource *res;
int ret;

Expand All @@ -1085,12 +1089,16 @@ int __ref add_memory(int nid, u64 start, u64 size)
if (!res)
goto out;

if (!node_online(nid)) {
{ /* Stupid hack to suppress address-never-null warning */
void *p = NODE_DATA(nid);
new_pgdat = !p;
}
new_node = !node_online(nid);
if (new_node) {
pgdat = hotadd_new_pgdat(nid, start);
ret = -ENOMEM;
if (!pgdat)
goto error;
new_pgdat = 1;
}

/* call arch's memory hotadd */
Expand All @@ -1102,7 +1110,7 @@ int __ref add_memory(int nid, u64 start, u64 size)
/* we online node here. we can't roll back from here. */
node_set_online(nid);

if (new_pgdat) {
if (new_node) {
ret = register_one_node(nid);
/*
* If sysfs file of new node can't create, cpu on the node
Expand Down

0 comments on commit a1e565a

Please sign in to comment.