Add initcall_blacklist kernel parameter [v2]
PATCH 1/1 Add initcall_blacklist kernel parameter [v2]
When a module is built into the kernel the module_init() function becomes an initcall. Sometimes debugging through dynamic debug can help, however, debugging built in kernel modules is typically done by changing the .config, recompiling, and booting the new kernel in an effort to determine exactly which module caused a problem.
This patchset can be useful stand-alone or combined with initcall_debug. There are cases where some initcalls can hang the machine before the console can be flushed, which can make initcall_debug output inaccurate. Having the ability to skip initcalls can help further debugging of these scenarios.
Usage: initcall_blacklist=<list of comma separated initcalls>
ex) added "initcall_blacklist=sgi_uv_sysfs_init" as a kernel parameter and the log contains:
blacklisted initcall sgi_uv_sysfs_init ... ... function sgi_uv_sysfs_init returning without executing
ex) added "initcall_blacklist=foo_bar,sgi_uv_sysfs_init" as a kernel parameter and the log contains:
initcall blacklisted foo_bar
initcall blacklisted sgi_uv_sysfs_init
...
...
function sgi_uv_sysfs_init returning without executing
[v2]: A few people recommended that I add code to allow for a list of initcalls as there maybe dependencies between initcalls such that one cannot be made without the other. I also updated the patch description.
--- Documentation/kernel-parameters.txt | 4 +++ init/main.c | 50 +++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+)
Documentation/kernel-parameters.txt +4 -0
@@ -1268,6 +1268,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted. for working out where the kernel is dying during startup. + initcall_blacklist= [KNL] Do not execute a comma-separated list of + initcall functions. Useful for debugging built-in + modules and initcalls. + initrd= [BOOT] Specify the location of the initial ramdisk inport.irq= [HW] Inport (ATI XL and Microsoft) busmouse driver
init/main.c +50 -0
77 lines not on this page · raw message
Signature · 1 line
1.7.9.3
init/main.c static void __init do_initcall_level(int level) · line 819
Quoted 6 lines
init/main.c +5
-0do_initcall_level (level); + +list_for_each_safe (tmp, next, &blacklisted_initcalls) { + entry = list_entry(tmp, struct blacklist_entry, next); +free_bootmem (entry->buf,strlen (entry->buf)); +free_bootmem (entry,sizeof (*entry));
Does that really work? At this point the bootmem allocator should be already finished, so no memory will be freed.
For this case it's probably ok to leak it.
Alternatively you could use static arrays and storing pointer/len.
-Andi
Quoted 9 lines · Andi Kleen
init/main.c static void __init do_initcall_level(int level) · line 819
Quoted 6 lines
init/main.c +5
-0do_initcall_level (level); + +list_for_each_safe (tmp, next, &blacklisted_initcalls) { + entry = list_entry(tmp, struct blacklist_entry, next); +free_bootmem (entry->buf,strlen (entry->buf)); +free_bootmem (entry,sizeof (*entry));Does that really work? At this point the bootmem allocator should be already finished, so no memory will be freed.
Oh, geez ... that's a good point. I completely missed that.
Quoted 2 lines
For this case it's probably ok to leak it.
Okay ... maybe that's an option.
Quoted 3 lines
Alternatively you could use static arrays and storing pointer/len.
Yeah, I was thinking about the pros-cons of doing static vs. dynamic. I was planning on doing an array of 5 but kept falling into the trap of "how much is too much or too little?".
Does anyone object to a static array? If not I'll bang out a static version for [v3] tomorrow ...
P.
Quoted 2 lines
-Andi