aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2009-03-31 15:05:35 -0400
committerRusty Russell <rusty@rustcorp.com.au>2009-03-30 22:35:35 -0400
commite91defa26c527ceeaff6266c55cdc7e17c9081a2 (patch)
tree03554f76949e5b1bcd4e640a10846d9540b97640
parentacae05156551fd7528fbb616271e672789388e3c (diff)
module: don't use stop_machine on module load
Kay Sievers <kay.sievers@vrfy.org> discovered that boot times are slowed by about half a second because all the stop_machine_create() calls, and he only probes about 40 modules (I have 125 loaded on this laptop). We only do stop_machine_create() so we can unlink the module if something goes wrong, but it's overkill (and buggy anyway: if stop_machine_create() fails we still call stop_machine_destroy()). Since we are only protecting against kallsyms (esp. oops) walking the list, synchronize_sched() is sufficient (synchronize_rcu() is probably sufficient, but we're not in a hurry). Kay says of this patch: ... no module takes more than 40 millisecs to link now, most of them are between 3 and 8 millisecs. That looks very different to the numbers without this patch and the otherwise same setup, where we get heavy noise in the traces and many delays of up to 200 millisecs until linking, most of them taking 30+ millisecs. Tested-by: Kay Sievers <kay.sievers@vrfy.org> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r--kernel/module.c12
1 files changed, 3 insertions, 9 deletions
diff --git a/kernel/module.c b/kernel/module.c
index e8cf636e614b..1a9a3986b136 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -1912,12 +1912,6 @@ static noinline struct module *load_module(void __user *umod,
1912 if (len > 64 * 1024 * 1024 || (hdr = vmalloc(len)) == NULL) 1912 if (len > 64 * 1024 * 1024 || (hdr = vmalloc(len)) == NULL)
1913 return ERR_PTR(-ENOMEM); 1913 return ERR_PTR(-ENOMEM);
1914 1914
1915 /* Create stop_machine threads since the error path relies on
1916 * a non-failing stop_machine call. */
1917 err = stop_machine_create();
1918 if (err)
1919 goto free_hdr;
1920
1921 if (copy_from_user(hdr, umod, len) != 0) { 1915 if (copy_from_user(hdr, umod, len) != 0) {
1922 err = -EFAULT; 1916 err = -EFAULT;
1923 goto free_hdr; 1917 goto free_hdr;
@@ -2303,12 +2297,13 @@ static noinline struct module *load_module(void __user *umod,
2303 /* Get rid of temporary copy */ 2297 /* Get rid of temporary copy */
2304 vfree(hdr); 2298 vfree(hdr);
2305 2299
2306 stop_machine_destroy();
2307 /* Done! */ 2300 /* Done! */
2308 return mod; 2301 return mod;
2309 2302
2310 unlink: 2303 unlink:
2311 stop_machine(__unlink_module, mod, NULL); 2304 /* Unlink carefully: kallsyms could be walking list. */
2305 list_del_rcu(&mod->list);
2306 synchronize_sched();
2312 module_arch_cleanup(mod); 2307 module_arch_cleanup(mod);
2313 cleanup: 2308 cleanup:
2314 kobject_del(&mod->mkobj.kobj); 2309 kobject_del(&mod->mkobj.kobj);
@@ -2331,7 +2326,6 @@ static noinline struct module *load_module(void __user *umod,
2331 kfree(args); 2326 kfree(args);
2332 free_hdr: 2327 free_hdr:
2333 vfree(hdr); 2328 vfree(hdr);
2334 stop_machine_destroy();
2335 return ERR_PTR(err); 2329 return ERR_PTR(err);
2336 2330
2337 truncated: 2331 truncated: