diff options
Diffstat (limited to 'kernel/trace/trace.c')
-rw-r--r-- | kernel/trace/trace.c | 92 |
1 files changed, 75 insertions, 17 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 8ac204360a39..63dbc7ff213f 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -323,12 +323,21 @@ static const char *trace_options[] = { | |||
323 | "printk-msg-only", | 323 | "printk-msg-only", |
324 | "context-info", | 324 | "context-info", |
325 | "latency-format", | 325 | "latency-format", |
326 | "global-clock", | ||
327 | "sleep-time", | 326 | "sleep-time", |
328 | "graph-time", | 327 | "graph-time", |
329 | NULL | 328 | NULL |
330 | }; | 329 | }; |
331 | 330 | ||
331 | static struct { | ||
332 | u64 (*func)(void); | ||
333 | const char *name; | ||
334 | } trace_clocks[] = { | ||
335 | { trace_clock_local, "local" }, | ||
336 | { trace_clock_global, "global" }, | ||
337 | }; | ||
338 | |||
339 | int trace_clock_id; | ||
340 | |||
332 | /* | 341 | /* |
333 | * ftrace_max_lock is used to protect the swapping of buffers | 342 | * ftrace_max_lock is used to protect the swapping of buffers |
334 | * when taking a max snapshot. The buffers themselves are | 343 | * when taking a max snapshot. The buffers themselves are |
@@ -2159,22 +2168,6 @@ static void set_tracer_flags(unsigned int mask, int enabled) | |||
2159 | trace_flags |= mask; | 2168 | trace_flags |= mask; |
2160 | else | 2169 | else |
2161 | trace_flags &= ~mask; | 2170 | trace_flags &= ~mask; |
2162 | |||
2163 | if (mask == TRACE_ITER_GLOBAL_CLK) { | ||
2164 | u64 (*func)(void); | ||
2165 | |||
2166 | if (enabled) | ||
2167 | func = trace_clock_global; | ||
2168 | else | ||
2169 | func = trace_clock_local; | ||
2170 | |||
2171 | mutex_lock(&trace_types_lock); | ||
2172 | ring_buffer_set_clock(global_trace.buffer, func); | ||
2173 | |||
2174 | if (max_tr.buffer) | ||
2175 | ring_buffer_set_clock(max_tr.buffer, func); | ||
2176 | mutex_unlock(&trace_types_lock); | ||
2177 | } | ||
2178 | } | 2171 | } |
2179 | 2172 | ||
2180 | static ssize_t | 2173 | static ssize_t |
@@ -3142,6 +3135,62 @@ tracing_mark_write(struct file *filp, const char __user *ubuf, | |||
3142 | return cnt; | 3135 | return cnt; |
3143 | } | 3136 | } |
3144 | 3137 | ||
3138 | static ssize_t tracing_clock_read(struct file *filp, char __user *ubuf, | ||
3139 | size_t cnt, loff_t *ppos) | ||
3140 | { | ||
3141 | char buf[64]; | ||
3142 | int bufiter = 0; | ||
3143 | int i; | ||
3144 | |||
3145 | for (i = 0; i < ARRAY_SIZE(trace_clocks); i++) | ||
3146 | bufiter += snprintf(buf + bufiter, sizeof(buf) - bufiter, | ||
3147 | "%s%s%s%s", i ? " " : "", | ||
3148 | i == trace_clock_id ? "[" : "", trace_clocks[i].name, | ||
3149 | i == trace_clock_id ? "]" : ""); | ||
3150 | bufiter += snprintf(buf + bufiter, sizeof(buf) - bufiter, "\n"); | ||
3151 | |||
3152 | return simple_read_from_buffer(ubuf, cnt, ppos, buf, bufiter); | ||
3153 | } | ||
3154 | |||
3155 | static ssize_t tracing_clock_write(struct file *filp, const char __user *ubuf, | ||
3156 | size_t cnt, loff_t *fpos) | ||
3157 | { | ||
3158 | char buf[64]; | ||
3159 | const char *clockstr; | ||
3160 | int i; | ||
3161 | |||
3162 | if (cnt >= sizeof(buf)) | ||
3163 | return -EINVAL; | ||
3164 | |||
3165 | if (copy_from_user(&buf, ubuf, cnt)) | ||
3166 | return -EFAULT; | ||
3167 | |||
3168 | buf[cnt] = 0; | ||
3169 | |||
3170 | clockstr = strstrip(buf); | ||
3171 | |||
3172 | for (i = 0; i < ARRAY_SIZE(trace_clocks); i++) { | ||
3173 | if (strcmp(trace_clocks[i].name, clockstr) == 0) | ||
3174 | break; | ||
3175 | } | ||
3176 | if (i == ARRAY_SIZE(trace_clocks)) | ||
3177 | return -EINVAL; | ||
3178 | |||
3179 | trace_clock_id = i; | ||
3180 | |||
3181 | mutex_lock(&trace_types_lock); | ||
3182 | |||
3183 | ring_buffer_set_clock(global_trace.buffer, trace_clocks[i].func); | ||
3184 | if (max_tr.buffer) | ||
3185 | ring_buffer_set_clock(max_tr.buffer, trace_clocks[i].func); | ||
3186 | |||
3187 | mutex_unlock(&trace_types_lock); | ||
3188 | |||
3189 | *fpos += cnt; | ||
3190 | |||
3191 | return cnt; | ||
3192 | } | ||
3193 | |||
3145 | static const struct file_operations tracing_max_lat_fops = { | 3194 | static const struct file_operations tracing_max_lat_fops = { |
3146 | .open = tracing_open_generic, | 3195 | .open = tracing_open_generic, |
3147 | .read = tracing_max_lat_read, | 3196 | .read = tracing_max_lat_read, |
@@ -3179,6 +3228,12 @@ static const struct file_operations tracing_mark_fops = { | |||
3179 | .write = tracing_mark_write, | 3228 | .write = tracing_mark_write, |
3180 | }; | 3229 | }; |
3181 | 3230 | ||
3231 | static const struct file_operations trace_clock_fops = { | ||
3232 | .open = tracing_open_generic, | ||
3233 | .read = tracing_clock_read, | ||
3234 | .write = tracing_clock_write, | ||
3235 | }; | ||
3236 | |||
3182 | struct ftrace_buffer_info { | 3237 | struct ftrace_buffer_info { |
3183 | struct trace_array *tr; | 3238 | struct trace_array *tr; |
3184 | void *spare; | 3239 | void *spare; |
@@ -3918,6 +3973,9 @@ static __init int tracer_init_debugfs(void) | |||
3918 | trace_create_file("saved_cmdlines", 0444, d_tracer, | 3973 | trace_create_file("saved_cmdlines", 0444, d_tracer, |
3919 | NULL, &tracing_saved_cmdlines_fops); | 3974 | NULL, &tracing_saved_cmdlines_fops); |
3920 | 3975 | ||
3976 | trace_create_file("trace_clock", 0644, d_tracer, NULL, | ||
3977 | &trace_clock_fops); | ||
3978 | |||
3921 | #ifdef CONFIG_DYNAMIC_FTRACE | 3979 | #ifdef CONFIG_DYNAMIC_FTRACE |
3922 | trace_create_file("dyn_ftrace_total_info", 0444, d_tracer, | 3980 | trace_create_file("dyn_ftrace_total_info", 0444, d_tracer, |
3923 | &ftrace_update_tot_cnt, &tracing_dyn_info_fops); | 3981 | &ftrace_update_tot_cnt, &tracing_dyn_info_fops); |