aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2008-11-11 15:01:42 -0500
committerSteven Rostedt <srostedt@redhat.com>2008-11-11 15:02:04 -0500
commita358324466b171e145df20bdb74fe81759906de6 (patch)
tree50b2b0b72ff40da6be232eb85d33a203612f3164 /kernel/trace
parent4143c5cb36331155a1823af8b3a8c761a59fed71 (diff)
ring-buffer: buffer record on/off switch
Impact: enable/disable ring buffer recording API added Several kernel developers have requested that there be a way to stop recording into the ring buffers with a simple switch that can also be enabled from userspace. This patch addes a new kernel API to the ring buffers called: tracing_on() tracing_off() When tracing_off() is called, all ring buffers will not be able to record into their buffers. tracing_on() will enable the ring buffers again. These two act like an on/off switch. That is, there is no counting of the number of times tracing_off or tracing_on has been called. A new file is added to the debugfs/tracing directory called tracing_on This allows for userspace applications to also flip the switch. echo 0 > debugfs/tracing/tracing_on disables the tracing. echo 1 > /debugfs/tracing/tracing_on enables it. Note, this does not disable or enable any tracers. It only sets or clears a flag that needs to be set in order for the ring buffers to write to their buffers. It is a global flag, and affects all ring buffers. The buffers start out with tracing_on enabled. There are now three flags that control recording into the buffers: tracing_on: which affects all ring buffer tracers. buffer->record_disabled: which affects an allocated buffer, which may be set if an anomaly is detected, and tracing is disabled. cpu_buffer->record_disabled: which is set by tracing_stop() or if an anomaly is detected. tracing_start can not reenable this if an anomaly occurred. The userspace debugfs/tracing/tracing_enabled is implemented with tracing_stop() but the user space code can not enable it if the kernel called tracing_stop(). Userspace can enable the tracing_on even if the kernel disabled it. It is just a switch used to stop tracing if a condition was hit. tracing_on is not for protecting critical areas in the kernel nor is it for stopping tracing if an anomaly occurred. This is because userspace can reenable it at any time. Side effect: With this patch, I discovered a dead variable in ftrace.c called tracing_on. This patch removes it. Signed-off-by: Steven Rostedt <srostedt@redhat.com>
Diffstat (limited to 'kernel/trace')
-rw-r--r--kernel/trace/ftrace.c8
-rw-r--r--kernel/trace/ring_buffer.c101
2 files changed, 103 insertions, 6 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 4a39d24568c8..14fa52297b28 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -185,7 +185,6 @@ enum {
185}; 185};
186 186
187static int ftrace_filtered; 187static int ftrace_filtered;
188static int tracing_on;
189 188
190static LIST_HEAD(ftrace_new_addrs); 189static LIST_HEAD(ftrace_new_addrs);
191 190
@@ -506,13 +505,10 @@ static int __ftrace_modify_code(void *data)
506{ 505{
507 int *command = data; 506 int *command = data;
508 507
509 if (*command & FTRACE_ENABLE_CALLS) { 508 if (*command & FTRACE_ENABLE_CALLS)
510 ftrace_replace_code(1); 509 ftrace_replace_code(1);
511 tracing_on = 1; 510 else if (*command & FTRACE_DISABLE_CALLS)
512 } else if (*command & FTRACE_DISABLE_CALLS) {
513 ftrace_replace_code(0); 511 ftrace_replace_code(0);
514 tracing_on = 0;
515 }
516 512
517 if (*command & FTRACE_UPDATE_TRACE_FUNC) 513 if (*command & FTRACE_UPDATE_TRACE_FUNC)
518 ftrace_update_ftrace_func(ftrace_trace_function); 514 ftrace_update_ftrace_func(ftrace_trace_function);
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 2f76193c3489..b08ee9f00c8d 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -16,6 +16,35 @@
16#include <linux/list.h> 16#include <linux/list.h>
17#include <linux/fs.h> 17#include <linux/fs.h>
18 18
19#include "trace.h"
20
21/* Global flag to disable all recording to ring buffers */
22static int ring_buffers_off __read_mostly;
23
24/**
25 * tracing_on - enable all tracing buffers
26 *
27 * This function enables all tracing buffers that may have been
28 * disabled with tracing_off.
29 */
30void tracing_on(void)
31{
32 ring_buffers_off = 0;
33}
34
35/**
36 * tracing_off - turn off all tracing buffers
37 *
38 * This function stops all tracing buffers from recording data.
39 * It does not disable any overhead the tracers themselves may
40 * be causing. This function simply causes all recording to
41 * the ring buffers to fail.
42 */
43void tracing_off(void)
44{
45 ring_buffers_off = 1;
46}
47
19/* Up this if you want to test the TIME_EXTENTS and normalization */ 48/* Up this if you want to test the TIME_EXTENTS and normalization */
20#define DEBUG_SHIFT 0 49#define DEBUG_SHIFT 0
21 50
@@ -1133,6 +1162,9 @@ ring_buffer_lock_reserve(struct ring_buffer *buffer,
1133 struct ring_buffer_event *event; 1162 struct ring_buffer_event *event;
1134 int cpu, resched; 1163 int cpu, resched;
1135 1164
1165 if (ring_buffers_off)
1166 return NULL;
1167
1136 if (atomic_read(&buffer->record_disabled)) 1168 if (atomic_read(&buffer->record_disabled))
1137 return NULL; 1169 return NULL;
1138 1170
@@ -1249,6 +1281,9 @@ int ring_buffer_write(struct ring_buffer *buffer,
1249 int ret = -EBUSY; 1281 int ret = -EBUSY;
1250 int cpu, resched; 1282 int cpu, resched;
1251 1283
1284 if (ring_buffers_off)
1285 return -EBUSY;
1286
1252 if (atomic_read(&buffer->record_disabled)) 1287 if (atomic_read(&buffer->record_disabled))
1253 return -EBUSY; 1288 return -EBUSY;
1254 1289
@@ -2070,3 +2105,69 @@ int ring_buffer_swap_cpu(struct ring_buffer *buffer_a,
2070 return 0; 2105 return 0;
2071} 2106}
2072 2107
2108static ssize_t
2109rb_simple_read(struct file *filp, char __user *ubuf,
2110 size_t cnt, loff_t *ppos)
2111{
2112 int *p = filp->private_data;
2113 char buf[64];
2114 int r;
2115
2116 /* !ring_buffers_off == tracing_on */
2117 r = sprintf(buf, "%d\n", !*p);
2118
2119 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
2120}
2121
2122static ssize_t
2123rb_simple_write(struct file *filp, const char __user *ubuf,
2124 size_t cnt, loff_t *ppos)
2125{
2126 int *p = filp->private_data;
2127 char buf[64];
2128 long val;
2129 int ret;
2130
2131 if (cnt >= sizeof(buf))
2132 return -EINVAL;
2133
2134 if (copy_from_user(&buf, ubuf, cnt))
2135 return -EFAULT;
2136
2137 buf[cnt] = 0;
2138
2139 ret = strict_strtoul(buf, 10, &val);
2140 if (ret < 0)
2141 return ret;
2142
2143 /* !ring_buffers_off == tracing_on */
2144 *p = !val;
2145
2146 (*ppos)++;
2147
2148 return cnt;
2149}
2150
2151static struct file_operations rb_simple_fops = {
2152 .open = tracing_open_generic,
2153 .read = rb_simple_read,
2154 .write = rb_simple_write,
2155};
2156
2157
2158static __init int rb_init_debugfs(void)
2159{
2160 struct dentry *d_tracer;
2161 struct dentry *entry;
2162
2163 d_tracer = tracing_init_dentry();
2164
2165 entry = debugfs_create_file("tracing_on", 0644, d_tracer,
2166 &ring_buffers_off, &rb_simple_fops);
2167 if (!entry)
2168 pr_warning("Could not create debugfs 'tracing_on' entry\n");
2169
2170 return 0;
2171}
2172
2173fs_initcall(rb_init_debugfs);