Skip to content

Commit

Permalink
memcg: fix page_cgroup allocation
Browse files Browse the repository at this point in the history
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

[[email protected]: remove unneeded/bad mem_cgroup_subsys declaration]
[[email protected]: fix build]
Acked-by: Balbir Singh <[email protected]>
Tested-by: Balbir Singh <[email protected]>
Signed-off-by: KAMEZAWA Hiroyuki <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
hkamezawa authored and torvalds committed Oct 23, 2008
1 parent be07c4e commit 94b6da5
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 8 deletions.
5 changes: 5 additions & 0 deletions include/linux/page_cgroup.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,5 +99,10 @@ static inline struct page_cgroup *lookup_page_cgroup(struct page *page)
{
return NULL;
}

static inline void page_cgroup_init(void)
{
}

#endif
#endif
2 changes: 2 additions & 0 deletions init/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
#include <linux/key.h>
#include <linux/unwind.h>
#include <linux/buffer_head.h>
#include <linux/page_cgroup.h>
#include <linux/debug_locks.h>
#include <linux/debugobjects.h>
#include <linux/lockdep.h>
Expand Down Expand Up @@ -647,6 +648,7 @@ asmlinkage void __init start_kernel(void)
vmalloc_init();
vfs_caches_init_early();
cpuset_init_early();
page_cgroup_init();
mem_init();
enable_debug_pagealloc();
cpu_hotplug_init();
Expand Down
1 change: 0 additions & 1 deletion mm/memcontrol.c
Original file line number Diff line number Diff line change
Expand Up @@ -1088,7 +1088,6 @@ mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont)
int node;

if (unlikely((cont->parent) == NULL)) {
page_cgroup_init();
mem = &init_mem_cgroup;
} else {
mem = mem_cgroup_alloc();
Expand Down
32 changes: 25 additions & 7 deletions mm/page_cgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
#include <linux/bit_spinlock.h>
#include <linux/page_cgroup.h>
#include <linux/hash.h>
#include <linux/slab.h>
#include <linux/memory.h>
#include <linux/vmalloc.h>
#include <linux/cgroup.h>

static void __meminit
__init_page_cgroup(struct page_cgroup *pc, unsigned long pfn)
Expand Down Expand Up @@ -67,6 +69,9 @@ void __init page_cgroup_init(void)

int nid, fail;

if (mem_cgroup_subsys.disabled)
return;

for_each_online_node(nid) {
fail = alloc_node_page_cgroup(nid);
if (fail)
Expand Down Expand Up @@ -107,9 +112,14 @@ int __meminit init_section_page_cgroup(unsigned long pfn)
nid = page_to_nid(pfn_to_page(pfn));

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) {
printk(KERN_ERR "page cgroup allocation failure\n");
Expand All @@ -136,11 +146,16 @@ void __free_page_cgroup(unsigned long pfn)
if (!ms || !ms->page_cgroup)
return;
base = ms->page_cgroup + pfn;
ms->page_cgroup = NULL;
if (is_vmalloc_addr(base))
if (is_vmalloc_addr(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,
Expand Down Expand Up @@ -214,6 +229,9 @@ void __init page_cgroup_init(void)
unsigned long pfn;
int fail = 0;

if (mem_cgroup_subsys.disabled)
return;

for (pfn = 0; !fail && pfn < max_pfn; pfn += PAGES_PER_SECTION) {
if (!pfn_present(pfn))
continue;
Expand Down

0 comments on commit 94b6da5

Please sign in to comment.