diff options
-rw-r--r-- | kernel/cgroup.c | 100 |
1 files changed, 49 insertions, 51 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index b604c7e0cfc6..e66b9ee5ecc1 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -338,16 +338,24 @@ struct cgrp_cset_link { | |||
338 | struct list_head cgrp_link; | 338 | struct list_head cgrp_link; |
339 | }; | 339 | }; |
340 | 340 | ||
341 | /* The default css_set - used by init and its children prior to any | 341 | /* |
342 | * The default css_set - used by init and its children prior to any | ||
342 | * hierarchies being mounted. It contains a pointer to the root state | 343 | * hierarchies being mounted. It contains a pointer to the root state |
343 | * for each subsystem. Also used to anchor the list of css_sets. Not | 344 | * for each subsystem. Also used to anchor the list of css_sets. Not |
344 | * reference-counted, to improve performance when child cgroups | 345 | * reference-counted, to improve performance when child cgroups |
345 | * haven't been created. | 346 | * haven't been created. |
346 | */ | 347 | */ |
348 | static struct css_set init_css_set = { | ||
349 | .refcount = ATOMIC_INIT(1), | ||
350 | .cgrp_links = LIST_HEAD_INIT(init_css_set.cgrp_links), | ||
351 | .tasks = LIST_HEAD_INIT(init_css_set.tasks), | ||
352 | .mg_tasks = LIST_HEAD_INIT(init_css_set.mg_tasks), | ||
353 | .mg_preload_node = LIST_HEAD_INIT(init_css_set.mg_preload_node), | ||
354 | .mg_node = LIST_HEAD_INIT(init_css_set.mg_node), | ||
355 | }; | ||
347 | 356 | ||
348 | static struct css_set init_css_set; | ||
349 | static struct cgrp_cset_link init_cgrp_cset_link; | 357 | static struct cgrp_cset_link init_cgrp_cset_link; |
350 | static int css_set_count; | 358 | static int css_set_count = 1; /* 1 for init_css_set */ |
351 | 359 | ||
352 | /* | 360 | /* |
353 | * hash table for cgroup groups. This improves the performance to find | 361 | * hash table for cgroup groups. This improves the performance to find |
@@ -1352,7 +1360,8 @@ static void init_cgroup_housekeeping(struct cgroup *cgrp) | |||
1352 | cgrp->dummy_css.cgroup = cgrp; | 1360 | cgrp->dummy_css.cgroup = cgrp; |
1353 | } | 1361 | } |
1354 | 1362 | ||
1355 | static void init_cgroup_root(struct cgroupfs_root *root) | 1363 | static void init_cgroup_root(struct cgroupfs_root *root, |
1364 | struct cgroup_sb_opts *opts) | ||
1356 | { | 1365 | { |
1357 | struct cgroup *cgrp = &root->top_cgroup; | 1366 | struct cgroup *cgrp = &root->top_cgroup; |
1358 | 1367 | ||
@@ -1361,20 +1370,6 @@ static void init_cgroup_root(struct cgroupfs_root *root) | |||
1361 | cgrp->root = root; | 1370 | cgrp->root = root; |
1362 | init_cgroup_housekeeping(cgrp); | 1371 | init_cgroup_housekeeping(cgrp); |
1363 | idr_init(&root->cgroup_idr); | 1372 | idr_init(&root->cgroup_idr); |
1364 | } | ||
1365 | |||
1366 | static struct cgroupfs_root *cgroup_root_from_opts(struct cgroup_sb_opts *opts) | ||
1367 | { | ||
1368 | struct cgroupfs_root *root; | ||
1369 | |||
1370 | if (!opts->subsys_mask && !opts->none) | ||
1371 | return ERR_PTR(-EINVAL); | ||
1372 | |||
1373 | root = kzalloc(sizeof(*root), GFP_KERNEL); | ||
1374 | if (!root) | ||
1375 | return ERR_PTR(-ENOMEM); | ||
1376 | |||
1377 | init_cgroup_root(root); | ||
1378 | 1373 | ||
1379 | root->flags = opts->flags; | 1374 | root->flags = opts->flags; |
1380 | if (opts->release_agent) | 1375 | if (opts->release_agent) |
@@ -1383,7 +1378,6 @@ static struct cgroupfs_root *cgroup_root_from_opts(struct cgroup_sb_opts *opts) | |||
1383 | strcpy(root->name, opts->name); | 1378 | strcpy(root->name, opts->name); |
1384 | if (opts->cpuset_clone_children) | 1379 | if (opts->cpuset_clone_children) |
1385 | set_bit(CGRP_CPUSET_CLONE_CHILDREN, &root->top_cgroup.flags); | 1380 | set_bit(CGRP_CPUSET_CLONE_CHILDREN, &root->top_cgroup.flags); |
1386 | return root; | ||
1387 | } | 1381 | } |
1388 | 1382 | ||
1389 | static int cgroup_setup_root(struct cgroupfs_root *root, unsigned long ss_mask) | 1383 | static int cgroup_setup_root(struct cgroupfs_root *root, unsigned long ss_mask) |
@@ -1548,13 +1542,24 @@ retry: | |||
1548 | goto out_unlock; | 1542 | goto out_unlock; |
1549 | } | 1543 | } |
1550 | 1544 | ||
1551 | /* no such thing, create a new one */ | 1545 | /* |
1552 | root = cgroup_root_from_opts(&opts); | 1546 | * No such thing, create a new one. name= matching without subsys |
1553 | if (IS_ERR(root)) { | 1547 | * specification is allowed for already existing hierarchies but we |
1554 | ret = PTR_ERR(root); | 1548 | * can't create new one without subsys specification. |
1549 | */ | ||
1550 | if (!opts.subsys_mask && !opts.none) { | ||
1551 | ret = -EINVAL; | ||
1552 | goto out_unlock; | ||
1553 | } | ||
1554 | |||
1555 | root = kzalloc(sizeof(*root), GFP_KERNEL); | ||
1556 | if (!root) { | ||
1557 | ret = -ENOMEM; | ||
1555 | goto out_unlock; | 1558 | goto out_unlock; |
1556 | } | 1559 | } |
1557 | 1560 | ||
1561 | init_cgroup_root(root, &opts); | ||
1562 | |||
1558 | ret = cgroup_setup_root(root, opts.subsys_mask); | 1563 | ret = cgroup_setup_root(root, opts.subsys_mask); |
1559 | if (ret) | 1564 | if (ret) |
1560 | cgroup_free_root(root); | 1565 | cgroup_free_root(root); |
@@ -4030,26 +4035,13 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss) | |||
4030 | */ | 4035 | */ |
4031 | int __init cgroup_init_early(void) | 4036 | int __init cgroup_init_early(void) |
4032 | { | 4037 | { |
4038 | static struct cgroup_sb_opts __initdata opts = { }; | ||
4033 | struct cgroup_subsys *ss; | 4039 | struct cgroup_subsys *ss; |
4034 | int i; | 4040 | int i; |
4035 | 4041 | ||
4036 | atomic_set(&init_css_set.refcount, 1); | 4042 | init_cgroup_root(&cgroup_dummy_root, &opts); |
4037 | INIT_LIST_HEAD(&init_css_set.cgrp_links); | ||
4038 | INIT_LIST_HEAD(&init_css_set.tasks); | ||
4039 | INIT_LIST_HEAD(&init_css_set.mg_tasks); | ||
4040 | INIT_LIST_HEAD(&init_css_set.mg_preload_node); | ||
4041 | INIT_LIST_HEAD(&init_css_set.mg_node); | ||
4042 | INIT_HLIST_NODE(&init_css_set.hlist); | ||
4043 | css_set_count = 1; | ||
4044 | init_cgroup_root(&cgroup_dummy_root); | ||
4045 | cgroup_root_count = 1; | ||
4046 | RCU_INIT_POINTER(init_task.cgroups, &init_css_set); | 4043 | RCU_INIT_POINTER(init_task.cgroups, &init_css_set); |
4047 | 4044 | ||
4048 | init_cgrp_cset_link.cset = &init_css_set; | ||
4049 | init_cgrp_cset_link.cgrp = cgroup_dummy_top; | ||
4050 | list_add(&init_cgrp_cset_link.cset_link, &cgroup_dummy_top->cset_links); | ||
4051 | list_add(&init_cgrp_cset_link.cgrp_link, &init_css_set.cgrp_links); | ||
4052 | |||
4053 | for_each_subsys(ss, i) { | 4045 | for_each_subsys(ss, i) { |
4054 | WARN(!ss->css_alloc || !ss->css_free || ss->name || ss->id, | 4046 | WARN(!ss->css_alloc || !ss->css_free || ss->name || ss->id, |
4055 | "invalid cgroup_subsys %d:%s css_alloc=%p css_free=%p name:id=%d:%s\n", | 4047 | "invalid cgroup_subsys %d:%s css_alloc=%p css_free=%p name:id=%d:%s\n", |
@@ -4077,22 +4069,10 @@ int __init cgroup_init(void) | |||
4077 | { | 4069 | { |
4078 | struct cgroup_subsys *ss; | 4070 | struct cgroup_subsys *ss; |
4079 | unsigned long key; | 4071 | unsigned long key; |
4080 | int i, err; | 4072 | int ssid, err; |
4081 | 4073 | ||
4082 | BUG_ON(cgroup_init_cftypes(NULL, cgroup_base_files)); | 4074 | BUG_ON(cgroup_init_cftypes(NULL, cgroup_base_files)); |
4083 | 4075 | ||
4084 | for_each_subsys(ss, i) { | ||
4085 | if (!ss->early_init) | ||
4086 | cgroup_init_subsys(ss); | ||
4087 | |||
4088 | /* | ||
4089 | * cftype registration needs kmalloc and can't be done | ||
4090 | * during early_init. Register base cftypes separately. | ||
4091 | */ | ||
4092 | if (ss->base_cftypes) | ||
4093 | WARN_ON(cgroup_add_cftypes(ss, ss->base_cftypes)); | ||
4094 | } | ||
4095 | |||
4096 | /* allocate id for the dummy hierarchy */ | 4076 | /* allocate id for the dummy hierarchy */ |
4097 | mutex_lock(&cgroup_mutex); | 4077 | mutex_lock(&cgroup_mutex); |
4098 | 4078 | ||
@@ -4106,8 +4086,26 @@ int __init cgroup_init(void) | |||
4106 | 0, 1, GFP_KERNEL); | 4086 | 0, 1, GFP_KERNEL); |
4107 | BUG_ON(err < 0); | 4087 | BUG_ON(err < 0); |
4108 | 4088 | ||
4089 | cgroup_root_count = 1; | ||
4090 | init_cgrp_cset_link.cset = &init_css_set; | ||
4091 | init_cgrp_cset_link.cgrp = cgroup_dummy_top; | ||
4092 | list_add(&init_cgrp_cset_link.cset_link, &cgroup_dummy_top->cset_links); | ||
4093 | list_add(&init_cgrp_cset_link.cgrp_link, &init_css_set.cgrp_links); | ||
4094 | |||
4109 | mutex_unlock(&cgroup_mutex); | 4095 | mutex_unlock(&cgroup_mutex); |
4110 | 4096 | ||
4097 | for_each_subsys(ss, ssid) { | ||
4098 | if (!ss->early_init) | ||
4099 | cgroup_init_subsys(ss); | ||
4100 | |||
4101 | /* | ||
4102 | * cftype registration needs kmalloc and can't be done | ||
4103 | * during early_init. Register base cftypes separately. | ||
4104 | */ | ||
4105 | if (ss->base_cftypes) | ||
4106 | WARN_ON(cgroup_add_cftypes(ss, ss->base_cftypes)); | ||
4107 | } | ||
4108 | |||
4111 | cgroup_kobj = kobject_create_and_add("cgroup", fs_kobj); | 4109 | cgroup_kobj = kobject_create_and_add("cgroup", fs_kobj); |
4112 | if (!cgroup_kobj) | 4110 | if (!cgroup_kobj) |
4113 | return -ENOMEM; | 4111 | return -ENOMEM; |