diff options
-rw-r--r-- | include/linux/memcontrol.h | 36 | ||||
-rw-r--r-- | include/linux/mm_types.h | 6 | ||||
-rw-r--r-- | include/linux/sched.h | 1 | ||||
-rw-r--r-- | kernel/fork.c | 11 | ||||
-rw-r--r-- | mm/memcontrol.c | 57 |
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 | ||
23 | struct mem_cgroup; | ||
24 | struct page_cgroup; | ||
25 | |||
26 | #ifdef CONFIG_CGROUP_MEM_CONT | ||
27 | |||
28 | extern void mm_init_cgroup(struct mm_struct *mm, struct task_struct *p); | ||
29 | extern void mm_free_cgroup(struct mm_struct *mm); | ||
30 | extern void page_assign_page_cgroup(struct page *page, | ||
31 | struct page_cgroup *pc); | ||
32 | extern struct page_cgroup *page_get_page_cgroup(struct page *page); | ||
33 | |||
34 | #else /* CONFIG_CGROUP_MEM_CONT */ | ||
35 | static inline void mm_init_cgroup(struct mm_struct *mm, | ||
36 | struct task_struct *p) | ||
37 | { | ||
38 | } | ||
39 | |||
40 | static inline void mm_free_cgroup(struct mm_struct *mm) | ||
41 | { | ||
42 | } | ||
43 | |||
44 | static inline void page_assign_page_cgroup(struct page *page, | ||
45 | struct page_cgroup *pc) | ||
46 | { | ||
47 | } | ||
48 | |||
49 | static 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 | ||
95 | struct mem_cgroup; | ||
95 | struct exec_domain; | 96 | struct exec_domain; |
96 | struct futex_pi_state; | 97 | struct futex_pi_state; |
97 | struct robust_list_head; | 98 | struct 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 | ||
343 | static struct mm_struct * mm_init(struct mm_struct * mm) | 344 | static 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 | ||
21 | struct cgroup_subsys mem_cgroup_subsys; | 25 | struct 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 | ||
70 | static inline | ||
71 | struct 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 | |||
77 | void 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 | |||
86 | void mm_free_cgroup(struct mm_struct *mm) | ||
87 | { | ||
88 | css_put(&mm->mem_cgroup->css); | ||
89 | } | ||
90 | |||
91 | void page_assign_page_cgroup(struct page *page, struct page_cgroup *pc) | ||
92 | { | ||
93 | page->page_cgroup = (unsigned long)pc; | ||
94 | } | ||
95 | |||
96 | struct page_cgroup *page_get_page_cgroup(struct page *page) | ||
97 | { | ||
98 | return page->page_cgroup; | ||
99 | } | ||
100 | |||
59 | static ssize_t mem_cgroup_read(struct cgroup *cont, struct cftype *cft, | 101 | static 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 | ||
136 | static struct mem_cgroup init_mem_cgroup; | ||
137 | |||
94 | static struct cgroup_subsys_state * | 138 | static struct cgroup_subsys_state * |
95 | mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont) | 139 | mem_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 | }; |