aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/sched.h2
-rw-r--r--kernel/trace/ftrace.c13
-rw-r--r--kernel/trace/ring_buffer.c10
-rw-r--r--kernel/trace/trace.h15
4 files changed, 33 insertions, 7 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h
index d8b2d0bec0d8..7b78d9cad471 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1513,7 +1513,7 @@ struct task_struct {
1513#ifdef CONFIG_TRACING 1513#ifdef CONFIG_TRACING
1514 /* state flags for use by tracers */ 1514 /* state flags for use by tracers */
1515 unsigned long trace; 1515 unsigned long trace;
1516 /* bitmask of trace recursion */ 1516 /* bitmask and counter of trace recursion */
1517 unsigned long trace_recursion; 1517 unsigned long trace_recursion;
1518#endif /* CONFIG_TRACING */ 1518#endif /* CONFIG_TRACING */
1519#ifdef CONFIG_CGROUP_MEM_RES_CTLR /* memcg uses this to do batch job */ 1519#ifdef CONFIG_CGROUP_MEM_RES_CTLR /* memcg uses this to do batch job */
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 25949b33057c..1ee417fcbfa5 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -109,12 +109,18 @@ ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip);
109static void ftrace_global_list_func(unsigned long ip, 109static void ftrace_global_list_func(unsigned long ip,
110 unsigned long parent_ip) 110 unsigned long parent_ip)
111{ 111{
112 struct ftrace_ops *op = rcu_dereference_raw(ftrace_global_list); /*see above*/ 112 struct ftrace_ops *op;
113
114 if (unlikely(trace_recursion_test(TRACE_GLOBAL_BIT)))
115 return;
113 116
117 trace_recursion_set(TRACE_GLOBAL_BIT);
118 op = rcu_dereference_raw(ftrace_global_list); /*see above*/
114 while (op != &ftrace_list_end) { 119 while (op != &ftrace_list_end) {
115 op->func(ip, parent_ip); 120 op->func(ip, parent_ip);
116 op = rcu_dereference_raw(op->next); /*see above*/ 121 op = rcu_dereference_raw(op->next); /*see above*/
117 }; 122 };
123 trace_recursion_clear(TRACE_GLOBAL_BIT);
118} 124}
119 125
120static void ftrace_pid_func(unsigned long ip, unsigned long parent_ip) 126static void ftrace_pid_func(unsigned long ip, unsigned long parent_ip)
@@ -3490,6 +3496,10 @@ ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip)
3490{ 3496{
3491 struct ftrace_ops *op; 3497 struct ftrace_ops *op;
3492 3498
3499 if (unlikely(trace_recursion_test(TRACE_INTERNAL_BIT)))
3500 return;
3501
3502 trace_recursion_set(TRACE_INTERNAL_BIT);
3493 /* 3503 /*
3494 * Some of the ops may be dynamically allocated, 3504 * Some of the ops may be dynamically allocated,
3495 * they must be freed after a synchronize_sched(). 3505 * they must be freed after a synchronize_sched().
@@ -3502,6 +3512,7 @@ ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip)
3502 op = rcu_dereference_raw(op->next); 3512 op = rcu_dereference_raw(op->next);
3503 }; 3513 };
3504 preempt_enable_notrace(); 3514 preempt_enable_notrace();
3515 trace_recursion_clear(TRACE_INTERNAL_BIT);
3505} 3516}
3506 3517
3507static void clear_ftrace_swapper(void) 3518static void clear_ftrace_swapper(void)
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 0ef7b4b2a1f7..b0c7aa407943 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -2216,7 +2216,7 @@ static noinline void trace_recursive_fail(void)
2216 2216
2217 printk_once(KERN_WARNING "Tracing recursion: depth[%ld]:" 2217 printk_once(KERN_WARNING "Tracing recursion: depth[%ld]:"
2218 "HC[%lu]:SC[%lu]:NMI[%lu]\n", 2218 "HC[%lu]:SC[%lu]:NMI[%lu]\n",
2219 current->trace_recursion, 2219 trace_recursion_buffer(),
2220 hardirq_count() >> HARDIRQ_SHIFT, 2220 hardirq_count() >> HARDIRQ_SHIFT,
2221 softirq_count() >> SOFTIRQ_SHIFT, 2221 softirq_count() >> SOFTIRQ_SHIFT,
2222 in_nmi()); 2222 in_nmi());
@@ -2226,9 +2226,9 @@ static noinline void trace_recursive_fail(void)
2226 2226
2227static inline int trace_recursive_lock(void) 2227static inline int trace_recursive_lock(void)
2228{ 2228{
2229 current->trace_recursion++; 2229 trace_recursion_inc();
2230 2230
2231 if (likely(current->trace_recursion < TRACE_RECURSIVE_DEPTH)) 2231 if (likely(trace_recursion_buffer() < TRACE_RECURSIVE_DEPTH))
2232 return 0; 2232 return 0;
2233 2233
2234 trace_recursive_fail(); 2234 trace_recursive_fail();
@@ -2238,9 +2238,9 @@ static inline int trace_recursive_lock(void)
2238 2238
2239static inline void trace_recursive_unlock(void) 2239static inline void trace_recursive_unlock(void)
2240{ 2240{
2241 WARN_ON_ONCE(!current->trace_recursion); 2241 WARN_ON_ONCE(!trace_recursion_buffer());
2242 2242
2243 current->trace_recursion--; 2243 trace_recursion_dec();
2244} 2244}
2245 2245
2246#else 2246#else
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 6b69c4bd306f..229f8591f61d 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -784,4 +784,19 @@ extern const char *__stop___trace_bprintk_fmt[];
784 FTRACE_ENTRY(call, struct_name, id, PARAMS(tstruct), PARAMS(print)) 784 FTRACE_ENTRY(call, struct_name, id, PARAMS(tstruct), PARAMS(print))
785#include "trace_entries.h" 785#include "trace_entries.h"
786 786
787/* Only current can touch trace_recursion */
788#define trace_recursion_inc() do { (current)->trace_recursion++; } while (0)
789#define trace_recursion_dec() do { (current)->trace_recursion--; } while (0)
790
791/* Ring buffer has the 10 LSB bits to count */
792#define trace_recursion_buffer() ((current)->trace_recursion & 0x3ff)
793
794/* for function tracing recursion */
795#define TRACE_INTERNAL_BIT (1<<11)
796#define TRACE_GLOBAL_BIT (1<<12)
797
798#define trace_recursion_set(bit) do { (current)->trace_recursion |= (bit); } while (0)
799#define trace_recursion_clear(bit) do { (current)->trace_recursion &= ~(bit); } while (0)
800#define trace_recursion_test(bit) ((current)->trace_recursion & (bit))
801
787#endif /* _LINUX_KERNEL_TRACE_H */ 802#endif /* _LINUX_KERNEL_TRACE_H */