linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] ftrace: enable trampoline when rec count decrement to one
@ 2019-05-04 11:39 Cheng Jian
  2019-05-05 19:34 ` Steven Rostedt
  0 siblings, 1 reply; 4+ messages in thread
From: Cheng Jian @ 2019-05-04 11:39 UTC (permalink / raw)
  To: linux-kernel; +Cc: cj.chengjian, huawei.libin, xiexiuqi, rostedt, mingo

Trampoline can only be enabled if there is only a single ops
attached to it. If there's only a single callback registered
to a function, and the ops has a trampoline registered for it,
then we can call the trampoline directly. This is very useful
for improving the performance of ftrace and livepatch.

But we always disable trampoline when unregister ftrace. So if
you have registered multiple ftrace_ops at the same location,
even if the other ones have been unregistered, you will no longer
be able to use trampoline.

To fix it, set FTRACE_FL_TRAMP flag if rec count is decremented
to one, and the ops that left has a trampoline.

Testing After this patch :

insmod livepatch_unshare_files.ko
cat /sys/kernel/debug/tracing/enabled_functions

	unshare_files (1) R I	tramp: 0xffffffffc0000000(klp_ftrace_handler+0x0/0xa0) ->ftrace_ops_assist_func+0x0/0xf0

echo unshare_files > /sys/kernel/debug/tracing/set_ftrace_filter
echo function > /sys/kernel/debug/tracing/current_tracer
cat /sys/kernel/debug/tracing/enabled_functions

	unshare_files (2) R I ->ftrace_ops_list_func+0x0/0x150

echo nop > /sys/kernel/debug/tracing/current_tracer
cat /sys/kernel/debug/tracing/enabled_functions

	unshare_files (1) R I	tramp: 0xffffffffc0000000(klp_ftrace_handler+0x0/0xa0) ->ftrace_ops_assist_func+0x0/0xf0

Signed-off-by: Cheng Jian <cj.chengjian@huawei.com>
---
 kernel/trace/ftrace.c | 28 +++++++++++++++-------------
 1 file changed, 15 insertions(+), 13 deletions(-)

diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index b920358..bdc29c2 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -1626,6 +1626,11 @@ static bool test_rec_ops_needs_regs(struct dyn_ftrace *rec)
 	return  keep_regs;
 }
 
+static struct ftrace_ops *
+ftrace_find_tramp_ops_any(struct dyn_ftrace *rec);
+static struct ftrace_ops *
+ftrace_find_tramp_ops_next(struct dyn_ftrace *rec, struct ftrace_ops *ops);
+
 static bool __ftrace_hash_rec_update(struct ftrace_ops *ops,
 				     int filter_hash,
 				     bool inc)
@@ -1754,15 +1759,17 @@ static bool __ftrace_hash_rec_update(struct ftrace_ops *ops,
 			}
 
 			/*
-			 * If the rec had TRAMP enabled, then it needs to
-			 * be cleared. As TRAMP can only be enabled iff
-			 * there is only a single ops attached to it.
-			 * In otherwords, always disable it on decrementing.
-			 * In the future, we may set it if rec count is
-			 * decremented to one, and the ops that is left
-			 * has a trampoline.
+			 * The TRAMP needs to be set only if rec count
+			 * is decremented to one, and the ops that is
+			 * left has a trampoline. As TRAMP can only be
+			 * enabled if there is only a single ops attached
+			 * to it.
 			 */
-			rec->flags &= ~FTRACE_FL_TRAMP;
+			if (ftrace_rec_count(rec) == 1 &&
+			    ftrace_find_tramp_ops_any(rec))
+				rec->flags |= FTRACE_FL_TRAMP;
+			else
+				rec->flags &= ~FTRACE_FL_TRAMP;
 
 			/*
 			 * flags will be cleared in ftrace_check_record()
@@ -1955,11 +1962,6 @@ static void print_ip_ins(const char *fmt, const unsigned char *p)
 		printk(KERN_CONT "%s%02x", i ? ":" : "", p[i]);
 }
 
-static struct ftrace_ops *
-ftrace_find_tramp_ops_any(struct dyn_ftrace *rec);
-static struct ftrace_ops *
-ftrace_find_tramp_ops_next(struct dyn_ftrace *rec, struct ftrace_ops *ops);
-
 enum ftrace_bug_type ftrace_bug_type;
 const void *ftrace_expected;
 
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] ftrace: enable trampoline when rec count decrement to one
  2019-05-04 11:39 [PATCH] ftrace: enable trampoline when rec count decrement to one Cheng Jian
@ 2019-05-05 19:34 ` Steven Rostedt
  2019-05-08 15:02   ` chengjian (D)
  0 siblings, 1 reply; 4+ messages in thread
From: Steven Rostedt @ 2019-05-05 19:34 UTC (permalink / raw)
  To: Cheng Jian; +Cc: linux-kernel, huawei.libin, xiexiuqi, mingo

On Sat, 4 May 2019 19:39:39 +0800
Cheng Jian <cj.chengjian@huawei.com> wrote:

> Trampoline can only be enabled if there is only a single ops
> attached to it. If there's only a single callback registered
> to a function, and the ops has a trampoline registered for it,
> then we can call the trampoline directly. This is very useful
> for improving the performance of ftrace and livepatch.
> 
> But we always disable trampoline when unregister ftrace. So if
> you have registered multiple ftrace_ops at the same location,
> even if the other ones have been unregistered, you will no longer
> be able to use trampoline.
> 
> To fix it, set FTRACE_FL_TRAMP flag if rec count is decremented
> to one, and the ops that left has a trampoline.
> 
> Testing After this patch :
> 
> insmod livepatch_unshare_files.ko
> cat /sys/kernel/debug/tracing/enabled_functions
> 
> 	unshare_files (1) R I	tramp: 0xffffffffc0000000(klp_ftrace_handler+0x0/0xa0) ->ftrace_ops_assist_func+0x0/0xf0
> 
> echo unshare_files > /sys/kernel/debug/tracing/set_ftrace_filter
> echo function > /sys/kernel/debug/tracing/current_tracer
> cat /sys/kernel/debug/tracing/enabled_functions
> 
> 	unshare_files (2) R I ->ftrace_ops_list_func+0x0/0x150
> 
> echo nop > /sys/kernel/debug/tracing/current_tracer
> cat /sys/kernel/debug/tracing/enabled_functions
> 
> 	unshare_files (1) R I	tramp: 0xffffffffc0000000(klp_ftrace_handler+0x0/0xa0) ->ftrace_ops_assist_func+0x0/0xf0

Thanks for the patch. There was some race condition that prevented me
from doing this in the first place, but unfortunately, I don't remember
what that was :-/

I'll have to think about this before applying this patch.

Maybe there isn't a race condition, and I was just playing it safe, as
there was a race condition between switching from regs caller back to
non regs caller.

-- Steve


> 
> Signed-off-by: Cheng Jian <cj.chengjian@huawei.com>
> ---
>  kernel/trace/ftrace.c | 28 +++++++++++++++-------------
>  1 file changed, 15 insertions(+), 13 deletions(-)
> 
> diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
> index b920358..bdc29c2 100644
> --- a/kernel/trace/ftrace.c
> +++ b/kernel/trace/ftrace.c
> @@ -1626,6 +1626,11 @@ static bool test_rec_ops_needs_regs(struct
> dyn_ftrace *rec) return  keep_regs;
>  }
>  
> +static struct ftrace_ops *
> +ftrace_find_tramp_ops_any(struct dyn_ftrace *rec);
> +static struct ftrace_ops *
> +ftrace_find_tramp_ops_next(struct dyn_ftrace *rec, struct ftrace_ops
> *ops); +
>  static bool __ftrace_hash_rec_update(struct ftrace_ops *ops,
>  				     int filter_hash,
>  				     bool inc)
> @@ -1754,15 +1759,17 @@ static bool __ftrace_hash_rec_update(struct
> ftrace_ops *ops, }
>  
>  			/*
> -			 * If the rec had TRAMP enabled, then it
> needs to
> -			 * be cleared. As TRAMP can only be enabled
> iff
> -			 * there is only a single ops attached to it.
> -			 * In otherwords, always disable it on
> decrementing.
> -			 * In the future, we may set it if rec count
> is
> -			 * decremented to one, and the ops that is
> left
> -			 * has a trampoline.
> +			 * The TRAMP needs to be set only if rec
> count
> +			 * is decremented to one, and the ops that is
> +			 * left has a trampoline. As TRAMP can only
> be
> +			 * enabled if there is only a single ops
> attached
> +			 * to it.
>  			 */
> -			rec->flags &= ~FTRACE_FL_TRAMP;
> +			if (ftrace_rec_count(rec) == 1 &&
> +			    ftrace_find_tramp_ops_any(rec))
> +				rec->flags |= FTRACE_FL_TRAMP;
> +			else
> +				rec->flags &= ~FTRACE_FL_TRAMP;
>  
>  			/*
>  			 * flags will be cleared in
> ftrace_check_record() @@ -1955,11 +1962,6 @@ static void
> print_ip_ins(const char *fmt, const unsigned char *p)
> printk(KERN_CONT "%s%02x", i ? ":" : "", p[i]); }
>  
> -static struct ftrace_ops *
> -ftrace_find_tramp_ops_any(struct dyn_ftrace *rec);
> -static struct ftrace_ops *
> -ftrace_find_tramp_ops_next(struct dyn_ftrace *rec, struct ftrace_ops
> *ops); -
>  enum ftrace_bug_type ftrace_bug_type;
>  const void *ftrace_expected;
>  


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] ftrace: enable trampoline when rec count decrement to one
  2019-05-05 19:34 ` Steven Rostedt
@ 2019-05-08 15:02   ` chengjian (D)
  2019-05-08 16:53     ` Steven Rostedt
  0 siblings, 1 reply; 4+ messages in thread
From: chengjian (D) @ 2019-05-08 15:02 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: linux-kernel, huawei.libin, xiexiuqi, mingo, chengjian (D),
	bobo.shaobowang

Hi, Steven


On 2019/5/6 3:34, Steven Rostedt wrote:
>
> Thanks for the patch. There was some race condition that prevented me
> from doing this in the first place, but unfortunately, I don't remember
> what that was :-/
>
> I'll have to think about this before applying this patch.
>
> Maybe there isn't a race condition, and I was just playing it safe, as
> there was a race condition between switching from regs caller back to
> non regs caller.
>
> -- Steve
> .


function tracer uses ftrace_caller() and livepatch uses 
ftrace_regs_caller().

I can modify my testcase to trigger this race condition.


#enable livepatch
insmod klp_unshare_files.ko
cat /sys/kernel/debug/tracing/enabled_functions
         unshare_files (1) R I	tramp: 0xffffffffc0008000 (klp_ftrace_handler+0x0/0xa0) ->ftrace_ops_assist_func+0x0/0xf0
[NOW, the rec caller is ftracer_regs_caller TRAMPOLINE]

