cgroup: remove synchronize_rcu() from cgroup_attach_{task|proc}()
PATCH 1/2 cgroup: remove synchronize_rcu() from cgroup_attach_{task|proc}()
These 2 syncronize_rcu()s make attaching a task to a cgroup quite slow, and it can't be ignored in some situations.
A real case from Colin Cross: Android uses cgroups heavily to manage thread priorities, putting threads in a background group with reduced cpu.shares when they are not visible to the user, and in a foreground group when they are. Some RPCs from foreground threads to background threads will temporarily move the background thread into the foreground group for the duration of the RPC. This results in many calls to cgroup_attach_task.
In cgroup_attach_task() it's task->cgroups that is protected by RCU, and put_css_set() calls kfree_rcu() to free it.
If we remove this synchronize_rcu(), there can be threads in RCU-read sections accessing their old cgroup via current->cgroups with concurrent rmdir operation, but this is safe.
# time for ((i=0; i<50; i++)) { echo $$ > /mnt/sub/tasks; echo $$ > /mnt/tasks; }real 0m2.524s user 0m0.008s sys 0m0.004s
With this patch:
real 0m0.004s user 0m0.004s sys 0m0.000s
--- kernel/cgroup.c | 2 -- 1 file changed, 2 deletions(-)
kernel/cgroup.c +0 -2
@@ -1974,7 +1974,6 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk) ss->attach (cgrp, &tset); } -synchronize_rcu (); out:if (retval) {for_each_subsys (root, ss) {
@@ -2143,7 +2142,6 @@ static int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)/* * step 5: success! and cleanup */ -synchronize_rcu (); retval =0 ; out_put_css_set_refs:if (retval) {
Signature · 1 line
1.8.0.2
PATCH 2/2 cgroup: remove synchronize_rcu() from rebind_subsystems()
Nothing's protected by RCU in rebind_subsystems(), and I can't think of a reason why it is needed.
--- kernel/cgroup.c | 1 - 1 file changed, 1 deletion(-)
kernel/cgroup.c +0 -1
@@ -1079,7 +1079,6 @@ static int rebind_subsystems(struct cgroupfs_root *root, } } root->subsys_mask = root->actual_subsys_mask = final_subsys_mask; -synchronize_rcu ();return 0 ; }
Signature · 1 line
1.8.0.2
Re: [PATCH 2/2] cgroup: remove synchronize_rcu() from rebind_subsystems()
Quoted 4 lines · Li Zefan
Nothing's protected by RCU in
rebind_subsystems(), and I can't think of a reason why it is needed.Signed-off-by Li Zefan <[email protected]>
Applied to cgroup/for-3.9. We probably should synchornize_rcu() from cgroup_diput() too. Probably by punting css_free() and cgrp freeing to a work item from call_rcu() callback.
Thanks.
Signature · 1 line
tejun
Tejun Heo
maintainerRe: [PATCH 2/2] cgroup: remove synchronize_rcu() from rebind_subsystems()
Quoted 7 lines · Tejun Heo
Quoted 4 lines · Li Zefan
Nothing's protected by RCU in
rebind_subsystems(), and I can't think of a reason why it is needed.Signed-off-by Li Zefan <[email protected]>Applied to cgroup/for-3.9. We probably should
synchornize_rcu()from
^ remove
Quoted 2 lines
cgroup_diput()too. Probably by puntingcss_free()and cgrp freeing to a work item fromcall_rcu()callback.
Signature · 1 line
tejun
Tejun Heo
maintainerHey, Li.
Quoted 11 lines · Li Zefan
These 2 syncronize_rcu()s make attaching a task to a cgroup quite slow, and it can't be ignored in some situations.
A real case from Colin Cross: Android uses cgroups heavily to manage thread priorities, putting threads in a background group with reduced cpu.shares when they are not visible to the user, and in a foreground group when they are. Some RPCs from foreground threads to background threads will temporarily move the background thread into the foreground group for the duration of the RPC. This results in many calls to
cgroup_attach_task.
Quoted 6 lines
In
cgroup_attach_task()it'stask->cgroupsthat is protected by RCU, andput_css_set()callskfree_rcu()to free it.If we remove this
synchronize_rcu(), there can be threads in RCU-read sections accessing their old cgroup viacurrent->cgroupswith concurrent rmdir operation, but this is safe.
Yeah, these synchronize_rcu()s are utterly confused. synchornize_rcu() necessarily have to come between two operations to guarantee that the changes made before it are visible to all rcu readers before proceeding beyond it. Here, synchornize_rcu() are at the end of attach operations with nothing beyond it. Duh.... its only effect would be delaying completion of write(2) to sysfs tasks/procs files until all rcu readers see the change, which is utterly irrelevant. It doesn't mean anything.
Applying to cgroup/for-3.9.
Thanks.
Signature · 1 line
tejun