diff options
Diffstat (limited to 'kernel/trace/ring_buffer.c')
| -rw-r--r-- | kernel/trace/ring_buffer.c | 79 |
1 files changed, 66 insertions, 13 deletions
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 | ||
