Skip to contentSkip to conversation

tracing: Updates for 3.17

PATCH In review Steven Rostedt 2 participants 28 messages Jul 3, 2014 – Jul 14, 2014

Subsystems (7)
Documentation Arm (32-bit) x86 SCSI +3 more subsystems
lore
Share & tools
lore

Steven Rostedt

author maintainer
#0 lore raw

cover tracing: Updates for 3.17

This is my current 3.17 queue. I'm still waiting on acks from various arch maintainers to add the ftrace_stop/start() removal code that I also want to add to this.

This includes various clean ups and enhancements, but the big feature is the "trampoline" field added to the ftrace_ops. The only user of that currently is the function_graph tracer. This is because the function graph tracer normally jumps to the function tracer mcount trampoline, saves and restores regs without doing anything before it gets to the function graph code that also saves and restores regs (slightly differently mind you), and runs its code. Now, if function graph tracer is the only callback of a function, its code will be called directly, skipping the function trampoline entirely.

The trace_seq code was also cleaned up. This opens up the possibility that the trace_seq can be converted to "seq_buf" and used for printing in NMI context.

I'm still waiting on a Acked-by from the SCSI folks for a change to the trace_seq code that removes some open access of the trace_seq buffer. I wont push this to my next branch until I hear back from them.

The way to push will also let people give me feedback before this becomes solidified in stone, as I don't like to rebase my for-next branch.

-- Steve

git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git
for-next

Head SHA1: d048a8c7b509f35dd351e1415fe49fa99e4cb7ef

Fabian Frederick (2):
tracing: Remove unnecessary null test before debugfs_remove()
tracing: Convert pr_warning() to pr_warn() in trace_events.c

Masami Hiramatsu (1):
ftrace: Simplify ftrace_hash_disable/enable path in ftrace_hash_move

Namhyung Kim (7):
ftrace: Get rid of obsolete global_start_up variable
ftrace: Fix memory leak on failure path in ftrace_allocate_pages()
ftrace: Do not copy hash if O_TRUNC is set
tracing: Add ftrace_graph_notrace boot parameter
tracing: Improve message of empty set_graph_notrace file
tracing: Improve message of empty set_ftrace_notrace file
tracing: Add description of set_graph_notrace to tracing/README

Steven Rostedt (Red Hat) (10):
ftrace: Allow no regs if no more callbacks require it
ftrace: Use macros for numbers in ftrace rec shift bits
ftrace: Add ftrace_rec_counter() macro to simplify the code
ftrace: Optimize function graph to be called directly
ftrace: Add trampolines to enabled_functions debug file
tracing: Move the trace_seq_* functions into its own trace_seq.c file
tracing: Clean up trace_seq.c
tracing: Make trace_seq_putmem_hex() more robust
tracing: Remove trace_seq_reserve()
tracing: Add trace_seq_buffer_ptr() helper function

Zhao Hongjiang (1):
tracing: Change trace event sample to use strlcpy instead of strncpy

----

 Documentation/kernel-parameters.txt        |   6 +
 arch/x86/kernel/mcount_64.S                |   5 +
 arch/x86/kvm/mmutrace.h                    |   2 +-
 drivers/scsi/scsi_trace.c                  |  16 +-
 include/linux/ftrace.h                     |  24 +-
 include/linux/trace_seq.h                  |  36 ++-
 kernel/trace/Makefile                      |   1 +
 kernel/trace/ftrace.c                      | 394 ++++++++++++++++++++++----
 kernel/trace/trace.c                       |  31 +--
 kernel/trace/trace_events.c                |  56 ++--
 kernel/trace/trace_output.c                | 282 +------------------
 kernel/trace/trace_output.h                |   4 -
 kernel/trace/trace_seq.c                   | 428 +++++++++++++++++++++++++++++
 samples/trace_events/trace-events-sample.h |   2 +-
 14 files changed, 870 insertions(+), 417 deletions(-)
author maintainer
#1 lore raw

PATCH 1/21 ftrace: Allow no regs if no more callbacks require it

From: "Steven Rostedt (Red Hat)" <[email protected]>

When registering a function callback for the function tracer, the ops can specify if it wants to save full regs (like an interrupt would) for each function that it traces, or if it does not care about regs and just wants to have the fastest return possible.

Once a ops has registered a function, if other ops register that function they all will receive the regs too. That's because it does the work once, it does it for everyone.

Now if the ops wanting regs unregisters the function so that there's only ops left that do not care about regs, those ops will still continue getting regs and going through the work for it on that function. This is because the disabling of the rec counter only sees the ops registered, and does not see the ops that are still attached, and does not know if the current ops that are still attached want regs or not. To play it safe, it just keeps regs being processed until no function is registered anymore.

Instead of doing that, check the ops that are still registered for that function and if none want regs for it anymore, then disable the processing of regs.

---
 kernel/trace/ftrace.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)
kernel/trace/ftrace.c +32 -0
index 5b372e3ed675..b867c647e5bc 100644
@@ -1492,6 +1492,26 @@ int ftrace_text_reserved(const void *start, const void *end)
 	return (int)!!ret;
 }
 
+/* Test if ops registered to this rec needs regs */
+static bool test_rec_ops_needs_regs(struct dyn_ftrace *rec)
+{
+	struct ftrace_ops *ops;
+	bool keep_regs = false;
+
+	for (ops = ftrace_ops_list;
+	     ops != &ftrace_list_end; ops = ops->next) {
+		/* pass rec in as regs to have non-NULL val */
+		if (ftrace_ops_test(ops, rec->ip, rec)) {
+			if (ops->flags & FTRACE_OPS_FL_SAVE_REGS) {
+				keep_regs = true;
+				break;
+			}
+		}
+	}
+
+	return  keep_regs;
+}
+
 static void __ftrace_hash_rec_update(struct ftrace_ops *ops,
 				     int filter_hash,
 				     bool inc)
@@ -1584,6 +1604,18 @@ static void __ftrace_hash_rec_update(struct ftrace_ops *ops,
 			if (FTRACE_WARN_ON((rec->flags & ~FTRACE_FL_MASK) == 0))
 				return;
 			rec->flags--;
+			/*
+			 * If the rec had REGS enabled and the ops that is
+			 * being removed had REGS set, then see if there is
+			 * still any ops for this record that wants regs.
+			 * If not, we can stop recording them.
+			 */
+			if ((rec->flags & ~FTRACE_FL_MASK) > 0 &&
+			    rec->flags & FTRACE_FL_REGS &&
+			    ops->flags & FTRACE_OPS_FL_SAVE_REGS) {
+				if (!test_rec_ops_needs_regs(rec))
+					rec->flags &= ~FTRACE_FL_REGS;
+			}
 		}
 		count++;
 		/* Shortcut, if we handled all records, we are done. */
Signature · 1 line
2.0.0
author maintainer
#2 lore raw

PATCH 2/21 ftrace: Use macros for numbers in ftrace rec shift bits

In reply to Steven Rostedt

From: "Steven Rostedt (Red Hat)" <[email protected]>

As new flags will be added to the ftrace dynamic record, and since the flags field is also a counter, converting the numbers used to do the shifting and masking into a set of macros where we only need to deal with the max bit count of the counter and the number of bits for the flags will prevent mistakes in the future.

Dealing with only two numbers is much easier than updating all the macros that deal with shifting and masking.

---
 include/linux/ftrace.h | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
include/linux/ftrace.h +5 -2
index 404a686a3644..e4e7df422021 100644
@@ -322,8 +322,11 @@ enum {
 	FTRACE_FL_REGS_EN	= (1UL << 31)
 };
 
