mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-01 00:58:39 +02:00 
			
		
		
		
	ftrace: Add 'function-fork' trace option
The function-fork option is same as event-fork that it tracks task fork/exit and set the pid filter properly. This can be useful if user wants to trace selected tasks including their children only. Link: http://lkml.kernel.org/r/20170417024430.21194-3-namhyung@kernel.org Signed-off-by: Namhyung Kim <namhyung@kernel.org> Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
This commit is contained in:
		
							parent
							
								
									b980b117c9
								
							
						
					
					
						commit
						1e10486ffe
					
				
					 3 changed files with 46 additions and 2 deletions
				
			
		|  | @ -5600,6 +5600,43 @@ ftrace_filter_pid_sched_switch_probe(void *data, bool preempt, | ||||||
| 		       trace_ignore_this_task(pid_list, next)); | 		       trace_ignore_this_task(pid_list, next)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static void | ||||||
|  | ftrace_pid_follow_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->function_pids); | ||||||
|  | 	trace_filter_add_remove_task(pid_list, self, task); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | ftrace_pid_follow_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->function_pids); | ||||||
|  | 	trace_filter_add_remove_task(pid_list, NULL, task); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void ftrace_pid_follow_fork(struct trace_array *tr, bool enable) | ||||||
|  | { | ||||||
|  | 	if (enable) { | ||||||
|  | 		register_trace_sched_process_fork(ftrace_pid_follow_sched_process_fork, | ||||||
|  | 						  tr); | ||||||
|  | 		register_trace_sched_process_exit(ftrace_pid_follow_sched_process_exit, | ||||||
|  | 						  tr); | ||||||
|  | 	} else { | ||||||
|  | 		unregister_trace_sched_process_fork(ftrace_pid_follow_sched_process_fork, | ||||||
|  | 						    tr); | ||||||
|  | 		unregister_trace_sched_process_exit(ftrace_pid_follow_sched_process_exit, | ||||||
|  | 						    tr); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static void clear_ftrace_pids(struct trace_array *tr) | static void clear_ftrace_pids(struct trace_array *tr) | ||||||
| { | { | ||||||
| 	struct trace_pid_list *pid_list; | 	struct trace_pid_list *pid_list; | ||||||
|  |  | ||||||
|  | @ -257,7 +257,7 @@ unsigned long long ns2usecs(u64 nsec) | ||||||
| 
 | 
 | ||||||
| /* trace_flags that are default zero for instances */ | /* trace_flags that are default zero for instances */ | ||||||
| #define ZEROED_TRACE_FLAGS \ | #define ZEROED_TRACE_FLAGS \ | ||||||
| 	TRACE_ITER_EVENT_FORK | 	(TRACE_ITER_EVENT_FORK | TRACE_ITER_FUNC_FORK) | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * The global_trace is the descriptor that holds the top-level tracing |  * The global_trace is the descriptor that holds the top-level tracing | ||||||
|  | @ -4205,6 +4205,9 @@ int set_tracer_flag(struct trace_array *tr, unsigned int mask, int enabled) | ||||||
| 	if (mask == TRACE_ITER_EVENT_FORK) | 	if (mask == TRACE_ITER_EVENT_FORK) | ||||||
| 		trace_event_follow_fork(tr, enabled); | 		trace_event_follow_fork(tr, enabled); | ||||||
| 
 | 
 | ||||||
|  | 	if (mask == TRACE_ITER_FUNC_FORK) | ||||||
|  | 		ftrace_pid_follow_fork(tr, enabled); | ||||||
|  | 
 | ||||||
| 	if (mask == TRACE_ITER_OVERWRITE) { | 	if (mask == TRACE_ITER_OVERWRITE) { | ||||||
| 		ring_buffer_change_overwrite(tr->trace_buffer.buffer, enabled); | 		ring_buffer_change_overwrite(tr->trace_buffer.buffer, enabled); | ||||||
| #ifdef CONFIG_TRACER_MAX_TRACE | #ifdef CONFIG_TRACER_MAX_TRACE | ||||||
|  |  | ||||||
|  | @ -897,6 +897,7 @@ void ftrace_init_tracefs(struct trace_array *tr, struct dentry *d_tracer); | ||||||
| void ftrace_init_tracefs_toplevel(struct trace_array *tr, | void ftrace_init_tracefs_toplevel(struct trace_array *tr, | ||||||
| 				  struct dentry *d_tracer); | 				  struct dentry *d_tracer); | ||||||
| int init_function_trace(void); | int init_function_trace(void); | ||||||
|  | void ftrace_pid_follow_fork(struct trace_array *tr, bool enable); | ||||||
| #else | #else | ||||||
| static inline int ftrace_trace_task(struct trace_array *tr) | static inline int ftrace_trace_task(struct trace_array *tr) | ||||||
| { | { | ||||||
|  | @ -916,6 +917,7 @@ static inline void ftrace_reset_array_ops(struct trace_array *tr) { } | ||||||
| static inline void ftrace_init_tracefs(struct trace_array *tr, struct dentry *d) { } | static inline void ftrace_init_tracefs(struct trace_array *tr, struct dentry *d) { } | ||||||
| static inline void ftrace_init_tracefs_toplevel(struct trace_array *tr, struct dentry *d) { } | static inline void ftrace_init_tracefs_toplevel(struct trace_array *tr, struct dentry *d) { } | ||||||
| static inline int init_function_trace(void) { return 0; } | static inline int init_function_trace(void) { return 0; } | ||||||
|  | static inline void ftrace_pid_follow_fork(struct trace_array *tr, bool enable) { } | ||||||
| /* ftace_func_t type is not defined, use macro instead of static inline */ | /* ftace_func_t type is not defined, use macro instead of static inline */ | ||||||
| #define ftrace_init_array_ops(tr, func) do { } while (0) | #define ftrace_init_array_ops(tr, func) do { } while (0) | ||||||
| #endif /* CONFIG_FUNCTION_TRACER */ | #endif /* CONFIG_FUNCTION_TRACER */ | ||||||
|  | @ -989,11 +991,13 @@ extern int trace_get_user(struct trace_parser *parser, const char __user *ubuf, | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_FUNCTION_TRACER | #ifdef CONFIG_FUNCTION_TRACER | ||||||
| # define FUNCTION_FLAGS						\ | # define FUNCTION_FLAGS						\ | ||||||
| 		C(FUNCTION,		"function-trace"), | 		C(FUNCTION,		"function-trace"),	\ | ||||||
|  | 		C(FUNC_FORK,		"function-fork"), | ||||||
| # define FUNCTION_DEFAULT_FLAGS		TRACE_ITER_FUNCTION | # define FUNCTION_DEFAULT_FLAGS		TRACE_ITER_FUNCTION | ||||||
| #else | #else | ||||||
| # define FUNCTION_FLAGS | # define FUNCTION_FLAGS | ||||||
| # define FUNCTION_DEFAULT_FLAGS		0UL | # define FUNCTION_DEFAULT_FLAGS		0UL | ||||||
|  | # define TRACE_ITER_FUNC_FORK		0UL | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_STACKTRACE | #ifdef CONFIG_STACKTRACE | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Namhyung Kim
						Namhyung Kim