From: KAMEZAWA Hiroyuki mem_cgroup_uncharge() against old page is done after radix-tree-replacement. And there were special handling to ingore swap-cache page. But, shmem can be swap-cache and file-cache at the same time. Chekcing PageSwapCache() is not correct here. Check PageAnon() instead. Signed-off-by: KAMEZAWA Hiroyuki Acked-by: Daisuke Nishimura Signed-off-by: KOSAKI Motohiro Cc: Balbir Singh Cc: "Eric W. Biederman" Cc: Pavel Emelyanov Cc: Li Zefan Cc: Hugh Dickins Cc: YAMAMOTO Takashi Cc: Paul Menage Cc: David Rientjes Signed-off-by: Andrew Morton --- mm/migrate.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff -puN mm/migrate.c~memcg-handle-swap-cache-fix-shmem-page-migration-incorrectness-on-memcgroup mm/migrate.c --- a/mm/migrate.c~memcg-handle-swap-cache-fix-shmem-page-migration-incorrectness-on-memcgroup +++ a/mm/migrate.c @@ -358,7 +358,13 @@ static int migrate_page_move_mapping(str __inc_zone_page_state(newpage, NR_FILE_PAGES); write_unlock_irq(&mapping->tree_lock); - if (!PageSwapCache(newpage)) + + /* + * The page is removed from radix-tree implicitly. + * We uncharge it here but swap cache of anonymous page should be + * uncharged by mem_cgroup_ucharge_page(). + */ + if (!PageAnon(newpage)) mem_cgroup_uncharge_cache_page(page); return 0; @@ -402,7 +408,8 @@ static void migrate_page_copy(struct pag /* * SwapCache is removed implicitly. Uncharge against swapcache * should be called after ClearPageSwapCache() because - * mem_cgroup_uncharge_page checks the flag. + * mem_cgroup_uncharge_page checks the flag. shmem's swap cache + * is uncharged before here. */ mem_cgroup_uncharge_page(page); } _