Commit 2468c723 authored by Daisuke Nishimura's avatar Daisuke Nishimura Committed by Linus Torvalds

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: default avatarDaisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
Acked-by: default avatarLi Zefan <lizf@cn.fujitsu.com>
Reviewed-by: default avatarPaul Menage <menage@google.com>
Cc: Balbir Singh <balbir@linux.vnet.ibm.com>
Acked-by: default avatarKAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 5ce9f07b
...@@ -536,10 +536,21 @@ returns an error, this will abort the attach operation. If a NULL ...@@ -536,10 +536,21 @@ returns an error, this will abort the attach operation. If a NULL
task is passed, then a successful result indicates that *any* task is passed, then a successful result indicates that *any*
unspecified task can be moved into the cgroup. Note that this isn't unspecified task can be moved into the cgroup. Note that this isn't
called on a fork. If this method returns 0 (success) then this should called on a fork. If this method returns 0 (success) then this should
remain valid while the caller holds cgroup_mutex. If threadgroup is remain valid while the caller holds cgroup_mutex and it is ensured that either
attach() or cancel_attach() will be called in future. If threadgroup is
true, then a successful result indicates that all threads in the given true, then a successful result indicates that all threads in the given
thread's threadgroup can be moved together. thread's threadgroup can be moved together.
void cancel_attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
struct task_struct *task, bool threadgroup)
(cgroup_mutex held by caller)
Called when a task attach operation has failed after can_attach() has succeeded.
A subsystem whose can_attach() has some side-effects should provide this
function, so that the subsytem can implement a rollback. If not, not necessary.
This will be called only about subsystems whose can_attach() operation have
succeeded.
void attach(struct cgroup_subsys *ss, struct cgroup *cgrp, void attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
struct cgroup *old_cgrp, struct task_struct *task, struct cgroup *old_cgrp, struct task_struct *task,
bool threadgroup) bool threadgroup)
......
...@@ -428,6 +428,8 @@ struct cgroup_subsys { ...@@ -428,6 +428,8 @@ struct cgroup_subsys {
void (*destroy)(struct cgroup_subsys *ss, struct cgroup *cgrp); void (*destroy)(struct cgroup_subsys *ss, struct cgroup *cgrp);
int (*can_attach)(struct cgroup_subsys *ss, struct cgroup *cgrp, int (*can_attach)(struct cgroup_subsys *ss, struct cgroup *cgrp,
struct task_struct *tsk, bool threadgroup); struct task_struct *tsk, bool threadgroup);
void (*cancel_attach)(struct cgroup_subsys *ss, struct cgroup *cgrp,
struct task_struct *tsk, bool threadgroup);
void (*attach)(struct cgroup_subsys *ss, struct cgroup *cgrp, void (*attach)(struct cgroup_subsys *ss, struct cgroup *cgrp,
struct cgroup *old_cgrp, struct task_struct *tsk, struct cgroup *old_cgrp, struct task_struct *tsk,
bool threadgroup); bool threadgroup);
......
...@@ -1554,7 +1554,7 @@ int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen) ...@@ -1554,7 +1554,7 @@ int cgroup_path(const struct cgroup *cgrp, char *buf, int buflen)
int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk) int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
{ {
int retval = 0; int retval = 0;
struct cgroup_subsys *ss; struct cgroup_subsys *ss, *failed_ss = NULL;
struct cgroup *oldcgrp; struct cgroup *oldcgrp;
struct css_set *cg; struct css_set *cg;
struct css_set *newcg; struct css_set *newcg;
...@@ -1568,8 +1568,16 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk) ...@@ -1568,8 +1568,16 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
for_each_subsys(root, ss) { for_each_subsys(root, ss) {
if (ss->can_attach) { if (ss->can_attach) {
retval = ss->can_attach(ss, cgrp, tsk, false); retval = ss->can_attach(ss, cgrp, tsk, false);
if (retval) if (retval) {
return retval; /*
* Remember on which subsystem the can_attach()
* failed, so that we only call cancel_attach()
* against the subsystems whose can_attach()
* succeeded. (See below)
*/
failed_ss = ss;
goto out;
}
} }
} }
...@@ -1583,14 +1591,17 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk) ...@@ -1583,14 +1591,17 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
*/ */
newcg = find_css_set(cg, cgrp); newcg = find_css_set(cg, cgrp);
put_css_set(cg); put_css_set(cg);
if (!newcg) if (!newcg) {
return -ENOMEM; retval = -ENOMEM;
goto out;
}
task_lock(tsk); task_lock(tsk);
if (tsk->flags & PF_EXITING) { if (tsk->flags & PF_EXITING) {
task_unlock(tsk); task_unlock(tsk);
put_css_set(newcg); put_css_set(newcg);
return -ESRCH; retval = -ESRCH;
goto out;
} }
rcu_assign_pointer(tsk->cgroups, newcg); rcu_assign_pointer(tsk->cgroups, newcg);
task_unlock(tsk); task_unlock(tsk);
...@@ -1616,7 +1627,22 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk) ...@@ -1616,7 +1627,22 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
* is no longer empty. * is no longer empty.
*/ */
cgroup_wakeup_rmdir_waiter(cgrp); cgroup_wakeup_rmdir_waiter(cgrp);
return 0; out:
if (retval) {
for_each_subsys(root, ss) {
if (ss == failed_ss)
/*
* This subsystem was the one that failed the
* can_attach() check earlier, so we don't need
* to call cancel_attach() against it or any
* remaining subsystems.
*/
break;
if (ss->cancel_attach)
ss->cancel_attach(ss, cgrp, tsk, false);
}
}
return retval;
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment