diff options
author | Joonsoo Kim <iamjoonsoo.kim@lge.com> | 2014-01-22 00:49:46 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-22 01:19:45 +0100 |
commit | faecd8dd852d4e4a63a1b8ad43e5df8e41ee0336 (patch) | |
tree | aa0354aa874c37ac14b75176ee910db37e1c455b /mm | |
parent | mm/rmap: factor nonlinear handling out of try_to_unmap_file() (diff) | |
download | linux-faecd8dd852d4e4a63a1b8ad43e5df8e41ee0336.tar.xz linux-faecd8dd852d4e4a63a1b8ad43e5df8e41ee0336.zip |
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
diff --git a/mm/rmap.c b/mm/rmap.c index 7eab4ed304c1..5a79bf585e27 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -1684,6 +1684,24 @@ void __put_anon_vma(struct anon_vma *anon_vma) } #ifdef CONFIG_MIGRATION +static struct anon_vma *rmap_walk_anon_lock(struct page *page) +{ + struct anon_vma *anon_vma; + + /* + * Note: remove_migration_ptes() cannot use page_lock_anon_vma_read() + * because that depends on page_mapped(); but not all its usages + * are holding mmap_sem. Users without mmap_sem are required to + * take a reference count to prevent the anon_vma disappearing + */ + anon_vma = page_anon_vma(page); + if (!anon_vma) + return NULL; + + anon_vma_lock_read(anon_vma); + return anon_vma; +} + /* * rmap_walk() and its helpers rmap_walk_anon() and rmap_walk_file(): * 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 *, struct anon_vma_chain *avc; int ret = SWAP_AGAIN; - /* - * Note: remove_migration_ptes() cannot use page_lock_anon_vma_read() - * because that depends on page_mapped(); but not all its usages - * are holding mmap_sem. Users without mmap_sem are required to - * take a reference count to prevent the anon_vma disappearing - */ - anon_vma = page_anon_vma(page); + anon_vma = rmap_walk_anon_lock(page); if (!anon_vma) return ret; - anon_vma_lock_read(anon_vma); + anon_vma_interval_tree_foreach(avc, &anon_vma->rb_root, pgoff, pgoff) { struct vm_area_struct *vma = avc->vma; unsigned long address = vma_address(page, vma); |