diff options
| author | Steven Rostedt <srostedt@redhat.com> | 2008-12-04 00:26:40 -0500 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2008-12-04 03:09:37 -0500 |
| commit | 978f3a45d9499c7a447ca7615455cefb63d44165 (patch) | |
| tree | 13a59046c8fe7ae3a095444515cd50c0a57727b3 /kernel/trace | |
| parent | 5ef6476190d24419a9a537baa0b5641845136989 (diff) | |
ftrace: use struct pid
Impact: clean up, extend PID filtering to PID namespaces
Eric Biederman suggested using the struct pid for filtering on
pids in the kernel. This patch is based off of a demonstration
of an implementation that Eric sent me in an email.
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/trace')
| -rw-r--r-- | kernel/trace/ftrace.c | 76 | ||||
| -rw-r--r-- | kernel/trace/trace.h | 4 |
2 files changed, 46 insertions, 34 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 57592a9dd630..10b1d7c1b1dd 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
| @@ -48,7 +48,7 @@ int ftrace_enabled __read_mostly; | |||
| 48 | static int last_ftrace_enabled; | 48 | static int last_ftrace_enabled; |
| 49 | 49 | ||
| 50 | /* set when tracing only a pid */ | 50 | /* set when tracing only a pid */ |
| 51 | int ftrace_pid_trace = -1; | 51 | struct pid *ftrace_pid_trace; |
| 52 | 52 | ||
| 53 | /* Quick disabling of function tracer. */ | 53 | /* Quick disabling of function tracer. */ |
| 54 | int function_trace_stop; | 54 | int function_trace_stop; |
| @@ -153,7 +153,7 @@ static int __register_ftrace_function(struct ftrace_ops *ops) | |||
| 153 | else | 153 | else |
| 154 | func = ftrace_list_func; | 154 | func = ftrace_list_func; |
| 155 | 155 | ||
| 156 | if (ftrace_pid_trace >= 0) { | 156 | if (ftrace_pid_trace) { |
| 157 | set_ftrace_pid_function(func); | 157 | set_ftrace_pid_function(func); |
| 158 | func = ftrace_pid_func; | 158 | func = ftrace_pid_func; |
| 159 | } | 159 | } |
| @@ -209,7 +209,7 @@ static int __unregister_ftrace_function(struct ftrace_ops *ops) | |||
| 209 | if (ftrace_list->next == &ftrace_list_end) { | 209 | if (ftrace_list->next == &ftrace_list_end) { |
| 210 | ftrace_func_t func = ftrace_list->func; | 210 | ftrace_func_t func = ftrace_list->func; |
| 211 | 211 | ||
| 212 | if (ftrace_pid_trace >= 0) { | 212 | if (ftrace_pid_trace) { |
| 213 | set_ftrace_pid_function(func); | 213 | set_ftrace_pid_function(func); |
| 214 | func = ftrace_pid_func; | 214 | func = ftrace_pid_func; |
| 215 | } | 215 | } |
| @@ -239,7 +239,7 @@ static void ftrace_update_pid_func(void) | |||
| 239 | 239 | ||
| 240 | func = ftrace_trace_function; | 240 | func = ftrace_trace_function; |
| 241 | 241 | ||
| 242 | if (ftrace_pid_trace >= 0) { | 242 | if (ftrace_pid_trace) { |
| 243 | set_ftrace_pid_function(func); | 243 | set_ftrace_pid_function(func); |
| 244 | func = ftrace_pid_func; | 244 | func = ftrace_pid_func; |
| 245 | } else { | 245 | } else { |
| @@ -1678,18 +1678,40 @@ ftrace_pid_read(struct file *file, char __user *ubuf, | |||
| 1678 | char buf[64]; | 1678 | char buf[64]; |
| 1679 | int r; | 1679 | int r; |
| 1680 | 1680 | ||
| 1681 | if (ftrace_pid_trace >= 0) | 1681 | if (ftrace_pid_trace) |
| 1682 | r = sprintf(buf, "%u\n", ftrace_pid_trace); | 1682 | r = sprintf(buf, "%u\n", pid_nr(ftrace_pid_trace)); |
| 1683 | else | 1683 | else |
| 1684 | r = sprintf(buf, "no pid\n"); | 1684 | r = sprintf(buf, "no pid\n"); |
| 1685 | 1685 | ||
| 1686 | return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); | 1686 | return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); |
| 1687 | } | 1687 | } |
| 1688 | 1688 | ||
| 1689 | static void clear_ftrace_pid_task(struct pid **pid) | ||
| 1690 | { | ||
| 1691 | struct task_struct *p; | ||
| 1692 | |||
| 1693 | do_each_pid_task(*pid, PIDTYPE_PID, p) { | ||
| 1694 | clear_tsk_trace_trace(p); | ||
| 1695 | } while_each_pid_task(*pid, PIDTYPE_PID, p); | ||
| 1696 | put_pid(*pid); | ||
| 1697 | |||
| 1698 | *pid = NULL; | ||
| 1699 | } | ||
| 1700 | |||
| 1701 | static void set_ftrace_pid_task(struct pid *pid) | ||
| 1702 | { | ||
| 1703 | struct task_struct *p; | ||
| 1704 | |||
| 1705 | do_each_pid_task(pid, PIDTYPE_PID, p) { | ||
| 1706 | set_tsk_trace_trace(p); | ||
| 1707 | } while_each_pid_task(pid, PIDTYPE_PID, p); | ||
| 1708 | } | ||
| 1709 | |||
| 1689 | static ssize_t | 1710 | static ssize_t |
| 1690 | ftrace_pid_write(struct file *filp, const char __user *ubuf, | 1711 | ftrace_pid_write(struct file *filp, const char __user *ubuf, |
| 1691 | size_t cnt, loff_t *ppos) | 1712 | size_t cnt, loff_t *ppos) |
| 1692 | { | 1713 | { |
| 1714 | struct pid *pid; | ||
| 1693 | char buf[64]; | 1715 | char buf[64]; |
| 1694 | long val; | 1716 | long val; |
| 1695 | int ret; | 1717 | int ret; |
| @@ -1707,40 +1729,30 @@ ftrace_pid_write(struct file *filp, const char __user *ubuf, | |||
| 1707 | return ret; | 1729 | return ret; |
| 1708 | 1730 | ||
| 1709 | mutex_lock(&ftrace_start_lock); | 1731 | mutex_lock(&ftrace_start_lock); |
| 1710 | if (ret < 0) { | 1732 | if (val < 0) { |
| 1711 | /* disable pid tracing */ | 1733 | /* disable pid tracing */ |
| 1712 | if (ftrace_pid_trace < 0) | 1734 | if (!ftrace_pid_trace) |
| 1713 | goto out; | 1735 | goto out; |
| 1714 | ftrace_pid_trace = -1; | 1736 | |
| 1737 | clear_ftrace_pid_task(&ftrace_pid_trace); | ||
| 1715 | 1738 | ||
| 1716 | } else { | 1739 | } else { |
| 1717 | struct task_struct *p; | 1740 | pid = find_get_pid(val); |
| 1718 | int found = 0; | ||
| 1719 | 1741 | ||
| 1720 | if (ftrace_pid_trace == val) | 1742 | if (pid == ftrace_pid_trace) { |
| 1743 | put_pid(pid); | ||
| 1721 | goto out; | 1744 | goto out; |
| 1722 | |||
| 1723 | /* | ||
| 1724 | * Find the task that matches this pid. | ||
| 1725 | * TODO: use pid namespaces instead. | ||
| 1726 | */ | ||
| 1727 | rcu_read_lock(); | ||
| 1728 | for_each_process(p) { | ||
| 1729 | if (p->pid == val) { | ||
| 1730 | found = 1; | ||
| 1731 | set_tsk_trace_trace(p); | ||
| 1732 | } else if (test_tsk_trace_trace(p)) | ||
| 1733 | clear_tsk_trace_trace(p); | ||
| 1734 | } | 1745 | } |
| 1735 | rcu_read_unlock(); | ||
| 1736 | 1746 | ||
| 1737 | if (found) | 1747 | if (ftrace_pid_trace) |
| 1738 | ftrace_pid_trace = val; | 1748 | clear_ftrace_pid_task(&ftrace_pid_trace); |
| 1739 | else { | 1749 | |
| 1740 | if (ftrace_pid_trace < 0) | 1750 | if (!pid) |
| 1741 | goto out; | 1751 | goto out; |
| 1742 | ftrace_pid_trace = -1; | 1752 | |
| 1743 | } | 1753 | ftrace_pid_trace = pid; |
| 1754 | |||
| 1755 | set_ftrace_pid_task(ftrace_pid_trace); | ||
| 1744 | } | 1756 | } |
| 1745 | 1757 | ||
| 1746 | /* update the function call */ | 1758 | /* update the function call */ |
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 95fff37ed970..8b81b4d727bd 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
| @@ -541,11 +541,11 @@ print_graph_function(struct trace_iterator *iter) | |||
| 541 | } | 541 | } |
| 542 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ | 542 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ |
| 543 | 543 | ||
| 544 | extern int ftrace_pid_trace; | 544 | extern struct pid *ftrace_pid_trace; |
| 545 | 545 | ||
| 546 | static inline int ftrace_trace_task(struct task_struct *task) | 546 | static inline int ftrace_trace_task(struct task_struct *task) |
| 547 | { | 547 | { |
| 548 | if (ftrace_pid_trace < 0) | 548 | if (ftrace_pid_trace) |
| 549 | return 1; | 549 | return 1; |
| 550 | 550 | ||
| 551 | return test_tsk_trace_trace(task); | 551 | return test_tsk_trace_trace(task); |
