diff options
Diffstat (limited to 'kernel/trace/ftrace.c')
-rw-r--r-- | kernel/trace/ftrace.c | 72 |
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 | ||
165 | static int ftrace_filtered; | 165 | static int ftrace_filtered; |
166 | static int tracing_on; | ||
167 | static int frozen_record_count; | ||
166 | 168 | ||
167 | static struct hlist_head ftrace_hash[FTRACE_HASHSIZE]; | 169 | static struct hlist_head ftrace_hash[FTRACE_HASHSIZE]; |
168 | 170 | ||
@@ -195,6 +197,71 @@ static int ftrace_record_suspend; | |||
195 | 197 | ||
196 | static struct dyn_ftrace *ftrace_free_records; | 198 | static struct dyn_ftrace *ftrace_free_records; |
197 | 199 | ||
200 | |||
201 | #ifdef CONFIG_KPROBES | ||
202 | static 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 | |||
210 | static 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 | |||
218 | static 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 | |||
228 | int 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 | |||
198 | static inline int | 265 | static inline int |
199 | ftrace_ip_in_hash(unsigned long ip, unsigned long key) | 266 | ftrace_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); |