Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b0fc494f authored by Steven Rostedt's avatar Steven Rostedt Committed by Thomas Gleixner
Browse files

ftrace: add ftrace_enabled sysctl to disable mcount function



This patch adds back the sysctl ftrace_enabled. This time it is
defaulted to on, if DYNAMIC_FTRACE is configured. When ftrace_enabled
is disabled, the ftrace function is set to the stub return.

If DYNAMIC_FTRACE is also configured, on ftrace_enabled = 0,
the registered ftrace functions will all be set to jmps, but no more
new calls to ftrace recording (used to find the ftrace calling sites)
will be called.

Signed-off-by: default avatarSteven Rostedt <srostedt@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent 3d083395
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -5,6 +5,12 @@

#include <linux/linkage.h>

extern int ftrace_enabled;
extern int
ftrace_enable_sysctl(struct ctl_table *table, int write,
		     struct file *filp, void __user *buffer, size_t *lenp,
		     loff_t *ppos);

typedef void (*ftrace_func_t)(unsigned long ip, unsigned long parent_ip);

struct ftrace_ops {
+11 −0
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@
#include <linux/nfs_fs.h>
#include <linux/acpi.h>
#include <linux/reboot.h>
#include <linux/ftrace.h>

#include <asm/uaccess.h>
#include <asm/processor.h>
@@ -455,6 +456,16 @@ static struct ctl_table kern_table[] = {
		.mode		= 0644,
		.proc_handler	= &proc_dointvec,
	},
#ifdef CONFIG_FTRACE
	{
		.ctl_name	= CTL_UNNUMBERED,
		.procname	= "ftrace_enabled",
		.data		= &ftrace_enabled,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= &ftrace_enable_sysctl,
	},
#endif
#ifdef CONFIG_KMOD
	{
		.ctl_name	= KERN_MODPROBE,
+107 −18
Original line number Diff line number Diff line
@@ -20,12 +20,24 @@
#include <linux/hardirq.h>
#include <linux/ftrace.h>
#include <linux/module.h>
#include <linux/sysctl.h>
#include <linux/hash.h>
#include <linux/list.h>

#include "trace.h"

#ifdef CONFIG_DYNAMIC_FTRACE
# define FTRACE_ENABLED_INIT 1
#else
# define FTRACE_ENABLED_INIT 0
#endif

int ftrace_enabled = FTRACE_ENABLED_INIT;
static int last_ftrace_enabled = FTRACE_ENABLED_INIT;

static DEFINE_SPINLOCK(ftrace_lock);
static DEFINE_MUTEX(ftrace_sysctl_lock);

static struct ftrace_ops ftrace_list_end __read_mostly =
{
	.func = ftrace_stub,
@@ -78,6 +90,7 @@ static int notrace __register_ftrace_function(struct ftrace_ops *ops)
	smp_wmb();
	ftrace_list = ops;

	if (ftrace_enabled) {
		/*
		 * For one func, simply call it directly.
		 * For more than one func, call the chain.
@@ -86,6 +99,7 @@ static int notrace __register_ftrace_function(struct ftrace_ops *ops)
			ftrace_trace_function = ops->func;
		else
			ftrace_trace_function = ftrace_list_func;
	}

	spin_unlock(&ftrace_lock);

@@ -120,10 +134,12 @@ static int notrace __unregister_ftrace_function(struct ftrace_ops *ops)

	*p = (*p)->next;

	if (ftrace_enabled) {
		/* If we only have one func left, then call that directly */
		if (ftrace_list == &ftrace_list_end ||
		    ftrace_list->next == &ftrace_list_end)
			ftrace_trace_function = ftrace_list->func;
	}

 out:
	spin_unlock(&ftrace_lock);
@@ -263,6 +279,7 @@ static void notrace ftrace_startup(void)
		goto out;
	__unregister_ftrace_function(&ftrace_shutdown_ops);

	if (ftrace_enabled)
		ftrace_run_startup_code();
 out:
	mutex_unlock(&ftraced_lock);
@@ -275,6 +292,7 @@ static void notrace ftrace_shutdown(void)
	if (ftraced_suspend)
		goto out;

	if (ftrace_enabled)
		ftrace_run_shutdown_code();

	__register_ftrace_function(&ftrace_shutdown_ops);
@@ -282,6 +300,24 @@ static void notrace ftrace_shutdown(void)
	mutex_unlock(&ftraced_lock);
}

static void notrace ftrace_startup_sysctl(void)
{
	mutex_lock(&ftraced_lock);
	/* ftraced_suspend is true if we want ftrace running */
	if (ftraced_suspend)
		ftrace_run_startup_code();
	mutex_unlock(&ftraced_lock);
}

static void notrace ftrace_shutdown_sysctl(void)
{
	mutex_lock(&ftraced_lock);
	/* ftraced_suspend is true if ftrace is running */
	if (ftraced_suspend)
		ftrace_run_shutdown_code();
	mutex_unlock(&ftraced_lock);
}

static cycle_t		ftrace_update_time;
static unsigned long	ftrace_update_cnt;
unsigned long		ftrace_update_tot_cnt;
@@ -341,8 +377,9 @@ static int notrace ftraced(void *ignore)
		/* check once a second */
		schedule_timeout(HZ);

		mutex_lock(&ftrace_sysctl_lock);
		mutex_lock(&ftraced_lock);
		if (ftraced_trigger && !ftraced_suspend) {
		if (ftrace_enabled && ftraced_trigger && !ftraced_suspend) {
			ftrace_record_suspend++;
			ftrace_update_code();
			usecs = nsecs_to_usecs(ftrace_update_time);
@@ -360,6 +397,7 @@ static int notrace ftraced(void *ignore)
			ftrace_record_suspend--;
		}
		mutex_unlock(&ftraced_lock);
		mutex_unlock(&ftrace_sysctl_lock);

		ftrace_shutdown_replenish();

@@ -391,6 +429,8 @@ core_initcall(ftrace_shutdown_init);
#else
# define ftrace_startup()	  do { } while (0)
# define ftrace_shutdown()	  do { } while (0)
# define ftrace_startup_sysctl()  do { } while (0)
# define ftrace_shutdown_sysctl() do { } while (0)
#endif /* CONFIG_DYNAMIC_FTRACE */

/**
@@ -406,9 +446,15 @@ core_initcall(ftrace_shutdown_init);
 */
int register_ftrace_function(struct ftrace_ops *ops)
{
	int ret;

	mutex_lock(&ftrace_sysctl_lock);
	ftrace_startup();

	return __register_ftrace_function(ops);
	ret = __register_ftrace_function(ops);
	mutex_unlock(&ftrace_sysctl_lock);

	return ret;
}

/**
@@ -421,10 +467,53 @@ int unregister_ftrace_function(struct ftrace_ops *ops)
{
	int ret;

	mutex_lock(&ftrace_sysctl_lock);
	ret = __unregister_ftrace_function(ops);

	if (ftrace_list == &ftrace_list_end)
		ftrace_shutdown();

	mutex_unlock(&ftrace_sysctl_lock);

	return ret;
}

notrace int
ftrace_enable_sysctl(struct ctl_table *table, int write,
		     struct file *filp, void __user *buffer, size_t *lenp,
		     loff_t *ppos)
{
	int ret;

	mutex_lock(&ftrace_sysctl_lock);

	ret  = proc_dointvec(table, write, filp, buffer, lenp, ppos);

	if (ret || !write || (last_ftrace_enabled == ftrace_enabled))
		goto out;

	last_ftrace_enabled = ftrace_enabled;

	if (ftrace_enabled) {

		ftrace_startup_sysctl();

		/* we are starting ftrace again */
		if (ftrace_list != &ftrace_list_end) {
			if (ftrace_list->next == &ftrace_list_end)
				ftrace_trace_function = ftrace_list->func;
			else
				ftrace_trace_function = ftrace_list_func;
		}

	} else {
		/* stopping ftrace calls (just send to ftrace_stub) */
		ftrace_trace_function = ftrace_stub;

		ftrace_shutdown_sysctl();
	}

 out:
	mutex_unlock(&ftrace_sysctl_lock);
	return ret;
}