-#define FTRACE_FL_MASK		(0x7UL << 29)
-#define FTRACE_REF_MAX		((1UL << 29) - 1)
+#define FTRACE_REF_MAX_SHIFT	29
+#define FTRACE_FL_BITS		3
+#define FTRACE_FL_MASKED_BITS	((1UL << FTRACE_FL_BITS) - 1)
+#define FTRACE_FL_MASK		(FTRACE_FL_MASKED_BITS << FTRACE_REF_MAX_SHIFT)
+#define FTRACE_REF_MAX		((1UL << FTRACE_REF_MAX_SHIFT) - 1)
 
 struct dyn_ftrace {
 	unsigned long		ip; /* address of mcount call-site */
Signature · 1 line
2.0.0
author maintainer
#3 lore raw

PATCH 3/21 ftrace: Add ftrace_rec_counter() macro to simplify the code

In reply to Steven Rostedt

From: "Steven Rostedt (Red Hat)" <[email protected]>

The ftrace dynamic record has a flags element that also has a counter. Instead of hard coding "rec->flags & ~FTRACE_FL_MASK" all over the place. Use a macro instead.

---
 include/linux/ftrace.h |  2 ++
 kernel/trace/ftrace.c  | 12 ++++++------
 2 files changed, 8 insertions(+), 6 deletions(-)
include/linux/ftrace.h +2 -0
index e4e7df422021..e5baa6b2c93f 100644
@@ -328,6 +328,8 @@ enum {
 #define FTRACE_FL_MASK		(FTRACE_FL_MASKED_BITS << FTRACE_REF_MAX_SHIFT)
 #define FTRACE_REF_MAX		((1UL << FTRACE_REF_MAX_SHIFT) - 1)
 
+#define ftrace_rec_count(rec)	((rec)->flags & ~FTRACE_FL_MASK)
+
 struct dyn_ftrace {
 	unsigned long		ip; /* address of mcount call-site */
 	unsigned long		flags;
kernel/trace/ftrace.c +6 -6
index b867c647e5bc..a58d840305c3 100644
@@ -1592,7 +1592,7 @@ static void __ftrace_hash_rec_update(struct ftrace_ops *ops,
 
 		if (inc) {
 			rec->flags++;
-			if (FTRACE_WARN_ON((rec->flags & ~FTRACE_FL_MASK) == FTRACE_REF_MAX))
+			if (FTRACE_WARN_ON(ftrace_rec_count(rec) == FTRACE_REF_MAX))
 				return;
 			/*
 			 * If any ops wants regs saved for this function
@@ -1601,7 +1601,7 @@ static void __ftrace_hash_rec_update(struct ftrace_ops *ops,
 			if (ops->flags & FTRACE_OPS_FL_SAVE_REGS)
 				rec->flags |= FTRACE_FL_REGS;
 		} else {
-			if (FTRACE_WARN_ON((rec->flags & ~FTRACE_FL_MASK) == 0))
+			if (FTRACE_WARN_ON(ftrace_rec_count(rec) == 0))
 				return;
 			rec->flags--;
 			/*
@@ -1610,7 +1610,7 @@ static void __ftrace_hash_rec_update(struct ftrace_ops *ops,
 			 * still any ops for this record that wants regs.
 			 * If not, we can stop recording them.
 			 */
-			if ((rec->flags & ~FTRACE_FL_MASK) > 0 &&
+			if (ftrace_rec_count(rec) > 0 &&
 			    rec->flags & FTRACE_FL_REGS &&
 			    ops->flags & FTRACE_OPS_FL_SAVE_REGS) {
 				if (!test_rec_ops_needs_regs(rec))
@@ -1700,7 +1700,7 @@ static int ftrace_check_record(struct dyn_ftrace *rec, int enable, int update)
 	 * If we are disabling calls, then disable all records that
 	 * are enabled.
 	 */
-	if (enable && (rec->flags & ~FTRACE_FL_MASK))
+	if (enable && ftrace_rec_count(rec))
 		flag = FTRACE_FL_ENABLED;
 
 	/*
@@ -1746,7 +1746,7 @@ static int ftrace_check_record(struct dyn_ftrace *rec, int enable, int update)
 
 	if (update) {
 		/* If there's no more users, clear all flags */
-		if (!(rec->flags & ~FTRACE_FL_MASK))
+		if (!ftrace_rec_count(rec))
 			rec->flags = 0;
 		else
 			/* Just disable the record (keep REGS state) */
@@ -2685,7 +2685,7 @@ static int t_show(struct seq_file *m, void *v)
 	seq_printf(m, "%ps", (void *)rec->ip);
 	if (iter->flags & FTRACE_ITER_ENABLED)
 		seq_printf(m, " (%ld)%s",
-			   rec->flags & ~FTRACE_FL_MASK,
+			   ftrace_rec_count(rec),
 			   rec->flags & FTRACE_FL_REGS ? " R" : "");
 	seq_printf(m, "\n");
 
Signature · 1 line
2.0.0
author maintainer
#4 lore raw

PATCH 4/21 ftrace: Optimize function graph to be called directly

In reply to Steven Rostedt

From: "Steven Rostedt (Red Hat)" <[email protected]>

Function graph tracing is a bit different than the function tracers, as it is processed after either the ftrace_caller or ftrace_regs_caller and we only have one place to modify the jump to ftrace_graph_caller, the jump needs to happen after the restore of registeres.

The function graph tracer is dependent on the function tracer, where even if the function graph tracing is going on by itself, the save and restore of registers is still done for function tracing regardless of if function tracing is happening, before it calls the function graph code.

If there's no function tracing happening, it is possible to just call the function graph tracer directly, and avoid the wasted effort to save and restore regs for function tracing.

This requires adding new flags to the dyn_ftrace records:

FTRACE_FL_TRAMP
FTRACE_FL_TRAMP_EN

The first is set if the count for the record is one, and the ftrace_ops associated to that record has its own trampoline. That way the mcount code can call that trampoline directly.

In the future, trampolines can be added to arbitrary ftrace_ops, where you can have two or more ftrace_ops registered to ftrace (like kprobes and perf) and if they are not tracing the same functions, then instead of doing a loop to check all registered ftrace_ops against their hashes, just call the ftrace_ops trampoline directly, which would call the registered ftrace_ops function directly.

Without this patch perf showed:

  0.05%  hackbench  [kernel.kallsyms]  [k] ftrace_caller
  0.05%  hackbench  [kernel.kallsyms]  [k] arch_local_irq_save
  0.05%  hackbench  [kernel.kallsyms]  [k] native_sched_clock
  0.04%  hackbench  [kernel.kallsyms]  [k] __buffer_unlock_commit
  0.04%  hackbench  [kernel.kallsyms]  [k] preempt_trace
  0.04%  hackbench  [kernel.kallsyms]  [k] prepare_ftrace_return
  0.04%  hackbench  [kernel.kallsyms]  [k] __this_cpu_preempt_check
  0.04%  hackbench  [kernel.kallsyms]  [k] ftrace_graph_caller

See that the ftrace_caller took up more time than the ftrace_graph_caller did.

With this patch:

  0.05%  hackbench  [kernel.kallsyms]  [k] __buffer_unlock_commit
  0.04%  hackbench  [kernel.kallsyms]  [k] call_filter_check_discard
  0.04%  hackbench  [kernel.kallsyms]  [k] ftrace_graph_caller
  0.04%  hackbench  [kernel.kallsyms]  [k] sched_clock

The ftrace_caller is no where to be found and ftrace_graph_caller still takes up the same percentage.

---
 arch/x86/kernel/mcount_64.S |   5 +
 include/linux/ftrace.h      |  19 +++-
 kernel/trace/ftrace.c       | 242 ++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 254 insertions(+), 12 deletions(-)
arch/x86/kernel/mcount_64.S +5 -0
index c050a0153168..6b4e3c3b3d74 100644
@@ -182,6 +182,10 @@ END(function_hook)
 ENTRY(ftrace_graph_caller)
 	MCOUNT_SAVE_FRAME
 
+	/* Check if tracing was disabled (quick check) */
+	cmpl $0, function_trace_stop
+	jne  fgraph_skip
+
 #ifdef CC_USING_FENTRY
 	leaq SS+16(%rsp), %rdi
 	movq $0, %rdx	/* No framepointers needed */
@@ -194,6 +198,7 @@ ENTRY(ftrace_graph_caller)
 
 	call	prepare_ftrace_return
 
+fgraph_skip:
 	MCOUNT_RESTORE_FRAME
 
 	retq
include/linux/ftrace.h +14 -5
index e5baa6b2c93f..11e18fd58b1a 100644
@@ -118,12 +118,15 @@ struct ftrace_ops {
 	ftrace_func_t			func;
 	struct ftrace_ops		*next;
 	unsigned long			flags;
-	int __percpu			*disabled;
 	void				*private;
+	int __percpu			*disabled;
 #ifdef CONFIG_DYNAMIC_FTRACE
+	int				trampolines;
 	struct ftrace_hash		*notrace_hash;
 	struct ftrace_hash		*filter_hash;
+	struct ftrace_hash		*tramp_hash;
 	struct mutex			regex_lock;
+	unsigned long			trampoline;
 #endif
 };
 
@@ -317,13 +320,15 @@ extern int ftrace_nr_registered_ops(void);
  * from tracing that function.
  */
 enum {
-	FTRACE_FL_ENABLED	= (1UL << 29),
+	FTRACE_FL_ENABLED	= (1UL << 31),
 	FTRACE_FL_REGS		= (1UL << 30),
-	FTRACE_FL_REGS_EN	= (1UL << 31)
+	FTRACE_FL_REGS_EN	= (1UL << 29),
+	FTRACE_FL_TRAMP		= (1UL << 28),
+	FTRACE_FL_TRAMP_EN	= (1UL << 27),
 };
 
-#define FTRACE_REF_MAX_SHIFT	29
-#define FTRACE_FL_BITS		3
+#define FTRACE_REF_MAX_SHIFT	27
+#define FTRACE_FL_BITS		5
 #define FTRACE_FL_MASKED_BITS	((1UL << FTRACE_FL_BITS) - 1)
 #define FTRACE_FL_MASK		(FTRACE_FL_MASKED_BITS << FTRACE_REF_MAX_SHIFT)
 #define FTRACE_REF_MAX		((1UL << FTRACE_REF_MAX_SHIFT) - 1)
@@ -436,6 +441,10 @@ void ftrace_modify_all_code(int command);
 #define FTRACE_ADDR ((unsigned long)ftrace_caller)
 #endif
 
+#ifndef FTRACE_GRAPH_ADDR
+#define FTRACE_GRAPH_ADDR ((unsigned long)ftrace_graph_caller)
+#endif
+
 #ifndef FTRACE_REGS_ADDR
 #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
 # define FTRACE_REGS_ADDR ((unsigned long)ftrace_regs_caller)
kernel/trace/ftrace.c +235 -7

341 lines not on this page · raw message

Signature · 1 line
2.0.0
#5 lore raw

Re: [for-next][PATCH 04/21] ftrace: Optimize function graph to be called directly

Quoted 57 lines · Steven Rostedt

From: "Steven Rostedt (Red Hat)"<[email protected]>

Function graph tracing is a bit different than the function tracers, as it is processed after either the ftrace_caller or ftrace_regs_caller and we only have one place to modify the jump to ftrace_graph_caller, the jump needs to happen after the restore of registeres.

The function graph tracer is dependent on the function tracer, where even if the function graph tracing is going on by itself, the save and restore of registers is still done for function tracing regardless of if function tracing is happening, before it calls the function graph code.

If there's no function tracing happening, it is possible to just call the function graph tracer directly, and avoid the wasted effort to save and restore regs for function tracing.

This requires adding new flags to the dyn_ftrace records:

FTRACE_FL_TRAMP
FTRACE_FL_TRAMP_EN

The first is set if the count for the record is one, and the ftrace_ops associated to that record has its own trampoline. That way the mcount code can call that trampoline directly.

In the future, trampolines can be added to arbitrary ftrace_ops, where you can have two or more ftrace_ops registered to ftrace (like kprobes and perf) and if they are not tracing the same functions, then instead of doing a loop to check all registered ftrace_ops against their hashes, just call the ftrace_ops trampoline directly, which would call the registered ftrace_ops function directly.

Without this patch perf showed:

   0.05%  hackbench  [kernel.kallsyms]  [k] ftrace_caller
   0.05%  hackbench  [kernel.kallsyms]  [k] arch_local_irq_save
   0.05%  hackbench  [kernel.kallsyms]  [k] native_sched_clock
   0.04%  hackbench  [kernel.kallsyms]  [k] __buffer_unlock_commit
   0.04%  hackbench  [kernel.kallsyms]  [k] preempt_trace
   0.04%  hackbench  [kernel.kallsyms]  [k] prepare_ftrace_return
   0.04%  hackbench  [kernel.kallsyms]  [k] __this_cpu_preempt_check
   0.04%  hackbench  [kernel.kallsyms]  [k] ftrace_graph_caller

See that the ftrace_caller took up more time than the ftrace_graph_caller did.

With this patch:

   0.05%  hackbench  [kernel.kallsyms]  [k] __buffer_unlock_commit
   0.04%  hackbench  [kernel.kallsyms]  [k] call_filter_check_discard
   0.04%  hackbench  [kernel.kallsyms]  [k] ftrace_graph_caller
   0.04%  hackbench  [kernel.kallsyms]  [k] sched_clock

The ftrace_caller is no where to be found and ftrace_graph_caller still takes up the same percentage.

Quoted 7 lines
---
  arch/x86/kernel/mcount_64.S |   5 +
  include/linux/ftrace.h      |  19 +++-
  kernel/trace/ftrace.c       | 242 ++++++++++++++++++++++++++++++++++++++++++--
  3 files changed, 254 insertions(+), 12 deletions(-)

This commit (79922b8) breaks the function graph tracer on today's -next. This is on an ARM Tegra board.

I'm using ftrace with this script:

#!/bin/sh
echo function_graph > /d/tracing/current_tracer
echo clear > /d/tracing/trace
echo $$ > /d/tracing/set_ftrace_pid
exec "$@"

...and a simple './trace.sh ls' crashes with no console output. SysRq is not responsive either.

author maintainer
#6 lore raw

Re: [for-next][PATCH 04/21] ftrace: Optimize function graph to be called directly

Quoted 5 lines · On Thu, 10 Jul 2014 20:45:57 +0300 Tuomas Tynkkynen <[email protected]>…

This commit (79922b8) breaks the function graph tracer on today's -next. This is on an ARM Tegra board.

I'm using ftrace with this script:

Quoted 8 lines

#!/bin/sh
echo function_graph > /d/tracing/current_tracer
echo clear > /d/tracing/trace
echo $$ > /d/tracing/set_ftrace_pid
exec "$@"

...and a simple './trace.sh ls' crashes with no console output. SysRq is not responsive either.

Thanks for the report. I'll boot up one of my arm boards and see if I can reproduce it. I'll try to get to it either this week or next.

-- Steve

author maintainer
#7 lore raw

Re: [for-next][PATCH 04/21] ftrace: Optimize function graph to be called directly

In reply to Tuomas Tynkkynen
Quoted 4 lines · On Thu, 10 Jul 2014 20:45:57 +0300 Tuomas Tynkkynen <[email protected]>…
Quoted 1 line

This commit (79922b8) breaks the function graph tracer on today's -next. This is on an ARM Tegra board.

Can you test this patch. It makes the default operation of calling the function graph tracer trampoline directly being disabled. It is now up to the arch to define FTRACE_GRAPH_TRAMP_ADDR that can be used to call directly. If it is not set, the old method of calling the function tracer first is used.

I'll worked on getting arm to be called directly too. Can you test that patch as well? I'll reply to this email with that one.

Thanks!

-- Steve

Quoted 1 line

From 641e0d82e5be65adac6449f62d68d83012b780d9 Mon Sep 17 00:00:00 2001

From: "Steven Rostedt (Red Hat)" <[email protected]>
Date: Fri, 11 Jul 2014 14:39:10 -0400
Subject: [PATCH] ftrace: Allow archs to specify if they need a separate
function graph trampoline

Currently if an arch supports function graph tracing, the core code will just assign the function graph trampoline to the function graph addr that gets called.

But as the old method for function graph tracing always calls the function trampoline first and that calls the function graph trampoline, some archs may have the function graph trampoline dependent on operations that were done in the function trampoline. This causes function graph tracer to break on those archs.

Instead of having the default be to set the function graph ftrace_ops to the function graph trampoline, have it instead just set it to zero which will keep it from jumping to a trampoline that is not set up to be jumped directly too.

---
 include/linux/ftrace.h | 10 ++++++++++
 kernel/trace/ftrace.c  |  6 ++++--
 2 files changed, 14 insertions(+), 2 deletions(-)
include/linux/ftrace.h +10 -0
index 11e18fd..4807a39 100644
@@ -453,6 +453,16 @@ void ftrace_modify_all_code(int command);
 #endif
 #endif
 
+/*
+ * If an arch would like functions that are only traced
+ * by the function graph tracer to jump directly to its own
+ * trampoline, then they can define FTRACE_GRAPH_TRAMP_ADDR
+ * to be that address to jump to.
+ */
+#ifndef FTRACE_GRAPH_TRAMP_ADDR
+#define FTRACE_GRAPH_TRAMP_ADDR ((unsigned long) 0)
+#endif
+
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 extern void ftrace_graph_caller(void);
 extern int ftrace_enable_ftrace_graph_caller(void);
kernel/trace/ftrace.c +4 -2
index 45aac1a..c52d37d 100644
@@ -5366,7 +5366,8 @@ int register_ftrace_graph(trace_func_graph_ret_t retfunc,
 
 #ifdef CONFIG_DYNAMIC_FTRACE
 	/* Optimize function graph calling (if implemented by arch) */
-	global_ops.trampoline = FTRACE_GRAPH_ADDR;
+	if (FTRACE_GRAPH_TRAMP_ADDR)
+		global_ops.trampoline = FTRACE_GRAPH_TRAMP_ADDR;
 #endif
 
 	ret = ftrace_startup(&global_ops, FTRACE_START_FUNC_RET);
@@ -5390,7 +5391,8 @@ void unregister_ftrace_graph(void)
 	ftrace_shutdown(&global_ops, FTRACE_STOP_FUNC_RET);
 	global_ops.flags &= ~FTRACE_OPS_FL_STUB;
 #ifdef CONFIG_DYNAMIC_FTRACE
-	global_ops.trampoline = 0;
+	if (FTRACE_GRAPH_TRAMP_ADDR)
+		global_ops.trampoline = 0;
 #endif
 	unregister_pm_notifier(&ftrace_suspend_notifier);
 	unregister_trace_sched_switch(ftrace_graph_probe_sched_switch, NULL);
Signature · 1 line
1.8.1.4
author maintainer
#8 lore raw

Re: [for-next][PATCH 04/21] ftrace: Optimize function graph to be called directly

Quoted 2 lines · On Fri, 11 Jul 2014 23:36:10 -0400 Steven Rostedt <[email protected]> wrote:

I'll worked on getting arm to be called directly too. Can you test that patch as well? I'll reply to this email with that one.

Here's that patch:

-- Steve

Quoted 1 line

From ff9ee792640d802415eaedf0e8d41992c898d2a9 Mon Sep 17 00:00:00 2001

From: "Steven Rostedt (Red Hat)" <[email protected]>
Date: Fri, 11 Jul 2014 23:28:11 -0400
Subject: [PATCH] ARM: ftrace: Allow function graph tracer to have its own
trampoline

The ftrace infrastructure now allows the function graph tracer trampoline to be called directly instead of having to first go through the function tracer trampoline. But in order for this to work, the function graph tracer must be dependent from the function tracer trampoline. Currently in ARM, the function graph tracer does not save registers as it depends on the function tracer trampoline to do so.

By adding a ftrace_graph_tramp_caller function that saves the regs then does the function graph tracing work, this can be used as the trampoline for function graph tracing.

---
 arch/arm/include/asm/ftrace.h  | 5 +++++
 arch/arm/kernel/entry-common.S | 7 +++++++
 2 files changed, 12 insertions(+)
arch/arm/include/asm/ftrace.h +5 -0
index 39eb16b..6af3929 100644
@@ -54,6 +54,11 @@ extern inline void *return_address(unsigned int level)
 
 #define ftrace_return_address(n) return_address(n)
 
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+extern void ftrace_graph_tramp_caller(void);
+#define FTRACE_GRAPH_TRAMP_ADDR ((unsigned long)ftrace_graph_tramp_caller)
+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+
 #endif /* ifndef __ASSEMBLY__ */
 
 #endif /* _ASM_ARM_FTRACE */
arch/arm/kernel/entry-common.S +7 -0
index 7139d4a..0199167 100644
@@ -314,6 +314,13 @@ ENDPROC(ftrace_caller)
 #endif
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
+ENTRY(ftrace_graph_tramp_caller)
+UNWIND(.fnstart)
+	mcount_enter
+	__ftrace_graph_caller
+UNWIND(.fnend)
+ENDPROC(ftrace_graph_tramp_caller)
+
 ENTRY(ftrace_graph_caller)
 UNWIND(.fnstart)
 	__ftrace_graph_caller
Signature · 1 line
1.8.1.4
#9 lore raw

Re: [for-next][PATCH 04/21] ftrace: Optimize function graph to be called directly

Quoted 28 lines · Steven Rostedt
Quoted 2 lines · On Fri, 11 Jul 2014 23:36:10 -0400 Steven Rostedt <[email protected]> wrote:

I'll worked on getting arm to be called directly too. Can you test that patch as well? I'll reply to this email with that one.

Here's that patch:

-- Steve

From ff9ee792640d802415eaedf0e8d41992c898d2a9 Mon Sep 17 00:00:00 2001
From: "Steven Rostedt (Red Hat)" <[email protected]>
Date: Fri, 11 Jul 2014 23:28:11 -0400
Subject: [PATCH] ARM: ftrace: Allow function graph tracer to have its own
trampoline

The ftrace infrastructure now allows the function graph tracer trampoline to be called directly instead of having to first go through the function tracer trampoline. But in order for this to work, the function graph tracer must be dependent from the function tracer trampoline. Currently in ARM, the function graph tracer does not save registers as it depends on the function tracer trampoline to do so.

By adding a ftrace_graph_tramp_caller function that saves the regs then does the function graph tracing work, this can be used as the trampoline for function graph tracing.

Quoted 9 lines
---
  arch/arm/include/asm/ftrace.h  | 5 +++++
  arch/arm/kernel/entry-common.S | 7 +++++++
  2 files changed, 12 insertions(+)

[...]

Thanks, both of these patches work for me.

- Tuomas

Signature · 1 line
nvpublic
author maintainer
#10 lore raw

Re: [for-next][PATCH 04/21] ftrace: Optimize function graph to be called directly

Quoted 3 lines · On Mon, 14 Jul 2014 16:46:40 +0300 Tuomas Tynkkynen <[email protected]>…

Thanks, both of these patches work for me.

Thanks for testing.

I'll pull the first one if for my for-next, and the second one I'll send to the arm folks for 3.18, after the first one is in mainline.

Hopefully I remember to do that :-)

-- Steve

author maintainer
#11 lore raw

PATCH 5/21 ftrace: Add trampolines to enabled_functions debug file

In reply to Steven Rostedt

From: "Steven Rostedt (Red Hat)" <[email protected]>

The enabled_functions is used to help debug the dynamic function tracing. Adding what trampolines are attached to files is useful for debugging.

---
 kernel/trace/ftrace.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)
kernel/trace/ftrace.c +14 -2
index 5d15eb8146a7..3ded796e10e0 100644
@@ -2903,10 +2903,22 @@ static int t_show(struct seq_file *m, void *v)
 		return 0;
 
 	seq_printf(m, "%ps", (void *)rec->ip);
-	if (iter->flags & FTRACE_ITER_ENABLED)
+	if (iter->flags & FTRACE_ITER_ENABLED) {
 		seq_printf(m, " (%ld)%s",
 			   ftrace_rec_count(rec),
-			   rec->flags & FTRACE_FL_REGS ? " R" : "");
+			   rec->flags & FTRACE_FL_REGS ? " R" : "  ");
+		if (rec->flags & FTRACE_FL_TRAMP_EN) {
+			struct ftrace_ops *ops;
+
+			ops = ftrace_find_tramp_ops_curr(rec);
+			if (ops && ops->trampoline)
+				seq_printf(m, "\ttramp: %pS",
+					   (void *)ops->trampoline);
+			else
+				seq_printf(m, "\ttramp: ERROR!");
+		}
+	}	
+
 	seq_printf(m, "\n");
 
 	return 0;
Signature · 1 line
2.0.0
author maintainer
#12 lore raw

PATCH 6/21 tracing: Change trace event sample to use strlcpy instead of strncpy

In reply to Steven Rostedt

From: Zhao Hongjiang <[email protected]>

Strings should be copied with strlcpy instead of strncpy when they will later be printed via %s. This guarantees that they terminate with a NUL '\0' character and do not run pass the end of the allocated string.

This is only for sample code, but it should stil represent a good role model.

---
 samples/trace_events/trace-events-sample.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
samples/trace_events/trace-events-sample.h +1 -1
index 4b0113f73ee9..476429281389 100644
@@ -87,7 +87,7 @@ TRACE_EVENT(foo_bar,
 	),
 
 	TP_fast_assign(
-		strncpy(__entry->foo, foo, 10);
+		strlcpy(__entry->foo, foo, 10);
 		__entry->bar	= bar;
 	),
 
Signature · 1 line
2.0.0
author maintainer
#13 lore raw

PATCH 7/21 ftrace: Simplify ftrace_hash_disable/enable path in ftrace_hash_move

In reply to Steven Rostedt

From: Masami Hiramatsu <[email protected]>

Simplify ftrace_hash_disable/enable path in ftrace_hash_move for hardening the process if the memory allocation failed.

---
 kernel/trace/ftrace.c | 33 +++++++++++----------------------
 1 file changed, 11 insertions(+), 22 deletions(-)
kernel/trace/ftrace.c +11 -22
index 3ded796e10e0..8323082dbc21 100644
@@ -1306,25 +1306,15 @@ ftrace_hash_move(struct ftrace_ops *ops, int enable,
 	struct ftrace_hash *new_hash;
 	int size = src->count;
 	int bits = 0;
-	int ret;
 	int i;
 
 	/*
-	 * Remove the current set, update the hash and add
-	 * them back.
-	 */
-	ftrace_hash_rec_disable(ops, enable);
-
-	/*
 	 * If the new source is empty, just free dst and assign it
 	 * the empty_hash.
 	 */
 	if (!src->count) {
-		free_ftrace_hash_rcu(*dst);
-		rcu_assign_pointer(*dst, EMPTY_HASH);
-		/* still need to update the function records */
-		ret = 0;
-		goto out;
+		new_hash = EMPTY_HASH;
+		goto update;
 	}
 
 	/*
@@ -1337,10 +1327,9 @@ ftrace_hash_move(struct ftrace_ops *ops, int enable,
 	if (bits > FTRACE_HASH_MAX_BITS)
 		bits = FTRACE_HASH_MAX_BITS;
 
-	ret = -ENOMEM;
 	new_hash = alloc_ftrace_hash(bits);
 	if (!new_hash)
-		goto out;
+		return -ENOMEM;
 
 	size = 1 << src->size_bits;
 	for (i = 0; i < size; i++) {
@@ -1351,20 +1340,20 @@ ftrace_hash_move(struct ftrace_ops *ops, int enable,
 		}
 	}
 
+update:
+	/*
+	 * Remove the current set, update the hash and add
+	 * them back.
+	 */
+	ftrace_hash_rec_disable(ops, enable);
+
 	old_hash = *dst;
 	rcu_assign_pointer(*dst, new_hash);
 	free_ftrace_hash_rcu(old_hash);
 
-	ret = 0;
- out:
-	/*
-	 * Enable regardless of ret:
-	 *  On success, we enable the new hash.
-	 *  On failure, we re-enable the original hash.
-	 */
 	ftrace_hash_rec_enable(ops, enable);
 
-	return ret;
+	return 0;
 }
 
 /*
Signature · 1 line
2.0.0
author maintainer
#14 lore raw

PATCH 8/21 tracing: Move the trace_seq_* functions into its own trace_seq.c file

In reply to Steven Rostedt

From: "Steven Rostedt (Red Hat)" <[email protected]>

The trace_seq_*() functions are a nice utility that allows users to manipulate buffers with printf() like formats. It has its own trace_seq.h header in include/linux and should be in its own file. Being tied with trace_output.c is rather awkward.

---
 include/linux/trace_seq.h   |   2 +
 kernel/trace/Makefile       |   1 +
 kernel/trace/trace.c        |  24 ----
 kernel/trace/trace_output.c | 268 ---------------------------------------
 kernel/trace/trace_output.h |   3 -
 kernel/trace/trace_seq.c    | 303 ++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 306 insertions(+), 295 deletions(-)
 create mode 100644 kernel/trace/trace_seq.c
include/linux/trace_seq.h +2 -0
index 136116924d8d..66ea365acf01 100644
@@ -25,6 +25,8 @@ trace_seq_init(struct trace_seq *s)
 	s->full = 0;
 }
 
+#define MAX_MEMHEX_BYTES	8
+
 /*
  * Currently only defined when tracing is enabled.
  */
kernel/trace/Makefile +1 -0
index 2611613f14f1..67d6369ddf83 100644
@@ -28,6 +28,7 @@ obj-$(CONFIG_RING_BUFFER_BENCHMARK) += ring_buffer_benchmark.o
 
 obj-$(CONFIG_TRACING) += trace.o
 obj-$(CONFIG_TRACING) += trace_output.o
+obj-$(CONFIG_TRACING) += trace_seq.o
 obj-$(CONFIG_TRACING) += trace_stat.o
 obj-$(CONFIG_TRACING) += trace_printk.o
 obj-$(CONFIG_CONTEXT_SWITCH_TRACER) += trace_sched_switch.o
kernel/trace/trace.c +0 -24
index 384ede311717..eeb233cbac4f 100644
@@ -923,30 +923,6 @@ out:
 	return ret;
 }
 
-ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf, size_t cnt)
-{
-	int len;
-	int ret;
-
-	if (!cnt)
-		return 0;
-
-	if (s->len <= s->readpos)
-		return -EBUSY;
-
-	len = s->len - s->readpos;
-	if (cnt > len)
-		cnt = len;
-	ret = copy_to_user(ubuf, s->buffer + s->readpos, cnt);
-	if (ret == cnt)
-		return -EFAULT;
-
-	cnt -= ret;
-
-	s->readpos += cnt;
-	return cnt;
-}
-
 static ssize_t trace_seq_to_buffer(struct trace_seq *s, void *buf, size_t cnt)
 {
 	int len;
kernel/trace/trace_output.c +0 -268

280 lines not on this page · raw message

kernel/trace/trace_output.h +0 -3
index 127a9d8c8357..bf7daf2237ed 100644
@@ -35,9 +35,6 @@ trace_print_lat_fmt(struct trace_seq *s, struct trace_entry *entry);
 extern int __unregister_ftrace_event(struct trace_event *event);
 extern struct rw_semaphore trace_event_sem;
 
-#define MAX_MEMHEX_BYTES	8
-#define HEX_CHARS		(MAX_MEMHEX_BYTES*2 + 1)
-
 #define SEQ_PUT_FIELD_RET(s, x)				\
 do {							\
 	if (!trace_seq_putmem(s, &(x), sizeof(x)))	\
kernel/trace/trace_seq.c new file +303 -0

303 lines not on this page · raw message

Signature · 1 line
2.0.0
author maintainer
#15 lore raw

PATCH 9/21 tracing: Clean up trace_seq.c

In reply to Steven Rostedt

From: "Steven Rostedt (Red Hat)" <[email protected]>

For using trace_seq_*() functions in NMI context, I posted a patch to move it to the lib/ directory. This caused Andrew Morton to take a look at the code. He went through and gave a lot of comments about missing kernel doc, inconsistent types for the save variable, mix match of EXPORT_SYMBOL_GPL() and EXPORT_SYMBOL() as well as missing EXPORT_SYMBOL*()s. There were a few comments about the way variables were being compared (int vs uint).

All these were good review comments and should be implemented regardless of if trace_seq.c should be moved to lib/ or not.

---
 include/linux/trace_seq.h |  20 ++---
 kernel/trace/trace_seq.c  | 207 +++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 185 insertions(+), 42 deletions(-)
include/linux/trace_seq.h +10 -10
index 66ea365acf01..1f05317f51c4 100644
@@ -38,14 +38,14 @@ int trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args);
 extern int
 trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary);
 extern int trace_print_seq(struct seq_file *m, struct trace_seq *s);
-extern ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf,
-				 size_t cnt);
+extern int trace_seq_to_user(struct trace_seq *s, char __user *ubuf,
+			     int cnt);
 extern int trace_seq_puts(struct trace_seq *s, const char *str);
 extern int trace_seq_putc(struct trace_seq *s, unsigned char c);
-extern int trace_seq_putmem(struct trace_seq *s, const void *mem, size_t len);
+extern int trace_seq_putmem(struct trace_seq *s, const void *mem, unsigned int len);
 extern int trace_seq_putmem_hex(struct trace_seq *s, const void *mem,
-				size_t len);
-extern void *trace_seq_reserve(struct trace_seq *s, size_t len);
+				unsigned int len);
+extern void *trace_seq_reserve(struct trace_seq *s, unsigned int len);
 extern int trace_seq_path(struct trace_seq *s, const struct path *path);
 
 extern int trace_seq_bitmask(struct trace_seq *s, const unsigned long *maskp,
@@ -73,8 +73,8 @@ static inline int trace_print_seq(struct seq_file *m, struct trace_seq *s)
 {
 	return 0;
 }
-static inline ssize_t trace_seq_to_user(struct trace_seq *s, char __user *ubuf,
-				 size_t cnt)
+static inline int trace_seq_to_user(struct trace_seq *s, char __user *ubuf,
+				    int cnt)
 {
 	return 0;
 }
@@ -87,16 +87,16 @@ static inline int trace_seq_putc(struct trace_seq *s, unsigned char c)
 	return 0;
 }
 static inline int
-trace_seq_putmem(struct trace_seq *s, const void *mem, size_t len)
+trace_seq_putmem(struct trace_seq *s, const void *mem, unsigned int len)
 {
 	return 0;
 }
 static inline int trace_seq_putmem_hex(struct trace_seq *s, const void *mem,
-				       size_t len)
+				       unsigned int len)
 {
 	return 0;
 }
