diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/cgroup.c | 68 |
1 files changed, 40 insertions, 28 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index ced292d720b9..1b18090269ad 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
| @@ -88,7 +88,7 @@ static DEFINE_MUTEX(cgroup_root_mutex); | |||
| 88 | 88 | ||
| 89 | /* | 89 | /* |
| 90 | * Generate an array of cgroup subsystem pointers. At boot time, this is | 90 | * Generate an array of cgroup subsystem pointers. At boot time, this is |
| 91 | * populated up to CGROUP_BUILTIN_SUBSYS_COUNT, and modular subsystems are | 91 | * populated with the built in subsystems, and modular subsystems are |
| 92 | * registered after that. The mutable section of this array is protected by | 92 | * registered after that. The mutable section of this array is protected by |
| 93 | * cgroup_mutex. | 93 | * cgroup_mutex. |
| 94 | */ | 94 | */ |
| @@ -1321,7 +1321,7 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts) | |||
| 1321 | * take duplicate reference counts on a subsystem that's already used, | 1321 | * take duplicate reference counts on a subsystem that's already used, |
| 1322 | * but rebind_subsystems handles this case. | 1322 | * but rebind_subsystems handles this case. |
| 1323 | */ | 1323 | */ |
| 1324 | for (i = CGROUP_BUILTIN_SUBSYS_COUNT; i < CGROUP_SUBSYS_COUNT; i++) { | 1324 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { |
| 1325 | unsigned long bit = 1UL << i; | 1325 | unsigned long bit = 1UL << i; |
| 1326 | 1326 | ||
| 1327 | if (!(bit & opts->subsys_mask)) | 1327 | if (!(bit & opts->subsys_mask)) |
| @@ -1337,7 +1337,7 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts) | |||
| 1337 | * raced with a module_delete call, and to the user this is | 1337 | * raced with a module_delete call, and to the user this is |
| 1338 | * essentially a "subsystem doesn't exist" case. | 1338 | * essentially a "subsystem doesn't exist" case. |
| 1339 | */ | 1339 | */ |
| 1340 | for (i--; i >= CGROUP_BUILTIN_SUBSYS_COUNT; i--) { | 1340 | for (i--; i >= 0; i--) { |
| 1341 | /* drop refcounts only on the ones we took */ | 1341 | /* drop refcounts only on the ones we took */ |
| 1342 | unsigned long bit = 1UL << i; | 1342 | unsigned long bit = 1UL << i; |
| 1343 | 1343 | ||
| @@ -1354,7 +1354,7 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts) | |||
| 1354 | static void drop_parsed_module_refcounts(unsigned long subsys_mask) | 1354 | static void drop_parsed_module_refcounts(unsigned long subsys_mask) |
| 1355 | { | 1355 | { |
| 1356 | int i; | 1356 | int i; |
| 1357 | for (i = CGROUP_BUILTIN_SUBSYS_COUNT; i < CGROUP_SUBSYS_COUNT; i++) { | 1357 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { |
| 1358 | unsigned long bit = 1UL << i; | 1358 | unsigned long bit = 1UL << i; |
| 1359 | 1359 | ||
| 1360 | if (!(bit & subsys_mask)) | 1360 | if (!(bit & subsys_mask)) |
| @@ -4442,8 +4442,7 @@ int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss) | |||
| 4442 | * since cgroup_init_subsys will have already taken care of it. | 4442 | * since cgroup_init_subsys will have already taken care of it. |
| 4443 | */ | 4443 | */ |
| 4444 | if (ss->module == NULL) { | 4444 | if (ss->module == NULL) { |
| 4445 | /* a few sanity checks */ | 4445 | /* a sanity check */ |
| 4446 | BUG_ON(ss->subsys_id >= CGROUP_BUILTIN_SUBSYS_COUNT); | ||
| 4447 | BUG_ON(subsys[ss->subsys_id] != ss); | 4446 | BUG_ON(subsys[ss->subsys_id] != ss); |
| 4448 | return 0; | 4447 | return 0; |
| 4449 | } | 4448 | } |
| @@ -4457,7 +4456,7 @@ int __init_or_module cgroup_load_subsys(struct cgroup_subsys *ss) | |||
| 4457 | */ | 4456 | */ |
| 4458 | mutex_lock(&cgroup_mutex); | 4457 | mutex_lock(&cgroup_mutex); |
| 4459 | /* find the first empty slot in the array */ | 4458 | /* find the first empty slot in the array */ |
| 4460 | for (i = CGROUP_BUILTIN_SUBSYS_COUNT; i < CGROUP_SUBSYS_COUNT; i++) { | 4459 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { |
| 4461 | if (subsys[i] == NULL) | 4460 | if (subsys[i] == NULL) |
| 4462 | break; | 4461 | break; |
| 4463 | } | 4462 | } |
| @@ -4560,7 +4559,6 @@ void cgroup_unload_subsys(struct cgroup_subsys *ss) | |||
| 4560 | 4559 | ||
| 4561 | mutex_lock(&cgroup_mutex); | 4560 | mutex_lock(&cgroup_mutex); |
| 4562 | /* deassign the subsys_id */ | 4561 | /* deassign the subsys_id */ |
| 4563 | BUG_ON(ss->subsys_id < CGROUP_BUILTIN_SUBSYS_COUNT); | ||
| 4564 | subsys[ss->subsys_id] = NULL; | 4562 | subsys[ss->subsys_id] = NULL; |
| 4565 | 4563 | ||
| 4566 | /* remove subsystem from rootnode's list of subsystems */ | 4564 | /* remove subsystem from rootnode's list of subsystems */ |
| @@ -4623,10 +4621,13 @@ int __init cgroup_init_early(void) | |||
| 4623 | for (i = 0; i < CSS_SET_TABLE_SIZE; i++) | 4621 | for (i = 0; i < CSS_SET_TABLE_SIZE; i++) |
| 4624 | INIT_HLIST_HEAD(&css_set_table[i]); | 4622 | INIT_HLIST_HEAD(&css_set_table[i]); |
| 4625 | 4623 | ||
| 4626 | /* at bootup time, we don't worry about modular subsystems */ | 4624 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { |
| 4627 | for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) { | ||
| 4628 | struct cgroup_subsys *ss = subsys[i]; | 4625 | struct cgroup_subsys *ss = subsys[i]; |
| 4629 | 4626 | ||
| 4627 | /* at bootup time, we don't worry about modular subsystems */ | ||
| 4628 | if (!ss || ss->module) | ||
| 4629 | continue; | ||
| 4630 | |||
| 4630 | BUG_ON(!ss->name); | 4631 | BUG_ON(!ss->name); |
| 4631 | BUG_ON(strlen(ss->name) > MAX_CGROUP_TYPE_NAMELEN); | 4632 | BUG_ON(strlen(ss->name) > MAX_CGROUP_TYPE_NAMELEN); |
| 4632 | BUG_ON(!ss->create); | 4633 | BUG_ON(!ss->create); |
| @@ -4659,9 +4660,12 @@ int __init cgroup_init(void) | |||
| 4659 | if (err) | 4660 | if (err) |
| 4660 | return err; | 4661 | return err; |
| 4661 | 4662 | ||
| 4662 | /* at bootup time, we don't worry about modular subsystems */ | 4663 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { |
| 4663 | for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) { | ||
| 4664 | struct cgroup_subsys *ss = subsys[i]; | 4664 | struct cgroup_subsys *ss = subsys[i]; |
| 4665 | |||
| 4666 | /* at bootup time, we don't worry about modular subsystems */ | ||
| 4667 | if (!ss || ss->module) | ||
| 4668 | continue; | ||
| 4665 | if (!ss->early_init) | 4669 | if (!ss->early_init) |
| 4666 | cgroup_init_subsys(ss); | 4670 | cgroup_init_subsys(ss); |
| 4667 | if (ss->use_id) | 4671 | if (ss->use_id) |
| @@ -4856,13 +4860,16 @@ void cgroup_fork_callbacks(struct task_struct *child) | |||
| 4856 | { | 4860 | { |
| 4857 | if (need_forkexit_callback) { | 4861 | if (need_forkexit_callback) { |
| 4858 | int i; | 4862 | int i; |
| 4859 | /* | 4863 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { |
| 4860 | * forkexit callbacks are only supported for builtin | ||
| 4861 | * subsystems, and the builtin section of the subsys array is | ||
| 4862 | * immutable, so we don't need to lock the subsys array here. | ||
| 4863 | */ | ||
| 4864 | for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) { | ||
| 4865 | struct cgroup_subsys *ss = subsys[i]; | 4864 | struct cgroup_subsys *ss = subsys[i]; |
| 4865 | |||
| 4866 | /* | ||
| 4867 | * forkexit callbacks are only supported for | ||
| 4868 | * builtin subsystems. | ||
| 4869 | */ | ||
| 4870 | if (!ss || ss->module) | ||
| 4871 | continue; | ||
| 4872 | |||
| 4866 | if (ss->fork) | 4873 | if (ss->fork) |
| 4867 | ss->fork(child); | 4874 | ss->fork(child); |
| 4868 | } | 4875 | } |
| @@ -4967,12 +4974,13 @@ void cgroup_exit(struct task_struct *tsk, int run_callbacks) | |||
| 4967 | tsk->cgroups = &init_css_set; | 4974 | tsk->cgroups = &init_css_set; |
| 4968 | 4975 | ||
| 4969 | if (run_callbacks && need_forkexit_callback) { | 4976 | if (run_callbacks && need_forkexit_callback) { |
| 4970 | /* | 4977 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { |
| 4971 | * modular subsystems can't use callbacks, so no need to lock | ||
| 4972 | * the subsys array | ||
| 4973 | */ | ||
| 4974 | for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) { | ||
| 4975 | struct cgroup_subsys *ss = subsys[i]; | 4978 | struct cgroup_subsys *ss = subsys[i]; |
| 4979 | |||
| 4980 | /* modular subsystems can't use callbacks */ | ||
| 4981 | if (!ss || ss->module) | ||
| 4982 | continue; | ||
| 4983 | |||
| 4976 | if (ss->exit) { | 4984 | if (ss->exit) { |
| 4977 | struct cgroup *old_cgrp = | 4985 | struct cgroup *old_cgrp = |
| 4978 | rcu_dereference_raw(cg->subsys[i])->cgroup; | 4986 | rcu_dereference_raw(cg->subsys[i])->cgroup; |
| @@ -5158,13 +5166,17 @@ static int __init cgroup_disable(char *str) | |||
| 5158 | while ((token = strsep(&str, ",")) != NULL) { | 5166 | while ((token = strsep(&str, ",")) != NULL) { |
| 5159 | if (!*token) | 5167 | if (!*token) |
| 5160 | continue; | 5168 | continue; |
| 5161 | /* | 5169 | for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { |
| 5162 | * cgroup_disable, being at boot time, can't know about module | ||
| 5163 | * subsystems, so we don't worry about them. | ||
| 5164 | */ | ||
| 5165 | for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) { | ||
| 5166 | struct cgroup_subsys *ss = subsys[i]; | 5170 | struct cgroup_subsys *ss = subsys[i]; |
| 5167 | 5171 | ||
| 5172 | /* | ||
| 5173 | * cgroup_disable, being at boot time, can't | ||
| 5174 | * know about module subsystems, so we don't | ||
| 5175 | * worry about them. | ||
| 5176 | */ | ||
| 5177 | if (!ss || ss->module) | ||
| 5178 | continue; | ||
| 5179 | |||
| 5168 | if (!strcmp(token, ss->name)) { | 5180 | if (!strcmp(token, ss->name)) { |
| 5169 | ss->disabled = 1; | 5181 | ss->disabled = 1; |
| 5170 | printk(KERN_INFO "Disabling %s control group" | 5182 | printk(KERN_INFO "Disabling %s control group" |
