From: Brian Norris <computersforpeace@gmail.com>
To: Julia Lawall <Julia.Lawall@lip6.fr>
Cc: kernel-janitors@vger.kernel.org,
David Woodhouse <dwmw2@infradead.org>,
linux-mtd@lists.infradead.org,
bcm-kernel-feedback-list@broadcom.com,
linux-kernel@vger.kernel.org,
Russell King - ARM Linux <linux@arm.linux.org.uk>,
Thomas Petazzoni <thomas.petazzoni@free-electrons.com>,
Andrew Lunn <andrew@lunn.ch>, Bjorn Helgaas <bhelgaas@google.com>,
Jason Cooper <jason@lakedaemon.net>,
Kamal Dasu <kdasu.kdev@gmail.com>
Subject: Re: [PATCH 1/4] mtd: brcmnand: improve memory management
Date: Wed, 18 Nov 2015 22:44:40 +0000 [thread overview]
Message-ID: <20151118224440.GC64635@google.com> (raw)
In-Reply-To: <1447884254-26336-2-git-send-email-Julia.Lawall@lip6.fr>
On Wed, Nov 18, 2015 at 11:04:11PM +0100, Julia Lawall wrote:
> This patch addresses several related memory management issues in the probe
> function:
>
> 1. for_each_available_child_of_node performs an of_node_get on each
> iteration, so a break out of the loop requires an of_node_put.
>
> A simplified version of the semantic patch that fixes this problem is as
> follows (http://coccinelle.lip6.fr):
>
> // <smpl>
> @@
> expression root,e;
> local idexpression child;
> @@
>
> for_each_available_child_of_node(root, child) {
> ... when != of_node_put(child)
> when != e = child
> (
> return child;
> |
> + of_node_put(child);
> ? return ...;
> )
> ...
> }
> // </smpl>
Good catch again
> 2. The devm_kzalloc'd data is not used if brcmnand_init_cs fails. Free it
> immediately, using devm_kfree in this case, instead of waiting for the
> remove function.
Same
> 3. If the continue is not taken, then host is added to a list, that has a
> lifetime beyond the end of the for_each_available_child_of_node loop body.
> Thus, of_node_get is needed on child, which is referenced by host. A
> corresponding of_node_put is needed in the remove function.
This one's a bit silly. We really shouldn't be keeping the reference in
'host' at all. Also, as of commit 215a02fd3087 ("mtd: grab a reference to
the MTD of_node before registering it"), the MTD core will actually be
refcounting the node for us, too, so this isn't really necessary.
I have a patch to remove brcmnand_host::of_node (appended below), which
should make this step obsolete, and be more obvious that no extra
of_node_get()'ing is required.
> Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>
>
> ---
>
> One could consider whether the of_node_get should be on host->of_node,
> which looks more similar to the thing that is stored in the list. I used
> child, to be more similar to the of_node_put in the same function.
>
> drivers/mtd/nand/brcmnand/brcmnand.c | 14 ++++++++++----
> 1 file changed, 10 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c
> index 2a437c7..b0cb55d 100644
> --- a/drivers/mtd/nand/brcmnand/brcmnand.c
> +++ b/drivers/mtd/nand/brcmnand/brcmnand.c
> @@ -2237,16 +2237,20 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
> struct brcmnand_host *host;
>
> host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
> - if (!host)
> + if (!host) {
> + of_node_put(child);
> return -ENOMEM;
In code reading, I noticed that we don't actually cleanup for prior
iterations of brcmnand_init_cs() here. i.e., if we're exiting here, we
should be doing nand_release() on all previously-registered chips.
> + }
> host->pdev = pdev;
> host->ctrl = ctrl;
> host->of_node = child;
>
> ret = brcmnand_init_cs(host);
> - if (ret)
> + if (ret) {
> + devm_kfree(dev, host);
> continue; /* Try all chip-selects */
> -
> + }
> + of_node_get(child);
> list_add_tail(&host->node, &ctrl->host_list);
> }
> }
> @@ -2264,8 +2268,10 @@ int brcmnand_remove(struct platform_device *pdev)
> struct brcmnand_controller *ctrl = dev_get_drvdata(&pdev->dev);
> struct brcmnand_host *host;
>
> - list_for_each_entry(host, &ctrl->host_list, node)
> + list_for_each_entry(host, &ctrl->host_list, node) {
> + of_node_put(host->of_node);
> nand_release(&host->mtd);
> + }
>
> dev_set_drvdata(&pdev->dev, NULL);
>
Patch to kill off some of this:
---8<---
From 6c51a9ef1325e7b06a7623c1fbca1adf6eeb8253 Mon Sep 17 00:00:00 2001
From: Brian Norris <computersforpeace@gmail.com>
Date: Wed, 18 Nov 2015 14:33:24 -0800
Subject: [PATCH] mtd: brcmnand: drop brcmnand_host::of_node field
We don't actually need to stash a copy of this device_node indefinitely;
we only need it in brcmnand_init_cs().
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
Cc: <bcm-kernel-feedback-list@broadcom.com>
Cc: Kamal Dasu <kdasu.kdev@gmail.com>
---
drivers/mtd/nand/brcmnand/brcmnand.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c
index c395b4a75fb1..351438a62aaa 100644
--- a/drivers/mtd/nand/brcmnand/brcmnand.c
+++ b/drivers/mtd/nand/brcmnand/brcmnand.c
@@ -176,7 +176,6 @@ struct brcmnand_cfg {
struct brcmnand_host {
struct list_head node;
- struct device_node *of_node;
struct nand_chip chip;
struct mtd_info mtd;
@@ -1896,10 +1895,9 @@ static int brcmnand_setup_dev(struct brcmnand_host *host)
return 0;
}
-static int brcmnand_init_cs(struct brcmnand_host *host)
+static int brcmnand_init_cs(struct brcmnand_host *host, struct device_node *dn)
{
struct brcmnand_controller *ctrl = host->ctrl;
- struct device_node *dn = host->of_node;
struct platform_device *pdev = host->pdev;
struct mtd_info *mtd;
struct nand_chip *chip;
@@ -2231,9 +2229,8 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
return -ENOMEM;
host->pdev = pdev;
host->ctrl = ctrl;
- host->of_node = child;
- ret = brcmnand_init_cs(host);
+ ret = brcmnand_init_cs(host, child);
if (ret)
continue; /* Try all chip-selects */
--
2.6.0.rc2.230.g3dd15c0
WARNING: multiple messages have this Message-ID (diff)
From: Brian Norris <computersforpeace@gmail.com>
To: Julia Lawall <Julia.Lawall@lip6.fr>
Cc: kernel-janitors@vger.kernel.org,
David Woodhouse <dwmw2@infradead.org>,
linux-mtd@lists.infradead.org,
bcm-kernel-feedback-list@broadcom.com,
linux-kernel@vger.kernel.org,
Russell King - ARM Linux <linux@arm.linux.org.uk>,
Thomas Petazzoni <thomas.petazzoni@free-electrons.com>,
Andrew Lunn <andrew@lunn.ch>, Bjorn Helgaas <bhelgaas@google.com>,
Jason Cooper <jason@lakedaemon.net>,
Kamal Dasu <kdasu.kdev@gmail.com>
Subject: Re: [PATCH 1/4] mtd: brcmnand: improve memory management
Date: Wed, 18 Nov 2015 14:44:40 -0800 [thread overview]
Message-ID: <20151118224440.GC64635@google.com> (raw)
In-Reply-To: <1447884254-26336-2-git-send-email-Julia.Lawall@lip6.fr>
On Wed, Nov 18, 2015 at 11:04:11PM +0100, Julia Lawall wrote:
> This patch addresses several related memory management issues in the probe
> function:
>
> 1. for_each_available_child_of_node performs an of_node_get on each
> iteration, so a break out of the loop requires an of_node_put.
>
> A simplified version of the semantic patch that fixes this problem is as
> follows (http://coccinelle.lip6.fr):
>
> // <smpl>
> @@
> expression root,e;
> local idexpression child;
> @@
>
> for_each_available_child_of_node(root, child) {
> ... when != of_node_put(child)
> when != e = child
> (
> return child;
> |
> + of_node_put(child);
> ? return ...;
> )
> ...
> }
> // </smpl>
Good catch again
> 2. The devm_kzalloc'd data is not used if brcmnand_init_cs fails. Free it
> immediately, using devm_kfree in this case, instead of waiting for the
> remove function.
Same
> 3. If the continue is not taken, then host is added to a list, that has a
> lifetime beyond the end of the for_each_available_child_of_node loop body.
> Thus, of_node_get is needed on child, which is referenced by host. A
> corresponding of_node_put is needed in the remove function.
This one's a bit silly. We really shouldn't be keeping the reference in
'host' at all. Also, as of commit 215a02fd3087 ("mtd: grab a reference to
the MTD of_node before registering it"), the MTD core will actually be
refcounting the node for us, too, so this isn't really necessary.
I have a patch to remove brcmnand_host::of_node (appended below), which
should make this step obsolete, and be more obvious that no extra
of_node_get()'ing is required.
> Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>
>
> ---
>
> One could consider whether the of_node_get should be on host->of_node,
> which looks more similar to the thing that is stored in the list. I used
> child, to be more similar to the of_node_put in the same function.
>
> drivers/mtd/nand/brcmnand/brcmnand.c | 14 ++++++++++----
> 1 file changed, 10 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c
> index 2a437c7..b0cb55d 100644
> --- a/drivers/mtd/nand/brcmnand/brcmnand.c
> +++ b/drivers/mtd/nand/brcmnand/brcmnand.c
> @@ -2237,16 +2237,20 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
> struct brcmnand_host *host;
>
> host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
> - if (!host)
> + if (!host) {
> + of_node_put(child);
> return -ENOMEM;
In code reading, I noticed that we don't actually cleanup for prior
iterations of brcmnand_init_cs() here. i.e., if we're exiting here, we
should be doing nand_release() on all previously-registered chips.
> + }
> host->pdev = pdev;
> host->ctrl = ctrl;
> host->of_node = child;
>
> ret = brcmnand_init_cs(host);
> - if (ret)
> + if (ret) {
> + devm_kfree(dev, host);
> continue; /* Try all chip-selects */
> -
> + }
> + of_node_get(child);
> list_add_tail(&host->node, &ctrl->host_list);
> }
> }
> @@ -2264,8 +2268,10 @@ int brcmnand_remove(struct platform_device *pdev)
> struct brcmnand_controller *ctrl = dev_get_drvdata(&pdev->dev);
> struct brcmnand_host *host;
>
> - list_for_each_entry(host, &ctrl->host_list, node)
> + list_for_each_entry(host, &ctrl->host_list, node) {
> + of_node_put(host->of_node);
> nand_release(&host->mtd);
> + }
>
> dev_set_drvdata(&pdev->dev, NULL);
>
Patch to kill off some of this:
---8<---
>From 6c51a9ef1325e7b06a7623c1fbca1adf6eeb8253 Mon Sep 17 00:00:00 2001
From: Brian Norris <computersforpeace@gmail.com>
Date: Wed, 18 Nov 2015 14:33:24 -0800
Subject: [PATCH] mtd: brcmnand: drop brcmnand_host::of_node field
We don't actually need to stash a copy of this device_node indefinitely;
we only need it in brcmnand_init_cs().
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
Cc: <bcm-kernel-feedback-list@broadcom.com>
Cc: Kamal Dasu <kdasu.kdev@gmail.com>
---
drivers/mtd/nand/brcmnand/brcmnand.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c
index c395b4a75fb1..351438a62aaa 100644
--- a/drivers/mtd/nand/brcmnand/brcmnand.c
+++ b/drivers/mtd/nand/brcmnand/brcmnand.c
@@ -176,7 +176,6 @@ struct brcmnand_cfg {
struct brcmnand_host {
struct list_head node;
- struct device_node *of_node;
struct nand_chip chip;
struct mtd_info mtd;
@@ -1896,10 +1895,9 @@ static int brcmnand_setup_dev(struct brcmnand_host *host)
return 0;
}
-static int brcmnand_init_cs(struct brcmnand_host *host)
+static int brcmnand_init_cs(struct brcmnand_host *host, struct device_node *dn)
{
struct brcmnand_controller *ctrl = host->ctrl;
- struct device_node *dn = host->of_node;
struct platform_device *pdev = host->pdev;
struct mtd_info *mtd;
struct nand_chip *chip;
@@ -2231,9 +2229,8 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
return -ENOMEM;
host->pdev = pdev;
host->ctrl = ctrl;
- host->of_node = child;
- ret = brcmnand_init_cs(host);
+ ret = brcmnand_init_cs(host, child);
if (ret)
continue; /* Try all chip-selects */
--
2.6.0.rc2.230.g3dd15c0
next prev parent reply other threads:[~2015-11-18 22:44 UTC|newest]
Thread overview: 53+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-10-22 9:02 [PATCH 0/4] add missing of_node_put Julia Lawall
2015-10-22 9:02 ` Julia Lawall
2015-10-22 9:02 ` [PATCH 1/4] of/overlay: " Julia Lawall
2015-10-22 9:02 ` Julia Lawall
2015-10-22 9:02 ` [PATCH 2/4] of/platform: " Julia Lawall
2015-10-22 9:02 ` Julia Lawall
[not found] ` <1445504571-19838-1-git-send-email-Julia.Lawall-L2FTfq7BK8M@public.gmane.org>
2015-10-22 9:02 ` [PATCH 3/4] of/unittest: " Julia Lawall
2015-10-22 9:02 ` Julia Lawall
2015-10-22 9:02 ` Julia Lawall
2015-10-22 9:02 ` [PATCH 4/4] of/irq: " Julia Lawall
2015-10-22 9:02 ` Julia Lawall
2015-10-22 13:04 ` [PATCH 0/4] " Rob Herring
2015-10-22 13:04 ` Rob Herring
[not found] ` <CAL_JsqJGS+L=FZAwPs-wBSYiX8kQWqZyaLTGhadYVNT3=Qte_Q-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-10-22 13:19 ` Julia Lawall
2015-10-22 13:19 ` Julia Lawall
2015-10-22 13:19 ` Julia Lawall
2015-10-22 15:08 ` Rob Herring
2015-10-22 15:08 ` Rob Herring
2015-11-18 22:04 ` Julia Lawall
2015-11-18 22:04 ` Julia Lawall
2015-11-18 22:04 ` Julia Lawall
2015-11-18 22:04 ` Julia Lawall
2015-11-18 22:04 ` [PATCH 1/4] mtd: brcmnand: improve memory management Julia Lawall
2015-11-18 22:04 ` Julia Lawall
2015-11-18 22:44 ` Brian Norris [this message]
2015-11-18 22:44 ` Brian Norris
2015-11-19 6:13 ` Julia Lawall
2015-11-19 6:13 ` Julia Lawall
2015-11-19 19:26 ` Brian Norris
2015-11-19 19:26 ` Brian Norris
2015-11-19 21:32 ` [PATCH 1/4 v2] " Julia Lawall
2015-11-19 21:32 ` Julia Lawall
2015-12-01 1:56 ` Brian Norris
2015-12-01 1:56 ` Brian Norris
2015-11-18 22:04 ` [PATCH 2/4] mtd: nand: sunxi: add missing of_node_put Julia Lawall
2015-11-18 22:04 ` Julia Lawall
2015-11-18 22:04 ` Julia Lawall
2015-11-23 7:26 ` Chen-Yu Tsai
2015-11-23 7:26 ` Chen-Yu Tsai
2015-11-23 7:26 ` Chen-Yu Tsai
2015-11-23 13:59 ` Boris Brezillon
2015-11-23 13:59 ` Boris Brezillon
2015-11-23 13:59 ` Boris Brezillon
2015-12-01 1:56 ` Brian Norris
2015-12-01 1:56 ` Brian Norris
2015-12-01 1:56 ` Brian Norris
2015-11-18 22:04 ` [PATCH 3/4] iio: adc: spmi-vadc: " Julia Lawall
2015-11-18 22:04 ` Julia Lawall
2015-11-21 18:25 ` Jonathan Cameron
2015-11-18 22:04 ` [PATCH 4/4] power/reset: at91-reset: " Julia Lawall
2015-11-18 22:04 ` Julia Lawall
2015-12-05 0:42 ` Sebastian Reichel
2015-12-05 0:42 ` Sebastian Reichel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20151118224440.GC64635@google.com \
--to=computersforpeace@gmail.com \
--cc=Julia.Lawall@lip6.fr \
--cc=andrew@lunn.ch \
--cc=bcm-kernel-feedback-list@broadcom.com \
--cc=bhelgaas@google.com \
--cc=dwmw2@infradead.org \
--cc=jason@lakedaemon.net \
--cc=kdasu.kdev@gmail.com \
--cc=kernel-janitors@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mtd@lists.infradead.org \
--cc=linux@arm.linux.org.uk \
--cc=thomas.petazzoni@free-electrons.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.