-static inline void *trace_seq_reserve(struct trace_seq *s, size_t len)
+static inline void *trace_seq_reserve(struct trace_seq *s, unsigned int len)
 {
 	return NULL;
 }
kernel/trace/trace_seq.c +175 -32

354 lines not on this page · raw message

Signature · 1 line
2.0.0
author maintainer
#16 lore raw

PATCH 10/21 tracing: Make trace_seq_putmem_hex() more robust

In reply to Steven Rostedt

From: "Steven Rostedt (Red Hat)" <[email protected]>

Currently trace_seq_putmem_hex() can only take as a parameter a pointer to something that is 8 bytes or less, otherwise it will overflow the buffer. This is protected by a macro that encompasses the call to trace_seq_putmem_hex() that has a BUILD_BUG_ON() for the variable before it is passed in. This is not very robust and if trace_seq_putmem_hex() ever gets used outside that macro it will cause issues.

Instead of only being able to produce a hex output of memory that is for a single word, change it to be more robust and allow any size input.

---
 include/linux/trace_seq.h   |  2 --
 kernel/trace/trace_output.h |  1 -
 kernel/trace/trace_seq.c    | 26 +++++++++++++++++++-------
 3 files changed, 19 insertions(+), 10 deletions(-)
include/linux/trace_seq.h +0 -2
index 1f05317f51c4..8283762ab7ef 100644
@@ -25,8 +25,6 @@ trace_seq_init(struct trace_seq *s)
 	s->full = 0;
 }
 
