diff mbox series

[v2,1/6] software node: Free resources explicitly when swnode_register() fails

Message ID 20210329151207.36619-1-andriy.shevchenko@linux.intel.com
State Accepted
Commit 3f6b6536a73fad0c2c82db1672fc500cc15ff551
Headers show
Series [v2,1/6] software node: Free resources explicitly when swnode_register() fails | expand

Commit Message

Andy Shevchenko March 29, 2021, 3:12 p.m. UTC
Currently we have a slightly twisted logic in swnode_register().
It frees resources that it doesn't allocate on error path and
in once case it relies on the ->release() implementation.

Untwist the logic by freeing resources explicitly when swnode_register()
fails. Currently it happens only in fwnode_create_software_node().

Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
v2: no changes
 drivers/base/swnode.c | 29 +++++++++++++++++------------
 1 file changed, 17 insertions(+), 12 deletions(-)

Comments

Daniel Scally March 29, 2021, 9:06 p.m. UTC | #1
Hi Andy

On 29/03/2021 16:12, Andy Shevchenko wrote:
> Deduplicate conditional and assignment in fwnode_create_software_node(),
> i.e. parent is checked in two out of three cases and parent software node
> is assigned by to_swnode() call.
>
> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>


Reviewed-by: Daniel Scally <djrscally@gmail.com>

