diff options
Diffstat (limited to 'kernel/module.c')
-rw-r--r-- | kernel/module.c | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/kernel/module.c b/kernel/module.c index fd1411403558..05ce49ced8f6 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -55,6 +55,11 @@ | |||
55 | #include <linux/percpu.h> | 55 | #include <linux/percpu.h> |
56 | #include <linux/kmemleak.h> | 56 | #include <linux/kmemleak.h> |
57 | 57 | ||
58 | #define CREATE_TRACE_POINTS | ||
59 | #include <trace/events/module.h> | ||
60 | |||
61 | EXPORT_TRACEPOINT_SYMBOL(module_get); | ||
62 | |||
58 | #if 0 | 63 | #if 0 |
59 | #define DEBUGP printk | 64 | #define DEBUGP printk |
60 | #else | 65 | #else |
@@ -364,7 +369,7 @@ EXPORT_SYMBOL_GPL(find_module); | |||
364 | 369 | ||
365 | #ifdef CONFIG_SMP | 370 | #ifdef CONFIG_SMP |
366 | 371 | ||
367 | #ifdef CONFIG_HAVE_DYNAMIC_PER_CPU_AREA | 372 | #ifndef CONFIG_HAVE_LEGACY_PER_CPU_AREA |
368 | 373 | ||
369 | static void *percpu_modalloc(unsigned long size, unsigned long align, | 374 | static void *percpu_modalloc(unsigned long size, unsigned long align, |
370 | const char *name) | 375 | const char *name) |
@@ -389,7 +394,7 @@ static void percpu_modfree(void *freeme) | |||
389 | free_percpu(freeme); | 394 | free_percpu(freeme); |
390 | } | 395 | } |
391 | 396 | ||
392 | #else /* ... !CONFIG_HAVE_DYNAMIC_PER_CPU_AREA */ | 397 | #else /* ... CONFIG_HAVE_LEGACY_PER_CPU_AREA */ |
393 | 398 | ||
394 | /* Number of blocks used and allocated. */ | 399 | /* Number of blocks used and allocated. */ |
395 | static unsigned int pcpu_num_used, pcpu_num_allocated; | 400 | static unsigned int pcpu_num_used, pcpu_num_allocated; |
@@ -535,7 +540,7 @@ static int percpu_modinit(void) | |||
535 | } | 540 | } |
536 | __initcall(percpu_modinit); | 541 | __initcall(percpu_modinit); |
537 | 542 | ||
538 | #endif /* CONFIG_HAVE_DYNAMIC_PER_CPU_AREA */ | 543 | #endif /* CONFIG_HAVE_LEGACY_PER_CPU_AREA */ |
539 | 544 | ||
540 | static unsigned int find_pcpusec(Elf_Ehdr *hdr, | 545 | static unsigned int find_pcpusec(Elf_Ehdr *hdr, |
541 | Elf_Shdr *sechdrs, | 546 | Elf_Shdr *sechdrs, |
@@ -909,16 +914,18 @@ void __symbol_put(const char *symbol) | |||
909 | } | 914 | } |
910 | EXPORT_SYMBOL(__symbol_put); | 915 | EXPORT_SYMBOL(__symbol_put); |
911 | 916 | ||
917 | /* Note this assumes addr is a function, which it currently always is. */ | ||
912 | void symbol_put_addr(void *addr) | 918 | void symbol_put_addr(void *addr) |
913 | { | 919 | { |
914 | struct module *modaddr; | 920 | struct module *modaddr; |
921 | unsigned long a = (unsigned long)dereference_function_descriptor(addr); | ||
915 | 922 | ||
916 | if (core_kernel_text((unsigned long)addr)) | 923 | if (core_kernel_text(a)) |
917 | return; | 924 | return; |
918 | 925 | ||
919 | /* module_text_address is safe here: we're supposed to have reference | 926 | /* module_text_address is safe here: we're supposed to have reference |
920 | * to module from symbol_get, so it can't go away. */ | 927 | * to module from symbol_get, so it can't go away. */ |
921 | modaddr = __module_text_address((unsigned long)addr); | 928 | modaddr = __module_text_address(a); |
922 | BUG_ON(!modaddr); | 929 | BUG_ON(!modaddr); |
923 | module_put(modaddr); | 930 | module_put(modaddr); |
924 | } | 931 | } |
@@ -940,6 +947,8 @@ void module_put(struct module *module) | |||
940 | if (module) { | 947 | if (module) { |
941 | unsigned int cpu = get_cpu(); | 948 | unsigned int cpu = get_cpu(); |
942 | local_dec(__module_ref_addr(module, cpu)); | 949 | local_dec(__module_ref_addr(module, cpu)); |
950 | trace_module_put(module, _RET_IP_, | ||
951 | local_read(__module_ref_addr(module, cpu))); | ||
943 | /* Maybe they're waiting for us to drop reference? */ | 952 | /* Maybe they're waiting for us to drop reference? */ |
944 | if (unlikely(!module_is_live(module))) | 953 | if (unlikely(!module_is_live(module))) |
945 | wake_up_process(module->waiter); | 954 | wake_up_process(module->waiter); |
@@ -1272,6 +1281,10 @@ static void add_notes_attrs(struct module *mod, unsigned int nsect, | |||
1272 | struct module_notes_attrs *notes_attrs; | 1281 | struct module_notes_attrs *notes_attrs; |
1273 | struct bin_attribute *nattr; | 1282 | struct bin_attribute *nattr; |
1274 | 1283 | ||
1284 | /* failed to create section attributes, so can't create notes */ | ||
1285 | if (!mod->sect_attrs) | ||
1286 | return; | ||
1287 | |||
1275 | /* Count notes sections and allocate structures. */ | 1288 | /* Count notes sections and allocate structures. */ |
1276 | notes = 0; | 1289 | notes = 0; |
1277 | for (i = 0; i < nsect; i++) | 1290 | for (i = 0; i < nsect; i++) |
@@ -1491,6 +1504,8 @@ static int __unlink_module(void *_mod) | |||
1491 | /* Free a module, remove from lists, etc (must hold module_mutex). */ | 1504 | /* Free a module, remove from lists, etc (must hold module_mutex). */ |
1492 | static void free_module(struct module *mod) | 1505 | static void free_module(struct module *mod) |
1493 | { | 1506 | { |
1507 | trace_module_free(mod); | ||
1508 | |||
1494 | /* Delete from various lists */ | 1509 | /* Delete from various lists */ |
1495 | stop_machine(__unlink_module, mod, NULL); | 1510 | stop_machine(__unlink_module, mod, NULL); |
1496 | remove_notes_attrs(mod); | 1511 | remove_notes_attrs(mod); |
@@ -2358,6 +2373,8 @@ static noinline struct module *load_module(void __user *umod, | |||
2358 | /* Get rid of temporary copy */ | 2373 | /* Get rid of temporary copy */ |
2359 | vfree(hdr); | 2374 | vfree(hdr); |
2360 | 2375 | ||
2376 | trace_module_load(mod); | ||
2377 | |||
2361 | /* Done! */ | 2378 | /* Done! */ |
2362 | return mod; | 2379 | return mod; |
2363 | 2380 | ||