|
@@ -4,8 +4,10 @@
|
|
#include <linux/bit_spinlock.h>
|
|
#include <linux/bit_spinlock.h>
|
|
#include <linux/page_cgroup.h>
|
|
#include <linux/page_cgroup.h>
|
|
#include <linux/hash.h>
|
|
#include <linux/hash.h>
|
|
|
|
+#include <linux/slab.h>
|
|
#include <linux/memory.h>
|
|
#include <linux/memory.h>
|
|
#include <linux/vmalloc.h>
|
|
#include <linux/vmalloc.h>
|
|
|
|
+#include <linux/cgroup.h>
|
|
|
|
|
|
static void __meminit
|
|
static void __meminit
|
|
__init_page_cgroup(struct page_cgroup *pc, unsigned long pfn)
|
|
__init_page_cgroup(struct page_cgroup *pc, unsigned long pfn)
|
|
@@ -67,6 +69,9 @@ void __init page_cgroup_init(void)
|
|
|
|
|
|
int nid, fail;
|
|
int nid, fail;
|
|
|
|
|
|
|
|
+ if (mem_cgroup_subsys.disabled)
|
|
|
|
+ return;
|
|
|
|
+
|
|
for_each_online_node(nid) {
|
|
for_each_online_node(nid) {
|
|
fail = alloc_node_page_cgroup(nid);
|
|
fail = alloc_node_page_cgroup(nid);
|
|
if (fail)
|
|
if (fail)
|
|
@@ -107,9 +112,14 @@ int __meminit init_section_page_cgroup(unsigned long pfn)
|
|
nid = page_to_nid(pfn_to_page(pfn));
|
|
nid = page_to_nid(pfn_to_page(pfn));
|
|
|
|
|
|
table_size = sizeof(struct page_cgroup) * PAGES_PER_SECTION;
|
|
table_size = sizeof(struct page_cgroup) * PAGES_PER_SECTION;
|
|
- base = kmalloc_node(table_size, GFP_KERNEL, nid);
|
|
|
|
- if (!base)
|
|
|
|
- base = vmalloc_node(table_size, nid);
|
|
|
|
|
|
+ if (slab_is_available()) {
|
|
|
|
+ base = kmalloc_node(table_size, GFP_KERNEL, nid);
|
|
|
|
+ if (!base)
|
|
|
|
+ base = vmalloc_node(table_size, nid);
|
|
|
|
+ } else {
|
|
|
|
+ base = __alloc_bootmem_node_nopanic(NODE_DATA(nid), table_size,
|
|
|
|
+ PAGE_SIZE, __pa(MAX_DMA_ADDRESS));
|
|
|
|
+ }
|
|
|
|
|
|
if (!base) {
|
|
if (!base) {
|
|
printk(KERN_ERR "page cgroup allocation failure\n");
|
|
printk(KERN_ERR "page cgroup allocation failure\n");
|
|
@@ -136,11 +146,16 @@ void __free_page_cgroup(unsigned long pfn)
|
|
if (!ms || !ms->page_cgroup)
|
|
if (!ms || !ms->page_cgroup)
|
|
return;
|
|
return;
|
|
base = ms->page_cgroup + pfn;
|
|
base = ms->page_cgroup + pfn;
|
|
- ms->page_cgroup = NULL;
|
|
|
|
- if (is_vmalloc_addr(base))
|
|
|
|
|
|
+ if (is_vmalloc_addr(base)) {
|
|
vfree(base);
|
|
vfree(base);
|
|
- else
|
|
|
|
- kfree(base);
|
|
|
|
|
|
+ ms->page_cgroup = NULL;
|
|
|
|
+ } else {
|
|
|
|
+ struct page *page = virt_to_page(base);
|
|
|
|
+ if (!PageReserved(page)) { /* Is bootmem ? */
|
|
|
|
+ kfree(base);
|
|
|
|
+ ms->page_cgroup = NULL;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
int online_page_cgroup(unsigned long start_pfn,
|
|
int online_page_cgroup(unsigned long start_pfn,
|
|
@@ -214,6 +229,9 @@ void __init page_cgroup_init(void)
|
|
unsigned long pfn;
|
|
unsigned long pfn;
|
|
int fail = 0;
|
|
int fail = 0;
|
|
|
|
|
|
|
|
+ if (mem_cgroup_subsys.disabled)
|
|
|
|
+ return;
|
|
|
|
+
|
|
for (pfn = 0; !fail && pfn < max_pfn; pfn += PAGES_PER_SECTION) {
|
|
for (pfn = 0; !fail && pfn < max_pfn; pfn += PAGES_PER_SECTION) {
|
|
if (!pfn_present(pfn))
|
|
if (!pfn_present(pfn))
|
|
continue;
|
|
continue;
|