OSDN Git Service

Merge "net/packet: fix overflow in check for tp_reserve"
[sagit-ice-cold/kernel_xiaomi_msm8998.git] / mm / rmap.c
index b577fbb..59489b3 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1459,9 +1459,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
  * 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.
  *
  * 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
  * Return values are:
  *
  * SWAP_SUCCESS        - we succeeded in removing all mappings
@@ -1469,7 +1472,8 @@ static int page_not_mapped(struct page *page)
  * SWAP_FAIL   - the page is unswappable
  * SWAP_MLOCK  - page is mlocked.
  */
  * 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 = {
 {
        int ret;
        struct rmap_walk_control rwc = {
@@ -1477,6 +1481,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,
                .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);
        };
 
        VM_BUG_ON_PAGE(!PageHuge(page) && PageTransHuge(page), page);
@@ -1522,6 +1527,7 @@ int try_to_munlock(struct page *page)
                .arg = (void *)TTU_MUNLOCK,
                .done = page_not_mapped,
                .anon_lock = page_lock_anon_vma_read,
                .arg = (void *)TTU_MUNLOCK,
                .done = page_not_mapped,
                .anon_lock = page_lock_anon_vma_read,
+               .target_vma = NULL,
 
        };
 
 
        };
 
@@ -1583,6 +1589,11 @@ static int rmap_walk_anon(struct page *page, struct rmap_walk_control *rwc)
        struct anon_vma_chain *avc;
        int ret = SWAP_AGAIN;
 
        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;
        anon_vma = rmap_walk_anon_lock(page, rwc);
        if (!anon_vma)
                return ret;
@@ -1625,6 +1636,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;
        struct address_space *mapping = page->mapping;
        pgoff_t pgoff;
        struct vm_area_struct *vma;
+       unsigned long address;
        int ret = SWAP_AGAIN;
 
        /*
        int ret = SWAP_AGAIN;
 
        /*
@@ -1640,6 +1652,12 @@ static int rmap_walk_file(struct page *page, struct rmap_walk_control *rwc)
 
        pgoff = page_to_pgoff(page);
        i_mmap_lock_read(mapping);
 
        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);
 
        vma_interval_tree_foreach(vma, &mapping->i_mmap, pgoff, pgoff) {
                unsigned long address = vma_address(page, vma);