ftrace: Add enable/disable ftrace_ops control interface
Adding a way to temporarily enable/disable ftrace_ops. The change follows the same way as 'global' ftrace_ops are done. Introducing 2 global ftrace_ops - control_ops and ftrace_control_list which take over all ftrace_ops registered with FTRACE_OPS_FL_CONTROL flag. In addition new per cpu flag called 'disabled' is also added to ftrace_ops to provide the control information for each cpu. When ftrace_ops with FTRACE_OPS_FL_CONTROL is registered, it is set as disabled for all cpus. The ftrace_control_list contains all the registered 'control' ftrace_ops. The control_ops provides function which iterates ftrace_control_list and does the check for 'disabled' flag on current cpu. Adding 3 inline functions: ftrace_function_local_disable/ftrace_function_local_enable - enable/disable the ftrace_ops on current cpu ftrace_function_local_disabled - get disabled ftrace_ops::disabled value for current cpu Link: http://lkml.kernel.org/r/1329317514-8131-2-git-send-email-jolsa@redhat.com Acked-by: Frederic Weisbecker <fweisbec@gmail.com> Signed-off-by: Jiri Olsa <jolsa@redhat.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
This commit is contained in:
		
					parent
					
						
							
								5b34926114
							
						
					
				
			
			
				commit
				
					
						e248491ac2
					
				
			
		
					 3 changed files with 172 additions and 7 deletions
				
			
		| 
						 | 
				
			
			@ -31,16 +31,33 @@ ftrace_enable_sysctl(struct ctl_table *table, int write,
 | 
			
		|||
 | 
			
		||||
typedef void (*ftrace_func_t)(unsigned long ip, unsigned long parent_ip);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * FTRACE_OPS_FL_* bits denote the state of ftrace_ops struct and are
 | 
			
		||||
 * set in the flags member.
 | 
			
		||||
 *
 | 
			
		||||
 * ENABLED - set/unset when ftrace_ops is registered/unregistered
 | 
			
		||||
 * GLOBAL  - set manualy by ftrace_ops user to denote the ftrace_ops
 | 
			
		||||
 *           is part of the global tracers sharing the same filter
 | 
			
		||||
 *           via set_ftrace_* debugfs files.
 | 
			
		||||
 * DYNAMIC - set when ftrace_ops is registered to denote dynamically
 | 
			
		||||
 *           allocated ftrace_ops which need special care
 | 
			
		||||
 * CONTROL - set manualy by ftrace_ops user to denote the ftrace_ops
 | 
			
		||||
 *           could be controled by following calls:
 | 
			
		||||
 *             ftrace_function_local_enable
 | 
			
		||||
 *             ftrace_function_local_disable
 | 
			
		||||
 */
 | 
			
		||||
enum {
 | 
			
		||||
	FTRACE_OPS_FL_ENABLED		= 1 << 0,
 | 
			
		||||
	FTRACE_OPS_FL_GLOBAL		= 1 << 1,
 | 
			
		||||
	FTRACE_OPS_FL_DYNAMIC		= 1 << 2,
 | 
			
		||||
	FTRACE_OPS_FL_CONTROL		= 1 << 3,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ftrace_ops {
 | 
			
		||||
	ftrace_func_t			func;
 | 
			
		||||
	struct ftrace_ops		*next;
 | 
			
		||||
	unsigned long			flags;
 | 
			
		||||
	int __percpu			*disabled;
 | 
			
		||||
#ifdef CONFIG_DYNAMIC_FTRACE
 | 
			
		||||
	struct ftrace_hash		*notrace_hash;
 | 
			
		||||
	struct ftrace_hash		*filter_hash;
 | 
			
		||||
| 
						 | 
				
			
			@ -97,6 +114,55 @@ int register_ftrace_function(struct ftrace_ops *ops);
 | 
			
		|||
int unregister_ftrace_function(struct ftrace_ops *ops);
 | 
			
		||||
void clear_ftrace_function(void);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ftrace_function_local_enable - enable controlled ftrace_ops on current cpu
 | 
			
		||||
 *
 | 
			
		||||
 * This function enables tracing on current cpu by decreasing
 | 
			
		||||
 * the per cpu control variable.
 | 
			
		||||
 * It must be called with preemption disabled and only on ftrace_ops
 | 
			
		||||
 * registered with FTRACE_OPS_FL_CONTROL. If called without preemption
 | 
			
		||||
 * disabled, this_cpu_ptr will complain when CONFIG_DEBUG_PREEMPT is enabled.
 | 
			
		||||
 */
 | 
			
		||||
static inline void ftrace_function_local_enable(struct ftrace_ops *ops)
 | 
			
		||||
{
 | 
			
		||||
	if (WARN_ON_ONCE(!(ops->flags & FTRACE_OPS_FL_CONTROL)))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	(*this_cpu_ptr(ops->disabled))--;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ftrace_function_local_disable - enable controlled ftrace_ops on current cpu
 | 
			
		||||
 *
 | 
			
		||||
 * This function enables tracing on current cpu by decreasing
 | 
			
		||||
 * the per cpu control variable.
 | 
			
		||||
 * It must be called with preemption disabled and only on ftrace_ops
 | 
			
		||||
 * registered with FTRACE_OPS_FL_CONTROL. If called without preemption
 | 
			
		||||
 * disabled, this_cpu_ptr will complain when CONFIG_DEBUG_PREEMPT is enabled.
 | 
			
		||||
 */
 | 
			
		||||
static inline void ftrace_function_local_disable(struct ftrace_ops *ops)
 | 
			
		||||
{
 | 
			
		||||
	if (WARN_ON_ONCE(!(ops->flags & FTRACE_OPS_FL_CONTROL)))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	(*this_cpu_ptr(ops->disabled))++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ftrace_function_local_disabled - returns ftrace_ops disabled value
 | 
			
		||||
 *                                  on current cpu
 | 
			
		||||
 *
 | 
			
		||||
 * This function returns value of ftrace_ops::disabled on current cpu.
 | 
			
		||||
 * It must be called with preemption disabled and only on ftrace_ops
 | 
			
		||||
 * registered with FTRACE_OPS_FL_CONTROL. If called without preemption
 | 
			
		||||
 * disabled, this_cpu_ptr will complain when CONFIG_DEBUG_PREEMPT is enabled.
 | 
			
		||||
 */
 | 
			
		||||
static inline int ftrace_function_local_disabled(struct ftrace_ops *ops)
 | 
			
		||||
{
 | 
			
		||||
	WARN_ON_ONCE(!(ops->flags & FTRACE_OPS_FL_CONTROL));
 | 
			
		||||
	return *this_cpu_ptr(ops->disabled);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern void ftrace_stub(unsigned long a0, unsigned long a1);
 | 
			
		||||
 | 
			
		||||
#else /* !CONFIG_FUNCTION_TRACER */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue