diff options
-rw-r--r-- | include/linux/memcontrol.h | 6 | ||||
-rw-r--r-- | include/linux/swap.h | 8 | ||||
-rw-r--r-- | mm/memcontrol.c | 16 | ||||
-rw-r--r-- | mm/thrash.c | 87 | ||||
-rw-r--r-- | mm/vmscan.c | 4 |
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 | ||
85 | extern struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page); | 85 | extern struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page); |
86 | extern struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p); | 86 | extern struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p); |
87 | extern struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm); | ||
87 | 88 | ||
88 | static inline | 89 | static inline |
89 | int mm_match_cgroup(const struct mm_struct *mm, const struct mem_cgroup *cgroup) | 90 | int 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 | ||
250 | static inline struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm) | ||
251 | { | ||
252 | return NULL; | ||
253 | } | ||
254 | |||
249 | static inline int mm_match_cgroup(struct mm_struct *mm, struct mem_cgroup *mem) | 255 | static 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; | |||
358 | extern struct mm_struct *swap_token_mm; | 358 | extern struct mm_struct *swap_token_mm; |
359 | extern void grab_swap_token(struct mm_struct *); | 359 | extern void grab_swap_token(struct mm_struct *); |
360 | extern void __put_swap_token(struct mm_struct *); | 360 | extern void __put_swap_token(struct mm_struct *); |
361 | extern void disable_swap_token(struct mem_cgroup *memcg); | ||
361 | 362 | ||
362 | static inline int has_swap_token(struct mm_struct *mm) | 363 | static 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 | ||
373 | static 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 |
379 | extern void | 375 | extern void |
380 | mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout); | 376 | mem_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 | ||
503 | static inline void disable_swap_token(void) | 499 | static 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 | ||
738 | static struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm) | 738 | struct 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 */ |
5431 | static int mem_cgroup_can_attach(struct cgroup_subsys *ss, | 5429 | static 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 | ||
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 | } | ||
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; |