[PATCH 14/16] kn-trace

Chris Wilson chris at chris-wilson.co.uk
Mon Jan 18 22:56:29 UTC 2021


---
 include/linux/trace.h |  10 +++
 kernel/trace/trace.c  | 174 ++++++++++++++++++++++++++++++++++++------
 2 files changed, 159 insertions(+), 25 deletions(-)

diff --git a/include/linux/trace.h b/include/linux/trace.h
index 69ad44ad288b..695103ace1fc 100644
--- a/include/linux/trace.h
+++ b/include/linux/trace.h
@@ -2,6 +2,8 @@
 #ifndef _LINUX_TRACE_H
 #define _LINUX_TRACE_H
 
+#include <linux/uidgid.h>
+
 #ifdef CONFIG_TRACING
 
 #define TRACE_EXPORT_FUNCTION	BIT(0)
@@ -44,6 +46,14 @@ int trace_array_destroy(struct trace_array *tr);
 
 int anon_trace_getfd(const char *name, struct trace_array *tr);
 
+struct kernfs_node;
+int trace_create_kernfs(struct kernfs_node *parent,
+			const char *name,
+			umode_t mode,
+			kuid_t uid,
+			kgid_t gid,
+			struct trace_array *tr);
+
 #else
 
 static inline struct trace_array *trace_array_create(void) { return NULL; }
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index d006b585c871..2de8c9eb5280 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -49,6 +49,7 @@
 #include <linux/irq_work.h>
 #include <linux/workqueue.h>
 #include <linux/anon_inodes.h>
+#include <linux/kernfs.h>
 
 #include "trace.h"
 #include "trace_output.h"
@@ -3609,9 +3610,9 @@ static void trace_consume(struct trace_iterator *iter)
 			    &iter->lost_events);
 }
 
-static void *s_next(struct seq_file *m, void *v, loff_t *pos)
+static void *__s_next(struct seq_file *m, struct trace_iterator *iter,
+		      void *v, loff_t *pos)
 {
-	struct trace_iterator *iter = m->private;
 	int i = (int)*pos;
 	void *ent;
 
@@ -3636,6 +3637,11 @@ static void *s_next(struct seq_file *m, void *v, loff_t *pos)
 	return ent;
 }
 
+static void *s_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	return __s_next(m, m->private, v, pos);
+}
+
 void tracing_iter_reset(struct trace_iterator *iter, int cpu)
 {
 	struct ring_buffer_iter *buf_iter;
@@ -3669,9 +3675,8 @@ void tracing_iter_reset(struct trace_iterator *iter, int cpu)
  * The current tracer is copied to avoid a global locking
  * all around.
  */
-static void *s_start(struct seq_file *m, loff_t *pos)
+static void *__s_start(struct seq_file *m, struct trace_iterator *iter, loff_t *pos)
 {
-	struct trace_iterator *iter = m->private;
 	struct trace_array *tr = iter->tr;
 	int cpu_file = iter->cpu_file;
 	void *p = NULL;
@@ -3709,7 +3714,7 @@ static void *s_start(struct seq_file *m, loff_t *pos)
 			tracing_iter_reset(iter, cpu_file);
 
 		iter->leftover = 0;
-		for (p = iter; p && l < *pos; p = s_next(m, p, &l))
+		for (p = iter; p && l < *pos; p = __s_next(m, iter, p, &l))
 			;
 
 	} else {
@@ -3721,7 +3726,7 @@ static void *s_start(struct seq_file *m, loff_t *pos)
 			p = iter;
 		else {
 			l = *pos - 1;
-			p = s_next(m, p, &l);
+			p = __s_next(m, iter, p, &l);
 		}
 	}
 
@@ -3730,10 +3735,13 @@ static void *s_start(struct seq_file *m, loff_t *pos)
 	return p;
 }
 
-static void s_stop(struct seq_file *m, void *p)
+static void *s_start(struct seq_file *m, loff_t *pos)
 {
-	struct trace_iterator *iter = m->private;
+	return __s_start(m, m->private, pos);
+}
 
+static void __s_stop(struct seq_file *m, struct trace_iterator *iter)
+{
 #ifdef CONFIG_TRACER_MAX_TRACE
 	if (iter->snapshot && iter->trace->use_max_tr)
 		return;
@@ -3746,6 +3754,11 @@ static void s_stop(struct seq_file *m, void *p)
 	trace_event_read_unlock();
 }
 
+static void s_stop(struct seq_file *m, void *p)
+{
+	return __s_stop(m, p);
+}
+
 static void
 get_total_entries_cpu(struct array_buffer *buf, unsigned long *total,
 		      unsigned long *entries, int cpu)
@@ -4241,9 +4254,8 @@ static void print_snapshot_help(struct seq_file *m, struct trace_iterator *iter)
 static inline void print_snapshot_help(struct seq_file *m, struct trace_iterator *iter) { }
 #endif
 
