|
@@ -16,6 +16,35 @@
|
|
|
#include <linux/list.h>
|
|
|
#include <linux/fs.h>
|
|
|
|
|
|
+#include "trace.h"
|
|
|
+
|
|
|
+/* Global flag to disable all recording to ring buffers */
|
|
|
+static int ring_buffers_off __read_mostly;
|
|
|
+
|
|
|
+/**
|
|
|
+ * tracing_on - enable all tracing buffers
|
|
|
+ *
|
|
|
+ * This function enables all tracing buffers that may have been
|
|
|
+ * disabled with tracing_off.
|
|
|
+ */
|
|
|
+void tracing_on(void)
|
|
|
+{
|
|
|
+ ring_buffers_off = 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * tracing_off - turn off all tracing buffers
|
|
|
+ *
|
|
|
+ * This function stops all tracing buffers from recording data.
|
|
|
+ * It does not disable any overhead the tracers themselves may
|
|
|
+ * be causing. This function simply causes all recording to
|
|
|
+ * the ring buffers to fail.
|
|
|
+ */
|
|
|
+void tracing_off(void)
|
|
|
+{
|
|
|
+ ring_buffers_off = 1;
|
|
|
+}
|
|
|
+
|
|
|
/* Up this if you want to test the TIME_EXTENTS and normalization */
|
|
|
#define DEBUG_SHIFT 0
|
|
|
|
|
@@ -1133,6 +1162,9 @@ ring_buffer_lock_reserve(struct ring_buffer *buffer,
|
|
|
struct ring_buffer_event *event;
|
|
|
int cpu, resched;
|
|
|
|
|
|
+ if (ring_buffers_off)
|
|
|
+ return NULL;
|
|
|
+
|
|
|
if (atomic_read(&buffer->record_disabled))
|
|
|
return NULL;
|
|
|
|
|
@@ -1249,6 +1281,9 @@ int ring_buffer_write(struct ring_buffer *buffer,
|
|
|
int ret = -EBUSY;
|
|
|
int cpu, resched;
|
|
|
|
|
|
+ if (ring_buffers_off)
|
|
|
+ return -EBUSY;
|
|
|
+
|
|
|
if (atomic_read(&buffer->record_disabled))
|
|
|
return -EBUSY;
|
|
|
|
|
@@ -2070,3 +2105,69 @@ int ring_buffer_swap_cpu(struct ring_buffer *buffer_a,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static ssize_t
|
|
|
+rb_simple_read(struct file *filp, char __user *ubuf,
|
|
|
+ size_t cnt, loff_t *ppos)
|
|
|
+{
|
|
|
+ int *p = filp->private_data;
|
|
|
+ char buf[64];
|
|
|
+ int r;
|
|
|
+
|
|
|
+ /* !ring_buffers_off == tracing_on */
|
|
|
+ r = sprintf(buf, "%d\n", !*p);
|
|
|
+
|
|
|
+ return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
|
|
|
+}
|
|
|
+
|
|
|
+static ssize_t
|
|
|
+rb_simple_write(struct file *filp, const char __user *ubuf,
|
|
|
+ size_t cnt, loff_t *ppos)
|
|
|
+{
|
|
|
+ int *p = filp->private_data;
|
|
|
+ char buf[64];
|
|
|
+ long val;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (cnt >= sizeof(buf))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ if (copy_from_user(&buf, ubuf, cnt))
|
|
|
+ return -EFAULT;
|
|
|
+
|
|
|
+ buf[cnt] = 0;
|
|
|
+
|
|
|
+ ret = strict_strtoul(buf, 10, &val);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ /* !ring_buffers_off == tracing_on */
|
|
|
+ *p = !val;
|
|
|
+
|
|
|
+ (*ppos)++;
|
|
|
+
|
|
|
+ return cnt;
|
|
|
+}
|
|
|
+
|
|
|
+static struct file_operations rb_simple_fops = {
|
|
|
+ .open = tracing_open_generic,
|
|
|
+ .read = rb_simple_read,
|
|
|
+ .write = rb_simple_write,
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+static __init int rb_init_debugfs(void)
|
|
|
+{
|
|
|
+ struct dentry *d_tracer;
|
|
|
+ struct dentry *entry;
|
|
|
+
|
|
|
+ d_tracer = tracing_init_dentry();
|
|
|
+
|
|
|
+ entry = debugfs_create_file("tracing_on", 0644, d_tracer,
|
|
|
+ &ring_buffers_off, &rb_simple_fops);
|
|
|
+ if (!entry)
|
|
|
+ pr_warning("Could not create debugfs 'tracing_on' entry\n");
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+fs_initcall(rb_init_debugfs);
|