powerpc/powermac: Add missing of_node_put
Subsystems (3)
PATCH 1/1 powerpc/powermac: Add missing of_node_put
of_node_put is needed before discarding a value received from of_find_node_by_name, eg in error handling code or when the device node is no longer used.
The semantic match that catches the bug is as follows:
(http://www.emn.fr/x-info/coccinelle/)
// <smpl>
@r exists@
local idexpression struct device_node *n;
position p1, p2;
struct device_node *n1;
statement S;
identifier f;
expression E;
expression *ptr != NULL;
@@
n@p1 = of_find_node_by_name(...)
...
if (!n) S
... when != of_node_put(n)
when != n1 = f(n,...)
when != E = n
when any
when strict(
return \(0\|<+...n...+>\|ptr\);
|
return@p2 ...;
|
of_node_put(n);
|
n1 = f(n,...)
|
E = n
)
@script:python@
p1 << r.p1;
p2 << r.p2;
@@
print "* file: %s of_find_node_by_name %s return %s" % (p1[0].file,p1[0].line,p2[0].line) // </smpl>
--- arch/powerpc/platforms/powermac/pci.c | 2 ++ arch/powerpc/platforms/powermac/time.c | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-)
arch/powerpc/platforms/powermac/pci.c +2 -0
@@ -661,6 +661,7 @@ static void __init init_second_ohare(void)pci_find_hose_for_OF_device (np);if (!hose) {printk (KERN_ERR "Can't find PCI hose for OHare2 !\n" ); +of_node_put (np);return ; }early_read_config_word (hose, bus, devfn,PCI_COMMAND , &cmd);
@@ -669,6 +670,7 @@ static void __init init_second_ohare(void)early_write_config_word (hose, bus, devfn,PCI_COMMAND , cmd); } has_second_ohare =1 ; +of_node_put (np); }/*
arch/powerpc/platforms/powermac/time.c +3 -1
@@ -265,12 +265,14 @@ int __init via_calibrate_decr(void)struct resource rsrc; vias =of_find_node_by_name (NULL ,"via-cuda" );if (vias =0 ) vias =of_find_node_by_name (NULL ,"via-pmu" );if (vias =0 ) vias =of_find_node_by_name (NULL ,"via" );if (vias =0 ||of_address_to_resource (vias,0 , &rsrc))return 0 ; +of_node_put (vias); + via =ioremap (rsrc.start, rsrc.end - rsrc.start +1 );if (via =NULL ) {printk (KERN_ERR "Failed to map VIA for timer calibration !\n" );
@@ -297,7 +299,7 @@ int __init via_calibrate_decr(void) ppc_tb_freq = (dstart - dend) *100 /6 ;iounmap (via); - + return 1; }#endif
Signature · 1 line
Nicolas Palix
Hi Nicolas,
Thanks for all this work.
I think this particular patch is also required against Linus' kernel (not just linux-next).
Quoted 14 lines · On Tue, 2 Dec 2008 14:45:18 +0100 Nicolas Palix <[email protected]> wrote:
arch/powerpc/platforms/powermac/pci.c +1
-0@@ -661,6 +661,7 @@ static void __init init_second_ohare(void)pci_find_hose_for_OF_device (np);if (!hose) {printk (KERN_ERR "Can't find PCI hose for OHare2 !\n" ); +of_node_put (np);return ; }early_read_config_word (hose, bus, devfn,PCI_COMMAND , &cmd);
arch/powerpc/platforms/powermac/pci.c static void __init init_second_ohare(void) · line 674
Quoted 5 lines
arch/powerpc/platforms/powermac/pci.c +1
-0@@ -669,6 +670,7 @@ static void __init init_second_ohare(void)early_write_config_word (hose, bus, devfn,PCI_COMMAND , cmd); } has_second_ohare =1 ; +of_node_put (np); }
This part looks good.
Quoted 6 lines
arch/powerpc/platforms/powermac/time.c +0
-0@@ -265,12 +265,14 @@ int __init via_calibrate_decr(void)struct resource rsrc;
arch/powerpc/platforms/powermac/time.c int __init via_calibrate_decr(void) · line 275
Quoted 10 lines
arch/powerpc/platforms/powermac/time.c +2
-0vias =of_find_node_by_name (NULL ,"via-cuda" );if (vias ==0 ) vias =of_find_node_by_name (NULL ,"via-pmu" );if (vias ==0 ) vias =of_find_node_by_name (NULL ,"via" );if (vias ==0 ||of_address_to_resource (vias,0 , &rsrc))return 0 ; +of_node_put (vias); +
But this needs to also do the of_node_put() if the above "return 0" is taken i.e. if of_address_to_resource() fails.
Signature · 3 lines
Cheers, Stephen Rothwell [email protected] http://www.canb.auug.org.au/~sfr/
Hi Nicolas,
Quoted 3 lines · On Wed, 3 Dec 2008 10:19:01 +1100 Stephen Rothwell <[email protected]> wrote:
I think this particular patch is also required against Linus' kernel (not just linux-next).
In fact, I think all these patches can apply to Linus' current tree.
Signature · 3 lines
Cheers, Stephen Rothwell [email protected] http://www.canb.auug.org.au/~sfr/
Hi Stephen,
I fix the patch. I also change the "vias = 0" in "vias = NULL". Is "!vias" better ?
Quoted 9 lines · On Wednesday 03 December 2008 00:25:08 Stephen Rothwell wrote:
Hi Nicolas,
Quoted 3 lines · On Wed, 3 Dec 2008 10:19:01 +1100 Stephen Rothwell <[email protected]> wrote:
I think this particular patch is also required against Linus' kernel (not just linux-next).
In fact, I think all these patches can apply to Linus' current tree.
--- arch/powerpc/platforms/powermac/pci.c | 2 + arch/powerpc/platforms/powermac/time.c | 11 ++++++---- 2 files changed, 9 insertions(+), 4 deletions(-)
arch/powerpc/platforms/powermac/pci.c +2 -0
@@ -661,6 +661,7 @@ static void __init init_second_ohare(void)pci_find_hose_for_OF_device (np);if (!hose) {printk (KERN_ERR "Can't find PCI hose for OHare2 !\n" ); +of_node_put (np);return ; }early_read_config_word (hose, bus, devfn,PCI_COMMAND , &cmd);
@@ -669,6 +670,7 @@ static void __init init_second_ohare(void)early_write_config_word (hose, bus, devfn,PCI_COMMAND , cmd); } has_second_ohare =1 ; +of_node_put (np); }/*
arch/powerpc/platforms/powermac/time.c +7 -4
@@ -265,12 +265,15 @@ int __init via_calibrate_decr(void)struct resource rsrc; vias =of_find_node_by_name (NULL ,"via-cuda" ); -if (vias =0 ) +if (vias =NULL ) vias =of_find_node_by_name (NULL ,"via-pmu" ); -if (vias =0 ) +if (vias =NULL ) vias =of_find_node_by_name (NULL ,"via" ); -if (vias =0 ||of_address_to_resource (vias,0 , &rsrc)) +if (vias =NULL ||of_address_to_resource (vias,0 , &rsrc)) { +of_node_put (vias);return 0 ; + } +of_node_put (vias); via =ioremap (rsrc.start, rsrc.end - rsrc.start +1 );if (via =NULL ) {printk (KERN_ERR "Failed to map VIA for timer calibration !\n" );
@@ -297,7 +300,7 @@ int __init via_calibrate_decr(void) ppc_tb_freq = (dstart - dend) *100 /6 ;iounmap (via); - + return 1; }#endif
Signature · 1 line
Nicolas Palix
Quoted 4 lines · On Tue, 2 Dec 2008 14:45:18 +0100 Nicolas Palix <[email protected]> wrote:
arch/powerpc/platforms/powermac/time.c +0
-0@@ -265,12 +265,14 @@ int __init via_calibrate_decr(void)struct resource rsrc;
arch/powerpc/platforms/powermac/time.c int __init via_calibrate_decr(void) · line 275
Quoted 10 lines
arch/powerpc/platforms/powermac/time.c +2
-0vias =of_find_node_by_name (NULL ,"via-cuda" );if (vias =0 ) vias =of_find_node_by_name (NULL ,"via-pmu" );if (vias =0 ) vias =of_find_node_by_name (NULL ,"via" );if (vias =0 ||of_address_to_resource (vias,0 , &rsrc))return 0 ; +of_node_put (vias); +
This still misses a path - if that `return 0' is taken, we still leak the reference.
This is reason #345 why sprinkling return statements all over your code is bad.
I fixed it up thusly. Please check.
of_node_put is needed before discarding a value received from of_find_node_by_name, eg in error handling code or when the device node is no longer used.
The semantic match that catches the bug is as follows:
(http://www.emn.fr/x-info/coccinelle/)
// <smpl>
@r exists@
local idexpression struct device_node *n;
position p1, p2;
struct device_node *n1;
statement S;
identifier f;
expression E;
expression *ptr != NULL;
@@
n@p1 = of_find_node_by_name(...)
...
if (!n) S
... when != of_node_put(n)
when != n1 = f(n,...)
when != E = n
when any
when strict(
return \(0\|<+...n...+>\|ptr\);
|
return@p2 ...;
|
of_node_put(n);
|
n1 = f(n,...)
|
E = n
)
@script:python@
p1 << r.p1;
p2 << r.p2;
@@
print "* file: %s of_find_node_by_name %s return %s" % (p1[0].file,p1[0].line,p2[0].line) // </smpl>
---
index bcf50d7..800fcce 100644
---
arch/powerpc/platforms/powermac/pci.c | 2 ++ arch/powerpc/platforms/powermac/time.c | 9 ++++++--- 2 files changed, 8 insertions(+), 3 deletions(-)
arch/powerpc/platforms/powermac/pci.c renamed from arch/powerpc/platforms/powermac/pci.c~powerpc-powermac-add-missing-of_node_put +2 -0
@@ -661,6 +661,7 @@ static void __init init_second_ohare(voipci_find_hose_for_OF_device (np);if (!hose) {printk (KERN_ERR "Can't find PCI hose for OHare2 !\n" ); +of_node_put (np);return ; }early_read_config_word (hose, bus, devfn,PCI_COMMAND , &cmd);
@@ -669,6 +670,7 @@ static void __init init_second_ohare(voiearly_write_config_word (hose, bus, devfn,PCI_COMMAND , cmd); } has_second_ohare =1 ; +of_node_put (np); }/*
arch/powerpc/platforms/powermac/time.c renamed from arch/powerpc/platforms/powermac/time.c~powerpc-powermac-add-missing-of_node_put +6 -3
@@ -270,11 +270,11 @@ int __init via_calibrate_decr(void)if (vias =0 ) vias =of_find_node_by_name (NULL ,"via" );if (vias =0 ||of_address_to_resource (vias,0 , &rsrc)) -return 0 ; + goto fail; via =ioremap (rsrc.start, rsrc.end - rsrc.start +1 );if (via =NULL ) {printk (KERN_ERR "Failed to map VIA for timer calibration !\n" ); -return 0 ; + goto fail; }/* set timer 1 for continuous interrupts */
@@ -297,8 +297,11 @@ int __init via_calibrate_decr(void) ppc_tb_freq = (dstart - dend) *100 /6 ;iounmap (via); - +return 1 ; +fail: +of_node_put (vias); + return 0; }#endif
_
Quoted 7 lines · Andrew Morton
This still misses a path - if that `return 0' is taken, we still leak the reference.
This is reason #345 why sprinkling return statements all over your code is bad.
I fixed it up thusly. Please check.
I'm really in two minds about applying any of the of_node_put patches that only affect powermacs. The reference counts only matter on platforms where we update the OF device tree at runtime, which is currently only IBM pSeries machines. Since we don't have any hotplug on powermacs, and never will have, the OF device tree is completely static and we don't actually need refcounts on the nodes at all, so who cares if they're a bit higher than they might be?
In particular, the VIA whose node we're looking for here is built-in on the motherboard, and there can never be more than one, and it can never be removed.
Paul.
Hi Paul,
Quoted 9 lines · On Sun, 7 Dec 2008 13:31:00 +1100 Paul Mackerras <[email protected]> wrote:
I'm really in two minds about applying any of the
of_node_putpatches that only affect powermacs. The reference counts only matter on platforms where we update the OF device tree at runtime, which is currently only IBM pSeries machines. Since we don't have any hotplug on powermacs, and never will have, the OF device tree is completely static and we don't actually need refcounts on the nodes at all, so who cares if they're a bit higher than they might be?
Quoted 3 lines
In particular, the VIA whose node we're looking for here is built-in on the motherboard, and there can never be more than one, and it can never be removed.
I my mind it is about consistent use of the API and good examples for people to copy. Also, in about a year you will be presented with the same set of patches when a new pair of eyes looks at the same code and notices the discrepancy ...
Signature · 3 lines
Cheers, Stephen Rothwell [email protected] http://www.canb.auug.org.au/~sfr/
Quoted 12 lines · On Sunday 07 December 2008 06:43:33 Stephen Rothwell wrote:
Hi Paul,
Quoted 9 lines · On Sun, 7 Dec 2008 13:31:00 +1100 Paul Mackerras <[email protected]> wrote:
I'm really in two minds about applying any of the
of_node_putpatches that only affect powermacs. The reference counts only matter on platforms where we update the OF device tree at runtime, which is currently only IBM pSeries machines. Since we don't have any hotplug on powermacs, and never will have, the OF device tree is completely static and we don't actually need refcounts on the nodes at all, so who cares if they're a bit higher than they might be?
Quoted 9 lines
Quoted 3 lines
In particular, the VIA whose node we're looking for here is built-in on the motherboard, and there can never be more than one, and it can never be removed.
I my mind it is about consistent use of the API and good examples for people to copy. Also, in about a year you will be presented with the same set of patches when a new pair of eyes looks at the same code and notices the discrepancy ...
Hi Andrew,
Indeed, there is an updated version of this patch in my second mail which fixes this issue.
http://lkml.org/lkml/2008/12/3/88
Moreover, there is still a reference count unbalanced with your patch in the case where the function returns 1.
Regards,
Signature · 1 line
Nicolas Palix
Quoted 12 lines · Stephen Rothwell
Hi Paul,
Quoted 9 lines · On Sun, 7 Dec 2008 13:31:00 +1100 Paul Mackerras <[email protected]> wrote:
I'm really in two minds about applying any of the
of_node_putpatches that only affect powermacs. The reference counts only matter on platforms where we update the OF device tree at runtime, which is currently only IBM pSeries machines. Since we don't have any hotplug on powermacs, and never will have, the OF device tree is completely static and we don't actually need refcounts on the nodes at all, so who cares if they're a bit higher than they might be?
Quoted 8 lines
Quoted 3 lines
In particular, the VIA whose node we're looking for here is built-in on the motherboard, and there can never be more than one, and it can never be removed.
I my mind it is about consistent use of the API and good examples for people to copy. Also, in about a year you will be presented with the same set of patches when a new pair of eyes looks at the same code and notices the discrepancy ...
what-he-said++
Allowing the ref counting to be broken in one part of the code is just asking for it to be broken everywhere.
cheers
Signature · 8 lines
Michael Ellerman OzLabs, IBM Australia Development Lab wwweb: http://michael.ellerman.id.au phone: +61 2 6212 1183 (tie line 70 21183) We do not inherit the earth from our ancestors, we borrow it from our children. - S.M.A.R.T Person