modules: extend initcall_debug functionality to the module loader
authorArjan van de Ven <arjan@linux.intel.com>
Wed, 30 Jul 2008 19:49:02 +0000 (12:49 -0700)
committerRusty Russell <rusty@rustcorp.com.au>
Tue, 12 Aug 2008 07:52:54 +0000 (17:52 +1000)
The kernel has this really nice facility where if you put "initcall_debug"
on the kernel commandline, it'll print which function it's going to
execute just before calling an initcall, and then after the call completes
it will

1) print if it had an error code

2) checks for a few simple bugs (like leaving irqs off)
and

3) print how long the init call took in milliseconds.

While trying to optimize the boot speed of my laptop, I have been loving
number 3 to figure out what to optimize...  ...  and then I wished that
the same thing was done for module loading.

This patch makes the module loader use this exact same functionality; it's
a logical extension in my view (since modules are just sort of late
binding initcalls anyway) and so far I've found it quite useful in finding
where things are too slow in my boot.

Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
include/linux/init.h
init/main.c
kernel/module.c

index 11b84e1060532ecf62f73e3151b9f6eaed043c8b..93538b696e3d99f2bb30d96b83d3516c66442233 100644 (file)
@@ -139,6 +139,7 @@ extern initcall_t __con_initcall_start[], __con_initcall_end[];
 extern initcall_t __security_initcall_start[], __security_initcall_end[];
 
 /* Defined in init/main.c */
+extern int do_one_initcall(initcall_t fn);
 extern char __initdata boot_command_line[];
 extern char *saved_command_line;
 extern unsigned int reset_devices;
index 0bc7e167bf4556c63dde64eb249a1880b6675548..f6f7042331dc3ef9dbf156a807398936e0824b1a 100644 (file)
@@ -691,7 +691,7 @@ asmlinkage void __init start_kernel(void)
        rest_init();
 }
 
-static int __initdata initcall_debug;
+static int initcall_debug;
 
 static int __init initcall_debug_setup(char *str)
 {
@@ -700,7 +700,7 @@ static int __init initcall_debug_setup(char *str)
 }
 __setup("initcall_debug", initcall_debug_setup);
 
-static void __init do_one_initcall(initcall_t fn)
+int do_one_initcall(initcall_t fn)
 {
        int count = preempt_count();
        ktime_t t0, t1, delta;
@@ -740,6 +740,8 @@ static void __init do_one_initcall(initcall_t fn)
                print_fn_descriptor_symbol(KERN_WARNING "initcall %s", fn);
                printk(" returned with %s\n", msgbuf);
        }
+
+       return result;
 }
 
 
index 61d212120df48e82a1b6521120fdbd428d983a81..08864d257eb0ece2239cd86008973826bc49abd0 100644 (file)
@@ -2288,7 +2288,7 @@ sys_init_module(void __user *umod,
 
        /* Start the module */
        if (mod->init != NULL)
-               ret = mod->init();
+               ret = do_one_initcall(mod->init);
        if (ret < 0) {
                /* Init routine failed: abort.  Try to protect us from
                    buggy refcounters. */