lkml.org 
[lkml]   [2011]   [Oct]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[PATCH 1/2] cgroups: use sighand lock instead of tasklist_lock in cgroup_attach_proc
    Use sighand lock instead of tasklist_lock in cgroup_attach_proc.

    From: Ben Blum <bblum@andrew.cmu.edu>

    Signed-off-by: Ben Blum <bblum@andrew.cmu.edu>
    ---
    kernel/cgroup.c | 27 +++++++++++++--------------
    1 files changed, 13 insertions(+), 14 deletions(-)

    diff --git a/kernel/cgroup.c b/kernel/cgroup.c
    index 893fc3d..32fb4c8 100644
    --- a/kernel/cgroup.c
    +++ b/kernel/cgroup.c
    @@ -2003,6 +2003,7 @@ int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
    /* threadgroup list cursor and array */
    struct task_struct *tsk;
    struct flex_array *group;
    + unsigned long flags;
    /*
    * we need to make sure we have css_sets for all the tasks we're
    * going to move -before- we actually start moving them, so that in
    @@ -2029,20 +2030,18 @@ int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
    if (retval)
    goto out_free_group_list;

    - /* prevent changes to the threadgroup list while we take a snapshot. */
    - read_lock(&tasklist_lock);
    - if (!thread_group_leader(leader)) {
    - /*
    - * a race with de_thread from another thread's exec() may strip
    - * us of our leadership, making while_each_thread unsafe to use
    - * on this task. if this happens, there is no choice but to
    - * throw this task away and try again (from cgroup_procs_write);
    - * this is "double-double-toil-and-trouble-check locking".
    - */
    - read_unlock(&tasklist_lock);
    - retval = -EAGAIN;
    + /* prevent changes to the threadgroup list while we take a snapshot.
    + * If the leader exits, its links on the thread_group list become
    + * invalid. One way this can happen is if a sub-thread does exec() when
    + * de_thread() calls release_task(leader) (and leader->sighand gets set
    + * to NULL, in which case lock_task_sighand will fail). Since in that
    + * case the threadgroup is still around, cgroup_procs_write should try
    + * again (finding the new leader), which EAGAIN indicates here. This is
    + * double-double-toil-and-trouble-check locking". */
    + retval = -EAGAIN;
    + if (!lock_task_sighand(leader, &flags))
    goto out_free_group_list;
    - }
    +
    /* take a reference on each task in the group to go in the array. */
    tsk = leader;
    i = 0;
    @@ -2058,9 +2057,9 @@ int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
    BUG_ON(retval != 0);
    i++;
    } while_each_thread(leader, tsk);
    + unlock_task_sighand(leader, &flags);
    /* remember the number of threads in the array for later. */
    group_size = i;
    - read_unlock(&tasklist_lock);

    /*
    * step 1: check that we can legitimately attach to the cgroup.

    \
     
     \ /
      Last update: 2011-10-14 02:37    [W:0.025 / U:1.184 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site