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;
 }
 

Reply via email to