In some LPAR migration scenarios, device-tree modifications are made to the affinity of the memory in the system. For instance, it may occur that memory is installed to nodes 0,3 on a source system, and to nodes 0,2 on a target system. Node 2 may not have been initialized/allocated on the target system.
During normal DLPAR memory 'hot add' operations, unitialized nodes are initialized/allocated prior to use. After migration, if a RTAS PRRN memory remove operation is made on a memory block that was in node 3 on the source system, then try_offline_node tries to remove it from node 2 on the target assuming that it was in node 2 on the source system and that node 2 had been setup. The NODE_DATA(2) block is not initialized on the target, and there is no validation check to prevent the use of a NULL pointer. Call traces such as the following may be observed: pseries-hotplug-mem: Attempting to update LMB, drc index 80000002 Offlined Pages 4096 ... Oops: Kernel access of bad area, sig: 11 [#1] ... Workqueue: pseries hotplug workque pseries_hp_work_fn ... NIP [c0000000002bc088] try_offline_node+0x48/0x1e0 LR [c0000000002e0b84] remove_memory+0xb4/0xf0 Call Trace: [c0000002bbee7a30] [c0000002bbee7a70] 0xc0000002bbee7a70 (unreliable) [c0000002bbee7a70] [c0000000002e0b84] remove_memory+0xb4/0xf0 [c0000002bbee7ab0] [c000000000097784] dlpar_remove_lmb+0xb4/0x160 [c0000002bbee7af0] [c000000000097f38] dlpar_memory+0x328/0xcb0 [c0000002bbee7ba0] [c0000000000906d0] handle_dlpar_errorlog+0xc0/0x130 [c0000002bbee7c10] [c0000000000907d4] pseries_hp_work_fn+0x94/0xa0 [c0000002bbee7c40] [c0000000000e1cd0] process_one_work+0x1a0/0x4e0 [c0000002bbee7cd0] [c0000000000e21b0] worker_thread+0x1a0/0x610 [c0000002bbee7d80] [c0000000000ea458] kthread+0x128/0x150 [c0000002bbee7e30] [c00000000000982c] ret_from_kernel_thread+0x5c/0xb0 A similar problem of moving memory to an unitialized node has also been observed on systems where multiple PRRN events occur prior to a complete update of the device-tree. This patch attempts to detect and initialize an uninitialized node in the memory_add_physaddr_to_nid -> hot_add_scn_to_nid functions used by powerpc DLPAR memory operations to compute the node of a emory address based on the device-tree affinity configuration after migration. This occurs before try_offline_node is used by remove_memory. Signed-off-by: Michael Bringmann <m...@linux.vnet.ibm.com> --- arch/powerpc/mm/numa.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 0ade0a1..d6f6e24 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -1020,6 +1020,13 @@ int hot_add_scn_to_nid(unsigned long scn_addr) if (nid < 0 || !node_possible(nid)) nid = first_online_node; + if (NODE_DATA(nid) == NULL) { + if (try_online_node(nid)) + nid = first_online_node; + else + pr_debug("new nid %d for %#010lx\n", nid, scn_addr); + } + return nid; }