Commit 50de1dd967d4ba3b8a90ebe7a4f5feca24191317
Committed by
Linus Torvalds
1 parent
17295c88a1
memcg: fix memory migration of shmem swapcache
In the current implementation mem_cgroup_end_migration() decides whether the page migration has succeeded or not by checking "oldpage->mapping". But if we are tring to migrate a shmem swapcache, the page->mapping of it is NULL from the begining, so the check would be invalid. As a result, mem_cgroup_end_migration() assumes the migration has succeeded even if it's not, so "newpage" would be freed while it's not uncharged. This patch fixes it by passing mem_cgroup_end_migration() the result of the page migration. Signed-off-by: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp> Reviewed-by: Minchan Kim <minchan.kim@gmail.com> Acked-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Acked-by: Balbir Singh <balbir@linux.vnet.ibm.com> Cc: Minchan Kim <minchan.kim@gmail.com> Reviewed-by: Johannes Weiner <hannes@cmpxchg.org> Cc: Hugh Dickins <hughd@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 3 changed files with 5 additions and 7 deletions Side-by-side Diff
include/linux/memcontrol.h
... | ... | @@ -98,7 +98,7 @@ |
98 | 98 | mem_cgroup_prepare_migration(struct page *page, |
99 | 99 | struct page *newpage, struct mem_cgroup **ptr); |
100 | 100 | extern void mem_cgroup_end_migration(struct mem_cgroup *mem, |
101 | - struct page *oldpage, struct page *newpage); | |
101 | + struct page *oldpage, struct page *newpage, bool migration_ok); | |
102 | 102 | |
103 | 103 | /* |
104 | 104 | * For memory reclaim. |
... | ... | @@ -251,8 +251,7 @@ |
251 | 251 | } |
252 | 252 | |
253 | 253 | static inline void mem_cgroup_end_migration(struct mem_cgroup *mem, |
254 | - struct page *oldpage, | |
255 | - struct page *newpage) | |
254 | + struct page *oldpage, struct page *newpage, bool migration_ok) | |
256 | 255 | { |
257 | 256 | } |
258 | 257 |
mm/memcontrol.c
... | ... | @@ -2896,7 +2896,7 @@ |
2896 | 2896 | |
2897 | 2897 | /* remove redundant charge if migration failed*/ |
2898 | 2898 | void mem_cgroup_end_migration(struct mem_cgroup *mem, |
2899 | - struct page *oldpage, struct page *newpage) | |
2899 | + struct page *oldpage, struct page *newpage, bool migration_ok) | |
2900 | 2900 | { |
2901 | 2901 | struct page *used, *unused; |
2902 | 2902 | struct page_cgroup *pc; |
... | ... | @@ -2905,8 +2905,7 @@ |
2905 | 2905 | return; |
2906 | 2906 | /* blocks rmdir() */ |
2907 | 2907 | cgroup_exclude_rmdir(&mem->css); |
2908 | - /* at migration success, oldpage->mapping is NULL. */ | |
2909 | - if (oldpage->mapping) { | |
2908 | + if (!migration_ok) { | |
2910 | 2909 | used = oldpage; |
2911 | 2910 | unused = newpage; |
2912 | 2911 | } else { |