diff options
Diffstat (limited to 'mm/thrash.c')
-rw-r--r-- | mm/thrash.c | 87 |
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 | ||
25 | static DEFINE_SPINLOCK(swap_token_lock); | 26 | static DEFINE_SPINLOCK(swap_token_lock); |
26 | struct mm_struct *swap_token_mm; | 27 | struct mm_struct *swap_token_mm; |
28 | struct mem_cgroup *swap_token_memcg; | ||
27 | static unsigned int global_faults; | 29 | static unsigned int global_faults; |
28 | 30 | ||
31 | #ifdef CONFIG_CGROUP_MEM_RES_CTLR | ||
32 | static 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 | ||
43 | static struct mem_cgroup *swap_token_memcg_from_mm(struct mm_struct *mm) | ||
44 | { | ||
45 | return NULL; | ||
46 | } | ||
47 | #endif | ||
48 | |||
29 | void grab_swap_token(struct mm_struct *mm) | 49 | void 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 | |||
64 | out: | 80 | out: |
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 | |||
86 | replace_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. */ |
71 | void __put_swap_token(struct mm_struct *mm) | 94 | void __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 | |||
104 | static 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 | |||
115 | void 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 | } | ||