> ---
> v2: no changes
>  drivers/base/swnode.c | 17 ++++++++---------
>  1 file changed, 8 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
> index 19aa44bc2628..db982859171e 100644
> --- a/drivers/base/swnode.c
> +++ b/drivers/base/swnode.c
> @@ -973,15 +973,14 @@ fwnode_create_software_node(const struct property_entry *properties,
>  {
>  	struct fwnode_handle *fwnode;
>  	struct software_node *node;
> -	struct swnode *p = NULL;
> -
> -	if (parent) {
> -		if (IS_ERR(parent))
> -			return ERR_CAST(parent);
> -		if (!is_software_node(parent))
> -			return ERR_PTR(-EINVAL);
> -		p = to_swnode(parent);
> -	}
> +	struct swnode *p;
> +
> +	if (IS_ERR(parent))
> +		return ERR_CAST(parent);
> +
> +	p = to_swnode(parent);
> +	if (parent && !p)
> +		return ERR_PTR(-EINVAL);
>  
>  	node = software_node_alloc(properties);
>  	if (IS_ERR(node))
Daniel Scally March 29, 2021, 10:45 p.m. UTC | #2
Hi Andy

On 29/03/2021 16:12, Andy Shevchenko wrote:
> Currently we have a slightly twisted logic in swnode_register().
> It frees resources that it doesn't allocate on error path and
> in once case it relies on the ->release() implementation.
>
> Untwist the logic by freeing resources explicitly when swnode_register()
> fails. Currently it happens only in fwnode_create_software_node().
>
> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>


Reviewed-by: Daniel Scally <djrscally@gmail.com>

and

Tested-by: Daniel Scally <djrscally@gmail.com>

> ---
> v2: no changes
>  drivers/base/swnode.c | 29 +++++++++++++++++------------
>  1 file changed, 17 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
> index fa3719ef80e4..456f5fe58b58 100644
> --- a/drivers/base/swnode.c
> +++ b/drivers/base/swnode.c
> @@ -767,22 +767,19 @@ swnode_register(const struct software_node *node, struct swnode *parent,
>  	int ret;
>  
>  	swnode = kzalloc(sizeof(*swnode), GFP_KERNEL);
> -	if (!swnode) {
> -		ret = -ENOMEM;
> -		goto out_err;
> -	}
> +	if (!swnode)
> +		return ERR_PTR(-ENOMEM);
>  
>  	ret = ida_simple_get(parent ? &parent->child_ids : &swnode_root_ids,
>  			     0, 0, GFP_KERNEL);
>  	if (ret < 0) {
>  		kfree(swnode);
> -		goto out_err;
> +		return ERR_PTR(ret);
>  	}
>  
>  	swnode->id = ret;
>  	swnode->node = node;
>  	swnode->parent = parent;
> -	swnode->allocated = allocated;
>  	swnode->kobj.kset = swnode_kset;
>  	fwnode_init(&swnode->fwnode, &software_node_ops);
>  
> @@ -803,16 +800,17 @@ swnode_register(const struct software_node *node, struct swnode *parent,
>  		return ERR_PTR(ret);
>  	}
>  
> +	/*
> +	 * Assign the flag only in the successful case, so
> +	 * the above kobject_put() won't mess up with properties.
> +	 */
> +	swnode->allocated = allocated;
> +
>  	if (parent)
>  		list_add_tail(&swnode->entry, &parent->children);
>  
>  	kobject_uevent(&swnode->kobj, KOBJ_ADD);
>  	return &swnode->fwnode;
> -
> -out_err:
> -	if (allocated)
> -		property_entries_free(node->properties);
> -	return ERR_PTR(ret);
>  }
>  
>  /**
> @@ -963,6 +961,7 @@ struct fwnode_handle *
>  fwnode_create_software_node(const struct property_entry *properties,
>  			    const struct fwnode_handle *parent)
>  {
> +	struct fwnode_handle *fwnode;
>  	struct software_node *node;
>  	struct swnode *p = NULL;
>  	int ret;
> @@ -987,7 +986,13 @@ fwnode_create_software_node(const struct property_entry *properties,
>  
>  	node->parent = p ? p->node : NULL;
>  
> -	return swnode_register(node, p, 1);
> +	fwnode = swnode_register(node, p, 1);
> +	if (IS_ERR(fwnode)) {
> +		property_entries_free(node->properties);
> +		kfree(node);
> +	}
> +
> +	return fwnode;
>  }
>  EXPORT_SYMBOL_GPL(fwnode_create_software_node);
>
Heikki Krogerus March 31, 2021, 11:06 a.m. UTC | #3
On Mon, Mar 29, 2021 at 06:12:02PM +0300, Andy Shevchenko wrote:
> Currently we have a slightly twisted logic in swnode_register().

> It frees resources that it doesn't allocate on error path and

> in once case it relies on the ->release() implementation.

> 

> Untwist the logic by freeing resources explicitly when swnode_register()

> fails. Currently it happens only in fwnode_create_software_node().

> 

> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>


It all looks OK to me. FWIW, for the whole series:

Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>


> ---

> v2: no changes

>  drivers/base/swnode.c | 29 +++++++++++++++++------------

>  1 file changed, 17 insertions(+), 12 deletions(-)

> 

> diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c

> index fa3719ef80e4..456f5fe58b58 100644

> --- a/drivers/base/swnode.c

> +++ b/drivers/base/swnode.c

> @@ -767,22 +767,19 @@ swnode_register(const struct software_node *node, struct swnode *parent,

>  	int ret;

>  

>  	swnode = kzalloc(sizeof(*swnode), GFP_KERNEL);

> -	if (!swnode) {

> -		ret = -ENOMEM;

> -		goto out_err;

> -	}

> +	if (!swnode)

> +		return ERR_PTR(-ENOMEM);

>  

>  	ret = ida_simple_get(parent ? &parent->child_ids : &swnode_root_ids,

>  			     0, 0, GFP_KERNEL);

>  	if (ret < 0) {

>  		kfree(swnode);

> -		goto out_err;

> +		return ERR_PTR(ret);

>  	}

>  

>  	swnode->id = ret;

>  	swnode->node = node;

>  	swnode->parent = parent;

> -	swnode->allocated = allocated;

>  	swnode->kobj.kset = swnode_kset;

>  	fwnode_init(&swnode->fwnode, &software_node_ops);

>  

> @@ -803,16 +800,17 @@ swnode_register(const struct software_node *node, struct swnode *parent,

>  		return ERR_PTR(ret);

>  	}

>  

> +	/*

> +	 * Assign the flag only in the successful case, so

> +	 * the above kobject_put() won't mess up with properties.

> +	 */

> +	swnode->allocated = allocated;

> +

>  	if (parent)

>  		list_add_tail(&swnode->entry, &parent->children);

>  

>  	kobject_uevent(&swnode->kobj, KOBJ_ADD);

>  	return &swnode->fwnode;

> -

> -out_err:

> -	if (allocated)

> -		property_entries_free(node->properties);

> -	return ERR_PTR(ret);

>  }

>  

>  /**

> @@ -963,6 +961,7 @@ struct fwnode_handle *

>  fwnode_create_software_node(const struct property_entry *properties,

>  			    const struct fwnode_handle *parent)

>  {

> +	struct fwnode_handle *fwnode;

>  	struct software_node *node;

>  	struct swnode *p = NULL;

>  	int ret;

> @@ -987,7 +986,13 @@ fwnode_create_software_node(const struct property_entry *properties,

>  

>  	node->parent = p ? p->node : NULL;

>  

> -	return swnode_register(node, p, 1);

> +	fwnode = swnode_register(node, p, 1);

> +	if (IS_ERR(fwnode)) {

> +		property_entries_free(node->properties);

> +		kfree(node);

> +	}

> +

> +	return fwnode;

>  }

>  EXPORT_SYMBOL_GPL(fwnode_create_software_node);

>  

> -- 

> 2.30.2


thanks,

-- 
heikki
Rafael J. Wysocki April 8, 2021, 2:15 p.m. UTC | #4
On Wed, Mar 31, 2021 at 1:06 PM Heikki Krogerus
<heikki.krogerus@linux.intel.com> wrote:
>

> On Mon, Mar 29, 2021 at 06:12:02PM +0300, Andy Shevchenko wrote:

> > Currently we have a slightly twisted logic in swnode_register().

> > It frees resources that it doesn't allocate on error path and

> > in once case it relies on the ->release() implementation.

> >

> > Untwist the logic by freeing resources explicitly when swnode_register()

> > fails. Currently it happens only in fwnode_create_software_node().

> >

> > Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

>

> It all looks OK to me. FWIW, for the whole series:

>

> Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>


Whole series applied (with some minor changelog edits) as 5.13 material, thanks!
Andy Shevchenko April 8, 2021, 2:50 p.m. UTC | #5
On Thu, Apr 08, 2021 at 04:15:37PM +0200, Rafael J. Wysocki wrote:
> On Wed, Mar 31, 2021 at 1:06 PM Heikki Krogerus

> <heikki.krogerus@linux.intel.com> wrote:

> >

> > On Mon, Mar 29, 2021 at 06:12:02PM +0300, Andy Shevchenko wrote:

> > > Currently we have a slightly twisted logic in swnode_register().

> > > It frees resources that it doesn't allocate on error path and

> > > in once case it relies on the ->release() implementation.

> > >

> > > Untwist the logic by freeing resources explicitly when swnode_register()

> > > fails. Currently it happens only in fwnode_create_software_node().

> > >

> > > Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

> >

> > It all looks OK to me. FWIW, for the whole series:

> >

> > Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>

> 

> Whole series applied (with some minor changelog edits) as 5.13 material, thanks!


It seems Greg applied it already. Was it dropped there?

-- 
With Best Regards,
Andy Shevchenko
Rafael J. Wysocki April 8, 2021, 3:04 p.m. UTC | #6
On Thu, Apr 8, 2021 at 4:50 PM Andy Shevchenko
<andriy.shevchenko@linux.intel.com> wrote:
>

> On Thu, Apr 08, 2021 at 04:15:37PM +0200, Rafael J. Wysocki wrote:

> > On Wed, Mar 31, 2021 at 1:06 PM Heikki Krogerus

> > <heikki.krogerus@linux.intel.com> wrote:

> > >

> > > On Mon, Mar 29, 2021 at 06:12:02PM +0300, Andy Shevchenko wrote:

> > > > Currently we have a slightly twisted logic in swnode_register().

> > > > It frees resources that it doesn't allocate on error path and

> > > > in once case it relies on the ->release() implementation.

> > > >

> > > > Untwist the logic by freeing resources explicitly when swnode_register()

> > > > fails. Currently it happens only in fwnode_create_software_node().

> > > >

> > > > Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

> > >

> > > It all looks OK to me. FWIW, for the whole series:

> > >

> > > Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>

> >

> > Whole series applied (with some minor changelog edits) as 5.13 material, thanks!

>

> It seems Greg applied it already. Was it dropped there?


Did he?

OK, so please let me know if it's still there in the Greg's tree.
Andy Shevchenko April 8, 2021, 3:18 p.m. UTC | #7
On Thu, Apr 08, 2021 at 05:04:32PM +0200, Rafael J. Wysocki wrote:
> On Thu, Apr 8, 2021 at 4:50 PM Andy Shevchenko

> <andriy.shevchenko@linux.intel.com> wrote:

> > On Thu, Apr 08, 2021 at 04:15:37PM +0200, Rafael J. Wysocki wrote:

> > > On Wed, Mar 31, 2021 at 1:06 PM Heikki Krogerus

> > > <heikki.krogerus@linux.intel.com> wrote:

> > > >

> > > > On Mon, Mar 29, 2021 at 06:12:02PM +0300, Andy Shevchenko wrote:

> > > > > Currently we have a slightly twisted logic in swnode_register().

> > > > > It frees resources that it doesn't allocate on error path and

> > > > > in once case it relies on the ->release() implementation.

> > > > >

> > > > > Untwist the logic by freeing resources explicitly when swnode_register()

> > > > > fails. Currently it happens only in fwnode_create_software_node().

> > > > >

> > > > > Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>

> > > >

> > > > It all looks OK to me. FWIW, for the whole series:

> > > >

> > > > Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>

> > >

> > > Whole series applied (with some minor changelog edits) as 5.13 material, thanks!

> >

> > It seems Greg applied it already. Was it dropped there?

> 

> Did he?

> 

> OK, so please let me know if it's still there in the Greg's tree.


Here [1] what I see. Seems still there.

[1]: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git/commit/?h=driver-core-next&id=6e11b376fd74356e32d842be588e12dc9bf6e197

-- 
With Best Regards,
Andy Shevchenko
diff mbox series

Patch

diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
index fa3719ef80e4..456f5fe58b58 100644
--- a/drivers/base/swnode.c
+++ b/drivers/base/swnode.c
@@ -767,22 +767,19 @@  swnode_register(const struct software_node *node, struct swnode *parent,
 	int ret;
 
 	swnode = kzalloc(sizeof(*swnode), GFP_KERNEL);
-	if (!swnode) {
-		ret = -ENOMEM;
-		goto out_err;
-	}
+	if (!swnode)
+		return ERR_PTR(-ENOMEM);
 
 	ret = ida_simple_get(parent ? &parent->child_ids : &swnode_root_ids,
 			     0, 0, GFP_KERNEL);
 	if (ret < 0) {
 		kfree(swnode);
-		goto out_err;
+		return ERR_PTR(ret);
 	}
 
 	swnode->id = ret;
 	swnode->node = node;
 	swnode->parent = parent;
-	swnode->allocated = allocated;
 	swnode->kobj.kset = swnode_kset;
 	fwnode_init(&swnode->fwnode, &software_node_ops);
 
@@ -803,16 +800,17 @@  swnode_register(const struct software_node *node, struct swnode *parent,
 		return ERR_PTR(ret);
 	}
 
+	/*
+	 * Assign the flag only in the successful case, so
+	 * the above kobject_put() won't mess up with properties.
+	 */
+	swnode->allocated = allocated;
+
 	if (parent)
 		list_add_tail(&swnode->entry, &parent->children);
 
 	kobject_uevent(&swnode->kobj, KOBJ_ADD);
 	return &swnode->fwnode;
-
-out_err:
-	if (allocated)
-		property_entries_free(node->properties);
-	return ERR_PTR(ret);
 }
 
 /**
@@ -963,6 +961,7 @@  struct fwnode_handle *
 fwnode_create_software_node(const struct property_entry *properties,
 			    const struct fwnode_handle *parent)
 {
+	struct fwnode_handle *fwnode;
 	struct software_node *node;
 	struct swnode *p = NULL;
 	int ret;
@@ -987,7 +986,13 @@  fwnode_create_software_node(const struct property_entry *properties,
 
 	node->parent = p ? p->node : NULL;
 
-	return swnode_register(node, p, 1);
+	fwnode = swnode_register(node, p, 1);
+	if (IS_ERR(fwnode)) {
+		property_entries_free(node->properties);
+		kfree(node);
+	}
+
+	return fwnode;
 }
 EXPORT_SYMBOL_GPL(fwnode_create_software_node);