aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace
diff options
context:
space:
mode:
authorSteven Rostedt (Red Hat) <srostedt@redhat.com>2013-03-06 15:27:24 -0500
committerSteven Rostedt <rostedt@goodmis.org>2013-03-15 00:35:51 -0400
commita695cb5816228f86576f5f5c6809fdf8ed382ece (patch)
tree922f12a1a2fab1efa16f74216d6883deeefd1b74 /kernel/trace
parenttracing: Add per_cpu directory into tracing instances (diff)
downloadlinux-dev-a695cb5816228f86576f5f5c6809fdf8ed382ece.tar.xz
linux-dev-a695cb5816228f86576f5f5c6809fdf8ed382ece.zip
tracing: Prevent deleting instances when they are being read
Add a ref count to the trace_array structure and prevent removal of instances that have open descriptors. Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace')
-rw-r--r--kernel/trace/trace.c23
-rw-r--r--kernel/trace/trace.h1
2 files changed, 24 insertions, 0 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index c547ebbe36ff..3a89496dc99b 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -2613,6 +2613,8 @@ __tracing_open(struct inode *inode, struct file *file, bool snapshot)
tracing_iter_reset(iter, cpu);
}
+ tr->ref++;
+
mutex_unlock(&trace_types_lock);
return iter;
@@ -2649,6 +2651,10 @@ static int tracing_release(struct inode *inode, struct file *file)
tr = iter->tr;
mutex_lock(&trace_types_lock);
+
+ WARN_ON(!tr->ref);
+ tr->ref--;
+
for_each_tracing_cpu(cpu) {
if (iter->buffer_iter[cpu])
ring_buffer_read_finish(iter->buffer_iter[cpu]);
@@ -4460,6 +4466,10 @@ static int tracing_buffers_open(struct inode *inode, struct file *filp)
if (!info)
return -ENOMEM;
+ mutex_lock(&trace_types_lock);
+
+ tr->ref++;
+
info->iter.tr = tr;
info->iter.cpu_file = tc->cpu;
info->iter.trace = tr->current_trace;
@@ -4470,6 +4480,8 @@ static int tracing_buffers_open(struct inode *inode, struct file *filp)
filp->private_data = info;
+ mutex_unlock(&trace_types_lock);
+
return nonseekable_open(inode, filp);
}
@@ -4568,10 +4580,17 @@ static int tracing_buffers_release(struct inode *inode, struct file *file)
struct ftrace_buffer_info *info = file->private_data;
struct trace_iterator *iter = &info->iter;
+ mutex_lock(&trace_types_lock);
+
+ WARN_ON(!iter->tr->ref);
+ iter->tr->ref--;
+
if (info->spare)
ring_buffer_free_read_page(iter->trace_buffer->buffer, info->spare);
kfree(info);
+ mutex_unlock(&trace_types_lock);
+
return 0;
}
@@ -5411,6 +5430,10 @@ static int instance_delete(const char *name)
if (!found)
goto out_unlock;
+ ret = -EBUSY;
+ if (tr->ref)
+ goto out_unlock;
+
list_del(&tr->list);
event_trace_del_tracer(tr);
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 1a456c291a07..f4931821a966 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -219,6 +219,7 @@ struct trace_array {
struct list_head systems;
struct list_head events;
struct task_struct *waiter;
+ int ref;
};
enum {