Commit 7049027c6f0098eb6b23b8f6ca65a905541faf81
Committed by
Linus Torvalds
1 parent
ae5a2c1c9b
Exists in
master
and in
7 other branches
[PATCH] pgdat allocation and update for ia64 of memory hotplug: update pgdat address array
This is to refresh node_data[] array for ia64. As I mentioned previous patches, ia64 has copies of information of pgdat address array on each node as per node data. At v2 of node_add, this function used stop_machine_run() to update them. (I wished that they were copied safety as much as possible.) But, in this patch, this arrays are just copied simply, and set node_online_map bit after completion of pgdat initialization. So, kernel must touch NODE_DATA() macro after checking node_online_map(). (Current code has already done it.) This is more simple way for just hot-add..... Note : It will be problem when hot-remove will occur, because, even if online_map bit is set, kernel may touch NODE_DATA() due to race condition. :-( 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>
Showing 3 changed files with 32 additions and 8 deletions Side-by-side Diff
arch/ia64/mm/discontig.c
... | ... | @@ -308,6 +308,17 @@ |
308 | 308 | } |
309 | 309 | } |
310 | 310 | |
311 | +static void __meminit scatter_node_data(void) | |
312 | +{ | |
313 | + pg_data_t **dst; | |
314 | + int node; | |
315 | + | |
316 | + for_each_online_node(node) { | |
317 | + dst = LOCAL_DATA_ADDR(pgdat_list[node])->pg_data_ptrs; | |
318 | + memcpy(dst, pgdat_list, sizeof(pgdat_list)); | |
319 | + } | |
320 | +} | |
321 | + | |
311 | 322 | /** |
312 | 323 | * initialize_pernode_data - fixup per-cpu & per-node pointers |
313 | 324 | * |
... | ... | @@ -320,11 +331,8 @@ |
320 | 331 | { |
321 | 332 | int cpu, node; |
322 | 333 | |
323 | - /* Copy the pg_data_t list to each node and init the node field */ | |
324 | - for_each_online_node(node) { | |
325 | - memcpy(mem_data[node].node_data->pg_data_ptrs, pgdat_list, | |
326 | - sizeof(pgdat_list)); | |
327 | - } | |
334 | + scatter_node_data(); | |
335 | + | |
328 | 336 | #ifdef CONFIG_SMP |
329 | 337 | /* Set the node_data pointer for each per-cpu struct */ |
330 | 338 | for (cpu = 0; cpu < NR_CPUS; cpu++) { |
... | ... | @@ -782,5 +790,11 @@ |
782 | 790 | } |
783 | 791 | |
784 | 792 | zero_page_memmap_ptr = virt_to_page(ia64_imva(empty_zero_page)); |
793 | +} | |
794 | + | |
795 | +void arch_refresh_nodedata(int update_node, pg_data_t *update_pgdat) | |
796 | +{ | |
797 | + pgdat_list[update_node] = update_pgdat; | |
798 | + scatter_node_data(); | |
785 | 799 | } |
include/asm-ia64/nodedata.h
... | ... | @@ -46,6 +46,18 @@ |
46 | 46 | */ |
47 | 47 | #define NODE_DATA(nid) (local_node_data->pg_data_ptrs[nid]) |
48 | 48 | |
49 | +/* | |
50 | + * LOCAL_DATA_ADDR - This is to calculate the address of other node's | |
51 | + * "local_node_data" at hot-plug phase. The local_node_data | |
52 | + * is pointed by per_cpu_page. Kernel usually use it for | |
53 | + * just executing cpu. However, when new node is hot-added, | |
54 | + * the addresses of local data for other nodes are necessary | |
55 | + * to update all of them. | |
56 | + */ | |
57 | +#define LOCAL_DATA_ADDR(pgdat) \ | |
58 | + ((struct ia64_node_data *)((u64)(pgdat) + \ | |
59 | + L1_CACHE_ALIGN(sizeof(struct pglist_data)))) | |
60 | + | |
49 | 61 | #endif /* CONFIG_NUMA */ |
50 | 62 | |
51 | 63 | #endif /* _ASM_IA64_NODEDATA_H */ |
include/linux/memory_hotplug.h
... | ... | @@ -91,9 +91,7 @@ |
91 | 91 | static inline void arch_free_nodedata(pg_data_t *pgdat) |
92 | 92 | { |
93 | 93 | } |
94 | -static inline void arch_refresh_nodedata(int nid, pg_data_t *pgdat) | |
95 | -{ | |
96 | -} | |
94 | +extern void arch_refresh_nodedata(int nid, pg_data_t *pgdat); | |
97 | 95 | |
98 | 96 | #else /* CONFIG_HAVE_ARCH_NODEDATA_EXTENSION */ |
99 | 97 |