diff options
author | Pekka Paalanen <pq@iki.fi> | 2008-09-16 15:06:42 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-10-14 04:37:20 -0400 |
commit | 5bf9a1ee350a10feb94107de32a203d81fbbe706 (patch) | |
tree | ac6b11aaa35194aed9fe9f1403c9542d070d0c62 /kernel | |
parent | 4427414170a63331a9cc36b9598502c5cdfe453b (diff) |
ftrace: inject markers via trace_marker file
Allow a user to inject a marker (TRACE_PRINT entry) into the trace ring
buffer. The related file operations are derived from code by Frédéric
Weisbecker <fweisbec@gmail.com>.
Signed-off-by: Pekka Paalanen <pq@iki.fi>
Acked-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/trace/trace.c | 76 | ||||
-rw-r--r-- | kernel/trace/trace.h | 4 |
2 files changed, 75 insertions, 5 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 7e7154f77009..eee1fd964898 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -2879,6 +2879,66 @@ tracing_entries_write(struct file *filp, const char __user *ubuf, | |||
2879 | return cnt; | 2879 | return cnt; |
2880 | } | 2880 | } |
2881 | 2881 | ||
2882 | static int tracing_open_mark(struct inode *inode, struct file *filp) | ||
2883 | { | ||
2884 | int ret; | ||
2885 | |||
2886 | ret = tracing_open_generic(inode, filp); | ||
2887 | if (ret) | ||
2888 | return ret; | ||
2889 | |||
2890 | if (current_trace == &no_tracer) | ||
2891 | return -ENODEV; | ||
2892 | |||
2893 | return 0; | ||
2894 | } | ||
2895 | |||
2896 | static int mark_printk(const char *fmt, ...) | ||
2897 | { | ||
2898 | int ret; | ||
2899 | va_list args; | ||
2900 | va_start(args, fmt); | ||
2901 | ret = trace_vprintk(0, fmt, args); | ||
2902 | va_end(args); | ||
2903 | return ret; | ||
2904 | } | ||
2905 | |||
2906 | static ssize_t | ||
2907 | tracing_mark_write(struct file *filp, const char __user *ubuf, | ||
2908 | size_t cnt, loff_t *fpos) | ||
2909 | { | ||
2910 | char *buf; | ||
2911 | char *end; | ||
2912 | struct trace_array *tr = &global_trace; | ||
2913 | |||
2914 | if (current_trace == &no_tracer || !tr->ctrl || tracing_disabled) | ||
2915 | return -EINVAL; | ||
2916 | |||
2917 | if (cnt > TRACE_BUF_SIZE) | ||
2918 | cnt = TRACE_BUF_SIZE; | ||
2919 | |||
2920 | buf = kmalloc(cnt + 1, GFP_KERNEL); | ||
2921 | if (buf == NULL) | ||
2922 | return -ENOMEM; | ||
2923 | |||
2924 | if (copy_from_user(buf, ubuf, cnt)) { | ||
2925 | kfree(buf); | ||
2926 | return -EFAULT; | ||
2927 | } | ||
2928 | |||
2929 | /* Cut from the first nil or newline. */ | ||
2930 | buf[cnt] = '\0'; | ||
2931 | end = strchr(buf, '\n'); | ||
2932 | if (end) | ||
2933 | *end = '\0'; | ||
2934 | |||
2935 | cnt = mark_printk("%s\n", buf); | ||
2936 | kfree(buf); | ||
2937 | *fpos += cnt; | ||
2938 | |||
2939 | return cnt; | ||
2940 | } | ||
2941 | |||
2882 | static struct file_operations tracing_max_lat_fops = { | 2942 | static struct file_operations tracing_max_lat_fops = { |
2883 | .open = tracing_open_generic, | 2943 | .open = tracing_open_generic, |
2884 | .read = tracing_max_lat_read, | 2944 | .read = tracing_max_lat_read, |
@@ -2910,6 +2970,11 @@ static struct file_operations tracing_entries_fops = { | |||
2910 | .write = tracing_entries_write, | 2970 | .write = tracing_entries_write, |
2911 | }; | 2971 | }; |
2912 | 2972 | ||
2973 | static struct file_operations tracing_mark_fops = { | ||
2974 | .open = tracing_open_mark, | ||
2975 | .write = tracing_mark_write, | ||
2976 | }; | ||
2977 | |||
2913 | #ifdef CONFIG_DYNAMIC_FTRACE | 2978 | #ifdef CONFIG_DYNAMIC_FTRACE |
2914 | 2979 | ||
2915 | static ssize_t | 2980 | static ssize_t |
@@ -3027,6 +3092,12 @@ static __init void tracer_init_debugfs(void) | |||
3027 | pr_warning("Could not create debugfs " | 3092 | pr_warning("Could not create debugfs " |
3028 | "'trace_entries' entry\n"); | 3093 | "'trace_entries' entry\n"); |
3029 | 3094 | ||
3095 | entry = debugfs_create_file("trace_marker", 0220, d_tracer, | ||
3096 | NULL, &tracing_mark_fops); | ||
3097 | if (!entry) | ||
3098 | pr_warning("Could not create debugfs " | ||
3099 | "'trace_marker' entry\n"); | ||
3100 | |||
3030 | #ifdef CONFIG_DYNAMIC_FTRACE | 3101 | #ifdef CONFIG_DYNAMIC_FTRACE |
3031 | entry = debugfs_create_file("dyn_ftrace_total_info", 0444, d_tracer, | 3102 | entry = debugfs_create_file("dyn_ftrace_total_info", 0444, d_tracer, |
3032 | &ftrace_update_tot_cnt, | 3103 | &ftrace_update_tot_cnt, |
@@ -3040,11 +3111,6 @@ static __init void tracer_init_debugfs(void) | |||
3040 | #endif | 3111 | #endif |
3041 | } | 3112 | } |
3042 | 3113 | ||
3043 | #define TRACE_BUF_SIZE 1024 | ||
3044 | #define TRACE_PRINT_BUF_SIZE \ | ||
3045 | (sizeof(struct trace_field) - offsetof(struct trace_field, print.buf)) | ||
3046 | #define TRACE_CONT_BUF_SIZE sizeof(struct trace_field) | ||
3047 | |||
3048 | int trace_vprintk(unsigned long ip, const char *fmt, va_list args) | 3114 | int trace_vprintk(unsigned long ip, const char *fmt, va_list args) |
3049 | { | 3115 | { |
3050 | static DEFINE_SPINLOCK(trace_buf_lock); | 3116 | static DEFINE_SPINLOCK(trace_buf_lock); |
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 648433d18ccb..42f65d0097f0 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
@@ -124,6 +124,10 @@ struct trace_entry { | |||
124 | }; | 124 | }; |
125 | 125 | ||
126 | #define TRACE_ENTRY_SIZE sizeof(struct trace_entry) | 126 | #define TRACE_ENTRY_SIZE sizeof(struct trace_entry) |
127 | #define TRACE_BUF_SIZE 1024 | ||
128 | #define TRACE_PRINT_BUF_SIZE \ | ||
129 | (sizeof(struct trace_field) - offsetof(struct trace_field, print.buf)) | ||
130 | #define TRACE_CONT_BUF_SIZE sizeof(struct trace_field) | ||
127 | 131 | ||
128 | /* | 132 | /* |
129 | * The CPU trace array - it consists of thousands of trace entries | 133 | * The CPU trace array - it consists of thousands of trace entries |