linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [for-next][PATCH 0/5] tracing: Addition of set_event_pid
@ 2015-10-29  7:07 Steven Rostedt
  2015-10-29  7:07 ` [for-next][PATCH 1/5] tracepoint: Give priority to probes of tracepoints Steven Rostedt
                   ` (4 more replies)
  0 siblings, 5 replies; 14+ messages in thread
From: Steven Rostedt @ 2015-10-29  7:07 UTC (permalink / raw)
  To: linux-kernel; +Cc: Ingo Molnar, Andrew Morton

Allowing for fork and exit to modify this list will have to wait til
4.5, as that code is much more complex and needs a release cycle to
go in. I at least want to have the pid file added for trace-cmd to
use (and modify itself). The static updates are not that complex.
And 4.4 is a LTS kernel (wink to Greg KH for his early announcement).

  git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git
for-next

Head SHA1: fb662288284e8f2ec26f13d50a6b0d5781771648


Steven Rostedt (Red Hat) (5):
      tracepoint: Give priority to probes of tracepoints
      tracing: Add set_event_pid directory for future use
      tracing: Implement event pid filtering
      tracing: Check all tasks on each CPU when filtering pids
      tracing: Fix sparse RCU warning

----
 include/linux/trace_events.h |   7 +
 include/linux/tracepoint.h   |  13 ++
 kernel/trace/trace.h         |   9 +
 kernel/trace/trace_events.c  | 453 +++++++++++++++++++++++++++++++++++++++++++
 kernel/tracepoint.c          |  61 ++++--
 5 files changed, 532 insertions(+), 11 deletions(-)

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [for-next][PATCH 1/5] tracepoint: Give priority to probes of tracepoints
  2015-10-29  7:07 [for-next][PATCH 0/5] tracing: Addition of set_event_pid Steven Rostedt
@ 2015-10-29  7:07 ` Steven Rostedt
  2015-10-29 17:52   ` Mathieu Desnoyers
  2015-10-29  7:07 ` [for-next][PATCH 2/5] tracing: Add set_event_pid directory for future use Steven Rostedt
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 14+ messages in thread
From: Steven Rostedt @ 2015-10-29  7:07 UTC (permalink / raw)
  To: linux-kernel; +Cc: Ingo Molnar, Andrew Morton, Mathieu Desnoyers

[-- Attachment #1: 0001-tracepoint-Give-priority-to-probes-of-tracepoints.patch --]
[-- Type: text/plain, Size: 7051 bytes --]

From: "Steven Rostedt (Red Hat)" <rostedt@goodmis.org>

In order to guarantee that a probe will be called before other probes that
are attached to a tracepoint, there needs to be a mechanism to provide
priority of one probe over the others.

Adding a prio field to the struct tracepoint_func, which lets the probes be
sorted by the priority set in the structure. If no priority is specified,
then a priority of 10 is given (this is a macro, and perhaps may be changed
in the future).

Now probes may be added to affect other probes that are attached to a
tracepoint with a guaranteed order.

One use case would be to allow tracing of tracepoints be able to filter by
pid. A special (higher priority probe) may be added to the sched_switch
tracepoint and set the necessary flags of the other tracepoints to notify
them if they should be traced or not. In case a tracepoint is enabled at the
sched_switch tracepoint too, the order of the two are not random.

Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
---
 include/linux/tracepoint.h | 13 ++++++++++
 kernel/tracepoint.c        | 61 +++++++++++++++++++++++++++++++++++++---------
 2 files changed, 63 insertions(+), 11 deletions(-)

diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
index afada369c5b7..6b79537a42b1 100644
--- a/include/linux/tracepoint.h
+++ b/include/linux/tracepoint.h
@@ -26,6 +26,7 @@ struct notifier_block;
 struct tracepoint_func {
 	void *func;
 	void *data;
+	int prio;
 };
 
 struct tracepoint {
@@ -42,9 +43,14 @@ struct trace_enum_map {
 	unsigned long		enum_value;
 };
 
+#define TRACEPOINT_DEFAULT_PRIO	10
+
 extern int
 tracepoint_probe_register(struct tracepoint *tp, void *probe, void *data);
 extern int
+tracepoint_probe_register_prio(struct tracepoint *tp, void *probe, void *data,
+			       int prio);
+extern int
 tracepoint_probe_unregister(struct tracepoint *tp, void *probe, void *data);
 extern void
 for_each_kernel_tracepoint(void (*fct)(struct tracepoint *tp, void *priv),
@@ -207,6 +213,13 @@ extern void syscall_unregfunc(void);
 						(void *)probe, data);	\
 	}								\
 	static inline int						\
+	register_trace_prio_##name(void (*probe)(data_proto), void *data,\
+				   int prio)				\
+	{								\
+		return tracepoint_probe_register_prio(&__tracepoint_##name, \
+					      (void *)probe, data, prio); \
+	}								\
+	static inline int						\
 	unregister_trace_##name(void (*probe)(data_proto), void *data)	\
 	{								\
 		return tracepoint_probe_unregister(&__tracepoint_##name,\
diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c
index 3490407dc7b7..ecd536de603a 100644
--- a/kernel/tracepoint.c
+++ b/kernel/tracepoint.c
@@ -91,11 +91,13 @@ static void debug_print_probes(struct tracepoint_func *funcs)
 		printk(KERN_DEBUG "Probe %d : %p\n", i, funcs[i].func);
 }
 
-static struct tracepoint_func *func_add(struct tracepoint_func **funcs,
-		struct tracepoint_func *tp_func)
+static struct tracepoint_func *
+func_add(struct tracepoint_func **funcs, struct tracepoint_func *tp_func,
+	 int prio)
 {
-	int nr_probes = 0;
 	struct tracepoint_func *old, *new;
+	int nr_probes = 0;
+	int pos = -1;
 
 	if (WARN_ON(!tp_func->func))
 		return ERR_PTR(-EINVAL);
@@ -104,18 +106,33 @@ static struct tracepoint_func *func_add(struct tracepoint_func **funcs,
 	old = *funcs;
 	if (old) {
 		/* (N -> N+1), (N != 0, 1) probes */
-		for (nr_probes = 0; old[nr_probes].func; nr_probes++)
+		for (nr_probes = 0; old[nr_probes].func; nr_probes++) {
+			/* Insert before probes of lower priority */
+			if (pos < 0 && old[nr_probes].prio < prio)
+				pos = nr_probes;
 			if (old[nr_probes].func == tp_func->func &&
 			    old[nr_probes].data == tp_func->data)
 				return ERR_PTR(-EEXIST);
+		}
 	}
 	/* + 2 : one for new probe, one for NULL func */
 	new = allocate_probes(nr_probes + 2);
 	if (new == NULL)
 		return ERR_PTR(-ENOMEM);
-	if (old)
-		memcpy(new, old, nr_probes * sizeof(struct tracepoint_func));
-	new[nr_probes] = *tp_func;
+	if (old) {
+		if (pos < 0) {
+			pos = nr_probes;
+			memcpy(new, old, nr_probes * sizeof(struct tracepoint_func));
+		} else {
+			/* Copy higher priority probes ahead of the new probe */
+			memcpy(new, old, pos * sizeof(struct tracepoint_func));
+			/* Copy the rest after it. */
+			memcpy(new + pos + 1, old + pos,
+			       (nr_probes - pos) * sizeof(struct tracepoint_func));
+		}
+	} else
+		pos = 0;
+	new[pos] = *tp_func;
 	new[nr_probes + 1].func = NULL;
 	*funcs = new;
 	debug_print_probes(*funcs);
@@ -174,7 +191,7 @@ static void *func_remove(struct tracepoint_func **funcs,
  * Add the probe function to a tracepoint.
  */
 static int tracepoint_add_func(struct tracepoint *tp,
-		struct tracepoint_func *func)
+			       struct tracepoint_func *func, int prio)
 {
 	struct tracepoint_func *old, *tp_funcs;
 
@@ -183,7 +200,7 @@ static int tracepoint_add_func(struct tracepoint *tp,
 
 	tp_funcs = rcu_dereference_protected(tp->funcs,
 			lockdep_is_held(&tracepoints_mutex));
-	old = func_add(&tp_funcs, func);
+	old = func_add(&tp_funcs, func, prio);
 	if (IS_ERR(old)) {
 		WARN_ON_ONCE(1);
 		return PTR_ERR(old);
@@ -240,6 +257,7 @@ static int tracepoint_remove_func(struct tracepoint *tp,
  * @tp: tracepoint
  * @probe: probe handler
  * @data: tracepoint data
+ * @prio: priority of this function over other registered functions
  *
  * Returns 0 if ok, error value on error.
  * Note: if @tp is within a module, the caller is responsible for
@@ -247,7 +265,8 @@ static int tracepoint_remove_func(struct tracepoint *tp,
  * performed either with a tracepoint module going notifier, or from
  * within module exit functions.
  */
-int tracepoint_probe_register(struct tracepoint *tp, void *probe, void *data)
+int tracepoint_probe_register_prio(struct tracepoint *tp, void *probe,
+				   void *data, int prio)
 {
 	struct tracepoint_func tp_func;
 	int ret;
@@ -255,10 +274,30 @@ int tracepoint_probe_register(struct tracepoint *tp, void *probe, void *data)
 	mutex_lock(&tracepoints_mutex);
 	tp_func.func = probe;
 	tp_func.data = data;
-	ret = tracepoint_add_func(tp, &tp_func);
+	tp_func.prio = prio;
+	ret = tracepoint_add_func(tp, &tp_func, prio);
 	mutex_unlock(&tracepoints_mutex);
 	return ret;
 }
+EXPORT_SYMBOL_GPL(tracepoint_probe_register_prio);
+
+/**
+ * tracepoint_probe_register -  Connect a probe to a tracepoint
+ * @tp: tracepoint
+ * @probe: probe handler
+ * @data: tracepoint data
+ * @prio: priority of this function over other registered functions
+ *
+ * Returns 0 if ok, error value on error.
+ * Note: if @tp is within a module, the caller is responsible for
+ * unregistering the probe before the module is gone. This can be
+ * performed either with a tracepoint module going notifier, or from
+ * within module exit functions.
+ */
+int tracepoint_probe_register(struct tracepoint *tp, void *probe, void *data)
+{
+	return tracepoint_probe_register_prio(tp, probe, data, TRACEPOINT_DEFAULT_PRIO);
+}
 EXPORT_SYMBOL_GPL(tracepoint_probe_register);
 
 /**
-- 
2.6.1



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [for-next][PATCH 2/5] tracing: Add set_event_pid directory for future use
  2015-10-29  7:07 [for-next][PATCH 0/5] tracing: Addition of set_event_pid Steven Rostedt
  2015-10-29  7:07 ` [for-next][PATCH 1/5] tracepoint: Give priority to probes of tracepoints Steven Rostedt