-static int s_show(struct seq_file *m, void *v)
+static int __s_show(struct seq_file *m, struct trace_iterator *iter)
 {
-	struct trace_iterator *iter = v;
 	int ret;
 
 	if (iter->ent == NULL) {
@@ -4285,6 +4297,11 @@ static int s_show(struct seq_file *m, void *v)
 	return 0;
 }
 
+static int s_show(struct seq_file *m, void *v)
+{
+	return __s_show(m, v);
+}
+
 /*
  * Should be used after trace_array_get(), trace_types_lock
  * ensures that i_cdev was already initialized.
@@ -4304,23 +4321,17 @@ static const struct seq_operations tracer_seq_ops = {
 };
 
 static struct trace_iterator *
-__tracing_open(struct inode *inode, struct file *file, bool snapshot)
+__tracing_open_iter(struct trace_iterator *iter,
+		    struct trace_array *tr,
+		    struct inode *inode,
+		    bool snapshot)
 {
-	struct trace_array *tr = inode->i_private;
-	struct trace_iterator *iter;
 	int cpu;
 
-	if (tracing_disabled)
-		return ERR_PTR(-ENODEV);
-
-	iter = __seq_open_private(file, &tracer_seq_ops, sizeof(*iter));
-	if (!iter)
-		return ERR_PTR(-ENOMEM);
-
 	iter->buffer_iter = kcalloc(nr_cpu_ids, sizeof(*iter->buffer_iter),
 				    GFP_KERNEL);
 	if (!iter->buffer_iter)
-		goto release;
+		return ERR_PTR(-ENOMEM);
 
 	/*
 	 * trace_find_next_entry() may need to save off iter->ent.
@@ -4411,11 +4422,32 @@ __tracing_open(struct inode *inode, struct file *file, bool snapshot)
 	kfree(iter->trace);
 	kfree(iter->temp);
 	kfree(iter->buffer_iter);
-release:
-	seq_release_private(inode, file);
 	return ERR_PTR(-ENOMEM);
 }
 
+static struct trace_iterator *
+__tracing_open(struct trace_array *tr,
+	       struct inode *inode, struct file *file,
+	       bool snapshot)
+{
+	struct trace_iterator *iter;
+	void *ret;
+
+	if (tracing_disabled)
+		return ERR_PTR(-ENODEV);
+
+	iter = __seq_open_private(file, &tracer_seq_ops, sizeof(*iter));
+	if (!iter)
+		return ERR_PTR(-ENOMEM);
+
+	ret = __tracing_open_iter(iter, tr, inode, snapshot);
+	if (!IS_ERR(ret))
+		return iter;
+
+	seq_release_private(inode, file);
+	return ret;
+}
+
 int tracing_open_generic(struct inode *inode, struct file *filp)
 {
 	int ret;
@@ -4537,7 +4569,7 @@ static int tracing_open(struct inode *inode, struct file *file)
 	}
 
 	if (file->f_mode & FMODE_READ) {
-		iter = __tracing_open(inode, file, false);
+		iter = __tracing_open(tr, inode, file, false);
 		if (IS_ERR(iter))
 			ret = PTR_ERR(iter);
 		else if (tr->trace_flags & TRACE_ITER_LATENCY_FMT)
@@ -6968,7 +7000,7 @@ static int tracing_snapshot_open(struct inode *inode, struct file *file)
 		return ret;
 
 	if (file->f_mode & FMODE_READ) {
-		iter = __tracing_open(inode, file, true);
+		iter = __tracing_open(tr, inode, file, true);
 		if (IS_ERR(iter))
 			ret = PTR_ERR(iter);
 	} else {
@@ -9499,6 +9531,98 @@ int anon_trace_getfd(const char *name, struct trace_array *tr)
 }
 EXPORT_SYMBOL_GPL(anon_trace_getfd);
 
+static int kn_trace_open(struct kernfs_open_file *of)
+{
+	struct trace_array *tr = of->kn->priv;
+	struct trace_iterator *iter;
+	int ret;
+
+	if (tracing_disabled)
+		return -ENODEV;
+
+	ret = tracing_check_open_get_tr(tr);
+	if (ret)
+		return ret;
+
+	of->priv = kzalloc(sizeof(*iter), GFP_KERNEL_ACCOUNT);
+	if (!of->priv)
+		return -ENOMEM;
+
+	iter = __tracing_open_iter(of->priv, tr, NULL, false);
+	if (IS_ERR(iter))
+		ret = PTR_ERR(iter);
+
+	return ret;
+}
+
+static void kn_trace_release(struct kernfs_open_file *of)
+{
+	struct trace_iterator *iter = of->priv;
+
+	if (!iter)
+		return;
+
+	trace_array_put(iter->tr);
+	kfree(iter);
+}
+
+static void *kn_trace_start(struct seq_file *sf, loff_t *pos)
+{
+	struct kernfs_open_file *of = sf->private;
+
+	return __s_start(sf, of->priv, pos);
+}
+
+static void *kn_trace_next(struct seq_file *sf, void *v, loff_t *pos)
+{
+	struct kernfs_open_file *of = sf->private;
+
+	return __s_next(sf, of->priv, v, pos);
+}
+
+static void kn_trace_stop(struct seq_file *sf, void *v)
+{
+	struct kernfs_open_file *of = sf->private;
+
+	return __s_stop(sf, of->priv);
+}
+
+static int kn_trace_show(struct seq_file *sf, void *v)
+{
+	struct kernfs_open_file *of = sf->private;
+
+	return __s_show(sf, of->priv);
+}
+
+static const struct kernfs_ops kn_trace = {
+	.open		= kn_trace_open,
+	.release	= kn_trace_release,
+
+	.seq_start	= kn_trace_start,
+	.seq_next	= kn_trace_next,
+	.seq_stop	= kn_trace_stop,
+	.seq_show	= kn_trace_show,
+};
+
+int trace_create_kernfs(struct kernfs_node *parent,
+			const char *name,
+			umode_t mode,
+			kuid_t uid,
+			kgid_t gid,
+			struct trace_array *tr)
+{
+	struct lock_class_key key;
+	struct kernfs_node *kn;
+
+	if (!tr)
+		return 0;
+
+	kn = __kernfs_create_file(parent, name, mode, uid, gid, 0,
+				  &kn_trace, tr, NULL, &key);
+	return PTR_ERR_OR_ZERO(kn);
+}
+EXPORT_SYMBOL_GPL(trace_create_kernfs);
+
 int trace_run_command(const char *buf, int (*createfn)(int, char **))
 {
 	char **argv;
-- 
2.20.1



More information about the Intel-gfx-trybot mailing list