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
next prev 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