aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/memcontrol.h6
-rw-r--r--include/linux/swap.h8
-rw-r--r--mm/memcontrol.c16
-rw-r--r--mm/thrash.c87
-rw-r--r--mm/vmscan.c4
5 files changed, 85 insertions, 36 deletions
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index 9724a38ee69d..50940da6adf3 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -84,6 +84,7 @@ int task_in_mem_cgroup(struct task_struct *task, const struct mem_cgroup *mem);
84 84
85extern struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page); 85extern struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page);
86extern struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p); 86extern struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p);
87extern struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm);
87 88
88static inline 89static inline
89int mm_match_cgroup(const struct mm_struct *mm, const struct mem_cgroup *cgroup) 90int mm_match_cgroup(const struct mm_struct *mm, const struct mem_cgroup *cgroup)
@@ -246,6 +247,11 @@ static inline struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page)
246 return NULL; 247 return NULL;
247} 248}
248 249
250static inline struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm)
251{
252 return NULL;
253}
254
249static inline int mm_match_cgroup(struct mm_struct *mm, struct mem_cgroup *mem) 255static inline int mm_match_cgroup(struct mm_struct *mm, struct mem_cgroup *mem)
250{ 256{
251 return 1; 257 return 1;
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 384eb5fe530b..e70564647039 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -358,6 +358,7 @@ struct backing_dev_info;
358extern struct mm_struct *swap_token_mm; 358extern struct mm_struct *swap_token_mm;
359extern void grab_swap_token(struct mm_struct *); 359extern void grab_swap_token(struct mm_struct *);
360extern void __put_swap_token(struct mm_struct *); 360extern void __put_swap_token(struct mm_struct *);
361extern void disable_swap_token(struct mem_cgroup *memcg);
361 362
362static inline int has_swap_token(struct mm_struct *mm) 363static inline int has_swap_token(struct mm_struct *mm)
363{ 364{
@@ -370,11 +371,6 @@ static inline void put_swap_token(struct mm_struct *mm)
370 __put_swap_token(mm); 371 __put_swap_token(mm);
371} 372}
372 373
373static inline void disable_swap_token(void)
374{
375 put_swap_token(swap_token_mm);
376}
377
378#ifdef CONFIG_CGROUP_MEM_RES_CTLR 374#ifdef CONFIG_CGROUP_MEM_RES_CTLR
379extern void 375extern void
380mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout); 376mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout);
@@ -500,7 +496,7 @@ static inline int has_swap_token(struct mm_struct *mm)
500 return 0; 496 return 0;
501} 497}
502 498
503static inline void disable_swap_token(void) 499static inline void disable_swap_token(struct mem_cgroup *memcg)
504{ 500{
505} 501}
506 502
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index bd9052a5d3ad..e37c44d88d46 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -735,7 +735,7 @@ struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p)
735 struct mem_cgroup, css); 735 struct mem_cgroup, css);
736} 736}
737 737
738static struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm) 738struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm)
739{ 739{
740 struct mem_cgroup *mem = NULL; 740 struct mem_cgroup *mem = NULL;
741 741
@@ -5414,18 +5414,16 @@ static void mem_cgroup_move_task(struct cgroup_subsys *ss,
5414 struct cgroup *old_cont, 5414 struct cgroup *old_cont,
5415 struct task_struct *p) 5415 struct task_struct *p)
5416{ 5416{
5417 struct mm_struct *mm; 5417 struct mm_struct *mm = get_task_mm(p);
5418 5418
5419 if (!mc.to)
5420 /* no need to move charge */
5421 return;
5422
5423 mm = get_task_mm(p);
5424 if (mm) { 5419 if (mm) {
5425 mem_cgroup_move_charge(mm); 5420 if (mc.to)
5421 mem_cgroup_move_charge(mm);
5422 put_swap_token(mm);
5426 mmput(mm); 5423 mmput(mm);
5427 } 5424 }
5428 mem_cgroup_clear_mc(); 5425 if (mc.to)
5426 mem_cgroup_clear_mc();
5429} 5427}
5430#else /* !CONFIG_MMU */ 5428#else /* !CONFIG_MMU */
5431static int mem_cgroup_can_attach(struct cgroup_subsys *ss, 5429static int mem_cgroup_can_attach(struct cgroup_subsys *ss,
diff --git a/mm/thrash.c b/mm/thrash.c
index 2372d4ed5dd8..6cdf86511385 100644
--- a/mm/thrash.c
+++ b/mm/thrash.c
@@ -21,11 +21,31 @@
21#include <linux/mm.h> 21#include <linux/mm.h>
22#include <linux/sched.h> 22#include <linux/sched.h>
23#include <linux/swap.h> 23#include <linux/swap.h>
24#include <linux/memcontrol.h>
24 25
25static DEFINE_SPINLOCK(swap_token_lock); 26static DEFINE_SPINLOCK(swap_token_lock);
26struct mm_struct *swap_token_mm; 27struct mm_struct *swap_token_mm;
28struct mem_cgroup *swap_token_memcg;
27static unsigned int global_faults; 29static unsigned int global_faults;
28 30
31#ifdef CONFIG_CGROUP_MEM_RES_CTLR
32static struct mem_cgroup *swap_token_memcg_from_mm(struct mm_struct *mm)
33{
34 struct mem_cgroup *memcg;
35
36 memcg = try_get_mem_cgroup_from_mm(mm);
37 if (memcg)
38 css_put(mem_cgroup_css(memcg));
39
40 return memcg;
41}
42#else
43static struct mem_cgroup *swap_token_memcg_from_mm(struct mm_struct *mm)
44{
45 return NULL;
46}
47#endif
48
29void grab_swap_token(struct mm_struct *mm) 49void grab_swap_token(struct mm_struct *mm)
30{ 50{
31 int current_interval; 51 int current_interval;
@@ -38,40 +58,69 @@ void grab_swap_token(struct mm_struct *mm)
38 return; 58 return;
39 59
40 /* First come first served */ 60 /* First come first served */
41 if (swap_token_mm == NULL) { 61 if (!swap_token_mm)
42 mm->token_priority = mm->token_priority + 2; 62 goto replace_token;
43 swap_token_mm = mm; 63
64 if (mm == swap_token_mm) {
65 mm->token_priority += 2;
44 goto out; 66 goto out;
45 } 67 }
46 68
47 if (mm != swap_token_mm) { 69 if (current_interval < mm->last_interval)
48 if (current_interval < mm->last_interval) 70 mm->token_priority++;
49 mm->token_priority++; 71 else {
50 else { 72 if (likely(mm->token_priority > 0))
51 if (likely(mm->token_priority > 0)) 73 mm->token_priority--;
52 mm->token_priority--;
53 }
54 /* Check if we deserve the token */
55 if (mm->token_priority > swap_token_mm->token_priority) {
56 mm->token_priority += 2;
57 swap_token_mm = mm;
58 }
59 } else {
60 /* Token holder came in again! */
61 mm->token_priority += 2;
62 } 74 }
63 75
76 /* Check if we deserve the token */
77 if (mm->token_priority > swap_token_mm->token_priority)
78 goto replace_token;
79
64out: 80out:
65 mm->faultstamp = global_faults; 81 mm->faultstamp = global_faults;
66 mm->last_interval = current_interval; 82 mm->last_interval = current_interval;
67 spin_unlock(&swap_token_lock); 83 spin_unlock(&swap_token_lock);
84 return;
85
86replace_token:
87 mm->token_priority += 2;
88 swap_token_mm = mm;
89 swap_token_memcg = swap_token_memcg_from_mm(mm);
90 goto out;
68} 91}
69 92
70/* Called on process exit. */ 93/* Called on process exit. */
71void __put_swap_token(struct mm_struct *mm) 94void __put_swap_token(struct mm_struct *mm)
72{ 95{
73 spin_lock(&swap_token_lock); 96 spin_lock(&swap_token_lock);
74 if (likely(mm == swap_token_mm)) 97 if (likely(mm == swap_token_mm)) {
75 swap_token_mm = NULL; 98 swap_token_mm = NULL;
99 swap_token_memcg = NULL;
100 }
76 spin_unlock(&swap_token_lock); 101 spin_unlock(&swap_token_lock);
77} 102}
103
104static bool match_memcg(struct mem_cgroup *a, struct mem_cgroup *b)
105{
106 if (!a)
107 return true;
108 if (!b)
109 return true;
110 if (a == b)
111 return true;
112 return false;
113}
114
115void disable_swap_token(struct mem_cgroup *memcg)
116{
117 /* memcg reclaim don't disable unrelated mm token. */
118 if (match_memcg(memcg, swap_token_memcg)) {
119 spin_lock(&swap_token_lock);
120 if (match_memcg(memcg, swap_token_memcg)) {
121 swap_token_mm = NULL;
122 swap_token_memcg = NULL;
123 }
124 spin_unlock(&swap_token_lock);
125 }
126}
diff --git a/mm/vmscan.c b/mm/vmscan.c
index faa0a088f9cc..dbe6ea321df4 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -2081,7 +2081,7 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist,
2081 for (priority = DEF_PRIORITY; priority >= 0; priority--) { 2081 for (priority = DEF_PRIORITY; priority >= 0; priority--) {
2082 sc->nr_scanned = 0; 2082 sc->nr_scanned = 0;
2083 if (!priority) 2083 if (!priority)
2084 disable_swap_token(); 2084 disable_swap_token(sc->mem_cgroup);
2085 total_scanned += shrink_zones(priority, zonelist, sc); 2085 total_scanned += shrink_zones(priority, zonelist, sc);
2086 /* 2086 /*
2087 * Don't shrink slabs when reclaiming memory from 2087 * Don't shrink slabs when reclaiming memory from
@@ -2407,7 +2407,7 @@ loop_again:
2407 2407
2408 /* The swap token gets in the way of swapout... */ 2408 /* The swap token gets in the way of swapout... */
2409 if (!priority) 2409 if (!priority)
2410 disable_swap_token(); 2410 disable_swap_token(NULL);
2411 2411
2412 all_zones_ok = 1; 2412 all_zones_ok = 1;
2413 balanced = 0; 2413 balanced = 0;