-#define MAX_MEMHEX_BYTES	8
-
 /*
  * Currently only defined when tracing is enabled.
  */
kernel/trace/trace_output.h +0 -1
index bf7daf2237ed..80b25b585a70 100644
@@ -43,7 +43,6 @@ do {							\
 
 #define SEQ_PUT_HEX_FIELD_RET(s, x)			\
 do {							\
-	BUILD_BUG_ON(sizeof(x) > MAX_MEMHEX_BYTES);	\
 	if (!trace_seq_putmem_hex(s, &(x), sizeof(x)))	\
 		return TRACE_TYPE_PARTIAL_LINE;		\
 } while (0)
kernel/trace/trace_seq.c +19 -7
index 0fabca773e51..88c0f80f0a1f 100644
@@ -291,6 +291,7 @@ int trace_seq_putmem(struct trace_seq *s, const void *mem, unsigned int len)
 }
 EXPORT_SYMBOL_GPL(trace_seq_putmem);
 
+#define MAX_MEMHEX_BYTES	8U
 #define HEX_CHARS		(MAX_MEMHEX_BYTES*2 + 1)
 
 /**
@@ -310,22 +311,33 @@ int trace_seq_putmem_hex(struct trace_seq *s, const void *mem,
 {
 	unsigned char hex[HEX_CHARS];
 	const unsigned char *data = mem;
+	unsigned int start_len;
 	int i, j;
+	int cnt = 0;
 
 	if (s->full)
 		return 0;
 
+	while (len) {
+		start_len = min(len, HEX_CHARS - 1);
 #ifdef __BIG_ENDIAN
-	for (i = 0, j = 0; i < len; i++) {
+		for (i = 0, j = 0; i < start_len; i++) {
 #else
-	for (i = len-1, j = 0; i >= 0; i--) {
+		for (i = start_len-1, j = 0; i >= 0; i--) {
 #endif
-		hex[j++] = hex_asc_hi(data[i]);
-		hex[j++] = hex_asc_lo(data[i]);
-	}
-	hex[j++] = ' ';
+			hex[j++] = hex_asc_hi(data[i]);
+			hex[j++] = hex_asc_lo(data[i]);
+		}
+		if (WARN_ON_ONCE(j == 0 || j/2 > len))
+			break;
+
+		/* j increments twice per loop */
+		len -= j / 2;
+		hex[j++] = ' ';
 
