Skip to content

Commit 6e6de3d

Browse files
praritJessica Yu
authored andcommitted
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 <[email protected]> Signed-off-by: Barret Rhoden <[email protected]> Cc: David Arcari <[email protected]> Cc: Jessica Yu <[email protected]> Cc: Heiko Carstens <[email protected]> Signed-off-by: Jessica Yu <[email protected]>
1 parent cd6c84d commit 6e6de3d

File tree

1 file changed

+2
-4
lines changed

1 file changed

+2
-4
lines changed

kernel/module.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3397,8 +3397,7 @@ static bool finished_loading(const char *name)
33973397
sched_annotate_sleep();
33983398
mutex_lock(&module_mutex);
33993399
mod = find_module_all(name, strlen(name), true);
3400-
ret = !mod || mod->state == MODULE_STATE_LIVE
3401-
|| mod->state == MODULE_STATE_GOING;
3400+
ret = !mod || mod->state == MODULE_STATE_LIVE;
34023401
mutex_unlock(&module_mutex);
34033402

34043403
return ret;
@@ -3588,8 +3587,7 @@ static int add_unformed_module(struct module *mod)
35883587
mutex_lock(&module_mutex);
35893588
old = find_module_all(mod->name, strlen(mod->name), true);
35903589
if (old != NULL) {
3591-
if (old->state == MODULE_STATE_COMING
3592-
|| old->state == MODULE_STATE_UNFORMED) {
3590+
if (old->state != MODULE_STATE_LIVE) {
35933591
/* Wait in case it fails to load. */
35943592
mutex_unlock(&module_mutex);
35953593
err = wait_event_interruptible(module_wq,

0 commit comments

Comments
 (0)