aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--Documentation/cgroups/cgroups.txt13
-rw-r--r--include/linux/cgroup.h2
-rw-r--r--kernel/cgroup.c40
3 files changed, 47 insertions, 8 deletions
diff --git a/Documentation/cgroups/cgroups.txt b/Documentation/cgroups/cgroups.txt
index 0b33bfe7dde9..d45082653e3d 100644
--- a/Documentation/cgroups/cgroups.txt
+++ b/Documentation/cgroups/cgroups.txt
@@ -536,10 +536,21 @@ returns an error, this will abort the attach operation. If a NULL
536task is passed, then a successful result indicates that *any* 536task is passed, then a successful result indicates that *any*
537unspecified task can be moved into the cgroup. Note that this isn't 537unspecified task can be moved into the cgroup. Note that this isn't
538called on a fork. If this method returns 0 (success) then this should 538called on a fork. If this method returns 0 (success) then this should
539remain valid while the caller holds cgroup_mutex. If threadgroup is 539remain valid while the caller holds cgroup_mutex and it is ensured that either
540attach() or cancel_attach() will be called in future. If threadgroup is
540true, then a successful result indicates that all threads in the given 541true, then a successful result indicates that all threads in the given
541thread's threadgroup can be moved together. 542thread's threadgroup can be moved together.
542 543
544void cancel_attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
545 struct task_struct *task, bool threadgroup)
546(cgroup_mutex held by caller)
547
548Called when a task attach operation has failed after can_attach() has succeeded.
549A subsystem whose can_attach() has some side-effects should provide this
550function, so that the subsytem can implement a rollback. If not, not necessary.
551This will be called only about subsystems whose can_attach() operation have
552succeeded.
553
543void attach(struct cgroup_subsys *ss, struct cgroup *cgrp, 554void attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
544 struct cgroup *old_cgrp, struct task_struct *task, 555 struct cgroup *old_cgrp, struct task_struct *task,
545 bool threadgroup) 556 bool threadgroup)
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index c9bbcb2a75ae..d08cfe7e12e5 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -428,6 +428,8 @@ struct cgroup_subsys {
428 void (*destroy)(struct cgroup_subsys *ss, struct cgroup *cgrp); 428 void (*destroy)(struct cgroup_subsys *ss, struct cgroup *cgrp);
429 int (*can_attach)(struct cgroup_subsys *ss, struct cgroup *cgrp, 429 int (*can_attach)(struct cgroup_subsys *ss, struct cgroup *cgrp,
430 struct task_struct *tsk, bool threadgroup); 430 struct task_struct *tsk, bool threadgroup);
431 void (*cancel_attach)(struct cgroup_subsys *ss, struct cgroup *cgrp,
432 struct task_struct *tsk, bool threadgroup);
431 void (*attach)(struct cgroup_subsys *ss, struct cgroup *cgrp, 433 void (*attach)(struct cgroup_subsys *ss, struct cgroup *cgrp,
432 struct cgroup *old_cgrp, struct task_struct *tsk, 434 struct cgroup *old_cgrp, struct task_struct *tsk,
433 bool threadgroup); 435 bool threadgroup);
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/*