aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/ftrace.h7
-rw-r--r--include/linux/module.h4
-rw-r--r--kernel/module.c19
-rw-r--r--kernel/trace/ftrace.c90
4 files changed, 75 insertions, 45 deletions
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 53869bef6102..97c83e1bc589 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -233,8 +233,6 @@ extern int ftrace_arch_read_dyn_info(char *buf, int size);
233 233
234extern int skip_trace(unsigned long ip); 234extern int skip_trace(unsigned long ip);
235 235
236extern void ftrace_release(void *start, unsigned long size);
237
238extern void ftrace_disable_daemon(void); 236extern void ftrace_disable_daemon(void);
239extern void ftrace_enable_daemon(void); 237extern void ftrace_enable_daemon(void);
240#else 238#else
@@ -325,13 +323,8 @@ static inline void __ftrace_enabled_restore(int enabled)
325 323
326#ifdef CONFIG_FTRACE_MCOUNT_RECORD 324#ifdef CONFIG_FTRACE_MCOUNT_RECORD
327extern void ftrace_init(void); 325extern void ftrace_init(void);
328extern void ftrace_init_module(struct module *mod,
329 unsigned long *start, unsigned long *end);
330#else 326#else
331static inline void ftrace_init(void) { } 327static inline void ftrace_init(void) { }
332static inline void
333ftrace_init_module(struct module *mod,
334 unsigned long *start, unsigned long *end) { }
335#endif 328#endif
336 329
337/* 330/*
diff --git a/include/linux/module.h b/include/linux/module.h
index 6155fa44168b..a8f2c0aa4c32 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -341,6 +341,10 @@ struct module
341 struct ftrace_event_call *trace_events; 341 struct ftrace_event_call *trace_events;
342 unsigned int num_trace_events; 342 unsigned int num_trace_events;
343#endif 343#endif
344#ifdef CONFIG_FTRACE_MCOUNT_RECORD
345 unsigned long *ftrace_callsites;
346 unsigned int num_ftrace_callsites;
347#endif
344 348
345#ifdef CONFIG_MODULE_UNLOAD 349#ifdef CONFIG_MODULE_UNLOAD
346 /* What modules depend on me? */ 350 /* What modules depend on me? */
diff --git a/kernel/module.c b/kernel/module.c
index a0394706f10c..2383e60fcf3f 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -1490,9 +1490,6 @@ static void free_module(struct module *mod)
1490 /* Free any allocated parameters. */ 1490 /* Free any allocated parameters. */
1491 destroy_params(mod->kp, mod->num_kp); 1491 destroy_params(mod->kp, mod->num_kp);
1492 1492
1493 /* release any pointers to mcount in this module */
1494 ftrace_release(mod->module_core, mod->core_size);
1495
1496 /* This may be NULL, but that's OK */ 1493 /* This may be NULL, but that's OK */
1497 module_free(mod, mod->module_init); 1494 module_free(mod, mod->module_init);
1498 kfree(mod->args); 1495 kfree(mod->args);
@@ -1893,11 +1890,9 @@ static noinline struct module *load_module(void __user *umod,
1893 unsigned int symindex = 0; 1890 unsigned int symindex = 0;
1894 unsigned int strindex = 0; 1891 unsigned int strindex = 0;
1895 unsigned int modindex, versindex, infoindex, pcpuindex; 1892 unsigned int modindex, versindex, infoindex, pcpuindex;
1896 unsigned int num_mcount;
1897 struct module *mod; 1893 struct module *mod;
1898 long err = 0; 1894 long err = 0;
1899 void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */ 1895 void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
1900 unsigned long *mseg;
1901 mm_segment_t old_fs; 1896 mm_segment_t old_fs;
1902 1897
1903 DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n", 1898 DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n",
@@ -2179,7 +2174,13 @@ static noinline struct module *load_module(void __user *umod,
2179 sizeof(*mod->trace_events), 2174 sizeof(*mod->trace_events),
2180 &mod->num_trace_events); 2175 &mod->num_trace_events);
2181#endif 2176#endif
2182 2177#ifdef CONFIG_FTRACE_MCOUNT_RECORD
2178 /* sechdrs[0].sh_size is always zero */
2179 mod->ftrace_callsites = section_objs(hdr, sechdrs, secstrings,
2180 "__mcount_loc",
2181 sizeof(*mod->ftrace_callsites),
2182 &mod->num_ftrace_callsites);
2183#endif
2183#ifdef CONFIG_MODVERSIONS 2184#ifdef CONFIG_MODVERSIONS
2184 if ((mod->num_syms && !mod->crcs) 2185 if ((mod->num_syms && !mod->crcs)
2185 || (mod->num_gpl_syms && !mod->gpl_crcs) 2186 || (mod->num_gpl_syms && !mod->gpl_crcs)
@@ -2244,11 +2245,6 @@ static noinline struct module *load_module(void __user *umod,
2244 dynamic_debug_setup(debug, num_debug); 2245 dynamic_debug_setup(debug, num_debug);
2245 } 2246 }
2246 2247
2247 /* sechdrs[0].sh_size is always zero */
2248 mseg = section_objs(hdr, sechdrs, secstrings, "__mcount_loc",
2249 sizeof(*mseg), &num_mcount);
2250 ftrace_init_module(mod, mseg, mseg + num_mcount);
2251
2252 err = module_finalize(hdr, sechdrs, mod); 2248 err = module_finalize(hdr, sechdrs, mod);
2253 if (err < 0) 2249 if (err < 0)
2254 goto cleanup; 2250 goto cleanup;
@@ -2309,7 +2305,6 @@ static noinline struct module *load_module(void __user *umod,
2309 cleanup: 2305 cleanup:
2310 kobject_del(&mod->mkobj.kobj); 2306 kobject_del(&mod->mkobj.kobj);
2311 kobject_put(&mod->mkobj.kobj); 2307 kobject_put(&mod->mkobj.kobj);
2312 ftrace_release(mod->module_core, mod->core_size);
2313 free_unload: 2308 free_unload:
2314 module_unload_free(mod); 2309 module_unload_free(mod);
2315#if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) 2310#if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP)
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index a23488988581..5b606f45b6c4 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -916,30 +916,6 @@ static void ftrace_free_rec(struct dyn_ftrace *rec)
916 rec->flags |= FTRACE_FL_FREE; 916 rec->flags |= FTRACE_FL_FREE;
917} 917}
918 918
919void ftrace_release(void *start, unsigned long size)
920{
921 struct dyn_ftrace *rec;
922 struct ftrace_page *pg;
923 unsigned long s = (unsigned long)start;
924 unsigned long e = s + size;
925
926 if (ftrace_disabled || !start)
927 return;
928
929 mutex_lock(&ftrace_lock);
930 do_for_each_ftrace_rec(pg, rec) {
931 if ((rec->ip >= s) && (rec->ip < e)) {
932 /*
933 * rec->ip is changed in ftrace_free_rec()
934 * It should not between s and e if record was freed.
935 */
936 FTRACE_WARN_ON(rec->flags & FTRACE_FL_FREE);
937 ftrace_free_rec(rec);
938 }
939 } while_for_each_ftrace_rec();
940 mutex_unlock(&ftrace_lock);
941}
942
943static struct dyn_ftrace *ftrace_alloc_dyn_node(unsigned long ip) 919static struct dyn_ftrace *ftrace_alloc_dyn_node(unsigned long ip)
944{ 920{
945 struct dyn_ftrace *rec; 921 struct dyn_ftrace *rec;
@@ -2752,14 +2728,72 @@ static int ftrace_convert_nops(struct module *mod,
2752 return 0; 2728 return 0;
2753} 2729}
2754 2730
2755void ftrace_init_module(struct module *mod, 2731#ifdef CONFIG_MODULES
2756 unsigned long *start, unsigned long *end) 2732void ftrace_release(void *start, void *end)
2733{
2734 struct dyn_ftrace *rec;
2735 struct ftrace_page *pg;
2736 unsigned long s = (unsigned long)start;
2737 unsigned long e = (unsigned long)end;
2738
2739 if (ftrace_disabled || !start || start == end)
2740 return;
2741
2742 mutex_lock(&ftrace_lock);
2743 do_for_each_ftrace_rec(pg, rec) {
2744 if ((rec->ip >= s) && (rec->ip < e)) {
2745 /*
2746 * rec->ip is changed in ftrace_free_rec()
2747 * It should not between s and e if record was freed.
2748 */
2749 FTRACE_WARN_ON(rec->flags & FTRACE_FL_FREE);
2750 ftrace_free_rec(rec);
2751 }
2752 } while_for_each_ftrace_rec();
2753 mutex_unlock(&ftrace_lock);
2754}
2755
2756static void ftrace_init_module(struct module *mod,
2757 unsigned long *start, unsigned long *end)
2757{ 2758{
2758 if (ftrace_disabled || start == end) 2759 if (ftrace_disabled || start == end)
2759 return; 2760 return;
2760 ftrace_convert_nops(mod, start, end); 2761 ftrace_convert_nops(mod, start, end);
2761} 2762}
2762 2763
2764static int ftrace_module_notify(struct notifier_block *self,
2765 unsigned long val, void *data)
2766{
2767 struct module *mod = data;
2768
2769 switch (val) {
2770 case MODULE_STATE_COMING:
2771 ftrace_init_module(mod, mod->ftrace_callsites,
2772 mod->ftrace_callsites +
2773 mod->num_ftrace_callsites);
2774 break;
2775 case MODULE_STATE_GOING:
2776 ftrace_release(mod->ftrace_callsites,
2777 mod->ftrace_callsites +
2778 mod->num_ftrace_callsites);
2779 break;
2780 }
2781
2782 return 0;
2783}
2784#else
2785static int ftrace_module_notify(struct notifier_block *self,
2786 unsigned long val, void *data)
2787{
2788 return 0;
2789}
2790#endif /* CONFIG_MODULES */
2791
2792struct notifier_block ftrace_module_nb = {
2793 .notifier_call = ftrace_module_notify,
2794 .priority = 0,
2795};
2796
2763extern unsigned long __start_mcount_loc[]; 2797extern unsigned long __start_mcount_loc[];
2764extern unsigned long __stop_mcount_loc[]; 2798extern unsigned long __stop_mcount_loc[];
2765 2799
@@ -2791,6 +2825,10 @@ void __init ftrace_init(void)
2791 __start_mcount_loc, 2825 __start_mcount_loc,
2792 __stop_mcount_loc); 2826 __stop_mcount_loc);
2793 2827
2828 ret = register_module_notifier(&ftrace_module_nb);
2829 if (!ret)
2830 pr_warning("Failed to register trace ftrace module notifier\n");
2831
2794 return; 2832 return;
2795 failed: 2833 failed:
2796 ftrace_disabled = 1; 2834 ftrace_disabled = 1;