Commit 81336333 authored by Linus Torvalds's avatar Linus Torvalds

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()
parents 5f129721 9eb76d77
...@@ -4,9 +4,13 @@ Description: ...@@ -4,9 +4,13 @@ Description:
/sys/module/MODULENAME /sys/module/MODULENAME
The name of the module that is in the kernel. This The name of the module that is in the kernel. This
module name will show up either if the module is built module name will always show up if the module is loaded as a
directly into the kernel, or if it is loaded as a dynamic module. If it is built directly into the kernel, it
dynamic module. will only show up if it has a version or at least one
parameter.
Note: The conditions of creation in the built-in case are not
by design and may be removed in the future.
/sys/module/MODULENAME/parameters /sys/module/MODULENAME/parameters
This directory contains individual files that are each This directory contains individual files that are each
......
...@@ -439,7 +439,7 @@ extern struct kernel_param_ops param_ops_string; ...@@ -439,7 +439,7 @@ extern struct kernel_param_ops param_ops_string;
extern int param_set_copystring(const char *val, const struct kernel_param *); extern int param_set_copystring(const char *val, const struct kernel_param *);
extern int param_get_string(char *buffer, const struct kernel_param *kp); extern int param_get_string(char *buffer, const struct kernel_param *kp);
/* for exporting parameters in /sys/parameters */ /* for exporting parameters in /sys/module/.../parameters */
struct module; struct module;
......
...@@ -455,7 +455,7 @@ const struct kernel_symbol *find_symbol(const char *name, ...@@ -455,7 +455,7 @@ const struct kernel_symbol *find_symbol(const char *name,
EXPORT_SYMBOL_GPL(find_symbol); EXPORT_SYMBOL_GPL(find_symbol);
/* Search for module by name: must hold module_mutex. */ /* Search for module by name: must hold module_mutex. */
static struct module *find_module_all(const char *name, static struct module *find_module_all(const char *name, size_t len,
bool even_unformed) bool even_unformed)
{ {
struct module *mod; struct module *mod;
...@@ -463,7 +463,7 @@ static struct module *find_module_all(const char *name, ...@@ -463,7 +463,7 @@ static struct module *find_module_all(const char *name,
list_for_each_entry(mod, &modules, list) { list_for_each_entry(mod, &modules, list) {
if (!even_unformed && mod->state == MODULE_STATE_UNFORMED) if (!even_unformed && mod->state == MODULE_STATE_UNFORMED)
continue; continue;
if (strcmp(mod->name, name) == 0) if (strlen(mod->name) == len && !memcmp(mod->name, name, len))
return mod; return mod;
} }
return NULL; return NULL;
...@@ -471,7 +471,7 @@ static struct module *find_module_all(const char *name, ...@@ -471,7 +471,7 @@ static struct module *find_module_all(const char *name,
struct module *find_module(const char *name) struct module *find_module(const char *name)
{ {
return find_module_all(name, false); return find_module_all(name, strlen(name), false);
} }
EXPORT_SYMBOL_GPL(find_module); EXPORT_SYMBOL_GPL(find_module);
...@@ -482,23 +482,28 @@ static inline void __percpu *mod_percpu(struct module *mod) ...@@ -482,23 +482,28 @@ static inline void __percpu *mod_percpu(struct module *mod)
return mod->percpu; return mod->percpu;
} }
static int percpu_modalloc(struct module *mod, static int percpu_modalloc(struct module *mod, struct load_info *info)
unsigned long size, unsigned long align)
{ {
Elf_Shdr *pcpusec = &info->sechdrs[info->index.pcpu];
unsigned long align = pcpusec->sh_addralign;
if (!pcpusec->sh_size)
return 0;
if (align > PAGE_SIZE) { if (align > PAGE_SIZE) {
printk(KERN_WARNING "%s: per-cpu alignment %li > %li\n", printk(KERN_WARNING "%s: per-cpu alignment %li > %li\n",
mod->name, align, PAGE_SIZE); mod->name, align, PAGE_SIZE);
align = PAGE_SIZE; align = PAGE_SIZE;
} }
mod->percpu = __alloc_reserved_percpu(size, align); mod->percpu = __alloc_reserved_percpu(pcpusec->sh_size, align);
if (!mod->percpu) { if (!mod->percpu) {
printk(KERN_WARNING printk(KERN_WARNING
"%s: Could not allocate %lu bytes percpu data\n", "%s: Could not allocate %lu bytes percpu data\n",
mod->name, size); mod->name, (unsigned long)pcpusec->sh_size);
return -ENOMEM; return -ENOMEM;
} }
mod->percpu_size = size; mod->percpu_size = pcpusec->sh_size;
return 0; return 0;
} }
...@@ -563,10 +568,12 @@ static inline void __percpu *mod_percpu(struct module *mod) ...@@ -563,10 +568,12 @@ static inline void __percpu *mod_percpu(struct module *mod)
{ {
return NULL; return NULL;
} }
static inline int percpu_modalloc(struct module *mod, static int percpu_modalloc(struct module *mod, struct load_info *info)
unsigned long size, unsigned long align)
{ {
return -ENOMEM; /* UP modules shouldn't have this section: ENOMEM isn't quite right */
if (info->sechdrs[info->index.pcpu].sh_size != 0)
return -ENOMEM;
return 0;
} }
static inline void percpu_modfree(struct module *mod) static inline void percpu_modfree(struct module *mod)
{ {
...@@ -2927,7 +2934,6 @@ static struct module *layout_and_allocate(struct load_info *info, int flags) ...@@ -2927,7 +2934,6 @@ static struct module *layout_and_allocate(struct load_info *info, int flags)
{ {
/* Module within temporary copy. */ /* Module within temporary copy. */
struct module *mod; struct module *mod;
Elf_Shdr *pcpusec;
int err; int err;
mod = setup_load_info(info, flags); mod = setup_load_info(info, flags);
...@@ -2942,17 +2948,10 @@ static struct module *layout_and_allocate(struct load_info *info, int flags) ...@@ -2942,17 +2948,10 @@ static struct module *layout_and_allocate(struct load_info *info, int flags)
err = module_frob_arch_sections(info->hdr, info->sechdrs, err = module_frob_arch_sections(info->hdr, info->sechdrs,
info->secstrings, mod); info->secstrings, mod);
if (err < 0) if (err < 0)
goto out; return ERR_PTR(err);
pcpusec = &info->sechdrs[info->index.pcpu]; /* We will do a special allocation for per-cpu sections later. */
if (pcpusec->sh_size) { info->sechdrs[info->index.pcpu].sh_flags &= ~(unsigned long)SHF_ALLOC;
/* We have a special allocation for this section. */
err = percpu_modalloc(mod,
pcpusec->sh_size, pcpusec->sh_addralign);
if (err)
goto out;
pcpusec->sh_flags &= ~(unsigned long)SHF_ALLOC;
}
/* Determine total sizes, and put offsets in sh_entsize. For now /* Determine total sizes, and put offsets in sh_entsize. For now
this is done generically; there doesn't appear to be any 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,17 +2962,12 @@ static struct module *layout_and_allocate(struct load_info *info, int flags)
/* Allocate and move to the final place */ /* Allocate and move to the final place */
err = move_module(mod, info); err = move_module(mod, info);
if (err) if (err)
goto free_percpu; return ERR_PTR(err);
/* Module has been copied to its final place now: return it. */ /* Module has been copied to its final place now: return it. */
mod = (void *)info->sechdrs[info->index.mod].sh_addr; mod = (void *)info->sechdrs[info->index.mod].sh_addr;
kmemleak_load_module(mod, info); kmemleak_load_module(mod, info);
return mod; return mod;
free_percpu:
percpu_modfree(mod);
out:
return ERR_PTR(err);
} }
/* mod is no longer valid after this! */ /* mod is no longer valid after this! */
...@@ -3014,7 +3008,7 @@ static bool finished_loading(const char *name) ...@@ -3014,7 +3008,7 @@ static bool finished_loading(const char *name)
bool ret; bool ret;
mutex_lock(&module_mutex); mutex_lock(&module_mutex);
mod = find_module_all(name, true); mod = find_module_all(name, strlen(name), true);
ret = !mod || mod->state == MODULE_STATE_LIVE ret = !mod || mod->state == MODULE_STATE_LIVE
|| mod->state == MODULE_STATE_GOING; || mod->state == MODULE_STATE_GOING;
mutex_unlock(&module_mutex); mutex_unlock(&module_mutex);
...@@ -3152,7 +3146,8 @@ static int add_unformed_module(struct module *mod) ...@@ -3152,7 +3146,8 @@ static int add_unformed_module(struct module *mod)
again: again:
mutex_lock(&module_mutex); mutex_lock(&module_mutex);
if ((old = find_module_all(mod->name, true)) != NULL) { old = find_module_all(mod->name, strlen(mod->name), true);
if (old != NULL) {
if (old->state == MODULE_STATE_COMING if (old->state == MODULE_STATE_COMING
|| old->state == MODULE_STATE_UNFORMED) { || old->state == MODULE_STATE_UNFORMED) {
/* Wait in case it fails to load. */ /* Wait in case it fails to load. */
...@@ -3198,6 +3193,17 @@ static int complete_formation(struct module *mod, struct load_info *info) ...@@ -3198,6 +3193,17 @@ static int complete_formation(struct module *mod, struct load_info *info)
return err; return err;
} }
static int unknown_module_param_cb(char *param, char *val, const char *modname)
{
/* Check for magic 'dyndbg' arg */
int ret = ddebug_dyndbg_module_param_cb(param, val, modname);
if (ret != 0) {
printk(KERN_WARNING "%s: unknown parameter '%s' ignored\n",
modname, param);
}
return 0;
}
/* Allocate and load the module: note that size of section 0 is always /* Allocate and load the module: note that size of section 0 is always
zero, and we rely on this for optional sections. */ zero, and we rely on this for optional sections. */
static int load_module(struct load_info *info, const char __user *uargs, 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,6 +3243,11 @@ static int load_module(struct load_info *info, const char __user *uargs,
} }
#endif #endif
/* To avoid stressing percpu allocator, do this once we're unique. */
err = percpu_modalloc(mod, info);
if (err)
goto unlink_mod;
/* Now module is in final location, initialize linked lists, etc. */ /* Now module is in final location, initialize linked lists, etc. */
err = module_unload_init(mod); err = module_unload_init(mod);
if (err) if (err)
...@@ -3284,7 +3295,7 @@ static int load_module(struct load_info *info, const char __user *uargs, ...@@ -3284,7 +3295,7 @@ static int load_module(struct load_info *info, const char __user *uargs,
/* Module is ready to execute: parsing args may do that. */ /* Module is ready to execute: parsing args may do that. */
err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp,
-32768, 32767, &ddebug_dyndbg_module_param_cb); -32768, 32767, unknown_module_param_cb);
if (err < 0) if (err < 0)
goto bug_cleanup; goto bug_cleanup;
...@@ -3563,10 +3574,8 @@ unsigned long module_kallsyms_lookup_name(const char *name) ...@@ -3563,10 +3574,8 @@ unsigned long module_kallsyms_lookup_name(const char *name)
/* Don't lock: we're in enough trouble already. */ /* Don't lock: we're in enough trouble already. */
preempt_disable(); preempt_disable();
if ((colon = strchr(name, ':')) != NULL) { if ((colon = strchr(name, ':')) != NULL) {
*colon = '\0'; if ((mod = find_module_all(name, colon - name, false)) != NULL)
if ((mod = find_module(name)) != NULL)
ret = mod_find_symname(mod, colon+1); ret = mod_find_symname(mod, colon+1);
*colon = ':';
} else { } else {
list_for_each_entry_rcu(mod, &modules, list) { list_for_each_entry_rcu(mod, &modules, list) {
if (mod->state == MODULE_STATE_UNFORMED) if (mod->state == MODULE_STATE_UNFORMED)
......
...@@ -787,7 +787,7 @@ static void __init kernel_add_sysfs_param(const char *name, ...@@ -787,7 +787,7 @@ static void __init kernel_add_sysfs_param(const char *name,
} }
/* /*
* param_sysfs_builtin - add contents in /sys/parameters for built-in modules * param_sysfs_builtin - add sysfs parameters for built-in modules
* *
* Add module_parameters to sysfs for "modules" built into the kernel. * Add module_parameters to sysfs for "modules" built into the kernel.
* *
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment