diff options
author | Joonsoo Kim <iamjoonsoo.kim@lge.com> | 2014-01-21 18:49:46 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-21 19:19:45 -0500 |
commit | faecd8dd852d4e4a63a1b8ad43e5df8e41ee0336 (patch) | |
tree | aa0354aa874c37ac14b75176ee910db37e1c455b /mm | |
parent | 0f843c6ac318bb3ea7b63437b66dd39d8f01b088 (diff) |
mm/rmap: factor lock function out of rmap_walk_anon()
When we traverse anon_vma, we need to take a read-side anon_lock. But
there is subtle difference in the situation so that we can't use same
method to take a lock in each cases. Therefore, we need to make
rmap_walk_anon() taking difference lock function.
This patch is the first step, factoring lock function for anon_lock out
of rmap_walk_anon(). It will be used in case of removing migration
entry and in default of rmap_walk_anon().
Signed-off-by: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Reviewed-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Hugh Dickins <hughd@google.com>
Cc: Rik van Riel <riel@redhat.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Hillf Danton <dhillf@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r-- | mm/rmap.c | 28 |
1 files changed, 20 insertions, 8 deletions
@@ -1684,6 +1684,24 @@ void __put_anon_vma(struct anon_vma *anon_vma) | |||
1684 | } | 1684 | } |
1685 | 1685 | ||
1686 | #ifdef CONFIG_MIGRATION | 1686 | #ifdef CONFIG_MIGRATION |
1687 | static struct anon_vma *rmap_walk_anon_lock(struct page *page) | ||
1688 | { | ||
1689 | struct anon_vma *anon_vma; | ||
1690 | |||
1691 | /* | ||
1692 | * Note: remove_migration_ptes() cannot use page_lock_anon_vma_read() | ||
1693 | * because that depends on page_mapped(); but not all its usages | ||
1694 | * are holding mmap_sem. Users without mmap_sem are required to | ||
1695 | * take a reference count to prevent the anon_vma disappearing | ||
1696 | */ | ||
1697 | anon_vma = page_anon_vma(page); | ||
1698 | if (!anon_vma) | ||
1699 | return NULL; | ||
1700 | |||
1701 | anon_vma_lock_read(anon_vma); | ||
1702 | return anon_vma; | ||
1703 | } | ||
1704 | |||
1687 | /* | 1705 | /* |
1688 | * rmap_walk() and its helpers rmap_walk_anon() and rmap_walk_file(): | 1706 | * rmap_walk() and its helpers rmap_walk_anon() and rmap_walk_file(): |
1689 | * Called by migrate.c to remove migration ptes, but might be used more later. | 1707 | * Called by migrate.c to remove migration ptes, but might be used more later. |
@@ -1696,16 +1714,10 @@ static int rmap_walk_anon(struct page *page, int (*rmap_one)(struct page *, | |||
1696 | struct anon_vma_chain *avc; | 1714 | struct anon_vma_chain *avc; |
1697 | int ret = SWAP_AGAIN; | 1715 | int ret = SWAP_AGAIN; |
1698 | 1716 | ||
1699 | /* | 1717 | anon_vma = rmap_walk_anon_lock(page); |
1700 | * Note: remove_migration_ptes() cannot use page_lock_anon_vma_read() | ||
1701 | * because that depends on page_mapped(); but not all its usages | ||
1702 | * are holding mmap_sem. Users without mmap_sem are required to | ||
1703 | * take a reference count to prevent the anon_vma disappearing | ||
1704 | */ | ||
1705 | anon_vma = page_anon_vma(page); | ||
1706 | if (!anon_vma) | 1718 | if (!anon_vma) |
1707 | return ret; | 1719 | return ret; |
1708 | anon_vma_lock_read(anon_vma); | 1720 | |
1709 | anon_vma_interval_tree_foreach(avc, &anon_vma->rb_root, pgoff, pgoff) { | 1721 | anon_vma_interval_tree_foreach(avc, &anon_vma->rb_root, pgoff, pgoff) { |
1710 | struct vm_area_struct *vma = avc->vma; | 1722 | struct vm_area_struct *vma = avc->vma; |
1711 | unsigned long address = vma_address(page, vma); | 1723 | unsigned long address = vma_address(page, vma); |