aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/module.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2010-03-10 04:56:10 -0500
committerTejun Heo <tj@kernel.org>2010-03-29 10:07:12 -0400
commit259354deaaf03d49a02dbb9975d6ec2a54675672 (patch)
treea05fbdfecfa5c2924235ce2fb7618b3acdecaa16 /kernel/module.c
parentb72c40949b0f04728f2993a1434598d3bad094ea (diff)
module: encapsulate percpu handling better and record percpu_size
Better encapsulate module static percpu area handling so that code outsidef of CONFIG_SMP ifdef doesn't deal with mod->percpu directly and add mod->percpu_size and record percpu_size in it. Both percpu fields are compiled out on UP. While at it, mark mod->percpu w/ __percpu. This is to prepare for is_module_percpu_address(). Signed-off-by: Tejun Heo <tj@kernel.org> Acked-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'kernel/module.c')
-rw-r--r--kernel/module.c66
1 files changed, 35 insertions, 31 deletions
diff --git a/kernel/module.c b/kernel/module.c
index c968d3606dca..e7a6e53fc73e 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -370,27 +370,33 @@ EXPORT_SYMBOL_GPL(find_module);
370 370
371#ifdef CONFIG_SMP 371#ifdef CONFIG_SMP
372 372
373static void *percpu_modalloc(unsigned long size, unsigned long align, 373static inline void __percpu *mod_percpu(struct module *mod)
374 const char *name)
375{ 374{
376 void *ptr; 375 return mod->percpu;
376}
377 377
378static int percpu_modalloc(struct module *mod,
379 unsigned long size, unsigned long align)
380{
378 if (align > PAGE_SIZE) { 381 if (align > PAGE_SIZE) {
379 printk(KERN_WARNING "%s: per-cpu alignment %li > %li\n", 382 printk(KERN_WARNING "%s: per-cpu alignment %li > %li\n",
380 name, align, PAGE_SIZE); 383 mod->name, align, PAGE_SIZE);
381 align = PAGE_SIZE; 384 align = PAGE_SIZE;
382 } 385 }
383 386
384 ptr = __alloc_reserved_percpu(size, align); 387 mod->percpu = __alloc_reserved_percpu(size, align);
385 if (!ptr) 388 if (!mod->percpu) {
386 printk(KERN_WARNING 389 printk(KERN_WARNING
387 "Could not allocate %lu bytes percpu data\n", size); 390 "Could not allocate %lu bytes percpu data\n", size);
388 return ptr; 391 return -ENOMEM;
392 }
393 mod->percpu_size = size;
394 return 0;
389} 395}
390 396
391static void percpu_modfree(void *freeme) 397static void percpu_modfree(struct module *mod)
392{ 398{
393 free_percpu(freeme); 399 free_percpu(mod->percpu);
394} 400}
395 401
396static unsigned int find_pcpusec(Elf_Ehdr *hdr, 402static unsigned int find_pcpusec(Elf_Ehdr *hdr,
@@ -400,24 +406,28 @@ static unsigned int find_pcpusec(Elf_Ehdr *hdr,
400 return find_sec(hdr, sechdrs, secstrings, ".data.percpu"); 406 return find_sec(hdr, sechdrs, secstrings, ".data.percpu");
401} 407}
402 408
403static void percpu_modcopy(void *pcpudest, const void *from, unsigned long size) 409static void percpu_modcopy(struct module *mod,
410 const void *from, unsigned long size)
404{ 411{
405 int cpu; 412 int cpu;
406 413
407 for_each_possible_cpu(cpu) 414 for_each_possible_cpu(cpu)
408 memcpy(pcpudest + per_cpu_offset(cpu), from, size); 415 memcpy(per_cpu_ptr(mod->percpu, cpu), from, size);
409} 416}
410 417
411#else /* ... !CONFIG_SMP */ 418#else /* ... !CONFIG_SMP */
412 419
413static inline void *percpu_modalloc(unsigned long size, unsigned long align, 420static inline void __percpu *mod_percpu(struct module *mod)
414 const char *name)
415{ 421{
416 return NULL; 422 return NULL;
417} 423}
418static inline void percpu_modfree(void *pcpuptr) 424static inline int percpu_modalloc(struct module *mod,
425 unsigned long size, unsigned long align)
426{
427 return -ENOMEM;
428}
429static inline void percpu_modfree(struct module *mod)
419{ 430{
420 BUG();
421} 431}
422static inline unsigned int find_pcpusec(Elf_Ehdr *hdr, 432static inline unsigned int find_pcpusec(Elf_Ehdr *hdr,
423 Elf_Shdr *sechdrs, 433 Elf_Shdr *sechdrs,
@@ -425,8 +435,8 @@ static inline unsigned int find_pcpusec(Elf_Ehdr *hdr,
425{ 435{
426 return 0; 436 return 0;
427} 437}
428static inline void percpu_modcopy(void *pcpudst, const void *src, 438static inline void percpu_modcopy(struct module *mod,
429 unsigned long size) 439 const void *from, unsigned long size)
430{ 440{
431 /* pcpusec should be 0, and size of that section should be 0. */ 441 /* pcpusec should be 0, and size of that section should be 0. */
432 BUG_ON(size != 0); 442 BUG_ON(size != 0);
@@ -1400,8 +1410,7 @@ static void free_module(struct module *mod)
1400 /* This may be NULL, but that's OK */ 1410 /* This may be NULL, but that's OK */
1401 module_free(mod, mod->module_init); 1411 module_free(mod, mod->module_init);
1402 kfree(mod->args); 1412 kfree(mod->args);
1403 if (mod->percpu) 1413 percpu_modfree(mod);
1404 percpu_modfree(mod->percpu);
1405#if defined(CONFIG_MODULE_UNLOAD) 1414#if defined(CONFIG_MODULE_UNLOAD)
1406 if (mod->refptr) 1415 if (mod->refptr)
1407 free_percpu(mod->refptr); 1416 free_percpu(mod->refptr);
@@ -1520,7 +1529,7 @@ static int simplify_symbols(Elf_Shdr *sechdrs,
1520 default: 1529 default:
1521 /* Divert to percpu allocation if a percpu var. */ 1530 /* Divert to percpu allocation if a percpu var. */
1522 if (sym[i].st_shndx == pcpuindex) 1531 if (sym[i].st_shndx == pcpuindex)
1523 secbase = (unsigned long)mod->percpu; 1532 secbase = (unsigned long)mod_percpu(mod);
1524 else 1533 else
1525 secbase = sechdrs[sym[i].st_shndx].sh_addr; 1534 secbase = sechdrs[sym[i].st_shndx].sh_addr;
1526 sym[i].st_value += secbase; 1535 sym[i].st_value += secbase;
@@ -1954,7 +1963,7 @@ static noinline struct module *load_module(void __user *umod,
1954 unsigned int modindex, versindex, infoindex, pcpuindex; 1963 unsigned int modindex, versindex, infoindex, pcpuindex;
1955 struct module *mod; 1964 struct module *mod;
1956 long err = 0; 1965 long err = 0;
1957 void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */ 1966 void *ptr = NULL; /* Stops spurious gcc warning */
1958 unsigned long symoffs, stroffs, *strmap; 1967 unsigned long symoffs, stroffs, *strmap;
1959 1968
1960 mm_segment_t old_fs; 1969 mm_segment_t old_fs;
@@ -2094,15 +2103,11 @@ static noinline struct module *load_module(void __user *umod,
2094 2103
2095 if (pcpuindex) { 2104 if (pcpuindex) {
2096 /* We have a special allocation for this section. */ 2105 /* We have a special allocation for this section. */
2097 percpu = percpu_modalloc(sechdrs[pcpuindex].sh_size, 2106 err = percpu_modalloc(mod, sechdrs[pcpuindex].sh_size,
2098 sechdrs[pcpuindex].sh_addralign, 2107 sechdrs[pcpuindex].sh_addralign);
2099 mod->name); 2108 if (err)
2100 if (!percpu) {
2101 err = -ENOMEM;
2102 goto free_mod; 2109 goto free_mod;
2103 }
2104 sechdrs[pcpuindex].sh_flags &= ~(unsigned long)SHF_ALLOC; 2110 sechdrs[pcpuindex].sh_flags &= ~(unsigned long)SHF_ALLOC;
2105 mod->percpu = percpu;
2106 } 2111 }
2107 2112
2108 /* Determine total sizes, and put offsets in sh_entsize. For now 2113 /* Determine total sizes, and put offsets in sh_entsize. For now
@@ -2317,7 +2322,7 @@ static noinline struct module *load_module(void __user *umod,
2317 sort_extable(mod->extable, mod->extable + mod->num_exentries); 2322 sort_extable(mod->extable, mod->extable + mod->num_exentries);
2318 2323
2319 /* Finally, copy percpu area over. */ 2324 /* Finally, copy percpu area over. */
2320 percpu_modcopy(mod->percpu, (void *)sechdrs[pcpuindex].sh_addr, 2325 percpu_modcopy(mod, (void *)sechdrs[pcpuindex].sh_addr,
2321 sechdrs[pcpuindex].sh_size); 2326 sechdrs[pcpuindex].sh_size);
2322 2327
2323 add_kallsyms(mod, sechdrs, hdr->e_shnum, symindex, strindex, 2328 add_kallsyms(mod, sechdrs, hdr->e_shnum, symindex, strindex,
@@ -2409,8 +2414,7 @@ static noinline struct module *load_module(void __user *umod,
2409 module_free(mod, mod->module_core); 2414 module_free(mod, mod->module_core);
2410 /* mod will be freed with core. Don't access it beyond this line! */ 2415 /* mod will be freed with core. Don't access it beyond this line! */
2411 free_percpu: 2416 free_percpu:
2412 if (percpu) 2417 percpu_modfree(mod);
2413 percpu_modfree(percpu);
2414 free_mod: 2418 free_mod:
2415 kfree(args); 2419 kfree(args);
2416 kfree(strmap); 2420 kfree(strmap);