[PATCH 13/15] kn-trace
Chris Wilson
chris at chris-wilson.co.uk
Tue Jan 19 00:31:22 UTC 2021
---
include/linux/trace.h | 10 +++
kernel/trace/trace.c | 178 +++++++++++++++++++++++++++++++++++-------
2 files changed, 161 insertions(+), 27 deletions(-)
diff --git a/include/linux/trace.h b/include/linux/trace.h
index a4634fa546bb..8acbfbeea920 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 5a7d1a942056..95771e7bcc86 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,8 @@ 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 trace_iterator *iter, void *v, loff_t *pos)
{
- struct trace_iterator *iter = m->private;
int i = (int)*pos;
void *ent;
@@ -3636,6 +3636,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->private, v, pos);
+}
+
void tracing_iter_reset(struct trace_iterator *iter, int cpu)
{
struct ring_buffer_iter *buf_iter;
@@ -3669,9 +3674,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 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 +3713,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(iter, p, &l))
;
} else {
@@ -3721,7 +3725,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(iter, p, &l);
}
}
@@ -3730,10 +3734,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->private, pos);
+}
+static void __s_stop(struct trace_iterator *iter)
+{
#ifdef CONFIG_TRACER_MAX_TRACE
if (iter->snapshot && iter->trace->use_max_tr)
return;
@@ -3746,6 +3753,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->private);
+}
+
static void
get_total_entries_cpu(struct array_buffer *buf, unsigned long *total,
unsigned long *entries, int cpu)
@@ -4241,9 +4253,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 +4296,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.
@@ -4303,24 +4319,18 @@ static const struct seq_operations tracer_seq_ops = {
.show = s_show,
};
-static struct trace_iterator *
-__tracing_open(struct inode *inode, struct file *file, bool snapshot)
+static int
+__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 -ENOMEM;
/*
* trace_find_next_entry() may need to save off iter->ent.
@@ -4404,16 +4414,37 @@ __tracing_open(struct inode *inode, struct file *file, bool snapshot)
mutex_unlock(&trace_types_lock);
- return iter;
+ return 0;
fail:
mutex_unlock(&trace_types_lock);
kfree(iter->trace);
kfree(iter->temp);
kfree(iter->buffer_iter);
-release:
+ return -ENOMEM;
+}
+
+static struct trace_iterator *
+__tracing_open(struct trace_array *tr,
+ struct inode *inode, struct file *file,
+ bool snapshot)
+{
+ struct trace_iterator *iter;
+ int 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 (!ret)
+ return iter;
+
seq_release_private(inode, file);
- return ERR_PTR(-ENOMEM);
+ return ERR_PTR(ret);
}
int tracing_open_generic(struct inode *inode, struct file *filp)
@@ -4537,7 +4568,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 +6999,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 {
@@ -9501,6 +9532,99 @@ 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;
+
+ ret = __tracing_open_iter(of->priv, tr, NULL, false);
+ if (ret) {
+ kfree(of->priv);
+ trace_array_put(tr);
+ }
+
+ 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(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(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(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)
+{
+ static 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