diff options
| author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2023-05-01 15:20:08 -0700 | 
|---|---|---|
| committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2023-05-01 15:20:08 -0700 | 
| commit | 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e (patch) | |
| tree | d57f3a63479a07b4e0cece029886e76e04feb984 /kernel/module/main.c | |
| parent | 5dc63e56a9cf8df0b59c234a505a1653f1bdf885 (diff) | |
| parent | 53bea86b5712c7491bb3dae12e271666df0a308c (diff) | |
Merge branch 'next' into for-linus
Prepare input updates for 6.4 merge window.
Diffstat (limited to 'kernel/module/main.c')
| -rw-r--r-- | kernel/module/main.c | 29 | 
1 files changed, 23 insertions, 6 deletions
diff --git a/kernel/module/main.c b/kernel/module/main.c index 48568a0f5651..d3be89de706d 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -17,6 +17,7 @@  #include <linux/fs.h>  #include <linux/kernel.h>  #include <linux/kernel_read_file.h> +#include <linux/kstrtox.h>  #include <linux/slab.h>  #include <linux/vmalloc.h>  #include <linux/elf.h> @@ -2393,7 +2394,8 @@ static bool finished_loading(const char *name)  	sched_annotate_sleep();  	mutex_lock(&module_mutex);  	mod = find_module_all(name, strlen(name), true); -	ret = !mod || mod->state == MODULE_STATE_LIVE; +	ret = !mod || mod->state == MODULE_STATE_LIVE +		|| mod->state == MODULE_STATE_GOING;  	mutex_unlock(&module_mutex);  	return ret; @@ -2569,20 +2571,35 @@ static int add_unformed_module(struct module *mod)  	mod->state = MODULE_STATE_UNFORMED; -again:  	mutex_lock(&module_mutex);  	old = find_module_all(mod->name, strlen(mod->name), true);  	if (old != NULL) { -		if (old->state != MODULE_STATE_LIVE) { +		if (old->state == MODULE_STATE_COMING +		    || old->state == MODULE_STATE_UNFORMED) {  			/* Wait in case it fails to load. */  			mutex_unlock(&module_mutex);  			err = wait_event_interruptible(module_wq,  					       finished_loading(mod->name));  			if (err)  				goto out_unlocked; -			goto again; + +			/* The module might have gone in the meantime. */ +			mutex_lock(&module_mutex); +			old = find_module_all(mod->name, strlen(mod->name), +					      true);  		} -		err = -EEXIST; + +		/* +		 * We are here only when the same module was being loaded. Do +		 * not try to load it again right now. It prevents long delays +		 * caused by serialized module load failures. It might happen +		 * when more devices of the same type trigger load of +		 * a particular module. +		 */ +		if (old && old->state == MODULE_STATE_LIVE) +			err = -EEXIST; +		else +			err = -EBUSY;  		goto out;  	}  	mod_update_bounds(mod); @@ -2659,7 +2676,7 @@ static int unknown_module_param_cb(char *param, char *val, const char *modname,  	int ret;  	if (strcmp(param, "async_probe") == 0) { -		if (strtobool(val, &mod->async_probe_requested)) +		if (kstrtobool(val, &mod->async_probe_requested))  			mod->async_probe_requested = true;  		return 0;  	}  | 
