diff options
Diffstat (limited to 'mm/rmap.c')
-rw-r--r-- | mm/rmap.c | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/mm/rmap.c b/mm/rmap.c index 1bceb49aa214..effcea83ac4e 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -1481,9 +1481,12 @@ static int page_not_mapped(struct page *page) * try_to_unmap - try to remove all page table mappings to a page * @page: the page to get unmapped * @flags: action and flags + * @vma : target vma for reclaim * * Tries to remove all the page table entries which are mapping this * page, used in the pageout path. Caller must hold the page lock. + * If @vma is not NULL, this function try to remove @page from only @vma + * without peeking all mapped vma for @page. * Return values are: * * SWAP_SUCCESS - we succeeded in removing all mappings @@ -1491,7 +1494,8 @@ static int page_not_mapped(struct page *page) * SWAP_FAIL - the page is unswappable * SWAP_MLOCK - page is mlocked. */ -int try_to_unmap(struct page *page, enum ttu_flags flags) +int try_to_unmap(struct page *page, enum ttu_flags flags, + struct vm_area_struct *vma) { int ret; struct rmap_walk_control rwc = { @@ -1499,6 +1503,7 @@ int try_to_unmap(struct page *page, enum ttu_flags flags) .arg = (void *)flags, .done = page_not_mapped, .anon_lock = page_lock_anon_vma_read, + .target_vma = vma, }; VM_BUG_ON_PAGE(!PageHuge(page) && PageTransHuge(page), page); @@ -1544,6 +1549,7 @@ int try_to_munlock(struct page *page) .arg = (void *)TTU_MUNLOCK, .done = page_not_mapped, .anon_lock = page_lock_anon_vma_read, + .target_vma = NULL, }; @@ -1605,6 +1611,11 @@ static int rmap_walk_anon(struct page *page, struct rmap_walk_control *rwc) struct anon_vma_chain *avc; int ret = SWAP_AGAIN; + if (rwc->target_vma) { + unsigned long address = vma_address(page, rwc->target_vma); + return rwc->rmap_one(page, rwc->target_vma, address, rwc->arg); + } + anon_vma = rmap_walk_anon_lock(page, rwc); if (!anon_vma) return ret; @@ -1647,6 +1658,7 @@ static int rmap_walk_file(struct page *page, struct rmap_walk_control *rwc) struct address_space *mapping = page->mapping; pgoff_t pgoff; struct vm_area_struct *vma; + unsigned long address; int ret = SWAP_AGAIN; /* @@ -1662,6 +1674,12 @@ static int rmap_walk_file(struct page *page, struct rmap_walk_control *rwc) pgoff = page_to_pgoff(page); i_mmap_lock_read(mapping); + if (rwc->target_vma) { + address = vma_address(page, rwc->target_vma); + ret = rwc->rmap_one(page, rwc->target_vma, address, rwc->arg); + goto done; + } + vma_interval_tree_foreach(vma, &mapping->i_mmap, pgoff, pgoff) { unsigned long address = vma_address(page, vma); |