@ 2015-10-29  7:07 ` Steven Rostedt
  2015-11-19 23:24   ` Paul E. McKenney
  2015-10-29  7:07 ` [for-next][PATCH 3/5] tracing: Implement event pid filtering Steven Rostedt
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 14+ messages in thread
From: Steven Rostedt @ 2015-10-29  7:07 UTC (permalink / raw)
  To: linux-kernel; +Cc: Ingo Molnar, Andrew Morton, Paul E. McKenney

[-- Attachment #1: 0002-tracing-Add-set_event_pid-directory-for-future-use.patch --]
[-- Type: text/plain, Size: 10507 bytes --]

From: "Steven Rostedt (Red Hat)" <rostedt@goodmis.org>

Create a tracing directory called set_event_pid, which currently has no
function, but will be used to filter all events for the tracing instance or
the pids that are added to the file.

The reason no functionality is added with this commit is that this commit
focuses on the creation and removal of the pids in a safe manner. And tests
can be made against this change to make sure things are correct before
hooking features to the list of pids.

Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
---
 kernel/trace/trace.h        |   7 ++
 kernel/trace/trace_events.c | 287 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 294 insertions(+)

diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index fb8a61c710ea..250481043bb5 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -176,6 +176,12 @@ struct trace_options {
 	struct trace_option_dentry	*topts;
 };
 
+struct trace_pid_list {
+	unsigned int			nr_pids;
+	int				order;
+	pid_t				*pids;
+};
+
 /*
  * The trace array - an array of per-CPU trace arrays. This is the
  * highest level data structure that individual tracers deal with.
@@ -201,6 +207,7 @@ struct trace_array {
 	bool			allocated_snapshot;
 	unsigned long		max_latency;
 #endif
+	struct trace_pid_list	__rcu *filtered_pids;
 	/*
 	 * max_lock is used to protect the swapping of buffers
 	 * when taking a max snapshot. The buffers themselves are
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index d120cfe3cca7..2ad7014707ee 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -15,8 +15,10 @@
 #include <linux/kthread.h>
 #include <linux/tracefs.h>
 #include <linux/uaccess.h>
+#include <linux/bsearch.h>
 #include <linux/module.h>
 #include <linux/ctype.h>
+#include <linux/sort.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
 
@@ -445,6 +447,43 @@ static void ftrace_clear_events(struct trace_array *tr)
 	mutex_unlock(&event_mutex);
 }
 
+static int cmp_pid(const void *key, const void *elt)
+{
+	const pid_t *search_pid = key;
+	const pid_t *pid = elt;
+
+	if (*search_pid == *pid)
+		return 0;
+	if (*search_pid < *pid)
+		return -1;
+	return 1;
+}
+
+static void __ftrace_clear_event_pids(struct trace_array *tr)
+{
+	struct trace_pid_list *pid_list;
+
+	pid_list = rcu_dereference_protected(tr->filtered_pids,
+					     lockdep_is_held(&event_mutex));
+	if (!pid_list)
+		return;
+
+	rcu_assign_pointer(tr->filtered_pids, NULL);
+
+	/* Wait till all users are no longer using pid filtering */
+	synchronize_sched();
+
+	free_pages((unsigned long)pid_list->pids, pid_list->order);
+	kfree(pid_list);
+}
+
+static void ftrace_clear_event_pids(struct trace_array *tr)
+{
+	mutex_lock(&event_mutex);
+	__ftrace_clear_event_pids(tr);
+	mutex_unlock(&event_mutex);
+}
+
 static void __put_system(struct event_subsystem *system)
 {
 	struct event_filter *filter = system->filter;
@@ -777,6 +816,56 @@ static void t_stop(struct seq_file *m, void *p)
 	mutex_unlock(&event_mutex);
 }
 
+static void *p_start(struct seq_file *m, loff_t *pos)
+{
+	struct trace_pid_list *pid_list;
+	struct trace_array *tr = m->private;
+
+	/*
+	 * Grab the mutex, to keep calls to p_next() having the same
+	 * tr->filtered_pids as p_start() has.
+	 * If we just passed the tr->filtered_pids around, then RCU would
+	 * have been enough, but doing that makes things more complex.
+	 */
+	mutex_lock(&event_mutex);
+	rcu_read_lock_sched();
+
+	pid_list = rcu_dereference_sched(tr->filtered_pids);
+
+	if (!pid_list || *pos >= pid_list->nr_pids)
+		return NULL;
+
+	return (void *)&pid_list->pids[*pos];
+}
+
+static void p_stop(struct seq_file *m, void *p)
+{
+	rcu_read_unlock_sched();
+	mutex_unlock(&event_mutex);
+}
+
+static void *
+p_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	struct trace_array *tr = m->private;
+	struct trace_pid_list *pid_list = rcu_dereference_sched(tr->filtered_pids);
+
+	(*pos)++;
+
+	if (*pos >= pid_list->nr_pids)
+		return NULL;
+
+	return (void *)&pid_list->pids[*pos];
+}
+
+static int p_show(struct seq_file *m, void *v)
+{
+	pid_t *pid = v;
+
+	seq_printf(m, "%d\n", *pid);
+	return 0;
+}
+
 static ssize_t
 event_enable_read(struct file *filp, char __user *ubuf, size_t cnt,
 		  loff_t *ppos)
@@ -1334,8 +1423,165 @@ show_header(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
 	return r;
 }
 
+static int max_pids(struct trace_pid_list *pid_list)
+{
+	return (PAGE_SIZE << pid_list->order) / sizeof(pid_t);
+}
+
+static ssize_t
+ftrace_event_pid_write(struct file *file, const char __user *ubuf,
+		       size_t cnt, loff_t *ppos)
+{
+	struct seq_file *m = file->private_data;
+	struct trace_array *tr = m->private;
+	struct trace_pid_list *filtered_pids = NULL;
+	struct trace_pid_list *pid_list = NULL;
+	struct trace_parser parser;
+	unsigned long val;
+	loff_t this_pos;
+	ssize_t read = 0;
+	ssize_t ret = 0;
+	pid_t pid;
+	int i;
+
+	if (!cnt)
+		return 0;
+
+	ret = tracing_update_buffers();
+	if (ret < 0)
+		return ret;
+
+	if (trace_parser_get_init(&parser, EVENT_BUF_SIZE + 1))
+		return -ENOMEM;
+
+	mutex_lock(&event_mutex);
+	/*
+	 * Load as many pids into the array before doing a
+	 * swap from the tr->filtered_pids to the new list.
+	 */
+	while (cnt > 0) {
+
+		this_pos = 0;
+
+		ret = trace_get_user(&parser, ubuf, cnt, &this_pos);
+		if (ret < 0 || !trace_parser_loaded(&parser))
+			break;
+
+		read += ret;
+		ubuf += ret;
+		cnt -= ret;
+
+		parser.buffer[parser.idx] = 0;
+
+		ret = -EINVAL;
+		if (kstrtoul(parser.buffer, 0, &val))
+			break;
+		if (val > INT_MAX)
+			break;
+
+		pid = (pid_t)val;
+
+		ret = -ENOMEM;
+		if (!pid_list) {
+			pid_list = kmalloc(sizeof(*pid_list), GFP_KERNEL);
+			if (!pid_list)
+				break;
+
+			filtered_pids = rcu_dereference_protected(tr->filtered_pids,
+							lockdep_is_held(&event_mutex));
+			if (filtered_pids)
+				pid_list->order = filtered_pids->order;
+			else
+				pid_list->order = 0;
+
+			pid_list->pids = (void *)__get_free_pages(GFP_KERNEL,
+								  pid_list->order);
+			if (!pid_list->pids)
+				break;
+
+			if (filtered_pids) {
+				pid_list->nr_pids = filtered_pids->nr_pids;
+				memcpy(pid_list->pids, filtered_pids->pids,
+				       pid_list->nr_pids * sizeof(pid_t));
+			} else
+				pid_list->nr_pids = 0;
+		}
+
+		if (pid_list->nr_pids >= max_pids(pid_list)) {
+			pid_t *pid_page;
+
+			pid_page = (void *)__get_free_pages(GFP_KERNEL,
+							    pid_list->order + 1);
+			if (!pid_page)
+				break;
+			memcpy(pid_page, pid_list->pids,
+			       pid_list->nr_pids * sizeof(pid_t));
+			free_pages((unsigned long)pid_list->pids, pid_list->order);
+
+			pid_list->order++;
+			pid_list->pids = pid_page;
+		}
+
+		pid_list->pids[pid_list->nr_pids++] = pid;
+		trace_parser_clear(&parser);
+		ret = 0;
+	}
+	trace_parser_put(&parser);
+
+	if (ret < 0) {
+		if (pid_list)
+			free_pages((unsigned long)pid_list->pids, pid_list->order);
+		kfree(pid_list);
+		mutex_unlock(&event_mutex);
+		return ret;
+	}
+
+	if (!pid_list) {
+		mutex_unlock(&event_mutex);
+		return ret;
+	}
+
+	sort(pid_list->pids, pid_list->nr_pids, sizeof(pid_t), cmp_pid, NULL);
+
+	/* Remove duplicates */
+	for (i = 1; i < pid_list->nr_pids; i++) {
+		int start = i;
+
+		while (i < pid_list->nr_pids &&
+		       pid_list->pids[i - 1] == pid_list->pids[i])
+			i++;
+
+		if (start != i) {
+			if (i < pid_list->nr_pids) {
+				memmove(&pid_list->pids[start], &pid_list->pids[i],
+					(pid_list->nr_pids - i) * sizeof(pid_t));
+				pid_list->nr_pids -= i - start;
+				i = start;
+			} else
+				pid_list->nr_pids = start;
+		}
+	}
+
+	rcu_assign_pointer(tr->filtered_pids, pid_list);
+
+	mutex_unlock(&event_mutex);
+
+	if (filtered_pids) {
+		synchronize_sched();
+
+		free_pages((unsigned long)filtered_pids->pids, filtered_pids->order);
+		kfree(filtered_pids);
+	}
+
+	ret = read;
+	*ppos += read;
+
+	return ret;
+}
+
 static int ftrace_event_avail_open(struct inode *inode, struct file *file);
 static int ftrace_event_set_open(struct inode *inode, struct file *file);
+static int ftrace_event_set_pid_open(struct inode *inode, struct file *file);
 static int ftrace_event_release(struct inode *inode, struct file *file);
 
 static const struct seq_operations show_event_seq_ops = {
@@ -1352,6 +1598,13 @@ static const struct seq_operations show_set_event_seq_ops = {
 	.stop = t_stop,
 };
 
+static const struct seq_operations show_set_pid_seq_ops = {
+	.start = p_start,
+	.next = p_next,
+	.show = p_show,
+	.stop = p_stop,
+};
+
 static const struct file_operations ftrace_avail_fops = {
 	.open = ftrace_event_avail_open,
 	.read = seq_read,
@@ -1367,6 +1620,14 @@ static const struct file_operations ftrace_set_event_fops = {
 	.release = ftrace_event_release,
 };
 
+static const struct file_operations ftrace_set_event_pid_fops = {
+	.open = ftrace_event_set_pid_open,
+	.read = seq_read,
+	.write = ftrace_event_pid_write,
+	.llseek = seq_lseek,
+	.release = ftrace_event_release,
+};
+
 static const struct file_operations ftrace_enable_fops = {
 	.open = tracing_open_generic,
 	.read = event_enable_read,
@@ -1477,6 +1738,26 @@ ftrace_event_set_open(struct inode *inode, struct file *file)
 	return ret;
 }
 
+static int
+ftrace_event_set_pid_open(struct inode *inode, struct file *file)
+{
+	const struct seq_operations *seq_ops = &show_set_pid_seq_ops;
+	struct trace_array *tr = inode->i_private;
+	int ret;
+
+	if (trace_array_get(tr) < 0)
+		return -ENODEV;
+
+	if ((file->f_mode & FMODE_WRITE) &&
+	    (file->f_flags & O_TRUNC))
+		ftrace_clear_event_pids(tr);
+
+	ret = ftrace_event_open(inode, file, seq_ops);
+	if (ret < 0)
+		trace_array_put(tr);
+	return ret;
+}
+
 static struct event_subsystem *
 create_new_subsystem(const char *name)
 {
@@ -2471,6 +2752,9 @@ create_event_toplevel_files(struct dentry *parent, struct trace_array *tr)
 		return -ENOMEM;
 	}
 
+	entry = tracefs_create_file("set_event_pid", 0644, parent,
+				    tr, &ftrace_set_event_pid_fops);
+
 	/* ring buffer internal formats */
 	trace_create_file("header_page", 0444, d_events,
 			  ring_buffer_print_page_header,
@@ -2551,6 +2835,9 @@ int event_trace_del_tracer(struct trace_array *tr)
 	/* Disable any event triggers and associated soft-disabled events */
 	clear_event_triggers(tr);
 
+	/* Clear the pid list */
+	__ftrace_clear_event_pids(tr);
+
 	/* Disable any running events */
 	__ftrace_set_clr_event_nolock(tr, NULL, NULL, NULL, 0);
 
-- 
2.6.1



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [for-next][PATCH 3/5] tracing: Implement event pid filtering
  2015-10-29  7:07 [for-next][PATCH 0/5] tracing: Addition of set_event_pid Steven Rostedt
  2015-10-29  7:07 ` [for-next][PATCH 1/5] tracepoint: Give priority to probes of tracepoints Steven Rostedt
  2015-10-29  7:07 ` [for-next][PATCH 2/5] tracing: Add set_event_pid directory for future use Steven Rostedt
@ 2015-10-29  7:07 ` Steven Rostedt
  2015-10-29  7:07 ` [for-next][PATCH 4/5] tracing: Check all tasks on each CPU when filtering pids Steven Rostedt
  2015-10-29  7:07 ` [for-next][PATCH 5/5] tracing: Fix sparse RCU warning Steven Rostedt
  4 siblings, 0 replies; 14+ messages in thread
