Commit bc0f51d3 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull more tracing updates from Steven Rostedt:
 "A few more minor updates:

   - Show the tgid mappings for user space trace tools to use

   - Fix and optimize the comm and tgid cache recording

   - Sanitize derived kprobe names

   - Ftrace selftest updates

   - trace file header fix

   - Update of Documentation/trace/ftrace.txt

   - Compiler warning fixes

   - Fix possible uninitialized variable"

* tag 'trace-v4.13-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace:
  ftrace: Fix uninitialized variable in match_records()
  ftrace: Remove an unneeded NULL check
  ftrace: Hide cached module code for !CONFIG_MODULES
  tracing: Do note expose stack_trace_filter without DYNAMIC_FTRACE
  tracing: Update Documentation/trace/ftrace.txt
  tracing: Fixup trace file header alignment
  selftests/ftrace: Add a testcase for kprobe event naming
  selftests/ftrace: Add a test to probe module functions
  selftests/ftrace: Update multiple kprobes test for powerpc
  trace/kprobes: Sanitize derived event names
  tracing: Attempt to record other information even if some fail
  tracing: Treat recording tgid for idle task as a success
  tracing: Treat recording comm for idle task as a success
  tracing: Add saved_tgids file to show cached pid to tgid mappings
parents ad51271a 2e028c4f
This diff is collapsed.
...@@ -3816,7 +3816,7 @@ match_records(struct ftrace_hash *hash, char *func, int len, char *mod) ...@@ -3816,7 +3816,7 @@ match_records(struct ftrace_hash *hash, char *func, int len, char *mod)
int exclude_mod = 0; int exclude_mod = 0;
int found = 0; int found = 0;
int ret; int ret;
int clear_filter; int clear_filter = 0;
if (func) { if (func) {
func_g.type = filter_parse_regex(func, len, &func_g.search, func_g.type = filter_parse_regex(func, len, &func_g.search,
...@@ -3950,7 +3950,7 @@ static int cache_mod(struct trace_array *tr, ...@@ -3950,7 +3950,7 @@ static int cache_mod(struct trace_array *tr,
continue; continue;
/* no func matches all */ /* no func matches all */
if (!func || strcmp(func, "*") == 0 || if (strcmp(func, "*") == 0 ||
(ftrace_mod->func && (ftrace_mod->func &&
strcmp(ftrace_mod->func, func) == 0)) { strcmp(ftrace_mod->func, func) == 0)) {
ret = 0; ret = 0;
...@@ -3978,6 +3978,7 @@ static int ...@@ -3978,6 +3978,7 @@ static int
ftrace_set_regex(struct ftrace_ops *ops, unsigned char *buf, int len, ftrace_set_regex(struct ftrace_ops *ops, unsigned char *buf, int len,
int reset, int enable); int reset, int enable);
#ifdef CONFIG_MODULES
static void process_mod_list(struct list_head *head, struct ftrace_ops *ops, static void process_mod_list(struct list_head *head, struct ftrace_ops *ops,
char *mod, bool enable) char *mod, bool enable)
{ {
...@@ -4068,6 +4069,7 @@ static void process_cached_mods(const char *mod_name) ...@@ -4068,6 +4069,7 @@ static void process_cached_mods(const char *mod_name)
kfree(mod); kfree(mod);
} }
#endif
/* /*
* We register the module command as a template to show others how * We register the module command as a template to show others how
......
...@@ -1916,7 +1916,11 @@ static int trace_save_cmdline(struct task_struct *tsk) ...@@ -1916,7 +1916,11 @@ static int trace_save_cmdline(struct task_struct *tsk)
{ {
unsigned pid, idx; unsigned pid, idx;
if (!tsk->pid || unlikely(tsk->pid > PID_MAX_DEFAULT)) /* treat recording of idle task as a success */
if (!tsk->pid)
return 1;
if (unlikely(tsk->pid > PID_MAX_DEFAULT))
return 0; return 0;
/* /*
...@@ -2002,7 +2006,11 @@ int trace_find_tgid(int pid) ...@@ -2002,7 +2006,11 @@ int trace_find_tgid(int pid)
static int trace_save_tgid(struct task_struct *tsk) static int trace_save_tgid(struct task_struct *tsk)
{ {
if (unlikely(!tgid_map || !tsk->pid || tsk->pid > PID_MAX_DEFAULT)) /* treat recording of idle task as a success */
if (!tsk->pid)
return 1;
if (unlikely(!tgid_map || tsk->pid > PID_MAX_DEFAULT))
return 0; return 0;
tgid_map[tsk->pid] = tsk->tgid; tgid_map[tsk->pid] = tsk->tgid;
...@@ -2029,11 +2037,20 @@ static bool tracing_record_taskinfo_skip(int flags) ...@@ -2029,11 +2037,20 @@ static bool tracing_record_taskinfo_skip(int flags)
*/ */
void tracing_record_taskinfo(struct task_struct *task, int flags) void tracing_record_taskinfo(struct task_struct *task, int flags)
{ {
bool done;
if (tracing_record_taskinfo_skip(flags)) if (tracing_record_taskinfo_skip(flags))
return; return;
if ((flags & TRACE_RECORD_CMDLINE) && !trace_save_cmdline(task))
return; /*
if ((flags & TRACE_RECORD_TGID) && !trace_save_tgid(task)) * Record as much task information as possible. If some fail, continue
* to try to record the others.
*/
done = !(flags & TRACE_RECORD_CMDLINE) || trace_save_cmdline(task);
done &= !(flags & TRACE_RECORD_TGID) || trace_save_tgid(task);
/* If recording any information failed, retry again soon. */
if (!done)
return; return;
__this_cpu_write(trace_taskinfo_save, false); __this_cpu_write(trace_taskinfo_save, false);
...@@ -2050,15 +2067,22 @@ void tracing_record_taskinfo(struct task_struct *task, int flags) ...@@ -2050,15 +2067,22 @@ void tracing_record_taskinfo(struct task_struct *task, int flags)
void tracing_record_taskinfo_sched_switch(struct task_struct *prev, void tracing_record_taskinfo_sched_switch(struct task_struct *prev,
struct task_struct *next, int flags) struct task_struct *next, int flags)
{ {
bool done;
if (tracing_record_taskinfo_skip(flags)) if (tracing_record_taskinfo_skip(flags))
return; return;
if ((flags & TRACE_RECORD_CMDLINE) && /*
(!trace_save_cmdline(prev) || !trace_save_cmdline(next))) * Record as much task information as possible. If some fail, continue
return; * to try to record the others.
*/
done = !(flags & TRACE_RECORD_CMDLINE) || trace_save_cmdline(prev);
done &= !(flags & TRACE_RECORD_CMDLINE) || trace_save_cmdline(next);
done &= !(flags & TRACE_RECORD_TGID) || trace_save_tgid(prev);
done &= !(flags & TRACE_RECORD_TGID) || trace_save_tgid(next);
if ((flags & TRACE_RECORD_TGID) && /* If recording any information failed, retry again soon. */
(!trace_save_tgid(prev) || !trace_save_tgid(next))) if (!done)
return; return;
__this_cpu_write(trace_taskinfo_save, false); __this_cpu_write(trace_taskinfo_save, false);
...@@ -3334,14 +3358,23 @@ static void print_func_help_header_irq(struct trace_buffer *buf, struct seq_file ...@@ -3334,14 +3358,23 @@ static void print_func_help_header_irq(struct trace_buffer *buf, struct seq_file
unsigned int flags) unsigned int flags)
{ {
bool tgid = flags & TRACE_ITER_RECORD_TGID; bool tgid = flags & TRACE_ITER_RECORD_TGID;
const char tgid_space[] = " ";
seq_printf(m, "# %s _-----=> irqs-off\n", tgid ? " " : ""); const char space[] = " ";
seq_printf(m, "# %s / _----=> need-resched\n", tgid ? " " : "");
seq_printf(m, "# %s| / _---=> hardirq/softirq\n", tgid ? " " : ""); seq_printf(m, "# %s _-----=> irqs-off\n",
seq_printf(m, "# %s|| / _--=> preempt-depth\n", tgid ? " " : ""); tgid ? tgid_space : space);
seq_printf(m, "# %s||| / delay\n", tgid ? " " : ""); seq_printf(m, "# %s / _----=> need-resched\n",
seq_printf(m, "# TASK-PID CPU#%s|||| TIMESTAMP FUNCTION\n", tgid ? " TGID " : ""); tgid ? tgid_space : space);
seq_printf(m, "# | | | %s|||| | |\n", tgid ? " | " : ""); seq_printf(m, "# %s| / _---=> hardirq/softirq\n",
tgid ? tgid_space : space);
seq_printf(m, "# %s|| / _--=> preempt-depth\n",
tgid ? tgid_space : space);
seq_printf(m, "# %s||| / delay\n",
tgid ? tgid_space : space);
seq_printf(m, "# TASK-PID CPU#%s|||| TIMESTAMP FUNCTION\n",
tgid ? " TGID " : space);
seq_printf(m, "# | | | %s|||| | |\n",
tgid ? " | " : space);
} }
void void
...@@ -4689,6 +4722,76 @@ static const struct file_operations tracing_readme_fops = { ...@@ -4689,6 +4722,76 @@ static const struct file_operations tracing_readme_fops = {
.llseek = generic_file_llseek, .llseek = generic_file_llseek,
}; };
static void *saved_tgids_next(struct seq_file *m, void *v, loff_t *pos)
{
int *ptr = v;
if (*pos || m->count)
ptr++;
(*pos)++;
for (; ptr <= &tgid_map[PID_MAX_DEFAULT]; ptr++) {
if (trace_find_tgid(*ptr))
return ptr;
}
return NULL;
}
static void *saved_tgids_start(struct seq_file *m, loff_t *pos)
{
void *v;
loff_t l = 0;
if (!tgid_map)
return NULL;
v = &tgid_map[0];
while (l <= *pos) {
v = saved_tgids_next(m, v, &l);
if (!v)
return NULL;
}
return v;
}
static void saved_tgids_stop(struct seq_file *m, void *v)
{
}
static int saved_tgids_show(struct seq_file *m, void *v)
{
int pid = (int *)v - tgid_map;
seq_printf(m, "%d %d\n", pid, trace_find_tgid(pid));
return 0;
}
static const struct seq_operations tracing_saved_tgids_seq_ops = {
.start = saved_tgids_start,
.stop = saved_tgids_stop,
.next = saved_tgids_next,
.show = saved_tgids_show,
};
static int tracing_saved_tgids_open(struct inode *inode, struct file *filp)
{
if (tracing_disabled)
return -ENODEV;
return seq_open(filp, &tracing_saved_tgids_seq_ops);
}
static const struct file_operations tracing_saved_tgids_fops = {
.open = tracing_saved_tgids_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
static void *saved_cmdlines_next(struct seq_file *m, void *v, loff_t *pos) static void *saved_cmdlines_next(struct seq_file *m, void *v, loff_t *pos)
{ {
unsigned int *ptr = v; unsigned int *ptr = v;
...@@ -7921,6 +8024,9 @@ static __init int tracer_init_tracefs(void) ...@@ -7921,6 +8024,9 @@ static __init int tracer_init_tracefs(void)
trace_create_file("saved_cmdlines_size", 0644, d_tracer, trace_create_file("saved_cmdlines_size", 0644, d_tracer,
NULL, &tracing_saved_cmdlines_size_fops); NULL, &tracing_saved_cmdlines_size_fops);
trace_create_file("saved_tgids", 0444, d_tracer,
NULL, &tracing_saved_tgids_fops);
trace_eval_init(); trace_eval_init();
trace_create_eval_file(d_tracer); trace_create_eval_file(d_tracer);
......
...@@ -598,6 +598,14 @@ static struct notifier_block trace_kprobe_module_nb = { ...@@ -598,6 +598,14 @@ static struct notifier_block trace_kprobe_module_nb = {
.priority = 1 /* Invoked after kprobe module callback */ .priority = 1 /* Invoked after kprobe module callback */
}; };
/* Convert certain expected symbols into '_' when generating event names */
static inline void sanitize_event_name(char *name)
{
while (*name++ != '\0')
if (*name == ':' || *name == '.')
*name = '_';
}
static int create_trace_kprobe(int argc, char **argv) static int create_trace_kprobe(int argc, char **argv)
{ {
/* /*
...@@ -736,6 +744,7 @@ static int create_trace_kprobe(int argc, char **argv) ...@@ -736,6 +744,7 @@ static int create_trace_kprobe(int argc, char **argv)
else else
snprintf(buf, MAX_EVENT_NAME_LEN, "%c_0x%p", snprintf(buf, MAX_EVENT_NAME_LEN, "%c_0x%p",
is_return ? 'r' : 'p', addr); is_return ? 'r' : 'p', addr);
sanitize_event_name(buf);
event = buf; event = buf;
} }
tk = alloc_trace_kprobe(group, event, addr, symbol, offset, maxactive, tk = alloc_trace_kprobe(group, event, addr, symbol, offset, maxactive,
......
...@@ -406,6 +406,8 @@ static const struct file_operations stack_trace_fops = { ...@@ -406,6 +406,8 @@ static const struct file_operations stack_trace_fops = {
.release = seq_release, .release = seq_release,
}; };
#ifdef CONFIG_DYNAMIC_FTRACE
static int static int
stack_trace_filter_open(struct inode *inode, struct file *file) stack_trace_filter_open(struct inode *inode, struct file *file)
{ {
...@@ -423,6 +425,8 @@ static const struct file_operations stack_trace_filter_fops = { ...@@ -423,6 +425,8 @@ static const struct file_operations stack_trace_filter_fops = {
.release = ftrace_regex_release, .release = ftrace_regex_release,
}; };
#endif /* CONFIG_DYNAMIC_FTRACE */
int int
stack_trace_sysctl(struct ctl_table *table, int write, stack_trace_sysctl(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, void __user *buffer, size_t *lenp,
...@@ -477,8 +481,10 @@ static __init int stack_trace_init(void) ...@@ -477,8 +481,10 @@ static __init int stack_trace_init(void)
trace_create_file("stack_trace", 0444, d_tracer, trace_create_file("stack_trace", 0444, d_tracer,
NULL, &stack_trace_fops); NULL, &stack_trace_fops);
#ifdef CONFIG_DYNAMIC_FTRACE
trace_create_file("stack_trace_filter", 0444, d_tracer, trace_create_file("stack_trace_filter", 0444, d_tracer,
&trace_ops, &stack_trace_filter_fops); &trace_ops, &stack_trace_filter_fops);
#endif
if (stack_trace_filter_buf[0]) if (stack_trace_filter_buf[0])
ftrace_set_early_filter(&trace_ops, stack_trace_filter_buf, 1); ftrace_set_early_filter(&trace_ops, stack_trace_filter_buf, 1);
......
#!/bin/sh
# description: Kprobe event auto/manual naming
[ -f kprobe_events ] || exit_unsupported # this is configurable
disable_events
echo > kprobe_events
:;: "Add an event on function without name" ;:
FUNC=`grep " [tT] .*vfs_read$" /proc/kallsyms | tail -n 1 | cut -f 3 -d " "`
[ "x" != "x$FUNC" ] || exit_unresolved
echo "p $FUNC" > kprobe_events
PROBE_NAME=`echo $FUNC | tr ".:" "_"`
test -d events/kprobes/p_${PROBE_NAME}_0 || exit_failure
:;: "Add an event on function with new name" ;:
echo "p:event1 $FUNC" > kprobe_events
test -d events/kprobes/event1 || exit_failure
:;: "Add an event on function with new name and group" ;:
echo "p:kprobes2/event2 $FUNC" > kprobe_events
test -d events/kprobes2/event2 || exit_failure
:;: "Add an event on dot function without name" ;:
FUNC=`grep -m 10 " [tT] .*\.isra\..*$" /proc/kallsyms | tail -n 1 | cut -f 3 -d " "`
[ "x" != "x$FUNC" ] || exit_unresolved
echo "p $FUNC" > kprobe_events
EVENT=`grep $FUNC kprobe_events | cut -f 1 -d " " | cut -f 2 -d:`
[ "x" != "x$EVENT" ] || exit_failure
test -d events/$EVENT || exit_failure
echo > kprobe_events
#!/bin/sh
# description: Kprobe dynamic event - probing module
[ -f kprobe_events ] || exit_unsupported # this is configurable
disable_events
echo > kprobe_events
:;: "Add an event on a module function without specifying event name" ;:
MOD=`lsmod | head -n 2 | tail -n 1 | cut -f1 -d" "`
FUNC=`grep -m 1 ".* t .*\\[$MOD\\]" /proc/kallsyms | xargs | cut -f3 -d" "`
[ "x" != "x$MOD" -a "y" != "y$FUNC" ] || exit_unresolved
echo "p $MOD:$FUNC" > kprobe_events
PROBE_NAME=`echo $MOD:$FUNC | tr ".:" "_"`
test -d events/kprobes/p_${PROBE_NAME}_0 || exit_failure
:;: "Add an event on a module function with new event name" ;:
echo "p:event1 $MOD:$FUNC" > kprobe_events
test -d events/kprobes/event1 || exit_failure
:;: "Add an event on a module function with new event and group name" ;:
echo "p:kprobes1/event1 $MOD:$FUNC" > kprobe_events
test -d events/kprobes1/event1 || exit_failure
echo > kprobe_events
...@@ -2,10 +2,10 @@ ...@@ -2,10 +2,10 @@
# description: Register/unregister many kprobe events # description: Register/unregister many kprobe events
# ftrace fentry skip size depends on the machine architecture. # ftrace fentry skip size depends on the machine architecture.
# Currently HAVE_KPROBES_ON_FTRACE defined on x86 and powerpc # Currently HAVE_KPROBES_ON_FTRACE defined on x86 and powerpc64le
case `uname -m` in case `uname -m` in
x86_64|i[3456]86) OFFS=5;; x86_64|i[3456]86) OFFS=5;;
ppc*) OFFS=4;; ppc64le) OFFS=8;;
*) OFFS=0;; *) OFFS=0;;
esac esac
......
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