diff options
Diffstat (limited to 'kernel/params.c')
-rw-r--r-- | kernel/params.c | 50 |
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 */ |
29 | static DEFINE_MUTEX(param_lock); | 29 | static 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 : ¶m_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. */ |
32 | struct kmalloced_param { | 36 | struct kmalloced_param { |
33 | struct list_head list; | 37 | struct list_head list; |
34 | char val[]; | 38 | char val[]; |
35 | }; | 39 | }; |
36 | static LIST_HEAD(kmalloced_params); | 40 | static LIST_HEAD(kmalloced_params); |
41 | static DEFINE_SPINLOCK(kmalloced_params_lock); | ||
37 | 42 | ||
38 | static void *kmalloc_parameter(unsigned int size) | 43 | static 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 | ||
64 | static char dash2underscore(char c) | 74 | static 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(¶m_lock); | 131 | kernel_param_lock(params[i].mod); |
122 | param_check_unsafe(¶ms[i]); | 132 | param_check_unsafe(¶ms[i]); |
123 | err = params[i].ops->set(val, ¶ms[i]); | 133 | err = params[i].ops->set(val, ¶ms[i]); |
124 | mutex_unlock(¶m_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 = { | |||
417 | EXPORT_SYMBOL(param_ops_bint); | 427 | EXPORT_SYMBOL(param_ops_bint); |
418 | 428 | ||
419 | /* We break the rule and mangle the string. */ | 429 | /* We break the rule and mangle the string. */ |
420 | static int param_array(const char *name, | 430 | static 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(¶m_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(¶m_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(¶m_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(¶m_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. */ |
582 | static ssize_t param_attr_store(struct module_attribute *mattr, | 593 | static 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(¶m_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(¶m_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 | 619 | void kernel_param_lock(struct module *mod) |
609 | void __kernel_param_lock(void) | ||
610 | { | 620 | { |
611 | mutex_lock(¶m_lock); | 621 | mutex_lock(KPARAM_MUTEX(mod)); |
612 | } | 622 | } |
613 | EXPORT_SYMBOL(__kernel_param_lock); | ||
614 | 623 | ||
615 | void __kernel_param_unlock(void) | 624 | void kernel_param_unlock(struct module *mod) |
616 | { | 625 | { |
617 | mutex_unlock(¶m_lock); | 626 | mutex_unlock(KPARAM_MUTEX(mod)); |
618 | } | 627 | } |
619 | EXPORT_SYMBOL(__kernel_param_unlock); | 628 | |
629 | #ifdef CONFIG_SYSFS | ||
630 | EXPORT_SYMBOL(kernel_param_lock); | ||
631 | EXPORT_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 |