Commit 56f410cf authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'trace-v4.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace

Pull tracing fixes from Steven Rostedt:

 - Fix a bug caused by not cleaning up the new instance unique triggers
   when deleting an instance. It also creates a selftest that triggers
   that bug.

 - Fix the delayed optimization happening after kprobes boot up self
   tests being removed by freeing of init memory.

 - Comment kprobes on why the delay optimization is not a problem for
   removal of modules, to keep other developers from searching that
   riddle.

 - Fix another case of rcu not watching in stack trace tracing.

* tag 'trace-v4.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace:
  tracing: Make sure RCU is watching before calling a stack trace
  kprobes: Document how optimized kprobes are removed from module unload
  selftests/ftrace: Add test to remove instance with active event triggers
  selftests/ftrace: Fix bashisms
  ftrace: Remove #ifdef from code and add clear_ftrace_function_probes() stub
  ftrace/instances: Clear function triggers when removing instances
  ftrace: Simplify glob handling in unregister_ftrace_function_probe_func()
  tracing/kprobes: Enforce kprobes teardown after testing
  tracing: Move postpone selftests to core from early_initcall
parents 894e2164 a33d7d94
...@@ -349,6 +349,9 @@ extern int proc_kprobes_optimization_handler(struct ctl_table *table, ...@@ -349,6 +349,9 @@ extern int proc_kprobes_optimization_handler(struct ctl_table *table,
int write, void __user *buffer, int write, void __user *buffer,
size_t *length, loff_t *ppos); size_t *length, loff_t *ppos);
#endif #endif
extern void wait_for_kprobe_optimizer(void);
#else
static inline void wait_for_kprobe_optimizer(void) { }
#endif /* CONFIG_OPTPROBES */ #endif /* CONFIG_OPTPROBES */
#ifdef CONFIG_KPROBES_ON_FTRACE #ifdef CONFIG_KPROBES_ON_FTRACE
extern void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip, extern void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
......
...@@ -595,7 +595,7 @@ static void kprobe_optimizer(struct work_struct *work) ...@@ -595,7 +595,7 @@ static void kprobe_optimizer(struct work_struct *work)
} }
/* Wait for completing optimization and unoptimization */ /* Wait for completing optimization and unoptimization */
static void wait_for_kprobe_optimizer(void) void wait_for_kprobe_optimizer(void)
{ {
mutex_lock(&kprobe_mutex); mutex_lock(&kprobe_mutex);
...@@ -2183,6 +2183,12 @@ static int kprobes_module_callback(struct notifier_block *nb, ...@@ -2183,6 +2183,12 @@ static int kprobes_module_callback(struct notifier_block *nb,
* The vaddr this probe is installed will soon * The vaddr this probe is installed will soon
* be vfreed buy not synced to disk. Hence, * be vfreed buy not synced to disk. Hence,
* disarming the breakpoint isn't needed. * disarming the breakpoint isn't needed.
*
* Note, this will also move any optimized probes
* that are pending to be removed from their
* corresponding lists to the freeing_list and
* will not be touched by the delayed
* kprobe_optimizer work handler.
*/ */
kill_kprobe(p); kill_kprobe(p);
} }
......
...@@ -4144,9 +4144,9 @@ unregister_ftrace_function_probe_func(char *glob, struct trace_array *tr, ...@@ -4144,9 +4144,9 @@ unregister_ftrace_function_probe_func(char *glob, struct trace_array *tr,
int i, ret = -ENODEV; int i, ret = -ENODEV;
int size; int size;
if (glob && (strcmp(glob, "*") == 0 || !strlen(glob))) if (!glob || !strlen(glob) || !strcmp(glob, "*"))
func_g.search = NULL; func_g.search = NULL;
else if (glob) { else {
int not; int not;
func_g.type = filter_parse_regex(glob, strlen(glob), func_g.type = filter_parse_regex(glob, strlen(glob),
...@@ -4256,6 +4256,14 @@ unregister_ftrace_function_probe_func(char *glob, struct trace_array *tr, ...@@ -4256,6 +4256,14 @@ unregister_ftrace_function_probe_func(char *glob, struct trace_array *tr,
return ret; return ret;
} }
void clear_ftrace_function_probes(struct trace_array *tr)
{
struct ftrace_func_probe *probe, *n;
list_for_each_entry_safe(probe, n, &tr->func_probes, list)
unregister_ftrace_function_probe_func(NULL, tr, probe->probe_ops);
}
static LIST_HEAD(ftrace_commands); static LIST_HEAD(ftrace_commands);
static DEFINE_MUTEX(ftrace_cmd_mutex); static DEFINE_MUTEX(ftrace_cmd_mutex);
......
...@@ -1558,7 +1558,7 @@ static __init int init_trace_selftests(void) ...@@ -1558,7 +1558,7 @@ static __init int init_trace_selftests(void)
return 0; return 0;
} }
early_initcall(init_trace_selftests); core_initcall(init_trace_selftests);
#else #else
static inline int run_tracer_selftest(struct tracer *type) static inline int run_tracer_selftest(struct tracer *type)
{ {
...@@ -2568,7 +2568,36 @@ static inline void ftrace_trace_stack(struct trace_array *tr, ...@@ -2568,7 +2568,36 @@ static inline void ftrace_trace_stack(struct trace_array *tr,
void __trace_stack(struct trace_array *tr, unsigned long flags, int skip, void __trace_stack(struct trace_array *tr, unsigned long flags, int skip,
int pc) int pc)
{ {
__ftrace_trace_stack(tr->trace_buffer.buffer, flags, skip, pc, NULL); struct ring_buffer *buffer = tr->trace_buffer.buffer;
if (rcu_is_watching()) {
__ftrace_trace_stack(buffer, flags, skip, pc, NULL);
return;
}
/*
* When an NMI triggers, RCU is enabled via rcu_nmi_enter(),
* but if the above rcu_is_watching() failed, then the NMI
* triggered someplace critical, and rcu_irq_enter() should
* not be called from NMI.
*/
if (unlikely(in_nmi()))
return;
/*
* It is possible that a function is being traced in a
* location that RCU is not watching. A call to
* rcu_irq_enter() will make sure that it is, but there's
* a few internal rcu functions that could be traced
* where that wont work either. In those cases, we just
* do nothing.
*/
if (unlikely(rcu_irq_enter_disabled()))
return;
rcu_irq_enter_irqson();
__ftrace_trace_stack(buffer, flags, skip, pc, NULL);
rcu_irq_exit_irqson();
} }
/** /**
...@@ -7550,6 +7579,7 @@ static int instance_rmdir(const char *name) ...@@ -7550,6 +7579,7 @@ static int instance_rmdir(const char *name)
} }
tracing_set_nop(tr); tracing_set_nop(tr);
clear_ftrace_function_probes(tr);
event_trace_del_tracer(tr); event_trace_del_tracer(tr);
ftrace_clear_pids(tr); ftrace_clear_pids(tr);
ftrace_destroy_function_files(tr); ftrace_destroy_function_files(tr);
......
...@@ -980,6 +980,7 @@ register_ftrace_function_probe(char *glob, struct trace_array *tr, ...@@ -980,6 +980,7 @@ register_ftrace_function_probe(char *glob, struct trace_array *tr,
extern int extern int
unregister_ftrace_function_probe_func(char *glob, struct trace_array *tr, unregister_ftrace_function_probe_func(char *glob, struct trace_array *tr,
struct ftrace_probe_ops *ops); struct ftrace_probe_ops *ops);
extern void clear_ftrace_function_probes(struct trace_array *tr);
int register_ftrace_command(struct ftrace_func_command *cmd); int register_ftrace_command(struct ftrace_func_command *cmd);
int unregister_ftrace_command(struct ftrace_func_command *cmd); int unregister_ftrace_command(struct ftrace_func_command *cmd);
...@@ -998,6 +999,10 @@ static inline __init int unregister_ftrace_command(char *cmd_name) ...@@ -998,6 +999,10 @@ static inline __init int unregister_ftrace_command(char *cmd_name)
{ {
return -EINVAL; return -EINVAL;
} }
static inline void clear_ftrace_function_probes(struct trace_array *tr)
{
}
/* /*
* The ops parameter passed in is usually undefined. * The ops parameter passed in is usually undefined.
* This must be a macro. * This must be a macro.
......
...@@ -1535,6 +1535,11 @@ static __init int kprobe_trace_self_tests_init(void) ...@@ -1535,6 +1535,11 @@ static __init int kprobe_trace_self_tests_init(void)
end: end:
release_all_trace_kprobes(); release_all_trace_kprobes();
/*
* Wait for the optimizer work to finish. Otherwise it might fiddle
* with probes in already freed __init text.
*/
wait_for_kprobe_optimizer();
if (warn) if (warn)
pr_cont("NG: Some tests are failed. Please check them.\n"); pr_cont("NG: Some tests are failed. Please check them.\n");
else else
......
...@@ -58,7 +58,7 @@ parse_opts() { # opts ...@@ -58,7 +58,7 @@ parse_opts() { # opts
;; ;;
--verbose|-v|-vv) --verbose|-v|-vv)
VERBOSE=$((VERBOSE + 1)) VERBOSE=$((VERBOSE + 1))
[ $1 == '-vv' ] && VERBOSE=$((VERBOSE + 1)) [ $1 = '-vv' ] && VERBOSE=$((VERBOSE + 1))
shift 1 shift 1
;; ;;
--debug|-d) --debug|-d)
......
...@@ -48,7 +48,7 @@ test_event_enabled() { ...@@ -48,7 +48,7 @@ test_event_enabled() {
e=`cat $EVENT_ENABLE` e=`cat $EVENT_ENABLE`
if [ "$e" != $val ]; then if [ "$e" != $val ]; then
echo "Expected $val but found $e" echo "Expected $val but found $e"
exit -1 exit 1
fi fi
} }
......
...@@ -34,10 +34,10 @@ reset_ftrace_filter() { # reset all triggers in set_ftrace_filter ...@@ -34,10 +34,10 @@ reset_ftrace_filter() { # reset all triggers in set_ftrace_filter
echo > set_ftrace_filter echo > set_ftrace_filter
grep -v '^#' set_ftrace_filter | while read t; do grep -v '^#' set_ftrace_filter | while read t; do
tr=`echo $t | cut -d: -f2` tr=`echo $t | cut -d: -f2`
if [ "$tr" == "" ]; then if [ "$tr" = "" ]; then
continue continue
fi fi
if [ $tr == "enable_event" -o $tr == "disable_event" ]; then if [ $tr = "enable_event" -o $tr = "disable_event" ]; then
tr=`echo $t | cut -d: -f1-4` tr=`echo $t | cut -d: -f1-4`
limit=`echo $t | cut -d: -f5` limit=`echo $t | cut -d: -f5`
else else
......
...@@ -75,9 +75,13 @@ rmdir foo ...@@ -75,9 +75,13 @@ rmdir foo
if [ -d foo ]; then if [ -d foo ]; then
fail "foo still exists" fail "foo still exists"
fi fi
exit 0
mkdir foo
echo "schedule:enable_event:sched:sched_switch" > foo/set_ftrace_filter
rmdir foo
if [ -d foo ]; then
fail "foo still exists"
fi
instance_slam() { instance_slam() {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment