Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=6a281856c02d2291df2f7d9df5bfdee2e7bdd747
Commit:     6a281856c02d2291df2f7d9df5bfdee2e7bdd747
Parent:     d3b814bb1e8b0c63449a3430196c20cbe24a3e67
Author:     Michael Ellerman <[EMAIL PROTECTED]>
AuthorDate: Tue Jun 19 16:08:00 2007 +1000
Committer:  Paul Mackerras <[EMAIL PROTECTED]>
CommitDate: Tue Jul 10 21:53:47 2007 +1000

    [POWERPC] Add a warning to help trackdown device_node refcounting bugs
    
    When the refcount for a device node goes to 0, we call the
    destructor - of_node_release(). This should only happen if we've
    already detached the node from the device tree.
    
    So add a flag OF_DETACHED which tracks detached-ness, and if we
    find ourselves in of_node_release() without it set, issue a
    warning and don't free the device_node. To avoid warning
    continuously reinitialise the kref to a sane value.
    
    Signed-off-by: Michael Ellerman <[EMAIL PROTECTED]>
    Signed-off-by: Paul Mackerras <[EMAIL PROTECTED]>
---
 arch/powerpc/kernel/prom.c |   11 +++++++++++
 include/asm-powerpc/prom.h |    1 +
 2 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index bcd1c5e..6d5e601 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -1375,8 +1375,17 @@ static void of_node_release(struct kref *kref)
        struct device_node *node = kref_to_device_node(kref);
        struct property *prop = node->properties;
 
+       /* We should never be releasing nodes that haven't been detached. */
+       if (!of_node_check_flag(node, OF_DETACHED)) {
+               printk("WARNING: Bad of_node_put() on %s\n", node->full_name);
+               dump_stack();
+               kref_init(&node->kref);
+               return;
+       }
+
        if (!of_node_check_flag(node, OF_DYNAMIC))
                return;
+
        while (prop) {
                struct property *next = prop->next;
                kfree(prop->name);
@@ -1457,6 +1466,8 @@ void of_detach_node(const struct device_node *np)
                prevsib->sibling = np->sibling;
        }
 
+       of_node_set_flag(np, OF_DETACHED);
+
 out_unlock:
        write_unlock(&devtree_lock);
 }
diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h
index f1006b9..1632baa 100644
--- a/include/asm-powerpc/prom.h
+++ b/include/asm-powerpc/prom.h
@@ -99,6 +99,7 @@ extern struct device_node *of_chosen;
 
 /* flag descriptions */
 #define OF_DYNAMIC     1 /* node and properties were allocated via kmalloc */
+#define OF_DETACHED    2 /* node has been detached from the device tree */
 
 static inline int of_node_check_flag(struct device_node *n, unsigned long flag)
 {
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to