Linux Container Development
 help / color / mirror / Atom feed
  • [parent not found: <20111222225102.GM17084@google.com>]
  • * [PATCH 1/2] cgroup: remove tasklist_lock from cgroup_attach_proc
    @ 2011-12-23  2:52 Mandeep Singh Baines
      0 siblings, 0 replies; 7+ messages in thread
    From: Mandeep Singh Baines @ 2011-12-23  2:52 UTC (permalink / raw)
      To: Li Zefan, Frederic Weisbecker,
    	linux-kernel-u79uwXL29TY76Z2rM5mHXA
      Cc: Mandeep Singh Baines, Oleg Nesterov, Paul Menage, Tejun Heo,
    	cgroups-u79uwXL29TY76Z2rM5mHXA, Andrew Morton,
    	containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
    
    Since cgroup_attach_proc is protected by a threadgroup_lock, we
    no longer need a tasklist_lock to protect while_each_thread.
    To keep the complexity of the double-check locking in one place,
    I also moved the thread_group_leader check up into
    attach_task_by_pid. This allows us to use a goto instead of
    returning -EAGAIN.
    
    While at it, also converted a couple of returns to gotos.
    
    Changes in V2:
    * https://lkml.org/lkml/2011/12/22/86 (Tejun Heo)
      * Use a goto instead of returning -EAGAIN
    
    Suggested-by: Frederic Weisbecker <fweisbec-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
    Signed-off-by: Mandeep Singh Baines <msb-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
    Cc: Tejun Heo <tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
    Cc: Li Zefan <lizf-BthXqXjhjHXQFUHtdCDX3A@public.gmane.org>
    Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org
    Cc: cgroups-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
    Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu-+CUm20s59erQFUHtdCDX3A@public.gmane.org>
    Cc: Oleg Nesterov <oleg-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
    Cc: Andrew Morton <akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
    Cc: Paul Menage <paul-inf54ven1CmVyaH7bEyXVA@public.gmane.org>
    ---
     kernel/cgroup.c |   72 ++++++++++++++++++------------------------------------
     1 files changed, 24 insertions(+), 48 deletions(-)
    
    diff --git a/kernel/cgroup.c b/kernel/cgroup.c
    index 1042b3c..625526b 100644
    --- a/kernel/cgroup.c
    +++ b/kernel/cgroup.c
    @@ -2102,21 +2102,6 @@ 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;
    -		goto out_free_group_list;
    -	}
    -
     	tsk = leader;
     	i = 0;
     	do {
    @@ -2145,7 +2130,6 @@ int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
     	group_size = i;
     	tset.tc_array = group;
     	tset.tc_array_len = group_size;
    -	read_unlock(&tasklist_lock);
     
     	/* methods shouldn't be called if no task is actually migrating */
     	retval = 0;
    @@ -2242,22 +2226,14 @@ static int attach_task_by_pid(struct cgroup *cgrp, u64 pid, bool threadgroup)
     	if (!cgroup_lock_live_group(cgrp))
     		return -ENODEV;
     
    +retry_find_task:
     	if (pid) {
     		rcu_read_lock();
     		tsk = find_task_by_vpid(pid);
     		if (!tsk) {
     			rcu_read_unlock();
    -			cgroup_unlock();
    -			return -ESRCH;
    -		}
    -		if (threadgroup) {
    -			/*
    -			 * RCU protects this access, since tsk was found in the
    -			 * tid map. a race with de_thread may cause group_leader
    -			 * to stop being the leader, but cgroup_attach_proc will
    -			 * detect it later.
    -			 */
    -			tsk = tsk->group_leader;
    +			ret= -ESRCH;
    +			goto out_unlock_cgroup;
     		}
     		/*
     		 * even if we're attaching all tasks in the thread group, we
    @@ -2268,29 +2244,38 @@ static int attach_task_by_pid(struct cgroup *cgrp, u64 pid, bool threadgroup)
     		    cred->euid != tcred->uid &&
     		    cred->euid != tcred->suid) {
     			rcu_read_unlock();
    -			cgroup_unlock();
    -			return -EACCES;
    +			ret = -EACCES;
    +			goto out_unlock_cgroup;
     		}
     		get_task_struct(tsk);
     		rcu_read_unlock();
     	} else {
    -		if (threadgroup)
    -			tsk = current->group_leader;
    -		else
    -			tsk = current;
    +		tsk = current;
     		get_task_struct(tsk);
     	}
     
     	threadgroup_lock(tsk);
    -
    -	if (threadgroup)
    -		ret = cgroup_attach_proc(cgrp, tsk);
    -	else
    +	if (threadgroup) {
    +		struct task_struct *leader = tsk->group_leader;
    +		if (!thread_group_leader(leader)) {
    +			/*
    +			 * a race with de_thread from another thread's exec()
    +			 * may strip us of our leadership, if this happens,
    +			 * there is no choice but to throw this task away and
    +			 * try again; this is
    +			 * "double-double-toil-and-trouble-check locking".
    +			 */
    +			threadgroup_unlock(tsk);
    +			put_task_struct(tsk);
    +			goto retry_find_task;
    +		}
    +		ret = cgroup_attach_proc(cgrp, leader);
    +	} else
     		ret = cgroup_attach_task(cgrp, tsk);
    -
     	threadgroup_unlock(tsk);
     
     	put_task_struct(tsk);
    +out_unlock_cgroup:
     	cgroup_unlock();
     	return ret;
     }
    @@ -2302,16 +2287,7 @@ static int cgroup_tasks_write(struct cgroup *cgrp, struct cftype *cft, u64 pid)
     
     static int cgroup_procs_write(struct cgroup *cgrp, struct cftype *cft, u64 tgid)
     {
    -	int ret;
    -	do {
    -		/*
    -		 * attach_proc fails with -EAGAIN if threadgroup leadership
    -		 * changes in the middle of the operation, in which case we need
    -		 * to find the task_struct for the new leader and start over.
    -		 */
    -		ret = attach_task_by_pid(cgrp, tgid, true);
    -	} while (ret == -EAGAIN);
    -	return ret;
    +	return attach_task_by_pid(cgrp, tgid, true);
     }
     
     /**
    -- 
    1.7.3.1
    
    ^ permalink raw reply related	[flat|nested] 7+ messages in thread
    * [PATCH 1/2] cgroup: remove tasklist_lock from cgroup_attach_proc
    @ 2011-12-22 22:26 Mandeep Singh Baines
      0 siblings, 0 replies; 7+ messages in thread
    From: Mandeep Singh Baines @ 2011-12-22 22:26 UTC (permalink / raw)
      To: Li Zefan, Frederic Weisbecker,
    	linux-kernel-u79uwXL29TY76Z2rM5mHXA
      Cc: Mandeep Singh Baines, Oleg Nesterov, Paul Menage, Tejun Heo,
    	cgroups-u79uwXL29TY76Z2rM5mHXA, Andrew Morton,
    	containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
    
    Since cgroup_attach_proc is protected by a threadgroup_lock, we
    no longer need a tasklist_lock to protect while_each_thread.
    To keep the complexity of the double-check locking in one place,
    I also moved the thread_group_leader check up into
    attach_task_by_pid.
    
    While at it, also converted a couple of returns to gotos.
    
    The suggestion was made here:
    
    https://lkml.org/lkml/2011/12/22/86
    
    Suggested-by: Frederic Weisbecker <fweisbec-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
    Signed-off-by: Mandeep Singh Baines <msb-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
    Cc: Tejun Heo <tj-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
    Cc: Li Zefan <lizf-BthXqXjhjHXQFUHtdCDX3A@public.gmane.org>
    Cc: containers-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org
    Cc: cgroups-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
    Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu-+CUm20s59erQFUHtdCDX3A@public.gmane.org>
    Cc: Oleg Nesterov <oleg-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
    Cc: Andrew Morton <akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
    Cc: Paul Menage <paul-inf54ven1CmVyaH7bEyXVA@public.gmane.org>
    ---
     kernel/cgroup.c |   52 +++++++++++++++++++++-------------------------------
     1 files changed, 21 insertions(+), 31 deletions(-)
    
    diff --git a/kernel/cgroup.c b/kernel/cgroup.c
    index 1042b3c..032139d 100644
    --- a/kernel/cgroup.c
    +++ b/kernel/cgroup.c
    @@ -2102,21 +2102,6 @@ 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;
    -		goto out_free_group_list;
    -	}
    -
     	tsk = leader;
     	i = 0;
     	do {
    @@ -2145,7 +2130,6 @@ int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
     	group_size = i;
     	tset.tc_array = group;
     	tset.tc_array_len = group_size;
    -	read_unlock(&tasklist_lock);
     
     	/* methods shouldn't be called if no task is actually migrating */
     	retval = 0;
    @@ -2247,18 +2231,12 @@ static int attach_task_by_pid(struct cgroup *cgrp, u64 pid, bool threadgroup)
     		tsk = find_task_by_vpid(pid);
     		if (!tsk) {
     			rcu_read_unlock();
    -			cgroup_unlock();
    -			return -ESRCH;
    +			ret= -ESRCH;
    +			goto out_unlock_cgroup;
     		}
    -		if (threadgroup) {
    -			/*
    -			 * RCU protects this access, since tsk was found in the
    -			 * tid map. a race with de_thread may cause group_leader
    -			 * to stop being the leader, but cgroup_attach_proc will
    -			 * detect it later.
    -			 */
    +		/* we check later for a group_leader race with de_thread */
    +		if (threadgroup)
     			tsk = tsk->group_leader;
    -		}
     		/*
     		 * even if we're attaching all tasks in the thread group, we
     		 * only need to check permissions on one of them.
    @@ -2268,8 +2246,8 @@ static int attach_task_by_pid(struct cgroup *cgrp, u64 pid, bool threadgroup)
     		    cred->euid != tcred->uid &&
     		    cred->euid != tcred->suid) {
     			rcu_read_unlock();
    -			cgroup_unlock();
    -			return -EACCES;
    +			ret = -EACCES;
    +			goto out_unlock_cgroup;
     		}
     		get_task_struct(tsk);
     		rcu_read_unlock();
    @@ -2283,14 +2261,26 @@ static int attach_task_by_pid(struct cgroup *cgrp, u64 pid, bool threadgroup)
     
     	threadgroup_lock(tsk);
     
    -	if (threadgroup)
    +	if (threadgroup) {
    +		if (!thread_group_leader(tsk)) {
    +			/*
    +			 * a race with de_thread from another thread's exec()
    +			 * may strip us of our leadership, 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".
    +			 */
    +			ret = -EAGAIN;
    +			goto out_unlock_threadgroup;
    +		}
     		ret = cgroup_attach_proc(cgrp, tsk);
    -	else
    +	} else
     		ret = cgroup_attach_task(cgrp, tsk);
     
    +out_unlock_threadgroup:
     	threadgroup_unlock(tsk);
    -
     	put_task_struct(tsk);
    +out_unlock_cgroup:
     	cgroup_unlock();
     	return ret;
     }
    -- 
    1.7.3.1
    
    ^ permalink raw reply related	[flat|nested] 7+ messages in thread

    end of thread, other threads:[~2011-12-23  2:52 UTC | newest]
    
    Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
    -- links below jump to the message on this page --
         [not found] <1324592816-13792-1-git-send-email-msb@chromium.org>
         [not found] ` <1324592816-13792-1-git-send-email-msb-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
    2011-12-22 22:26   ` [PATCH 2/2] cgroup: remove extra calls to find_existing_css_set Mandeep Singh Baines
         [not found]     ` <1324592816-13792-2-git-send-email-msb-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
    2011-12-22 23:12       ` Tejun Heo
         [not found]     ` <20111222231203.GO17084@google.com>
         [not found]       ` <20111222231203.GO17084-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
    2011-12-23  0:29         ` Mandeep Singh Baines
    2011-12-22 22:51   ` [PATCH 1/2] cgroup: remove tasklist_lock from cgroup_attach_proc Tejun Heo
         [not found] ` <20111222225102.GM17084@google.com>
         [not found]   ` <20111222225102.GM17084-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
    2011-12-23  0:58     ` Mandeep Singh Baines
    2011-12-23  2:52 Mandeep Singh Baines
      -- strict thread matches above, loose matches on Subject: below --
    2011-12-22 22:26 Mandeep Singh Baines
    

    This is a public inbox, see mirroring instructions
    for how to clone and mirror all data and code used for this inbox