diff options
Diffstat (limited to 'kernel/trace')
-rw-r--r-- | kernel/trace/ftrace.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 4dda4f60a2a9..1f54a94189fe 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
@@ -164,10 +164,14 @@ static DEFINE_SPINLOCK(ftrace_hash_lock); | |||
164 | #define ftrace_hash_lock(flags) spin_lock_irqsave(&ftrace_hash_lock, flags) | 164 | #define ftrace_hash_lock(flags) spin_lock_irqsave(&ftrace_hash_lock, flags) |
165 | #define ftrace_hash_unlock(flags) \ | 165 | #define ftrace_hash_unlock(flags) \ |
166 | spin_unlock_irqrestore(&ftrace_hash_lock, flags) | 166 | spin_unlock_irqrestore(&ftrace_hash_lock, flags) |
167 | static void ftrace_release_hash(unsigned long start, unsigned long end); | ||
167 | #else | 168 | #else |
168 | /* This is protected via the ftrace_lock with MCOUNT_RECORD. */ | 169 | /* This is protected via the ftrace_lock with MCOUNT_RECORD. */ |
169 | #define ftrace_hash_lock(flags) do { (void)(flags); } while (0) | 170 | #define ftrace_hash_lock(flags) do { (void)(flags); } while (0) |
170 | #define ftrace_hash_unlock(flags) do { } while(0) | 171 | #define ftrace_hash_unlock(flags) do { } while(0) |
172 | static inline void ftrace_release_hash(unsigned long start, unsigned long end) | ||
173 | { | ||
174 | } | ||
171 | #endif | 175 | #endif |
172 | 176 | ||
173 | /* | 177 | /* |
@@ -347,6 +351,7 @@ void ftrace_release(void *start, unsigned long size) | |||
347 | } | 351 | } |
348 | spin_unlock(&ftrace_lock); | 352 | spin_unlock(&ftrace_lock); |
349 | 353 | ||
354 | ftrace_release_hash(s, e); | ||
350 | } | 355 | } |
351 | 356 | ||
352 | static struct dyn_ftrace *ftrace_alloc_dyn_node(unsigned long ip) | 357 | static struct dyn_ftrace *ftrace_alloc_dyn_node(unsigned long ip) |
@@ -1659,6 +1664,44 @@ void __init ftrace_init(void) | |||
1659 | ftrace_disabled = 1; | 1664 | ftrace_disabled = 1; |
1660 | } | 1665 | } |
1661 | #else /* CONFIG_FTRACE_MCOUNT_RECORD */ | 1666 | #else /* CONFIG_FTRACE_MCOUNT_RECORD */ |
1667 | |||
1668 | static void ftrace_release_hash(unsigned long start, unsigned long end) | ||
1669 | { | ||
1670 | struct dyn_ftrace *rec; | ||
1671 | struct hlist_node *t, *n; | ||
1672 | struct hlist_head *head, temp_list; | ||
1673 | unsigned long flags; | ||
1674 | int i, cpu; | ||
1675 | |||
1676 | preempt_disable_notrace(); | ||
1677 | |||
1678 | /* disable incase we call something that calls mcount */ | ||
1679 | cpu = raw_smp_processor_id(); | ||
1680 | per_cpu(ftrace_shutdown_disable_cpu, cpu)++; | ||
1681 | |||
1682 | ftrace_hash_lock(flags); | ||
1683 | |||
1684 | for (i = 0; i < FTRACE_HASHSIZE; i++) { | ||
1685 | INIT_HLIST_HEAD(&temp_list); | ||
1686 | head = &ftrace_hash[i]; | ||
1687 | |||
1688 | /* all CPUS are stopped, we are safe to modify code */ | ||
1689 | hlist_for_each_entry_safe(rec, t, n, head, node) { | ||
1690 | if (rec->flags & FTRACE_FL_FREE) | ||
1691 | continue; | ||
1692 | |||
1693 | if ((rec->ip >= start) && (rec->ip < end)) | ||
1694 | ftrace_free_rec(rec); | ||
1695 | } | ||
1696 | } | ||
1697 | |||
1698 | ftrace_hash_unlock(flags); | ||
1699 | |||
1700 | per_cpu(ftrace_shutdown_disable_cpu, cpu)--; | ||
1701 | preempt_enable_notrace(); | ||
1702 | |||
1703 | } | ||
1704 | |||
1662 | static int ftraced(void *ignore) | 1705 | static int ftraced(void *ignore) |
1663 | { | 1706 | { |
1664 | unsigned long usecs; | 1707 | unsigned long usecs; |