powerpc/pseries: Fix "OF: ERROR: Bad of_node_put() on /cpus" during DLPAR
authorTyrel Datwyler <tyreld@linux.vnet.ibm.com>
Wed, 20 Sep 2017 21:02:51 +0000 (17:02 -0400)
committerMichael Ellerman <mpe@ellerman.id.au>
Thu, 21 Sep 2017 09:30:53 +0000 (19:30 +1000)
Commit 215ee763f8cb ("powerpc: pseries: remove dlpar_attach_node
dependency on full path") reworked dlpar_attach_node() to no longer
look up the parent node "/cpus", but instead to have the parent node
passed by the caller in the function parameter list.

As a result dlpar_attach_node() is no longer responsible for freeing
the reference to the parent node. However, commit 215ee763f8cb failed
to remove the of_node_put(parent) call in dlpar_attach_node(), or to
take into account that the reference to the parent in the caller
dlpar_cpu_add() needs to be held until after dlpar_attach_node()
returns.

As a result doing repeated cpu add/remove dlpar operations will
eventually result in the following error:

  OF: ERROR: Bad of_node_put() on /cpus
  CPU: 0 PID: 10896 Comm: drmgr Not tainted 4.13.0-autotest #1
  Call Trace:
   dump_stack+0x15c/0x1f8 (unreliable)
   of_node_release+0x1a4/0x1c0
   kobject_put+0x1a8/0x310
   kobject_del+0xbc/0xf0
   __of_detach_node_sysfs+0x144/0x210
   of_detach_node+0xf0/0x180
   dlpar_detach_node+0xc4/0x120
   dlpar_cpu_remove+0x280/0x560
   dlpar_cpu_release+0xbc/0x1b0
   arch_cpu_release+0x6c/0xb0
   cpu_release_store+0xa0/0x100
   dev_attr_store+0x68/0xa0
   sysfs_kf_write+0xa8/0xf0
   kernfs_fop_write+0x2cc/0x400
   __vfs_write+0x5c/0x340
   vfs_write+0x1a8/0x3d0
   SyS_write+0xa8/0x1a0
   system_call+0x58/0x6c

Fix the issue by removing the of_node_put(parent) call from
dlpar_attach_node(), and ensuring that the reference to the parent
node is properly held and released by the caller dlpar_cpu_add().

Fixes: 215ee763f8cb ("powerpc: pseries: remove dlpar_attach_node dependency on full path")
Signed-off-by: Tyrel Datwyler <tyreld@linux.vnet.ibm.com>
Reported-by: Abdul Haleem <abdhalee@linux.vnet.ibm.com>
[mpe: Add a comment in the code and frob the change log slightly]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/platforms/pseries/dlpar.c
arch/powerpc/platforms/pseries/hotplug-cpu.c

index 783f3636469093034ae26a23856fef6aaf1922a6..e45b5f10645ae54b6610298a0a03c07f7e5d0966 100644 (file)
@@ -266,7 +266,6 @@ int dlpar_attach_node(struct device_node *dn, struct device_node *parent)
                return rc;
        }
 
-       of_node_put(dn->parent);
        return 0;
 }
 
index fc0d8f97c03a2f243a51c9ba27c7043626bd95cc..fadb95efbb9e1856ed8a7182cf870dcf3a5f5331 100644 (file)
@@ -462,15 +462,19 @@ static ssize_t dlpar_cpu_add(u32 drc_index)
        }
 
        dn = dlpar_configure_connector(cpu_to_be32(drc_index), parent);
-       of_node_put(parent);
        if (!dn) {
                pr_warn("Failed call to configure-connector, drc index: %x\n",
                        drc_index);
                dlpar_release_drc(drc_index);
+               of_node_put(parent);
                return -EINVAL;
        }
 
        rc = dlpar_attach_node(dn, parent);
+
+       /* Regardless we are done with parent now */
+       of_node_put(parent);
+
        if (rc) {
                saved_rc = rc;
                pr_warn("Failed to attach node %s, rc: %d, drc index: %x\n",