aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/ftrace.c
diff options
context:
space:
mode:
authorQiu Peiyang <peiyangx.qiu@intel.com>2015-12-25 01:46:00 -0500
committerSteven Rostedt <rostedt@goodmis.org>2016-01-07 15:56:21 -0500
commit5156dca34a3e1e1edac2d0dabf43d8632909b7aa (patch)
tree9b75d4ecfe3d1d1b20d73f21baab2bf0b0969b70 /kernel/trace/ftrace.c
parentb7ffffbb46f205e7727a18bcc7a46c3c2b534f7c (diff)
ftrace: Fix the race between ftrace and insmod
We hit ftrace_bug report when booting Android on a 64bit ATOM SOC chip. Basically, there is a race between insmod and ftrace_run_update_code. After load_module=>ftrace_module_init, another thread jumps in to call ftrace_run_update_code=>ftrace_arch_code_modify_prepare =>set_all_modules_text_rw, to change all modules as RW. Since the new module is at MODULE_STATE_UNFORMED, the text attribute is not changed. Then, the 2nd thread goes ahead to change codes. However, load_module continues to call complete_formation=>set_section_ro_nx, then 2nd thread would fail when probing the module's TEXT. The patch fixes it by using notifier to delay the enabling of ftrace records to the time when module is at state MODULE_STATE_COMING. Link: http://lkml.kernel.org/r/567CE628.3000609@intel.com Signed-off-by: Qiu Peiyang <peiyangx.qiu@intel.com> Signed-off-by: Zhang Yanmin <yanmin.zhang@intel.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace/ftrace.c')
-rw-r--r--kernel/trace/ftrace.c25
1 files changed, 16 insertions, 9 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 23683b06b18c..eca592f977b2 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -5037,29 +5037,36 @@ void ftrace_module_init(struct module *mod)
5037 5037
5038 ftrace_process_locs(mod, mod->ftrace_callsites, 5038 ftrace_process_locs(mod, mod->ftrace_callsites,
5039 mod->ftrace_callsites + mod->num_ftrace_callsites); 5039 mod->ftrace_callsites + mod->num_ftrace_callsites);
5040 ftrace_module_enable(mod);
5041} 5040}
5042 5041
5043static int ftrace_module_notify_exit(struct notifier_block *self, 5042static int ftrace_module_notify(struct notifier_block *self,
5044 unsigned long val, void *data) 5043 unsigned long val, void *data)
5045{ 5044{
5046 struct module *mod = data; 5045 struct module *mod = data;
5047 5046
5048 if (val == MODULE_STATE_GOING) 5047 switch (val) {
5048 case MODULE_STATE_COMING:
5049 ftrace_module_enable(mod);
5050 break;
5051 case MODULE_STATE_GOING:
5049 ftrace_release_mod(mod); 5052 ftrace_release_mod(mod);
5053 break;
5054 default:
5055 break;
5056 }
5050 5057
5051 return 0; 5058 return 0;
5052} 5059}
5053#else 5060#else
5054static int ftrace_module_notify_exit(struct notifier_block *self, 5061static int ftrace_module_notify(struct notifier_block *self,
5055 unsigned long val, void *data) 5062 unsigned long val, void *data)
5056{ 5063{
5057 return 0; 5064 return 0;
5058} 5065}
5059#endif /* CONFIG_MODULES */ 5066#endif /* CONFIG_MODULES */
5060 5067
5061struct notifier_block ftrace_module_exit_nb = { 5068struct notifier_block ftrace_module_nb = {
5062 .notifier_call = ftrace_module_notify_exit, 5069 .notifier_call = ftrace_module_notify,
5063 .priority = INT_MIN, /* Run after anything that can remove kprobes */ 5070 .priority = INT_MIN, /* Run after anything that can remove kprobes */
5064}; 5071};
5065 5072
@@ -5091,7 +5098,7 @@ void __init ftrace_init(void)
5091 __start_mcount_loc, 5098 __start_mcount_loc,
5092 __stop_mcount_loc); 5099 __stop_mcount_loc);
5093 5100
5094 ret = register_module_notifier(&ftrace_module_exit_nb); 5101 ret = register_module_notifier(&ftrace_module_nb);
5095 if (ret) 5102 if (ret)
5096 pr_warning("Failed to register trace ftrace module exit notifier\n"); 5103 pr_warning("Failed to register trace ftrace module exit notifier\n");
5097 5104