]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - mm/madvise.c
Merge branch 'akpm-current/current'
[karo-tx-linux.git] / mm / madvise.c
index f68b1130f3e32d569ac7338670f0f907ed0b69c1..5db5464312854586a5987fc3d13fc4a21487dfc9 100644 (file)
@@ -270,7 +270,9 @@ static int madvise_free_pte_range(pmd_t *pmd, unsigned long addr,
        spinlock_t *ptl;
        pte_t *pte, ptent;
        struct page *page;
+       swp_entry_t entry;
        unsigned long next;
+       int nr_swap = 0;
 
        next = pmd_addr_end(addr, end);
        if (pmd_trans_huge(*pmd)) {
@@ -289,8 +291,22 @@ static int madvise_free_pte_range(pmd_t *pmd, unsigned long addr,
        for (; addr != end; pte++, addr += PAGE_SIZE) {
                ptent = *pte;
 
-               if (!pte_present(ptent))
+               if (pte_none(ptent))
                        continue;
+               /*
+                * If the pte has swp_entry, just clear page table to
+                * prevent swap-in which is more expensive rather than
+                * (page allocation + zeroing).
+                */
+               if (!pte_present(ptent)) {
+                       entry = pte_to_swp_entry(ptent);
+                       if (non_swap_entry(entry))
+                               continue;
+                       nr_swap--;
+                       free_swap_and_cache(entry);
+                       pte_clear_not_present_full(mm, addr, pte, tlb->fullmm);
+                       continue;
+               }
 
                page = vm_normal_page(vma, addr, ptent);
                if (!page)
@@ -328,8 +344,18 @@ static int madvise_free_pte_range(pmd_t *pmd, unsigned long addr,
                ptent = pte_mkold(ptent);
                ptent = pte_mkclean(ptent);
                set_pte_at(mm, addr, pte, ptent);
+               if (PageActive(page))
+                       deactivate_page(page);
                tlb_remove_tlb_entry(tlb, pte, addr);
        }
+
+       if (nr_swap) {
+               if (current->mm == mm)
+                       sync_mm_rss(mm);
+
+               add_mm_counter(mm, MM_SWAPENTS, nr_swap);
+       }
+
        arch_leave_lazy_mmu_mode();
        pte_unmap_unlock(pte - 1, ptl);
 next: