diff options
Diffstat (limited to 'mm/page_cgroup.c')
-rw-r--r-- | mm/page_cgroup.c | 32 |
1 files changed, 25 insertions, 7 deletions
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; |