diff options
Diffstat (limited to 'kernel/module.c')
-rw-r--r-- | kernel/module.c | 109 |
1 files changed, 78 insertions, 31 deletions
diff --git a/kernel/module.c b/kernel/module.c index c9332c90d5a0..f0e04d6b67d8 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <linux/tracepoint.h> | 51 | #include <linux/tracepoint.h> |
52 | #include <linux/ftrace.h> | 52 | #include <linux/ftrace.h> |
53 | #include <linux/async.h> | 53 | #include <linux/async.h> |
54 | #include <linux/percpu.h> | ||
54 | 55 | ||
55 | #if 0 | 56 | #if 0 |
56 | #define DEBUGP printk | 57 | #define DEBUGP printk |
@@ -366,6 +367,34 @@ static struct module *find_module(const char *name) | |||
366 | } | 367 | } |
367 | 368 | ||
368 | #ifdef CONFIG_SMP | 369 | #ifdef CONFIG_SMP |
370 | |||
371 | #ifdef CONFIG_HAVE_DYNAMIC_PER_CPU_AREA | ||
372 | |||
373 | static void *percpu_modalloc(unsigned long size, unsigned long align, | ||
374 | const char *name) | ||
375 | { | ||
376 | void *ptr; | ||
377 | |||
378 | if (align > PAGE_SIZE) { | ||
379 | printk(KERN_WARNING "%s: per-cpu alignment %li > %li\n", | ||
380 | name, align, PAGE_SIZE); | ||
381 | align = PAGE_SIZE; | ||
382 | } | ||
383 | |||
384 | ptr = __alloc_reserved_percpu(size, align); | ||
385 | if (!ptr) | ||
386 | printk(KERN_WARNING | ||
387 | "Could not allocate %lu bytes percpu data\n", size); | ||
388 | return ptr; | ||
389 | } | ||
390 | |||
391 | static void percpu_modfree(void *freeme) | ||
392 | { | ||
393 | free_percpu(freeme); | ||
394 | } | ||
395 | |||
396 | #else /* ... !CONFIG_HAVE_DYNAMIC_PER_CPU_AREA */ | ||
397 | |||
369 | /* Number of blocks used and allocated. */ | 398 | /* Number of blocks used and allocated. */ |
370 | static unsigned int pcpu_num_used, pcpu_num_allocated; | 399 | static unsigned int pcpu_num_used, pcpu_num_allocated; |
371 | /* Size of each block. -ve means used. */ | 400 | /* Size of each block. -ve means used. */ |
@@ -480,21 +509,6 @@ static void percpu_modfree(void *freeme) | |||
480 | } | 509 | } |
481 | } | 510 | } |
482 | 511 | ||
483 | static unsigned int find_pcpusec(Elf_Ehdr *hdr, | ||
484 | Elf_Shdr *sechdrs, | ||
485 | const char *secstrings) | ||
486 | { | ||
487 | return find_sec(hdr, sechdrs, secstrings, ".data.percpu"); | ||
488 | } | ||
489 | |||
490 | static void percpu_modcopy(void *pcpudest, const void *from, unsigned long size) | ||
491 | { | ||
492 | int cpu; | ||
493 | |||
494 | for_each_possible_cpu(cpu) | ||
495 | memcpy(pcpudest + per_cpu_offset(cpu), from, size); | ||
496 | } | ||
497 | |||
498 | static int percpu_modinit(void) | 512 | static int percpu_modinit(void) |
499 | { | 513 | { |
500 | pcpu_num_used = 2; | 514 | pcpu_num_used = 2; |
@@ -513,7 +527,26 @@ static int percpu_modinit(void) | |||
513 | return 0; | 527 | return 0; |
514 | } | 528 | } |
515 | __initcall(percpu_modinit); | 529 | __initcall(percpu_modinit); |
530 | |||
531 | #endif /* CONFIG_HAVE_DYNAMIC_PER_CPU_AREA */ | ||
532 | |||
533 | static unsigned int find_pcpusec(Elf_Ehdr *hdr, | ||
534 | Elf_Shdr *sechdrs, | ||
535 | const char *secstrings) | ||
536 | { | ||
537 | return find_sec(hdr, sechdrs, secstrings, ".data.percpu"); | ||
538 | } | ||
539 | |||
540 | static void percpu_modcopy(void *pcpudest, const void *from, unsigned long size) | ||
541 | { | ||
542 | int cpu; | ||
543 | |||
544 | for_each_possible_cpu(cpu) | ||
545 | memcpy(pcpudest + per_cpu_offset(cpu), from, size); | ||
546 | } | ||
547 | |||
516 | #else /* ... !CONFIG_SMP */ | 548 | #else /* ... !CONFIG_SMP */ |
549 | |||
517 | static inline void *percpu_modalloc(unsigned long size, unsigned long align, | 550 | static inline void *percpu_modalloc(unsigned long size, unsigned long align, |
518 | const char *name) | 551 | const char *name) |
519 | { | 552 | { |
@@ -535,6 +568,7 @@ static inline void percpu_modcopy(void *pcpudst, const void *src, | |||
535 | /* pcpusec should be 0, and size of that section should be 0. */ | 568 | /* pcpusec should be 0, and size of that section should be 0. */ |
536 | BUG_ON(size != 0); | 569 | BUG_ON(size != 0); |
537 | } | 570 | } |
571 | |||
538 | #endif /* CONFIG_SMP */ | 572 | #endif /* CONFIG_SMP */ |
539 | 573 | ||
540 | #define MODINFO_ATTR(field) \ | 574 | #define MODINFO_ATTR(field) \ |
@@ -573,13 +607,13 @@ static char last_unloaded_module[MODULE_NAME_LEN+1]; | |||
573 | /* Init the unload section of the module. */ | 607 | /* Init the unload section of the module. */ |
574 | static void module_unload_init(struct module *mod) | 608 | static void module_unload_init(struct module *mod) |
575 | { | 609 | { |
576 | unsigned int i; | 610 | int cpu; |
577 | 611 | ||
578 | INIT_LIST_HEAD(&mod->modules_which_use_me); | 612 | INIT_LIST_HEAD(&mod->modules_which_use_me); |
579 | for (i = 0; i < NR_CPUS; i++) | 613 | for_each_possible_cpu(cpu) |
580 | local_set(&mod->ref[i].count, 0); | 614 | local_set(__module_ref_addr(mod, cpu), 0); |
581 | /* Hold reference count during initialization. */ | 615 | /* Hold reference count during initialization. */ |
582 | local_set(&mod->ref[raw_smp_processor_id()].count, 1); | 616 | local_set(__module_ref_addr(mod, raw_smp_processor_id()), 1); |
583 | /* Backwards compatibility macros put refcount during init. */ | 617 | /* Backwards compatibility macros put refcount during init. */ |
584 | mod->waiter = current; | 618 | mod->waiter = current; |
585 | } | 619 | } |
@@ -717,10 +751,11 @@ static int try_stop_module(struct module *mod, int flags, int *forced) | |||
717 | 751 | ||
718 | unsigned int module_refcount(struct module *mod) | 752 | unsigned int module_refcount(struct module *mod) |
719 | { | 753 | { |
720 | unsigned int i, total = 0; | 754 | unsigned int total = 0; |
755 | int cpu; | ||
721 | 756 | ||
722 | for (i = 0; i < NR_CPUS; i++) | 757 | for_each_possible_cpu(cpu) |
723 | total += local_read(&mod->ref[i].count); | 758 | total += local_read(__module_ref_addr(mod, cpu)); |
724 | return total; | 759 | return total; |
725 | } | 760 | } |
726 | EXPORT_SYMBOL(module_refcount); | 761 | EXPORT_SYMBOL(module_refcount); |
@@ -743,8 +778,8 @@ static void wait_for_zero_refcount(struct module *mod) | |||
743 | mutex_lock(&module_mutex); | 778 | mutex_lock(&module_mutex); |
744 | } | 779 | } |
745 | 780 | ||
746 | asmlinkage long | 781 | SYSCALL_DEFINE2(delete_module, const char __user *, name_user, |
747 | sys_delete_module(const char __user *name_user, unsigned int flags) | 782 | unsigned int, flags) |
748 | { | 783 | { |
749 | struct module *mod; | 784 | struct module *mod; |
750 | char name[MODULE_NAME_LEN]; | 785 | char name[MODULE_NAME_LEN]; |
@@ -894,7 +929,7 @@ void module_put(struct module *module) | |||
894 | { | 929 | { |
895 | if (module) { | 930 | if (module) { |
896 | unsigned int cpu = get_cpu(); | 931 | unsigned int cpu = get_cpu(); |
897 | local_dec(&module->ref[cpu].count); | 932 | local_dec(__module_ref_addr(module, cpu)); |
898 | /* Maybe they're waiting for us to drop reference? */ | 933 | /* Maybe they're waiting for us to drop reference? */ |
899 | if (unlikely(!module_is_live(module))) | 934 | if (unlikely(!module_is_live(module))) |
900 | wake_up_process(module->waiter); | 935 | wake_up_process(module->waiter); |
@@ -1464,7 +1499,10 @@ static void free_module(struct module *mod) | |||
1464 | kfree(mod->args); | 1499 | kfree(mod->args); |
1465 | if (mod->percpu) | 1500 | if (mod->percpu) |
1466 | percpu_modfree(mod->percpu); | 1501 | percpu_modfree(mod->percpu); |
1467 | 1502 | #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) | |
1503 | if (mod->refptr) | ||
1504 | percpu_modfree(mod->refptr); | ||
1505 | #endif | ||
1468 | /* Free lock-classes: */ | 1506 | /* Free lock-classes: */ |
1469 | lockdep_free_key_range(mod->module_core, mod->core_size); | 1507 | lockdep_free_key_range(mod->module_core, mod->core_size); |
1470 | 1508 | ||
@@ -2011,6 +2049,14 @@ static noinline struct module *load_module(void __user *umod, | |||
2011 | if (err < 0) | 2049 | if (err < 0) |
2012 | goto free_mod; | 2050 | goto free_mod; |
2013 | 2051 | ||
2052 | #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) | ||
2053 | mod->refptr = percpu_modalloc(sizeof(local_t), __alignof__(local_t), | ||
2054 | mod->name); | ||
2055 | if (!mod->refptr) { | ||
2056 | err = -ENOMEM; | ||
2057 | goto free_mod; | ||
2058 | } | ||
2059 | #endif | ||
2014 | if (pcpuindex) { | 2060 | if (pcpuindex) { |
2015 | /* We have a special allocation for this section. */ | 2061 | /* We have a special allocation for this section. */ |
2016 | percpu = percpu_modalloc(sechdrs[pcpuindex].sh_size, | 2062 | percpu = percpu_modalloc(sechdrs[pcpuindex].sh_size, |
@@ -2018,7 +2064,7 @@ static noinline struct module *load_module(void __user *umod, | |||
2018 | mod->name); | 2064 | mod->name); |
2019 | if (!percpu) { | 2065 | if (!percpu) { |
2020 | err = -ENOMEM; | 2066 | err = -ENOMEM; |
2021 | goto free_mod; | 2067 | goto free_percpu; |
2022 | } | 2068 | } |
2023 | sechdrs[pcpuindex].sh_flags &= ~(unsigned long)SHF_ALLOC; | 2069 | sechdrs[pcpuindex].sh_flags &= ~(unsigned long)SHF_ALLOC; |
2024 | mod->percpu = percpu; | 2070 | mod->percpu = percpu; |
@@ -2282,6 +2328,9 @@ static noinline struct module *load_module(void __user *umod, | |||
2282 | free_percpu: | 2328 | free_percpu: |
2283 | if (percpu) | 2329 | if (percpu) |
2284 | percpu_modfree(percpu); | 2330 | percpu_modfree(percpu); |
2331 | #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) | ||
2332 | percpu_modfree(mod->refptr); | ||
2333 | #endif | ||
2285 | free_mod: | 2334 | free_mod: |
2286 | kfree(args); | 2335 | kfree(args); |
2287 | free_hdr: | 2336 | free_hdr: |
@@ -2296,10 +2345,8 @@ static noinline struct module *load_module(void __user *umod, | |||
2296 | } | 2345 | } |
2297 | 2346 | ||
2298 | /* This is where the real work happens */ | 2347 | /* This is where the real work happens */ |
2299 | asmlinkage long | 2348 | SYSCALL_DEFINE3(init_module, void __user *, umod, |
2300 | sys_init_module(void __user *umod, | 2349 | unsigned long, len, const char __user *, uargs) |
2301 | unsigned long len, | ||
2302 | const char __user *uargs) | ||
2303 | { | 2350 | { |
2304 | struct module *mod; | 2351 | struct module *mod; |
2305 | int ret = 0; | 2352 | int ret = 0; |