aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/ftrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/trace/ftrace.c')
-rw-r--r--kernel/trace/ftrace.c72
1 files changed, 71 insertions, 1 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index f1e9e5c74e64..d1238163155f 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -163,6 +163,8 @@ enum {
163}; 163};
164 164
165static int ftrace_filtered; 165static int ftrace_filtered;
166static int tracing_on;
167static int frozen_record_count;
166 168
167static struct hlist_head ftrace_hash[FTRACE_HASHSIZE]; 169static struct hlist_head ftrace_hash[FTRACE_HASHSIZE];
168 170
@@ -195,6 +197,71 @@ static int ftrace_record_suspend;
195 197
196static struct dyn_ftrace *ftrace_free_records; 198static struct dyn_ftrace *ftrace_free_records;
197 199
200
201#ifdef CONFIG_KPROBES
202static inline void freeze_record(struct dyn_ftrace *rec)
203{
204 if (!(rec->flags & FTRACE_FL_FROZEN)) {
205 rec->flags |= FTRACE_FL_FROZEN;
206 frozen_record_count++;
207 }
208}
209
210static inline void unfreeze_record(struct dyn_ftrace *rec)
211{
212 if (rec->flags & FTRACE_FL_FROZEN) {
213 rec->flags &= ~FTRACE_FL_FROZEN;
214 frozen_record_count--;
215 }
216}
217
218static inline int record_frozen(struct dyn_ftrace *rec)
219{
220 return rec->flags & FTRACE_FL_FROZEN;
221}
222#else
223# define freeze_record(rec) ({ 0; })
224# define unfreeze_record(rec) ({ 0; })
225# define record_frozen(rec) ({ 0; })
226#endif /* CONFIG_KPROBES */
227
228int skip_trace(unsigned long ip)
229{
230 unsigned long fl;
231 struct dyn_ftrace *rec;
232 struct hlist_node *t;
233 struct hlist_head *head;
234
235 if (frozen_record_count == 0)
236 return 0;
237
238 head = &ftrace_hash[hash_long(ip, FTRACE_HASHBITS)];
239 hlist_for_each_entry_rcu(rec, t, head, node) {
240 if (rec->ip == ip) {
241 if (record_frozen(rec)) {
242 if (rec->flags & FTRACE_FL_FAILED)
243 return 1;
244
245 if (!(rec->flags & FTRACE_FL_CONVERTED))
246 return 1;
247
248 if (!tracing_on || !ftrace_enabled)
249 return 1;
250
251 if (ftrace_filtered) {
252 fl = rec->flags & (FTRACE_FL_FILTER |
253 FTRACE_FL_NOTRACE);
254 if (!fl || (fl & FTRACE_FL_NOTRACE))
255 return 1;
256 }
257 }
258 break;
259 }
260 }
261
262 return 0;
263}
264
198static inline int 265static inline int
199ftrace_ip_in_hash(unsigned long ip, unsigned long key) 266ftrace_ip_in_hash(unsigned long ip, unsigned long key)
200{ 267{
@@ -489,8 +556,11 @@ static int __ftrace_modify_code(void *data)
489 */ 556 */
490 __ftrace_update_code(NULL); 557 __ftrace_update_code(NULL);
491 ftrace_replace_code(1); 558 ftrace_replace_code(1);
492 } else if (*command & FTRACE_DISABLE_CALLS) 559 tracing_on = 1;
560 } else if (*command & FTRACE_DISABLE_CALLS) {
493 ftrace_replace_code(0); 561 ftrace_replace_code(0);
562 tracing_on = 0;
563 }
494 564
495 if (*command & FTRACE_UPDATE_TRACE_FUNC) 565 if (*command & FTRACE_UPDATE_TRACE_FUNC)
496 ftrace_update_ftrace_func(ftrace_trace_function); 566 ftrace_update_ftrace_func(ftrace_trace_function);