aboutsummaryrefslogtreecommitdiffstats
path: root/mm/thrash.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/thrash.c')
-rw-r--r--mm/thrash.c87
1 files changed, 68 insertions, 19 deletions
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}