summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYasunori Goto <y-goto@jp.fujitsu.com>2006-07-04 02:57:51 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2006-07-04 10:24:57 -0700
commitdd8041f16b117f63f40fb844d6cdebe8b03514d2 (patch)
tree40521ea93b2034484ceb1f16af7d47bfa1b35b6c
parent31304c909e6945b005af62cd55a582e9c010a0b4 (diff)
[PATCH] Fix copying of pgdat array on each node for ia64 memory hotplug
I found a bug in memory hot-add code for ia64. IA64's code has copies of pgdat's array on each node to reduce memory access over crossing node. This array is used by NODE_DATA() macro. When new node is hot-added, this pgdat's array should be updated and copied on new node too. However, I used for_each_online_node() in scatter_node_data() to copy it. This meant its array is not copied on new node. Because initialization of structures for new node was halfway, so online_node_map couldn't be set at this time. To copy arrays on new node, I changed it to check value of pgdat_list[] which is source array of copies. I tested this patch with my Memory Hotadd emulation on Tiger4. This patch is for 2.6.17-git20. Signed-off-by: Yasunori Goto <y-goto@jp.fujitsu.com> Cc: "Luck, Tony" <tony.luck@intel.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/ia64/mm/discontig.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
index 525b082eb66..99bd9e30db9 100644
--- a/arch/ia64/mm/discontig.c
+++ b/arch/ia64/mm/discontig.c
@@ -313,9 +313,19 @@ static void __meminit scatter_node_data(void)
pg_data_t **dst;
int node;
- for_each_online_node(node) {
- dst = LOCAL_DATA_ADDR(pgdat_list[node])->pg_data_ptrs;
- memcpy(dst, pgdat_list, sizeof(pgdat_list));
+ /*
+ * for_each_online_node() can't be used at here.
+ * node_online_map is not set for hot-added nodes at this time,
+ * because we are halfway through initialization of the new node's
+ * structures. If for_each_online_node() is used, a new node's
+ * pg_data_ptrs will be not initialized. Insted of using it,
+ * pgdat_list[] is checked.
+ */
+ for_each_node(node) {
+ if (pgdat_list[node]) {
+ dst = LOCAL_DATA_ADDR(pgdat_list[node])->pg_data_ptrs;
+ memcpy(dst, pgdat_list, sizeof(pgdat_list));
+ }
}
}