aboutsummaryrefslogtreecommitdiffstats
path: root/mm/migrate.c
diff options
context:
space:
mode:
authorKAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>2008-07-25 04:47:10 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-25 13:53:37 -0400
commite8589cc189f96b87348ae83ea4db38eaac624135 (patch)
tree6693422dc81e6da78c4ad892b0d326fb7f946dda /mm/migrate.c
parent508b7be0a5b06b64203512ed9b34191cddc83f56 (diff)
memcg: better migration handling
This patch changes page migration under memory controller to use a different algorithm. (thanks to Christoph for new idea.) Before: - page_cgroup is migrated from an old page to a new page. After: - a new page is accounted , no reuse of page_cgroup. Pros: - We can avoid compliated lock depndencies and races in migration. Cons: - new param to mem_cgroup_charge_common(). - mem_cgroup_getref() is added for handling ref_cnt ping-pong. This version simplifies complicated lock dependency in page migraiton under memory resource controller. new refcnt sequence is following. a mapped page: prepage_migration() ..... +1 to NEW page try_to_unmap() ..... all refs to OLD page is gone. move_pages() ..... +1 to NEW page if page cache. remap... ..... all refs from *map* is added to NEW one. end_migration() ..... -1 to New page. page's mapcount + (page_is_cache) refs are added to NEW one. Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Balbir Singh <balbir@in.ibm.com> Cc: Pavel Emelyanov <xemul@openvz.org> Cc: Li Zefan <lizf@cn.fujitsu.com> Cc: YAMAMOTO Takashi <yamamoto@valinux.co.jp> Cc: Hugh Dickins <hugh@veritas.com> Cc: Christoph Lameter <cl@linux-foundation.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/migrate.c')
-rw-r--r--mm/migrate.c22
1 files changed, 15 insertions, 7 deletions
diff --git a/mm/migrate.c b/mm/migrate.c
index 376cceba82f9..f6d7f8efd1a8 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -358,6 +358,10 @@ static int migrate_page_move_mapping(struct address_space *mapping,
358 __inc_zone_page_state(newpage, NR_FILE_PAGES); 358 __inc_zone_page_state(newpage, NR_FILE_PAGES);
359 359
360 write_unlock_irq(&mapping->tree_lock); 360 write_unlock_irq(&mapping->tree_lock);
361 if (!PageSwapCache(newpage)) {
362 mem_cgroup_uncharge_page(page);
363 mem_cgroup_getref(newpage);
364 }
361 365
362 return 0; 366 return 0;
363} 367}
@@ -611,7 +615,6 @@ static int move_to_new_page(struct page *newpage, struct page *page)
611 rc = fallback_migrate_page(mapping, newpage, page); 615 rc = fallback_migrate_page(mapping, newpage, page);
612 616
613 if (!rc) { 617 if (!rc) {
614 mem_cgroup_page_migration(page, newpage);
615 remove_migration_ptes(page, newpage); 618 remove_migration_ptes(page, newpage);
616 } else 619 } else
617 newpage->mapping = NULL; 620 newpage->mapping = NULL;
@@ -641,6 +644,14 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private,
641 /* page was freed from under us. So we are done. */ 644 /* page was freed from under us. So we are done. */
642 goto move_newpage; 645 goto move_newpage;
643 646
647 charge = mem_cgroup_prepare_migration(page, newpage);
648 if (charge == -ENOMEM) {
649 rc = -ENOMEM;
650 goto move_newpage;
651 }
652 /* prepare cgroup just returns 0 or -ENOMEM */
653 BUG_ON(charge);
654
644 rc = -EAGAIN; 655 rc = -EAGAIN;
645 if (TestSetPageLocked(page)) { 656 if (TestSetPageLocked(page)) {
646 if (!force) 657 if (!force)
@@ -692,19 +703,14 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private,
692 goto rcu_unlock; 703 goto rcu_unlock;
693 } 704 }
694 705
695 charge = mem_cgroup_prepare_migration(page);
696 /* Establish migration ptes or remove ptes */ 706 /* Establish migration ptes or remove ptes */
697 try_to_unmap(page, 1); 707 try_to_unmap(page, 1);
698 708
699 if (!page_mapped(page)) 709 if (!page_mapped(page))
700 rc = move_to_new_page(newpage, page); 710 rc = move_to_new_page(newpage, page);
701 711
702 if (rc) { 712 if (rc)
703 remove_migration_ptes(page, page); 713 remove_migration_ptes(page, page);
704 if (charge)
705 mem_cgroup_end_migration(page);
706 } else if (charge)
707 mem_cgroup_end_migration(newpage);
708rcu_unlock: 714rcu_unlock:
709 if (rcu_locked) 715 if (rcu_locked)
710 rcu_read_unlock(); 716 rcu_read_unlock();
@@ -725,6 +731,8 @@ unlock:
725 } 731 }
726 732
727move_newpage: 733move_newpage:
734 if (!charge)
735 mem_cgroup_end_migration(newpage);
728 /* 736 /*
729 * Move the new page to the LRU. If migration was not successful 737 * Move the new page to the LRU. If migration was not successful
730 * then this will free the page. 738 * then this will free the page.