diff options
author | Andy Lutomirski <luto@kernel.org> | 2016-07-28 18:48:17 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-28 19:07:41 -0400 |
commit | efdc94907977d2db84b4b00cb9bd98ca011f6819 (patch) | |
tree | 9cccfb94330085fbc897f219bca95135c18765db /kernel/fork.c | |
parent | d30dd8be06a5ae640766b20ea9ae288832bd12ac (diff) |
mm: fix memcg stack accounting for sub-page stacks
We should account for stacks regardless of stack size, and we need to
account in sub-page units if THREAD_SIZE < PAGE_SIZE. Change the units
to kilobytes and Move it into account_kernel_stack().
Fixes: 12580e4b54ba8 ("mm: memcontrol: report kernel stack usage in cgroup2 memory.stat")
Link: http://lkml.kernel.org/r/9b5314e3ee5eda61b0317ec1563768602c1ef438.1468523549.git.luto@kernel.org
Signed-off-by: Andy Lutomirski <luto@kernel.org>
Cc: Vladimir Davydov <vdavydov@virtuozzo.com>
Acked-by: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@kernel.org>
Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com>
Reviewed-by: Vladimir Davydov <vdavydov@virtuozzo.com>
Acked-by: Michal Hocko <mhocko@suse.com>
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.c | 19 |
1 files changed, 8 insertions, 11 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index af3637e0ee52..52e725d4a866 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -165,20 +165,12 @@ static unsigned long *alloc_thread_stack_node(struct task_struct *tsk, | |||
165 | struct page *page = alloc_pages_node(node, THREADINFO_GFP, | 165 | struct page *page = alloc_pages_node(node, THREADINFO_GFP, |
166 | THREAD_SIZE_ORDER); | 166 | THREAD_SIZE_ORDER); |
167 | 167 | ||
168 | if (page) | ||
169 | memcg_kmem_update_page_stat(page, MEMCG_KERNEL_STACK, | ||
170 | 1 << THREAD_SIZE_ORDER); | ||
171 | |||
172 | return page ? page_address(page) : NULL; | 168 | return page ? page_address(page) : NULL; |
173 | } | 169 | } |
174 | 170 | ||
175 | static inline void free_thread_stack(unsigned long *stack) | 171 | static inline void free_thread_stack(unsigned long *stack) |
176 | { | 172 | { |
177 | struct page *page = virt_to_page(stack); | 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_pages(page, THREAD_SIZE_ORDER); | ||
182 | } | 174 | } |
183 | # else | 175 | # else |
184 | static struct kmem_cache *thread_stack_cache; | 176 | static struct kmem_cache *thread_stack_cache; |
@@ -223,10 +215,15 @@ static struct kmem_cache *mm_cachep; | |||
223 | 215 | ||
224 | static void account_kernel_stack(unsigned long *stack, int account) | 216 | static void account_kernel_stack(unsigned long *stack, int account) |
225 | { | 217 | { |
226 | struct zone *zone = page_zone(virt_to_page(stack)); | 218 | /* All stack pages are in the same zone and belong to the same memcg. */ |
219 | struct page *first_page = virt_to_page(stack); | ||
227 | 220 | ||
228 | mod_zone_page_state(zone, NR_KERNEL_STACK_KB, | 221 | mod_zone_page_state(page_zone(first_page), NR_KERNEL_STACK_KB, |
229 | THREAD_SIZE / 1024 * account); | 222 | THREAD_SIZE / 1024 * account); |
223 | |||
224 | memcg_kmem_update_page_stat( | ||
225 | first_page, MEMCG_KERNEL_STACK_KB, | ||
226 | account * (THREAD_SIZE / 1024)); | ||
230 | } | 227 | } |
231 | 228 | ||
232 | void free_task(struct task_struct *tsk) | 229 | void free_task(struct task_struct *tsk) |