]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - mm/madvise.c
pcnet32: use pci_set_dma_mask insted of pci_dma_supported
[karo-tx-linux.git] / mm / madvise.c
index 60533503b4c1353e08ce505bfcb5ebcc4d9f6536..5db5464312854586a5987fc3d13fc4a21487dfc9 100644 (file)
@@ -270,8 +270,19 @@ 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)) {
+               if (next - addr != HPAGE_PMD_SIZE)
+                       split_huge_pmd(vma, pmd, addr);
+               else if (!madvise_free_huge_pmd(tlb, vma, pmd, addr))
+                       goto next;
+               /* fall through */
+       }
 
-       split_huge_pmd(vma, addr, pmd);
        if (pmd_trans_unstable(pmd))
                return 0;
 
@@ -280,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)
@@ -319,10 +344,21 @@ 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:
        cond_resched();
        return 0;
 }