From a695cb5816228f86576f5f5c6809fdf8ed382ece Mon Sep 17 00:00:00 2001
From: "Steven Rostedt (Red Hat)" <srostedt@redhat.com>
Date: Wed, 6 Mar 2013 15:27:24 -0500
Subject: [PATCH] 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>
---
 kernel/trace/trace.c | 23 +++++++++++++++++++++++
 kernel/trace/trace.h |  1 +
 2 files changed, 24 insertions(+)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index c547ebbe36ffe..3a89496dc99b3 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 1a456c291a074..f4931821a9669 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 {
-- 
2.30.2