mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	kernel/module.c: Only return -EEXIST for modules that have finished loading
Microsoft HyperV disables the X86_FEATURE_SMCA bit on AMD systems, and linux guests boot with repeated errors: amd64_edac_mod: Unknown symbol amd_unregister_ecc_decoder (err -2) amd64_edac_mod: Unknown symbol amd_register_ecc_decoder (err -2) amd64_edac_mod: Unknown symbol amd_report_gart_errors (err -2) amd64_edac_mod: Unknown symbol amd_unregister_ecc_decoder (err -2) amd64_edac_mod: Unknown symbol amd_register_ecc_decoder (err -2) amd64_edac_mod: Unknown symbol amd_report_gart_errors (err -2) The warnings occur because the module code erroneously returns -EEXIST for modules that have failed to load and are in the process of being removed from the module list. module amd64_edac_mod has a dependency on module edac_mce_amd. Using modules.dep, systemd will load edac_mce_amd for every request of amd64_edac_mod. When the edac_mce_amd module loads, the module has state MODULE_STATE_UNFORMED and once the module load fails and the state becomes MODULE_STATE_GOING. Another request for edac_mce_amd module executes and add_unformed_module() will erroneously return -EEXIST even though the previous instance of edac_mce_amd has MODULE_STATE_GOING. Upon receiving -EEXIST, systemd attempts to load amd64_edac_mod, which fails because of unknown symbols from edac_mce_amd. add_unformed_module() must wait to return for any case other than MODULE_STATE_LIVE to prevent a race between multiple loads of dependent modules. Signed-off-by: Prarit Bhargava <prarit@redhat.com> Signed-off-by: Barret Rhoden <brho@google.com> Cc: David Arcari <darcari@redhat.com> Cc: Jessica Yu <jeyu@kernel.org> Cc: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Jessica Yu <jeyu@kernel.org>
This commit is contained in:
		
							parent
							
								
									cd6c84d8f0
								
							
						
					
					
						commit
						6e6de3dee5
					
				
					 1 changed files with 2 additions and 4 deletions
				
			
		| 
						 | 
				
			
			@ -3397,8 +3397,7 @@ 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
 | 
			
		||||
		|| mod->state == MODULE_STATE_GOING;
 | 
			
		||||
	ret = !mod || mod->state == MODULE_STATE_LIVE;
 | 
			
		||||
	mutex_unlock(&module_mutex);
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
| 
						 | 
				
			
			@ -3588,8 +3587,7 @@ static int add_unformed_module(struct module *mod)
 | 
			
		|||
	mutex_lock(&module_mutex);
 | 
			
		||||
	old = find_module_all(mod->name, strlen(mod->name), true);
 | 
			
		||||
	if (old != NULL) {
 | 
			
		||||
		if (old->state == MODULE_STATE_COMING
 | 
			
		||||
		    || old->state == MODULE_STATE_UNFORMED) {
 | 
			
		||||
		if (old->state != MODULE_STATE_LIVE) {
 | 
			
		||||
			/* Wait in case it fails to load. */
 | 
			
		||||
			mutex_unlock(&module_mutex);
 | 
			
		||||
			err = wait_event_interruptible(module_wq,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue