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 | |
| 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>
| -rw-r--r-- | Documentation/tracers/mmiotrace.txt | 5 | ||||
| -rw-r--r-- | kernel/trace/trace.c | 76 | ||||
| -rw-r--r-- | kernel/trace/trace.h | 4 |
3 files changed, 77 insertions, 8 deletions
diff --git a/Documentation/tracers/mmiotrace.txt b/Documentation/tracers/mmiotrace.txt index a4afb560a45..5bbbe209622 100644 --- a/Documentation/tracers/mmiotrace.txt +++ b/Documentation/tracers/mmiotrace.txt | |||
| @@ -36,7 +36,7 @@ $ mount -t debugfs debugfs /debug | |||
| 36 | $ echo mmiotrace > /debug/tracing/current_tracer | 36 | $ echo mmiotrace > /debug/tracing/current_tracer |
| 37 | $ cat /debug/tracing/trace_pipe > mydump.txt & | 37 | $ cat /debug/tracing/trace_pipe > mydump.txt & |
| 38 | Start X or whatever. | 38 | Start X or whatever. |
| 39 | $ echo "X is up" > /debug/tracing/marker | 39 | $ echo "X is up" > /debug/tracing/trace_marker |
| 40 | $ echo none > /debug/tracing/current_tracer | 40 | $ echo none > /debug/tracing/current_tracer |
| 41 | Check for lost events. | 41 | Check for lost events. |
| 42 | 42 | ||
| @@ -59,9 +59,8 @@ The 'cat' process should stay running (sleeping) in the background. | |||
| 59 | Load the driver you want to trace and use it. Mmiotrace will only catch MMIO | 59 | Load the driver you want to trace and use it. Mmiotrace will only catch MMIO |
| 60 | accesses to areas that are ioremapped while mmiotrace is active. | 60 | accesses to areas that are ioremapped while mmiotrace is active. |
| 61 | 61 | ||
| 62 | [Unimplemented feature:] | ||
| 63 | During tracing you can place comments (markers) into the trace by | 62 | During tracing you can place comments (markers) into the trace by |
| 64 | $ echo "X is up" > /debug/tracing/marker | 63 | $ echo "X is up" > /debug/tracing/trace_marker |
| 65 | This makes it easier to see which part of the (huge) trace corresponds to | 64 | This makes it easier to see which part of the (huge) trace corresponds to |
| 66 | which action. It is recommended to place descriptive markers about what you | 65 | which action. It is recommended to place descriptive markers about what you |
| 67 | do. | 66 | do. |
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 7e7154f7700..eee1fd96489 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 648433d18cc..42f65d0097f 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 |
