diff options
Diffstat (limited to 'kernel/module.c')
| -rw-r--r-- | kernel/module.c | 115 | 
1 files changed, 73 insertions, 42 deletions
diff --git a/kernel/module.c b/kernel/module.c index ba22484a987..f77ac320d0b 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -51,6 +51,7 @@  #include <linux/tracepoint.h>  #include <linux/ftrace.h>  #include <linux/async.h> +#include <linux/percpu.h>  #if 0  #define DEBUGP printk @@ -366,6 +367,34 @@ static struct module *find_module(const char *name)  }  #ifdef CONFIG_SMP + +#ifdef CONFIG_HAVE_DYNAMIC_PER_CPU_AREA + +static void *percpu_modalloc(unsigned long size, unsigned long align, +			     const char *name) +{ +	void *ptr; + +	if (align > PAGE_SIZE) { +		printk(KERN_WARNING "%s: per-cpu alignment %li > %li\n", +		       name, align, PAGE_SIZE); +		align = PAGE_SIZE; +	} + +	ptr = __alloc_reserved_percpu(size, align); +	if (!ptr) +		printk(KERN_WARNING +		       "Could not allocate %lu bytes percpu data\n", size); +	return ptr; +} + +static void percpu_modfree(void *freeme) +{ +	free_percpu(freeme); +} + +#else /* ... !CONFIG_HAVE_DYNAMIC_PER_CPU_AREA */ +  /* Number of blocks used and allocated. */  static unsigned int pcpu_num_used, pcpu_num_allocated;  /* Size of each block.  -ve means used. */ @@ -480,21 +509,6 @@ static void percpu_modfree(void *freeme)  	}  } -static unsigned int find_pcpusec(Elf_Ehdr *hdr, -				 Elf_Shdr *sechdrs, -				 const char *secstrings) -{ -	return find_sec(hdr, sechdrs, secstrings, ".data.percpu"); -} - -static void percpu_modcopy(void *pcpudest, const void *from, unsigned long size) -{ -	int cpu; - -	for_each_possible_cpu(cpu) -		memcpy(pcpudest + per_cpu_offset(cpu), from, size); -} -  static int percpu_modinit(void)  {  	pcpu_num_used = 2; @@ -513,7 +527,26 @@ static int percpu_modinit(void)  	return 0;  }  __initcall(percpu_modinit); + +#endif /* CONFIG_HAVE_DYNAMIC_PER_CPU_AREA */ + +static unsigned int find_pcpusec(Elf_Ehdr *hdr, +				 Elf_Shdr *sechdrs, +				 const char *secstrings) +{ +	return find_sec(hdr, sechdrs, secstrings, ".data.percpu"); +} + +static void percpu_modcopy(void *pcpudest, const void *from, unsigned long size) +{ +	int cpu; + +	for_each_possible_cpu(cpu) +		memcpy(pcpudest + per_cpu_offset(cpu), from, size); +} +  #else /* ... !CONFIG_SMP */ +  static inline void *percpu_modalloc(unsigned long size, unsigned long align,  				    const char *name)  { @@ -535,6 +568,7 @@ static inline void percpu_modcopy(void *pcpudst, const void *src,  	/* pcpusec should be 0, and size of that section should be 0. */  	BUG_ON(size != 0);  } +  #endif /* CONFIG_SMP */  #define MODINFO_ATTR(field)	\ @@ -822,7 +856,7 @@ SYSCALL_DEFINE2(delete_module, const char __user *, name_user,  	mutex_lock(&module_mutex);  	/* Store the name of the last unloaded module for diagnostic purposes */  	strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module)); -	unregister_dynamic_debug_module(mod->name); +	ddebug_remove_module(mod->name);  	free_module(mod);   out: @@ -1827,19 +1861,13 @@ static inline void add_kallsyms(struct module *mod,  }  #endif /* CONFIG_KALLSYMS */ -static void dynamic_printk_setup(struct mod_debug *debug, unsigned int num) +static void dynamic_debug_setup(struct _ddebug *debug, unsigned int num)  { -#ifdef CONFIG_DYNAMIC_PRINTK_DEBUG -	unsigned int i; - -	for (i = 0; i < num; i++) { -		register_dynamic_debug_module(debug[i].modname, -					      debug[i].type, -					      debug[i].logical_modname, -					      debug[i].flag_names, -					      debug[i].hash, debug[i].hash2); -	} -#endif /* CONFIG_DYNAMIC_PRINTK_DEBUG */ +#ifdef CONFIG_DYNAMIC_DEBUG +	if (ddebug_add_module(debug, num, debug->modname)) +		printk(KERN_ERR "dynamic debug error adding module: %s\n", +					debug->modname); +#endif  }  static void *module_alloc_update_bounds(unsigned long size) @@ -2015,14 +2043,6 @@ static noinline struct module *load_module(void __user *umod,  	if (err < 0)  		goto free_mod; -#if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) -	mod->refptr = percpu_modalloc(sizeof(local_t), __alignof__(local_t), -				      mod->name); -	if (!mod->refptr) { -		err = -ENOMEM; -		goto free_mod; -	} -#endif  	if (pcpuindex) {  		/* We have a special allocation for this section. */  		percpu = percpu_modalloc(sechdrs[pcpuindex].sh_size, @@ -2030,7 +2050,7 @@ static noinline struct module *load_module(void __user *umod,  					 mod->name);  		if (!percpu) {  			err = -ENOMEM; -			goto free_percpu; +			goto free_mod;  		}  		sechdrs[pcpuindex].sh_flags &= ~(unsigned long)SHF_ALLOC;  		mod->percpu = percpu; @@ -2082,6 +2102,14 @@ static noinline struct module *load_module(void __user *umod,  	/* Module has been moved. */  	mod = (void *)sechdrs[modindex].sh_addr; +#if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) +	mod->refptr = percpu_modalloc(sizeof(local_t), __alignof__(local_t), +				      mod->name); +	if (!mod->refptr) { +		err = -ENOMEM; +		goto free_init; +	} +#endif  	/* Now we've moved module, initialize linked lists, etc. */  	module_unload_init(mod); @@ -2213,12 +2241,13 @@ static noinline struct module *load_module(void __user *umod,  	add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);  	if (!mod->taints) { -		struct mod_debug *debug; +		struct _ddebug *debug;  		unsigned int num_debug;  		debug = section_objs(hdr, sechdrs, secstrings, "__verbose",  				     sizeof(*debug), &num_debug); -		dynamic_printk_setup(debug, num_debug); +		if (debug) +			dynamic_debug_setup(debug, num_debug);  	}  	/* sechdrs[0].sh_size is always zero */ @@ -2288,15 +2317,17 @@ static noinline struct module *load_module(void __user *umod,  	ftrace_release(mod->module_core, mod->core_size);   free_unload:  	module_unload_free(mod); + free_init: +#if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) +	percpu_modfree(mod->refptr); +#endif  	module_free(mod, mod->module_init);   free_core:  	module_free(mod, mod->module_core); +	/* mod will be freed with core. Don't access it beyond this line! */   free_percpu:  	if (percpu)  		percpu_modfree(percpu); -#if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) -	percpu_modfree(mod->refptr); -#endif   free_mod:  	kfree(args);   free_hdr:  |