diff options
Diffstat (limited to 'kernel/fork.c')
-rw-r--r-- | kernel/fork.c | 101 |
1 files changed, 57 insertions, 44 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index 9c042f901570..6067e429f281 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -132,6 +132,14 @@ void __put_task_struct(struct task_struct *tsk) | |||
132 | free_task(tsk); | 132 | free_task(tsk); |
133 | } | 133 | } |
134 | 134 | ||
135 | /* | ||
136 | * macro override instead of weak attribute alias, to workaround | ||
137 | * gcc 4.1.0 and 4.1.1 bugs with weak attribute and empty functions. | ||
138 | */ | ||
139 | #ifndef arch_task_cache_init | ||
140 | #define arch_task_cache_init() | ||
141 | #endif | ||
142 | |||
135 | void __init fork_init(unsigned long mempages) | 143 | void __init fork_init(unsigned long mempages) |
136 | { | 144 | { |
137 | #ifndef __HAVE_ARCH_TASK_STRUCT_ALLOCATOR | 145 | #ifndef __HAVE_ARCH_TASK_STRUCT_ALLOCATOR |
@@ -144,6 +152,9 @@ void __init fork_init(unsigned long mempages) | |||
144 | ARCH_MIN_TASKALIGN, SLAB_PANIC, NULL); | 152 | ARCH_MIN_TASKALIGN, SLAB_PANIC, NULL); |
145 | #endif | 153 | #endif |
146 | 154 | ||
155 | /* do the arch specific task caches init */ | ||
156 | arch_task_cache_init(); | ||
157 | |||
147 | /* | 158 | /* |
148 | * The default maximum number of threads is set to a safe | 159 | * The default maximum number of threads is set to a safe |
149 | * value: the thread structures can take up at most half | 160 | * value: the thread structures can take up at most half |
@@ -163,6 +174,13 @@ void __init fork_init(unsigned long mempages) | |||
163 | init_task.signal->rlim[RLIMIT_NPROC]; | 174 | init_task.signal->rlim[RLIMIT_NPROC]; |
164 | } | 175 | } |
165 | 176 | ||
177 | int __attribute__((weak)) arch_dup_task_struct(struct task_struct *dst, | ||
178 | struct task_struct *src) | ||
179 | { | ||
180 | *dst = *src; | ||
181 | return 0; | ||
182 | } | ||
183 | |||
166 | static struct task_struct *dup_task_struct(struct task_struct *orig) | 184 | static struct task_struct *dup_task_struct(struct task_struct *orig) |
167 | { | 185 | { |
168 | struct task_struct *tsk; | 186 | struct task_struct *tsk; |
@@ -181,15 +199,15 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) | |||
181 | return NULL; | 199 | return NULL; |
182 | } | 200 | } |
183 | 201 | ||
184 | *tsk = *orig; | 202 | err = arch_dup_task_struct(tsk, orig); |
203 | if (err) | ||
204 | goto out; | ||
205 | |||
185 | tsk->stack = ti; | 206 | tsk->stack = ti; |
186 | 207 | ||
187 | err = prop_local_init_single(&tsk->dirties); | 208 | err = prop_local_init_single(&tsk->dirties); |
188 | if (err) { | 209 | if (err) |
189 | free_thread_info(ti); | 210 | goto out; |
190 | free_task_struct(tsk); | ||
191 | return NULL; | ||
192 | } | ||
193 | 211 | ||
194 | setup_thread_stack(tsk, orig); | 212 | setup_thread_stack(tsk, orig); |
195 | 213 | ||
@@ -205,6 +223,11 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) | |||
205 | #endif | 223 | #endif |
206 | tsk->splice_pipe = NULL; | 224 | tsk->splice_pipe = NULL; |
207 | return tsk; | 225 | return tsk; |
226 | |||
227 | out: | ||
228 | free_thread_info(ti); | ||
229 | free_task_struct(tsk); | ||
230 | return NULL; | ||
208 | } | 231 | } |
209 | 232 | ||
210 | #ifdef CONFIG_MMU | 233 | #ifdef CONFIG_MMU |
@@ -256,7 +279,7 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) | |||
256 | if (!tmp) | 279 | if (!tmp) |
257 | goto fail_nomem; | 280 | goto fail_nomem; |
258 | *tmp = *mpnt; | 281 | *tmp = *mpnt; |
259 | pol = mpol_copy(vma_policy(mpnt)); | 282 | pol = mpol_dup(vma_policy(mpnt)); |
260 | retval = PTR_ERR(pol); | 283 | retval = PTR_ERR(pol); |
261 | if (IS_ERR(pol)) | 284 | if (IS_ERR(pol)) |
262 | goto fail_nomem_policy; | 285 | goto fail_nomem_policy; |
@@ -498,7 +521,7 @@ void mm_release(struct task_struct *tsk, struct mm_struct *mm) | |||
498 | * Allocate a new mm structure and copy contents from the | 521 | * Allocate a new mm structure and copy contents from the |
499 | * mm structure of the passed in task structure. | 522 | * mm structure of the passed in task structure. |
500 | */ | 523 | */ |
501 | static struct mm_struct *dup_mm(struct task_struct *tsk) | 524 | struct mm_struct *dup_mm(struct task_struct *tsk) |
502 | { | 525 | { |
503 | struct mm_struct *mm, *oldmm = current->mm; | 526 | struct mm_struct *mm, *oldmm = current->mm; |
504 | int err; | 527 | int err; |
@@ -782,12 +805,6 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk) | |||
782 | goto out; | 805 | goto out; |
783 | } | 806 | } |
784 | 807 | ||
785 | /* | ||
786 | * Note: we may be using current for both targets (See exec.c) | ||
787 | * This works because we cache current->files (old) as oldf. Don't | ||
788 | * break this. | ||
789 | */ | ||
790 | tsk->files = NULL; | ||
791 | newf = dup_fd(oldf, &error); | 808 | newf = dup_fd(oldf, &error); |
792 | if (!newf) | 809 | if (!newf) |
793 | goto out; | 810 | goto out; |
@@ -823,34 +840,6 @@ static int copy_io(unsigned long clone_flags, struct task_struct *tsk) | |||
823 | return 0; | 840 | return 0; |
824 | } | 841 | } |
825 | 842 | ||
826 | /* | ||
827 | * Helper to unshare the files of the current task. | ||
828 | * We don't want to expose copy_files internals to | ||
829 | * the exec layer of the kernel. | ||
830 | */ | ||
831 | |||
832 | int unshare_files(void) | ||
833 | { | ||
834 | struct files_struct *files = current->files; | ||
835 | int rc; | ||
836 | |||
837 | BUG_ON(!files); | ||
838 | |||
839 | /* This can race but the race causes us to copy when we don't | ||
840 | need to and drop the copy */ | ||
841 | if(atomic_read(&files->count) == 1) | ||
842 | { | ||
843 | atomic_inc(&files->count); | ||
844 | return 0; | ||
845 | } | ||
846 | rc = copy_files(0, current); | ||
847 | if(rc) | ||
848 | current->files = files; | ||
849 | return rc; | ||
850 | } | ||
851 | |||
852 | EXPORT_SYMBOL(unshare_files); | ||
853 | |||
854 | static int copy_sighand(unsigned long clone_flags, struct task_struct *tsk) | 843 | static int copy_sighand(unsigned long clone_flags, struct task_struct *tsk) |
855 | { | 844 | { |
856 | struct sighand_struct *sig; | 845 | struct sighand_struct *sig; |
@@ -1127,7 +1116,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1127 | p->audit_context = NULL; | 1116 | p->audit_context = NULL; |
1128 | cgroup_fork(p); | 1117 | cgroup_fork(p); |
1129 | #ifdef CONFIG_NUMA | 1118 | #ifdef CONFIG_NUMA |
1130 | p->mempolicy = mpol_copy(p->mempolicy); | 1119 | p->mempolicy = mpol_dup(p->mempolicy); |
1131 | if (IS_ERR(p->mempolicy)) { | 1120 | if (IS_ERR(p->mempolicy)) { |
1132 | retval = PTR_ERR(p->mempolicy); | 1121 | retval = PTR_ERR(p->mempolicy); |
1133 | p->mempolicy = NULL; | 1122 | p->mempolicy = NULL; |
@@ -1385,7 +1374,7 @@ bad_fork_cleanup_security: | |||
1385 | security_task_free(p); | 1374 | security_task_free(p); |
1386 | bad_fork_cleanup_policy: | 1375 | bad_fork_cleanup_policy: |
1387 | #ifdef CONFIG_NUMA | 1376 | #ifdef CONFIG_NUMA |
1388 | mpol_free(p->mempolicy); | 1377 | mpol_put(p->mempolicy); |
1389 | bad_fork_cleanup_cgroup: | 1378 | bad_fork_cleanup_cgroup: |
1390 | #endif | 1379 | #endif |
1391 | cgroup_exit(p, cgroup_callbacks_done); | 1380 | cgroup_exit(p, cgroup_callbacks_done); |
@@ -1788,3 +1777,27 @@ bad_unshare_cleanup_thread: | |||
1788 | bad_unshare_out: | 1777 | bad_unshare_out: |
1789 | return err; | 1778 | return err; |
1790 | } | 1779 | } |
1780 | |||
1781 | /* | ||
1782 | * Helper to unshare the files of the current task. | ||
1783 | * We don't want to expose copy_files internals to | ||
1784 | * the exec layer of the kernel. | ||
1785 | */ | ||
1786 | |||
1787 | int unshare_files(struct files_struct **displaced) | ||
1788 | { | ||
1789 | struct task_struct *task = current; | ||
1790 | struct files_struct *copy = NULL; | ||
1791 | int error; | ||
1792 | |||
1793 | error = unshare_fd(CLONE_FILES, ©); | ||
1794 | if (error || !copy) { | ||
1795 | *displaced = NULL; | ||
1796 | return error; | ||
1797 | } | ||
1798 | *displaced = task->files; | ||
1799 | task_lock(task); | ||
1800 | task->files = copy; | ||
1801 | task_unlock(task); | ||
1802 | return 0; | ||
1803 | } | ||