diff options
Diffstat (limited to 'kernel/trace/ftrace.c')
-rw-r--r-- | kernel/trace/ftrace.c | 76 |
1 files changed, 44 insertions, 32 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 */ |