diff options
Diffstat (limited to 'kernel/fork.c')
| -rw-r--r-- | kernel/fork.c | 90 |
1 files changed, 69 insertions, 21 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index 8ca1a14cdc8c..2b55b74cd999 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
| @@ -51,6 +51,7 @@ | |||
| 51 | #include <linux/random.h> | 51 | #include <linux/random.h> |
| 52 | #include <linux/tty.h> | 52 | #include <linux/tty.h> |
| 53 | #include <linux/proc_fs.h> | 53 | #include <linux/proc_fs.h> |
| 54 | #include <linux/blkdev.h> | ||
| 54 | 55 | ||
| 55 | #include <asm/pgtable.h> | 56 | #include <asm/pgtable.h> |
| 56 | #include <asm/pgalloc.h> | 57 | #include <asm/pgalloc.h> |
| @@ -324,7 +325,7 @@ static inline int mm_alloc_pgd(struct mm_struct * mm) | |||
| 324 | 325 | ||
| 325 | static inline void mm_free_pgd(struct mm_struct * mm) | 326 | static inline void mm_free_pgd(struct mm_struct * mm) |
| 326 | { | 327 | { |
| 327 | pgd_free(mm->pgd); | 328 | pgd_free(mm, mm->pgd); |
| 328 | } | 329 | } |
| 329 | #else | 330 | #else |
| 330 | #define dup_mmap(mm, oldmm) (0) | 331 | #define dup_mmap(mm, oldmm) (0) |
| @@ -392,6 +393,7 @@ void fastcall __mmdrop(struct mm_struct *mm) | |||
| 392 | destroy_context(mm); | 393 | destroy_context(mm); |
| 393 | free_mm(mm); | 394 | free_mm(mm); |
| 394 | } | 395 | } |
| 396 | EXPORT_SYMBOL_GPL(__mmdrop); | ||
| 395 | 397 | ||
| 396 | /* | 398 | /* |
| 397 | * Decrement the use count and release all resources for an mm. | 399 | * Decrement the use count and release all resources for an mm. |
| @@ -791,6 +793,31 @@ out: | |||
| 791 | return error; | 793 | return error; |
| 792 | } | 794 | } |
| 793 | 795 | ||
| 796 | static int copy_io(unsigned long clone_flags, struct task_struct *tsk) | ||
| 797 | { | ||
| 798 | #ifdef CONFIG_BLOCK | ||
| 799 | struct io_context *ioc = current->io_context; | ||
| 800 | |||
| 801 | if (!ioc) | ||
| 802 | return 0; | ||
| 803 | /* | ||
| 804 | * Share io context with parent, if CLONE_IO is set | ||
| 805 | */ | ||
| 806 | if (clone_flags & CLONE_IO) { | ||
| 807 | tsk->io_context = ioc_task_link(ioc); | ||
| 808 | if (unlikely(!tsk->io_context)) | ||
| 809 | return -ENOMEM; | ||
| 810 | } else if (ioprio_valid(ioc->ioprio)) { | ||
| 811 | tsk->io_context = alloc_io_context(GFP_KERNEL, -1); | ||
| 812 | if (unlikely(!tsk->io_context)) | ||
| 813 | return -ENOMEM; | ||
| 814 | |||
| 815 | tsk->io_context->ioprio = ioc->ioprio; | ||
| 816 | } | ||
| 817 | #endif | ||
| 818 | return 0; | ||
| 819 | } | ||
| 820 | |||
| 794 | /* | 821 | /* |
| 795 | * Helper to unshare the files of the current task. | 822 | * Helper to unshare the files of the current task. |
| 796 | * We don't want to expose copy_files internals to | 823 | * We don't want to expose copy_files internals to |
| @@ -1045,6 +1072,10 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1045 | copy_flags(clone_flags, p); | 1072 | copy_flags(clone_flags, p); |
| 1046 | INIT_LIST_HEAD(&p->children); | 1073 | INIT_LIST_HEAD(&p->children); |
| 1047 | INIT_LIST_HEAD(&p->sibling); | 1074 | INIT_LIST_HEAD(&p->sibling); |
| 1075 | #ifdef CONFIG_PREEMPT_RCU | ||
| 1076 | p->rcu_read_lock_nesting = 0; | ||
| 1077 | p->rcu_flipctr_idx = 0; | ||
| 1078 | #endif /* #ifdef CONFIG_PREEMPT_RCU */ | ||
| 1048 | p->vfork_done = NULL; | 1079 | p->vfork_done = NULL; |
| 1049 | spin_lock_init(&p->alloc_lock); | 1080 | spin_lock_init(&p->alloc_lock); |
| 1050 | 1081 | ||
| @@ -1059,6 +1090,11 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1059 | p->prev_utime = cputime_zero; | 1090 | p->prev_utime = cputime_zero; |
| 1060 | p->prev_stime = cputime_zero; | 1091 | p->prev_stime = cputime_zero; |
| 1061 | 1092 | ||
| 1093 | #ifdef CONFIG_DETECT_SOFTLOCKUP | ||
| 1094 | p->last_switch_count = 0; | ||
| 1095 | p->last_switch_timestamp = 0; | ||
| 1096 | #endif | ||
| 1097 | |||
| 1062 | #ifdef CONFIG_TASK_XACCT | 1098 | #ifdef CONFIG_TASK_XACCT |
| 1063 | p->rchar = 0; /* I/O counter: bytes read */ | 1099 | p->rchar = 0; /* I/O counter: bytes read */ |
| 1064 | p->wchar = 0; /* I/O counter: bytes written */ | 1100 | p->wchar = 0; /* I/O counter: bytes written */ |
| @@ -1082,6 +1118,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1082 | #ifdef CONFIG_SECURITY | 1118 | #ifdef CONFIG_SECURITY |
| 1083 | p->security = NULL; | 1119 | p->security = NULL; |
| 1084 | #endif | 1120 | #endif |
| 1121 | p->cap_bset = current->cap_bset; | ||
| 1085 | p->io_context = NULL; | 1122 | p->io_context = NULL; |
| 1086 | p->audit_context = NULL; | 1123 | p->audit_context = NULL; |
| 1087 | cgroup_fork(p); | 1124 | cgroup_fork(p); |
| @@ -1147,15 +1184,17 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1147 | goto bad_fork_cleanup_mm; | 1184 | goto bad_fork_cleanup_mm; |
| 1148 | if ((retval = copy_namespaces(clone_flags, p))) | 1185 | if ((retval = copy_namespaces(clone_flags, p))) |
| 1149 | goto bad_fork_cleanup_keys; | 1186 | goto bad_fork_cleanup_keys; |
| 1187 | if ((retval = copy_io(clone_flags, p))) | ||
| 1188 | goto bad_fork_cleanup_namespaces; | ||
| 1150 | retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs); | 1189 | retval = copy_thread(0, clone_flags, stack_start, stack_size, p, regs); |
| 1151 | if (retval) | 1190 | if (retval) |
| 1152 | goto bad_fork_cleanup_namespaces; | 1191 | goto bad_fork_cleanup_io; |
| 1153 | 1192 | ||
| 1154 | if (pid != &init_struct_pid) { | 1193 | if (pid != &init_struct_pid) { |
| 1155 | retval = -ENOMEM; | 1194 | retval = -ENOMEM; |
| 1156 | pid = alloc_pid(task_active_pid_ns(p)); | 1195 | pid = alloc_pid(task_active_pid_ns(p)); |
| 1157 | if (!pid) | 1196 | if (!pid) |
| 1158 | goto bad_fork_cleanup_namespaces; | 1197 | goto bad_fork_cleanup_io; |
| 1159 | 1198 | ||
| 1160 | if (clone_flags & CLONE_NEWPID) { | 1199 | if (clone_flags & CLONE_NEWPID) { |
| 1161 | retval = pid_ns_prepare_proc(task_active_pid_ns(p)); | 1200 | retval = pid_ns_prepare_proc(task_active_pid_ns(p)); |
| @@ -1196,6 +1235,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1196 | #ifdef TIF_SYSCALL_EMU | 1235 | #ifdef TIF_SYSCALL_EMU |
| 1197 | clear_tsk_thread_flag(p, TIF_SYSCALL_EMU); | 1236 | clear_tsk_thread_flag(p, TIF_SYSCALL_EMU); |
| 1198 | #endif | 1237 | #endif |
| 1238 | clear_all_latency_tracing(p); | ||
| 1199 | 1239 | ||
| 1200 | /* Our parent execution domain becomes current domain | 1240 | /* Our parent execution domain becomes current domain |
| 1201 | These must match for thread signalling to apply */ | 1241 | These must match for thread signalling to apply */ |
| @@ -1224,9 +1264,6 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1224 | /* Need tasklist lock for parent etc handling! */ | 1264 | /* Need tasklist lock for parent etc handling! */ |
| 1225 | write_lock_irq(&tasklist_lock); | 1265 | write_lock_irq(&tasklist_lock); |
| 1226 | 1266 | ||
| 1227 | /* for sys_ioprio_set(IOPRIO_WHO_PGRP) */ | ||
| 1228 | p->ioprio = current->ioprio; | ||
| 1229 | |||
| 1230 | /* | 1267 | /* |
| 1231 | * The task hasn't been attached yet, so its cpus_allowed mask will | 1268 | * The task hasn't been attached yet, so its cpus_allowed mask will |
| 1232 | * not be changed, nor will its assigned CPU. | 1269 | * not be changed, nor will its assigned CPU. |
| @@ -1237,6 +1274,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1237 | * parent's CPU). This avoids alot of nasty races. | 1274 | * parent's CPU). This avoids alot of nasty races. |
| 1238 | */ | 1275 | */ |
| 1239 | p->cpus_allowed = current->cpus_allowed; | 1276 | p->cpus_allowed = current->cpus_allowed; |
| 1277 | p->rt.nr_cpus_allowed = current->rt.nr_cpus_allowed; | ||
| 1240 | if (unlikely(!cpu_isset(task_cpu(p), p->cpus_allowed) || | 1278 | if (unlikely(!cpu_isset(task_cpu(p), p->cpus_allowed) || |
| 1241 | !cpu_online(task_cpu(p)))) | 1279 | !cpu_online(task_cpu(p)))) |
| 1242 | set_task_cpu(p, smp_processor_id()); | 1280 | set_task_cpu(p, smp_processor_id()); |
| @@ -1292,23 +1330,14 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1292 | __ptrace_link(p, current->parent); | 1330 | __ptrace_link(p, current->parent); |
| 1293 | 1331 | ||
| 1294 | if (thread_group_leader(p)) { | 1332 | if (thread_group_leader(p)) { |
| 1295 | if (clone_flags & CLONE_NEWPID) { | 1333 | if (clone_flags & CLONE_NEWPID) |
| 1296 | p->nsproxy->pid_ns->child_reaper = p; | 1334 | p->nsproxy->pid_ns->child_reaper = p; |
| 1297 | p->signal->tty = NULL; | ||
| 1298 | set_task_pgrp(p, p->pid); | ||
| 1299 | set_task_session(p, p->pid); | ||
| 1300 | attach_pid(p, PIDTYPE_PGID, pid); | ||
| 1301 | attach_pid(p, PIDTYPE_SID, pid); | ||
| 1302 | } else { | ||
| 1303 | p->signal->tty = current->signal->tty; | ||
| 1304 | set_task_pgrp(p, task_pgrp_nr(current)); | ||
| 1305 | set_task_session(p, task_session_nr(current)); | ||
| 1306 | attach_pid(p, PIDTYPE_PGID, | ||
| 1307 | task_pgrp(current)); | ||
| 1308 | attach_pid(p, PIDTYPE_SID, | ||
| 1309 | task_session(current)); | ||
| 1310 | } | ||
| 1311 | 1335 | ||
| 1336 | p->signal->tty = current->signal->tty; | ||
| 1337 | set_task_pgrp(p, task_pgrp_nr(current)); | ||
| 1338 | set_task_session(p, task_session_nr(current)); | ||
| 1339 | attach_pid(p, PIDTYPE_PGID, task_pgrp(current)); | ||
| 1340 | attach_pid(p, PIDTYPE_SID, task_session(current)); | ||
| 1312 | list_add_tail_rcu(&p->tasks, &init_task.tasks); | 1341 | list_add_tail_rcu(&p->tasks, &init_task.tasks); |
| 1313 | __get_cpu_var(process_counts)++; | 1342 | __get_cpu_var(process_counts)++; |
| 1314 | } | 1343 | } |
| @@ -1326,6 +1355,8 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
| 1326 | bad_fork_free_pid: | 1355 | bad_fork_free_pid: |
| 1327 | if (pid != &init_struct_pid) | 1356 | if (pid != &init_struct_pid) |
| 1328 | free_pid(pid); | 1357 | free_pid(pid); |
| 1358 | bad_fork_cleanup_io: | ||
| 1359 | put_io_context(p->io_context); | ||
| 1329 | bad_fork_cleanup_namespaces: | 1360 | bad_fork_cleanup_namespaces: |
| 1330 | exit_task_namespaces(p); | 1361 | exit_task_namespaces(p); |
| 1331 | bad_fork_cleanup_keys: | 1362 | bad_fork_cleanup_keys: |
| @@ -1420,6 +1451,23 @@ long do_fork(unsigned long clone_flags, | |||
| 1420 | int trace = 0; | 1451 | int trace = 0; |
| 1421 | long nr; | 1452 | long nr; |
| 1422 | 1453 | ||
| 1454 | /* | ||
| 1455 | * We hope to recycle these flags after 2.6.26 | ||
| 1456 | */ | ||
| 1457 | if (unlikely(clone_flags & CLONE_STOPPED)) { | ||
| 1458 | static int __read_mostly count = 100; | ||
| 1459 | |||
| 1460 | if (count > 0 && printk_ratelimit()) { | ||
| 1461 | char comm[TASK_COMM_LEN]; | ||
| 1462 | |||
| 1463 | count--; | ||
| 1464 | printk(KERN_INFO "fork(): process `%s' used deprecated " | ||
| 1465 | "clone flags 0x%lx\n", | ||
| 1466 | get_task_comm(comm, current), | ||
| 1467 | clone_flags & CLONE_STOPPED); | ||
| 1468 | } | ||
| 1469 | } | ||
| 1470 | |||
| 1423 | if (unlikely(current->ptrace)) { | 1471 | if (unlikely(current->ptrace)) { |
| 1424 | trace = fork_traceflag (clone_flags); | 1472 | trace = fork_traceflag (clone_flags); |
| 1425 | if (trace) | 1473 | if (trace) |
