From 944a1fa01266aa9ace607f29551b73c41e9440e9 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 17 Apr 2013 13:20:03 +0930 Subject: module: don't unlink the module until we've removed all exposure. Otherwise we get a race between unload and reload of the same module: the new module doesn't see the old one in the list, but then fails because it can't register over the still-extant entries in sysfs: [ 103.981925] ------------[ cut here ]------------ [ 103.986902] WARNING: at fs/sysfs/dir.c:536 sysfs_add_one+0xab/0xd0() [ 103.993606] Hardware name: CrownBay Platform [ 103.998075] sysfs: cannot create duplicate filename '/module/pch_gbe' [ 104.004784] Modules linked in: pch_gbe(+) [last unloaded: pch_gbe] [ 104.011362] Pid: 3021, comm: modprobe Tainted: G W 3.9.0-rc5+ #5 [ 104.018662] Call Trace: [ 104.021286] [] warn_slowpath_common+0x6d/0xa0 [ 104.026933] [] ? sysfs_add_one+0xab/0xd0 [ 104.031986] [] ? sysfs_add_one+0xab/0xd0 [ 104.037000] [] warn_slowpath_fmt+0x2e/0x30 [ 104.042188] [] sysfs_add_one+0xab/0xd0 [ 104.046982] [] create_dir+0x5e/0xa0 [ 104.051633] [] sysfs_create_dir+0x78/0xd0 [ 104.056774] [] kobject_add_internal+0x83/0x1f0 [ 104.062351] [] ? kvasprintf+0x46/0x60 [ 104.067231] [] kobject_add_varg+0x2d/0x50 [ 104.072450] [] kobject_init_and_add+0x27/0x30 [ 104.078075] [] mod_sysfs_setup+0x80/0x540 [ 104.083207] [] ? module_bug_finalize+0x51/0xc0 [ 104.088720] [] load_module+0x1429/0x18b0 We can teardown sysfs first, then to be sure, put the state in MODULE_STATE_UNFORMED so it's ignored while we deconstruct it. Reported-by: Veaceslav Falico Tested-by: Veaceslav Falico Signed-off-by: Rusty Russell --- kernel/module.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'kernel/module.c') diff --git a/kernel/module.c b/kernel/module.c index 3c2c72d3bf8..b049939177f 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1862,12 +1862,12 @@ static void free_module(struct module *mod) { trace_module_free(mod); - /* Delete from various lists */ - mutex_lock(&module_mutex); - stop_machine(__unlink_module, mod, NULL); - mutex_unlock(&module_mutex); mod_sysfs_teardown(mod); + /* We leave it in list to prevent duplicate loads, but make sure + * that noone uses it while it's being deconstructed. */ + mod->state = MODULE_STATE_UNFORMED; + /* Remove dynamic debug info */ ddebug_remove_module(mod->name); @@ -1880,6 +1880,11 @@ static void free_module(struct module *mod) /* Free any allocated parameters. */ destroy_params(mod->kp, mod->num_kp); + /* Now we can delete it from the lists */ + mutex_lock(&module_mutex); + stop_machine(__unlink_module, mod, NULL); + mutex_unlock(&module_mutex); + /* This may be NULL, but that's OK */ unset_module_init_ro_nx(mod); module_free(mod, mod->module_init); -- cgit v1.2.3