memcg: add per-memcg vmalloc stat
Subsystems (5)
PATCH v3 1/1 memcg: add per-memcg vmalloc stat
The kvmalloc* allocation functions can fallback to vmalloc allocations and more often on long running machines. In addition the kernel does have __GFP_ACCOUNT kvmalloc* calls. So, often on long running machines, the memory.stat does not tell the complete picture which type of memory is charged to the memcg. So add a per-memcg vmalloc stat.
Signed-off-by Shakeel Butt <[email protected]>
Reviewed-by Muchun Song <[email protected]>
Acked-by Roman Gushchin <[email protected]>
---
Changes since v2:
- remove cast, per Muchun
- add area->page[0] check, per Michal
Changes since v1:
- page_memcg() within rcu lock as suggested by Muchun.
Documentation/admin-guide/cgroup-v2.rst | 3 +++ include/linux/memcontrol.h | 21 +++++++++++++++++++++ mm/memcontrol.c | 1 + mm/vmalloc.c | 8 ++++++++ 4 files changed, 33 insertions(+)
Documentation/admin-guide/cgroup-v2.rst +3 -0
@@ -1314,6 +1314,9 @@ PAGE_SIZE multiple when read back. sock (npn) Amount of memory used in network transmission buffers + vmalloc (npn) + Amount of memory used for vmap backed memory. + shmem Amount of cached filesystem data that is swap-backed, such as tmpfs, shm segments, shared anonymous mmap()s
include/linux/memcontrol.h +21 -0
@@ -33,6 +33,7 @@ enum memcg_stat_item {MEMCG_SWAP =NR_VM_NODE_STAT_ITEMS ,MEMCG_SOCK ,MEMCG_PERCPU_B , +MEMCG_VMALLOC , MEMCG_NR_STAT, };
@@ -944,6 +945,21 @@ static inline void mod_memcg_state(struct mem_cgroup *memcg,local_irq_restore (flags); } +static inline void mod_memcg_page_state (struct page *page, +int idx,int val) +{ +struct mem_cgroup *memcg; + +if (mem_cgroup_disabled ()) +return ; + +rcu_read_lock (); + memcg =page_memcg (page); +if (memcg) +mod_memcg_state (memcg, idx, val); +rcu_read_unlock (); +} +static inline unsigned long memcg_page_state (struct mem_cgroup *memcg,int idx) {return READ_ONCE (memcg->vmstats.state[idx]);
@@ -1399,6 +1415,11 @@ static inline void mod_memcg_state(struct mem_cgroup *memcg, { } +static inline void mod_memcg_page_state (struct page *page, +int idx,int val) +{ +} +static inline unsigned long memcg_page_state (struct mem_cgroup *memcg,int idx) {return 0 ;
mm/memcontrol.c +1 -0
@@ -1375,6 +1375,7 @@ static const struct memory_stat memory_stats[] = { { "pagetables", NR_PAGETABLE }, { "percpu", MEMCG_PERCPU_B }, { "sock", MEMCG_SOCK }, + { "vmalloc", MEMCG_VMALLOC }, { "shmem", NR_SHMEM }, { "file_mapped", NR_FILE_MAPPED }, { "file_dirty", NR_FILE_DIRTY },
mm/vmalloc.c +8 -0
@@ -31,6 +31,7 @@#include <linux/kmemleak.h> #include <linux/atomic.h> #include <linux/compiler.h> +#include <linux/memcontrol.h> #include <linux/llist.h> #include <linux/bitops.h> #include <linux/rbtree_augmented.h>
@@ -2626,6 +2627,10 @@ static void __vunmap(const void *addr, int deallocate_pages)unsigned int page_order =vm_area_page_order (area);int i; +if (area->pages[0 ]) +mod_memcg_page_state (area->pages[0 ],MEMCG_VMALLOC , + -area->nr_pages); +for (i =0 ; i < area->nr_pages; i +=1U << page_order) {struct page *page = area->pages[i];
@@ -2964,6 +2969,9 @@ static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask, page_order, nr_small_pages, area->pages);atomic_long_add (area->nr_pages, &nr_vmalloc_pages); +if (area->pages[0 ]) +mod_memcg_page_state (area->pages[0 ],MEMCG_VMALLOC , + area->nr_pages);/* * If not enough pages were obtained to accomplish an
Signature · 1 line
2.34.1.448.ga2b2bfdf31-goog