diff options
Diffstat (limited to 'kernel/module.c')
-rw-r--r-- | kernel/module.c | 35 |
1 files changed, 16 insertions, 19 deletions
diff --git a/kernel/module.c b/kernel/module.c index d1a161be7b04..c18107942ac2 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -482,23 +482,28 @@ static inline void __percpu *mod_percpu(struct module *mod) | |||
482 | return mod->percpu; | 482 | return mod->percpu; |
483 | } | 483 | } |
484 | 484 | ||
485 | static int percpu_modalloc(struct module *mod, | 485 | static int percpu_modalloc(struct module *mod, struct load_info *info) |
486 | unsigned long size, unsigned long align) | ||
487 | { | 486 | { |
487 | Elf_Shdr *pcpusec = &info->sechdrs[info->index.pcpu]; | ||
488 | unsigned long align = pcpusec->sh_addralign; | ||
489 | |||
490 | if (!pcpusec->sh_size) | ||
491 | return 0; | ||
492 | |||
488 | if (align > PAGE_SIZE) { | 493 | if (align > PAGE_SIZE) { |
489 | printk(KERN_WARNING "%s: per-cpu alignment %li > %li\n", | 494 | printk(KERN_WARNING "%s: per-cpu alignment %li > %li\n", |
490 | mod->name, align, PAGE_SIZE); | 495 | mod->name, align, PAGE_SIZE); |
491 | align = PAGE_SIZE; | 496 | align = PAGE_SIZE; |
492 | } | 497 | } |
493 | 498 | ||
494 | mod->percpu = __alloc_reserved_percpu(size, align); | 499 | mod->percpu = __alloc_reserved_percpu(pcpusec->sh_size, align); |
495 | if (!mod->percpu) { | 500 | if (!mod->percpu) { |
496 | printk(KERN_WARNING | 501 | printk(KERN_WARNING |
497 | "%s: Could not allocate %lu bytes percpu data\n", | 502 | "%s: Could not allocate %lu bytes percpu data\n", |
498 | mod->name, size); | 503 | mod->name, (unsigned long)pcpusec->sh_size); |
499 | return -ENOMEM; | 504 | return -ENOMEM; |
500 | } | 505 | } |
501 | mod->percpu_size = size; | 506 | mod->percpu_size = pcpusec->sh_size; |
502 | return 0; | 507 | return 0; |
503 | } | 508 | } |
504 | 509 | ||
@@ -563,10 +568,12 @@ static inline void __percpu *mod_percpu(struct module *mod) | |||
563 | { | 568 | { |
564 | return NULL; | 569 | return NULL; |
565 | } | 570 | } |
566 | static inline int percpu_modalloc(struct module *mod, | 571 | static int percpu_modalloc(struct module *mod, struct load_info *info) |
567 | unsigned long size, unsigned long align) | ||
568 | { | 572 | { |
569 | return -ENOMEM; | 573 | /* UP modules shouldn't have this section: ENOMEM isn't quite right */ |
574 | if (info->sechdrs[info->index.pcpu].sh_size != 0) | ||
575 | return -ENOMEM; | ||
576 | return 0; | ||
570 | } | 577 | } |
571 | static inline void percpu_modfree(struct module *mod) | 578 | static inline void percpu_modfree(struct module *mod) |
572 | { | 579 | { |
@@ -2976,16 +2983,6 @@ static struct module *layout_and_allocate(struct load_info *info, int flags) | |||
2976 | return mod; | 2983 | return mod; |
2977 | } | 2984 | } |
2978 | 2985 | ||
2979 | static int alloc_module_percpu(struct module *mod, struct load_info *info) | ||
2980 | { | ||
2981 | Elf_Shdr *pcpusec = &info->sechdrs[info->index.pcpu]; | ||
2982 | if (!pcpusec->sh_size) | ||
2983 | return 0; | ||
2984 | |||
2985 | /* We have a special allocation for this section. */ | ||
2986 | return percpu_modalloc(mod, pcpusec->sh_size, pcpusec->sh_addralign); | ||
2987 | } | ||
2988 | |||
2989 | /* mod is no longer valid after this! */ | 2986 | /* mod is no longer valid after this! */ |
2990 | static void module_deallocate(struct module *mod, struct load_info *info) | 2987 | static void module_deallocate(struct module *mod, struct load_info *info) |
2991 | { | 2988 | { |
@@ -3260,7 +3257,7 @@ static int load_module(struct load_info *info, const char __user *uargs, | |||
3260 | #endif | 3257 | #endif |
3261 | 3258 | ||
3262 | /* To avoid stressing percpu allocator, do this once we're unique. */ | 3259 | /* To avoid stressing percpu allocator, do this once we're unique. */ |
3263 | err = alloc_module_percpu(mod, info); | 3260 | err = percpu_modalloc(mod, info); |
3264 | if (err) | 3261 | if (err) |
3265 | goto unlink_mod; | 3262 | goto unlink_mod; |
3266 | 3263 | ||