aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memcontrol.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/memcontrol.c')
-rw-r--r--mm/memcontrol.c109
1 files changed, 63 insertions, 46 deletions
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index da5912b84551..a61706193c31 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -166,7 +166,6 @@ struct page_cgroup {
166 struct list_head lru; /* per cgroup LRU list */ 166 struct list_head lru; /* per cgroup LRU list */
167 struct page *page; 167 struct page *page;
168 struct mem_cgroup *mem_cgroup; 168 struct mem_cgroup *mem_cgroup;
169 int ref_cnt; /* cached, mapped, migrating */
170 int flags; 169 int flags;
171}; 170};
172#define PAGE_CGROUP_FLAG_CACHE (0x1) /* charged as cache */ 171#define PAGE_CGROUP_FLAG_CACHE (0x1) /* charged as cache */
@@ -185,6 +184,7 @@ static enum zone_type page_cgroup_zid(struct page_cgroup *pc)
185enum charge_type { 184enum charge_type {
186 MEM_CGROUP_CHARGE_TYPE_CACHE = 0, 185 MEM_CGROUP_CHARGE_TYPE_CACHE = 0,
187 MEM_CGROUP_CHARGE_TYPE_MAPPED, 186 MEM_CGROUP_CHARGE_TYPE_MAPPED,
187 MEM_CGROUP_CHARGE_TYPE_FORCE, /* used by force_empty */
188}; 188};
189 189
190/* 190/*
@@ -552,9 +552,7 @@ retry:
552 */ 552 */
553 if (pc) { 553 if (pc) {
554 VM_BUG_ON(pc->page != page); 554 VM_BUG_ON(pc->page != page);
555 VM_BUG_ON(pc->ref_cnt <= 0); 555 VM_BUG_ON(!pc->mem_cgroup);
556
557 pc->ref_cnt++;
558 unlock_page_cgroup(page); 556 unlock_page_cgroup(page);
559 goto done; 557 goto done;
560 } 558 }
@@ -570,10 +568,7 @@ retry:
570 * thread group leader migrates. It's possible that mm is not 568 * thread group leader migrates. It's possible that mm is not
571 * set, if so charge the init_mm (happens for pagecache usage). 569 * set, if so charge the init_mm (happens for pagecache usage).
572 */ 570 */
573 if (!memcg) { 571 if (likely(!memcg)) {
574 if (!mm)
575 mm = &init_mm;
576
577 rcu_read_lock(); 572 rcu_read_lock();
578 mem = mem_cgroup_from_task(rcu_dereference(mm->owner)); 573 mem = mem_cgroup_from_task(rcu_dereference(mm->owner));
579 /* 574 /*
@@ -609,7 +604,6 @@ retry:
609 } 604 }
610 } 605 }
611 606
612 pc->ref_cnt = 1;
613 pc->mem_cgroup = mem; 607 pc->mem_cgroup = mem;
614 pc->page = page; 608 pc->page = page;
615 /* 609 /*
@@ -653,6 +647,17 @@ err:
653 647
654int mem_cgroup_charge(struct page *page, struct mm_struct *mm, gfp_t gfp_mask) 648int mem_cgroup_charge(struct page *page, struct mm_struct *mm, gfp_t gfp_mask)
655{ 649{
650 /*
651 * If already mapped, we don't have to account.
652 * If page cache, page->mapping has address_space.
653 * But page->mapping may have out-of-use anon_vma pointer,
654 * detecit it by PageAnon() check. newly-mapped-anon's page->mapping
655 * is NULL.
656 */
657 if (page_mapped(page) || (page->mapping && !PageAnon(page)))
658 return 0;
659 if (unlikely(!mm))
660 mm = &init_mm;
656 return mem_cgroup_charge_common(page, mm, gfp_mask, 661 return mem_cgroup_charge_common(page, mm, gfp_mask,
657 MEM_CGROUP_CHARGE_TYPE_MAPPED, NULL); 662 MEM_CGROUP_CHARGE_TYPE_MAPPED, NULL);
658} 663}
@@ -660,32 +665,17 @@ int mem_cgroup_charge(struct page *page, struct mm_struct *mm, gfp_t gfp_mask)
660int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm, 665int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
661 gfp_t gfp_mask) 666 gfp_t gfp_mask)
662{ 667{
663 if (!mm) 668 if (unlikely(!mm))
664 mm = &init_mm; 669 mm = &init_mm;
665 return mem_cgroup_charge_common(page, mm, gfp_mask, 670 return mem_cgroup_charge_common(page, mm, gfp_mask,
666 MEM_CGROUP_CHARGE_TYPE_CACHE, NULL); 671 MEM_CGROUP_CHARGE_TYPE_CACHE, NULL);
667} 672}
668 673
669int mem_cgroup_getref(struct page *page)
670{
671 struct page_cgroup *pc;
672
673 if (mem_cgroup_subsys.disabled)
674 return 0;
675
676 lock_page_cgroup(page);
677 pc = page_get_page_cgroup(page);
678 VM_BUG_ON(!pc);
679 pc->ref_cnt++;
680 unlock_page_cgroup(page);
681 return 0;
682}
683
684/* 674/*
685 * Uncharging is always a welcome operation, we never complain, simply 675 * uncharge if !page_mapped(page)
686 * uncharge.
687 */ 676 */
688void mem_cgroup_uncharge_page(struct page *page) 677static void
678__mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype)
689{ 679{
690 struct page_cgroup *pc; 680 struct page_cgroup *pc;
691 struct mem_cgroup *mem; 681 struct mem_cgroup *mem;
@@ -704,29 +694,41 @@ void mem_cgroup_uncharge_page(struct page *page)
704 goto unlock; 694 goto unlock;
705 695
706 VM_BUG_ON(pc->page != page); 696 VM_BUG_ON(pc->page != page);
707 VM_BUG_ON(pc->ref_cnt <= 0);
708 697
709 if (--(pc->ref_cnt) == 0) { 698 if ((ctype == MEM_CGROUP_CHARGE_TYPE_MAPPED)
710 mz = page_cgroup_zoneinfo(pc); 699 && ((pc->flags & PAGE_CGROUP_FLAG_CACHE)
711 spin_lock_irqsave(&mz->lru_lock, flags); 700 || page_mapped(page)))
712 __mem_cgroup_remove_list(mz, pc); 701 goto unlock;
713 spin_unlock_irqrestore(&mz->lru_lock, flags);
714 702
715 page_assign_page_cgroup(page, NULL); 703 mz = page_cgroup_zoneinfo(pc);
716 unlock_page_cgroup(page); 704 spin_lock_irqsave(&mz->lru_lock, flags);
705 __mem_cgroup_remove_list(mz, pc);
706 spin_unlock_irqrestore(&mz->lru_lock, flags);
717 707
718 mem = pc->mem_cgroup; 708 page_assign_page_cgroup(page, NULL);
719 res_counter_uncharge(&mem->res, PAGE_SIZE); 709 unlock_page_cgroup(page);
720 css_put(&mem->css);
721 710
722 kmem_cache_free(page_cgroup_cache, pc); 711 mem = pc->mem_cgroup;
723 return; 712 res_counter_uncharge(&mem->res, PAGE_SIZE);
724 } 713 css_put(&mem->css);
725 714
715 kmem_cache_free(page_cgroup_cache, pc);
716 return;
726unlock: 717unlock:
727 unlock_page_cgroup(page); 718 unlock_page_cgroup(page);
728} 719}
729 720
721void mem_cgroup_uncharge_page(struct page *page)
722{
723 __mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_MAPPED);
724}
725
726void mem_cgroup_uncharge_cache_page(struct page *page)
727{
728 VM_BUG_ON(page_mapped(page));
729 __mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_CACHE);
730}
731
730/* 732/*
731 * Before starting migration, account against new page. 733 * Before starting migration, account against new page.
732 */ 734 */
@@ -757,15 +759,29 @@ int mem_cgroup_prepare_migration(struct page *page, struct page *newpage)
757 return ret; 759 return ret;
758} 760}
759 761
760/* remove redundant charge */ 762/* remove redundant charge if migration failed*/
761void mem_cgroup_end_migration(struct page *newpage) 763void mem_cgroup_end_migration(struct page *newpage)
762{ 764{
763 mem_cgroup_uncharge_page(newpage); 765 /*
766 * At success, page->mapping is not NULL.
767 * special rollback care is necessary when
768 * 1. at migration failure. (newpage->mapping is cleared in this case)
769 * 2. the newpage was moved but not remapped again because the task
770 * exits and the newpage is obsolete. In this case, the new page
771 * may be a swapcache. So, we just call mem_cgroup_uncharge_page()
772 * always for avoiding mess. The page_cgroup will be removed if
773 * unnecessary. File cache pages is still on radix-tree. Don't
774 * care it.
775 */
776 if (!newpage->mapping)
777 __mem_cgroup_uncharge_common(newpage,
778 MEM_CGROUP_CHARGE_TYPE_FORCE);
779 else if (PageAnon(newpage))
780 mem_cgroup_uncharge_page(newpage);
764} 781}
765 782
766/* 783/*
767 * This routine traverse page_cgroup in given list and drop them all. 784 * This routine traverse page_cgroup in given list and drop them all.
768 * This routine ignores page_cgroup->ref_cnt.
769 * *And* this routine doesn't reclaim page itself, just removes page_cgroup. 785 * *And* this routine doesn't reclaim page itself, just removes page_cgroup.
770 */ 786 */
771#define FORCE_UNCHARGE_BATCH (128) 787#define FORCE_UNCHARGE_BATCH (128)
@@ -795,7 +811,8 @@ static void mem_cgroup_force_empty_list(struct mem_cgroup *mem,
795 * if it's under page migration. 811 * if it's under page migration.
796 */ 812 */
797 if (PageLRU(page)) { 813 if (PageLRU(page)) {
798 mem_cgroup_uncharge_page(page); 814 __mem_cgroup_uncharge_common(page,
815 MEM_CGROUP_CHARGE_TYPE_FORCE);
799 put_page(page); 816 put_page(page);
800 if (--count <= 0) { 817 if (--count <= 0) {
801 count = FORCE_UNCHARGE_BATCH; 818 count = FORCE_UNCHARGE_BATCH;