aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux
diff options
context:
space:
mode:
authorJohannes Weiner <hannes@cmpxchg.org>2014-12-10 18:44:52 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-10 20:41:09 -0500
commit1306a85aed3ec3db98945aafb7dfbe5648a1203c (patch)
tree63643e556c64118d963020758faf915325ba613c /include/linux
parent22811c6bc3c764d8935383ad0ddd7a96b45d75dc (diff)
mm: embed the memcg pointer directly into struct page
Memory cgroups used to have 5 per-page pointers. To allow users to disable that amount of overhead during runtime, those pointers were allocated in a separate array, with a translation layer between them and struct page. There is now only one page pointer remaining: the memcg pointer, that indicates which cgroup the page is associated with when charged. The complexity of runtime allocation and the runtime translation overhead is no longer justified to save that *potential* 0.19% of memory. With CONFIG_SLUB, page->mem_cgroup actually sits in the doubleword padding after the page->private member and doesn't even increase struct page, and then this patch actually saves space. Remaining users that care can still compile their kernels without CONFIG_MEMCG. text data bss dec hex filename 8828345 1725264 983040 11536649 b00909 vmlinux.old 8827425 1725264 966656 11519345 afc571 vmlinux.new [mhocko@suse.cz: update Documentation/cgroups/memory.txt] Signed-off-by: Johannes Weiner <hannes@cmpxchg.org> Acked-by: Michal Hocko <mhocko@suse.cz> Acked-by: Vladimir Davydov <vdavydov@parallels.com> Acked-by: David S. Miller <davem@davemloft.net> Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: "Kirill A. Shutemov" <kirill@shutemov.name> Cc: Michal Hocko <mhocko@suse.cz> Cc: Vladimir Davydov <vdavydov@parallels.com> Cc: Tejun Heo <tj@kernel.org> Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com> Acked-by: Konstantin Khlebnikov <koct9i@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/memcontrol.h6
-rw-r--r--include/linux/mm_types.h5
-rw-r--r--include/linux/mmzone.h12
-rw-r--r--include/linux/page_cgroup.h53
4 files changed, 6 insertions, 70 deletions
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index de018766be45..c4d080875164 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -25,7 +25,6 @@
25#include <linux/jump_label.h> 25#include <linux/jump_label.h>
26 26
27struct mem_cgroup; 27struct mem_cgroup;
28struct page_cgroup;
29struct page; 28struct page;
30struct mm_struct; 29struct mm_struct;
31struct kmem_cache; 30struct kmem_cache;
@@ -466,8 +465,6 @@ memcg_kmem_newpage_charge(gfp_t gfp, struct mem_cgroup **memcg, int order)
466 * memcg_kmem_uncharge_pages: uncharge pages from memcg 465 * memcg_kmem_uncharge_pages: uncharge pages from memcg
467 * @page: pointer to struct page being freed 466 * @page: pointer to struct page being freed
468 * @order: allocation order. 467 * @order: allocation order.
469 *
470 * there is no need to specify memcg here, since it is embedded in page_cgroup
471 */ 468 */
472static inline void 469static inline void
473memcg_kmem_uncharge_pages(struct page *page, int order) 470memcg_kmem_uncharge_pages(struct page *page, int order)
@@ -484,8 +481,7 @@ memcg_kmem_uncharge_pages(struct page *page, int order)
484 * 481 *
485 * Needs to be called after memcg_kmem_newpage_charge, regardless of success or 482 * Needs to be called after memcg_kmem_newpage_charge, regardless of success or
486 * failure of the allocation. if @page is NULL, this function will revert the 483 * failure of the allocation. if @page is NULL, this function will revert the
487 * charges. Otherwise, it will commit the memcg given by @memcg to the 484 * charges. Otherwise, it will commit @page to @memcg.
488 * corresponding page_cgroup.
489 */ 485 */
490static inline void 486static inline void
491memcg_kmem_commit_charge(struct page *page, struct mem_cgroup *memcg, int order) 487memcg_kmem_commit_charge(struct page *page, struct mem_cgroup *memcg, int order)
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 004e9d17b47e..bf9f57529dcf 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -22,6 +22,7 @@
22#define AT_VECTOR_SIZE (2*(AT_VECTOR_SIZE_ARCH + AT_VECTOR_SIZE_BASE + 1)) 22#define AT_VECTOR_SIZE (2*(AT_VECTOR_SIZE_ARCH + AT_VECTOR_SIZE_BASE + 1))
23 23
24struct address_space; 24struct address_space;
25struct mem_cgroup;
25 26
26#define USE_SPLIT_PTE_PTLOCKS (NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS) 27#define USE_SPLIT_PTE_PTLOCKS (NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS)
27#define USE_SPLIT_PMD_PTLOCKS (USE_SPLIT_PTE_PTLOCKS && \ 28#define USE_SPLIT_PMD_PTLOCKS (USE_SPLIT_PTE_PTLOCKS && \
@@ -167,6 +168,10 @@ struct page {
167 struct page *first_page; /* Compound tail pages */ 168 struct page *first_page; /* Compound tail pages */
168 }; 169 };
169 170
171#ifdef CONFIG_MEMCG
172 struct mem_cgroup *mem_cgroup;
173#endif
174
170 /* 175 /*
171 * On machines where all RAM is mapped into kernel address space, 176 * On machines where all RAM is mapped into kernel address space,
172 * we can simply calculate the virtual address. On machines with 177 * we can simply calculate the virtual address. On machines with
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index ffe66e381c04..3879d7664dfc 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -722,9 +722,6 @@ typedef struct pglist_data {
722 int nr_zones; 722 int nr_zones;
723#ifdef CONFIG_FLAT_NODE_MEM_MAP /* means !SPARSEMEM */ 723#ifdef CONFIG_FLAT_NODE_MEM_MAP /* means !SPARSEMEM */
724 struct page *node_mem_map; 724 struct page *node_mem_map;
725#ifdef CONFIG_MEMCG
726 struct page_cgroup *node_page_cgroup;
727#endif
728#endif 725#endif
729#ifndef CONFIG_NO_BOOTMEM 726#ifndef CONFIG_NO_BOOTMEM
730 struct bootmem_data *bdata; 727 struct bootmem_data *bdata;
@@ -1078,7 +1075,6 @@ static inline unsigned long early_pfn_to_nid(unsigned long pfn)
1078#define SECTION_ALIGN_DOWN(pfn) ((pfn) & PAGE_SECTION_MASK) 1075#define SECTION_ALIGN_DOWN(pfn) ((pfn) & PAGE_SECTION_MASK)
1079 1076
1080struct page; 1077struct page;
1081struct page_cgroup;
1082struct mem_section { 1078struct mem_section {
1083 /* 1079 /*
1084 * This is, logically, a pointer to an array of struct 1080 * This is, logically, a pointer to an array of struct
@@ -1096,14 +1092,6 @@ struct mem_section {
1096 1092
1097 /* See declaration of similar field in struct zone */ 1093 /* See declaration of similar field in struct zone */
1098 unsigned long *pageblock_flags; 1094 unsigned long *pageblock_flags;
1099#ifdef CONFIG_MEMCG
1100 /*
1101 * If !SPARSEMEM, pgdat doesn't have page_cgroup pointer. We use
1102 * section. (see memcontrol.h/page_cgroup.h about this.)
1103 */
1104 struct page_cgroup *page_cgroup;
1105 unsigned long pad;
1106#endif
1107 /* 1095 /*
1108 * WARNING: mem_section must be a power-of-2 in size for the 1096 * WARNING: mem_section must be a power-of-2 in size for the
1109 * calculation and use of SECTION_ROOT_MASK to make sense. 1097 * calculation and use of SECTION_ROOT_MASK to make sense.
diff --git a/include/linux/page_cgroup.h b/include/linux/page_cgroup.h
index 1289be6b436c..65be35785c86 100644
--- a/include/linux/page_cgroup.h
+++ b/include/linux/page_cgroup.h
@@ -1,59 +1,6 @@
1#ifndef __LINUX_PAGE_CGROUP_H 1#ifndef __LINUX_PAGE_CGROUP_H
2#define __LINUX_PAGE_CGROUP_H 2#define __LINUX_PAGE_CGROUP_H
3 3
4struct pglist_data;
5
6#ifdef CONFIG_MEMCG
7struct mem_cgroup;
8
9/*
10 * Page Cgroup can be considered as an extended mem_map.
11 * A page_cgroup page is associated with every page descriptor. The
12 * page_cgroup helps us identify information about the cgroup
13 * All page cgroups are allocated at boot or memory hotplug event,
14 * then the page cgroup for pfn always exists.
15 */
16struct page_cgroup {
17 struct mem_cgroup *mem_cgroup;
18};
19
20extern void pgdat_page_cgroup_init(struct pglist_data *pgdat);
21
22#ifdef CONFIG_SPARSEMEM
23static inline void page_cgroup_init_flatmem(void)
24{
25}
26extern void page_cgroup_init(void);
27#else
28extern void page_cgroup_init_flatmem(void);
29static inline void page_cgroup_init(void)
30{
31}
32#endif
33
34struct page_cgroup *lookup_page_cgroup(struct page *page);
35
36#else /* !CONFIG_MEMCG */
37struct page_cgroup;
38
39static inline void pgdat_page_cgroup_init(struct pglist_data *pgdat)
40{
41}
42
43static inline struct page_cgroup *lookup_page_cgroup(struct page *page)
44{
45 return NULL;
46}
47
48static inline void page_cgroup_init(void)
49{
50}
51
52static inline void page_cgroup_init_flatmem(void)
53{
54}
55#endif /* CONFIG_MEMCG */
56
57#include <linux/swap.h> 4#include <linux/swap.h>
58 5
59#ifdef CONFIG_MEMCG_SWAP 6#ifdef CONFIG_MEMCG_SWAP