From: Steven Rostedt @ 2015-10-29  7:07 UTC (permalink / raw)
  To: linux-kernel; +Cc: Ingo Molnar, Andrew Morton, Paul E. McKenney

[-- Attachment #1: 0003-tracing-Implement-event-pid-filtering.patch --]
[-- Type: text/plain, Size: 9613 bytes --]

From: "Steven Rostedt (Red Hat)" <rostedt@goodmis.org>

Add the necessary hooks to use the pids loaded in set_event_pid to filter
all the events enabled in the tracing instance that match the pids listed.

Two probes are added to both sched_switch and sched_wakeup tracepoints to be
called before other probes are called and after the other probes are called.
The first is used to set the necessary flags to let the probes know to test
if they should be traced or not.

The sched_switch pre probe will set the "ignore_pid" flag if neither the
previous or next task has a matching pid.

The sched_switch probe will set the "ignore_pid" flag if the next task
does not match the matching pid.

The pre probe allows for probes tracing sched_switch to be traced if
necessary.

The sched_wakeup pre probe will set the "ignore_pid" flag if neither the
current task nor the wakee task has a matching pid.

The sched_wakeup post probe will set the "ignore_pid" flag if the current
task does not have a matching pid.

Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
---
 include/linux/trace_events.h |   7 ++
 kernel/trace/trace.h         |   2 +
 kernel/trace/trace_events.c  | 148 ++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 154 insertions(+), 3 deletions(-)

diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h
index f85693bbcdc3..429fdfc3baf5 100644
--- a/include/linux/trace_events.h
+++ b/include/linux/trace_events.h
@@ -328,6 +328,7 @@ enum {
 	EVENT_FILE_FL_SOFT_DISABLED_BIT,
 	EVENT_FILE_FL_TRIGGER_MODE_BIT,
 	EVENT_FILE_FL_TRIGGER_COND_BIT,
+	EVENT_FILE_FL_PID_FILTER_BIT,
 };
 
 /*
@@ -341,6 +342,7 @@ enum {
  *                   tracepoint may be enabled)
  *  TRIGGER_MODE  - When set, invoke the triggers associated with the event
  *  TRIGGER_COND  - When set, one or more triggers has an associated filter
+ *  PID_FILTER    - When set, the event is filtered based on pid
  */
 enum {
 	EVENT_FILE_FL_ENABLED		= (1 << EVENT_FILE_FL_ENABLED_BIT),
@@ -351,6 +353,7 @@ enum {
 	EVENT_FILE_FL_SOFT_DISABLED	= (1 << EVENT_FILE_FL_SOFT_DISABLED_BIT),
 	EVENT_FILE_FL_TRIGGER_MODE	= (1 << EVENT_FILE_FL_TRIGGER_MODE_BIT),
 	EVENT_FILE_FL_TRIGGER_COND	= (1 << EVENT_FILE_FL_TRIGGER_COND_BIT),
+	EVENT_FILE_FL_PID_FILTER	= (1 << EVENT_FILE_FL_PID_FILTER_BIT),
 };
 
 struct trace_event_file {
@@ -429,6 +432,8 @@ extern enum event_trigger_type event_triggers_call(struct trace_event_file *file
 extern void event_triggers_post_call(struct trace_event_file *file,
 				     enum event_trigger_type tt);
 
+bool trace_event_ignore_this_pid(struct trace_event_file *trace_file);
+
 /**
  * trace_trigger_soft_disabled - do triggers and test if soft disabled
  * @file: The file pointer of the event to test
@@ -448,6 +453,8 @@ trace_trigger_soft_disabled(struct trace_event_file *file)
 			event_triggers_call(file, NULL);
 		if (eflags & EVENT_FILE_FL_SOFT_DISABLED)
 			return true;
+		if (eflags & EVENT_FILE_FL_PID_FILTER)
+			return trace_event_ignore_this_pid(file);
 	}
 	return false;
 }
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 250481043bb5..89ffdaf3e371 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -156,6 +156,8 @@ struct trace_array_cpu {
 	pid_t			pid;
 	kuid_t			uid;
 	char			comm[TASK_COMM_LEN];
+
+	bool			ignore_pid;
 };
 
 struct tracer;
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 2ad7014707ee..ab07058e27c1 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -22,6 +22,8 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 
+#include <trace/events/sched.h>
+
 #include <asm/setup.h>
 
 #include "trace_output.h"
@@ -212,12 +214,32 @@ int trace_event_raw_init(struct trace_event_call *call)
 }
 EXPORT_SYMBOL_GPL(trace_event_raw_init);
 
+bool trace_event_ignore_this_pid(struct trace_event_file *trace_file)
+{
+	struct trace_array *tr = trace_file->tr;
+	struct trace_array_cpu *data;
+	struct trace_pid_list *pid_list;
+
+	pid_list = rcu_dereference_sched(tr->filtered_pids);
+	if (!pid_list)
+		return false;
+
+	data = this_cpu_ptr(tr->trace_buffer.data);
+
+	return data->ignore_pid;
+}
+EXPORT_SYMBOL_GPL(trace_event_ignore_this_pid);
+
 void *trace_event_buffer_reserve(struct trace_event_buffer *fbuffer,
 				 struct trace_event_file *trace_file,
 				 unsigned long len)
 {
 	struct trace_event_call *event_call = trace_file->event_call;
 
+	if ((trace_file->flags & EVENT_FILE_FL_PID_FILTER) &&
+	    trace_event_ignore_this_pid(trace_file))
+		return NULL;
+
 	local_save_flags(fbuffer->flags);
 	fbuffer->pc = preempt_count();
 	fbuffer->trace_file = trace_file;
@@ -459,15 +481,114 @@ static int cmp_pid(const void *key, const void *elt)
 	return 1;
 }
 
+static bool
+check_ignore_pid(struct trace_pid_list *filtered_pids, struct task_struct *task)
+{
+	pid_t search_pid;
+	pid_t *pid;
+
+	/*
+	 * Return false, because if filtered_pids does not exist,
+	 * all pids are good to trace.
+	 */
+	if (!filtered_pids)
+		return false;
+
+	search_pid = task->pid;
+
+	pid = bsearch(&search_pid, filtered_pids->pids,
+		      filtered_pids->nr_pids, sizeof(pid_t),
+		      cmp_pid);
+	if (!pid)
+		return true;
+
+	return false;
+}
+
+static void
+event_filter_pid_sched_switch_probe_pre(void *data,
+		    struct task_struct *prev, struct task_struct *next)
+{
+	struct trace_array *tr = data;
+	struct trace_pid_list *pid_list;
+
+	pid_list = rcu_dereference_sched(tr->filtered_pids);
+
+	this_cpu_write(tr->trace_buffer.data->ignore_pid,
+		       check_ignore_pid(pid_list, prev) &&
+		       check_ignore_pid(pid_list, next));
+}
+
+static void
+event_filter_pid_sched_switch_probe_post(void *data,
+		    struct task_struct *prev, struct task_struct *next)
+{
+	struct trace_array *tr = data;
+	struct trace_pid_list *pid_list;
+
+	pid_list = rcu_dereference_sched(tr->filtered_pids);
+
+	this_cpu_write(tr->trace_buffer.data->ignore_pid,
+		       check_ignore_pid(pid_list, next));
+}
+
+static void
+event_filter_pid_sched_wakeup_probe_pre(void *data, struct task_struct *task)
+{
+	struct trace_array *tr = data;
+	struct trace_pid_list *pid_list;
+
+	/* Nothing to do if we are already tracing */
+	if (!this_cpu_read(tr->trace_buffer.data->ignore_pid))
+		return;
+
+	pid_list = rcu_dereference_sched(tr->filtered_pids);
+
+	this_cpu_write(tr->trace_buffer.data->ignore_pid,
+		       check_ignore_pid(pid_list, task));
+}
+
+static void
+event_filter_pid_sched_wakeup_probe_post(void *data, struct task_struct *task)
+{
+	struct trace_array *tr = data;
+	struct trace_pid_list *pid_list;
+
+	/* Nothing to do if we are not tracing */
+	if (this_cpu_read(tr->trace_buffer.data->ignore_pid))
+		return;
+
+	pid_list = rcu_dereference_sched(tr->filtered_pids);
+
+	/* Set tracing if current is enabled */
+	this_cpu_write(tr->trace_buffer.data->ignore_pid,
+		       check_ignore_pid(pid_list, current));
+}
+
 static void __ftrace_clear_event_pids(struct trace_array *tr)
 {
 	struct trace_pid_list *pid_list;
+	struct trace_event_file *file;
+	int cpu;
 
 	pid_list = rcu_dereference_protected(tr->filtered_pids,
 					     lockdep_is_held(&event_mutex));
 	if (!pid_list)
 		return;
 
+	unregister_trace_sched_switch(event_filter_pid_sched_switch_probe_pre, tr);
+	unregister_trace_sched_switch(event_filter_pid_sched_switch_probe_post, tr);
+
+	unregister_trace_sched_wakeup(event_filter_pid_sched_wakeup_probe_pre, tr);
+	unregister_trace_sched_wakeup(event_filter_pid_sched_wakeup_probe_post, tr);
+
+	list_for_each_entry(file, &tr->events, list) {
+		clear_bit(EVENT_FILE_FL_PID_FILTER_BIT, &file->flags);
+	}
+
+	for_each_possible_cpu(cpu)
+		per_cpu_ptr(tr->trace_buffer.data, cpu)->ignore_pid = false;
+
 	rcu_assign_pointer(tr->filtered_pids, NULL);
 
 	/* Wait till all users are no longer using pid filtering */
@@ -1429,13 +1550,14 @@ static int max_pids(struct trace_pid_list *pid_list)
 }
 
 static ssize_t
-ftrace_event_pid_write(struct file *file, const char __user *ubuf,
+ftrace_event_pid_write(struct file *filp, const char __user *ubuf,
 		       size_t cnt, loff_t *ppos)
 {
-	struct seq_file *m = file->private_data;
+	struct seq_file *m = filp->private_data;
 	struct trace_array *tr = m->private;
 	struct trace_pid_list *filtered_pids = NULL;
 	struct trace_pid_list *pid_list = NULL;
+	struct trace_event_file *file;
 	struct trace_parser parser;
 	unsigned long val;
 	loff_t this_pos;
@@ -1564,15 +1686,35 @@ ftrace_event_pid_write(struct file *file, const char __user *ubuf,
 
 	rcu_assign_pointer(tr->filtered_pids, pid_list);
 
-	mutex_unlock(&event_mutex);
+	list_for_each_entry(file, &tr->events, list) {
+		set_bit(EVENT_FILE_FL_PID_FILTER_BIT, &file->flags);
+	}
 
 	if (filtered_pids) {
 		synchronize_sched();
 
 		free_pages((unsigned long)filtered_pids->pids, filtered_pids->order);
 		kfree(filtered_pids);
+	} else {
+		/*
+		 * Register a probe that is called before all other probes
+		 * to set ignore_pid if next or prev do not match.
+		 * Register a probe this is called after all other probes
+		 * to only keep ignore_pid set if next pid matches.
+		 */
+		register_trace_prio_sched_switch(event_filter_pid_sched_switch_probe_pre,
+						 tr, INT_MAX);
+		register_trace_prio_sched_switch(event_filter_pid_sched_switch_probe_post,
+						 tr, 0);
+
+		register_trace_prio_sched_wakeup(event_filter_pid_sched_wakeup_probe_pre,
+						 tr, INT_MAX);
+		register_trace_prio_sched_wakeup(event_filter_pid_sched_wakeup_probe_post,
+						 tr, 0);
 	}
 
+	mutex_unlock(&event_mutex);
+
 	ret = read;
 	*ppos += read;
 
-- 
2.6.1



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [for-next][PATCH 4/5] tracing: Check all tasks on each CPU when filtering pids
  2015-10-29  7:07 [for-next][PATCH 0/5] tracing: Addition of set_event_pid Steven Rostedt
                   ` (2 preceding siblings ...)
  2015-10-29  7:07 ` [for-next][PATCH 3/5] tracing: Implement event pid filtering Steven Rostedt
@ 2015-10-29  7:07 ` Steven Rostedt
  2015-10-30  6:16   ` Jiaxing Wang
  2015-10-29  7:07 ` [for-next][PATCH 5/5] tracing: Fix sparse RCU warning Steven Rostedt
  4 siblings, 1 reply; 14+ messages in thread
From: Steven Rostedt @ 2015-10-29  7:07 UTC (permalink / raw)
  To: linux-kernel; +Cc: Ingo Molnar, Andrew Morton

[-- Attachment #1: 0004-tracing-Check-all-tasks-on-each-CPU-when-filtering-p.patch --]
[-- Type: text/plain, Size: 1735 bytes --]

From: "Steven Rostedt (Red Hat)" <rostedt@goodmis.org>

My tests found that if a task is running but not filtered when set_event_pid
is modified, then it can still be traced.

Call on_each_cpu() to check if the current running task should be filtered
and update the per cpu flags of tr->data appropriately.

Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
---
 kernel/trace/trace_events.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index ab07058e27c1..2b7fccd499c6 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -1549,6 +1549,22 @@ static int max_pids(struct trace_pid_list *pid_list)
 	return (PAGE_SIZE << pid_list->order) / sizeof(pid_t);
 }
 
+static void ignore_task_cpu(void *data)
+{
+	struct trace_array *tr = data;
+	struct trace_pid_list *pid_list;
+
+	/*
+	 * This function is called by on_each_cpu() while the
+	 * event_mutex is held.
+	 */
+	pid_list = rcu_dereference_protected(tr->filtered_pids,
+					     mutex_is_locked(&event_mutex));
+
+	this_cpu_write(tr->trace_buffer.data->ignore_pid,
+		       check_ignore_pid(pid_list, current));
+}
+
 static ssize_t
 ftrace_event_pid_write(struct file *filp, const char __user *ubuf,
 		       size_t cnt, loff_t *ppos)
@@ -1711,6 +1727,12 @@ ftrace_event_pid_write(struct file *filp, const char __user *ubuf,
 						 tr, INT_MAX);
 		register_trace_prio_sched_wakeup(event_filter_pid_sched_wakeup_probe_post,
 						 tr, 0);
+
+		/*
+		 * Ignoring of pids is done at task switch. But we have to
+		 * check for those tasks that are currently running.
+		 */
+		on_each_cpu(ignore_task_cpu, tr, 1);
 	}
 
 	mutex_unlock(&event_mutex);
-- 
2.6.1



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [for-next][PATCH 5/5] tracing: Fix sparse RCU warning
  2015-10-29  7:07 [for-next][PATCH 0/5] tracing: Addition of set_event_pid Steven Rostedt
                   ` (3 preceding siblings ...)
  2015-10-29  7:07 ` [for-next][PATCH 4/5] tracing: Check all tasks on each CPU when filtering pids Steven Rostedt
@ 2015-10-29  7:07 ` Steven Rostedt
  4 siblings, 0 replies; 14+ messages in thread
From: Steven Rostedt @ 2015-10-29  7:07 UTC (permalink / raw)
  To: linux-kernel; +Cc: Ingo Molnar, Andrew Morton, kbuild test robot

[-- Attachment #1: 0005-tracing-Fix-sparse-RCU-warning.patch --]
[-- Type: text/plain, Size: 1015 bytes --]

From: "Steven Rostedt (Red Hat)" <rostedt@goodmis.org>

p_start() and p_stop() are seq_file functions that match. Teach sparse to
know that rcu_read_lock_sched() that is taken by p_start() is released by
p_stop.

Reported-by: kbuild test robot <fengguang.wu@intel.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
---
 kernel/trace/trace_events.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 2b7fccd499c6..fb0261e90acc 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -938,6 +938,7 @@ static void t_stop(struct seq_file *m, void *p)
 }
 
 static void *p_start(struct seq_file *m, loff_t *pos)
+	__acquires(RCU)
 {
 	struct trace_pid_list *pid_list;
 	struct trace_array *tr = m->private;
@@ -960,6 +961,7 @@ static void *p_start(struct seq_file *m, loff_t *pos)
 }
 
 static void p_stop(struct seq_file *m, void *p)
+	__releases(RCU)
 {
 	rcu_read_unlock_sched();
 	mutex_unlock(&event_mutex);
-- 
2.6.1



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [for-next][PATCH 1/5] tracepoint: Give priority to probes of tracepoints
  2015-10-29  7:07 ` [for-next][PATCH 1/5] tracepoint: Give priority to probes of tracepoints Steven Rostedt
@ 2015-10-29 17:52   ` Mathieu Desnoyers
  2015-10-30 20:25     ` Steven Rostedt
  0 siblings, 1 reply; 14+ messages in thread
From: Mathieu Desnoyers @ 2015-10-29 17:52 UTC (permalink / raw)
  To: rostedt; +Cc: linux-kernel, Ingo Molnar, Andrew Morton

----- On Oct 29, 2015, at 3:07 AM, rostedt rostedt@goodmis.org wrote:

> From: "Steven Rostedt (Red Hat)" <rostedt@goodmis.org>
> 
> In order to guarantee that a probe will be called before other probes that
> are attached to a tracepoint, there needs to be a mechanism to provide
> priority of one probe over the others.
> 
> Adding a prio field to the struct tracepoint_func, which lets the probes be
> sorted by the priority set in the structure. If no priority is specified,
> then a priority of 10 is given (this is a macro, and perhaps may be changed
> in the future).
> 
> Now probes may be added to affect other probes that are attached to a
> tracepoint with a guaranteed order.
> 
> One use case would be to allow tracing of tracepoints be able to filter by
> pid. A special (higher priority probe) may be added to the sched_switch
> tracepoint and set the necessary flags of the other tracepoints to notify
> them if they should be traced or not. In case a tracepoint is enabled at the
> sched_switch tracepoint too, the order of the two are not random.
> 
> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>

Sounds good to me,

Acked-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>

Thanks,

Mathieu

> ---
> include/linux/tracepoint.h | 13 ++++++++++
> kernel/tracepoint.c        | 61 +++++++++++++++++++++++++++++++++++++---------
> 2 files changed, 63 insertions(+), 11 deletions(-)
> 
> diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
> index afada369c5b7..6b79537a42b1 100644
> --- a/include/linux/tracepoint.h
> +++ b/include/linux/tracepoint.h
> @@ -26,6 +26,7 @@ struct notifier_block;
> struct tracepoint_func {
> 	void *func;
> 	void *data;
> +	int prio;
> };
> 
> struct tracepoint {
> @@ -42,9 +43,14 @@ struct trace_enum_map {
> 	unsigned long		enum_value;
> };
> 
> +#define TRACEPOINT_DEFAULT_PRIO	10
> +
> extern int
> tracepoint_probe_register(struct tracepoint *tp, void *probe, void *data);
> extern int
> +tracepoint_probe_register_prio(struct tracepoint *tp, void *probe, void *data,
> +			       int prio);
> +extern int
> tracepoint_probe_unregister(struct tracepoint *tp, void *probe, void *data);
> extern void
> for_each_kernel_tracepoint(void (*fct)(struct tracepoint *tp, void *priv),
> @@ -207,6 +213,13 @@ extern void syscall_unregfunc(void);
> 						(void *)probe, data);	\
> 	}								\
> 	static inline int						\
> +	register_trace_prio_##name(void (*probe)(data_proto), void *data,\
> +				   int prio)				\
> +	{								\
> +		return tracepoint_probe_register_prio(&__tracepoint_##name, \
> +					      (void *)probe, data, prio); \
> +	}								\
> +	static inline int						\
> 	unregister_trace_##name(void (*probe)(data_proto), void *data)	\
> 	{								\
> 		return tracepoint_probe_unregister(&__tracepoint_##name,\
> diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c
> index 3490407dc7b7..ecd536de603a 100644
> --- a/kernel/tracepoint.c
> +++ b/kernel/tracepoint.c
> @@ -91,11 +91,13 @@ static void debug_print_probes(struct tracepoint_func
> *funcs)
> 		printk(KERN_DEBUG "Probe %d : %p\n", i, funcs[i].func);
> }
> 
> -static struct tracepoint_func *func_add(struct tracepoint_func **funcs,
> -		struct tracepoint_func *tp_func)
> +static struct tracepoint_func *
> +func_add(struct tracepoint_func **funcs, struct tracepoint_func *tp_func,
> +	 int prio)
> {
> -	int nr_probes = 0;
> 	struct tracepoint_func *old, *new;
> +	int nr_probes = 0;
> +	int pos = -1;
> 
> 	if (WARN_ON(!tp_func->func))
> 		return ERR_PTR(-EINVAL);
> @@ -104,18 +106,33 @@ static struct tracepoint_func *func_add(struct
> tracepoint_func **funcs,
> 	old = *funcs;
> 	if (old) {
> 		/* (N -> N+1), (N != 0, 1) probes */
> -		for (nr_probes = 0; old[nr_probes].func; nr_probes++)
> +		for (nr_probes = 0; old[nr_probes].func; nr_probes++) {
> +			/* Insert before probes of lower priority */
> +			if (pos < 0 && old[nr_probes].prio < prio)
> +				pos = nr_probes;
> 			if (old[nr_probes].func == tp_func->func &&
> 			    old[nr_probes].data == tp_func->data)
> 				return ERR_PTR(-EEXIST);
> +		}
> 	}
> 	/* + 2 : one for new probe, one for NULL func */
> 	new = allocate_probes(nr_probes + 2);
> 	if (new == NULL)
> 		return ERR_PTR(-ENOMEM);
> -	if (old)
> -		memcpy(new, old, nr_probes * sizeof(struct tracepoint_func));
> -	new[nr_probes] = *tp_func;
> +	if (old) {
> +		if (pos < 0) {
> +			pos = nr_probes;
> +			memcpy(new, old, nr_probes * sizeof(struct tracepoint_func));
> +		} else {
> +			/* Copy higher priority probes ahead of the new probe */
> +			memcpy(new, old, pos * sizeof(struct tracepoint_func));
> +			/* Copy the rest after it. */
> +			memcpy(new + pos + 1, old + pos,
> +			       (nr_probes - pos) * sizeof(struct tracepoint_func));
> +		}
> +	} else
> +		pos = 0;
> +	new[pos] = *tp_func;
> 	new[nr_probes + 1].func = NULL;
> 	*funcs = new;
> 	debug_print_probes(*funcs);
> @@ -174,7 +191,7 @@ static void *func_remove(struct tracepoint_func **funcs,
>  * Add the probe function to a tracepoint.
>  */
> static int tracepoint_add_func(struct tracepoint *tp,
> -		struct tracepoint_func *func)
> +			       struct tracepoint_func *func, int prio)
> {
> 	struct tracepoint_func *old, *tp_funcs;
> 
> @@ -183,7 +200,7 @@ static int tracepoint_add_func(struct tracepoint *tp,
> 
> 	tp_funcs = rcu_dereference_protected(tp->funcs,
> 			lockdep_is_held(&tracepoints_mutex));
> -	old = func_add(&tp_funcs, func);
> +	old = func_add(&tp_funcs, func, prio);
> 	if (IS_ERR(old)) {
> 		WARN_ON_ONCE(1);
> 		return PTR_ERR(old);
> @@ -240,6 +257,7 @@ static int tracepoint_remove_func(struct tracepoint *tp,
>  * @tp: tracepoint
>  * @probe: probe handler
>  * @data: tracepoint data
> + * @prio: priority of this function over other registered functions
>  *
>  * Returns 0 if ok, error value on error.
>  * Note: if @tp is within a module, the caller is responsible for
> @@ -247,7 +265,8 @@ static int tracepoint_remove_func(struct tracepoint *tp,
>  * performed either with a tracepoint module going notifier, or from
>  * within module exit functions.
>  */
> -int tracepoint_probe_register(struct tracepoint *tp, void *probe, void *data)
> +int tracepoint_probe_register_prio(struct tracepoint *tp, void *probe,
> +				   void *data, int prio)
> {
> 	struct tracepoint_func tp_func;
> 	int ret;
> @@ -255,10 +274,30 @@ int tracepoint_probe_register(struct tracepoint *tp, void
> *probe, void *data)
> 	mutex_lock(&tracepoints_mutex);
> 	tp_func.func = probe;
> 	tp_func.data = data;
> -	ret = tracepoint_add_func(tp, &tp_func);
> +	tp_func.prio = prio;
> +	ret = tracepoint_add_func(tp, &tp_func, prio);
> 	mutex_unlock(&tracepoints_mutex);
> 	return ret;
> }
> +EXPORT_SYMBOL_GPL(tracepoint_probe_register_prio);
> +
> +/**
> + * tracepoint_probe_register -  Connect a probe to a tracepoint
> + * @tp: tracepoint
> + * @probe: probe handler
> + * @data: tracepoint data
> + * @prio: priority of this function over other registered functions
> + *
> + * Returns 0 if ok, error value on error.
> + * Note: if @tp is within a module, the caller is responsible for
> + * unregistering the probe before the module is gone. This can be
> + * performed either with a tracepoint module going notifier, or from
> + * within module exit functions.
> + */
> +int tracepoint_probe_register(struct tracepoint *tp, void *probe, void *data)
> +{
> +	return tracepoint_probe_register_prio(tp, probe, data,
> TRACEPOINT_DEFAULT_PRIO);
> +}
> EXPORT_SYMBOL_GPL(tracepoint_probe_register);
> 
> /**
> --
> 2.6.1

-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [for-next][PATCH 4/5] tracing: Check all tasks on each CPU when filtering pids
  2015-10-29  7:07 ` [for-next][PATCH 4/5] tracing: Check all tasks on each CPU when filtering pids Steven Rostedt
@ 2015-10-30  6:16   ` Jiaxing Wang
  2015-10-30 20:28     ` Steven Rostedt
  0 siblings, 1 reply; 14+ messages in thread
From: Jiaxing Wang @ 2015-10-30  6:16 UTC (permalink / raw)
  To: Steven Rostedt; +Cc: linux-kernel, Ingo Molnar, Andrew Morton

On Thu, Oct 29, 2015 at 03:07:58AM -0400, Steven Rostedt wrote:
>  static ssize_t
>  ftrace_event_pid_write(struct file *filp, const char __user *ubuf,
>  		       size_t cnt, loff_t *ppos)
> @@ -1711,6 +1727,12 @@ ftrace_event_pid_write(struct file *filp, const char __user *ubuf,
>  						 tr, INT_MAX);
>  		register_trace_prio_sched_wakeup(event_filter_pid_sched_wakeup_probe_post,
>  						 tr, 0);
> +
> +		/*
> +		 * Ignoring of pids is done at task switch. But we have to
> +		 * check for those tasks that are currently running.
> +		 */
> +		on_each_cpu(ignore_task_cpu, tr, 1);
>  	}
on_each_cpu(ignore_task_cpu, tr, 1); can be put outside of the else
block, then ignore_pid can be updated when appending pid, 
eg. echo 'xxx' >> set_event_pid, in case xxx is running on some cpu.
>  
>  	mutex_unlock(&event_mutex);

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [for-next][PATCH 1/5] tracepoint: Give priority to probes of tracepoints
  2015-10-29 17:52   ` Mathieu Desnoyers
@ 2015-10-30 20:25     ` Steven Rostedt
  2015-10-30 20:49       ` Mathieu Desnoyers
  0 siblings, 1 reply; 14+ messages in thread
From: Steven Rostedt @ 2015-10-30 20:25 UTC (permalink / raw)
  To: Mathieu Desnoyers; +Cc: linux-kernel, Ingo Molnar, Andrew Morton

On Thu, 29 Oct 2015 17:52:16 +0000 (UTC)
Mathieu Desnoyers <mathieu.desnoyers@efficios.com> wrote:

> ----- On Oct 29, 2015, at 3:07 AM, rostedt rostedt@goodmis.org wrote:
> 
> > From: "Steven Rostedt (Red Hat)" <rostedt@goodmis.org>
> > 
> > In order to guarantee that a probe will be called before other probes that
> > are attached to a tracepoint, there needs to be a mechanism to provide
> > priority of one probe over the others.
> > 
> > Adding a prio field to the struct tracepoint_func, which lets the probes be
> > sorted by the priority set in the structure. If no priority is specified,
> > then a priority of 10 is given (this is a macro, and perhaps may be changed
> > in the future).
> > 
> > Now probes may be added to affect other probes that are attached to a
> > tracepoint with a guaranteed order.
> > 
> > One use case would be to allow tracing of tracepoints be able to filter by
> > pid. A special (higher priority probe) may be added to the sched_switch
> > tracepoint and set the necessary flags of the other tracepoints to notify
> > them if they should be traced or not. In case a tracepoint is enabled at the
> > sched_switch tracepoint too, the order of the two are not random.
> > 
> > Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
> > Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
> 
> Sounds good to me,
> 
> Acked-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
> 

Thanks.

Unfortunately I already pushed it out to linux-next (had a deadline),
otherwise I could have added your ack. I'm guessing you missed the RFC
version I posted a week ago.

-- Steve


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [for-next][PATCH 4/5] tracing: Check all tasks on each CPU when filtering pids
  2015-10-30  6:16   ` Jiaxing Wang
@ 2015-10-30 20:28     ` Steven Rostedt
  0 siblings, 0 replies; 14+ messages in thread
From: Steven Rostedt @ 2015-10-30 20:28 UTC (permalink / raw)
  To: Jiaxing Wang; +Cc: linux-kernel, Ingo Molnar, Andrew Morton

On Fri, 30 Oct 2015 14:16:43 +0800
Jiaxing Wang <hello.wjx@gmail.com> wrote:

> On Thu, Oct 29, 2015 at 03:07:58AM -0400, Steven Rostedt wrote:
> >  static ssize_t
> >  ftrace_event_pid_write(struct file *filp, const char __user *ubuf,
> >  		       size_t cnt, loff_t *ppos)
> > @@ -1711,6 +1727,12 @@ ftrace_event_pid_write(struct file *filp, const char __user *ubuf,
> >  						 tr, INT_MAX);
> >  		register_trace_prio_sched_wakeup(event_filter_pid_sched_wakeup_probe_post,
> >  						 tr, 0);
> > +
> > +		/*
> > +		 * Ignoring of pids is done at task switch. But we have to
> > +		 * check for those tasks that are currently running.
> > +		 */
> > +		on_each_cpu(ignore_task_cpu, tr, 1);
> >  	}
> on_each_cpu(ignore_task_cpu, tr, 1); can be put outside of the else
> block, then ignore_pid can be updated when appending pid, 
> eg. echo 'xxx' >> set_event_pid, in case xxx is running on some cpu.

Hmm, I guess I could.

-- Steve

> >  
> >  	mutex_unlock(&event_mutex);


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [for-next][PATCH 1/5] tracepoint: Give priority to probes of tracepoints
  2015-10-30 20:25     ` Steven Rostedt
@ 2015-10-30 20:49       ` Mathieu Desnoyers
  0 siblings, 0 replies; 14+ messages in thread
From: Mathieu Desnoyers @ 2015-10-30 20:49 UTC (permalink / raw)
  To: rostedt; +Cc: linux-kernel, Ingo Molnar, Andrew Morton

----- On Oct 30, 2015, at 4:25 PM, rostedt rostedt@goodmis.org wrote:

> On Thu, 29 Oct 2015 17:52:16 +0000 (UTC)
> Mathieu Desnoyers <mathieu.desnoyers@efficios.com> wrote:
> 
>> ----- On Oct 29, 2015, at 3:07 AM, rostedt rostedt@goodmis.org wrote:
>> 
>> > From: "Steven Rostedt (Red Hat)" <rostedt@goodmis.org>
>> > 
>> > In order to guarantee that a probe will be called before other probes that
>> > are attached to a tracepoint, there needs to be a mechanism to provide
>> > priority of one probe over the others.
>> > 
>> > Adding a prio field to the struct tracepoint_func, which lets the probes be
>> > sorted by the priority set in the structure. If no priority is specified,
>> > then a priority of 10 is given (this is a macro, and perhaps may be changed
>> > in the future).
>> > 
>> > Now probes may be added to affect other probes that are attached to a
>> > tracepoint with a guaranteed order.
>> > 
>> > One use case would be to allow tracing of tracepoints be able to filter by
>> > pid. A special (higher priority probe) may be added to the sched_switch
>> > tracepoint and set the necessary flags of the other tracepoints to notify
>> > them if they should be traced or not. In case a tracepoint is enabled at the
>> > sched_switch tracepoint too, the order of the two are not random.
>> > 
>> > Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
>> > Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
>> 
>> Sounds good to me,
>> 
>> Acked-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
>> 
> 
> Thanks.
> 
> Unfortunately I already pushed it out to linux-next (had a deadline),
> otherwise I could have added your ack. I'm guessing you missed the RFC
> version I posted a week ago.

No worries,

I've seen it, but was busy with other stuff.

Thanks,

Mathieu

> 
> -- Steve

-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [for-next][PATCH 2/5] tracing: Add set_event_pid directory for future use
  2015-10-29  7:07 ` [for-next][PATCH 2/5] tracing: Add set_event_pid directory for future use Steven Rostedt
@ 2015-11-19 23:24   ` Paul E. McKenney
  2015-11-20  4:17     ` Steven Rostedt
  0 siblings, 1 reply; 14+ messages in thread
From: Paul E. McKenney @ 2015-11-19 23:24 UTC (permalink / raw)
  To: Steven Rostedt; +Cc: linux-kernel, Ingo Molnar, Andrew Morton

On Thu, Oct 29, 2015 at 03:07:56AM -0400, Steven Rostedt wrote:
> From: "Steven Rostedt (Red Hat)" <rostedt@goodmis.org>
> 
> Create a tracing directory called set_event_pid, which currently has no
> function, but will be used to filter all events for the tracing instance or
> the pids that are added to the file.
> 
> The reason no functionality is added with this commit is that this commit
> focuses on the creation and removal of the pids in a safe manner. And tests
> can be made against this change to make sure things are correct before
> hooking features to the list of pids.
> 
> Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
> ---
>  kernel/trace/trace.h        |   7 ++
>  kernel/trace/trace_events.c | 287 ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 294 insertions(+)
> 
> diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
> index fb8a61c710ea..250481043bb5 100644
> --- a/kernel/trace/trace.h
> +++ b/kernel/trace/trace.h
> @@ -176,6 +176,12 @@ struct trace_options {
>  	struct trace_option_dentry	*topts;
>  };
> 
> +struct trace_pid_list {
> +	unsigned int			nr_pids;
> +	int				order;
> +	pid_t				*pids;
> +};
> +
>  /*
>   * The trace array - an array of per-CPU trace arrays. This is the
>   * highest level data structure that individual tracers deal with.
> @@ -201,6 +207,7 @@ struct trace_array {
>  	bool			allocated_snapshot;
>  	unsigned long		max_latency;
>  #endif
> +	struct trace_pid_list	__rcu *filtered_pids;
>  	/*
>  	 * max_lock is used to protect the swapping of buffers
>  	 * when taking a max snapshot. The buffers themselves are
> diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
> index d120cfe3cca7..2ad7014707ee 100644
> --- a/kernel/trace/trace_events.c
> +++ b/kernel/trace/trace_events.c
> @@ -15,8 +15,10 @@
>  #include <linux/kthread.h>
>  #include <linux/tracefs.h>
>  #include <linux/uaccess.h>
> +#include <linux/bsearch.h>
>  #include <linux/module.h>
>  #include <linux/ctype.h>
> +#include <linux/sort.h>
>  #include <linux/slab.h>
>  #include <linux/delay.h>
> 
> @@ -445,6 +447,43 @@ static void ftrace_clear_events(struct trace_array *tr)
>  	mutex_unlock(&event_mutex);
>  }
> 
> +static int cmp_pid(const void *key, const void *elt)
> +{
> +	const pid_t *search_pid = key;
> +	const pid_t *pid = elt;
> +
> +	if (*search_pid == *pid)
> +		return 0;
> +	if (*search_pid < *pid)
> +		return -1;
> +	return 1;
> +}
> +
> +static void __ftrace_clear_event_pids(struct trace_array *tr)
> +{
> +	struct trace_pid_list *pid_list;
> +
> +	pid_list = rcu_dereference_protected(tr->filtered_pids,
> +					     lockdep_is_held(&event_mutex));
> +	if (!pid_list)
> +		return;
> +
> +	rcu_assign_pointer(tr->filtered_pids, NULL);
> +
> +	/* Wait till all users are no longer using pid filtering */
> +	synchronize_sched();
> +
> +	free_pages((unsigned long)pid_list->pids, pid_list->order);
> +	kfree(pid_list);
> +}
> +
> +static void ftrace_clear_event_pids(struct trace_array *tr)
> +{
> +	mutex_lock(&event_mutex);
> +	__ftrace_clear_event_pids(tr);
> +	mutex_unlock(&event_mutex);
> +}
> +
>  static void __put_system(struct event_subsystem *system)
>  {
>  	struct event_filter *filter = system->filter;
> @@ -777,6 +816,56 @@ static void t_stop(struct seq_file *m, void *p)
>  	mutex_unlock(&event_mutex);
>  }
> 
> +static void *p_start(struct seq_file *m, loff_t *pos)
> +{
> +	struct trace_pid_list *pid_list;
> +	struct trace_array *tr = m->private;
> +
> +	/*
> +	 * Grab the mutex, to keep calls to p_next() having the same
> +	 * tr->filtered_pids as p_start() has.
> +	 * If we just passed the tr->filtered_pids around, then RCU would
> +	 * have been enough, but doing that makes things more complex.
> +	 */
> +	mutex_lock(&event_mutex);
> +	rcu_read_lock_sched();

This looks interesting...  You hold the mutex, which I am guessing
blocks changes.  Then why the need for rcu_read_lock_sched()?

						Thanx, Paul

> +
> +	pid_list = rcu_dereference_sched(tr->filtered_pids);
> +
> +	if (!pid_list || *pos >= pid_list->nr_pids)
> +		return NULL;
> +
> +	return (void *)&pid_list->pids[*pos];
> +}
> +
> +static void p_stop(struct seq_file *m, void *p)
> +{
> +	rcu_read_unlock_sched();
> +	mutex_unlock(&event_mutex);
> +}
> +
> +static void *
> +p_next(struct seq_file *m, void *v, loff_t *pos)
> +{
> +	struct trace_array *tr = m->private;
> +	struct trace_pid_list *pid_list = rcu_dereference_sched(tr->filtered_pids);
> +
> +	(*pos)++;
> +
> +	if (*pos >= pid_list->nr_pids)
> +		return NULL;
> +
> +	return (void *)&pid_list->pids[*pos];
> +}
> +
> +static int p_show(struct seq_file *m, void *v)
> +{
> +	pid_t *pid = v;
> +
> +	seq_printf(m, "%d\n", *pid);
> +	return 0;
> +}


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [for-next][PATCH 2/5] tracing: Add set_event_pid directory for future use
  2015-11-19 23:24   ` Paul E. McKenney
@ 2015-11-20  4:17     ` Steven Rostedt
  2015-12-01 18:12       ` Paul E. McKenney
  0 siblings, 1 reply; 14+ messages in thread
From: Steven Rostedt @ 2015-11-20  4:17 UTC (permalink / raw)
  To: Paul E. McKenney; +Cc: linux-kernel, Ingo Molnar, Andrew Morton

On Thu, 19 Nov 2015 15:24:27 -0800
"Paul E. McKenney" <paulmck@linux.vnet.ibm.com> wrote:

> > +static void *p_start(struct seq_file *m, loff_t *pos)
> > +{
> > +	struct trace_pid_list *pid_list;
> > +	struct trace_array *tr = m->private;
> > +
> > +	/*
> > +	 * Grab the mutex, to keep calls to p_next() having the same
> > +	 * tr->filtered_pids as p_start() has.
> > +	 * If we just passed the tr->filtered_pids around, then RCU would
> > +	 * have been enough, but doing that makes things more complex.
> > +	 */
> > +	mutex_lock(&event_mutex);
> > +	rcu_read_lock_sched();  
> 
> This looks interesting...  You hold the mutex, which I am guessing
> blocks changes.  Then why the need for rcu_read_lock_sched()?

Technically you are correct. It's not needed. But I added it more for
documentation :-)

Ideally, we wouldn't need the mutex here. But then we need to pass
around the pid_list which makes it a bit more complex in the seq_file
code than to pass around the tr (where we get pid_list from
tr->filtered_pids).

And we do multiple rcu_dereference_sched()s, and for this code to work
properly (give consistent output), the result should be the same.
Hence, we grab the mutex, to keep the tr->filtered_pids to be
consistent between the rcu_dereference_sched() calls, but since we are
not modifying tr->filtered_pids(), and if we changed this code to do a
single rcu_dereference_sched() and pass around the result, then we
wouldn't need to grab the mutex, and the rcu_read_lock_sched() would be
enough.

I could remove it and change the code to do rcu_dereferenced_lock() but
to me that makes it sound like this code is an update path, which it is
not.

Does this make sense in a crazy way?

-- Steve


> 
> 						Thanx, Paul
> 
> > +
> > +	pid_list = rcu_dereference_sched(tr->filtered_pids);
> > +
> > +	if (!pid_list || *pos >= pid_list->nr_pids)
> > +		return NULL;
> > +
> > +	return (void *)&pid_list->pids[*pos];
> > +}
> > +
> > +static void p_stop(struct seq_file *m, void *p)
> > +{
> > +	rcu_read_unlock_sched();
> > +	mutex_unlock(&event_mutex);
> > +}
> > +
> > +static void *
> > +p_next(struct seq_file *m, void *v, loff_t *pos)
> > +{
> > +	struct trace_array *tr = m->private;
> > +	struct trace_pid_list *pid_list = rcu_dereference_sched(tr->filtered_pids);
> > +
> > +	(*pos)++;
> > +
> > +	if (*pos >= pid_list->nr_pids)
> > +		return NULL;
> > +
> > +	return (void *)&pid_list->pids[*pos];
> > +}
> > +
> > +static int p_show(struct seq_file *m, void *v)
> > +{
> > +	pid_t *pid = v;
> > +
> > +	seq_printf(m, "%d\n", *pid);
> > +	return 0;
> > +}  


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [for-next][PATCH 2/5] tracing: Add set_event_pid directory for future use
  2015-11-20  4:17     ` Steven Rostedt
@ 2015-12-01 18:12       ` Paul E. McKenney
  0 siblings, 0 replies; 14+ messages in thread
From: Paul E. McKenney @ 2015-12-01 18:12 UTC (permalink / raw)
  To: Steven Rostedt; +Cc: linux-kernel, Ingo Molnar, Andrew Morton

On Thu, Nov 19, 2015 at 11:17:26PM -0500, Steven Rostedt wrote:
> On Thu, 19 Nov 2015 15:24:27 -0800
> "Paul E. McKenney" <paulmck@linux.vnet.ibm.com> wrote:
> 
> > > +static void *p_start(struct seq_file *m, loff_t *pos)
> > > +{
> > > +	struct trace_pid_list *pid_list;
> > > +	struct trace_array *tr = m->private;
> > > +
> > > +	/*
> > > +	 * Grab the mutex, to keep calls to p_next() having the same
> > > +	 * tr->filtered_pids as p_start() has.
> > > +	 * If we just passed the tr->filtered_pids around, then RCU would
> > > +	 * have been enough, but doing that makes things more complex.
> > > +	 */
> > > +	mutex_lock(&event_mutex);
> > > +	rcu_read_lock_sched();  
> > 
> > This looks interesting...  You hold the mutex, which I am guessing
> > blocks changes.  Then why the need for rcu_read_lock_sched()?
> 
> Technically you are correct. It's not needed. But I added it more for
> documentation :-)
> 
> Ideally, we wouldn't need the mutex here. But then we need to pass
> around the pid_list which makes it a bit more complex in the seq_file
> code than to pass around the tr (where we get pid_list from
> tr->filtered_pids).
> 
> And we do multiple rcu_dereference_sched()s, and for this code to work
> properly (give consistent output), the result should be the same.
> Hence, we grab the mutex, to keep the tr->filtered_pids to be
> consistent between the rcu_dereference_sched() calls, but since we are
> not modifying tr->filtered_pids(), and if we changed this code to do a
> single rcu_dereference_sched() and pass around the result, then we
> wouldn't need to grab the mutex, and the rcu_read_lock_sched() would be
> enough.
> 
> I could remove it and change the code to do rcu_dereferenced_lock() but
> to me that makes it sound like this code is an update path, which it is
> not.
> 
> Does this make sense in a crazy way?

Ummm...  Pretty crazy.  ;-)

For me, it was mostly confusing, as I could not figure out how the
rcu_read_lock_sched() was helping.  But of course, others' mileage
might vary.

							Thanx, Paul

> -- Steve
> 
> 
> > 
> > 						Thanx, Paul
> > 
> > > +
> > > +	pid_list = rcu_dereference_sched(tr->filtered_pids);
> > > +
> > > +	if (!pid_list || *pos >= pid_list->nr_pids)
> > > +		return NULL;
> > > +
> > > +	return (void *)&pid_list->pids[*pos];
> > > +}
> > > +
> > > +static void p_stop(struct seq_file *m, void *p)
> > > +{
> > > +	rcu_read_unlock_sched();
> > > +	mutex_unlock(&event_mutex);
> > > +}
> > > +
> > > +static void *
> > > +p_next(struct seq_file *m, void *v, loff_t *pos)
> > > +{
> > > +	struct trace_array *tr = m->private;
> > > +	struct trace_pid_list *pid_list = rcu_dereference_sched(tr->filtered_pids);
> > > +
> > > +	(*pos)++;
> > > +
> > > +	if (*pos >= pid_list->nr_pids)
> > > +		return NULL;
> > > +
> > > +	return (void *)&pid_list->pids[*pos];
> > > +}
> > > +
> > > +static int p_show(struct seq_file *m, void *v)
> > > +{
> > > +	pid_t *pid = v;
> > > +
> > > +	seq_printf(m, "%d\n", *pid);
> > > +	return 0;
> > > +}  
> 


^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2015-12-01 18:12 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-10-29  7:07 [for-next][PATCH 0/5] tracing: Addition of set_event_pid Steven Rostedt
2015-10-29  7:07 ` [for-next][PATCH 1/5] tracepoint: Give priority to probes of tracepoints Steven Rostedt
2015-10-29 17:52   ` Mathieu Desnoyers
2015-10-30 20:25     ` Steven Rostedt
2015-10-30 20:49       ` Mathieu Desnoyers
2015-10-29  7:07 ` [for-next][PATCH 2/5] tracing: Add set_event_pid directory for future use Steven Rostedt
2015-11-19 23:24   ` Paul E. McKenney
2015-11-20  4:17     ` Steven Rostedt
2015-12-01 18:12       ` Paul E. McKenney
2015-10-29  7:07 ` [for-next][PATCH 3/5] tracing: Implement event pid filtering Steven Rostedt
2015-10-29  7:07 ` [for-next][PATCH 4/5] tracing: Check all tasks on each CPU when filtering pids Steven Rostedt
2015-10-30  6:16   ` Jiaxing Wang
2015-10-30 20:28     ` Steven Rostedt
2015-10-29  7:07 ` [for-next][PATCH 5/5] tracing: Fix sparse RCU warning Steven Rostedt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).