From: KAMEZAWA Hiroyuki Now (-mm queue), SwapCache is handled by memcg. But Handling migration of swap-cache was wrong. Fix to call uncharge() after ClearPageSwapCache() as __delete_from_swap_cache()(swap_state.c) does. Signed-off-by: KAMEZAWA Hiroyuki Tested-by: Daisuke Nishimura 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 | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff -puN mm/migrate.c~memcg-handle-swap-cache-fix mm/migrate.c --- a/mm/migrate.c~memcg-handle-swap-cache-fix +++ a/mm/migrate.c @@ -358,10 +358,8 @@ static int migrate_page_move_mapping(str __inc_zone_page_state(newpage, NR_FILE_PAGES); write_unlock_irq(&mapping->tree_lock); - if (!PageSwapCache(newpage)) { + if (!PageSwapCache(newpage)) mem_cgroup_uncharge_cache_page(page); - } else - mem_cgroup_uncharge_page(page); return 0; } @@ -399,7 +397,15 @@ static void migrate_page_copy(struct pag } #ifdef CONFIG_SWAP - ClearPageSwapCache(page); + if (PageSwapCache(page)) { + ClearPageSwapCache(page); + /* + * SwapCache is removed implicitly. Uncharge against swapcache + * should be called after ClearPageSwapCache() because + * mem_cgroup_uncharge_page checks the flag. + */ + mem_cgroup_uncharge_page(page); + } #endif ClearPageActive(page); ClearPagePrivate(page); _