Commit f0c0c115 authored by Shakeel Butt's avatar Shakeel Butt Committed by Linus Torvalds

mm: memcontrol: account pagetables per node

For many workloads, pagetable consumption is significant and it makes
sense to expose it in the memory.stat for the memory cgroups.  However at
the moment, the pagetables are accounted per-zone.  Converting them to
per-node and using the right interface will correctly account for the
memory cgroups as well.

[akpm@linux-foundation.org: export __mod_lruvec_page_state to modules for arch/mips/kvm/]

Link: https://lkml.kernel.org/r/20201130212541.2781790-3-shakeelb@google.comSigned-off-by: default avatarShakeel Butt <shakeelb@google.com>
Acked-by: default avatarJohannes Weiner <hannes@cmpxchg.org>
Acked-by: default avatarRoman Gushchin <guro@fb.com>
Cc: Michal Hocko <mhocko@suse.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent c47d5032
...@@ -1274,6 +1274,9 @@ PAGE_SIZE multiple when read back. ...@@ -1274,6 +1274,9 @@ PAGE_SIZE multiple when read back.
kernel_stack kernel_stack
Amount of memory allocated to kernel stacks. Amount of memory allocated to kernel stacks.
pagetables
Amount of memory allocated for page tables.
percpu(npn) percpu(npn)
Amount of memory used for storing per-cpu kernel Amount of memory used for storing per-cpu kernel
data structures. data structures.
......
...@@ -34,7 +34,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm) ...@@ -34,7 +34,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
cpu_dcache_wb_range((unsigned long)new_pgd, cpu_dcache_wb_range((unsigned long)new_pgd,
(unsigned long)new_pgd + (unsigned long)new_pgd +
PTRS_PER_PGD * sizeof(pgd_t)); PTRS_PER_PGD * sizeof(pgd_t));
inc_zone_page_state(virt_to_page((unsigned long *)new_pgd), inc_lruvec_page_state(virt_to_page((unsigned long *)new_pgd),
NR_PAGETABLE); NR_PAGETABLE);
return new_pgd; return new_pgd;
...@@ -59,7 +59,7 @@ void pgd_free(struct mm_struct *mm, pgd_t * pgd) ...@@ -59,7 +59,7 @@ void pgd_free(struct mm_struct *mm, pgd_t * pgd)
pte = pmd_page(*pmd); pte = pmd_page(*pmd);
pmd_clear(pmd); pmd_clear(pmd);
dec_zone_page_state(virt_to_page((unsigned long *)pgd), NR_PAGETABLE); dec_lruvec_page_state(virt_to_page((unsigned long *)pgd), NR_PAGETABLE);
pte_free(mm, pte); pte_free(mm, pte);
mm_dec_nr_ptes(mm); mm_dec_nr_ptes(mm);
pmd_free(mm, pmd); pmd_free(mm, pmd);
......
...@@ -450,7 +450,7 @@ static ssize_t node_read_meminfo(struct device *dev, ...@@ -450,7 +450,7 @@ static ssize_t node_read_meminfo(struct device *dev,
#ifdef CONFIG_SHADOW_CALL_STACK #ifdef CONFIG_SHADOW_CALL_STACK
nid, node_page_state(pgdat, NR_KERNEL_SCS_KB), nid, node_page_state(pgdat, NR_KERNEL_SCS_KB),
#endif #endif
nid, K(sum_zone_node_page_state(nid, NR_PAGETABLE)), nid, K(node_page_state(pgdat, NR_PAGETABLE)),
nid, 0UL, nid, 0UL,
nid, K(sum_zone_node_page_state(nid, NR_BOUNCE)), nid, K(sum_zone_node_page_state(nid, NR_BOUNCE)),
nid, K(node_page_state(pgdat, NR_WRITEBACK_TEMP)), nid, K(node_page_state(pgdat, NR_WRITEBACK_TEMP)),
......
...@@ -107,7 +107,7 @@ static int meminfo_proc_show(struct seq_file *m, void *v) ...@@ -107,7 +107,7 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
global_node_page_state(NR_KERNEL_SCS_KB)); global_node_page_state(NR_KERNEL_SCS_KB));
#endif #endif
show_val_kb(m, "PageTables: ", show_val_kb(m, "PageTables: ",
global_zone_page_state(NR_PAGETABLE)); global_node_page_state(NR_PAGETABLE));
show_val_kb(m, "NFS_Unstable: ", 0); show_val_kb(m, "NFS_Unstable: ", 0);
show_val_kb(m, "Bounce: ", show_val_kb(m, "Bounce: ",
......
...@@ -2203,7 +2203,7 @@ static inline bool pgtable_pte_page_ctor(struct page *page) ...@@ -2203,7 +2203,7 @@ static inline bool pgtable_pte_page_ctor(struct page *page)
if (!ptlock_init(page)) if (!ptlock_init(page))
return false; return false;
__SetPageTable(page); __SetPageTable(page);
inc_zone_page_state(page, NR_PAGETABLE); inc_lruvec_page_state(page, NR_PAGETABLE);
return true; return true;
} }
...@@ -2211,7 +2211,7 @@ static inline void pgtable_pte_page_dtor(struct page *page) ...@@ -2211,7 +2211,7 @@ static inline void pgtable_pte_page_dtor(struct page *page)
{ {
ptlock_free(page); ptlock_free(page);
__ClearPageTable(page); __ClearPageTable(page);
dec_zone_page_state(page, NR_PAGETABLE); dec_lruvec_page_state(page, NR_PAGETABLE);
} }
#define pte_offset_map_lock(mm, pmd, address, ptlp) \ #define pte_offset_map_lock(mm, pmd, address, ptlp) \
...@@ -2298,7 +2298,7 @@ static inline bool pgtable_pmd_page_ctor(struct page *page) ...@@ -2298,7 +2298,7 @@ static inline bool pgtable_pmd_page_ctor(struct page *page)
if (!pmd_ptlock_init(page)) if (!pmd_ptlock_init(page))
return false; return false;
__SetPageTable(page); __SetPageTable(page);
inc_zone_page_state(page, NR_PAGETABLE); inc_lruvec_page_state(page, NR_PAGETABLE);
return true; return true;
} }
...@@ -2306,7 +2306,7 @@ static inline void pgtable_pmd_page_dtor(struct page *page) ...@@ -2306,7 +2306,7 @@ static inline void pgtable_pmd_page_dtor(struct page *page)
{ {
pmd_ptlock_free(page); pmd_ptlock_free(page);
__ClearPageTable(page); __ClearPageTable(page);
dec_zone_page_state(page, NR_PAGETABLE); dec_lruvec_page_state(page, NR_PAGETABLE);
} }
/* /*
......
...@@ -152,7 +152,6 @@ enum zone_stat_item { ...@@ -152,7 +152,6 @@ enum zone_stat_item {
NR_ZONE_UNEVICTABLE, NR_ZONE_UNEVICTABLE,
NR_ZONE_WRITE_PENDING, /* Count of dirty, writeback and unstable pages */ NR_ZONE_WRITE_PENDING, /* Count of dirty, writeback and unstable pages */
NR_MLOCK, /* mlock()ed pages found and moved off LRU */ NR_MLOCK, /* mlock()ed pages found and moved off LRU */
NR_PAGETABLE, /* used for pagetables */
/* Second 128 byte cacheline */ /* Second 128 byte cacheline */
NR_BOUNCE, NR_BOUNCE,
#if IS_ENABLED(CONFIG_ZSMALLOC) #if IS_ENABLED(CONFIG_ZSMALLOC)
...@@ -207,6 +206,7 @@ enum node_stat_item { ...@@ -207,6 +206,7 @@ enum node_stat_item {
#if IS_ENABLED(CONFIG_SHADOW_CALL_STACK) #if IS_ENABLED(CONFIG_SHADOW_CALL_STACK)
NR_KERNEL_SCS_KB, /* measured in KiB */ NR_KERNEL_SCS_KB, /* measured in KiB */
#endif #endif
NR_PAGETABLE, /* used for pagetables */
NR_VM_NODE_STAT_ITEMS NR_VM_NODE_STAT_ITEMS
}; };
......
...@@ -869,6 +869,7 @@ void __mod_lruvec_page_state(struct page *page, enum node_stat_item idx, ...@@ -869,6 +869,7 @@ void __mod_lruvec_page_state(struct page *page, enum node_stat_item idx,
lruvec = mem_cgroup_lruvec(head->mem_cgroup, pgdat); lruvec = mem_cgroup_lruvec(head->mem_cgroup, pgdat);
__mod_lruvec_state(lruvec, idx, val); __mod_lruvec_state(lruvec, idx, val);
} }
EXPORT_SYMBOL(__mod_lruvec_page_state);
void __mod_lruvec_kmem_state(void *p, enum node_stat_item idx, int val) void __mod_lruvec_kmem_state(void *p, enum node_stat_item idx, int val)
{ {
...@@ -1493,6 +1494,7 @@ static struct memory_stat memory_stats[] = { ...@@ -1493,6 +1494,7 @@ static struct memory_stat memory_stats[] = {
{ "anon", PAGE_SIZE, NR_ANON_MAPPED }, { "anon", PAGE_SIZE, NR_ANON_MAPPED },
{ "file", PAGE_SIZE, NR_FILE_PAGES }, { "file", PAGE_SIZE, NR_FILE_PAGES },
{ "kernel_stack", 1024, NR_KERNEL_STACK_KB }, { "kernel_stack", 1024, NR_KERNEL_STACK_KB },
{ "pagetables", PAGE_SIZE, NR_PAGETABLE },
{ "percpu", 1, MEMCG_PERCPU_B }, { "percpu", 1, MEMCG_PERCPU_B },
{ "sock", PAGE_SIZE, MEMCG_SOCK }, { "sock", PAGE_SIZE, MEMCG_SOCK },
{ "shmem", PAGE_SIZE, NR_SHMEM }, { "shmem", PAGE_SIZE, NR_SHMEM },
......
...@@ -5465,7 +5465,7 @@ void show_free_areas(unsigned int filter, nodemask_t *nodemask) ...@@ -5465,7 +5465,7 @@ void show_free_areas(unsigned int filter, nodemask_t *nodemask)
global_node_page_state_pages(NR_SLAB_UNRECLAIMABLE_B), global_node_page_state_pages(NR_SLAB_UNRECLAIMABLE_B),
global_node_page_state(NR_FILE_MAPPED), global_node_page_state(NR_FILE_MAPPED),
global_node_page_state(NR_SHMEM), global_node_page_state(NR_SHMEM),
global_zone_page_state(NR_PAGETABLE), global_node_page_state(NR_PAGETABLE),
global_zone_page_state(NR_BOUNCE), global_zone_page_state(NR_BOUNCE),
global_zone_page_state(NR_FREE_PAGES), global_zone_page_state(NR_FREE_PAGES),
free_pcp, free_pcp,
...@@ -5497,6 +5497,7 @@ void show_free_areas(unsigned int filter, nodemask_t *nodemask) ...@@ -5497,6 +5497,7 @@ void show_free_areas(unsigned int filter, nodemask_t *nodemask)
#ifdef CONFIG_SHADOW_CALL_STACK #ifdef CONFIG_SHADOW_CALL_STACK
" shadow_call_stack:%lukB" " shadow_call_stack:%lukB"
#endif #endif
" pagetables:%lukB"
" all_unreclaimable? %s" " all_unreclaimable? %s"
"\n", "\n",
pgdat->node_id, pgdat->node_id,
...@@ -5522,6 +5523,7 @@ void show_free_areas(unsigned int filter, nodemask_t *nodemask) ...@@ -5522,6 +5523,7 @@ void show_free_areas(unsigned int filter, nodemask_t *nodemask)
#ifdef CONFIG_SHADOW_CALL_STACK #ifdef CONFIG_SHADOW_CALL_STACK
node_page_state(pgdat, NR_KERNEL_SCS_KB), node_page_state(pgdat, NR_KERNEL_SCS_KB),
#endif #endif
K(node_page_state(pgdat, NR_PAGETABLE)),
pgdat->kswapd_failures >= MAX_RECLAIM_RETRIES ? pgdat->kswapd_failures >= MAX_RECLAIM_RETRIES ?
"yes" : "no"); "yes" : "no");
} }
...@@ -5553,7 +5555,6 @@ void show_free_areas(unsigned int filter, nodemask_t *nodemask) ...@@ -5553,7 +5555,6 @@ void show_free_areas(unsigned int filter, nodemask_t *nodemask)
" present:%lukB" " present:%lukB"
" managed:%lukB" " managed:%lukB"
" mlocked:%lukB" " mlocked:%lukB"
" pagetables:%lukB"
" bounce:%lukB" " bounce:%lukB"
" free_pcp:%lukB" " free_pcp:%lukB"
" local_pcp:%ukB" " local_pcp:%ukB"
...@@ -5574,7 +5575,6 @@ void show_free_areas(unsigned int filter, nodemask_t *nodemask) ...@@ -5574,7 +5575,6 @@ void show_free_areas(unsigned int filter, nodemask_t *nodemask)
K(zone->present_pages), K(zone->present_pages),
K(zone_managed_pages(zone)), K(zone_managed_pages(zone)),
K(zone_page_state(zone, NR_MLOCK)), K(zone_page_state(zone, NR_MLOCK)),
K(zone_page_state(zone, NR_PAGETABLE)),
K(zone_page_state(zone, NR_BOUNCE)), K(zone_page_state(zone, NR_BOUNCE)),
K(free_pcp), K(free_pcp),
K(this_cpu_read(zone->pageset->pcp.count)), K(this_cpu_read(zone->pageset->pcp.count)),
......
...@@ -1157,7 +1157,6 @@ const char * const vmstat_text[] = { ...@@ -1157,7 +1157,6 @@ const char * const vmstat_text[] = {
"nr_zone_unevictable", "nr_zone_unevictable",
"nr_zone_write_pending", "nr_zone_write_pending",
"nr_mlock", "nr_mlock",
"nr_page_table_pages",
"nr_bounce", "nr_bounce",
#if IS_ENABLED(CONFIG_ZSMALLOC) #if IS_ENABLED(CONFIG_ZSMALLOC)
"nr_zspages", "nr_zspages",
...@@ -1215,6 +1214,7 @@ const char * const vmstat_text[] = { ...@@ -1215,6 +1214,7 @@ const char * const vmstat_text[] = {
#if IS_ENABLED(CONFIG_SHADOW_CALL_STACK) #if IS_ENABLED(CONFIG_SHADOW_CALL_STACK)
"nr_shadow_call_stack", "nr_shadow_call_stack",
#endif #endif
"nr_page_table_pages",
/* enum writeback_stat_item counters */ /* enum writeback_stat_item counters */
"nr_dirty_threshold", "nr_dirty_threshold",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment