aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/params.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/params.c')
-rw-r--r--kernel/params.c50
1 files changed, 31 insertions, 19 deletions
diff --git a/kernel/params.c b/kernel/params.c
index a8b09f6c87dc..8890d0b8dffc 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -25,15 +25,20 @@
25#include <linux/slab.h> 25#include <linux/slab.h>
26#include <linux/ctype.h> 26#include <linux/ctype.h>
27 27
28/* Protects all parameters, and incidentally kmalloced_param list. */ 28/* Protects all built-in parameters, modules use their own param_lock */
29static DEFINE_MUTEX(param_lock); 29static DEFINE_MUTEX(param_lock);
30 30
31/* Use the module's mutex, or if built-in use the built-in mutex */
32#define KPARAM_MUTEX(mod) ((mod) ? &(mod)->param_lock : &param_lock)
33#define KPARAM_IS_LOCKED(mod) mutex_is_locked(KPARAM_MUTEX(mod))
34
31/* This just allows us to keep track of which parameters are kmalloced. */ 35/* This just allows us to keep track of which parameters are kmalloced. */
32struct kmalloced_param { 36struct kmalloced_param {
33 struct list_head list; 37 struct list_head list;
34 char val[]; 38 char val[];
35}; 39};
36static LIST_HEAD(kmalloced_params); 40static LIST_HEAD(kmalloced_params);
41static DEFINE_SPINLOCK(kmalloced_params_lock);
37 42
38static void *kmalloc_parameter(unsigned int size) 43static void *kmalloc_parameter(unsigned int size)
39{ 44{
@@ -43,7 +48,10 @@ static void *kmalloc_parameter(unsigned int size)
43 if (!p) 48 if (!p)
44 return NULL; 49 return NULL;
45 50
51 spin_lock(&kmalloced_params_lock);
46 list_add(&p->list, &kmalloced_params); 52 list_add(&p->list, &kmalloced_params);
53 spin_unlock(&kmalloced_params_lock);
54
47 return p->val; 55 return p->val;
48} 56}
49 57
@@ -52,6 +60,7 @@ static void maybe_kfree_parameter(void *param)
52{ 60{
53 struct kmalloced_param *p; 61 struct kmalloced_param *p;
54 62
63 spin_lock(&kmalloced_params_lock);
55 list_for_each_entry(p, &kmalloced_params, list) { 64 list_for_each_entry(p, &kmalloced_params, list) {
56 if (p->val == param) { 65 if (p->val == param) {
57 list_del(&p->list); 66 list_del(&p->list);
@@ -59,6 +68,7 @@ static void maybe_kfree_parameter(void *param)
59 break; 68 break;
60 } 69 }
61 } 70 }
71 spin_unlock(&kmalloced_params_lock);
62} 72}
63 73
64static char dash2underscore(char c) 74static char dash2underscore(char c)
@@ -118,10 +128,10 @@ static int parse_one(char *param,
118 return -EINVAL; 128 return -EINVAL;
119 pr_debug("handling %s with %p\n", param, 129 pr_debug("handling %s with %p\n", param,
120 params[i].ops->set); 130 params[i].ops->set);
121 mutex_lock(&param_lock); 131 kernel_param_lock(params[i].mod);
122 param_check_unsafe(&params[i]); 132 param_check_unsafe(&params[i]);
123 err = params[i].ops->set(val, &params[i]); 133 err = params[i].ops->set(val, &params[i]);
124 mutex_unlock(&param_lock); 134 kernel_param_unlock(params[i].mod);
125 return err; 135 return err;
126 } 136 }
127 } 137 }
@@ -417,7 +427,8 @@ const struct kernel_param_ops param_ops_bint = {
417EXPORT_SYMBOL(param_ops_bint); 427EXPORT_SYMBOL(param_ops_bint);
418 428
419/* We break the rule and mangle the string. */ 429/* We break the rule and mangle the string. */
420static int param_array(const char *name, 430static int param_array(struct module *mod,
431 const char *name,
421 const char *val, 432 const char *val,
422 unsigned int min, unsigned int max, 433 unsigned int min, unsigned int max,
423 void *elem, int elemsize, 434 void *elem, int elemsize,
@@ -448,7 +459,7 @@ static int param_array(const char *name,
448 /* nul-terminate and parse */ 459 /* nul-terminate and parse */
449 save = val[len]; 460 save = val[len];
450 ((char *)val)[len] = '\0'; 461 ((char *)val)[len] = '\0';
451 BUG_ON(!mutex_is_locked(&param_lock)); 462 BUG_ON(!KPARAM_IS_LOCKED(mod));
452 ret = set(val, &kp); 463 ret = set(val, &kp);
453 464
454 if (ret != 0) 465 if (ret != 0)
@@ -470,7 +481,7 @@ static int param_array_set(const char *val, const struct kernel_param *kp)
470 const struct kparam_array *arr = kp->arr; 481 const struct kparam_array *arr = kp->arr;
471 unsigned int temp_num; 482 unsigned int temp_num;
472 483
473 return param_array(kp->name, val, 1, arr->max, arr->elem, 484 return param_array(kp->mod, kp->name, val, 1, arr->max, arr->elem,
474 arr->elemsize, arr->ops->set, kp->level, 485 arr->elemsize, arr->ops->set, kp->level,
475 arr->num ?: &temp_num); 486 arr->num ?: &temp_num);
476} 487}
@@ -485,7 +496,7 @@ static int param_array_get(char *buffer, const struct kernel_param *kp)
485 if (i) 496 if (i)
486 buffer[off++] = ','; 497 buffer[off++] = ',';
487 p.arg = arr->elem + arr->elemsize * i; 498 p.arg = arr->elem + arr->elemsize * i;
488 BUG_ON(!mutex_is_locked(&param_lock)); 499 BUG_ON(!KPARAM_IS_LOCKED(p.mod));
489 ret = arr->ops->get(buffer + off, &p); 500 ret = arr->ops->get(buffer + off, &p);
490 if (ret < 0) 501 if (ret < 0)
491 return ret; 502 return ret;
@@ -568,9 +579,9 @@ static ssize_t param_attr_show(struct module_attribute *mattr,
568 if (!attribute->param->ops->get) 579 if (!attribute->param->ops->get)
569 return -EPERM; 580 return -EPERM;
570 581
571 mutex_lock(&param_lock); 582 kernel_param_lock(mk->mod);
572 count = attribute->param->ops->get(buf, attribute->param); 583 count = attribute->param->ops->get(buf, attribute->param);
573 mutex_unlock(&param_lock); 584 kernel_param_unlock(mk->mod);
574 if (count > 0) { 585 if (count > 0) {
575 strcat(buf, "\n"); 586 strcat(buf, "\n");
576 ++count; 587 ++count;
@@ -580,7 +591,7 @@ static ssize_t param_attr_show(struct module_attribute *mattr,
580 591
581/* sysfs always hands a nul-terminated string in buf. We rely on that. */ 592/* sysfs always hands a nul-terminated string in buf. We rely on that. */
582static ssize_t param_attr_store(struct module_attribute *mattr, 593static ssize_t param_attr_store(struct module_attribute *mattr,
583 struct module_kobject *km, 594 struct module_kobject *mk,
584 const char *buf, size_t len) 595 const char *buf, size_t len)
585{ 596{
586 int err; 597 int err;
@@ -589,10 +600,10 @@ static ssize_t param_attr_store(struct module_attribute *mattr,
589 if (!attribute->param->ops->set) 600 if (!attribute->param->ops->set)
590 return -EPERM; 601 return -EPERM;
591 602
592 mutex_lock(&param_lock); 603 kernel_param_lock(mk->mod);
593 param_check_unsafe(attribute->param); 604 param_check_unsafe(attribute->param);
594 err = attribute->param->ops->set(buf, attribute->param); 605 err = attribute->param->ops->set(buf, attribute->param);
595 mutex_unlock(&param_lock); 606 kernel_param_unlock(mk->mod);
596 if (!err) 607 if (!err)
597 return len; 608 return len;
598 return err; 609 return err;
@@ -605,18 +616,19 @@ static ssize_t param_attr_store(struct module_attribute *mattr,
605#define __modinit __init 616#define __modinit __init
606#endif 617#endif
607 618
608#ifdef CONFIG_SYSFS 619void kernel_param_lock(struct module *mod)
609void __kernel_param_lock(void)
610{ 620{
611 mutex_lock(&param_lock); 621 mutex_lock(KPARAM_MUTEX(mod));
612} 622}
613EXPORT_SYMBOL(__kernel_param_lock);
614 623
615void __kernel_param_unlock(void) 624void kernel_param_unlock(struct module *mod)
616{ 625{
617 mutex_unlock(&param_lock); 626 mutex_unlock(KPARAM_MUTEX(mod));
618} 627}
619EXPORT_SYMBOL(__kernel_param_unlock); 628
629#ifdef CONFIG_SYSFS
630EXPORT_SYMBOL(kernel_param_lock);
631EXPORT_SYMBOL(kernel_param_unlock);
620 632
621/* 633/*
622 * add_sysfs_param - add a parameter to sysfs 634 * add_sysfs_param - add a parameter to sysfs