Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1382570 > unrolled thread

[RFC][PATCH 3/4] tracing: Add infrastructure to allow set_event_pid to follow children

Started bySteven Rostedt <rostedt@goodmis.org>
First post2016-04-19 16:40 +0200
Last post2016-04-19 22:40 +0200
Articles 4 — 2 participants

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  [RFC][PATCH 3/4] tracing: Add infrastructure to allow set_event_pid to follow children Steven Rostedt <rostedt@goodmis.org> - 2016-04-19 16:40 +0200
    Re: [RFC][PATCH 3/4] tracing: Add infrastructure to allow  set_event_pid to follow children Mathieu Desnoyers <mathieu.desnoyers@efficios.com> - 2016-04-19 19:00 +0200
      Re: [RFC][PATCH 3/4] tracing: Add infrastructure to allow  set_event_pid to follow children Steven Rostedt <rostedt@goodmis.org> - 2016-04-19 19:20 +0200
        Re: [RFC][PATCH 3/4] tracing: Add infrastructure to allow  set_event_pid to follow children Mathieu Desnoyers <mathieu.desnoyers@efficios.com> - 2016-04-19 22:40 +0200

#1382570 — [RFC][PATCH 3/4] tracing: Add infrastructure to allow set_event_pid to follow children

FromSteven Rostedt <rostedt@goodmis.org>
Date2016-04-19 16:40 +0200
Subject[RFC][PATCH 3/4] tracing: Add infrastructure to allow set_event_pid to follow children
Message-ID<rpEYO-8k2-17@gated-at.bofh.it>
From: Steven Rostedt <rostedt@goodmis.org>

Add the infrastructure needed to have the PIDs in set_event_pid to
automatically add PIDs of the children of the tasks that have their PIDs in
set_event_pid. This will also remove PIDs from set_event_pid when a task
exits

This is implemented by adding hooks into the fork and exit tracepoints. On
fork, the PIDs are added to the list, and on exit, they are removed.

Add a new option called event_fork that when set, PIDs in set_event_pid will
automatically get their children PIDs added when they fork, as well as any
task that exits will have its PID removed from set_event_pid.

This works for instances as well.

Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
---
 kernel/trace/trace.c        |  3 ++
 kernel/trace/trace.h        |  2 ++
 kernel/trace/trace_events.c | 84 +++++++++++++++++++++++++++++++++++++++------
 3 files changed, 79 insertions(+), 10 deletions(-)

diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index a2f0b9f33e9b..0d12dbde8399 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -3571,6 +3571,9 @@ int set_tracer_flag(struct trace_array *tr, unsigned int mask, int enabled)
 	if (mask == TRACE_ITER_RECORD_CMD)
 		trace_event_enable_cmd_record(enabled);
 
