aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>2012-01-12 20:18:58 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-01-12 23:13:07 -0500
commit4e5f01c2b9b94321992acb09c35d34f5ee5bb274 (patch)
tree4e6ac9d29539dc26468fe2630d0e64cd022b1155
parent36b62ad539498d00c2d280a151abad5f7630fa73 (diff)
memcg: clear pc->mem_cgroup if necessary.
This is a preparation before removing a flag PCG_ACCT_LRU in page_cgroup and reducing atomic ops/complexity in memcg LRU handling. In some cases, pages are added to lru before charge to memcg and pages are not classfied to memory cgroup at lru addtion. Now, the lru where the page should be added is determined a bit in page_cgroup->flags and pc->mem_cgroup. I'd like to remove the check of flag. To handle the case pc->mem_cgroup may contain stale pointers if pages are added to LRU before classification. This patch resets pc->mem_cgroup to root_mem_cgroup before lru additions. [akpm@linux-foundation.org: fix CONFIG_CGROUP_MEM_CONT=n build] [hughd@google.com: fix CONFIG_CGROUP_MEM_RES_CTLR=y CONFIG_CGROUP_MEM_RES_CTLR_SWAP=n build] [akpm@linux-foundation.org: ksm.c needs memcontrol.h, per Michal] [hughd@google.com: stop oops in mem_cgroup_reset_owner()] [hughd@google.com: fix page migration to reset_owner] Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Miklos Szeredi <mszeredi@suse.cz> Acked-by: Michal Hocko <mhocko@suse.cz> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Ying Han <yinghan@google.com> Signed-off-by: Hugh Dickins <hughd@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--include/linux/memcontrol.h5
-rw-r--r--mm/ksm.c11
-rw-r--r--mm/memcontrol.c17
-rw-r--r--mm/migrate.c2
-rw-r--r--mm/swap_state.c10
5 files changed, 45 insertions, 0 deletions
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index b80de520670b..4d34356fe644 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -129,6 +129,7 @@ extern void mem_cgroup_print_oom_info(struct mem_cgroup *memcg,
129extern void mem_cgroup_replace_page_cache(struct page *oldpage, 129extern void mem_cgroup_replace_page_cache(struct page *oldpage,
130 struct page *newpage); 130 struct page *newpage);
131 131
132extern void mem_cgroup_reset_owner(struct page *page);
132#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP 133#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP
133extern int do_swap_account; 134extern int do_swap_account;
134#endif 135#endif
@@ -391,6 +392,10 @@ static inline void mem_cgroup_replace_page_cache(struct page *oldpage,
391 struct page *newpage) 392 struct page *newpage)
392{ 393{
393} 394}
395
396static inline void mem_cgroup_reset_owner(struct page *page)
397{
398}
394#endif /* CONFIG_CGROUP_MEM_CONT */ 399#endif /* CONFIG_CGROUP_MEM_CONT */
395 400
396#if !defined(CONFIG_CGROUP_MEM_RES_CTLR) || !defined(CONFIG_DEBUG_VM) 401#if !defined(CONFIG_CGROUP_MEM_RES_CTLR) || !defined(CONFIG_DEBUG_VM)
diff --git a/mm/ksm.c b/mm/ksm.c
index 310544a379ae..1925ffbfb27f 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -28,6 +28,7 @@
28#include <linux/kthread.h> 28#include <linux/kthread.h>
29#include <linux/wait.h> 29#include <linux/wait.h>
30#include <linux/slab.h> 30#include <linux/slab.h>
31#include <linux/memcontrol.h>
31#include <linux/rbtree.h> 32#include <linux/rbtree.h>
32#include <linux/memory.h> 33#include <linux/memory.h>
33#include <linux/mmu_notifier.h> 34#include <linux/mmu_notifier.h>
@@ -1571,6 +1572,16 @@ struct page *ksm_does_need_to_copy(struct page *page,
1571 1572
1572 new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address); 1573 new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address);
1573 if (new_page) { 1574 if (new_page) {
1575 /*
1576 * The memcg-specific accounting when moving
1577 * pages around the LRU lists relies on the
1578 * page's owner (memcg) to be valid. Usually,
1579 * pages are assigned to a new owner before
1580 * being put on the LRU list, but since this
1581 * is not the case here, the stale owner from
1582 * a previous allocation cycle must be reset.
1583 */
1584 mem_cgroup_reset_owner(new_page);
1574 copy_user_highpage(new_page, page, address, vma); 1585 copy_user_highpage(new_page, page, address, vma);
1575 1586
1576 SetPageDirty(new_page); 1587 SetPageDirty(new_page);
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index d58bb5fa4403..c74102d6eb5a 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -3050,6 +3050,23 @@ void mem_cgroup_uncharge_end(void)
3050 batch->memcg = NULL; 3050 batch->memcg = NULL;
3051} 3051}
3052 3052
3053/*
3054 * A function for resetting pc->mem_cgroup for newly allocated pages.
3055 * This function should be called if the newpage will be added to LRU
3056 * before start accounting.
3057 */
3058void mem_cgroup_reset_owner(struct page *newpage)
3059{
3060 struct page_cgroup *pc;
3061
3062 if (mem_cgroup_disabled())
3063 return;
3064
3065 pc = lookup_page_cgroup(newpage);
3066 VM_BUG_ON(PageCgroupUsed(pc));
3067 pc->mem_cgroup = root_mem_cgroup;
3068}
3069
3053#ifdef CONFIG_SWAP 3070#ifdef CONFIG_SWAP
3054/* 3071/*
3055 * called after __delete_from_swap_cache() and drop "page" account. 3072 * called after __delete_from_swap_cache() and drop "page" account.
diff --git a/mm/migrate.c b/mm/migrate.c
index 89ea0854332e..fc391985899f 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -777,6 +777,8 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private,
777 if (!newpage) 777 if (!newpage)
778 return -ENOMEM; 778 return -ENOMEM;
779 779
780 mem_cgroup_reset_owner(newpage);
781
780 if (page_count(page) == 1) { 782 if (page_count(page) == 1) {
781 /* page was freed from under us. So we are done. */ 783 /* page was freed from under us. So we are done. */
782 goto out; 784 goto out;
diff --git a/mm/swap_state.c b/mm/swap_state.c
index ea6b32d61873..470038a91873 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -300,6 +300,16 @@ struct page *read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask,
300 new_page = alloc_page_vma(gfp_mask, vma, addr); 300 new_page = alloc_page_vma(gfp_mask, vma, addr);
301 if (!new_page) 301 if (!new_page)
302 break; /* Out of memory */ 302 break; /* Out of memory */
303 /*
304 * The memcg-specific accounting when moving
305 * pages around the LRU lists relies on the
306 * page's owner (memcg) to be valid. Usually,
307 * pages are assigned to a new owner before
308 * being put on the LRU list, but since this
309 * is not the case here, the stale owner from
310 * a previous allocation cycle must be reset.
311 */
312 mem_cgroup_reset_owner(new_page);
303 } 313 }
304 314
305 /* 315 /*