aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/ftrace.c
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2009-02-16 15:28:00 -0500
committerSteven Rostedt <srostedt@redhat.com>2009-02-16 22:50:06 -0500
commit8fc0c701c5b6c0c3e242758c3acef6f9047940a9 (patch)
treeaa9c495fc2d898b39873e1ce9f154bed64b33f8e /kernel/trace/ftrace.c
parent23b4ff3aa479c9e3bb23cb6b2d0a97878399784a (diff)
ftrace: show selected functions in set_ftrace_filter
This patch adds output to show what functions have tracer hooks attached to them. # echo 'sys_open:traceon:4' > /debug/tracing/set_ftrace_filter # cat set_ftrace_filter #### all functions enabled #### sys_open:ftrace_traceon:0000000000000004 # echo 'do_fork:traceoff:' > set_ftrace_filter # cat set_ftrace_filter #### all functions enabled #### sys_open:ftrace_traceon:0000000000000002 do_fork:ftrace_traceoff:ffffffffffffffff Note the 4 changed to a 2. This is because The code was executed twice since the traceoff was added. If a cat is done again: #### all functions enabled #### sys_open:ftrace_traceon do_fork:ftrace_traceoff:ffffffffffffffff The number disappears. That is because it will not print a NULL. Callbacks to allow the tracer to pretty print will be implemented soon. Signed-off-by: Steven Rostedt <srostedt@redhat.com>
Diffstat (limited to 'kernel/trace/ftrace.c')
-rw-r--r--kernel/trace/ftrace.c123
1 files changed, 103 insertions, 20 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 0b80e325f296..1e058848cddb 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -45,14 +45,14 @@
45 ftrace_kill(); \ 45 ftrace_kill(); \
46 } while (0) 46 } while (0)
47 47
48/* hash bits for specific function selection */
49#define FTRACE_HASH_BITS 7
50#define FTRACE_FUNC_HASHSIZE (1 << FTRACE_HASH_BITS)
51
48/* ftrace_enabled is a method to turn ftrace on or off */ 52/* ftrace_enabled is a method to turn ftrace on or off */
49int ftrace_enabled __read_mostly; 53int ftrace_enabled __read_mostly;
50static int last_ftrace_enabled; 54static int last_ftrace_enabled;
51 55
52/* set when tracing only a pid */
53struct pid *ftrace_pid_trace;
54static struct pid * const ftrace_swapper_pid = &init_struct_pid;
55
56/* Quick disabling of function tracer. */ 56/* Quick disabling of function tracer. */
57int function_trace_stop; 57int function_trace_stop;
58 58
@@ -248,6 +248,21 @@ static void ftrace_update_pid_func(void)
248# error Dynamic ftrace depends on MCOUNT_RECORD 248# error Dynamic ftrace depends on MCOUNT_RECORD
249#endif 249#endif
250 250
251/* set when tracing only a pid */
252struct pid *ftrace_pid_trace;
253static struct pid * const ftrace_swapper_pid = &init_struct_pid;
254static struct hlist_head ftrace_func_hash[FTRACE_FUNC_HASHSIZE] __read_mostly;
255
256struct ftrace_func_hook {
257 struct hlist_node node;
258 struct ftrace_hook_ops *ops;
259 unsigned long flags;
260 unsigned long ip;
261 void *data;
262 struct rcu_head rcu;
263};
264
265
251enum { 266enum {
252 FTRACE_ENABLE_CALLS = (1 << 0), 267 FTRACE_ENABLE_CALLS = (1 << 0),
253 FTRACE_DISABLE_CALLS = (1 << 1), 268 FTRACE_DISABLE_CALLS = (1 << 1),
@@ -750,12 +765,14 @@ enum {
750 FTRACE_ITER_NOTRACE = (1 << 2), 765 FTRACE_ITER_NOTRACE = (1 << 2),
751 FTRACE_ITER_FAILURES = (1 << 3), 766 FTRACE_ITER_FAILURES = (1 << 3),
752 FTRACE_ITER_PRINTALL = (1 << 4), 767 FTRACE_ITER_PRINTALL = (1 << 4),
768 FTRACE_ITER_HASH = (1 << 5),
753}; 769};
754 770
755#define FTRACE_BUFF_MAX (KSYM_SYMBOL_LEN+4) /* room for wildcards */ 771#define FTRACE_BUFF_MAX (KSYM_SYMBOL_LEN+4) /* room for wildcards */
756 772
757struct ftrace_iterator { 773struct ftrace_iterator {
758 struct ftrace_page *pg; 774 struct ftrace_page *pg;
775 int hidx;
759 int idx; 776 int idx;
760 unsigned flags; 777 unsigned flags;
761 unsigned char buffer[FTRACE_BUFF_MAX+1]; 778 unsigned char buffer[FTRACE_BUFF_MAX+1];
@@ -764,17 +781,86 @@ struct ftrace_iterator {
764}; 781};
765 782
766static void * 783static void *
784t_hash_next(struct seq_file *m, void *v, loff_t *pos)
785{
786 struct ftrace_iterator *iter = m->private;
787 struct hlist_node *hnd = v;
788 struct hlist_head *hhd;
789
790 WARN_ON(!(iter->flags & FTRACE_ITER_HASH));
791
792 (*pos)++;
793
794 retry:
795 if (iter->hidx >= FTRACE_FUNC_HASHSIZE)
796 return NULL;
797
798 hhd = &ftrace_func_hash[iter->hidx];
799
800 if (hlist_empty(hhd)) {
801 iter->hidx++;
802 hnd = NULL;
803 goto retry;
804 }
805
806 if (!hnd)
807 hnd = hhd->first;
808 else {
809 hnd = hnd->next;
810 if (!hnd) {
811 iter->hidx++;
812 goto retry;
813 }
814 }
815
816 return hnd;
817}
818
819static void *t_hash_start(struct seq_file *m, loff_t *pos)
820{
821 struct ftrace_iterator *iter = m->private;
822 void *p = NULL;
823
824 iter->flags |= FTRACE_ITER_HASH;
825
826 return t_hash_next(m, p, pos);
827}
828
829static int t_hash_show(struct seq_file *m, void *v)
830{
831 struct ftrace_func_hook *rec;
832 struct hlist_node *hnd = v;
833 char str[KSYM_SYMBOL_LEN];
834
835 rec = hlist_entry(hnd, struct ftrace_func_hook, node);
836
837 kallsyms_lookup(rec->ip, NULL, NULL, NULL, str);
838 seq_printf(m, "%s:", str);
839
840 kallsyms_lookup((unsigned long)rec->ops->func, NULL, NULL, NULL, str);
841 seq_printf(m, "%s", str);
842
843 if (rec->data)
844 seq_printf(m, ":%p", rec->data);
845 seq_putc(m, '\n');
846
847 return 0;
848}
849
850static void *
767t_next(struct seq_file *m, void *v, loff_t *pos) 851t_next(struct seq_file *m, void *v, loff_t *pos)
768{ 852{
769 struct ftrace_iterator *iter = m->private; 853 struct ftrace_iterator *iter = m->private;
770 struct dyn_ftrace *rec = NULL; 854 struct dyn_ftrace *rec = NULL;
771 855
856 if (iter->flags & FTRACE_ITER_HASH)
857 return t_hash_next(m, v, pos);
858
772 (*pos)++; 859 (*pos)++;
773 860
774 if (iter->flags & FTRACE_ITER_PRINTALL) 861 if (iter->flags & FTRACE_ITER_PRINTALL)
775 return NULL; 862 return NULL;
776 863
777 mutex_lock(&ftrace_lock);
778 retry: 864 retry:
779 if (iter->idx >= iter->pg->index) { 865 if (iter->idx >= iter->pg->index) {
780 if (iter->pg->next) { 866 if (iter->pg->next) {
@@ -803,7 +889,6 @@ t_next(struct seq_file *m, void *v, loff_t *pos)
803 goto retry; 889 goto retry;
804 } 890 }
805 } 891 }
806 mutex_unlock(&ftrace_lock);
807 892
808 return rec; 893 return rec;
809} 894}
@@ -813,6 +898,7 @@ static void *t_start(struct seq_file *m, loff_t *pos)
813 struct ftrace_iterator *iter = m->private; 898 struct ftrace_iterator *iter = m->private;
814 void *p = NULL; 899 void *p = NULL;
815 900
901 mutex_lock(&ftrace_lock);
816 /* 902 /*
817 * For set_ftrace_filter reading, if we have the filter 903 * For set_ftrace_filter reading, if we have the filter
818 * off, we can short cut and just print out that all 904 * off, we can short cut and just print out that all
@@ -820,12 +906,15 @@ static void *t_start(struct seq_file *m, loff_t *pos)
820 */ 906 */
821 if (iter->flags & FTRACE_ITER_FILTER && !ftrace_filtered) { 907 if (iter->flags & FTRACE_ITER_FILTER && !ftrace_filtered) {
822 if (*pos > 0) 908 if (*pos > 0)
823 return NULL; 909 return t_hash_start(m, pos);
824 iter->flags |= FTRACE_ITER_PRINTALL; 910 iter->flags |= FTRACE_ITER_PRINTALL;
825 (*pos)++; 911 (*pos)++;
826 return iter; 912 return iter;
827 } 913 }
828 914
915 if (iter->flags & FTRACE_ITER_HASH)
916 return t_hash_start(m, pos);
917
829 if (*pos > 0) { 918 if (*pos > 0) {
830 if (iter->idx < 0) 919 if (iter->idx < 0)
831 return p; 920 return p;
@@ -835,11 +924,15 @@ static void *t_start(struct seq_file *m, loff_t *pos)
835 924
836 p = t_next(m, p, pos); 925 p = t_next(m, p, pos);
837 926
927 if (!p)
928 return t_hash_start(m, pos);
929
838 return p; 930 return p;
839} 931}
840 932
841static void t_stop(struct seq_file *m, void *p) 933static void t_stop(struct seq_file *m, void *p)
842{ 934{
935 mutex_unlock(&ftrace_lock);
843} 936}
844 937
845static int t_show(struct seq_file *m, void *v) 938static int t_show(struct seq_file *m, void *v)
@@ -848,6 +941,9 @@ static int t_show(struct seq_file *m, void *v)
848 struct dyn_ftrace *rec = v; 941 struct dyn_ftrace *rec = v;
849 char str[KSYM_SYMBOL_LEN]; 942 char str[KSYM_SYMBOL_LEN];
850 943
944 if (iter->flags & FTRACE_ITER_HASH)
945 return t_hash_show(m, v);
946
851 if (iter->flags & FTRACE_ITER_PRINTALL) { 947 if (iter->flags & FTRACE_ITER_PRINTALL) {
852 seq_printf(m, "#### all functions enabled ####\n"); 948 seq_printf(m, "#### all functions enabled ####\n");
853 return 0; 949 return 0;
@@ -1246,19 +1342,6 @@ static int __init ftrace_mod_cmd_init(void)
1246} 1342}
1247device_initcall(ftrace_mod_cmd_init); 1343device_initcall(ftrace_mod_cmd_init);
1248 1344
1249#define FTRACE_HASH_BITS 7
1250#define FTRACE_FUNC_HASHSIZE (1 << FTRACE_HASH_BITS)
1251static struct hlist_head ftrace_func_hash[FTRACE_FUNC_HASHSIZE] __read_mostly;
1252
1253struct ftrace_func_hook {
1254 struct hlist_node node;
1255 struct ftrace_hook_ops *ops;
1256 unsigned long flags;
1257 unsigned long ip;
1258 void *data;
1259 struct rcu_head rcu;
1260};
1261
1262static void 1345static void
1263function_trace_hook_call(unsigned long ip, unsigned long parent_ip) 1346function_trace_hook_call(unsigned long ip, unsigned long parent_ip)
1264{ 1347{