aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/module.c
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2009-04-15 13:24:06 -0400
committerIngo Molnar <mingo@elte.hu>2009-04-17 10:59:15 -0400
commit93eb677d74a4f7d3edfb678c94f6c0544d9fbad2 (patch)
tree8bbc46895be623a78316230362e94969dbb02135 /kernel/module.c
parentf3948f8857ef5de239f28a61dddb1554a0ae4c2c (diff)
ftrace: use module notifier for function tracer
The hooks in the module code for the function tracer must be called before any of that module code runs. The function tracer hooks modify the module (replacing calls to mcount to nops). If the code is executed while the change occurs, then the CPU can take a GPF. To handle the above with a bit of paranoia, I originally implemented the hooks as calls directly from the module code. After examining the notifier calls, it looks as though the start up notify is called before any of the module's code is executed. This makes the use of the notify safe with ftrace. Only the startup notify is required to be "safe". The shutdown simply removes the entries from the ftrace function list, and does not modify any code. This change has another benefit. It removes a issue with a reverse dependency in the mutexes of ftrace_lock and module_mutex. [ Impact: fix lock dependency bug, cleanup ] Cc: Rusty Russell <rusty@rustcorp.com.au> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/module.c')
-rw-r--r--kernel/module.c19
1 files changed, 7 insertions, 12 deletions
diff --git a/kernel/module.c b/kernel/module.c
index a0394706f10c..2383e60fcf3f 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -1490,9 +1490,6 @@ static void free_module(struct module *mod)
1490 /* Free any allocated parameters. */ 1490 /* Free any allocated parameters. */
1491 destroy_params(mod->kp, mod->num_kp); 1491 destroy_params(mod->kp, mod->num_kp);
1492 1492
1493 /* release any pointers to mcount in this module */
1494 ftrace_release(mod->module_core, mod->core_size);
1495
1496 /* This may be NULL, but that's OK */ 1493 /* This may be NULL, but that's OK */
1497 module_free(mod, mod->module_init); 1494 module_free(mod, mod->module_init);
1498 kfree(mod->args); 1495 kfree(mod->args);
@@ -1893,11 +1890,9 @@ static noinline struct module *load_module(void __user *umod,
1893 unsigned int symindex = 0; 1890 unsigned int symindex = 0;
1894 unsigned int strindex = 0; 1891 unsigned int strindex = 0;
1895 unsigned int modindex, versindex, infoindex, pcpuindex; 1892 unsigned int modindex, versindex, infoindex, pcpuindex;
1896 unsigned int num_mcount;
1897 struct module *mod; 1893 struct module *mod;
1898 long err = 0; 1894 long err = 0;
1899 void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */ 1895 void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
1900 unsigned long *mseg;
1901 mm_segment_t old_fs; 1896 mm_segment_t old_fs;
1902 1897
1903 DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n", 1898 DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n",
@@ -2179,7 +2174,13 @@ static noinline struct module *load_module(void __user *umod,
2179 sizeof(*mod->trace_events), 2174 sizeof(*mod->trace_events),
2180 &mod->num_trace_events); 2175 &mod->num_trace_events);
2181#endif 2176#endif
2182 2177#ifdef CONFIG_FTRACE_MCOUNT_RECORD
2178 /* sechdrs[0].sh_size is always zero */
2179 mod->ftrace_callsites = section_objs(hdr, sechdrs, secstrings,
2180 "__mcount_loc",
2181 sizeof(*mod->ftrace_callsites),
2182 &mod->num_ftrace_callsites);
2183#endif
2183#ifdef CONFIG_MODVERSIONS 2184#ifdef CONFIG_MODVERSIONS
2184 if ((mod->num_syms && !mod->crcs) 2185 if ((mod->num_syms && !mod->crcs)
2185 || (mod->num_gpl_syms && !mod->gpl_crcs) 2186 || (mod->num_gpl_syms && !mod->gpl_crcs)
@@ -2244,11 +2245,6 @@ static noinline struct module *load_module(void __user *umod,
2244 dynamic_debug_setup(debug, num_debug); 2245 dynamic_debug_setup(debug, num_debug);
2245 } 2246 }
2246 2247
2247 /* sechdrs[0].sh_size is always zero */
2248 mseg = section_objs(hdr, sechdrs, secstrings, "__mcount_loc",
2249 sizeof(*mseg), &num_mcount);
2250 ftrace_init_module(mod, mseg, mseg + num_mcount);
2251
2252 err = module_finalize(hdr, sechdrs, mod); 2248 err = module_finalize(hdr, sechdrs, mod);
2253 if (err < 0) 2249 if (err < 0)
2254 goto cleanup; 2250 goto cleanup;
@@ -2309,7 +2305,6 @@ static noinline struct module *load_module(void __user *umod,
2309 cleanup: 2305 cleanup:
2310 kobject_del(&mod->mkobj.kobj); 2306 kobject_del(&mod->mkobj.kobj);
2311 kobject_put(&mod->mkobj.kobj); 2307 kobject_put(&mod->mkobj.kobj);
2312 ftrace_release(mod->module_core, mod->core_size);
2313 free_unload: 2308 free_unload:
2314 module_unload_free(mod); 2309 module_unload_free(mod);
2315#if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) 2310#if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP)