Commit 78fb74669e80883323391090e4d26d17fe29488f
Committed by
Linus Torvalds
1 parent
8cdea7c054
Exists in
master
and in
4 other branches
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>
Showing 5 changed files with 104 additions and 7 deletions Side-by-side Diff
include/linux/memcontrol.h
... | ... | @@ -3,6 +3,9 @@ |
3 | 3 | * Copyright IBM Corporation, 2007 |
4 | 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 | 9 | * This program is free software; you can redistribute it and/or modify |
7 | 10 | * it under the terms of the GNU General Public License as published by |
8 | 11 | * the Free Software Foundation; either version 2 of the License, or |
... | ... | @@ -16,6 +19,39 @@ |
16 | 19 | |
17 | 20 | #ifndef _LINUX_MEMCONTROL_H |
18 | 21 | #define _LINUX_MEMCONTROL_H |
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 */ | |
19 | 55 | |
20 | 56 | #endif /* _LINUX_MEMCONTROL_H */ |
include/linux/mm_types.h
... | ... | @@ -88,6 +88,9 @@ |
88 | 88 | void *virtual; /* Kernel virtual address (NULL if |
89 | 89 | not kmapped, ie. highmem) */ |
90 | 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 @@ |
219 | 222 | /* aio bits */ |
220 | 223 | rwlock_t ioctx_list_lock; |
221 | 224 | struct kioctx *ioctx_list; |
225 | +#ifdef CONFIG_CGROUP_MEM_CONT | |
226 | + struct mem_cgroup *mem_cgroup; | |
227 | +#endif | |
222 | 228 | }; |
223 | 229 | |
224 | 230 | #endif /* _LINUX_MM_TYPES_H */ |
include/linux/sched.h
kernel/fork.c
... | ... | @@ -40,6 +40,7 @@ |
40 | 40 | #include <linux/ptrace.h> |
41 | 41 | #include <linux/mount.h> |
42 | 42 | #include <linux/audit.h> |
43 | +#include <linux/memcontrol.h> | |
43 | 44 | #include <linux/profile.h> |
44 | 45 | #include <linux/rmap.h> |
45 | 46 | #include <linux/acct.h> |
... | ... | @@ -340,7 +341,7 @@ |
340 | 341 | |
341 | 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 | 346 | atomic_set(&mm->mm_users, 1); |
346 | 347 | atomic_set(&mm->mm_count, 1); |
347 | 348 | |
... | ... | @@ -357,11 +358,14 @@ |
357 | 358 | mm->ioctx_list = NULL; |
358 | 359 | mm->free_area_cache = TASK_UNMAPPED_BASE; |
359 | 360 | mm->cached_hole_size = ~0UL; |
361 | + mm_init_cgroup(mm, p); | |
360 | 362 | |
361 | 363 | if (likely(!mm_alloc_pgd(mm))) { |
362 | 364 | mm->def_flags = 0; |
363 | 365 | return mm; |
364 | 366 | } |
367 | + | |
368 | + mm_free_cgroup(mm); | |
365 | 369 | free_mm(mm); |
366 | 370 | return NULL; |
367 | 371 | } |
... | ... | @@ -376,7 +380,7 @@ |
376 | 380 | mm = allocate_mm(); |
377 | 381 | if (mm) { |
378 | 382 | memset(mm, 0, sizeof(*mm)); |
379 | - mm = mm_init(mm); | |
383 | + mm = mm_init(mm, current); | |
380 | 384 | } |
381 | 385 | return mm; |
382 | 386 | } |
... | ... | @@ -390,6 +394,7 @@ |
390 | 394 | { |
391 | 395 | BUG_ON(mm == &init_mm); |
392 | 396 | mm_free_pgd(mm); |
397 | + mm_free_cgroup(mm); | |
393 | 398 | destroy_context(mm); |
394 | 399 | free_mm(mm); |
395 | 400 | } |
... | ... | @@ -511,7 +516,7 @@ |
511 | 516 | mm->token_priority = 0; |
512 | 517 | mm->last_interval = 0; |
513 | 518 | |
514 | - if (!mm_init(mm)) | |
519 | + if (!mm_init(mm, tsk)) | |
515 | 520 | goto fail_nomem; |
516 | 521 | |
517 | 522 | if (init_new_context(tsk, mm)) |
mm/memcontrol.c
... | ... | @@ -3,6 +3,9 @@ |
3 | 3 | * Copyright IBM Corporation, 2007 |
4 | 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 | 9 | * This program is free software; you can redistribute it and/or modify |
7 | 10 | * it under the terms of the GNU General Public License as published by |
8 | 11 | * the Free Software Foundation; either version 2 of the License, or |
... | ... | @@ -17,6 +20,7 @@ |
17 | 20 | #include <linux/res_counter.h> |
18 | 21 | #include <linux/memcontrol.h> |
19 | 22 | #include <linux/cgroup.h> |
23 | +#include <linux/mm.h> | |
20 | 24 | |
21 | 25 | struct cgroup_subsys mem_cgroup_subsys; |
22 | 26 | |
... | ... | @@ -35,6 +39,13 @@ |
35 | 39 | * the counter to account for memory usage |
36 | 40 | */ |
37 | 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 @@ |
56 | 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 | 101 | static ssize_t mem_cgroup_read(struct cgroup *cont, struct cftype *cft, |
60 | 102 | struct file *file, char __user *userbuf, size_t nbytes, |
61 | 103 | loff_t *ppos) |
62 | 104 | |
63 | 105 | |
... | ... | @@ -91,15 +133,22 @@ |
91 | 133 | }, |
92 | 134 | }; |
93 | 135 | |
136 | +static struct mem_cgroup init_mem_cgroup; | |
137 | + | |
94 | 138 | static struct cgroup_subsys_state * |
95 | 139 | mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont) |
96 | 140 | { |
97 | 141 | struct mem_cgroup *mem; |
98 | 142 | |
99 | - mem = kzalloc(sizeof(struct mem_cgroup), GFP_KERNEL); | |
100 | - if (!mem) | |
101 | - return -ENOMEM; | |
143 | + if (unlikely((cont->parent) == NULL)) { | |
144 | + mem = &init_mem_cgroup; | |
145 | + init_mm.mem_cgroup = mem; | |
146 | + } else | |
147 | + mem = kzalloc(sizeof(struct mem_cgroup), GFP_KERNEL); | |
102 | 148 | |
149 | + if (mem == NULL) | |
150 | + return NULL; | |
151 | + | |
103 | 152 | res_counter_init(&mem->res); |
104 | 153 | return &mem->css; |
105 | 154 | } |
... | ... | @@ -123,6 +172,6 @@ |
123 | 172 | .create = mem_cgroup_create, |
124 | 173 | .destroy = mem_cgroup_destroy, |
125 | 174 | .populate = mem_cgroup_populate, |
126 | - .early_init = 0, | |
175 | + .early_init = 1, | |
127 | 176 | }; |