-	return trace_seq_putmem(s, hex, j);
+		cnt += trace_seq_putmem(s, hex, j);
+	}
+	return cnt;
 }
 EXPORT_SYMBOL_GPL(trace_seq_putmem_hex);
 
Signature · 1 line
2.0.0
author maintainer
#17 lore raw

PATCH 11/21 tracing: Remove trace_seq_reserve()

In reply to Steven Rostedt

From: "Steven Rostedt (Red Hat)" <[email protected]>

trace_seq_reserve() has no users in the kernel, it just wastes space. Remove it.

Cc Eduard - Gabriel Munteanu <[email protected]>
---
 include/linux/trace_seq.h |  5 -----
 kernel/trace/trace_seq.c  | 30 ------------------------------
 2 files changed, 35 deletions(-)
include/linux/trace_seq.h +0 -5
index 8283762ab7ef..dd85753e1bb0 100644
@@ -43,7 +43,6 @@ extern int trace_seq_putc(struct trace_seq *s, unsigned char c);
 extern int trace_seq_putmem(struct trace_seq *s, const void *mem, unsigned int len);
 extern int trace_seq_putmem_hex(struct trace_seq *s, const void *mem,
 				unsigned int len);
-extern void *trace_seq_reserve(struct trace_seq *s, unsigned int len);
 extern int trace_seq_path(struct trace_seq *s, const struct path *path);
 
 extern int trace_seq_bitmask(struct trace_seq *s, const unsigned long *maskp,
@@ -94,10 +93,6 @@ static inline int trace_seq_putmem_hex(struct trace_seq *s, const void *mem,
 {
 	return 0;
 }
-static inline void *trace_seq_reserve(struct trace_seq *s, unsigned int len)
-{
-	return NULL;
-}
 static inline int trace_seq_path(struct trace_seq *s, const struct path *path)
 {
 	return 0;
kernel/trace/trace_seq.c +0 -30
index 88c0f80f0a1f..1f24ed99dca2 100644
@@ -342,36 +342,6 @@ int trace_seq_putmem_hex(struct trace_seq *s, const void *mem,
 EXPORT_SYMBOL_GPL(trace_seq_putmem_hex);
 
 /**
- * trace_seq_reserve - reserve space on the sequence buffer
- * @s: trace sequence descriptor
- * @len: The amount to reserver.
- *
- * If for some reason there is a need to save some space on the
- * buffer to fill in later, this function is used for that purpose.
- * The given length will be reserved and the pointer to that
- * location on the buffer is returned, unless there is not enough
- * buffer left to hold the given length then NULL is returned.
- */
-void *trace_seq_reserve(struct trace_seq *s, unsigned int len)
-{
-	void *ret;
-
-	if (s->full)
-		return NULL;
-
-	if (len > TRACE_SEQ_BUF_LEFT(s)) {
-		s->full = 1;
-		return NULL;
-	}
-
-	ret = s->buffer + s->len;
-	s->len += len;
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(trace_seq_reserve);
-
-/**
  * trace_seq_path - copy a path into the sequence buffer
  * @s: trace sequence descriptor
  * @path: path to write into the sequence buffer.
Signature · 1 line
2.0.0
author maintainer
#18 lore raw

PATCH 12/21 tracing: Remove unnecessary null test before debugfs_remove()

In reply to Steven Rostedt

From: Fabian Frederick <[email protected]>

This fixes checkpatch warning:

"WARNING: debugfs_remove(NULL) is safe this check is probably not required"

---
 kernel/trace/trace.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
kernel/trace/trace.c +2 -4
index eeb233cbac4f..4caa814d41c3 100644
@@ -6071,10 +6071,8 @@ destroy_trace_option_files(struct trace_option_dentry *topts)
 	if (!topts)
 		return;
 
-	for (cnt = 0; topts[cnt].opt; cnt++) {
-		if (topts[cnt].entry)
-			debugfs_remove(topts[cnt].entry);
-	}
+	for (cnt = 0; topts[cnt].opt; cnt++)
+		debugfs_remove(topts[cnt].entry);
 
 	kfree(topts);
 }
Signature · 1 line
2.0.0
author maintainer
#19 lore raw

PATCH 13/21 tracing: Add trace_seq_buffer_ptr() helper function

In reply to Steven Rostedt

From: "Steven Rostedt (Red Hat)" <[email protected]>

There's several locations in the kernel that open code the calculation of the next location in the trace_seq buffer. This is usually done with

p->buffer + p->len

Instead of having this open coded, supply a helper function in the header to do it for them. This function is called trace_seq_buffer_ptr().

---
 arch/x86/kvm/mmutrace.h     |  2 +-
 drivers/scsi/scsi_trace.c   | 16 ++++++++--------
 include/linux/trace_seq.h   | 15 +++++++++++++++
 kernel/trace/trace_output.c | 14 +++++++-------
 4 files changed, 31 insertions(+), 16 deletions(-)
arch/x86/kvm/mmutrace.h +1 -1
index 9d2e0ffcb190..2e5652b62fd6 100644
@@ -22,7 +22,7 @@
 	__entry->unsync = sp->unsync;
 
 #define KVM_MMU_PAGE_PRINTK() ({				        \
-	const char *ret = p->buffer + p->len;				\
+	const char *ret = trace_seq_buffer_ptr(p);			\
 	static const char *access_str[] = {			        \
 		"---", "--x", "w--", "w-x", "-u-", "-ux", "wu-", "wux"  \
 	};							        \
drivers/scsi/scsi_trace.c +8 -8
index 2bea4f0b684a..503594e5f76d 100644
@@ -28,7 +28,7 @@ scsi_trace_misc(struct trace_seq *, unsigned char *, int);
 static const char *
 scsi_trace_rw6(struct trace_seq *p, unsigned char *cdb, int len)
 {
-	const char *ret = p->buffer + p->len;
+	const char *ret = trace_seq_buffer_ptr(p);
 	sector_t lba = 0, txlen = 0;
 
 	lba |= ((cdb[1] & 0x1F) << 16);
@@ -46,7 +46,7 @@ scsi_trace_rw6(struct trace_seq *p, unsigned char *cdb, int len)
 static const char *
 scsi_trace_rw10(struct trace_seq *p, unsigned char *cdb, int len)
 {
-	const char *ret = p->buffer + p->len;
+	const char *ret = trace_seq_buffer_ptr(p);
 	sector_t lba = 0, txlen = 0;
 
 	lba |= (cdb[2] << 24);
@@ -71,7 +71,7 @@ scsi_trace_rw10(struct trace_seq *p, unsigned char *cdb, int len)
 static const char *
 scsi_trace_rw12(struct trace_seq *p, unsigned char *cdb, int len)
 {
-	const char *ret = p->buffer + p->len;
+	const char *ret = trace_seq_buffer_ptr(p);
 	sector_t lba = 0, txlen = 0;
 
 	lba |= (cdb[2] << 24);
@@ -94,7 +94,7 @@ scsi_trace_rw12(struct trace_seq *p, unsigned char *cdb, int len)
 static const char *
 scsi_trace_rw16(struct trace_seq *p, unsigned char *cdb, int len)
 {
-	const char *ret = p->buffer + p->len;
+	const char *ret = trace_seq_buffer_ptr(p);
 	sector_t lba = 0, txlen = 0;
 
 	lba |= ((u64)cdb[2] << 56);
@@ -125,7 +125,7 @@ scsi_trace_rw16(struct trace_seq *p, unsigned char *cdb, int len)
 static const char *
 scsi_trace_rw32(struct trace_seq *p, unsigned char *cdb, int len)
 {
-	const char *ret = p->buffer + p->len, *cmd;
+	const char *ret = trace_seq_buffer_ptr(p), *cmd;
 	sector_t lba = 0, txlen = 0;
 	u32 ei_lbrt = 0;
 
@@ -180,7 +180,7 @@ out:
 static const char *
 scsi_trace_unmap(struct trace_seq *p, unsigned char *cdb, int len)
 {
-	const char *ret = p->buffer + p->len;
+	const char *ret = trace_seq_buffer_ptr(p);
 	unsigned int regions = cdb[7] << 8 | cdb[8];
 
 	trace_seq_printf(p, "regions=%u", (regions - 8) / 16);
@@ -192,7 +192,7 @@ scsi_trace_unmap(struct trace_seq *p, unsigned char *cdb, int len)
 static const char *
 scsi_trace_service_action_in(struct trace_seq *p, unsigned char *cdb, int len)
 {
-	const char *ret = p->buffer + p->len, *cmd;
+	const char *ret = trace_seq_buffer_ptr(p), *cmd;
 	sector_t lba = 0;
 	u32 alloc_len = 0;
 
@@ -247,7 +247,7 @@ scsi_trace_varlen(struct trace_seq *p, unsigned char *cdb, int len)
 static const char *
 scsi_trace_misc(struct trace_seq *p, unsigned char *cdb, int len)
 {
-	const char *ret = p->buffer + p->len;
+	const char *ret = trace_seq_buffer_ptr(p);
 
 	trace_seq_printf(p, "-");
 	trace_seq_putc(p, 0);
include/linux/trace_seq.h +15 -0
index dd85753e1bb0..ea6c9dea79e3 100644
@@ -25,6 +25,21 @@ trace_seq_init(struct trace_seq *s)
 	s->full = 0;
 }
 
+/**
+ * trace_seq_buffer_ptr - return pointer to next location in buffer
+ * @s: trace sequence descriptor
+ *
+ * Returns the pointer to the buffer where the next write to
+ * the buffer will happen. This is useful to save the location
+ * that is about to be written to and then return the result
+ * of that write.
+ */
+static inline unsigned char *
+trace_seq_buffer_ptr(struct trace_seq *s)
+{
+	return s->buffer + s->len;
+}
+
 /*
  * Currently only defined when tracing is enabled.
  */
kernel/trace/trace_output.c +7 -7
index b8930f79a04b..c6977d5a9b12 100644
@@ -75,7 +75,7 @@ ftrace_print_flags_seq(struct trace_seq *p, const char *delim,
 {
 	unsigned long mask;
 	const char *str;
-	const char *ret = p->buffer + p->len;
+	const char *ret = trace_seq_buffer_ptr(p);
 	int i, first = 1;
 
 	for (i = 0;  flag_array[i].name && flags; i++) {
@@ -111,7 +111,7 @@ ftrace_print_symbols_seq(struct trace_seq *p, unsigned long val,
 			 const struct trace_print_flags *symbol_array)
 {
 	int i;
-	const char *ret = p->buffer + p->len;
+	const char *ret = trace_seq_buffer_ptr(p);
 
 	for (i = 0;  symbol_array[i].name; i++) {
 
@@ -122,7 +122,7 @@ ftrace_print_symbols_seq(struct trace_seq *p, unsigned long val,
 		break;
 	}
 
-	if (ret == (const char *)(p->buffer + p->len))
+	if (ret == (const char *)(trace_seq_buffer_ptr(p)))
 		trace_seq_printf(p, "0x%lx", val);
 		
 	trace_seq_putc(p, 0);
@@ -137,7 +137,7 @@ ftrace_print_symbols_seq_u64(struct trace_seq *p, unsigned long long val,
 			 const struct trace_print_flags_u64 *symbol_array)
 {
 	int i;
-	const char *ret = p->buffer + p->len;
+	const char *ret = trace_seq_buffer_ptr(p);
 
 	for (i = 0;  symbol_array[i].name; i++) {
 
@@ -148,7 +148,7 @@ ftrace_print_symbols_seq_u64(struct trace_seq *p, unsigned long long val,
 		break;
 	}
 
-	if (ret == (const char *)(p->buffer + p->len))
+	if (ret == (const char *)(trace_seq_buffer_ptr(p)))
 		trace_seq_printf(p, "0x%llx", val);
 
 	trace_seq_putc(p, 0);
@@ -162,7 +162,7 @@ const char *
 ftrace_print_bitmask_seq(struct trace_seq *p, void *bitmask_ptr,
 			 unsigned int bitmask_size)
 {
-	const char *ret = p->buffer + p->len;
+	const char *ret = trace_seq_buffer_ptr(p);
 
 	trace_seq_bitmask(p, bitmask_ptr, bitmask_size * 8);
 	trace_seq_putc(p, 0);
@@ -175,7 +175,7 @@ const char *
 ftrace_print_hex_seq(struct trace_seq *p, const unsigned char *buf, int buf_len)
 {
 	int i;
-	const char *ret = p->buffer + p->len;
+	const char *ret = trace_seq_buffer_ptr(p);
 
 	for (i = 0; i < buf_len; i++)
 		trace_seq_printf(p, "%s%2.2x", i == 0 ? "" : " ", buf[i]);
Signature · 1 line
2.0.0
author maintainer
#20 lore raw

PATCH 14/21 ftrace: Get rid of obsolete global_start_up variable

In reply to Steven Rostedt

From: Namhyung Kim <[email protected]>

It seems like it's a leftover from commit 4104d326b670 ("ftrace:
Remove global function list and call function directly"). As it isn't updated at all, checking its value is meaningless.

Let's get rid of it.

---
 kernel/trace/ftrace.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)
kernel/trace/ftrace.c +1 -3
index 8323082dbc21..39df3192e725 100644
@@ -2286,7 +2286,6 @@ static void ftrace_run_update_code(int command)
 
 static ftrace_func_t saved_ftrace_func;
 static int ftrace_start_up;
-static int global_start_up;
 
 static void control_ops_free(struct ftrace_ops *ops)
 {
@@ -2350,8 +2349,7 @@ static int ftrace_shutdown(struct ftrace_ops *ops, int command)
 
 	ftrace_hash_rec_disable(ops, 1);
 
-	if (!global_start_up)
-		ops->flags &= ~FTRACE_OPS_FL_ENABLED;
+	ops->flags &= ~FTRACE_OPS_FL_ENABLED;
 
 	command |= FTRACE_UPDATE_CALLS;
 
Signature · 1 line
2.0.0
author maintainer
#21 lore raw

PATCH 15/21 ftrace: Fix memory leak on failure path in ftrace_allocate_pages()

In reply to Steven Rostedt

From: Namhyung Kim <[email protected]>

As struct ftrace_page is managed in a single linked list, it should free from the start page.

---
 kernel/trace/ftrace.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
kernel/trace/ftrace.c +2 -1
index 39df3192e725..e14ff4c1713e 100644
@@ -2637,7 +2637,8 @@ ftrace_allocate_pages(unsigned long num_to_init)
 	return start_pg;
 
  free_pages:
-	while (start_pg) {
+	pg = start_pg;
+	while (pg) {
 		order = get_count_order(pg->size / ENTRIES_PER_PAGE);
 		free_pages((unsigned long)pg->records, order);
 		start_pg = pg->next;
Signature · 1 line
2.0.0
author maintainer
#22 lore raw

PATCH 16/21 ftrace: Do not copy hash if O_TRUNC is set

In reply to Steven Rostedt

From: Namhyung Kim <[email protected]>

When a filter file is open for writing and O_TRUNC is set, there's no need to copy and free the filter entries.

---
 kernel/trace/ftrace.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)
kernel/trace/ftrace.c +7 -5
index e14ff4c1713e..232b898eebbd 100644
@@ -3010,7 +3010,13 @@ ftrace_regex_open(struct ftrace_ops *ops, int flag,
 		hash = ops->filter_hash;
 
 	if (file->f_mode & FMODE_WRITE) {
-		iter->hash = alloc_and_copy_ftrace_hash(FTRACE_HASH_DEFAULT_BITS, hash);
+		const int size_bits = FTRACE_HASH_DEFAULT_BITS;
+
+		if (file->f_flags & O_TRUNC)
+			iter->hash = alloc_ftrace_hash(size_bits);
+		else
+			iter->hash = alloc_and_copy_ftrace_hash(size_bits, hash);
+
 		if (!iter->hash) {
 			trace_parser_put(&iter->parser);
 			kfree(iter);
@@ -3019,10 +3025,6 @@ ftrace_regex_open(struct ftrace_ops *ops, int flag,
 		}
 	}
 
-	if ((file->f_mode & FMODE_WRITE) &&
-	    (file->f_flags & O_TRUNC))
-		ftrace_filter_reset(iter->hash);
-
 	if (file->f_mode & FMODE_READ) {
 		iter->pg = ftrace_pages_start;
 
Signature · 1 line
2.0.0
author maintainer
#23 lore raw

PATCH 17/21 tracing: Convert pr_warning() to pr_warn() in trace_events.c

In reply to Steven Rostedt

From: Fabian Frederick <[email protected]>

Convert pr_warning to standard pr_warn
Define pr_fmt(fmt) fmt to avoid any future default fmt definition

---
 kernel/trace/trace_events.c | 56 ++++++++++++++++++++++-----------------------
 1 file changed, 27 insertions(+), 29 deletions(-)
kernel/trace/trace_events.c +27 -29
index f99e0b3bca8c..e7a814b3906b 100644
@@ -8,6 +8,8 @@
  *
  */
 
+#define pr_fmt(fmt) fmt
+
 #include <linux/workqueue.h>
 #include <linux/spinlock.h>
 #include <linux/kthread.h>
@@ -1490,7 +1492,7 @@ event_subsystem_dir(struct trace_array *tr, const char *name,
 
 	dir->entry = debugfs_create_dir(name, parent);
 	if (!dir->entry) {
-		pr_warning("Failed to create system directory %s\n", name);
+		pr_warn("Failed to create system directory %s\n", name);
 		__put_system(system);
 		goto out_free;
 	}
@@ -1506,7 +1508,7 @@ event_subsystem_dir(struct trace_array *tr, const char *name,
 	if (!entry) {
 		kfree(system->filter);
 		system->filter = NULL;
-		pr_warning("Could not create debugfs '%s/filter' entry\n", name);
+		pr_warn("Could not create debugfs '%s/filter' entry\n", name);
 	}
 
 	trace_create_file("enable", 0644, dir->entry, dir,
@@ -1521,8 +1523,7 @@ event_subsystem_dir(struct trace_array *tr, const char *name,
  out_fail:
 	/* Only print this message if failed on memory allocation */
 	if (!dir || !system)
-		pr_warning("No memory to create event subsystem %s\n",
-			   name);
+		pr_warn("No memory to create event subsystem %s\n", name);
 	return NULL;
 }
 
@@ -1550,8 +1551,7 @@ event_create_dir(struct dentry *parent, struct ftrace_event_file *file)
 	name = ftrace_event_name(call);
 	file->dir = debugfs_create_dir(name, d_events);
 	if (!file->dir) {
-		pr_warning("Could not create debugfs '%s' directory\n",
-			   name);
+		pr_warn("Could not create debugfs '%s' directory\n", name);
 		return -1;
 	}
 
@@ -1574,8 +1574,8 @@ event_create_dir(struct dentry *parent, struct ftrace_event_file *file)
 	if (list_empty(head)) {
 		ret = call->class->define_fields(call);
 		if (ret < 0) {
-			pr_warning("Could not initialize trace point"
-				   " events/%s\n", name);
+			pr_warn("Could not initialize trace point events/%s\n",
+				name);
 			return -1;
 		}
 	}
@@ -1648,8 +1648,7 @@ static int event_init(struct ftrace_event_call *call)
 	if (call->class->raw_init) {
 		ret = call->class->raw_init(call);
 		if (ret < 0 && ret != -ENOSYS)
-			pr_warn("Could not initialize trace events/%s\n",
-				name);
+			pr_warn("Could not initialize trace events/%s\n", name);
 	}
 
 	return ret;
@@ -1894,8 +1893,8 @@ __trace_add_event_dirs(struct trace_array *tr)
 	list_for_each_entry(call, &ftrace_events, list) {
 		ret = __trace_add_new_event(call, tr);
 		if (ret < 0)
-			pr_warning("Could not create directory for event %s\n",
-				   ftrace_event_name(call));
+			pr_warn("Could not create directory for event %s\n",
+				ftrace_event_name(call));
 	}
 }
 
@@ -2207,8 +2206,8 @@ __trace_early_add_event_dirs(struct trace_array *tr)
 	list_for_each_entry(file, &tr->events, list) {
 		ret = event_create_dir(tr->event_dir, file);
 		if (ret < 0)
-			pr_warning("Could not create directory for event %s\n",
-				   ftrace_event_name(file->event_call));
+			pr_warn("Could not create directory for event %s\n",
+				ftrace_event_name(file->event_call));
 	}
 }
 
@@ -2231,8 +2230,8 @@ __trace_early_add_events(struct trace_array *tr)
 
 		ret = __trace_early_add_new_event(call, tr);
 		if (ret < 0)
-			pr_warning("Could not create early event %s\n",
-				   ftrace_event_name(call));
+			pr_warn("Could not create early event %s\n",
+				ftrace_event_name(call));
 	}
 }
 
@@ -2279,13 +2278,13 @@ create_event_toplevel_files(struct dentry *parent, struct trace_array *tr)
 	entry = debugfs_create_file("set_event", 0644, parent,
 				    tr, &ftrace_set_event_fops);
 	if (!entry) {
-		pr_warning("Could not create debugfs 'set_event' entry\n");
+		pr_warn("Could not create debugfs 'set_event' entry\n");
 		return -ENOMEM;
 	}
 
 	d_events = debugfs_create_dir("events", parent);
 	if (!d_events) {
-		pr_warning("Could not create debugfs 'events' directory\n");
+		pr_warn("Could not create debugfs 'events' directory\n");
 		return -ENOMEM;
 	}
 
@@ -2461,11 +2460,10 @@ static __init int event_trace_init(void)
 	entry = debugfs_create_file("available_events", 0444, d_tracer,
 				    tr, &ftrace_avail_fops);
 	if (!entry)
-		pr_warning("Could not create debugfs "
-			   "'available_events' entry\n");
+		pr_warn("Could not create debugfs 'available_events' entry\n");
 
 	if (trace_define_common_fields())
-		pr_warning("tracing: Failed to allocate common fields");
+		pr_warn("tracing: Failed to allocate common fields");
 
 	ret = early_event_add_tracer(d_tracer, tr);
 	if (ret)
@@ -2474,7 +2472,7 @@ static __init int event_trace_init(void)
 #ifdef CONFIG_MODULES
 	ret = register_module_notifier(&trace_module_nb);
 	if (ret)
-		pr_warning("Failed to register trace events module notifier\n");
+		pr_warn("Failed to register trace events module notifier\n");
 #endif
 	return 0;
 }
@@ -2578,7 +2576,7 @@ static __init void event_trace_self_tests(void)
 		 * it and the self test should not be on.
 		 */
 		if (file->flags & FTRACE_EVENT_FL_ENABLED) {
-			pr_warning("Enabled event during self test!\n");
+			pr_warn("Enabled event during self test!\n");
 			WARN_ON_ONCE(1);
 			continue;
 		}
@@ -2606,8 +2604,8 @@ static __init void event_trace_self_tests(void)
 
 		ret = __ftrace_set_clr_event(tr, NULL, system->name, NULL, 1);
 		if (WARN_ON_ONCE(ret)) {
-			pr_warning("error enabling system %s\n",
-				   system->name);
+			pr_warn("error enabling system %s\n",
+				system->name);
 			continue;
 		}
 
@@ -2615,8 +2613,8 @@ static __init void event_trace_self_tests(void)
 
 		ret = __ftrace_set_clr_event(tr, NULL, system->name, NULL, 0);
 		if (WARN_ON_ONCE(ret)) {
-			pr_warning("error disabling system %s\n",
-				   system->name);
+			pr_warn("error disabling system %s\n",
+				system->name);
 			continue;
 		}
 
@@ -2630,7 +2628,7 @@ static __init void event_trace_self_tests(void)
 
 	ret = __ftrace_set_clr_event(tr, NULL, NULL, NULL, 1);
 	if (WARN_ON_ONCE(ret)) {
-		pr_warning("error enabling all events\n");
+		pr_warn("error enabling all events\n");
 		return;
 	}
 
@@ -2639,7 +2637,7 @@ static __init void event_trace_self_tests(void)
 	/* reset sysname */
 	ret = __ftrace_set_clr_event(tr, NULL, NULL, NULL, 0);
 	if (WARN_ON_ONCE(ret)) {
-		pr_warning("error disabling all events\n");
+		pr_warn("error disabling all events\n");
 		return;
 	}
 
Signature · 1 line
2.0.0
author maintainer
#24 lore raw

PATCH 18/21 tracing: Add ftrace_graph_notrace boot parameter

In reply to Steven Rostedt

From: Namhyung Kim <[email protected]>

The ftrace_graph_notrace option is for specifying notrace filter for function graph tracer at boot time. It can be altered after boot using set_graph_notrace file on the debugfs.

---
 Documentation/kernel-parameters.txt |  6 ++++++
 kernel/trace/ftrace.c               | 24 ++++++++++++++++++++----
 2 files changed, 26 insertions(+), 4 deletions(-)
Documentation/kernel-parameters.txt +6 -0
index c1b9aa8c5a52..19c0a9096a02 100644
@@ -1097,6 +1097,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			that can be changed at run time by the
 			set_graph_function file in the debugfs tracing directory.
 
+	ftrace_graph_notrace=[function-list]
+			[FTRACE] Do not trace from the functions specified in
+			function-list.  This list is a comma separated list of
+			functions that can be changed at run time by the
+			set_graph_notrace file in the debugfs tracing directory.
+
 	gamecon.map[2|3]=
 			[HW,JOY] Multisystem joystick and NES/SNES/PSX pad
 			support via parallel port (up to 5 devices per port)
kernel/trace/ftrace.c +20 -4
index 232b898eebbd..17885a27281c 100644
@@ -3884,6 +3884,7 @@ __setup("ftrace_filter=", set_ftrace_filter);
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 static char ftrace_graph_buf[FTRACE_FILTER_SIZE] __initdata;
+static char ftrace_graph_notrace_buf[FTRACE_FILTER_SIZE] __initdata;
 static int ftrace_set_func(unsigned long *array, int *idx, int size, char *buffer);
 
 static int __init set_graph_function(char *str)
@@ -3893,16 +3894,29 @@ static int __init set_graph_function(char *str)
 }
 __setup("ftrace_graph_filter=", set_graph_function);
 
-static void __init set_ftrace_early_graph(char *buf)
+static int __init set_graph_notrace_function(char *str)
+{
+	strlcpy(ftrace_graph_notrace_buf, str, FTRACE_FILTER_SIZE);
+	return 1;
+}
+__setup("ftrace_graph_notrace=", set_graph_notrace_function);
+
+static void __init set_ftrace_early_graph(char *buf, int enable)
 {
 	int ret;
 	char *func;
+	unsigned long *table = ftrace_graph_funcs;
+	int *count = &ftrace_graph_count;
+
+	if (!enable) {
+		table = ftrace_graph_notrace_funcs;
+		count = &ftrace_graph_notrace_count;
+	}
 
 	while (buf) {
 		func = strsep(&buf, ",");
 		/* we allow only one expression at a time */
-		ret = ftrace_set_func(ftrace_graph_funcs, &ftrace_graph_count,
-				      FTRACE_GRAPH_MAX_FUNCS, func);
+		ret = ftrace_set_func(table, count, FTRACE_GRAPH_MAX_FUNCS, func);
 		if (ret)
 			printk(KERN_DEBUG "ftrace: function %s not "
 					  "traceable\n", func);
@@ -3931,7 +3945,9 @@ static void __init set_ftrace_early_filters(void)
 		ftrace_set_early_filter(&global_ops, ftrace_notrace_buf, 0);
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 	if (ftrace_graph_buf[0])
-		set_ftrace_early_graph(ftrace_graph_buf);
+		set_ftrace_early_graph(ftrace_graph_buf, 1);
+	if (ftrace_graph_notrace_buf[0])
+		set_ftrace_early_graph(ftrace_graph_notrace_buf, 0);
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 }
 
Signature · 1 line
2.0.0
author maintainer
#25 lore raw

PATCH 19/21 tracing: Improve message of empty set_graph_notrace file

In reply to Steven Rostedt

From: Namhyung Kim <[email protected]>

When there's no entry in set_graph_notrace, it'll print below message

#### all functions enabled ####

While this is technically correct, it's better to print like below:

#### no functions disabled ####

---
 kernel/trace/ftrace.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
kernel/trace/ftrace.c +6 -1
index 17885a27281c..ee245c0659a6 100644
@@ -4089,7 +4089,12 @@ static int g_show(struct seq_file *m, void *v)
 		return 0;
 
 	if (ptr == (unsigned long *)1) {
-		seq_printf(m, "#### all functions enabled ####\n");
+		struct ftrace_graph_data *fgd = m->private;
+
+		if (fgd->table == ftrace_graph_funcs)
+			seq_printf(m, "#### all functions enabled ####\n");
+		else
+			seq_printf(m, "#### no functions disabled ####\n");
 		return 0;
 	}
 
Signature · 1 line
2.0.0
author maintainer
#26 lore raw

PATCH 20/21 tracing: Improve message of empty set_ftrace_notrace file

In reply to Steven Rostedt

From: Namhyung Kim <[email protected]>

When there's no entry in set_ftrace_notrace, it'll print nothing, but it's better to print something like below like set_graph_notrace does:

#### no functions disabled ####

---
 kernel/trace/ftrace.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)
kernel/trace/ftrace.c +8 -3
index ee245c0659a6..45aac1a742c5 100644
@@ -2835,8 +2835,10 @@ static void *t_start(struct seq_file *m, loff_t *pos)
 	 * off, we can short cut and just print out that all
 	 * functions are enabled.
 	 */
-	if (iter->flags & FTRACE_ITER_FILTER &&
-	    ftrace_hash_empty(ops->filter_hash)) {
+	if ((iter->flags & FTRACE_ITER_FILTER &&
+	     ftrace_hash_empty(ops->filter_hash)) ||
+	    (iter->flags & FTRACE_ITER_NOTRACE &&
+	     ftrace_hash_empty(ops->notrace_hash))) {
 		if (*pos > 0)
 			return t_hash_start(m, pos);
 		iter->flags |= FTRACE_ITER_PRINTALL;
@@ -2881,7 +2883,10 @@ static int t_show(struct seq_file *m, void *v)
 		return t_hash_show(m, iter);
 
 	if (iter->flags & FTRACE_ITER_PRINTALL) {
-		seq_printf(m, "#### all functions enabled ####\n");
+		if (iter->flags & FTRACE_ITER_NOTRACE)
+			seq_printf(m, "#### no functions disabled ####\n");
+		else
+			seq_printf(m, "#### all functions enabled ####\n");
 		return 0;
 	}
 
Signature · 1 line
2.0.0
author maintainer
#27 lore raw

PATCH 21/21 tracing: Add description of set_graph_notrace to tracing/README

In reply to Steven Rostedt

From: Namhyung Kim <[email protected]>

It was missing the description of set_graph_notrace file. Add it.

---
 kernel/trace/trace.c | 1 +
 1 file changed, 1 insertion(+)
kernel/trace/trace.c +1 -0
index 4caa814d41c3..822f6a0894f7 100644
@@ -3663,6 +3663,7 @@ static const char readme_msg[] =
 #endif
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 	"  set_graph_function\t- Trace the nested calls of a function (function_graph)\n"
+	"  set_graph_notrace\t- Do not trace the nested calls of a function (function_graph)\n"
 	"  max_graph_depth\t- Trace a limited depth of nested calls (0 is unlimited)\n"
 #endif
 #ifdef CONFIG_TRACER_SNAPSHOT
Signature · 1 line
2.0.0