+	if (mask == TRACE_ITER_EVENT_FORK)
+		trace_event_follow_fork(tr, enabled);
+
 	if (mask == TRACE_ITER_OVERWRITE) {
 		ring_buffer_change_overwrite(tr->trace_buffer.buffer, enabled);
 #ifdef CONFIG_TRACER_MAX_TRACE
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 68cbb8e10aea..2525042760e6 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -655,6 +655,7 @@ static inline void __trace_stack(struct trace_array *tr, unsigned long flags,
 extern cycle_t ftrace_now(int cpu);
 
 extern void trace_find_cmdline(int pid, char comm[]);
+extern void trace_event_follow_fork(struct trace_array *tr, bool enable);
 
 #ifdef CONFIG_DYNAMIC_FTRACE
 extern unsigned long ftrace_update_tot_cnt;
@@ -966,6 +967,7 @@ extern int trace_get_user(struct trace_parser *parser, const char __user *ubuf,
 		C(STOP_ON_FREE,		"disable_on_free"),	\
 		C(IRQ_INFO,		"irq-info"),		\
 		C(MARKERS,		"markers"),		\
+		C(EVENT_FORK,		"event-fork"),		\
 		FUNCTION_FLAGS					\
 		FGRAPH_FLAGS					\
 		STACK_FLAGS					\
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 45f7cc72bf25..add81dff7520 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -474,11 +474,23 @@ static void ftrace_clear_events(struct trace_array *tr)
 /* Shouldn't this be in a header? */
 extern int pid_max;
 
+/* Returns true if found in filter */
 static bool
-ignore_this_task(struct trace_pid_list *filtered_pids, struct task_struct *task)
+find_filtered_pid(struct trace_pid_list *filtered_pids, pid_t search_pid)
 {
-	pid_t pid;
+	/*
+	 * If pid_max changed after filtered_pids was created, we
+	 * by default ignore all pids greater than the previous pid_max.
+	 */
+	if (search_pid >= filtered_pids->pid_max)
+		return false;
+
+	return test_bit(search_pid, filtered_pids->pids);
+}
 
+static bool
+ignore_this_task(struct trace_pid_list *filtered_pids, struct task_struct *task)
+{
 	/*
 	 * Return false, because if filtered_pids does not exist,
 	 * all pids are good to trace.
@@ -486,16 +498,68 @@ ignore_this_task(struct trace_pid_list *filtered_pids, struct task_struct *task)
 	if (!filtered_pids)
 		return false;
 
-	pid = task->pid;
+	return !find_filtered_pid(filtered_pids, task->pid);
+}
 
-	/*
-	 * If pid_max changed after filtered_pids was created, we
-	 * by default ignore all pids greater than the previous pid_max.
-	 */
-	if (task->pid >= filtered_pids->pid_max)
-		return true;
+static void filter_add_remove_task(struct trace_pid_list *pid_list,
+				   struct task_struct *self,
+				   struct task_struct *task)
+{
+	if (!pid_list)
+		return;
+
+	/* For forks, we only add if the forking task is listed */
+	if (self) {
+		if (!find_filtered_pid(pid_list, self->pid))
+			return;
+	}
+
+	/* Sorry, but we don't support pid_max changing after setting */
+	if (task->pid >= pid_list->pid_max)
+		return;
+
+	/* "self" is set for forks, and NULL for exits */
+	if (self)
+		set_bit(task->pid, pid_list->pids);
+	else
+		clear_bit(task->pid, pid_list->pids);
+}
+
+static void
+event_filter_pid_sched_process_exit(void *data, struct task_struct *task)
+{
+	struct trace_pid_list *pid_list;
+	struct trace_array *tr = data;
+
+	pid_list = rcu_dereference_sched(tr->filtered_pids);
+	filter_add_remove_task(pid_list, NULL, task);
+}
 
-	return !test_bit(task->pid, filtered_pids->pids);
+static void
+event_filter_pid_sched_process_fork(void *data,
+				    struct task_struct *self,
+				    struct task_struct *task)
+{
+	struct trace_pid_list *pid_list;
+	struct trace_array *tr = data;
+
+	pid_list = rcu_dereference_sched(tr->filtered_pids);
+	filter_add_remove_task(pid_list, self, task);
+}
+
+void trace_event_follow_fork(struct trace_array *tr, bool enable)
+{
+	if (enable) {
+		register_trace_prio_sched_process_fork(event_filter_pid_sched_process_fork,
+						       tr, INT_MIN);
+		register_trace_prio_sched_process_exit(event_filter_pid_sched_process_exit,
+						       tr, INT_MAX);
+	} else {
+		unregister_trace_sched_process_fork(event_filter_pid_sched_process_fork,
+						    tr);
+		unregister_trace_sched_process_exit(event_filter_pid_sched_process_exit,
+						    tr);
+	}
 }
 
 static void
-- 
2.8.0.rc3

[toc] | [next] | [standalone]


#1382714 — Re: [RFC][PATCH 3/4] tracing: Add infrastructure to allow set_event_pid to follow children

FromMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Date2016-04-19 19:00 +0200
SubjectRe: [RFC][PATCH 3/4] tracing: Add infrastructure to allow set_event_pid to follow children
Message-ID<rpHaj-1sn-41@gated-at.bofh.it>
In reply to#1382570
----- On Apr 19, 2016, at 10:34 AM, rostedt rostedt@goodmis.org wrote:

> From: Steven Rostedt <rostedt@goodmis.org>
> 
> Add the infrastructure needed to have the PIDs in set_event_pid to
> automatically add PIDs of the children of the tasks that have their PIDs in
> set_event_pid. This will also remove PIDs from set_event_pid when a task
> exits
> 
> This is implemented by adding hooks into the fork and exit tracepoints. On
> fork, the PIDs are added to the list, and on exit, they are removed.
> 
> Add a new option called event_fork that when set, PIDs in set_event_pid will
> automatically get their children PIDs added when they fork, as well as any
> task that exits will have its PID removed from set_event_pid.

Just out of curiosity: how does it deal with multi-process and multi-thread ?
What events are expected in each case ?

Thanks,

Mathieu

> 
> This works for instances as well.
> 
> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
> ---
> kernel/trace/trace.c        |  3 ++
> kernel/trace/trace.h        |  2 ++
> kernel/trace/trace_events.c | 84 +++++++++++++++++++++++++++++++++++++++------
> 3 files changed, 79 insertions(+), 10 deletions(-)
> 
> diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
> index a2f0b9f33e9b..0d12dbde8399 100644
> --- a/kernel/trace/trace.c
> +++ b/kernel/trace/trace.c
> @@ -3571,6 +3571,9 @@ int set_tracer_flag(struct trace_array *tr, unsigned int
> mask, int enabled)
> 	if (mask == TRACE_ITER_RECORD_CMD)
> 		trace_event_enable_cmd_record(enabled);
> 
> +	if (mask == TRACE_ITER_EVENT_FORK)
> +		trace_event_follow_fork(tr, enabled);
> +
> 	if (mask == TRACE_ITER_OVERWRITE) {
> 		ring_buffer_change_overwrite(tr->trace_buffer.buffer, enabled);
> #ifdef CONFIG_TRACER_MAX_TRACE
> diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
> index 68cbb8e10aea..2525042760e6 100644
> --- a/kernel/trace/trace.h
> +++ b/kernel/trace/trace.h
> @@ -655,6 +655,7 @@ static inline void __trace_stack(struct trace_array *tr,
> unsigned long flags,
> extern cycle_t ftrace_now(int cpu);
> 
> extern void trace_find_cmdline(int pid, char comm[]);
> +extern void trace_event_follow_fork(struct trace_array *tr, bool enable);
> 
> #ifdef CONFIG_DYNAMIC_FTRACE
> extern unsigned long ftrace_update_tot_cnt;
> @@ -966,6 +967,7 @@ extern int trace_get_user(struct trace_parser *parser, const
> char __user *ubuf,
> 		C(STOP_ON_FREE,		"disable_on_free"),	\
> 		C(IRQ_INFO,		"irq-info"),		\
> 		C(MARKERS,		"markers"),		\
> +		C(EVENT_FORK,		"event-fork"),		\
> 		FUNCTION_FLAGS					\
> 		FGRAPH_FLAGS					\
> 		STACK_FLAGS					\
> diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
> index 45f7cc72bf25..add81dff7520 100644
> --- a/kernel/trace/trace_events.c
> +++ b/kernel/trace/trace_events.c
> @@ -474,11 +474,23 @@ static void ftrace_clear_events(struct trace_array *tr)
> /* Shouldn't this be in a header? */
> extern int pid_max;
> 
> +/* Returns true if found in filter */
> static bool
> -ignore_this_task(struct trace_pid_list *filtered_pids, struct task_struct
> *task)
> +find_filtered_pid(struct trace_pid_list *filtered_pids, pid_t search_pid)
> {
> -	pid_t pid;
> +	/*
> +	 * If pid_max changed after filtered_pids was created, we
> +	 * by default ignore all pids greater than the previous pid_max.
> +	 */
> +	if (search_pid >= filtered_pids->pid_max)
> +		return false;
> +
> +	return test_bit(search_pid, filtered_pids->pids);
> +}
> 
> +static bool
> +ignore_this_task(struct trace_pid_list *filtered_pids, struct task_struct
> *task)
> +{
> 	/*
> 	 * Return false, because if filtered_pids does not exist,
> 	 * all pids are good to trace.
> @@ -486,16 +498,68 @@ ignore_this_task(struct trace_pid_list *filtered_pids,
> struct task_struct *task)
> 	if (!filtered_pids)
> 		return false;
> 
> -	pid = task->pid;
> +	return !find_filtered_pid(filtered_pids, task->pid);
> +}
> 
> -	/*
> -	 * If pid_max changed after filtered_pids was created, we
> -	 * by default ignore all pids greater than the previous pid_max.
> -	 */
> -	if (task->pid >= filtered_pids->pid_max)
> -		return true;
> +static void filter_add_remove_task(struct trace_pid_list *pid_list,
> +				   struct task_struct *self,
> +				   struct task_struct *task)
> +{
> +	if (!pid_list)
> +		return;
> +
> +	/* For forks, we only add if the forking task is listed */
> +	if (self) {
> +		if (!find_filtered_pid(pid_list, self->pid))
> +			return;
> +	}
> +
> +	/* Sorry, but we don't support pid_max changing after setting */
> +	if (task->pid >= pid_list->pid_max)
> +		return;
> +
> +	/* "self" is set for forks, and NULL for exits */
> +	if (self)
> +		set_bit(task->pid, pid_list->pids);
> +	else
> +		clear_bit(task->pid, pid_list->pids);
> +}
> +
> +static void
> +event_filter_pid_sched_process_exit(void *data, struct task_struct *task)
> +{
> +	struct trace_pid_list *pid_list;
> +	struct trace_array *tr = data;
> +
> +	pid_list = rcu_dereference_sched(tr->filtered_pids);
> +	filter_add_remove_task(pid_list, NULL, task);
> +}
> 
> -	return !test_bit(task->pid, filtered_pids->pids);
> +static void
> +event_filter_pid_sched_process_fork(void *data,
> +				    struct task_struct *self,
> +				    struct task_struct *task)
> +{
> +	struct trace_pid_list *pid_list;
> +	struct trace_array *tr = data;
> +
> +	pid_list = rcu_dereference_sched(tr->filtered_pids);
> +	filter_add_remove_task(pid_list, self, task);
> +}
> +
> +void trace_event_follow_fork(struct trace_array *tr, bool enable)
> +{
> +	if (enable) {
> +		register_trace_prio_sched_process_fork(event_filter_pid_sched_process_fork,
> +						       tr, INT_MIN);
> +		register_trace_prio_sched_process_exit(event_filter_pid_sched_process_exit,
> +						       tr, INT_MAX);
> +	} else {
> +		unregister_trace_sched_process_fork(event_filter_pid_sched_process_fork,
> +						    tr);
> +		unregister_trace_sched_process_exit(event_filter_pid_sched_process_exit,
> +						    tr);
> +	}
> }
> 
> static void
> --
> 2.8.0.rc3
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-trace-users" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

[toc] | [prev] | [next] | [standalone]


#1382735 — Re: [RFC][PATCH 3/4] tracing: Add infrastructure to allow set_event_pid to follow children

FromSteven Rostedt <rostedt@goodmis.org>
Date2016-04-19 19:20 +0200
SubjectRe: [RFC][PATCH 3/4] tracing: Add infrastructure to allow set_event_pid to follow children
Message-ID<rpHtF-1RO-31@gated-at.bofh.it>
In reply to#1382714
On Tue, 19 Apr 2016 16:55:11 +0000 (UTC)
Mathieu Desnoyers <mathieu.desnoyers@efficios.com> wrote:

> ----- On Apr 19, 2016, at 10:34 AM, rostedt rostedt@goodmis.org wrote:
> 
> > From: Steven Rostedt <rostedt@goodmis.org>
> > 
> > Add the infrastructure needed to have the PIDs in set_event_pid to
> > automatically add PIDs of the children of the tasks that have their PIDs in
> > set_event_pid. This will also remove PIDs from set_event_pid when a task
> > exits
> > 
> > This is implemented by adding hooks into the fork and exit tracepoints. On
> > fork, the PIDs are added to the list, and on exit, they are removed.
> > 
> > Add a new option called event_fork that when set, PIDs in set_event_pid will
> > automatically get their children PIDs added when they fork, as well as any
> > task that exits will have its PID removed from set_event_pid.  
> 
> Just out of curiosity: how does it deal with multi-process and multi-thread ?
> What events are expected in each case ?
> 

Not sure what you mean by that. This is in-kernel, and it's simply
tasks. That is, any task (process or thread) that creates another task
has its kernel pid checked. That would be the thread ID as well. So it
works the same with processes as with threads because within the kernel
they are just all just "tasks".

-- Steve

[toc] | [prev] | [next] | [standalone]


#1382826 — Re: [RFC][PATCH 3/4] tracing: Add infrastructure to allow set_event_pid to follow children

FromMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Date2016-04-19 22:40 +0200
SubjectRe: [RFC][PATCH 3/4] tracing: Add infrastructure to allow set_event_pid to follow children
Message-ID<rpKBb-4bP-3@gated-at.bofh.it>
In reply to#1382735
----- On Apr 19, 2016, at 1:13 PM, rostedt rostedt@goodmis.org wrote:

> On Tue, 19 Apr 2016 16:55:11 +0000 (UTC)
> Mathieu Desnoyers <mathieu.desnoyers@efficios.com> wrote:
> 
>> ----- On Apr 19, 2016, at 10:34 AM, rostedt rostedt@goodmis.org wrote:
>> 
>> > From: Steven Rostedt <rostedt@goodmis.org>
>> > 
>> > Add the infrastructure needed to have the PIDs in set_event_pid to
>> > automatically add PIDs of the children of the tasks that have their PIDs in
>> > set_event_pid. This will also remove PIDs from set_event_pid when a task
>> > exits
>> > 
>> > This is implemented by adding hooks into the fork and exit tracepoints. On
>> > fork, the PIDs are added to the list, and on exit, they are removed.
>> > 
>> > Add a new option called event_fork that when set, PIDs in set_event_pid will
>> > automatically get their children PIDs added when they fork, as well as any
>> > task that exits will have its PID removed from set_event_pid.
>> 
>> Just out of curiosity: how does it deal with multi-process and multi-thread ?
>> What events are expected in each case ?
>> 
> 
> Not sure what you mean by that. This is in-kernel, and it's simply
> tasks. That is, any task (process or thread) that creates another task
> has its kernel pid checked. That would be the thread ID as well. So it
> works the same with processes as with threads because within the kernel
> they are just all just "tasks".

You register on sched_process_fork and sched_process_exit tracepoints
for adding/removing PIDs to/from your "PID tracker".

sched_process_fork() is called both when a process and when a thread
is created.

sched_process_exit() is called from do_exit(). Ah! and it seems do_exit
is called whenever a user-space thread exits. The process exiting
system call is rather exit_group(2).

I was concerned that you might miss the thread exiting system calls,
but it seems OK after digging back into that part of the kernel
source code. It's been a while since last time I had to do modeling
of the kernel state based on events by myself, sorry about the
confusion. :-)

Thanks,

Mathieu

> 
> -- Steve

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

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web