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

Andy Shevchenko
2021-03-27T22:21:14Z

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

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