aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/module.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/module.c')
-rw-r--r--kernel/module.c34
1 files changed, 18 insertions, 16 deletions
diff --git a/kernel/module.c b/kernel/module.c
index cab4bce49c23..fa53db8aadeb 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2927,7 +2927,6 @@ static struct module *layout_and_allocate(struct load_info *info, int flags)
2927{ 2927{
2928 /* Module within temporary copy. */ 2928 /* Module within temporary copy. */
2929 struct module *mod; 2929 struct module *mod;
2930 Elf_Shdr *pcpusec;
2931 int err; 2930 int err;
2932 2931
2933 mod = setup_load_info(info, flags); 2932 mod = setup_load_info(info, flags);
@@ -2942,17 +2941,10 @@ static struct module *layout_and_allocate(struct load_info *info, int flags)
2942 err = module_frob_arch_sections(info->hdr, info->sechdrs, 2941 err = module_frob_arch_sections(info->hdr, info->sechdrs,
2943 info->secstrings, mod); 2942 info->secstrings, mod);
2944 if (err < 0) 2943 if (err < 0)
2945 goto out; 2944 return ERR_PTR(err);
2946 2945
2947 pcpusec = &info->sechdrs[info->index.pcpu]; 2946 /* We will do a special allocation for per-cpu sections later. */
2948 if (pcpusec->sh_size) { 2947 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 2948
2957 /* Determine total sizes, and put offsets in sh_entsize. For now 2949 /* Determine total sizes, and put offsets in sh_entsize. For now
2958 this is done generically; there doesn't appear to be any 2950 this is done generically; there doesn't appear to be any
@@ -2963,17 +2955,22 @@ static struct module *layout_and_allocate(struct load_info *info, int flags)
2963 /* Allocate and move to the final place */ 2955 /* Allocate and move to the final place */
2964 err = move_module(mod, info); 2956 err = move_module(mod, info);
2965 if (err) 2957 if (err)
2966 goto free_percpu; 2958 return ERR_PTR(err);
2967 2959
2968 /* Module has been copied to its final place now: return it. */ 2960 /* Module has been copied to its final place now: return it. */
2969 mod = (void *)info->sechdrs[info->index.mod].sh_addr; 2961 mod = (void *)info->sechdrs[info->index.mod].sh_addr;
2970 kmemleak_load_module(mod, info); 2962 kmemleak_load_module(mod, info);
2971 return mod; 2963 return mod;
2964}
2972 2965
2973free_percpu: 2966static int alloc_module_percpu(struct module *mod, struct load_info *info)
2974 percpu_modfree(mod); 2967{
2975out: 2968 Elf_Shdr *pcpusec = &info->sechdrs[info->index.pcpu];
2976 return ERR_PTR(err); 2969 if (!pcpusec->sh_size)
2970 return 0;
2971
2972 /* We have a special allocation for this section. */
2973 return percpu_modalloc(mod, pcpusec->sh_size, pcpusec->sh_addralign);
2977} 2974}
2978 2975
2979/* mod is no longer valid after this! */ 2976/* mod is no longer valid after this! */
@@ -3237,6 +3234,11 @@ static int load_module(struct load_info *info, const char __user *uargs,
3237 } 3234 }
3238#endif 3235#endif
3239 3236
3237 /* To avoid stressing percpu allocator, do this once we're unique. */
3238 err = alloc_module_percpu(mod, info);
3239 if (err)
3240 goto unlink_mod;
3241
3240 /* Now module is in final location, initialize linked lists, etc. */ 3242 /* Now module is in final location, initialize linked lists, etc. */
3241 err = module_unload_init(mod); 3243 err = module_unload_init(mod);
3242 if (err) 3244 if (err)