public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Petr Mladek <pmladek@suse.com>
To: Steven Rostedt <rostedt@goodmis.org>, Ingo Molnar <mingo@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>,
	Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>,
	Jiri Kosina <jkosina@suse.cz>,
	linux-kernel@vger.kernel.org, x86@kernel.org,
	Petr Mladek <pmladek@suse.com>
Subject: [PATCH 3/4] ftrace: Always destroy trampoline when shutting down the trace
Date: Mon, 27 Jun 2016 15:54:36 +0200	[thread overview]
Message-ID: <1467035677-12193-4-git-send-email-pmladek@suse.com> (raw)
In-Reply-To: <1467035677-12193-1-git-send-email-pmladek@suse.com>

If have got the following kmemleak report when I enabled the ftrace self
test:

unreferenced object 0xffffffffa000a000 (size 179):
  comm "swapper/0", pid 1, jiffies 4294892507 (age 82553.780s)
  hex dump (first 32 bytes):
    55 ff 74 24 10 55 48 89 e5 ff 74 24 18 55 48 89  U.t$.UH...t$.UH.
    e5 48 81 ec a8 00 00 00 48 89 44 24 50 48 89 4c  .H......H.D$PH.L
  backtrace:
    [<ffffffff81915918>] kmemleak_alloc+0x28/0x50
    [<ffffffff811d7474>] __vmalloc_node_range+0x184/0x270
    [<ffffffff8104a463>] module_alloc+0x63/0x70
    [<ffffffff81046726>] arch_ftrace_update_trampoline+0x96/0x230
    [<ffffffff81149de6>] ftrace_startup+0x76/0x200
    [<ffffffff8114a330>] register_ftrace_function+0x50/0x70
    [<ffffffff8118e312>] trace_selftest_ops+0x1b8/0x308
    [<ffffffff81ff8b20>] trace_selftest_startup_function+0x25b/0x4a8
    [<ffffffff81ff9002>] register_tracer+0x1a7/0x2ec
    [<ffffffff81ff9753>] init_function_trace+0x90/0x92
    [<ffffffff810003b8>] do_one_initcall+0x88/0x1c0
    [<ffffffff81fd22dc>] kernel_init_freeable+0x1f9/0x289
    [<ffffffff81912d1e>] kernel_init+0xe/0x110
    [<ffffffff81920cf2>] ret_from_fork+0x22/0x50
    [<ffffffffffffffff>] 0xffffffffffffffff

It is ops->trampoline that gets allocated for dyn_ops in
trace_selftest_ops(). It is from the 2nd round when cnt == 2.
In this case, the default trampoline must be used because
there are two callbacks added to all functions, namely
trace_selftest_test_global_func() and trace_selftest_test_dyn_func().

It seems that we forget to free ops->trampoline when the ftrace function
gets unregistered and the trampoline is not being used.

This patch creates ftrace_ops_free() to share the code and avoid
such problems in the future.

Signed-off-by: Petr Mladek <pmladek@suse.com>
---
 kernel/trace/ftrace.c | 62 ++++++++++++++++++++++++++-------------------------
 1 file changed, 32 insertions(+), 30 deletions(-)

diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index a6804823a058..39f90bdb0f44 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -2678,6 +2678,36 @@ static int ftrace_startup(struct ftrace_ops *ops, int command)
 	return 0;
 }
 
+/*
+ * Dynamic ops may be freed, we must make sure that all callers are done
+ * before leaving this function. The same goes for freeing the per_cpu
+ * data of the per_cpu ops.
+ *
+ * Again, normal synchronize_sched() is not good enough. We need to do
+ * a hard force of sched synchronization. This is because we use
+ * preempt_disable() to do RCU, but the function tracers can be called
+ * where RCU is not watching (like before user_exit()). We can not rely
+ * on the RCU infrastructure to do the synchronization, thus we must do
+ * it ourselves.
+ *
+ * The synchronization is not needed when the function tracing is not
+ * active at the moment.
+ */
+static void ftrace_ops_free(struct ftrace_ops *ops, bool sync)
+{
+	if (!(ops->flags & (FTRACE_OPS_FL_DYNAMIC | FTRACE_OPS_FL_PER_CPU)))
+		return;
+
+	if (sync)
+		schedule_on_each_cpu(ftrace_sync);
+
+	if (ops->flags & FTRACE_OPS_FL_DYNAMIC)
+		arch_ftrace_trampoline_free(ops);
+
+	if (ops->flags & FTRACE_OPS_FL_PER_CPU)
+		per_cpu_ops_free(ops);
+}
+
 static int ftrace_shutdown(struct ftrace_ops *ops, int command)
 {
 	int ret;
@@ -2711,14 +2741,7 @@ static int ftrace_shutdown(struct ftrace_ops *ops, int command)
 	}
 
 	if (!command || !ftrace_enabled) {
-		/*
-		 * If these are per_cpu ops, they still need their
-		 * per_cpu field freed. Since, function tracing is
-		 * not currently active, we can just free them
-		 * without synchronizing all CPUs.
-		 */
-		if (ops->flags & FTRACE_OPS_FL_PER_CPU)
-			per_cpu_ops_free(ops);
+		ftrace_ops_free(ops, false);
 		return 0;
 	}
 
@@ -2756,28 +2779,7 @@ static int ftrace_shutdown(struct ftrace_ops *ops, int command)
 	removed_ops = NULL;
 	ops->flags &= ~FTRACE_OPS_FL_REMOVING;
 
-	/*
-	 * Dynamic ops may be freed, we must make sure that all
-	 * callers are done before leaving this function.
-	 * The same goes for freeing the per_cpu data of the per_cpu
-	 * ops.
-	 *
-	 * Again, normal synchronize_sched() is not good enough.
-	 * We need to do a hard force of sched synchronization.
-	 * This is because we use preempt_disable() to do RCU, but
-	 * the function tracers can be called where RCU is not watching
-	 * (like before user_exit()). We can not rely on the RCU
-	 * infrastructure to do the synchronization, thus we must do it
-	 * ourselves.
-	 */
-	if (ops->flags & (FTRACE_OPS_FL_DYNAMIC | FTRACE_OPS_FL_PER_CPU)) {
-		schedule_on_each_cpu(ftrace_sync);
-
-		arch_ftrace_trampoline_free(ops);
-
-		if (ops->flags & FTRACE_OPS_FL_PER_CPU)
-			per_cpu_ops_free(ops);
-	}
+	ftrace_ops_free(ops, true);
 
 	return 0;
 }
-- 
1.8.5.6

  parent reply	other threads:[~2016-06-27 13:54 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-06-27 13:54 [PATCH 0/4] ftrace: One more check on x86 and some small fixes Petr Mladek
2016-06-27 13:54 ` [PATCH 1/4] ftrace/x86: Make sure to modify 5-bite instructions Petr Mladek
2016-06-27 13:54 ` [PATCH 2/4] ftrace/x86: Do not crash when reading wrong ftrace func Petr Mladek
2016-06-27 14:48   ` Steven Rostedt
2016-06-28 10:00     ` Petr Mladek
2016-06-27 13:54 ` Petr Mladek [this message]
2016-06-27 13:54 ` [PATCH 4/4] ftrace: Fixup trace_selftest_ops() Petr Mladek
2016-06-28  5:22 ` [PATCH 0/4] ftrace: One more check on x86 and some small fixes Namhyung Kim
2016-06-28 19:17 ` Steven Rostedt
2016-06-29  8:22   ` Petr Mladek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1467035677-12193-4-git-send-email-pmladek@suse.com \
    --to=pmladek@suse.com \
    --cc=fweisbec@gmail.com \
    --cc=jkosina@suse.cz \
    --cc=linux-kernel@vger.kernel.org \
    --cc=masami.hiramatsu.pt@hitachi.com \
    --cc=mingo@redhat.com \
    --cc=rostedt@goodmis.org \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox