Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 187204
b: refs/heads/master
c: 2468c72
h: refs/heads/master
v: v3
  • Loading branch information
Daisuke Nishimura authored and Linus Torvalds committed Mar 12, 2010
1 parent 3a6da55 commit 5c2aa93
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 9 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 5ce9f07bf1bed9a1f9886373ad0b149294f84c25
refs/heads/master: 2468c7234b366eeb799ee0648cb58f9cba394a54
13 changes: 12 additions & 1 deletion trunk/Documentation/cgroups/cgroups.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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*
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
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
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,
struct cgroup *old_cgrp, struct task_struct *task,
bool threadgroup)
Expand Down
2 changes: 2 additions & 0 deletions trunk/include/linux/cgroup.h
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,8 @@ struct cgroup_subsys {
void (*destroy)(struct cgroup_subsys *ss, struct cgroup *cgrp);
int (*can_attach)(struct cgroup_subsys *ss, struct cgroup *cgrp,
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,
struct cgroup *old_cgrp, struct task_struct *tsk,
bool threadgroup);
Expand Down
40 changes: 33 additions & 7 deletions trunk/kernel/cgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 retval = 0;
struct cgroup_subsys *ss;
struct cgroup_subsys *ss, *failed_ss = NULL;
struct cgroup *oldcgrp;
struct css_set *cg;
struct css_set *newcg;
Expand All @@ -1568,8 +1568,16 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
for_each_subsys(root, ss) {
if (ss->can_attach) {
retval = ss->can_attach(ss, cgrp, tsk, false);
if (retval)
return retval;
if (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;
}
}
}

Expand All @@ -1583,14 +1591,17 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
*/
newcg = find_css_set(cg, cgrp);
put_css_set(cg);
if (!newcg)
return -ENOMEM;
if (!newcg) {
retval = -ENOMEM;
goto out;
}

task_lock(tsk);
if (tsk->flags & PF_EXITING) {
task_unlock(tsk);
put_css_set(newcg);
return -ESRCH;
retval = -ESRCH;
goto out;
}
rcu_assign_pointer(tsk->cgroups, newcg);
task_unlock(tsk);
Expand All @@ -1616,7 +1627,22 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
* is no longer empty.
*/
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;
}

/*
Expand Down

0 comments on commit 5c2aa93

Please sign in to comment.