diff mbox series

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

Message ID 20210327222012.54103-1-andriy.shevchenko@linux.intel.com
State Superseded
Headers show
Series [v1,1/8] software node: Free resources explicitly when swnode_register() fails | expand

Commit Message

Andy Shevchenko March 27, 2021, 10:20 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>
---
 drivers/base/swnode.c | 29 +++++++++++++++++------------
 1 file changed, 17 insertions(+), 12 deletions(-)

Comments

Greg Kroah-Hartman March 28, 2021, 8:43 a.m. UTC | #1
On Sun, Mar 28, 2021 at 12:20:09AM +0200, Andy Shevchenko wrote:
> Since we don't use structure field layout randomization

> the manual shuffling can affect some macros, in particular

> kobj_to_swnode(), which becomes a no-op when kobj member

> is the first one in the struct swnode.

> 

> Bloat-o-meter statistics:

> 

>   add/remove: 0/0 grow/shrink: 2/10 up/down: 9/-100 (-91)

>   Total: Before=7217, After=7126, chg -1.26%

> 

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

> ---

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

>  1 file changed, 1 insertion(+), 1 deletion(-)

> 

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

> index 22f81688af2c..ae53c48f84b1 100644

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

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

> @@ -13,10 +13,10 @@

>  #include <linux/sysfs.h>

>  

>  struct swnode {

> -	int id;

>  	struct kobject kobj;

>  	struct fwnode_handle fwnode;

>  	const struct software_node *node;

> +	int id;


So you remove one math operation on a pointer and get a 1% size decrease
of the whole kernel?  Or just one file?

thanks,

greg k-h
Greg Kroah-Hartman March 28, 2021, 8:44 a.m. UTC | #2
On Sun, Mar 28, 2021 at 12:20:10AM +0200, Andy Shevchenko wrote:
> By introducing two temporary variables simplify swnode_register() a bit.
> No functional change intended.
> 
> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> ---
>  drivers/base/swnode.c | 11 +++++------
>  1 file changed, 5 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c
> index ae53c48f84b1..1e81aaf5f6a1 100644
> --- a/drivers/base/swnode.c
> +++ b/drivers/base/swnode.c
> @@ -894,6 +894,8 @@ static struct fwnode_handle *
>  swnode_register(const struct software_node *node, struct swnode *parent,
>  		unsigned int allocated)
>  {
> +	struct ida *ids = parent ? &parent->child_ids : &swnode_root_ids;
> +	struct kobject *kobj_parent = parent ? &parent->kobj : NULL;

?: operations are horrid.  Please spell this out in real if statements
so that we can properly understand and maintain them for the next 20+
years.

thanks,

greg k-h
Andy Shevchenko March 28, 2021, 12:50 p.m. UTC | #3
On Sun, Mar 28, 2021 at 11:47 AM Greg Kroah-Hartman
<gregkh@linuxfoundation.org> wrote:
>

> On Sun, Mar 28, 2021 at 12:20:09AM +0200, Andy Shevchenko wrote:

> > Since we don't use structure field layout randomization

> > the manual shuffling can affect some macros, in particular

> > kobj_to_swnode(), which becomes a no-op when kobj member

> > is the first one in the struct swnode.

> >

> > Bloat-o-meter statistics:

> >

> >   add/remove: 0/0 grow/shrink: 2/10 up/down: 9/-100 (-91)

> >   Total: Before=7217, After=7126, chg -1.26%

> >

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

> > ---

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

> >  1 file changed, 1 insertion(+), 1 deletion(-)

> >

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

> > index 22f81688af2c..ae53c48f84b1 100644

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

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

> > @@ -13,10 +13,10 @@

> >  #include <linux/sysfs.h>

> >

> >  struct swnode {

> > -     int id;

> >       struct kobject kobj;

> >       struct fwnode_handle fwnode;

> >       const struct software_node *node;

> > +     int id;

>

> So you remove one math operation on a pointer and get a 1% size decrease

> of the whole kernel?  Or just one file?


One file, swnode.o. I'll clarify this in the commit message.

-- 
With Best Regards,
Andy Shevchenko
Andy Shevchenko March 28, 2021, 12:50 p.m. UTC | #4
On Sun, Mar 28, 2021 at 11:48 AM Greg Kroah-Hartman
<gregkh@linuxfoundation.org> wrote:
>

> On Sun, Mar 28, 2021 at 12:20:10AM +0200, Andy Shevchenko wrote:

> > By introducing two temporary variables simplify swnode_register() a bit.

> > No functional change intended.

> >

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

> > ---

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

> >  1 file changed, 5 insertions(+), 6 deletions(-)

> >

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

> > index ae53c48f84b1..1e81aaf5f6a1 100644

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

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

> > @@ -894,6 +894,8 @@ static struct fwnode_handle *

> >  swnode_register(const struct software_node *node, struct swnode *parent,

> >               unsigned int allocated)

> >  {

> > +     struct ida *ids = parent ? &parent->child_ids : &swnode_root_ids;

> > +     struct kobject *kobj_parent = parent ? &parent->kobj : NULL;

>

> ?: operations are horrid.  Please spell this out in real if statements

> so that we can properly understand and maintain them for the next 20+

> years.


Will do, thanks!

--
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);