aboutsummaryrefslogtreecommitdiffstats
path: root/mm/page_cgroup.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/page_cgroup.c')
-rw-r--r--mm/page_cgroup.c56
1 files changed, 36 insertions, 20 deletions
diff --git a/mm/page_cgroup.c b/mm/page_cgroup.c
index 1223d927904..0b3cbf090a6 100644
--- a/mm/page_cgroup.c
+++ b/mm/page_cgroup.c
@@ -21,7 +21,7 @@ static unsigned long total_usage;
21#if !defined(CONFIG_SPARSEMEM) 21#if !defined(CONFIG_SPARSEMEM)
22 22
23 23
24void __init pgdat_page_cgroup_init(struct pglist_data *pgdat) 24void __meminit pgdat_page_cgroup_init(struct pglist_data *pgdat)
25{ 25{
26 pgdat->node_page_cgroup = NULL; 26 pgdat->node_page_cgroup = NULL;
27} 27}
@@ -97,7 +97,8 @@ struct page_cgroup *lookup_page_cgroup(struct page *page)
97 return section->page_cgroup + pfn; 97 return section->page_cgroup + pfn;
98} 98}
99 99
100int __meminit init_section_page_cgroup(unsigned long pfn) 100/* __alloc_bootmem...() is protected by !slab_available() */
101int __init_refok init_section_page_cgroup(unsigned long pfn)
101{ 102{
102 struct mem_section *section; 103 struct mem_section *section;
103 struct page_cgroup *base, *pc; 104 struct page_cgroup *base, *pc;
@@ -106,19 +107,29 @@ int __meminit init_section_page_cgroup(unsigned long pfn)
106 107
107 section = __pfn_to_section(pfn); 108 section = __pfn_to_section(pfn);
108 109
109 if (section->page_cgroup) 110 if (!section->page_cgroup) {
110 return 0; 111 nid = page_to_nid(pfn_to_page(pfn));
111 112 table_size = sizeof(struct page_cgroup) * PAGES_PER_SECTION;
112 nid = page_to_nid(pfn_to_page(pfn)); 113 if (slab_is_available()) {
113 114 base = kmalloc_node(table_size, GFP_KERNEL, nid);
114 table_size = sizeof(struct page_cgroup) * PAGES_PER_SECTION; 115 if (!base)
115 if (slab_is_available()) { 116 base = vmalloc_node(table_size, nid);
116 base = kmalloc_node(table_size, GFP_KERNEL, nid); 117 } else {
117 if (!base) 118 base = __alloc_bootmem_node_nopanic(NODE_DATA(nid),
118 base = vmalloc_node(table_size, nid); 119 table_size,
119 } else {
120 base = __alloc_bootmem_node_nopanic(NODE_DATA(nid), table_size,
121 PAGE_SIZE, __pa(MAX_DMA_ADDRESS)); 120 PAGE_SIZE, __pa(MAX_DMA_ADDRESS));
121 }
122 } else {
123 /*
124 * We don't have to allocate page_cgroup again, but
125 * address of memmap may be changed. So, we have to initialize
126 * again.
127 */
128 base = section->page_cgroup + pfn;
129 table_size = 0;
130 /* check address of memmap is changed or not. */
131 if (base->page == pfn_to_page(pfn))
132 return 0;
122 } 133 }
123 134
124 if (!base) { 135 if (!base) {
@@ -158,7 +169,7 @@ void __free_page_cgroup(unsigned long pfn)
158 } 169 }
159} 170}
160 171
161int online_page_cgroup(unsigned long start_pfn, 172int __meminit online_page_cgroup(unsigned long start_pfn,
162 unsigned long nr_pages, 173 unsigned long nr_pages,
163 int nid) 174 int nid)
164{ 175{
@@ -183,7 +194,7 @@ int online_page_cgroup(unsigned long start_pfn,
183 return -ENOMEM; 194 return -ENOMEM;
184} 195}
185 196
186int offline_page_cgroup(unsigned long start_pfn, 197int __meminit offline_page_cgroup(unsigned long start_pfn,
187 unsigned long nr_pages, int nid) 198 unsigned long nr_pages, int nid)
188{ 199{
189 unsigned long start, end, pfn; 200 unsigned long start, end, pfn;
@@ -197,7 +208,7 @@ int offline_page_cgroup(unsigned long start_pfn,
197 208
198} 209}
199 210
200static int page_cgroup_callback(struct notifier_block *self, 211static int __meminit page_cgroup_callback(struct notifier_block *self,
201 unsigned long action, void *arg) 212 unsigned long action, void *arg)
202{ 213{
203 struct memory_notify *mn = arg; 214 struct memory_notify *mn = arg;
@@ -207,18 +218,23 @@ static int page_cgroup_callback(struct notifier_block *self,
207 ret = online_page_cgroup(mn->start_pfn, 218 ret = online_page_cgroup(mn->start_pfn,
208 mn->nr_pages, mn->status_change_nid); 219 mn->nr_pages, mn->status_change_nid);
209 break; 220 break;
210 case MEM_CANCEL_ONLINE:
211 case MEM_OFFLINE: 221 case MEM_OFFLINE:
212 offline_page_cgroup(mn->start_pfn, 222 offline_page_cgroup(mn->start_pfn,
213 mn->nr_pages, mn->status_change_nid); 223 mn->nr_pages, mn->status_change_nid);
214 break; 224 break;
225 case MEM_CANCEL_ONLINE:
215 case MEM_GOING_OFFLINE: 226 case MEM_GOING_OFFLINE:
216 break; 227 break;
217 case MEM_ONLINE: 228 case MEM_ONLINE:
218 case MEM_CANCEL_OFFLINE: 229 case MEM_CANCEL_OFFLINE:
219 break; 230 break;
220 } 231 }
221 ret = notifier_from_errno(ret); 232
233 if (ret)
234 ret = notifier_from_errno(ret);
235 else
236 ret = NOTIFY_OK;
237
222 return ret; 238 return ret;
223} 239}
224 240
@@ -248,7 +264,7 @@ void __init page_cgroup_init(void)
248 " want\n"); 264 " want\n");
249} 265}
250 266
251void __init pgdat_page_cgroup_init(struct pglist_data *pgdat) 267void __meminit pgdat_page_cgroup_init(struct pglist_data *pgdat)
252{ 268{
253 return; 269 return;
254} 270}