Commit 78fb74669e80883323391090e4d26d17fe29488f

Authored by Pavel Emelianov
Committed by Linus Torvalds
1 parent 8cdea7c054

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
... ... @@ -92,6 +92,7 @@
92 92  
93 93 #include <asm/processor.h>
94 94  
  95 +struct mem_cgroup;
95 96 struct exec_domain;
96 97 struct futex_pi_state;
97 98 struct robust_list_head;
... ... @@ -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))
... ... @@ -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 };