diff options
Diffstat (limited to 'kernel/trace/ftrace.c')
-rw-r--r-- | kernel/trace/ftrace.c | 48 |
1 files changed, 33 insertions, 15 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index f88ea18d2d9..86fd4170d24 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
@@ -3432,35 +3432,49 @@ static void ftrace_init_module(struct module *mod, | |||
3432 | ftrace_process_locs(mod, start, end); | 3432 | ftrace_process_locs(mod, start, end); |
3433 | } | 3433 | } |
3434 | 3434 | ||
3435 | static int ftrace_module_notify(struct notifier_block *self, | 3435 | static int ftrace_module_notify_enter(struct notifier_block *self, |
3436 | unsigned long val, void *data) | 3436 | unsigned long val, void *data) |
3437 | { | 3437 | { |
3438 | struct module *mod = data; | 3438 | struct module *mod = data; |
3439 | 3439 | ||
3440 | switch (val) { | 3440 | if (val == MODULE_STATE_COMING) |
3441 | case MODULE_STATE_COMING: | ||
3442 | ftrace_init_module(mod, mod->ftrace_callsites, | 3441 | ftrace_init_module(mod, mod->ftrace_callsites, |
3443 | mod->ftrace_callsites + | 3442 | mod->ftrace_callsites + |
3444 | mod->num_ftrace_callsites); | 3443 | mod->num_ftrace_callsites); |
3445 | break; | 3444 | return 0; |
3446 | case MODULE_STATE_GOING: | 3445 | } |
3446 | |||
3447 | static int ftrace_module_notify_exit(struct notifier_block *self, | ||
3448 | unsigned long val, void *data) | ||
3449 | { | ||
3450 | struct module *mod = data; | ||
3451 | |||
3452 | if (val == MODULE_STATE_GOING) | ||
3447 | ftrace_release_mod(mod); | 3453 | ftrace_release_mod(mod); |
3448 | break; | ||
3449 | } | ||
3450 | 3454 | ||
3451 | return 0; | 3455 | return 0; |
3452 | } | 3456 | } |
3453 | #else | 3457 | #else |
3454 | static int ftrace_module_notify(struct notifier_block *self, | 3458 | static int ftrace_module_notify_enter(struct notifier_block *self, |
3455 | unsigned long val, void *data) | 3459 | unsigned long val, void *data) |
3460 | { | ||
3461 | return 0; | ||
3462 | } | ||
3463 | static int ftrace_module_notify_exit(struct notifier_block *self, | ||
3464 | unsigned long val, void *data) | ||
3456 | { | 3465 | { |
3457 | return 0; | 3466 | return 0; |
3458 | } | 3467 | } |
3459 | #endif /* CONFIG_MODULES */ | 3468 | #endif /* CONFIG_MODULES */ |
3460 | 3469 | ||
3461 | struct notifier_block ftrace_module_nb = { | 3470 | struct notifier_block ftrace_module_enter_nb = { |
3462 | .notifier_call = ftrace_module_notify, | 3471 | .notifier_call = ftrace_module_notify_enter, |
3463 | .priority = 0, | 3472 | .priority = INT_MAX, /* Run before anything that can use kprobes */ |
3473 | }; | ||
3474 | |||
3475 | struct notifier_block ftrace_module_exit_nb = { | ||
3476 | .notifier_call = ftrace_module_notify_exit, | ||
3477 | .priority = INT_MIN, /* Run after anything that can remove kprobes */ | ||
3464 | }; | 3478 | }; |
3465 | 3479 | ||
3466 | extern unsigned long __start_mcount_loc[]; | 3480 | extern unsigned long __start_mcount_loc[]; |
@@ -3494,9 +3508,13 @@ void __init ftrace_init(void) | |||
3494 | __start_mcount_loc, | 3508 | __start_mcount_loc, |
3495 | __stop_mcount_loc); | 3509 | __stop_mcount_loc); |
3496 | 3510 | ||
3497 | ret = register_module_notifier(&ftrace_module_nb); | 3511 | ret = register_module_notifier(&ftrace_module_enter_nb); |
3512 | if (ret) | ||
3513 | pr_warning("Failed to register trace ftrace module enter notifier\n"); | ||
3514 | |||
3515 | ret = register_module_notifier(&ftrace_module_exit_nb); | ||
3498 | if (ret) | 3516 | if (ret) |
3499 | pr_warning("Failed to register trace ftrace module notifier\n"); | 3517 | pr_warning("Failed to register trace ftrace module exit notifier\n"); |
3500 | 3518 | ||
3501 | set_ftrace_early_filters(); | 3519 | set_ftrace_early_filters(); |
3502 | 3520 | ||