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