aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/cgroup.c
diff options
context:
space:
mode:
authorDaisuke Nishimura <nishimura@mxp.nes.nec.co.jp>2010-03-10 18:22:03 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2010-03-12 18:52:35 -0500
commit2468c7234b366eeb799ee0648cb58f9cba394a54 (patch)
tree050d7ea224b975eb71b05bf472f14f4c7bb13670 /kernel/cgroup.c
parent5ce9f07bf1bed9a1f9886373ad0b149294f84c25 (diff)
cgroup: introduce cancel_attach()
Add cancel_attach() operation to struct cgroup_subsys. cancel_attach() can be used when can_attach() operation prepares something for the subsys, but we should rollback what can_attach() operation has prepared if attach task fails after we've succeeded in can_attach(). Signed-off-by: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp> Acked-by: Li Zefan <lizf@cn.fujitsu.com> Reviewed-by: Paul Menage <menage@google.com> Cc: Balbir Singh <balbir@linux.vnet.ibm.com> Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r--kernel/cgroup.c40
1 files changed, 33 insertions, 7 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 4fd90e129772..be45d2f6008a 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -1554,7 +1554,7 @@ int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen)
1554int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk) 1554int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
1555{ 1555{
1556 int retval = 0; 1556 int retval = 0;
1557 struct cgroup_subsys *ss; 1557 struct cgroup_subsys *ss, *failed_ss = NULL;
1558 struct cgroup *oldcgrp; 1558 struct cgroup *oldcgrp;
1559 struct css_set *cg; 1559 struct css_set *cg;
1560 struct css_set *newcg; 1560 struct css_set *newcg;
@@ -1568,8 +1568,16 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
1568 for_each_subsys(root, ss) { 1568 for_each_subsys(root, ss) {
1569 if (ss->can_attach) { 1569 if (ss->can_attach) {
1570 retval = ss->can_attach(ss, cgrp, tsk, false); 1570 retval = ss->can_attach(ss, cgrp, tsk, false);
1571 if (retval) 1571 if (retval) {
1572 return retval; 1572 /*
1573 * Remember on which subsystem the can_attach()
1574 * failed, so that we only call cancel_attach()
1575 * against the subsystems whose can_attach()
1576 * succeeded. (See below)
1577 */
1578 failed_ss = ss;
1579 goto out;
1580 }
1573 } 1581 }
1574 } 1582 }
1575 1583
@@ -1583,14 +1591,17 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
1583 */ 1591 */
1584 newcg = find_css_set(cg, cgrp); 1592 newcg = find_css_set(cg, cgrp);
1585 put_css_set(cg); 1593 put_css_set(cg);
1586 if (!newcg) 1594 if (!newcg) {
1587 return -ENOMEM; 1595 retval = -ENOMEM;
1596 goto out;
1597 }
1588 1598
1589 task_lock(tsk); 1599 task_lock(tsk);
1590 if (tsk->flags & PF_EXITING) { 1600 if (tsk->flags & PF_EXITING) {
1591 task_unlock(tsk); 1601 task_unlock(tsk);
1592 put_css_set(newcg); 1602 put_css_set(newcg);
1593 return -ESRCH; 1603 retval = -ESRCH;
1604 goto out;
1594 } 1605 }
1595 rcu_assign_pointer(tsk->cgroups, newcg); 1606 rcu_assign_pointer(tsk->cgroups, newcg);
1596 task_unlock(tsk); 1607 task_unlock(tsk);
@@ -1616,7 +1627,22 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
1616 * is no longer empty. 1627 * is no longer empty.
1617 */ 1628 */
1618 cgroup_wakeup_rmdir_waiter(cgrp); 1629 cgroup_wakeup_rmdir_waiter(cgrp);
1619 return 0; 1630out:
1631 if (retval) {
1632 for_each_subsys(root, ss) {
1633 if (ss == failed_ss)
1634 /*
1635 * This subsystem was the one that failed the
1636 * can_attach() check earlier, so we don't need
1637 * to call cancel_attach() against it or any
1638 * remaining subsystems.
1639 */
1640 break;
1641 if (ss->cancel_attach)
1642 ss->cancel_attach(ss, cgrp, tsk, false);
1643 }
1644 }
1645 return retval;
1620} 1646}
1621 1647
1622/* 1648/*