diff options
Diffstat (limited to 'mm/page_cgroup.c')
-rw-r--r-- | mm/page_cgroup.c | 58 |
1 files changed, 36 insertions, 22 deletions
diff --git a/mm/page_cgroup.c b/mm/page_cgroup.c index 6c3f7a6a481a..8e7577cdf5e4 100644 --- a/mm/page_cgroup.c +++ b/mm/page_cgroup.c | |||
@@ -130,7 +130,38 @@ struct page *lookup_cgroup_page(struct page_cgroup *pc) | |||
130 | return page; | 130 | return page; |
131 | } | 131 | } |
132 | 132 | ||
133 | /* __alloc_bootmem...() is protected by !slab_available() */ | 133 | static void *__init_refok alloc_page_cgroup(size_t size, int nid) |
134 | { | ||
135 | void *addr = NULL; | ||
136 | |||
137 | addr = alloc_pages_exact(size, GFP_KERNEL | __GFP_NOWARN); | ||
138 | if (addr) | ||
139 | return addr; | ||
140 | |||
141 | if (node_state(nid, N_HIGH_MEMORY)) | ||
142 | addr = vmalloc_node(size, nid); | ||
143 | else | ||
144 | addr = vmalloc(size); | ||
145 | |||
146 | return addr; | ||
147 | } | ||
148 | |||
149 | #ifdef CONFIG_MEMORY_HOTPLUG | ||
150 | static void free_page_cgroup(void *addr) | ||
151 | { | ||
152 | if (is_vmalloc_addr(addr)) { | ||
153 | vfree(addr); | ||
154 | } else { | ||
155 | struct page *page = virt_to_page(addr); | ||
156 | if (!PageReserved(page)) { /* Is bootmem ? */ | ||
157 | size_t table_size = | ||
158 | sizeof(struct page_cgroup) * PAGES_PER_SECTION; | ||
159 | free_pages_exact(addr, table_size); | ||
160 | } | ||
161 | } | ||
162 | } | ||
163 | #endif | ||
164 | |||
134 | static int __init_refok init_section_page_cgroup(unsigned long pfn) | 165 | static int __init_refok init_section_page_cgroup(unsigned long pfn) |
135 | { | 166 | { |
136 | struct page_cgroup *base, *pc; | 167 | struct page_cgroup *base, *pc; |
@@ -147,17 +178,8 @@ static int __init_refok init_section_page_cgroup(unsigned long pfn) | |||
147 | 178 | ||
148 | nid = page_to_nid(pfn_to_page(pfn)); | 179 | nid = page_to_nid(pfn_to_page(pfn)); |
149 | table_size = sizeof(struct page_cgroup) * PAGES_PER_SECTION; | 180 | table_size = sizeof(struct page_cgroup) * PAGES_PER_SECTION; |
150 | VM_BUG_ON(!slab_is_available()); | 181 | base = alloc_page_cgroup(table_size, nid); |
151 | if (node_state(nid, N_HIGH_MEMORY)) { | 182 | |
152 | base = kmalloc_node(table_size, | ||
153 | GFP_KERNEL | __GFP_NOWARN, nid); | ||
154 | if (!base) | ||
155 | base = vmalloc_node(table_size, nid); | ||
156 | } else { | ||
157 | base = kmalloc(table_size, GFP_KERNEL | __GFP_NOWARN); | ||
158 | if (!base) | ||
159 | base = vmalloc(table_size); | ||
160 | } | ||
161 | /* | 183 | /* |
162 | * The value stored in section->page_cgroup is (base - pfn) | 184 | * The value stored in section->page_cgroup is (base - pfn) |
163 | * and it does not point to the memory block allocated above, | 185 | * and it does not point to the memory block allocated above, |
@@ -189,16 +211,8 @@ void __free_page_cgroup(unsigned long pfn) | |||
189 | if (!ms || !ms->page_cgroup) | 211 | if (!ms || !ms->page_cgroup) |
190 | return; | 212 | return; |
191 | base = ms->page_cgroup + pfn; | 213 | base = ms->page_cgroup + pfn; |
192 | if (is_vmalloc_addr(base)) { | 214 | free_page_cgroup(base); |
193 | vfree(base); | 215 | ms->page_cgroup = NULL; |
194 | ms->page_cgroup = NULL; | ||
195 | } else { | ||
196 | struct page *page = virt_to_page(base); | ||
197 | if (!PageReserved(page)) { /* Is bootmem ? */ | ||
198 | kfree(base); | ||
199 | ms->page_cgroup = NULL; | ||
200 | } | ||
201 | } | ||
202 | } | 216 | } |
203 | 217 | ||
204 | int __meminit online_page_cgroup(unsigned long start_pfn, | 218 | int __meminit online_page_cgroup(unsigned long start_pfn, |