aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Emelianov <xemul@openvz.org>2008-02-07 03:13:51 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-07 11:42:18 -0500
commit78fb74669e80883323391090e4d26d17fe29488f (patch)
tree9154b703510415ae87bdae8750c1054e79710c61
parent8cdea7c05454260c0d4d83503949c358eb131d17 (diff)
Memory controller: accounting setup
Basic setup routines, the mm_struct has a pointer to the cgroup that it belongs to and the the page has a page_cgroup associated with it. Signed-off-by: Pavel Emelianov <xemul@openvz.org> Signed-off-by: Balbir Singh <balbir@linux.vnet.ibm.com> Cc: Paul Menage <menage@google.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Nick Piggin <nickpiggin@yahoo.com.au> Cc: Kirill Korotaev <dev@sw.ru> Cc: Herbert Poetzl <herbert@13thfloor.at> Cc: David Rientjes <rientjes@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--include/linux/memcontrol.h36
-rw-r--r--include/linux/mm_types.h6
-rw-r--r--include/linux/sched.h1
-rw-r--r--kernel/fork.c11
-rw-r--r--mm/memcontrol.c57
5 files changed, 104 insertions, 7 deletions
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index 3f121b27677a..7d1f119c796e 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -3,6 +3,9 @@
3 * Copyright IBM Corporation, 2007 3 * Copyright IBM Corporation, 2007
4 * Author Balbir Singh <balbir@linux.vnet.ibm.com> 4 * Author Balbir Singh <balbir@linux.vnet.ibm.com>
5 * 5 *
6 * Copyright 2007 OpenVZ SWsoft Inc
7 * Author: Pavel Emelianov <xemul@openvz.org>
8 *
6 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by 10 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or 11 * the Free Software Foundation; either version 2 of the License, or
@@ -17,5 +20,38 @@
17#ifndef _LINUX_MEMCONTROL_H 20#ifndef _LINUX_MEMCONTROL_H
18#define _LINUX_MEMCONTROL_H 21#define _LINUX_MEMCONTROL_H
19 22
23struct mem_cgroup;
24struct page_cgroup;
25
26#ifdef CONFIG_CGROUP_MEM_CONT
27
28extern void mm_init_cgroup(struct mm_struct *mm, struct task_struct *p);
29extern void mm_free_cgroup(struct mm_struct *mm);
30extern void page_assign_page_cgroup(struct page *page,
31 struct page_cgroup *pc);
32extern struct page_cgroup *page_get_page_cgroup(struct page *page);
33
34#else /* CONFIG_CGROUP_MEM_CONT */
35static inline void mm_init_cgroup(struct mm_struct *mm,
36 struct task_struct *p)
37{
38}
39
40static inline void mm_free_cgroup(struct mm_struct *mm)
41{
42}
43
44static inline void page_assign_page_cgroup(struct page *page,
45 struct page_cgroup *pc)
46{
47}
48
49static inline struct page_cgroup *page_get_page_cgroup(struct page *page)
50{
51 return NULL;
52}
53
54#endif /* CONFIG_CGROUP_MEM_CONT */
55
20#endif /* _LINUX_MEMCONTROL_H */ 56#endif /* _LINUX_MEMCONTROL_H */
21 57
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index f4c03e0b355e..34023c65d466 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -88,6 +88,9 @@ struct page {
88 void *virtual; /* Kernel virtual address (NULL if 88 void *virtual; /* Kernel virtual address (NULL if
89 not kmapped, ie. highmem) */ 89 not kmapped, ie. highmem) */
90#endif /* WANT_PAGE_VIRTUAL */ 90#endif /* WANT_PAGE_VIRTUAL */
91#ifdef CONFIG_CGROUP_MEM_CONT
92 unsigned long page_cgroup;
93#endif
91}; 94};
92 95
93/* 96/*
@@ -219,6 +222,9 @@ struct mm_struct {
219 /* aio bits */ 222 /* aio bits */
220 rwlock_t ioctx_list_lock; 223 rwlock_t ioctx_list_lock;
221 struct kioctx *ioctx_list; 224 struct kioctx *ioctx_list;
225#ifdef CONFIG_CGROUP_MEM_CONT
226 struct mem_cgroup *mem_cgroup;
227#endif
222}; 228};
223 229
224#endif /* _LINUX_MM_TYPES_H */ 230#endif /* _LINUX_MM_TYPES_H */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 7c8ca05c3cae..8a4812c1c038 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -92,6 +92,7 @@ struct sched_param {
92 92
93#include <asm/processor.h> 93#include <asm/processor.h>
94 94
95struct mem_cgroup;
95struct exec_domain; 96struct exec_domain;
96struct futex_pi_state; 97struct futex_pi_state;
97struct robust_list_head; 98struct robust_list_head;
diff --git a/kernel/fork.c b/kernel/fork.c
index 3995297567a9..b2ef8e4fad70 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -40,6 +40,7 @@
40#include <linux/ptrace.h> 40#include <linux/ptrace.h>
41#include <linux/mount.h> 41#include <linux/mount.h>
42#include <linux/audit.h> 42#include <linux/audit.h>
43#include <linux/memcontrol.h>
43#include <linux/profile.h> 44#include <linux/profile.h>
44#include <linux/rmap.h> 45#include <linux/rmap.h>
45#include <linux/acct.h> 46#include <linux/acct.h>
@@ -340,7 +341,7 @@ __cacheline_aligned_in_smp DEFINE_SPINLOCK(mmlist_lock);
340 341
341#include <linux/init_task.h> 342#include <linux/init_task.h>
342 343
343static struct mm_struct * mm_init(struct mm_struct * mm) 344static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p)
344{ 345{
345 atomic_set(&mm->mm_users, 1); 346 atomic_set(&mm->mm_users, 1);
346 atomic_set(&mm->mm_count, 1); 347 atomic_set(&mm->mm_count, 1);
@@ -357,11 +358,14 @@ static struct mm_struct * mm_init(struct mm_struct * mm)
357 mm->ioctx_list = NULL; 358 mm->ioctx_list = NULL;
358 mm->free_area_cache = TASK_UNMAPPED_BASE; 359 mm->free_area_cache = TASK_UNMAPPED_BASE;
359 mm->cached_hole_size = ~0UL; 360 mm->cached_hole_size = ~0UL;
361 mm_init_cgroup(mm, p);
360 362
361 if (likely(!mm_alloc_pgd(mm))) { 363 if (likely(!mm_alloc_pgd(mm))) {
362 mm->def_flags = 0; 364 mm->def_flags = 0;
363 return mm; 365 return mm;
364 } 366 }
367
368 mm_free_cgroup(mm);
365 free_mm(mm); 369 free_mm(mm);
366 return NULL; 370 return NULL;
367} 371}
@@ -376,7 +380,7 @@ struct mm_struct * mm_alloc(void)
376 mm = allocate_mm(); 380 mm = allocate_mm();
377 if (mm) { 381 if (mm) {
378 memset(mm, 0, sizeof(*mm)); 382 memset(mm, 0, sizeof(*mm));
379 mm = mm_init(mm); 383 mm = mm_init(mm, current);
380 } 384 }
381 return mm; 385 return mm;
382} 386}
@@ -390,6 +394,7 @@ void fastcall __mmdrop(struct mm_struct *mm)
390{ 394{
391 BUG_ON(mm == &init_mm); 395 BUG_ON(mm == &init_mm);
392 mm_free_pgd(mm); 396 mm_free_pgd(mm);
397 mm_free_cgroup(mm);
393 destroy_context(mm); 398 destroy_context(mm);
394 free_mm(mm); 399 free_mm(mm);
395} 400}
@@ -511,7 +516,7 @@ static struct mm_struct *dup_mm(struct task_struct *tsk)
511 mm->token_priority = 0; 516 mm->token_priority = 0;
512 mm->last_interval = 0; 517 mm->last_interval = 0;
513 518
514 if (!mm_init(mm)) 519 if (!mm_init(mm, tsk))
515 goto fail_nomem; 520 goto fail_nomem;
516 521
517 if (init_new_context(tsk, mm)) 522 if (init_new_context(tsk, mm))
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 80e48cd9d0c7..4d4805eb37c7 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -3,6 +3,9 @@
3 * Copyright IBM Corporation, 2007 3 * Copyright IBM Corporation, 2007
4 * Author Balbir Singh <balbir@linux.vnet.ibm.com> 4 * Author Balbir Singh <balbir@linux.vnet.ibm.com>
5 * 5 *
6 * Copyright 2007 OpenVZ SWsoft Inc
7 * Author: Pavel Emelianov <xemul@openvz.org>
8 *
6 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by 10 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or 11 * the Free Software Foundation; either version 2 of the License, or
@@ -17,6 +20,7 @@
17#include <linux/res_counter.h> 20#include <linux/res_counter.h>
18#include <linux/memcontrol.h> 21#include <linux/memcontrol.h>
19#include <linux/cgroup.h> 22#include <linux/cgroup.h>
23#include <linux/mm.h>
20 24
21struct cgroup_subsys mem_cgroup_subsys; 25struct cgroup_subsys mem_cgroup_subsys;
22 26
@@ -35,6 +39,13 @@ struct mem_cgroup {
35 * the counter to account for memory usage 39 * the counter to account for memory usage
36 */ 40 */
37 struct res_counter res; 41 struct res_counter res;
42 /*
43 * Per cgroup active and inactive list, similar to the
44 * per zone LRU lists.
45 * TODO: Consider making these lists per zone
46 */
47 struct list_head active_list;
48 struct list_head inactive_list;
38}; 49};
39 50
40/* 51/*
@@ -56,6 +67,37 @@ struct mem_cgroup *mem_cgroup_from_cont(struct cgroup *cont)
56 css); 67 css);
57} 68}
58 69
70static inline
71struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p)
72{
73 return container_of(task_subsys_state(p, mem_cgroup_subsys_id),
74 struct mem_cgroup, css);
75}
76
77void mm_init_cgroup(struct mm_struct *mm, struct task_struct *p)
78{
79 struct mem_cgroup *mem;
80
81 mem = mem_cgroup_from_task(p);
82 css_get(&mem->css);
83 mm->mem_cgroup = mem;
84}
85
86void mm_free_cgroup(struct mm_struct *mm)
87{
88 css_put(&mm->mem_cgroup->css);
89}
90
91void page_assign_page_cgroup(struct page *page, struct page_cgroup *pc)
92{
93 page->page_cgroup = (unsigned long)pc;
94}
95
96struct page_cgroup *page_get_page_cgroup(struct page *page)
97{
98 return page->page_cgroup;
99}
100
59static ssize_t mem_cgroup_read(struct cgroup *cont, struct cftype *cft, 101static ssize_t mem_cgroup_read(struct cgroup *cont, struct cftype *cft,
60 struct file *file, char __user *userbuf, size_t nbytes, 102 struct file *file, char __user *userbuf, size_t nbytes,
61 loff_t *ppos) 103 loff_t *ppos)
@@ -91,14 +133,21 @@ static struct cftype mem_cgroup_files[] = {
91 }, 133 },
92}; 134};
93 135
136static struct mem_cgroup init_mem_cgroup;
137
94static struct cgroup_subsys_state * 138static struct cgroup_subsys_state *
95mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont) 139mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont)
96{ 140{
97 struct mem_cgroup *mem; 141 struct mem_cgroup *mem;
98 142
99 mem = kzalloc(sizeof(struct mem_cgroup), GFP_KERNEL); 143 if (unlikely((cont->parent) == NULL)) {
100 if (!mem) 144 mem = &init_mem_cgroup;
101 return -ENOMEM; 145 init_mm.mem_cgroup = mem;
146 } else
147 mem = kzalloc(sizeof(struct mem_cgroup), GFP_KERNEL);
148
149 if (mem == NULL)
150 return NULL;
102 151
103 res_counter_init(&mem->res); 152 res_counter_init(&mem->res);
104 return &mem->css; 153 return &mem->css;
@@ -123,5 +172,5 @@ struct cgroup_subsys mem_cgroup_subsys = {
123 .create = mem_cgroup_create, 172 .create = mem_cgroup_create,
124 .destroy = mem_cgroup_destroy, 173 .destroy = mem_cgroup_destroy,
125 .populate = mem_cgroup_populate, 174 .populate = mem_cgroup_populate,
126 .early_init = 0, 175 .early_init = 1,
127}; 176};