diff options
author | Steven Rostedt <srostedt@redhat.com> | 2008-11-21 12:41:55 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-11-23 05:44:37 -0500 |
commit | 033601a32b2012b6948e80e739cca40bff4de4a0 (patch) | |
tree | 79f5fb4de0c76472174a1fd46c28e1503ac88dfc | |
parent | a0a70c735ef714fe1b6777b571630c3d50c7b008 (diff) |
ring-buffer: add tracing_off_permanent
Impact: feature to permanently disable ring buffer
This patch adds a API to the ring buffer code that will permanently
disable the ring buffer from ever recording. This should only be
called when some serious anomaly is detected, and the system
may be in an unstable state. When that happens, shutting down the
recording to the ring buffers may be appropriate.
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | include/linux/ring_buffer.h | 1 | ||||
-rw-r--r-- | kernel/trace/ring_buffer.c | 79 |
2 files changed, 67 insertions, 13 deletions
diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h index e097c2e6b6dc..3bb87a753fa3 100644 --- a/include/linux/ring_buffer.h +++ b/include/linux/ring_buffer.h | |||
@@ -122,6 +122,7 @@ void ring_buffer_normalize_time_stamp(int cpu, u64 *ts); | |||
122 | 122 | ||
123 | void tracing_on(void); | 123 | void tracing_on(void); |
124 | void tracing_off(void); | 124 | void tracing_off(void); |
125 | void tracing_off_permanent(void); | ||
125 | 126 | ||
126 | enum ring_buffer_flags { | 127 | enum ring_buffer_flags { |
127 | RB_FL_OVERWRITE = 1 << 0, | 128 | RB_FL_OVERWRITE = 1 << 0, |
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 85ced143c2c4..e206951603c1 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c | |||
@@ -18,8 +18,46 @@ | |||
18 | 18 | ||
19 | #include "trace.h" | 19 | #include "trace.h" |
20 | 20 | ||
21 | /* Global flag to disable all recording to ring buffers */ | 21 | /* |
22 | static int ring_buffers_off __read_mostly; | 22 | * A fast way to enable or disable all ring buffers is to |
23 | * call tracing_on or tracing_off. Turning off the ring buffers | ||
24 | * prevents all ring buffers from being recorded to. | ||
25 | * Turning this switch on, makes it OK to write to the | ||
26 | * ring buffer, if the ring buffer is enabled itself. | ||
27 | * | ||
28 | * There's three layers that must be on in order to write | ||
29 | * to the ring buffer. | ||
30 | * | ||
31 | * 1) This global flag must be set. | ||
32 | * 2) The ring buffer must be enabled for recording. | ||
33 | * 3) The per cpu buffer must be enabled for recording. | ||
34 | * | ||
35 | * In case of an anomaly, this global flag has a bit set that | ||
36 | * will permantly disable all ring buffers. | ||
37 | */ | ||
38 | |||
39 | /* | ||
40 | * Global flag to disable all recording to ring buffers | ||
41 | * This has two bits: ON, DISABLED | ||
42 | * | ||
43 | * ON DISABLED | ||
44 | * ---- ---------- | ||
45 | * 0 0 : ring buffers are off | ||
46 | * 1 0 : ring buffers are on | ||
47 | * X 1 : ring buffers are permanently disabled | ||
48 | */ | ||
49 | |||
50 | enum { | ||
51 | RB_BUFFERS_ON_BIT = 0, | ||
52 | RB_BUFFERS_DISABLED_BIT = 1, | ||
53 | }; | ||
54 | |||
55 | enum { | ||
56 | RB_BUFFERS_ON = 1 << RB_BUFFERS_ON_BIT, | ||
57 | RB_BUFFERS_DISABLED = 1 << RB_BUFFERS_DISABLED_BIT, | ||
58 | }; | ||
59 | |||
60 | static long ring_buffer_flags __read_mostly = RB_BUFFERS_ON; | ||
23 | 61 | ||
24 | /** | 62 | /** |
25 | * tracing_on - enable all tracing buffers | 63 | * tracing_on - enable all tracing buffers |
@@ -29,7 +67,7 @@ static int ring_buffers_off __read_mostly; | |||
29 | */ | 67 | */ |
30 | void tracing_on(void) | 68 | void tracing_on(void) |
31 | { | 69 | { |
32 | ring_buffers_off = 0; | 70 | set_bit(RB_BUFFERS_ON_BIT, &ring_buffer_flags); |
33 | } | 71 | } |
34 | 72 | ||
35 | /** | 73 | /** |
@@ -42,7 +80,18 @@ void tracing_on(void) | |||
42 | */ | 80 | */ |
43 | void tracing_off(void) | 81 | void tracing_off(void) |
44 | { | 82 | { |
45 | ring_buffers_off = 1; | 83 | clear_bit(RB_BUFFERS_ON_BIT, &ring_buffer_flags); |
84 | } | ||
85 | |||
86 | /** | ||
87 | * tracing_off_permanent - permanently disable ring buffers | ||
88 | * | ||
89 | * This function, once called, will disable all ring buffers | ||
90 | * permanenty. | ||
91 | */ | ||
92 | void tracing_off_permanent(void) | ||
93 | { | ||
94 | set_bit(RB_BUFFERS_DISABLED_BIT, &ring_buffer_flags); | ||
46 | } | 95 | } |
47 | 96 | ||
48 | #include "trace.h" | 97 | #include "trace.h" |
@@ -1185,7 +1234,7 @@ ring_buffer_lock_reserve(struct ring_buffer *buffer, | |||
1185 | struct ring_buffer_event *event; | 1234 | struct ring_buffer_event *event; |
1186 | int cpu, resched; | 1235 | int cpu, resched; |
1187 | 1236 | ||
1188 | if (ring_buffers_off) | 1237 | if (ring_buffer_flags != RB_BUFFERS_ON) |
1189 | return NULL; | 1238 | return NULL; |
1190 | 1239 | ||
1191 | if (atomic_read(&buffer->record_disabled)) | 1240 | if (atomic_read(&buffer->record_disabled)) |
@@ -1297,7 +1346,7 @@ int ring_buffer_write(struct ring_buffer *buffer, | |||
1297 | int ret = -EBUSY; | 1346 | int ret = -EBUSY; |
1298 | int cpu, resched; | 1347 | int cpu, resched; |
1299 | 1348 | ||
1300 | if (ring_buffers_off) | 1349 | if (ring_buffer_flags != RB_BUFFERS_ON) |
1301 | return -EBUSY; | 1350 | return -EBUSY; |
1302 | 1351 | ||
1303 | if (atomic_read(&buffer->record_disabled)) | 1352 | if (atomic_read(&buffer->record_disabled)) |
@@ -2178,12 +2227,14 @@ static ssize_t | |||
2178 | rb_simple_read(struct file *filp, char __user *ubuf, | 2227 | rb_simple_read(struct file *filp, char __user *ubuf, |
2179 | size_t cnt, loff_t *ppos) | 2228 | size_t cnt, loff_t *ppos) |
2180 | { | 2229 | { |
2181 | int *p = filp->private_data; | 2230 | long *p = filp->private_data; |
2182 | char buf[64]; | 2231 | char buf[64]; |
2183 | int r; | 2232 | int r; |
2184 | 2233 | ||
2185 | /* !ring_buffers_off == tracing_on */ | 2234 | if (test_bit(RB_BUFFERS_DISABLED_BIT, p)) |
2186 | r = sprintf(buf, "%d\n", !*p); | 2235 | r = sprintf(buf, "permanently disabled\n"); |
2236 | else | ||
2237 | r = sprintf(buf, "%d\n", test_bit(RB_BUFFERS_ON_BIT, p)); | ||
2187 | 2238 | ||
2188 | return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); | 2239 | return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); |
2189 | } | 2240 | } |
@@ -2192,7 +2243,7 @@ static ssize_t | |||
2192 | rb_simple_write(struct file *filp, const char __user *ubuf, | 2243 | rb_simple_write(struct file *filp, const char __user *ubuf, |
2193 | size_t cnt, loff_t *ppos) | 2244 | size_t cnt, loff_t *ppos) |
2194 | { | 2245 | { |
2195 | int *p = filp->private_data; | 2246 | long *p = filp->private_data; |
2196 | char buf[64]; | 2247 | char buf[64]; |
2197 | long val; | 2248 | long val; |
2198 | int ret; | 2249 | int ret; |
@@ -2209,8 +2260,10 @@ rb_simple_write(struct file *filp, const char __user *ubuf, | |||
2209 | if (ret < 0) | 2260 | if (ret < 0) |
2210 | return ret; | 2261 | return ret; |
2211 | 2262 | ||
2212 | /* !ring_buffers_off == tracing_on */ | 2263 | if (val) |
2213 | *p = !val; | 2264 | set_bit(RB_BUFFERS_ON_BIT, p); |
2265 | else | ||
2266 | clear_bit(RB_BUFFERS_ON_BIT, p); | ||
2214 | 2267 | ||
2215 | (*ppos)++; | 2268 | (*ppos)++; |
2216 | 2269 | ||
@@ -2232,7 +2285,7 @@ static __init int rb_init_debugfs(void) | |||
2232 | d_tracer = tracing_init_dentry(); | 2285 | d_tracer = tracing_init_dentry(); |
2233 | 2286 | ||
2234 | entry = debugfs_create_file("tracing_on", 0644, d_tracer, | 2287 | entry = debugfs_create_file("tracing_on", 0644, d_tracer, |
2235 | &ring_buffers_off, &rb_simple_fops); | 2288 | &ring_buffer_flags, &rb_simple_fops); |
2236 | if (!entry) | 2289 | if (!entry) |
2237 | pr_warning("Could not create debugfs 'tracing_on' entry\n"); | 2290 | pr_warning("Could not create debugfs 'tracing_on' entry\n"); |
2238 | 2291 | ||