aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerge E. Hallyn <serue@us.ibm.com>2008-07-25 04:47:06 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-25 13:53:37 -0400
commite885dcde75685e09f23cffae1f6d5169c105b8a0 (patch)
tree711a91e83fad632c194700839d3e47631aee677a
parent856c13aa1ff6136c1968414fdea5938ea9d5ebf2 (diff)
cgroup_clone: use pid of newly created task for new cgroup
cgroup_clone creates a new cgroup with the pid of the task. This works correctly for unshare, but for clone cgroup_clone is called from copy_namespaces inside copy_process, which happens before the new pid is created. As a result, the new cgroup was created with current's pid. This patch: 1. Moves the call inside copy_process to after the new pid is created 2. Passes the struct pid into ns_cgroup_clone (as it is not yet attached to the task) 3. Passes a name from ns_cgroup_clone() into cgroup_clone() so as to keep cgroup_clone() itself simpler 4. Uses pid_vnr() to get the process id value, so that the pid used to name the new cgroup is always the pid as it would be known to the task which did the cloning or unsharing. I think that is the most intuitive thing to do. This way, task t1 does clone(CLONE_NEWPID) to get t2, which does clone(CLONE_NEWPID) to get t3, then the cgroup for t3 will be named for the pid by which t2 knows t3. (Thanks to Dan Smith for finding the main bug) Changelog: June 11: Incorporate Paul Menage's feedback: don't pass NULL to ns_cgroup_clone from unshare, and reduce patch size by using 'nodename' in cgroup_clone. June 10: Original version [akpm@linux-foundation.org: build fix] [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Serge Hallyn <serge@us.ibm.com> Acked-by: Paul Menage <menage@google.com> Tested-by: Dan Smith <danms@us.ibm.com> Cc: Balbir Singh <balbir@in.ibm.com> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--include/linux/cgroup.h3
-rw-r--r--include/linux/nsproxy.h7
-rw-r--r--kernel/cgroup.c7
-rw-r--r--kernel/fork.c6
-rw-r--r--kernel/ns_cgroup.c8
-rw-r--r--kernel/nsproxy.c8
6 files changed, 23 insertions, 16 deletions
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index cc59d3a21d87..c98dd7cb7076 100644
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -364,7 +364,8 @@ static inline struct cgroup* task_cgroup(struct task_struct *task,
364 return task_subsys_state(task, subsys_id)->cgroup; 364 return task_subsys_state(task, subsys_id)->cgroup;
365} 365}
366 366
367int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *ss); 367int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *ss,
368 char *nodename);
368 369
369/* A cgroup_iter should be treated as an opaque object */ 370/* A cgroup_iter should be treated as an opaque object */
370struct cgroup_iter { 371struct cgroup_iter {
diff --git a/include/linux/nsproxy.h b/include/linux/nsproxy.h
index 0e66b57631fc..c8a768e59640 100644
--- a/include/linux/nsproxy.h
+++ b/include/linux/nsproxy.h
@@ -82,9 +82,12 @@ static inline void get_nsproxy(struct nsproxy *ns)
82} 82}
83 83
84#ifdef CONFIG_CGROUP_NS 84#ifdef CONFIG_CGROUP_NS
85int ns_cgroup_clone(struct task_struct *tsk); 85int ns_cgroup_clone(struct task_struct *tsk, struct pid *pid);
86#else 86#else
87static inline int ns_cgroup_clone(struct task_struct *tsk) { return 0; } 87static inline int ns_cgroup_clone(struct task_struct *tsk, struct pid *pid)
88{
89 return 0;
90}
88#endif 91#endif
89 92
90#endif 93#endif
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 86b71e714e13..66ec9fd21e0c 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -2848,16 +2848,17 @@ void cgroup_exit(struct task_struct *tsk, int run_callbacks)
2848 * cgroup_clone - clone the cgroup the given subsystem is attached to 2848 * cgroup_clone - clone the cgroup the given subsystem is attached to
2849 * @tsk: the task to be moved 2849 * @tsk: the task to be moved
2850 * @subsys: the given subsystem 2850 * @subsys: the given subsystem
2851 * @nodename: the name for the new cgroup
2851 * 2852 *
2852 * Duplicate the current cgroup in the hierarchy that the given 2853 * Duplicate the current cgroup in the hierarchy that the given
2853 * subsystem is attached to, and move this task into the new 2854 * subsystem is attached to, and move this task into the new
2854 * child. 2855 * child.
2855 */ 2856 */
2856int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys) 2857int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys,
2858 char *nodename)
2857{ 2859{
2858 struct dentry *dentry; 2860 struct dentry *dentry;
2859 int ret = 0; 2861 int ret = 0;
2860 char nodename[MAX_CGROUP_TYPE_NAMELEN];
2861 struct cgroup *parent, *child; 2862 struct cgroup *parent, *child;
2862 struct inode *inode; 2863 struct inode *inode;
2863 struct css_set *cg; 2864 struct css_set *cg;
@@ -2882,8 +2883,6 @@ int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys)
2882 cg = tsk->cgroups; 2883 cg = tsk->cgroups;
2883 parent = task_cgroup(tsk, subsys->subsys_id); 2884 parent = task_cgroup(tsk, subsys->subsys_id);
2884 2885
2885 snprintf(nodename, MAX_CGROUP_TYPE_NAMELEN, "%d", tsk->pid);
2886
2887 /* Pin the hierarchy */ 2886 /* Pin the hierarchy */
2888 atomic_inc(&parent->root->sb->s_active); 2887 atomic_inc(&parent->root->sb->s_active);
2889 2888
diff --git a/kernel/fork.c b/kernel/fork.c
index 5a5d6fef341d..228f80c9155a 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1107,6 +1107,12 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1107 if (clone_flags & CLONE_THREAD) 1107 if (clone_flags & CLONE_THREAD)
1108 p->tgid = current->tgid; 1108 p->tgid = current->tgid;
1109 1109
1110 if (current->nsproxy != p->nsproxy) {
1111 retval = ns_cgroup_clone(p, pid);
1112 if (retval)
1113 goto bad_fork_free_pid;
1114 }
1115
1110 p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL; 1116 p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL;
1111 /* 1117 /*
1112 * Clear TID on mm_release()? 1118 * Clear TID on mm_release()?
diff --git a/kernel/ns_cgroup.c b/kernel/ns_cgroup.c
index 48d7ed6fc3a4..43c2111cd54d 100644
--- a/kernel/ns_cgroup.c
+++ b/kernel/ns_cgroup.c
@@ -7,6 +7,7 @@
7#include <linux/module.h> 7#include <linux/module.h>
8#include <linux/cgroup.h> 8#include <linux/cgroup.h>
9#include <linux/fs.h> 9#include <linux/fs.h>
10#include <linux/proc_fs.h>
10#include <linux/slab.h> 11#include <linux/slab.h>
11#include <linux/nsproxy.h> 12#include <linux/nsproxy.h>
12 13
@@ -24,9 +25,12 @@ static inline struct ns_cgroup *cgroup_to_ns(
24 struct ns_cgroup, css); 25 struct ns_cgroup, css);
25} 26}
26 27
27int ns_cgroup_clone(struct task_struct *task) 28int ns_cgroup_clone(struct task_struct *task, struct pid *pid)
28{ 29{
29 return cgroup_clone(task, &ns_subsys); 30 char name[PROC_NUMBUF];
31
32 snprintf(name, PROC_NUMBUF, "%d", pid_vnr(pid));
33 return cgroup_clone(task, &ns_subsys, name);
30} 34}
31 35
32/* 36/*
diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c
index adc785146a1c..21575fc46d05 100644
--- a/kernel/nsproxy.c
+++ b/kernel/nsproxy.c
@@ -157,12 +157,6 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk)
157 goto out; 157 goto out;
158 } 158 }
159 159
160 err = ns_cgroup_clone(tsk);
161 if (err) {
162 put_nsproxy(new_ns);
163 goto out;
164 }
165
166 tsk->nsproxy = new_ns; 160 tsk->nsproxy = new_ns;
167 161
168out: 162out:
@@ -209,7 +203,7 @@ int unshare_nsproxy_namespaces(unsigned long unshare_flags,
209 goto out; 203 goto out;
210 } 204 }
211 205
212 err = ns_cgroup_clone(current); 206 err = ns_cgroup_clone(current, task_pid(current));
213 if (err) 207 if (err)
214 put_nsproxy(*new_nsp); 208 put_nsproxy(*new_nsp);
215 209