aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/fork.c
diff options
context:
space:
mode:
authorPavel Emelyanov <xemul@openvz.org>2007-10-19 02:40:10 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-19 14:53:39 -0400
commit30e49c263e36341b60b735cbef5ca37912549264 (patch)
tree103e74c41db97476ae38cdd4ffc18e4da03f28e8 /kernel/fork.c
parentb461cc03828c743aed6b3855b9ab0d39a9d54ec5 (diff)
pid namespaces: allow cloning of new namespace
When clone() is invoked with CLONE_NEWPID, create a new pid namespace and then create a new struct pid for the new process. Allocate pid_t's for the new process in the new pid namespace and all ancestor pid namespaces. Make the newly cloned process the session and process group leader. Since the active pid namespace is special and expected to be the first entry in pid->upid_list, preserve the order of pid namespaces. The size of 'struct pid' is dependent on the the number of pid namespaces the process exists in, so we use multiple pid-caches'. Only one pid cache is created during system startup and this used by processes that exist only in init_pid_ns. When a process clones its pid namespace, we create additional pid caches as necessary and use the pid cache to allocate 'struct pids' for that depth. Note, that with this patch the newly created namespace won't work, since the rest of the kernel still uses global pids, but this is to be fixed soon. Init pid namespace still works. [oleg@tv-sign.ru: merge fix] Signed-off-by: Pavel Emelyanov <xemul@openvz.org> Signed-off-by: Sukadev Bhattiprolu <sukadev@us.ibm.com> Cc: Paul Menage <menage@google.com> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Oleg Nesterov <oleg@tv-sign.ru> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/fork.c')
-rw-r--r--kernel/fork.c43
1 files changed, 28 insertions, 15 deletions
diff --git a/kernel/fork.c b/kernel/fork.c
index bab34192799..f252784f933 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -973,7 +973,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
973 unsigned long stack_start, 973 unsigned long stack_start,
974 struct pt_regs *regs, 974 struct pt_regs *regs,
975 unsigned long stack_size, 975 unsigned long stack_size,
976 int __user *parent_tidptr,
977 int __user *child_tidptr, 976 int __user *child_tidptr,
978 struct pid *pid) 977 struct pid *pid)
979{ 978{
@@ -1043,11 +1042,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1043 p->did_exec = 0; 1042 p->did_exec = 0;
1044 delayacct_tsk_init(p); /* Must remain after dup_task_struct() */ 1043 delayacct_tsk_init(p); /* Must remain after dup_task_struct() */
1045 copy_flags(clone_flags, p); 1044 copy_flags(clone_flags, p);
1046 retval = -EFAULT;
1047 if (clone_flags & CLONE_PARENT_SETTID)
1048 if (put_user(p->pid, parent_tidptr))
1049 goto bad_fork_cleanup_delays_binfmt;
1050
1051 INIT_LIST_HEAD(&p->children); 1045 INIT_LIST_HEAD(&p->children);
1052 INIT_LIST_HEAD(&p->sibling); 1046 INIT_LIST_HEAD(&p->sibling);
1053 p->vfork_done = NULL; 1047 p->vfork_done = NULL;
@@ -1289,11 +1283,22 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1289 __ptrace_link(p, current->parent); 1283 __ptrace_link(p, current->parent);
1290 1284
1291 if (thread_group_leader(p)) { 1285 if (thread_group_leader(p)) {
1292 p->signal->tty = current->signal->tty; 1286 if (clone_flags & CLONE_NEWPID) {
1293 p->signal->pgrp = task_pgrp_nr(current); 1287 p->nsproxy->pid_ns->child_reaper = p;
1294 set_task_session(p, task_session_nr(current)); 1288 p->signal->tty = NULL;
1295 attach_pid(p, PIDTYPE_PGID, task_pgrp(current)); 1289 p->signal->pgrp = p->pid;
1296 attach_pid(p, PIDTYPE_SID, task_session(current)); 1290 set_task_session(p, p->pid);
1291 attach_pid(p, PIDTYPE_PGID, pid);
1292 attach_pid(p, PIDTYPE_SID, pid);
1293 } else {
1294 p->signal->tty = current->signal->tty;
1295 p->signal->pgrp = task_pgrp_nr(current);
1296 set_task_session(p, task_session_nr(current));
1297 attach_pid(p, PIDTYPE_PGID,
1298 task_pgrp(current));
1299 attach_pid(p, PIDTYPE_SID,
1300 task_session(current));
1301 }
1297 1302
1298 list_add_tail_rcu(&p->tasks, &init_task.tasks); 1303 list_add_tail_rcu(&p->tasks, &init_task.tasks);
1299 __get_cpu_var(process_counts)++; 1304 __get_cpu_var(process_counts)++;
@@ -1339,7 +1344,6 @@ bad_fork_cleanup_policy:
1339bad_fork_cleanup_cgroup: 1344bad_fork_cleanup_cgroup:
1340#endif 1345#endif
1341 cgroup_exit(p, cgroup_callbacks_done); 1346 cgroup_exit(p, cgroup_callbacks_done);
1342bad_fork_cleanup_delays_binfmt:
1343 delayacct_tsk_free(p); 1347 delayacct_tsk_free(p);
1344 if (p->binfmt) 1348 if (p->binfmt)
1345 module_put(p->binfmt->module); 1349 module_put(p->binfmt->module);
@@ -1366,7 +1370,7 @@ struct task_struct * __cpuinit fork_idle(int cpu)
1366 struct task_struct *task; 1370 struct task_struct *task;
1367 struct pt_regs regs; 1371 struct pt_regs regs;
1368 1372
1369 task = copy_process(CLONE_VM, 0, idle_regs(&regs), 0, NULL, NULL, 1373 task = copy_process(CLONE_VM, 0, idle_regs(&regs), 0, NULL,
1370 &init_struct_pid); 1374 &init_struct_pid);
1371 if (!IS_ERR(task)) 1375 if (!IS_ERR(task))
1372 init_idle(task, cpu); 1376 init_idle(task, cpu);
@@ -1414,7 +1418,7 @@ long do_fork(unsigned long clone_flags,
1414 } 1418 }
1415 1419
1416 p = copy_process(clone_flags, stack_start, regs, stack_size, 1420 p = copy_process(clone_flags, stack_start, regs, stack_size,
1417 parent_tidptr, child_tidptr, NULL); 1421 child_tidptr, NULL);
1418 /* 1422 /*
1419 * Do this prior waking up the new thread - the thread pointer 1423 * Do this prior waking up the new thread - the thread pointer
1420 * might get invalid after that point, if the thread exits quickly. 1424 * might get invalid after that point, if the thread exits quickly.
@@ -1422,7 +1426,16 @@ long do_fork(unsigned long clone_flags,
1422 if (!IS_ERR(p)) { 1426 if (!IS_ERR(p)) {
1423 struct completion vfork; 1427 struct completion vfork;
1424 1428
1425 nr = pid_nr(task_pid(p)); 1429 /*
1430 * this is enough to call pid_nr_ns here, but this if
1431 * improves optimisation of regular fork()
1432 */
1433 nr = (clone_flags & CLONE_NEWPID) ?
1434 task_pid_nr_ns(p, current->nsproxy->pid_ns) :
1435 task_pid_vnr(p);
1436
1437 if (clone_flags & CLONE_PARENT_SETTID)
1438 put_user(nr, parent_tidptr);
1426 1439
1427 if (clone_flags & CLONE_VFORK) { 1440 if (clone_flags & CLONE_VFORK) {
1428 p->vfork_done = &vfork; 1441 p->vfork_done = &vfork;