aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memcontrol.c
diff options
context:
space:
mode:
authorKAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>2009-01-07 21:07:50 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-01-08 11:31:04 -0500
commit01b1ae63c2270cbacfd43fea94578c17950eb548 (patch)
treeab0275f32e8548c4413014d43cab1f52f03c9c5c /mm/memcontrol.c
parentbced0520fe462bb94021dcabd32e99630c171be2 (diff)
memcg: simple migration handling
Now, management of "charge" under page migration is done under following manner. (Assume migrate page contents from oldpage to newpage) before - "newpage" is charged before migration. at success. - "oldpage" is uncharged at somewhere(unmap, radix-tree-replace) at failure - "newpage" is uncharged. - "oldpage" is charged if necessary (*1) But (*1) is not reliable....because of GFP_ATOMIC. This patch tries to change behavior as following by charge/commit/cancel ops. before - charge PAGE_SIZE (no target page) success - commit charge against "newpage". failure - commit charge against "oldpage". (PCG_USED bit works effectively to avoid double-counting) - if "oldpage" is obsolete, cancel charge of PAGE_SIZE. Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Reviewed-by: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp> Cc: Balbir Singh <balbir@in.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/memcontrol.c')
-rw-r--r--mm/memcontrol.c108
1 files changed, 52 insertions, 56 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index c34eb52bdc3..b71195e8198 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -627,34 +627,6 @@ int mem_cgroup_newpage_charge(struct page *page,
627 MEM_CGROUP_CHARGE_TYPE_MAPPED, NULL); 627 MEM_CGROUP_CHARGE_TYPE_MAPPED, NULL);
628} 628}
629 629
630/*
631 * same as mem_cgroup_newpage_charge(), now.
632 * But what we assume is different from newpage, and this is special case.
633 * treat this in special function. easy for maintenance.
634 */
635
636int mem_cgroup_charge_migrate_fixup(struct page *page,
637 struct mm_struct *mm, gfp_t gfp_mask)
638{
639 if (mem_cgroup_subsys.disabled)
640 return 0;
641
642 if (PageCompound(page))
643 return 0;
644
645 if (page_mapped(page) || (page->mapping && !PageAnon(page)))
646 return 0;
647
648 if (unlikely(!mm))
649 mm = &init_mm;
650
651 return mem_cgroup_charge_common(page, mm, gfp_mask,
652 MEM_CGROUP_CHARGE_TYPE_MAPPED, NULL);
653}
654
655
656
657
658int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm, 630int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
659 gfp_t gfp_mask) 631 gfp_t gfp_mask)
660{ 632{
@@ -697,7 +669,6 @@ int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
697 MEM_CGROUP_CHARGE_TYPE_SHMEM, NULL); 669 MEM_CGROUP_CHARGE_TYPE_SHMEM, NULL);
698} 670}
699 671
700
701void mem_cgroup_commit_charge_swapin(struct page *page, struct mem_cgroup *ptr) 672void mem_cgroup_commit_charge_swapin(struct page *page, struct mem_cgroup *ptr)
702{ 673{
703 struct page_cgroup *pc; 674 struct page_cgroup *pc;
@@ -782,13 +753,13 @@ void mem_cgroup_uncharge_cache_page(struct page *page)
782} 753}
783 754
784/* 755/*
785 * Before starting migration, account against new page. 756 * Before starting migration, account PAGE_SIZE to mem_cgroup that the old
757 * page belongs to.
786 */ 758 */
787int mem_cgroup_prepare_migration(struct page *page, struct page *newpage) 759int mem_cgroup_prepare_migration(struct page *page, struct mem_cgroup **ptr)
788{ 760{
789 struct page_cgroup *pc; 761 struct page_cgroup *pc;
790 struct mem_cgroup *mem = NULL; 762 struct mem_cgroup *mem = NULL;
791 enum charge_type ctype = MEM_CGROUP_CHARGE_TYPE_MAPPED;
792 int ret = 0; 763 int ret = 0;
793 764
794 if (mem_cgroup_subsys.disabled) 765 if (mem_cgroup_subsys.disabled)
@@ -799,42 +770,67 @@ int mem_cgroup_prepare_migration(struct page *page, struct page *newpage)
799 if (PageCgroupUsed(pc)) { 770 if (PageCgroupUsed(pc)) {
800 mem = pc->mem_cgroup; 771 mem = pc->mem_cgroup;
801 css_get(&mem->css); 772 css_get(&mem->css);
802 if (PageCgroupCache(pc)) {
803 if (page_is_file_cache(page))
804 ctype = MEM_CGROUP_CHARGE_TYPE_CACHE;
805 else
806 ctype = MEM_CGROUP_CHARGE_TYPE_SHMEM;
807 }
808 } 773 }
809 unlock_page_cgroup(pc); 774 unlock_page_cgroup(pc);
775
810 if (mem) { 776 if (mem) {
811 ret = mem_cgroup_charge_common(newpage, NULL, 777 ret = mem_cgroup_try_charge(NULL, GFP_HIGHUSER_MOVABLE, &mem);
812 GFP_HIGHUSER_MOVABLE,
813 ctype, mem);
814 css_put(&mem->css); 778 css_put(&mem->css);
815 } 779 }
780 *ptr = mem;
816 return ret; 781 return ret;
817} 782}
818 783
819/* remove redundant charge if migration failed*/ 784/* remove redundant charge if migration failed*/
820void mem_cgroup_end_migration(struct page *newpage) 785void mem_cgroup_end_migration(struct mem_cgroup *mem,
786 struct page *oldpage, struct page *newpage)
821{ 787{
788 struct page *target, *unused;
789 struct page_cgroup *pc;
790 enum charge_type ctype;
791
792 if (!mem)
793 return;
794
795 /* at migration success, oldpage->mapping is NULL. */
796 if (oldpage->mapping) {
797 target = oldpage;
798 unused = NULL;
799 } else {
800 target = newpage;
801 unused = oldpage;
802 }
803
804 if (PageAnon(target))
805 ctype = MEM_CGROUP_CHARGE_TYPE_MAPPED;
806 else if (page_is_file_cache(target))
807 ctype = MEM_CGROUP_CHARGE_TYPE_CACHE;
808 else
809 ctype = MEM_CGROUP_CHARGE_TYPE_SHMEM;
810
811 /* unused page is not on radix-tree now. */
812 if (unused && ctype != MEM_CGROUP_CHARGE_TYPE_MAPPED)
813 __mem_cgroup_uncharge_common(unused, ctype);
814
815 pc = lookup_page_cgroup(target);
822 /* 816 /*
823 * At success, page->mapping is not NULL. 817 * __mem_cgroup_commit_charge() check PCG_USED bit of page_cgroup.
824 * special rollback care is necessary when 818 * So, double-counting is effectively avoided.
825 * 1. at migration failure. (newpage->mapping is cleared in this case) 819 */
826 * 2. the newpage was moved but not remapped again because the task 820 __mem_cgroup_commit_charge(mem, pc, ctype);
827 * exits and the newpage is obsolete. In this case, the new page 821
828 * may be a swapcache. So, we just call mem_cgroup_uncharge_page() 822 /*
829 * always for avoiding mess. The page_cgroup will be removed if 823 * Both of oldpage and newpage are still under lock_page().
830 * unnecessary. File cache pages is still on radix-tree. Don't 824 * Then, we don't have to care about race in radix-tree.
831 * care it. 825 * But we have to be careful that this page is unmapped or not.
826 *
827 * There is a case for !page_mapped(). At the start of
828 * migration, oldpage was mapped. But now, it's zapped.
829 * But we know *target* page is not freed/reused under us.
830 * mem_cgroup_uncharge_page() does all necessary checks.
832 */ 831 */
833 if (!newpage->mapping) 832 if (ctype == MEM_CGROUP_CHARGE_TYPE_MAPPED)
834 __mem_cgroup_uncharge_common(newpage, 833 mem_cgroup_uncharge_page(target);
835 MEM_CGROUP_CHARGE_TYPE_FORCE);
836 else if (PageAnon(newpage))
837 mem_cgroup_uncharge_page(newpage);
838} 834}
839 835
840/* 836/*