diff options
author | KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> | 2008-10-22 17:15:05 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-23 11:55:02 -0400 |
commit | 94b6da5ab8293b04a300ba35c72eddfa94db8b02 (patch) | |
tree | 8ca1c8abb7934ab51657fffeb26a5f5aabd34743 /mm | |
parent | be07c4ed4043ab8c26f222348136141335e47a2f (diff) |
memcg: fix page_cgroup allocation
page_cgroup_init() is called from mem_cgroup_init(). But at this
point, we cannot call alloc_bootmem().
(and this caused panic at boot.)
This patch moves page_cgroup_init() to init/main.c.
Time table is following:
==
parse_args(). # we can trust mem_cgroup_subsys.disabled bit after this.
....
cgroup_init_early() # "early" init of cgroup.
....
setup_arch() # memmap is allocated.
...
page_cgroup_init();
mem_init(); # we cannot call alloc_bootmem after this.
....
cgroup_init() # mem_cgroup is initialized.
==
Before page_cgroup_init(), mem_map must be initialized. So,
I added page_cgroup_init() to init/main.c directly.
(*) maybe this is not very clean but
- cgroup_init_early() is too early
- in cgroup_init(), we have to use vmalloc instead of alloc_bootmem().
use of vmalloc area in x86-32 is important and we should avoid very large
vmalloc() in x86-32. So, we want to use alloc_bootmem() and added page_cgroup_init()
directly to init/main.c
[akpm@linux-foundation.org: remove unneeded/bad mem_cgroup_subsys declaration]
[akpm@linux-foundation.org: fix build]
Acked-by: Balbir Singh <balbir@linux.vnet.ibm.com>
Tested-by: Balbir Singh <balbir@linux.vnet.ibm.com>
Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r-- | mm/memcontrol.c | 1 | ||||
-rw-r--r-- | mm/page_cgroup.c | 32 |
2 files changed, 25 insertions, 8 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index d4a92b63e98e..866dcc7eeb0c 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
@@ -1088,7 +1088,6 @@ mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont) | |||
1088 | int node; | 1088 | int node; |
1089 | 1089 | ||
1090 | if (unlikely((cont->parent) == NULL)) { | 1090 | if (unlikely((cont->parent) == NULL)) { |
1091 | page_cgroup_init(); | ||
1092 | mem = &init_mem_cgroup; | 1091 | mem = &init_mem_cgroup; |
1093 | } else { | 1092 | } else { |
1094 | mem = mem_cgroup_alloc(); | 1093 | mem = mem_cgroup_alloc(); |
diff --git a/mm/page_cgroup.c b/mm/page_cgroup.c index 78242b4d7edf..f59d797dc5a9 100644 --- a/mm/page_cgroup.c +++ b/mm/page_cgroup.c | |||
@@ -4,8 +4,10 @@ | |||
4 | #include <linux/bit_spinlock.h> | 4 | #include <linux/bit_spinlock.h> |
5 | #include <linux/page_cgroup.h> | 5 | #include <linux/page_cgroup.h> |
6 | #include <linux/hash.h> | 6 | #include <linux/hash.h> |
7 | #include <linux/slab.h> | ||
7 | #include <linux/memory.h> | 8 | #include <linux/memory.h> |
8 | #include <linux/vmalloc.h> | 9 | #include <linux/vmalloc.h> |
10 | #include <linux/cgroup.h> | ||
9 | 11 | ||
10 | static void __meminit | 12 | static void __meminit |
11 | __init_page_cgroup(struct page_cgroup *pc, unsigned long pfn) | 13 | __init_page_cgroup(struct page_cgroup *pc, unsigned long pfn) |
@@ -67,6 +69,9 @@ void __init page_cgroup_init(void) | |||
67 | 69 | ||
68 | int nid, fail; | 70 | int nid, fail; |
69 | 71 | ||
72 | if (mem_cgroup_subsys.disabled) | ||
73 | return; | ||
74 | |||
70 | for_each_online_node(nid) { | 75 | for_each_online_node(nid) { |
71 | fail = alloc_node_page_cgroup(nid); | 76 | fail = alloc_node_page_cgroup(nid); |
72 | if (fail) | 77 | if (fail) |
@@ -107,9 +112,14 @@ int __meminit init_section_page_cgroup(unsigned long pfn) | |||
107 | nid = page_to_nid(pfn_to_page(pfn)); | 112 | nid = page_to_nid(pfn_to_page(pfn)); |
108 | 113 | ||
109 | table_size = sizeof(struct page_cgroup) * PAGES_PER_SECTION; | 114 | table_size = sizeof(struct page_cgroup) * PAGES_PER_SECTION; |
110 | base = kmalloc_node(table_size, GFP_KERNEL, nid); | 115 | if (slab_is_available()) { |
111 | if (!base) | 116 | base = kmalloc_node(table_size, GFP_KERNEL, nid); |
112 | base = vmalloc_node(table_size, nid); | 117 | if (!base) |
118 | base = vmalloc_node(table_size, nid); | ||
119 | } else { | ||
120 | base = __alloc_bootmem_node_nopanic(NODE_DATA(nid), table_size, | ||
121 | PAGE_SIZE, __pa(MAX_DMA_ADDRESS)); | ||
122 | } | ||
113 | 123 | ||
114 | if (!base) { | 124 | if (!base) { |
115 | printk(KERN_ERR "page cgroup allocation failure\n"); | 125 | printk(KERN_ERR "page cgroup allocation failure\n"); |
@@ -136,11 +146,16 @@ void __free_page_cgroup(unsigned long pfn) | |||
136 | if (!ms || !ms->page_cgroup) | 146 | if (!ms || !ms->page_cgroup) |
137 | return; | 147 | return; |
138 | base = ms->page_cgroup + pfn; | 148 | base = ms->page_cgroup + pfn; |
139 | ms->page_cgroup = NULL; | 149 | if (is_vmalloc_addr(base)) { |
140 | if (is_vmalloc_addr(base)) | ||
141 | vfree(base); | 150 | vfree(base); |
142 | else | 151 | ms->page_cgroup = NULL; |
143 | kfree(base); | 152 | } else { |
153 | struct page *page = virt_to_page(base); | ||
154 | if (!PageReserved(page)) { /* Is bootmem ? */ | ||
155 | kfree(base); | ||
156 | ms->page_cgroup = NULL; | ||
157 | } | ||
158 | } | ||
144 | } | 159 | } |
145 | 160 | ||
146 | int online_page_cgroup(unsigned long start_pfn, | 161 | int online_page_cgroup(unsigned long start_pfn, |
@@ -214,6 +229,9 @@ void __init page_cgroup_init(void) | |||
214 | unsigned long pfn; | 229 | unsigned long pfn; |
215 | int fail = 0; | 230 | int fail = 0; |
216 | 231 | ||
232 | if (mem_cgroup_subsys.disabled) | ||
233 | return; | ||
234 | |||
217 | for (pfn = 0; !fail && pfn < max_pfn; pfn += PAGES_PER_SECTION) { | 235 | for (pfn = 0; !fail && pfn < max_pfn; pfn += PAGES_PER_SECTION) { |
218 | if (!pfn_present(pfn)) | 236 | if (!pfn_present(pfn)) |
219 | continue; | 237 | continue; |