diff options
Diffstat (limited to 'kernel/module.c')
| -rw-r--r-- | kernel/module.c | 32 | 
1 files changed, 18 insertions, 14 deletions
| diff --git a/kernel/module.c b/kernel/module.c index f82386bd9ee9..c968d3606dca 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -474,9 +474,10 @@ static void module_unload_init(struct module *mod)  	INIT_LIST_HEAD(&mod->modules_which_use_me);  	for_each_possible_cpu(cpu) -		local_set(__module_ref_addr(mod, cpu), 0); +		per_cpu_ptr(mod->refptr, cpu)->count = 0; +  	/* Hold reference count during initialization. */ -	local_set(__module_ref_addr(mod, raw_smp_processor_id()), 1); +	__this_cpu_write(mod->refptr->count, 1);  	/* Backwards compatibility macros put refcount during init. */  	mod->waiter = current;  } @@ -619,7 +620,7 @@ unsigned int module_refcount(struct module *mod)  	int cpu;  	for_each_possible_cpu(cpu) -		total += local_read(__module_ref_addr(mod, cpu)); +		total += per_cpu_ptr(mod->refptr, cpu)->count;  	return total;  }  EXPORT_SYMBOL(module_refcount); @@ -796,14 +797,15 @@ static struct module_attribute refcnt = {  void module_put(struct module *module)  {  	if (module) { -		unsigned int cpu = get_cpu(); -		local_dec(__module_ref_addr(module, cpu)); +		preempt_disable(); +		__this_cpu_dec(module->refptr->count); +  		trace_module_put(module, _RET_IP_, -				 local_read(__module_ref_addr(module, cpu))); +				 __this_cpu_read(module->refptr->count));  		/* Maybe they're waiting for us to drop reference? */  		if (unlikely(!module_is_live(module)))  			wake_up_process(module->waiter); -		put_cpu(); +		preempt_enable();  	}  }  EXPORT_SYMBOL(module_put); @@ -1083,6 +1085,7 @@ static void add_sect_attrs(struct module *mod, unsigned int nsect,  		if (sattr->name == NULL)  			goto out;  		sect_attrs->nsections++; +		sysfs_attr_init(&sattr->mattr.attr);  		sattr->mattr.show = module_sect_show;  		sattr->mattr.store = NULL;  		sattr->mattr.attr.name = sattr->name; @@ -1178,6 +1181,7 @@ static void add_notes_attrs(struct module *mod, unsigned int nsect,  		if (sect_empty(&sechdrs[i]))  			continue;  		if (sechdrs[i].sh_type == SHT_NOTE) { +			sysfs_bin_attr_init(nattr);  			nattr->attr.name = mod->sect_attrs->attrs[loaded].name;  			nattr->attr.mode = S_IRUGO;  			nattr->size = sechdrs[i].sh_size; @@ -1250,6 +1254,7 @@ int module_add_modinfo_attrs(struct module *mod)  		if (!attr->test ||  		    (attr->test && attr->test(mod))) {  			memcpy(temp_attr, attr, sizeof(*temp_attr)); +			sysfs_attr_init(&temp_attr->attr);  			error = sysfs_create_file(&mod->mkobj.kobj,&temp_attr->attr);  			++temp_attr;  		} @@ -1397,9 +1402,9 @@ static void free_module(struct module *mod)  	kfree(mod->args);  	if (mod->percpu)  		percpu_modfree(mod->percpu); -#if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) +#if defined(CONFIG_MODULE_UNLOAD)  	if (mod->refptr) -		percpu_modfree(mod->refptr); +		free_percpu(mod->refptr);  #endif  	/* Free lock-classes: */  	lockdep_free_key_range(mod->module_core, mod->core_size); @@ -2162,9 +2167,8 @@ static noinline struct module *load_module(void __user *umod,  	mod = (void *)sechdrs[modindex].sh_addr;  	kmemleak_load_module(mod, hdr, sechdrs, secstrings); -#if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) -	mod->refptr = percpu_modalloc(sizeof(local_t), __alignof__(local_t), -				      mod->name); +#if defined(CONFIG_MODULE_UNLOAD) +	mod->refptr = alloc_percpu(struct module_ref);  	if (!mod->refptr) {  		err = -ENOMEM;  		goto free_init; @@ -2396,8 +2400,8 @@ static noinline struct module *load_module(void __user *umod,  	kobject_put(&mod->mkobj.kobj);   free_unload:  	module_unload_free(mod); -#if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) -	percpu_modfree(mod->refptr); +#if defined(CONFIG_MODULE_UNLOAD) +	free_percpu(mod->refptr);   free_init:  #endif  	module_free(mod, mod->module_init); | 