#function tracer
echo unshare_files > /sys/kernel/debug/tracing/set_ftrace_filter
echo function > /sys/kernel/debug/tracing/current_tracer
cat /sys/kernel/debug/tracing/enabled_functions
         unshare_files (2) R I ->ftrace_ops_list_func+0x0/0x170
[NOW, the rec caller is ftracer_regs_caller]


# disable livepatch
echo 0 > /sys/kernel/livepatch/klp_unshare_files/enabled
rmmod klp_unshare_files


cat /sys/kernel/debug/tracing/enabled_functions
         unshare_files (1)    	tramp: 0xffffffffc0005000 (function_trace_call+0x0/0x120) ->function_trace_call+0x0/0x120
[NOW, the rec caller is ftrace_caller TRAMPOLINE]

So, the caller switch from regs caller back to non regs caller
when disable the livepatch. Could this testcase cause the race
condition ? BUT, Nothing happened here.

What will happen when the race triggers ? What can I do.


Thanks.

Cheng Jian.





^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] ftrace: enable trampoline when rec count decrement to one
  2019-05-08 15:02   ` chengjian (D)
@ 2019-05-08 16:53     ` Steven Rostedt
  0 siblings, 0 replies; 4+ messages in thread
From: Steven Rostedt @ 2019-05-08 16:53 UTC (permalink / raw)
  To: chengjian (D)
  Cc: linux-kernel, huawei.libin, xiexiuqi, mingo, bobo.shaobowang

On Wed, 8 May 2019 23:02:33 +0800
"chengjian (D)" <cj.chengjian@huawei.com> wrote:

> function tracer uses ftrace_caller() and livepatch uses 
> ftrace_regs_caller().
> 
> I can modify my testcase to trigger this race condition.
> 
> 
> #enable livepatch
> insmod klp_unshare_files.ko
> cat /sys/kernel/debug/tracing/enabled_functions
>          unshare_files (1) R I	tramp: 0xffffffffc0008000 (klp_ftrace_handler+0x0/0xa0) ->ftrace_ops_assist_func+0x0/0xf0
> [NOW, the rec caller is ftracer_regs_caller TRAMPOLINE]
> 
> #function tracer
> echo unshare_files > /sys/kernel/debug/tracing/set_ftrace_filter
> echo function > /sys/kernel/debug/tracing/current_tracer
> cat /sys/kernel/debug/tracing/enabled_functions
>          unshare_files (2) R I ->ftrace_ops_list_func+0x0/0x170
> [NOW, the rec caller is ftracer_regs_caller]
> 
> 
> # disable livepatch
> echo 0 > /sys/kernel/livepatch/klp_unshare_files/enabled
> rmmod klp_unshare_files
> 
> 
> cat /sys/kernel/debug/tracing/enabled_functions
>          unshare_files (1)    	tramp: 0xffffffffc0005000 (function_trace_call+0x0/0x120) ->function_trace_call+0x0/0x120
> [NOW, the rec caller is ftrace_caller TRAMPOLINE]
> 
> So, the caller switch from regs caller back to non regs caller
> when disable the livepatch. Could this testcase cause the race
> condition ? BUT, Nothing happened here.
> 
> What will happen when the race triggers ? What can I do.
> 

I still can't think of it. But since the merge window already opened,
I'd like to have this patch sit in linux-next for a bit. That is, I
would wait to pull it in for the next merge window, and not this one.

-- Steve

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2019-05-08 16:53 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-05-04 11:39 [PATCH] ftrace: enable trampoline when rec count decrement to one Cheng Jian
2019-05-05 19:34 ` Steven Rostedt
2019-05-08 15:02   ` chengjian (D)
2019-05-08 16:53     ` Steven Rostedt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).