aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/fork.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/fork.c')
-rw-r--r--kernel/fork.c56
1 files changed, 33 insertions, 23 deletions
diff --git a/kernel/fork.c b/kernel/fork.c
index 4c14942a0ee3..98b450876f93 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -165,6 +165,18 @@ void free_task(struct task_struct *tsk)
165} 165}
166EXPORT_SYMBOL(free_task); 166EXPORT_SYMBOL(free_task);
167 167
168static inline void free_signal_struct(struct signal_struct *sig)
169{
170 taskstats_tgid_free(sig);
171 kmem_cache_free(signal_cachep, sig);
172}
173
174static inline void put_signal_struct(struct signal_struct *sig)
175{
176 if (atomic_dec_and_test(&sig->sigcnt))
177 free_signal_struct(sig);
178}
179
168void __put_task_struct(struct task_struct *tsk) 180void __put_task_struct(struct task_struct *tsk)
169{ 181{
170 WARN_ON(!tsk->exit_state); 182 WARN_ON(!tsk->exit_state);
@@ -173,6 +185,7 @@ void __put_task_struct(struct task_struct *tsk)
173 185
174 exit_creds(tsk); 186 exit_creds(tsk);
175 delayacct_tsk_free(tsk); 187 delayacct_tsk_free(tsk);
188 put_signal_struct(tsk->signal);
176 189
177 if (!profile_handoff_task(tsk)) 190 if (!profile_handoff_task(tsk))
178 free_task(tsk); 191 free_task(tsk);
@@ -864,8 +877,9 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
864 if (!sig) 877 if (!sig)
865 return -ENOMEM; 878 return -ENOMEM;
866 879
867 atomic_set(&sig->count, 1); 880 sig->nr_threads = 1;
868 atomic_set(&sig->live, 1); 881 atomic_set(&sig->live, 1);
882 atomic_set(&sig->sigcnt, 1);
869 init_waitqueue_head(&sig->wait_chldexit); 883 init_waitqueue_head(&sig->wait_chldexit);
870 if (clone_flags & CLONE_NEWPID) 884 if (clone_flags & CLONE_NEWPID)
871 sig->flags |= SIGNAL_UNKILLABLE; 885 sig->flags |= SIGNAL_UNKILLABLE;
@@ -885,22 +899,16 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
885 tty_audit_fork(sig); 899 tty_audit_fork(sig);
886 900
887 sig->oom_adj = current->signal->oom_adj; 901 sig->oom_adj = current->signal->oom_adj;
902 sig->oom_score_adj = current->signal->oom_score_adj;
888 903
889 return 0; 904 return 0;
890} 905}
891 906
892void __cleanup_signal(struct signal_struct *sig)
893{
894 thread_group_cputime_free(sig);
895 tty_kref_put(sig->tty);
896 kmem_cache_free(signal_cachep, sig);
897}
898
899static void copy_flags(unsigned long clone_flags, struct task_struct *p) 907static void copy_flags(unsigned long clone_flags, struct task_struct *p)
900{ 908{
901 unsigned long new_flags = p->flags; 909 unsigned long new_flags = p->flags;
902 910
903 new_flags &= ~PF_SUPERPRIV; 911 new_flags &= ~(PF_SUPERPRIV | PF_WQ_WORKER);
904 new_flags |= PF_FORKNOEXEC; 912 new_flags |= PF_FORKNOEXEC;
905 new_flags |= PF_STARTING; 913 new_flags |= PF_STARTING;
906 p->flags = new_flags; 914 p->flags = new_flags;
@@ -1112,8 +1120,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1112 p->memcg_batch.memcg = NULL; 1120 p->memcg_batch.memcg = NULL;
1113#endif 1121#endif
1114 1122
1115 p->bts = NULL;
1116
1117 /* Perform scheduler related setup. Assign this task to a CPU. */ 1123 /* Perform scheduler related setup. Assign this task to a CPU. */
1118 sched_fork(p, clone_flags); 1124 sched_fork(p, clone_flags);
1119 1125
@@ -1247,8 +1253,9 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1247 } 1253 }
1248 1254
1249 if (clone_flags & CLONE_THREAD) { 1255 if (clone_flags & CLONE_THREAD) {
1250 atomic_inc(&current->signal->count); 1256 current->signal->nr_threads++;
1251 atomic_inc(&current->signal->live); 1257 atomic_inc(&current->signal->live);
1258 atomic_inc(&current->signal->sigcnt);
1252 p->group_leader = current->group_leader; 1259 p->group_leader = current->group_leader;
1253 list_add_tail_rcu(&p->thread_group, &p->group_leader->thread_group); 1260 list_add_tail_rcu(&p->thread_group, &p->group_leader->thread_group);
1254 } 1261 }
@@ -1261,7 +1268,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1261 p->nsproxy->pid_ns->child_reaper = p; 1268 p->nsproxy->pid_ns->child_reaper = p;
1262 1269
1263 p->signal->leader_pid = pid; 1270 p->signal->leader_pid = pid;
1264 tty_kref_put(p->signal->tty);
1265 p->signal->tty = tty_kref_get(current->signal->tty); 1271 p->signal->tty = tty_kref_get(current->signal->tty);
1266 attach_pid(p, PIDTYPE_PGID, task_pgrp(current)); 1272 attach_pid(p, PIDTYPE_PGID, task_pgrp(current));
1267 attach_pid(p, PIDTYPE_SID, task_session(current)); 1273 attach_pid(p, PIDTYPE_SID, task_session(current));
@@ -1294,7 +1300,7 @@ bad_fork_cleanup_mm:
1294 mmput(p->mm); 1300 mmput(p->mm);
1295bad_fork_cleanup_signal: 1301bad_fork_cleanup_signal:
1296 if (!(clone_flags & CLONE_THREAD)) 1302 if (!(clone_flags & CLONE_THREAD))
1297 __cleanup_signal(p->signal); 1303 free_signal_struct(p->signal);
1298bad_fork_cleanup_sighand: 1304bad_fork_cleanup_sighand:
1299 __cleanup_sighand(p->sighand); 1305 __cleanup_sighand(p->sighand);
1300bad_fork_cleanup_fs: 1306bad_fork_cleanup_fs:
@@ -1329,6 +1335,16 @@ noinline struct pt_regs * __cpuinit __attribute__((weak)) idle_regs(struct pt_re
1329 return regs; 1335 return regs;
1330} 1336}
1331 1337
1338static inline void init_idle_pids(struct pid_link *links)
1339{
1340 enum pid_type type;
1341
1342 for (type = PIDTYPE_PID; type < PIDTYPE_MAX; ++type) {
1343 INIT_HLIST_NODE(&links[type].node); /* not really needed */
1344 links[type].pid = &init_struct_pid;
1345 }
1346}
1347
1332struct task_struct * __cpuinit fork_idle(int cpu) 1348struct task_struct * __cpuinit fork_idle(int cpu)
1333{ 1349{
1334 struct task_struct *task; 1350 struct task_struct *task;
@@ -1336,8 +1352,10 @@ struct task_struct * __cpuinit fork_idle(int cpu)
1336 1352
1337 task = copy_process(CLONE_VM, 0, idle_regs(&regs), 0, NULL, 1353 task = copy_process(CLONE_VM, 0, idle_regs(&regs), 0, NULL,
1338 &init_struct_pid, 0); 1354 &init_struct_pid, 0);
1339 if (!IS_ERR(task)) 1355 if (!IS_ERR(task)) {
1356 init_idle_pids(task->pids);
1340 init_idle(task, cpu); 1357 init_idle(task, cpu);
1358 }
1341 1359
1342 return task; 1360 return task;
1343} 1361}
@@ -1509,14 +1527,6 @@ static void check_unshare_flags(unsigned long *flags_ptr)
1509 *flags_ptr |= CLONE_SIGHAND; 1527 *flags_ptr |= CLONE_SIGHAND;
1510 1528
1511 /* 1529 /*
1512 * If unsharing signal handlers and the task was created
1513 * using CLONE_THREAD, then must unshare the thread
1514 */
1515 if ((*flags_ptr & CLONE_SIGHAND) &&
1516 (atomic_read(&current->signal->count) > 1))
1517 *flags_ptr |= CLONE_THREAD;
1518
1519 /*
1520 * If unsharing namespace, must also unshare filesystem information. 1530 * If unsharing namespace, must also unshare filesystem information.
1521 */ 1531 */
1522 if (*flags_ptr & CLONE_NEWNS) 1532 if (*flags_ptr & CLONE_NEWNS)