diff options
Diffstat (limited to 'kernel/params.c')
| -rw-r--r-- | kernel/params.c | 33 |
1 files changed, 26 insertions, 7 deletions
diff --git a/kernel/params.c b/kernel/params.c index a3eeeefc9472..08107d181758 100644 --- a/kernel/params.c +++ b/kernel/params.c | |||
| @@ -31,12 +31,14 @@ | |||
| 31 | #define DEBUGP(fmt, a...) | 31 | #define DEBUGP(fmt, a...) |
| 32 | #endif | 32 | #endif |
| 33 | 33 | ||
| 34 | /* Protects all parameters, and incidentally kmalloced_param list. */ | ||
| 35 | static DEFINE_MUTEX(param_lock); | ||
| 36 | |||
| 34 | /* This just allows us to keep track of which parameters are kmalloced. */ | 37 | /* This just allows us to keep track of which parameters are kmalloced. */ |
| 35 | struct kmalloced_param { | 38 | struct kmalloced_param { |
| 36 | struct list_head list; | 39 | struct list_head list; |
| 37 | char val[]; | 40 | char val[]; |
| 38 | }; | 41 | }; |
| 39 | static DEFINE_MUTEX(param_lock); | ||
| 40 | static LIST_HEAD(kmalloced_params); | 42 | static LIST_HEAD(kmalloced_params); |
| 41 | 43 | ||
| 42 | static void *kmalloc_parameter(unsigned int size) | 44 | static void *kmalloc_parameter(unsigned int size) |
| @@ -47,10 +49,7 @@ static void *kmalloc_parameter(unsigned int size) | |||
| 47 | if (!p) | 49 | if (!p) |
| 48 | return NULL; | 50 | return NULL; |
| 49 | 51 | ||
| 50 | mutex_lock(¶m_lock); | ||
| 51 | list_add(&p->list, &kmalloced_params); | 52 | list_add(&p->list, &kmalloced_params); |
| 52 | mutex_unlock(¶m_lock); | ||
| 53 | |||
| 54 | return p->val; | 53 | return p->val; |
| 55 | } | 54 | } |
| 56 | 55 | ||
| @@ -59,7 +58,6 @@ static void maybe_kfree_parameter(void *param) | |||
| 59 | { | 58 | { |
| 60 | struct kmalloced_param *p; | 59 | struct kmalloced_param *p; |
| 61 | 60 | ||
| 62 | mutex_lock(¶m_lock); | ||
| 63 | list_for_each_entry(p, &kmalloced_params, list) { | 61 | list_for_each_entry(p, &kmalloced_params, list) { |
| 64 | if (p->val == param) { | 62 | if (p->val == param) { |
| 65 | list_del(&p->list); | 63 | list_del(&p->list); |
| @@ -67,7 +65,6 @@ static void maybe_kfree_parameter(void *param) | |||
| 67 | break; | 65 | break; |
| 68 | } | 66 | } |
| 69 | } | 67 | } |
| 70 | mutex_unlock(¶m_lock); | ||
| 71 | } | 68 | } |
| 72 | 69 | ||
| 73 | static inline char dash2underscore(char c) | 70 | static inline char dash2underscore(char c) |
| @@ -93,6 +90,7 @@ static int parse_one(char *param, | |||
| 93 | int (*handle_unknown)(char *param, char *val)) | 90 | int (*handle_unknown)(char *param, char *val)) |
| 94 | { | 91 | { |
| 95 | unsigned int i; | 92 | unsigned int i; |
| 93 | int err; | ||
| 96 | 94 | ||
| 97 | /* Find parameter */ | 95 | /* Find parameter */ |
| 98 | for (i = 0; i < num_params; i++) { | 96 | for (i = 0; i < num_params; i++) { |
| @@ -102,7 +100,10 @@ static int parse_one(char *param, | |||
| 102 | return -EINVAL; | 100 | return -EINVAL; |
| 103 | DEBUGP("They are equal! Calling %p\n", | 101 | DEBUGP("They are equal! Calling %p\n", |
| 104 | params[i].ops->set); | 102 | params[i].ops->set); |
| 105 | return params[i].ops->set(val, ¶ms[i]); | 103 | mutex_lock(¶m_lock); |
| 104 | err = params[i].ops->set(val, ¶ms[i]); | ||
| 105 | mutex_unlock(¶m_lock); | ||
| 106 | return err; | ||
| 106 | } | 107 | } |
| 107 | } | 108 | } |
| 108 | 109 | ||
| @@ -400,6 +401,7 @@ static int param_array(const char *name, | |||
| 400 | /* nul-terminate and parse */ | 401 | /* nul-terminate and parse */ |
| 401 | save = val[len]; | 402 | save = val[len]; |
| 402 | ((char *)val)[len] = '\0'; | 403 | ((char *)val)[len] = '\0'; |
| 404 | BUG_ON(!mutex_is_locked(¶m_lock)); | ||
| 403 | ret = set(val, &kp); | 405 | ret = set(val, &kp); |
| 404 | 406 | ||
| 405 | if (ret != 0) | 407 | if (ret != 0) |
| @@ -438,6 +440,7 @@ static int param_array_get(char *buffer, const struct kernel_param *kp) | |||
| 438 | if (i) | 440 | if (i) |
| 439 | buffer[off++] = ','; | 441 | buffer[off++] = ','; |
| 440 | p.arg = arr->elem + arr->elemsize * i; | 442 | p.arg = arr->elem + arr->elemsize * i; |
| 443 | BUG_ON(!mutex_is_locked(¶m_lock)); | ||
| 441 | ret = arr->ops->get(buffer + off, &p); | 444 | ret = arr->ops->get(buffer + off, &p); |
| 442 | if (ret < 0) | 445 | if (ret < 0) |
| 443 | return ret; | 446 | return ret; |
| @@ -522,7 +525,9 @@ static ssize_t param_attr_show(struct module_attribute *mattr, | |||
| 522 | if (!attribute->param->ops->get) | 525 | if (!attribute->param->ops->get) |
| 523 | return -EPERM; | 526 | return -EPERM; |
| 524 | 527 | ||
| 528 | mutex_lock(¶m_lock); | ||
| 525 | count = attribute->param->ops->get(buf, attribute->param); | 529 | count = attribute->param->ops->get(buf, attribute->param); |
| 530 | mutex_unlock(¶m_lock); | ||
| 526 | if (count > 0) { | 531 | if (count > 0) { |
| 527 | strcat(buf, "\n"); | 532 | strcat(buf, "\n"); |
| 528 | ++count; | 533 | ++count; |
| @@ -541,7 +546,9 @@ static ssize_t param_attr_store(struct module_attribute *mattr, | |||
| 541 | if (!attribute->param->ops->set) | 546 | if (!attribute->param->ops->set) |
| 542 | return -EPERM; | 547 | return -EPERM; |
| 543 | 548 | ||
| 549 | mutex_lock(¶m_lock); | ||
| 544 | err = attribute->param->ops->set(buf, attribute->param); | 550 | err = attribute->param->ops->set(buf, attribute->param); |
| 551 | mutex_unlock(¶m_lock); | ||
| 545 | if (!err) | 552 | if (!err) |
| 546 | return len; | 553 | return len; |
| 547 | return err; | 554 | return err; |
| @@ -555,6 +562,18 @@ static ssize_t param_attr_store(struct module_attribute *mattr, | |||
| 555 | #endif | 562 | #endif |
| 556 | 563 | ||
| 557 | #ifdef CONFIG_SYSFS | 564 | #ifdef CONFIG_SYSFS |
| 565 | void __kernel_param_lock(void) | ||
| 566 | { | ||
| 567 | mutex_lock(¶m_lock); | ||
| 568 | } | ||
| 569 | EXPORT_SYMBOL(__kernel_param_lock); | ||
| 570 | |||
| 571 | void __kernel_param_unlock(void) | ||
| 572 | { | ||
| 573 | mutex_unlock(¶m_lock); | ||
| 574 | } | ||
| 575 | EXPORT_SYMBOL(__kernel_param_unlock); | ||
| 576 | |||
| 558 | /* | 577 | /* |
| 559 | * add_sysfs_param - add a parameter to sysfs | 578 | * add_sysfs_param - add a parameter to sysfs |
| 560 | * @mk: struct module_kobject | 579 | * @mk: struct module_kobject |
