During LPAR migration, the content of the device tree/sysfs may be updated including deletion and replacement of nodes in the tree. When nodes are added to the internal node structures, they are appended in FIFO order to a list of nodes maintained by the OF code APIs. When nodes are removed from the device tree, they are marked OF_DETACHED, but not actually deleted from the system to allow for pointers cached elsewhere in the kernel. The order and content of the entries in the list of nodes is not altered, though.
During LPAR migration some common nodes are deleted and re-added e.g. "ibm,platform-facilities". If a node is re-added to the OF node lists, the of_attach_node function checks to make sure that the name + ibm,phandle of the to-be-added data is unique. As the previous copy of a re-added node is not modified beyond the addition of a bit flag, the code (1) finds the old copy, (2) prints a WARNING notice to the console, (3) renames the to-be-added node to avoid filename collisions within a directory, and (3) adds entries to the sysfs/kernfs. This patch fixes the 'migration add' problem by changing the stored 'phandle' of the OF_DETACHed node to 0 (reserved value for of_find_node_by_phandle), so that subsequent re-add operations, such as those during migration, do not find the detached node, do not observe duplicate names, do not rename them, and the extra WARNING notices are removed from the console output. In addition, it erases the 'name' field of the OF_DETACHED node, to prevent any future calls to of_find_node_by_name() or of_find_node_by_path() from matching this node. Signed-off-by: Michael Bringmann <m...@linux.vnet.ibm.com> --- arch/powerpc/platforms/pseries/dlpar.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index 2de0f0d..9d82c28 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c @@ -274,6 +274,9 @@ int dlpar_detach_node(struct device_node *dn) if (rc) return rc; + dn->phandle = 0; + memset(dn->name, 0, strlen(dn->name)); + return 0; }