diff options
author | Vladimir Davydov <vdavydov@virtuozzo.com> | 2016-07-26 18:24:30 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-26 19:19:19 -0400 |
commit | 3e79ec7ddc33e5c69c20ce7f768d0e5c8b824f69 (patch) | |
tree | a53369a4d3b1cdc06be5b2e54ec7b47a4498ad86 /arch/x86/mm | |
parent | 5e8d35f849b1969b900695ae191326bfacf6bfc6 (diff) |
arch: x86: charge page tables to kmemcg
Page tables can bite a relatively big chunk off system memory and their
allocations are easy to trigger from userspace, so they should be
accounted to kmemcg.
This patch marks page table allocations as __GFP_ACCOUNT for x86. Note
we must not charge allocations of kernel page tables, because they can
be shared among processes from different cgroups so accounting them to a
particular one can pin other cgroups for indefinitely long. So we clear
__GFP_ACCOUNT flag if a page table is allocated for the kernel.
Link: http://lkml.kernel.org/r/7d5c54f6a2bcbe76f03171689440003d87e6c742.1464079538.git.vdavydov@virtuozzo.com
Signed-off-by: Vladimir Davydov <vdavydov@virtuozzo.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Minchan Kim <minchan@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/x86/mm')
-rw-r--r-- | arch/x86/mm/pgtable.c | 10 |
1 files changed, 7 insertions, 3 deletions
diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c index aa0ff4b02a96..3feec5af4e67 100644 --- a/arch/x86/mm/pgtable.c +++ b/arch/x86/mm/pgtable.c | |||
@@ -6,7 +6,7 @@ | |||
6 | #include <asm/fixmap.h> | 6 | #include <asm/fixmap.h> |
7 | #include <asm/mtrr.h> | 7 | #include <asm/mtrr.h> |
8 | 8 | ||
9 | #define PGALLOC_GFP GFP_KERNEL | __GFP_NOTRACK | __GFP_ZERO | 9 | #define PGALLOC_GFP (GFP_KERNEL_ACCOUNT | __GFP_NOTRACK | __GFP_ZERO) |
10 | 10 | ||
11 | #ifdef CONFIG_HIGHPTE | 11 | #ifdef CONFIG_HIGHPTE |
12 | #define PGALLOC_USER_GFP __GFP_HIGHMEM | 12 | #define PGALLOC_USER_GFP __GFP_HIGHMEM |
@@ -18,7 +18,7 @@ gfp_t __userpte_alloc_gfp = PGALLOC_GFP | PGALLOC_USER_GFP; | |||
18 | 18 | ||
19 | pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) | 19 | pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) |
20 | { | 20 | { |
21 | return (pte_t *)__get_free_page(PGALLOC_GFP); | 21 | return (pte_t *)__get_free_page(PGALLOC_GFP & ~__GFP_ACCOUNT); |
22 | } | 22 | } |
23 | 23 | ||
24 | pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address) | 24 | pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address) |
@@ -207,9 +207,13 @@ static int preallocate_pmds(struct mm_struct *mm, pmd_t *pmds[]) | |||
207 | { | 207 | { |
208 | int i; | 208 | int i; |
209 | bool failed = false; | 209 | bool failed = false; |
210 | gfp_t gfp = PGALLOC_GFP; | ||
211 | |||
212 | if (mm == &init_mm) | ||
213 | gfp &= ~__GFP_ACCOUNT; | ||
210 | 214 | ||
211 | for(i = 0; i < PREALLOCATED_PMDS; i++) { | 215 | for(i = 0; i < PREALLOCATED_PMDS; i++) { |
212 | pmd_t *pmd = (pmd_t *)__get_free_page(PGALLOC_GFP); | 216 | pmd_t *pmd = (pmd_t *)__get_free_page(gfp); |
213 | if (!pmd) | 217 | if (!pmd) |
214 | failed = true; | 218 | failed = true; |
215 | if (pmd && !pgtable_pmd_page_ctor(virt_to_page(pmd))) { | 219 | if (pmd && !pgtable_pmd_page_ctor(virt_to_page(pmd))) { |