diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-10 17:51:41 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-10 17:51:41 -0400 |
commit | 8133633368760656c76b8302dbd4bfa20f887df6 (patch) | |
tree | a779d8fab6dcff2db3dcbf3553097df79cb9dc54 | |
parent | 5f129721713e099a04c6024015f97faa58562ab1 (diff) | |
parent | 9eb76d7797b892a1dad4f2efb6f786681306dd13 (diff) |
Merge tag 'modules-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux
Pull module updates from Rusty Russell:
"Nothing interesting. Except the most embarrassing bugfix ever. But
let's ignore that"
* tag 'modules-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux:
module: cleanup call chain.
module: do percpu allocation after uniqueness check. No, really!
modules: don't fail to load on unknown parameters.
ABI: Clarify when /sys/module/MODULENAME is created
There is no /sys/parameters
module: don't modify argument of module_kallsyms_lookup_name()
-rw-r--r-- | Documentation/ABI/stable/sysfs-module | 10 | ||||
-rw-r--r-- | include/linux/moduleparam.h | 2 | ||||
-rw-r--r-- | kernel/module.c | 77 | ||||
-rw-r--r-- | kernel/params.c | 2 |
4 files changed, 52 insertions, 39 deletions
diff --git a/Documentation/ABI/stable/sysfs-module b/Documentation/ABI/stable/sysfs-module index a0dd21c6db59..6272ae5fb366 100644 --- a/Documentation/ABI/stable/sysfs-module +++ b/Documentation/ABI/stable/sysfs-module | |||
@@ -4,9 +4,13 @@ Description: | |||
4 | 4 | ||
5 | /sys/module/MODULENAME | 5 | /sys/module/MODULENAME |
6 | The name of the module that is in the kernel. This | 6 | The name of the module that is in the kernel. This |
7 | module name will show up either if the module is built | 7 | module name will always show up if the module is loaded as a |
8 | directly into the kernel, or if it is loaded as a | 8 | dynamic module. If it is built directly into the kernel, it |
9 | dynamic module. | 9 | will only show up if it has a version or at least one |
10 | parameter. | ||
11 | |||
12 | Note: The conditions of creation in the built-in case are not | ||
13 | by design and may be removed in the future. | ||
10 | 14 | ||
11 | /sys/module/MODULENAME/parameters | 15 | /sys/module/MODULENAME/parameters |
12 | This directory contains individual files that are each | 16 | This directory contains individual files that are each |
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h index 137b4198fc03..27d9da3f86ff 100644 --- a/include/linux/moduleparam.h +++ b/include/linux/moduleparam.h | |||
@@ -439,7 +439,7 @@ extern struct kernel_param_ops param_ops_string; | |||
439 | extern int param_set_copystring(const char *val, const struct kernel_param *); | 439 | extern int param_set_copystring(const char *val, const struct kernel_param *); |
440 | extern int param_get_string(char *buffer, const struct kernel_param *kp); | 440 | extern int param_get_string(char *buffer, const struct kernel_param *kp); |
441 | 441 | ||
442 | /* for exporting parameters in /sys/parameters */ | 442 | /* for exporting parameters in /sys/module/.../parameters */ |
443 | 443 | ||
444 | struct module; | 444 | struct module; |
445 | 445 | ||
diff --git a/kernel/module.c b/kernel/module.c index cab4bce49c23..206915830d29 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -455,7 +455,7 @@ const struct kernel_symbol *find_symbol(const char *name, | |||
455 | EXPORT_SYMBOL_GPL(find_symbol); | 455 | EXPORT_SYMBOL_GPL(find_symbol); |
456 | 456 | ||
457 | /* Search for module by name: must hold module_mutex. */ | 457 | /* Search for module by name: must hold module_mutex. */ |
458 | static struct module *find_module_all(const char *name, | 458 | static struct module *find_module_all(const char *name, size_t len, |
459 | bool even_unformed) | 459 | bool even_unformed) |
460 | { | 460 | { |
461 | struct module *mod; | 461 | struct module *mod; |
@@ -463,7 +463,7 @@ static struct module *find_module_all(const char *name, | |||
463 | list_for_each_entry(mod, &modules, list) { | 463 | list_for_each_entry(mod, &modules, list) { |
464 | if (!even_unformed && mod->state == MODULE_STATE_UNFORMED) | 464 | if (!even_unformed && mod->state == MODULE_STATE_UNFORMED) |
465 | continue; | 465 | continue; |
466 | if (strcmp(mod->name, name) == 0) | 466 | if (strlen(mod->name) == len && !memcmp(mod->name, name, len)) |
467 | return mod; | 467 | return mod; |
468 | } | 468 | } |
469 | return NULL; | 469 | return NULL; |
@@ -471,7 +471,7 @@ static struct module *find_module_all(const char *name, | |||
471 | 471 | ||
472 | struct module *find_module(const char *name) | 472 | struct module *find_module(const char *name) |
473 | { | 473 | { |
474 | return find_module_all(name, false); | 474 | return find_module_all(name, strlen(name), false); |
475 | } | 475 | } |
476 | EXPORT_SYMBOL_GPL(find_module); | 476 | EXPORT_SYMBOL_GPL(find_module); |
477 | 477 | ||
@@ -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 | { |
@@ -2927,7 +2934,6 @@ static struct module *layout_and_allocate(struct load_info *info, int flags) | |||
2927 | { | 2934 | { |
2928 | /* Module within temporary copy. */ | 2935 | /* Module within temporary copy. */ |
2929 | struct module *mod; | 2936 | struct module *mod; |
2930 | Elf_Shdr *pcpusec; | ||
2931 | int err; | 2937 | int err; |
2932 | 2938 | ||
2933 | mod = setup_load_info(info, flags); | 2939 | mod = setup_load_info(info, flags); |
@@ -2942,17 +2948,10 @@ static struct module *layout_and_allocate(struct load_info *info, int flags) | |||
2942 | err = module_frob_arch_sections(info->hdr, info->sechdrs, | 2948 | err = module_frob_arch_sections(info->hdr, info->sechdrs, |
2943 | info->secstrings, mod); | 2949 | info->secstrings, mod); |
2944 | if (err < 0) | 2950 | if (err < 0) |
2945 | goto out; | 2951 | return ERR_PTR(err); |
2946 | 2952 | ||
2947 | pcpusec = &info->sechdrs[info->index.pcpu]; | 2953 | /* We will do a special allocation for per-cpu sections later. */ |
2948 | if (pcpusec->sh_size) { | 2954 | info->sechdrs[info->index.pcpu].sh_flags &= ~(unsigned long)SHF_ALLOC; |
2949 | /* We have a special allocation for this section. */ | ||
2950 | err = percpu_modalloc(mod, | ||
2951 | pcpusec->sh_size, pcpusec->sh_addralign); | ||
2952 | if (err) | ||
2953 | goto out; | ||
2954 | pcpusec->sh_flags &= ~(unsigned long)SHF_ALLOC; | ||
2955 | } | ||
2956 | 2955 | ||
2957 | /* Determine total sizes, and put offsets in sh_entsize. For now | 2956 | /* Determine total sizes, and put offsets in sh_entsize. For now |
2958 | this is done generically; there doesn't appear to be any | 2957 | this is done generically; there doesn't appear to be any |
@@ -2963,17 +2962,12 @@ static struct module *layout_and_allocate(struct load_info *info, int flags) | |||
2963 | /* Allocate and move to the final place */ | 2962 | /* Allocate and move to the final place */ |
2964 | err = move_module(mod, info); | 2963 | err = move_module(mod, info); |
2965 | if (err) | 2964 | if (err) |
2966 | goto free_percpu; | 2965 | return ERR_PTR(err); |
2967 | 2966 | ||
2968 | /* Module has been copied to its final place now: return it. */ | 2967 | /* Module has been copied to its final place now: return it. */ |
2969 | mod = (void *)info->sechdrs[info->index.mod].sh_addr; | 2968 | mod = (void *)info->sechdrs[info->index.mod].sh_addr; |
2970 | kmemleak_load_module(mod, info); | 2969 | kmemleak_load_module(mod, info); |
2971 | return mod; | 2970 | return mod; |
2972 | |||
2973 | free_percpu: | ||
2974 | percpu_modfree(mod); | ||
2975 | out: | ||
2976 | return ERR_PTR(err); | ||
2977 | } | 2971 | } |
2978 | 2972 | ||
2979 | /* mod is no longer valid after this! */ | 2973 | /* mod is no longer valid after this! */ |
@@ -3014,7 +3008,7 @@ static bool finished_loading(const char *name) | |||
3014 | bool ret; | 3008 | bool ret; |
3015 | 3009 | ||
3016 | mutex_lock(&module_mutex); | 3010 | mutex_lock(&module_mutex); |
3017 | mod = find_module_all(name, true); | 3011 | mod = find_module_all(name, strlen(name), true); |
3018 | ret = !mod || mod->state == MODULE_STATE_LIVE | 3012 | ret = !mod || mod->state == MODULE_STATE_LIVE |
3019 | || mod->state == MODULE_STATE_GOING; | 3013 | || mod->state == MODULE_STATE_GOING; |
3020 | mutex_unlock(&module_mutex); | 3014 | mutex_unlock(&module_mutex); |
@@ -3152,7 +3146,8 @@ static int add_unformed_module(struct module *mod) | |||
3152 | 3146 | ||
3153 | again: | 3147 | again: |
3154 | mutex_lock(&module_mutex); | 3148 | mutex_lock(&module_mutex); |
3155 | if ((old = find_module_all(mod->name, true)) != NULL) { | 3149 | old = find_module_all(mod->name, strlen(mod->name), true); |
3150 | if (old != NULL) { | ||
3156 | if (old->state == MODULE_STATE_COMING | 3151 | if (old->state == MODULE_STATE_COMING |
3157 | || old->state == MODULE_STATE_UNFORMED) { | 3152 | || old->state == MODULE_STATE_UNFORMED) { |
3158 | /* Wait in case it fails to load. */ | 3153 | /* Wait in case it fails to load. */ |
@@ -3198,6 +3193,17 @@ out: | |||
3198 | return err; | 3193 | return err; |
3199 | } | 3194 | } |
3200 | 3195 | ||
3196 | static int unknown_module_param_cb(char *param, char *val, const char *modname) | ||
3197 | { | ||
3198 | /* Check for magic 'dyndbg' arg */ | ||
3199 | int ret = ddebug_dyndbg_module_param_cb(param, val, modname); | ||
3200 | if (ret != 0) { | ||
3201 | printk(KERN_WARNING "%s: unknown parameter '%s' ignored\n", | ||
3202 | modname, param); | ||
3203 | } | ||
3204 | return 0; | ||
3205 | } | ||
3206 | |||
3201 | /* Allocate and load the module: note that size of section 0 is always | 3207 | /* Allocate and load the module: note that size of section 0 is always |
3202 | zero, and we rely on this for optional sections. */ | 3208 | zero, and we rely on this for optional sections. */ |
3203 | static int load_module(struct load_info *info, const char __user *uargs, | 3209 | static int load_module(struct load_info *info, const char __user *uargs, |
@@ -3237,6 +3243,11 @@ static int load_module(struct load_info *info, const char __user *uargs, | |||
3237 | } | 3243 | } |
3238 | #endif | 3244 | #endif |
3239 | 3245 | ||
3246 | /* To avoid stressing percpu allocator, do this once we're unique. */ | ||
3247 | err = percpu_modalloc(mod, info); | ||
3248 | if (err) | ||
3249 | goto unlink_mod; | ||
3250 | |||
3240 | /* Now module is in final location, initialize linked lists, etc. */ | 3251 | /* Now module is in final location, initialize linked lists, etc. */ |
3241 | err = module_unload_init(mod); | 3252 | err = module_unload_init(mod); |
3242 | if (err) | 3253 | if (err) |
@@ -3284,7 +3295,7 @@ static int load_module(struct load_info *info, const char __user *uargs, | |||
3284 | 3295 | ||
3285 | /* Module is ready to execute: parsing args may do that. */ | 3296 | /* Module is ready to execute: parsing args may do that. */ |
3286 | err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, | 3297 | err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, |
3287 | -32768, 32767, &ddebug_dyndbg_module_param_cb); | 3298 | -32768, 32767, unknown_module_param_cb); |
3288 | if (err < 0) | 3299 | if (err < 0) |
3289 | goto bug_cleanup; | 3300 | goto bug_cleanup; |
3290 | 3301 | ||
@@ -3563,10 +3574,8 @@ unsigned long module_kallsyms_lookup_name(const char *name) | |||
3563 | /* Don't lock: we're in enough trouble already. */ | 3574 | /* Don't lock: we're in enough trouble already. */ |
3564 | preempt_disable(); | 3575 | preempt_disable(); |
3565 | if ((colon = strchr(name, ':')) != NULL) { | 3576 | if ((colon = strchr(name, ':')) != NULL) { |
3566 | *colon = '\0'; | 3577 | if ((mod = find_module_all(name, colon - name, false)) != NULL) |
3567 | if ((mod = find_module(name)) != NULL) | ||
3568 | ret = mod_find_symname(mod, colon+1); | 3578 | ret = mod_find_symname(mod, colon+1); |
3569 | *colon = ':'; | ||
3570 | } else { | 3579 | } else { |
3571 | list_for_each_entry_rcu(mod, &modules, list) { | 3580 | list_for_each_entry_rcu(mod, &modules, list) { |
3572 | if (mod->state == MODULE_STATE_UNFORMED) | 3581 | if (mod->state == MODULE_STATE_UNFORMED) |
diff --git a/kernel/params.c b/kernel/params.c index 53b958fcd639..440e65d1a544 100644 --- a/kernel/params.c +++ b/kernel/params.c | |||
@@ -787,7 +787,7 @@ static void __init kernel_add_sysfs_param(const char *name, | |||
787 | } | 787 | } |
788 | 788 | ||
789 | /* | 789 | /* |
790 | * param_sysfs_builtin - add contents in /sys/parameters for built-in modules | 790 | * param_sysfs_builtin - add sysfs parameters for built-in modules |
791 | * | 791 | * |
792 | * Add module_parameters to sysfs for "modules" built into the kernel. | 792 | * Add module_parameters to sysfs for "modules" built into the kernel. |
793 | * | 793 | * |