aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2013-08-08 20:11:23 -0400
committerTejun Heo <tj@kernel.org>2013-08-08 20:11:23 -0400
commit6387698699afd72d6304566fb6ccf84bffe07c56 (patch)
tree9440e96fa8e5adce62409a5b0e40984dfedaada3
parenta7c6d554aa01236ac2a9f851ab0f75704f76dfa2 (diff)
cgroup: add css_parent()
Currently, controllers have to explicitly follow the cgroup hierarchy to find the parent of a given css. cgroup is moving towards using cgroup_subsys_state as the main controller interface construct, so let's provide a way to climb the hierarchy using just csses. This patch implements css_parent() which, given a css, returns its parent. The function is guarnateed to valid non-NULL parent css as long as the target css is not at the top of the hierarchy. freezer, cpuset, cpu, cpuacct, hugetlb, memory, net_cls and devices are converted to use css_parent() instead of accessing cgroup->parent directly. * __parent_ca() is dropped from cpuacct and its usage is replaced with parent_ca(). The only difference between the two was NULL test on cgroup->parent which is now embedded in css_parent() making the distinction moot. Note that eventually a css->parent field will be added to css and the NULL check in css_parent() will go away. This patch shouldn't cause any behavior differences. Signed-off-by: Tejun Heo <tj@kernel.org> Acked-by: Li Zefan <lizefan@huawei.com>
-rw-r--r--block/blk-cgroup.h4
-rw-r--r--include/linux/cgroup.h15
-rw-r--r--kernel/cgroup_freezer.c8
-rw-r--r--kernel/cpuset.c6
-rw-r--r--kernel/sched/core.c9
-rw-r--r--kernel/sched/cpuacct.c11
-rw-r--r--mm/hugetlb_cgroup.c6
-rw-r--r--mm/memcontrol.c39
-rw-r--r--net/sched/cls_cgroup.c8
-rw-r--r--security/device_cgroup.c18
10 files changed, 46 insertions, 78 deletions
diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h
index 8e5863e900bf..b6802c46d68f 100644
--- a/block/blk-cgroup.h
+++ b/block/blk-cgroup.h
@@ -209,9 +209,7 @@ static inline struct blkcg *bio_blkcg(struct bio *bio)
209 */ 209 */
210static inline struct blkcg *blkcg_parent(struct blkcg *blkcg) 210static inline struct blkcg *blkcg_parent(struct blkcg *blkcg)
211{ 211{
212 struct cgroup *pcg = blkcg->css.cgroup->parent; 212 return css_to_blkcg(css_parent(&blkcg->css));
213
214 return pcg ? cgroup_to_blkcg(pcg) : NULL;
215} 213}
216 214
217/** 215/**
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 821678aae4db..18112a3bb12b 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -647,6 +647,21 @@ struct cgroup_subsys {
647#undef SUBSYS 647#undef SUBSYS
648 648
649/** 649/**
650 * css_parent - find the parent css
651 * @css: the target cgroup_subsys_state
652 *
653 * Return the parent css of @css. This function is guaranteed to return
654 * non-NULL parent as long as @css isn't the root.
655 */
656static inline
657struct cgroup_subsys_state *css_parent(struct cgroup_subsys_state *css)
658{
659 struct cgroup *parent_cgrp = css->cgroup->parent;
660
661 return parent_cgrp ? parent_cgrp->subsys[css->ss->subsys_id] : NULL;
662}
663
664/**
650 * cgroup_css - obtain a cgroup's css for the specified subsystem 665 * cgroup_css - obtain a cgroup's css for the specified subsystem
651 * @cgrp: the cgroup of interest 666 * @cgrp: the cgroup of interest
652 * @subsys_id: the subsystem of interest 667 * @subsys_id: the subsystem of interest
diff --git a/kernel/cgroup_freezer.c b/kernel/cgroup_freezer.c
index 1db686e47a22..657a73cd44c4 100644
--- a/kernel/cgroup_freezer.c
+++ b/kernel/cgroup_freezer.c
@@ -62,11 +62,7 @@ static inline struct freezer *task_freezer(struct task_struct *task)
62 62
63static struct freezer *parent_freezer(struct freezer *freezer) 63static struct freezer *parent_freezer(struct freezer *freezer)
64{ 64{
65 struct cgroup *pcg = freezer->css.cgroup->parent; 65 return css_freezer(css_parent(&freezer->css));
66
67 if (pcg)
68 return cgroup_freezer(pcg);
69 return NULL;
70} 66}
71 67
72bool cgroup_freezing(struct task_struct *task) 68bool cgroup_freezing(struct task_struct *task)
@@ -234,7 +230,7 @@ static void freezer_fork(struct task_struct *task)
234 * The root cgroup is non-freezable, so we can skip the 230 * The root cgroup is non-freezable, so we can skip the
235 * following check. 231 * following check.
236 */ 232 */
237 if (!freezer->css.cgroup->parent) 233 if (!parent_freezer(freezer))
238 goto out; 234 goto out;
239 235
240 spin_lock_irq(&freezer->lock); 236 spin_lock_irq(&freezer->lock);
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 6e9cbdde25bd..259a4af37e69 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -133,11 +133,7 @@ static inline struct cpuset *task_cs(struct task_struct *task)
133 133
134static inline struct cpuset *parent_cs(struct cpuset *cs) 134static inline struct cpuset *parent_cs(struct cpuset *cs)
135{ 135{
136 struct cgroup *pcgrp = cs->css.cgroup->parent; 136 return css_cs(css_parent(&cs->css));
137
138 if (pcgrp)
139 return cgroup_cs(pcgrp);
140 return NULL;
141} 137}
142 138
143#ifdef CONFIG_NUMA 139#ifdef CONFIG_NUMA
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 5bccb0277129..7a10742b389a 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -7114,13 +7114,10 @@ static struct cgroup_subsys_state *cpu_cgroup_css_alloc(struct cgroup *cgrp)
7114static int cpu_cgroup_css_online(struct cgroup *cgrp) 7114static int cpu_cgroup_css_online(struct cgroup *cgrp)
7115{ 7115{
7116 struct task_group *tg = cgroup_tg(cgrp); 7116 struct task_group *tg = cgroup_tg(cgrp);
7117 struct task_group *parent; 7117 struct task_group *parent = css_tg(css_parent(&tg->css));
7118 7118
7119 if (!cgrp->parent) 7119 if (parent)
7120 return 0; 7120 sched_online_group(tg, parent);
7121
7122 parent = cgroup_tg(cgrp->parent);
7123 sched_online_group(tg, parent);
7124 return 0; 7121 return 0;
7125} 7122}
7126 7123
diff --git a/kernel/sched/cpuacct.c b/kernel/sched/cpuacct.c
index 8ccfa10cc89f..f6926a149a71 100644
--- a/kernel/sched/cpuacct.c
+++ b/kernel/sched/cpuacct.c
@@ -50,16 +50,9 @@ static inline struct cpuacct *task_ca(struct task_struct *tsk)
50 return css_ca(task_css(tsk, cpuacct_subsys_id)); 50 return css_ca(task_css(tsk, cpuacct_subsys_id));
51} 51}
52 52
53static inline struct cpuacct *__parent_ca(struct cpuacct *ca)
54{
55 return cgroup_ca(ca->css.cgroup->parent);
56}
57
58static inline struct cpuacct *parent_ca(struct cpuacct *ca) 53static inline struct cpuacct *parent_ca(struct cpuacct *ca)
59{ 54{
60 if (!ca->css.cgroup->parent) 55 return css_ca(css_parent(&ca->css));
61 return NULL;
62 return cgroup_ca(ca->css.cgroup->parent);
63} 56}
64 57
65static DEFINE_PER_CPU(u64, root_cpuacct_cpuusage); 58static DEFINE_PER_CPU(u64, root_cpuacct_cpuusage);
@@ -284,7 +277,7 @@ void cpuacct_account_field(struct task_struct *p, int index, u64 val)
284 while (ca != &root_cpuacct) { 277 while (ca != &root_cpuacct) {
285 kcpustat = this_cpu_ptr(ca->cpustat); 278 kcpustat = this_cpu_ptr(ca->cpustat);
286 kcpustat->cpustat[index] += val; 279 kcpustat->cpustat[index] += val;
287 ca = __parent_ca(ca); 280 ca = parent_ca(ca);
288 } 281 }
289 rcu_read_unlock(); 282 rcu_read_unlock();
290} 283}
diff --git a/mm/hugetlb_cgroup.c b/mm/hugetlb_cgroup.c
index 95585a0b9c8d..57ecb5d2513f 100644
--- a/mm/hugetlb_cgroup.c
+++ b/mm/hugetlb_cgroup.c
@@ -59,11 +59,7 @@ static inline bool hugetlb_cgroup_is_root(struct hugetlb_cgroup *h_cg)
59static inline struct hugetlb_cgroup * 59static inline struct hugetlb_cgroup *
60parent_hugetlb_cgroup(struct hugetlb_cgroup *h_cg) 60parent_hugetlb_cgroup(struct hugetlb_cgroup *h_cg)
61{ 61{
62 struct cgroup *parent = h_cg->css.cgroup->parent; 62 return hugetlb_cgroup_from_css(css_parent(&h_cg->css));
63
64 if (!parent)
65 return NULL;
66 return hugetlb_cgroup_from_cgroup(parent);
67} 63}
68 64
69static inline bool hugetlb_cgroup_have_usage(struct hugetlb_cgroup *h_cg) 65static inline bool hugetlb_cgroup_have_usage(struct hugetlb_cgroup *h_cg)
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 11d659e3b08e..69b3e520f921 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -1524,10 +1524,8 @@ static unsigned long mem_cgroup_margin(struct mem_cgroup *memcg)
1524 1524
1525int mem_cgroup_swappiness(struct mem_cgroup *memcg) 1525int mem_cgroup_swappiness(struct mem_cgroup *memcg)
1526{ 1526{
1527 struct cgroup *cgrp = memcg->css.cgroup;
1528
1529 /* root ? */ 1527 /* root ? */
1530 if (cgrp->parent == NULL) 1528 if (!css_parent(&memcg->css))
1531 return vm_swappiness; 1529 return vm_swappiness;
1532 1530
1533 return memcg->swappiness; 1531 return memcg->swappiness;
@@ -5026,11 +5024,7 @@ static int mem_cgroup_hierarchy_write(struct cgroup *cont, struct cftype *cft,
5026{ 5024{
5027 int retval = 0; 5025 int retval = 0;
5028 struct mem_cgroup *memcg = mem_cgroup_from_cont(cont); 5026 struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
5029 struct cgroup *parent = cont->parent; 5027 struct mem_cgroup *parent_memcg = mem_cgroup_from_css(css_parent(&memcg->css));
5030 struct mem_cgroup *parent_memcg = NULL;
5031
5032 if (parent)
5033 parent_memcg = mem_cgroup_from_cont(parent);
5034 5028
5035 mutex_lock(&memcg_create_mutex); 5029 mutex_lock(&memcg_create_mutex);
5036 5030
@@ -5282,18 +5276,15 @@ static int mem_cgroup_write(struct cgroup *cont, struct cftype *cft,
5282static void memcg_get_hierarchical_limit(struct mem_cgroup *memcg, 5276static void memcg_get_hierarchical_limit(struct mem_cgroup *memcg,
5283 unsigned long long *mem_limit, unsigned long long *memsw_limit) 5277 unsigned long long *mem_limit, unsigned long long *memsw_limit)
5284{ 5278{
5285 struct cgroup *cgroup;
5286 unsigned long long min_limit, min_memsw_limit, tmp; 5279 unsigned long long min_limit, min_memsw_limit, tmp;
5287 5280
5288 min_limit = res_counter_read_u64(&memcg->res, RES_LIMIT); 5281 min_limit = res_counter_read_u64(&memcg->res, RES_LIMIT);
5289 min_memsw_limit = res_counter_read_u64(&memcg->memsw, RES_LIMIT); 5282 min_memsw_limit = res_counter_read_u64(&memcg->memsw, RES_LIMIT);
5290 cgroup = memcg->css.cgroup;
5291 if (!memcg->use_hierarchy) 5283 if (!memcg->use_hierarchy)
5292 goto out; 5284 goto out;
5293 5285
5294 while (cgroup->parent) { 5286 while (css_parent(&memcg->css)) {
5295 cgroup = cgroup->parent; 5287 memcg = mem_cgroup_from_css(css_parent(&memcg->css));
5296 memcg = mem_cgroup_from_cont(cgroup);
5297 if (!memcg->use_hierarchy) 5288 if (!memcg->use_hierarchy)
5298 break; 5289 break;
5299 tmp = res_counter_read_u64(&memcg->res, RES_LIMIT); 5290 tmp = res_counter_read_u64(&memcg->res, RES_LIMIT);
@@ -5523,16 +5514,11 @@ static int mem_cgroup_swappiness_write(struct cgroup *cgrp, struct cftype *cft,
5523 u64 val) 5514 u64 val)
5524{ 5515{
5525 struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp); 5516 struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp);
5526 struct mem_cgroup *parent; 5517 struct mem_cgroup *parent = mem_cgroup_from_css(css_parent(&memcg->css));
5527
5528 if (val > 100)
5529 return -EINVAL;
5530 5518
5531 if (cgrp->parent == NULL) 5519 if (val > 100 || !parent)
5532 return -EINVAL; 5520 return -EINVAL;
5533 5521
5534 parent = mem_cgroup_from_cont(cgrp->parent);
5535
5536 mutex_lock(&memcg_create_mutex); 5522 mutex_lock(&memcg_create_mutex);
5537 5523
5538 /* If under hierarchy, only empty-root can set this value */ 5524 /* If under hierarchy, only empty-root can set this value */
@@ -5861,14 +5847,12 @@ static int mem_cgroup_oom_control_write(struct cgroup *cgrp,
5861 struct cftype *cft, u64 val) 5847 struct cftype *cft, u64 val)
5862{ 5848{
5863 struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp); 5849 struct mem_cgroup *memcg = mem_cgroup_from_cont(cgrp);
5864 struct mem_cgroup *parent; 5850 struct mem_cgroup *parent = mem_cgroup_from_css(css_parent(&memcg->css));
5865 5851
5866 /* cannot set to root cgroup and only 0 and 1 are allowed */ 5852 /* cannot set to root cgroup and only 0 and 1 are allowed */
5867 if (!cgrp->parent || !((val == 0) || (val == 1))) 5853 if (!parent || !((val == 0) || (val == 1)))
5868 return -EINVAL; 5854 return -EINVAL;
5869 5855
5870 parent = mem_cgroup_from_cont(cgrp->parent);
5871
5872 mutex_lock(&memcg_create_mutex); 5856 mutex_lock(&memcg_create_mutex);
5873 /* oom-kill-disable is a flag for subhierarchy. */ 5857 /* oom-kill-disable is a flag for subhierarchy. */
5874 if ((parent->use_hierarchy) || memcg_has_children(memcg)) { 5858 if ((parent->use_hierarchy) || memcg_has_children(memcg)) {
@@ -6266,15 +6250,14 @@ free_out:
6266static int 6250static int
6267mem_cgroup_css_online(struct cgroup *cont) 6251mem_cgroup_css_online(struct cgroup *cont)
6268{ 6252{
6269 struct mem_cgroup *memcg, *parent; 6253 struct mem_cgroup *memcg = mem_cgroup_from_cont(cont);
6254 struct mem_cgroup *parent = mem_cgroup_from_css(css_parent(&memcg->css));
6270 int error = 0; 6255 int error = 0;
6271 6256
6272 if (!cont->parent) 6257 if (!parent)
6273 return 0; 6258 return 0;
6274 6259
6275 mutex_lock(&memcg_create_mutex); 6260 mutex_lock(&memcg_create_mutex);
6276 memcg = mem_cgroup_from_cont(cont);
6277 parent = mem_cgroup_from_cont(cont->parent);
6278 6261
6279 memcg->use_hierarchy = parent->use_hierarchy; 6262 memcg->use_hierarchy = parent->use_hierarchy;
6280 memcg->oom_kill_disable = parent->oom_kill_disable; 6263 memcg->oom_kill_disable = parent->oom_kill_disable;
diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c
index af412ab2b477..9e6b75e5efce 100644
--- a/net/sched/cls_cgroup.c
+++ b/net/sched/cls_cgroup.c
@@ -50,9 +50,11 @@ static struct cgroup_subsys_state *cgrp_css_alloc(struct cgroup *cgrp)
50 50
51static int cgrp_css_online(struct cgroup *cgrp) 51static int cgrp_css_online(struct cgroup *cgrp)
52{ 52{
53 if (cgrp->parent) 53 struct cgroup_cls_state *cs = cgrp_cls_state(cgrp);
54 cgrp_cls_state(cgrp)->classid = 54 struct cgroup_cls_state *parent = css_cls_state(css_parent(&cs->css));
55 cgrp_cls_state(cgrp->parent)->classid; 55
56 if (parent)
57 cs->classid = parent->classid;
56 return 0; 58 return 0;
57} 59}
58 60
diff --git a/security/device_cgroup.c b/security/device_cgroup.c
index 90953648c643..635a49db005d 100644
--- a/security/device_cgroup.c
+++ b/security/device_cgroup.c
@@ -198,13 +198,11 @@ static inline bool is_devcg_online(const struct dev_cgroup *devcg)
198 */ 198 */
199static int devcgroup_online(struct cgroup *cgroup) 199static int devcgroup_online(struct cgroup *cgroup)
200{ 200{
201 struct dev_cgroup *dev_cgroup, *parent_dev_cgroup = NULL; 201 struct dev_cgroup *dev_cgroup = cgroup_to_devcgroup(cgroup);
202 struct dev_cgroup *parent_dev_cgroup = css_to_devcgroup(css_parent(&dev_cgroup->css));
202 int ret = 0; 203 int ret = 0;
203 204
204 mutex_lock(&devcgroup_mutex); 205 mutex_lock(&devcgroup_mutex);
205 dev_cgroup = cgroup_to_devcgroup(cgroup);
206 if (cgroup->parent)
207 parent_dev_cgroup = cgroup_to_devcgroup(cgroup->parent);
208 206
209 if (parent_dev_cgroup == NULL) 207 if (parent_dev_cgroup == NULL)
210 dev_cgroup->behavior = DEVCG_DEFAULT_ALLOW; 208 dev_cgroup->behavior = DEVCG_DEFAULT_ALLOW;
@@ -394,12 +392,10 @@ static bool may_access(struct dev_cgroup *dev_cgroup,
394static int parent_has_perm(struct dev_cgroup *childcg, 392static int parent_has_perm(struct dev_cgroup *childcg,
395 struct dev_exception_item *ex) 393 struct dev_exception_item *ex)
396{ 394{
397 struct cgroup *pcg = childcg->css.cgroup->parent; 395 struct dev_cgroup *parent = css_to_devcgroup(css_parent(&childcg->css));
398 struct dev_cgroup *parent;
399 396
400 if (!pcg) 397 if (!parent)
401 return 1; 398 return 1;
402 parent = cgroup_to_devcgroup(pcg);
403 return may_access(parent, ex, childcg->behavior); 399 return may_access(parent, ex, childcg->behavior);
404} 400}
405 401
@@ -524,15 +520,11 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
524 char temp[12]; /* 11 + 1 characters needed for a u32 */ 520 char temp[12]; /* 11 + 1 characters needed for a u32 */
525 int count, rc = 0; 521 int count, rc = 0;
526 struct dev_exception_item ex; 522 struct dev_exception_item ex;
527 struct cgroup *p = devcgroup->css.cgroup; 523 struct dev_cgroup *parent = css_to_devcgroup(css_parent(&devcgroup->css));
528 struct dev_cgroup *parent = NULL;
529 524
530 if (!capable(CAP_SYS_ADMIN)) 525 if (!capable(CAP_SYS_ADMIN))
531 return -EPERM; 526 return -EPERM;
532 527
533 if (p->parent)
534 parent = cgroup_to_devcgroup(p->parent);
535
536 memset(&ex, 0, sizeof(ex)); 528 memset(&ex, 0, sizeof(ex));
537 b = buffer; 529 b = buffer;
538 530