[PATCH v3 1/4] kernel: param: initialize module_kset on-demand

Shashank Balaji
2026-04-22T09:49:23Z

module_kset is initialized in param_sysfs_init(), a subsys_initcall. A number
of platform drivers register themselves prior to subsys_initcalls. With an
upcoming patch ("driver core: platform: set mod_name in driver registration")
that sets their mod_name in struct device_driver, lookup_or_create_module()
will be called for those drivers, which calls kset_find_object(module_kset, mod_name).
This fails because module_kset isn't alive yet.

Fix this by initializing module_kset on-demand in lookup_or_create_module().
Retain the param_sysfs_init() subsys_initcall to ensure that module_kset is
live after subsys_initcalls (assuming no OOM) for any users who may need it,
on the off chance that it wasn't init'd on-demand because of no
pre-subsys_initcall drivers.

This on-demand path can trigger before subsys_initcall. kset_create_and_add()
be should safe in those contexts because the allocator is up and running by then,
no userspace to start uevent helper or listen to a uevent socket.

Suggested-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Co-developed-by: Rahul Bukte <rahul.bukte@sony.com>
Signed-off-by: Rahul Bukte <rahul.bukte@sony.com>
Signed-off-by: Shashank Balaji <shashank.mahadasyam@sony.com>

---

Patch 3 depends on this patch.
---
kernel/params.c | 41 +++++++++++++++++++++++++----------------
1 file changed, 25 insertions(+), 16 deletions(-)

diff --git a/kernel/params.c b/kernel/params.c
index 74d620bc2521..f25d6fda159c 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -745,6 +745,26 @@ void module_param_sysfs_remove(struct module *mod)
}
#endif

+static int uevent_filter(const struct kobject *kobj)
+{
+ const struct kobj_type *ktype = get_ktype(kobj);
+
+ if (ktype == &module_ktype)
+ return 1;
+ return 0;
+}
+
+static const struct kset_uevent_ops module_uevent_ops = {
+ .filter = uevent_filter,
+};
+
+static struct kset *__init_or_module ensure_module_kset(void)
+{
+ if (!module_kset)
+ module_kset = kset_create_and_add("module", &module_uevent_ops, NULL);
+ return module_kset;
+}
+
struct module_kobject * __init_or_module
lookup_or_create_module_kobject(const char *name)
{
@@ -752,6 +772,9 @@ lookup_or_create_module_kobject(const char *name)
struct kobject *kobj;
int err;

+ if (!ensure_module_kset())
+ return NULL;
+
kobj = kset_find_obj(module_kset, name);
if (kobj)
return to_module_kobject(kobj);
@@ -911,19 +934,6 @@ static const struct sysfs_ops module_sysfs_ops = {
.store = module_attr_store,
};

-static int uevent_filter(const struct kobject *kobj)
-{
- const struct kobj_type *ktype = get_ktype(kobj);
-
- if (ktype == &module_ktype)
- return 1;
- return 0;
-}
-
-static const struct kset_uevent_ops module_uevent_ops = {
- .filter = uevent_filter,
-};
-
struct kset *module_kset;

static void module_kobj_release(struct kobject *kobj)
@@ -940,7 +950,7 @@ const struct kobj_type module_ktype = {
};

/*
- * param_sysfs_init - create "module" kset
+ * param_sysfs_init - create module_kset if not already done
*
* This must be done before the initramfs is unpacked and
* request_module() thus becomes possible, because otherwise the
@@ -948,8 +958,7 @@ const struct kobj_type module_ktype = {
*/
static int __init param_sysfs_init(void)
{
- module_kset = kset_create_and_add("module", &module_uevent_ops, NULL);
- if (!module_kset) {
+ if (!ensure_module_kset()) {
printk(KERN_WARNING "%s (%d): error creating kset\n",
__FILE__, __LINE__);
return -ENOMEM;

--
2.43.0