diff options
Diffstat (limited to 'kernel/fork.c')
-rw-r--r-- | kernel/fork.c | 70 |
1 files changed, 34 insertions, 36 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index 5c2c355aa97f..52e725d4a866 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -148,57 +148,49 @@ static inline void free_task_struct(struct task_struct *tsk) | |||
148 | } | 148 | } |
149 | #endif | 149 | #endif |
150 | 150 | ||
151 | void __weak arch_release_thread_info(struct thread_info *ti) | 151 | void __weak arch_release_thread_stack(unsigned long *stack) |
152 | { | 152 | { |
153 | } | 153 | } |
154 | 154 | ||
155 | #ifndef CONFIG_ARCH_THREAD_INFO_ALLOCATOR | 155 | #ifndef CONFIG_ARCH_THREAD_STACK_ALLOCATOR |
156 | 156 | ||
157 | /* | 157 | /* |
158 | * Allocate pages if THREAD_SIZE is >= PAGE_SIZE, otherwise use a | 158 | * Allocate pages if THREAD_SIZE is >= PAGE_SIZE, otherwise use a |
159 | * kmemcache based allocator. | 159 | * kmemcache based allocator. |
160 | */ | 160 | */ |
161 | # if THREAD_SIZE >= PAGE_SIZE | 161 | # if THREAD_SIZE >= PAGE_SIZE |
162 | static struct thread_info *alloc_thread_info_node(struct task_struct *tsk, | 162 | static unsigned long *alloc_thread_stack_node(struct task_struct *tsk, |
163 | int node) | 163 | int node) |
164 | { | 164 | { |
165 | struct page *page = alloc_kmem_pages_node(node, THREADINFO_GFP, | 165 | struct page *page = alloc_pages_node(node, THREADINFO_GFP, |
166 | THREAD_SIZE_ORDER); | 166 | THREAD_SIZE_ORDER); |
167 | |||
168 | if (page) | ||
169 | memcg_kmem_update_page_stat(page, MEMCG_KERNEL_STACK, | ||
170 | 1 << THREAD_SIZE_ORDER); | ||
171 | 167 | ||
172 | return page ? page_address(page) : NULL; | 168 | return page ? page_address(page) : NULL; |
173 | } | 169 | } |
174 | 170 | ||
175 | static inline void free_thread_info(struct thread_info *ti) | 171 | static inline void free_thread_stack(unsigned long *stack) |
176 | { | 172 | { |
177 | struct page *page = virt_to_page(ti); | 173 | __free_pages(virt_to_page(stack), THREAD_SIZE_ORDER); |
178 | |||
179 | memcg_kmem_update_page_stat(page, MEMCG_KERNEL_STACK, | ||
180 | -(1 << THREAD_SIZE_ORDER)); | ||
181 | __free_kmem_pages(page, THREAD_SIZE_ORDER); | ||
182 | } | 174 | } |
183 | # else | 175 | # else |
184 | static struct kmem_cache *thread_info_cache; | 176 | static struct kmem_cache *thread_stack_cache; |
185 | 177 | ||
186 | static struct thread_info *alloc_thread_info_node(struct task_struct *tsk, | 178 | static unsigned long *alloc_thread_stack_node(struct task_struct *tsk, |
187 | int node) | 179 | int node) |
188 | { | 180 | { |
189 | return kmem_cache_alloc_node(thread_info_cache, THREADINFO_GFP, node); | 181 | return kmem_cache_alloc_node(thread_stack_cache, THREADINFO_GFP, node); |
190 | } | 182 | } |
191 | 183 | ||
192 | static void free_thread_info(struct thread_info *ti) | 184 | static void free_thread_stack(unsigned long *stack) |
193 | { | 185 | { |
194 | kmem_cache_free(thread_info_cache, ti); | 186 | kmem_cache_free(thread_stack_cache, stack); |
195 | } | 187 | } |
196 | 188 | ||
197 | void thread_info_cache_init(void) | 189 | void thread_stack_cache_init(void) |
198 | { | 190 | { |
199 | thread_info_cache = kmem_cache_create("thread_info", THREAD_SIZE, | 191 | thread_stack_cache = kmem_cache_create("thread_stack", THREAD_SIZE, |
200 | THREAD_SIZE, 0, NULL); | 192 | THREAD_SIZE, 0, NULL); |
201 | BUG_ON(thread_info_cache == NULL); | 193 | BUG_ON(thread_stack_cache == NULL); |
202 | } | 194 | } |
203 | # endif | 195 | # endif |
204 | #endif | 196 | #endif |
@@ -221,18 +213,24 @@ struct kmem_cache *vm_area_cachep; | |||
221 | /* SLAB cache for mm_struct structures (tsk->mm) */ | 213 | /* SLAB cache for mm_struct structures (tsk->mm) */ |
222 | static struct kmem_cache *mm_cachep; | 214 | static struct kmem_cache *mm_cachep; |
223 | 215 | ||
224 | static void account_kernel_stack(struct thread_info *ti, int account) | 216 | static void account_kernel_stack(unsigned long *stack, int account) |
225 | { | 217 | { |
226 | struct zone *zone = page_zone(virt_to_page(ti)); | 218 | /* All stack pages are in the same zone and belong to the same memcg. */ |
219 | struct page *first_page = virt_to_page(stack); | ||
220 | |||
221 | mod_zone_page_state(page_zone(first_page), NR_KERNEL_STACK_KB, | ||
222 | THREAD_SIZE / 1024 * account); | ||
227 | 223 | ||
228 | mod_zone_page_state(zone, NR_KERNEL_STACK, account); | 224 | memcg_kmem_update_page_stat( |
225 | first_page, MEMCG_KERNEL_STACK_KB, | ||
226 | account * (THREAD_SIZE / 1024)); | ||
229 | } | 227 | } |
230 | 228 | ||
231 | void free_task(struct task_struct *tsk) | 229 | void free_task(struct task_struct *tsk) |
232 | { | 230 | { |
233 | account_kernel_stack(tsk->stack, -1); | 231 | account_kernel_stack(tsk->stack, -1); |
234 | arch_release_thread_info(tsk->stack); | 232 | arch_release_thread_stack(tsk->stack); |
235 | free_thread_info(tsk->stack); | 233 | free_thread_stack(tsk->stack); |
236 | rt_mutex_debug_task_free(tsk); | 234 | rt_mutex_debug_task_free(tsk); |
237 | ftrace_graph_exit_task(tsk); | 235 | ftrace_graph_exit_task(tsk); |
238 | put_seccomp_filter(tsk); | 236 | put_seccomp_filter(tsk); |
@@ -343,7 +341,7 @@ void set_task_stack_end_magic(struct task_struct *tsk) | |||
343 | static struct task_struct *dup_task_struct(struct task_struct *orig, int node) | 341 | static struct task_struct *dup_task_struct(struct task_struct *orig, int node) |
344 | { | 342 | { |
345 | struct task_struct *tsk; | 343 | struct task_struct *tsk; |
346 | struct thread_info *ti; | 344 | unsigned long *stack; |
347 | int err; | 345 | int err; |
348 | 346 | ||
349 | if (node == NUMA_NO_NODE) | 347 | if (node == NUMA_NO_NODE) |
@@ -352,15 +350,15 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node) | |||
352 | if (!tsk) | 350 | if (!tsk) |
353 | return NULL; | 351 | return NULL; |
354 | 352 | ||
355 | ti = alloc_thread_info_node(tsk, node); | 353 | stack = alloc_thread_stack_node(tsk, node); |
356 | if (!ti) | 354 | if (!stack) |
357 | goto free_tsk; | 355 | goto free_tsk; |
358 | 356 | ||
359 | err = arch_dup_task_struct(tsk, orig); | 357 | err = arch_dup_task_struct(tsk, orig); |
360 | if (err) | 358 | if (err) |
361 | goto free_ti; | 359 | goto free_stack; |
362 | 360 | ||
363 | tsk->stack = ti; | 361 | tsk->stack = stack; |
364 | #ifdef CONFIG_SECCOMP | 362 | #ifdef CONFIG_SECCOMP |
365 | /* | 363 | /* |
366 | * We must handle setting up seccomp filters once we're under | 364 | * We must handle setting up seccomp filters once we're under |
@@ -392,14 +390,14 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node) | |||
392 | tsk->task_frag.page = NULL; | 390 | tsk->task_frag.page = NULL; |
393 | tsk->wake_q.next = NULL; | 391 | tsk->wake_q.next = NULL; |
394 | 392 | ||
395 | account_kernel_stack(ti, 1); | 393 | account_kernel_stack(stack, 1); |
396 | 394 | ||
397 | kcov_task_init(tsk); | 395 | kcov_task_init(tsk); |
398 | 396 | ||
399 | return tsk; | 397 | return tsk; |
400 | 398 | ||
401 | free_ti: | 399 | free_stack: |
402 | free_thread_info(ti); | 400 | free_thread_stack(stack); |
403 | free_tsk: | 401 | free_tsk: |
404 | free_task_struct(tsk); | 402 | free_task_struct(tsk); |
405 | return NULL; | 403 | return NULL; |