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

From: "Gary Guo" <[email-masked]>
Date: Fri, 24 Apr 2026 20:26:00 +0100

On Wed Apr 22, 2026 at 10:49 AM BST, Shashank Balaji wrote:
> 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 <[email-masked]>
> Co-developed-by: Rahul Bukte <[email-masked]>
> Signed-off-by: Rahul Bukte <[email-masked]>
> Signed-off-by: Shashank Balaji <[email-masked]>
>
> ---
>
> 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;

I don't think lazily creation of module_kset is the correct approach.

The only thing that param_sysfs_init does is create a kset_create_and_add, which
can be done really early. Driver core creates a couple of them during
initialization too.

This is ultimately just an init order problem, and you need things to be
initialized earlier. Given lack of dependency of anything else, this could just
be a pure_initcall which will be initialized before everything else.

Best,
Gary