proc: clean the ip_misc_proc_init and ip_proc_init_net error paths
[safe/jmp/linux-2.6] / mm / mprotect.c
index 955f9d0..360d9cc 100644 (file)
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 
+#ifndef pgprot_modify
+static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot)
+{
+       return newprot;
+}
+#endif
+
 static void change_pte_range(struct mm_struct *mm, pmd_t *pmd,
                unsigned long addr, unsigned long end, pgprot_t newprot,
                int dirty_accountable)
@@ -34,25 +41,23 @@ static void change_pte_range(struct mm_struct *mm, pmd_t *pmd,
        spinlock_t *ptl;
 
        pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
+       arch_enter_lazy_mmu_mode();
        do {
                oldpte = *pte;
                if (pte_present(oldpte)) {
                        pte_t ptent;
 
-                       /* Avoid an SMP race with hardware updated dirty/clean
-                        * bits by wiping the pte and then setting the new pte
-                        * into place.
-                        */
-                       ptent = ptep_get_and_clear(mm, addr, pte);
+                       ptent = ptep_modify_prot_start(mm, addr, pte);
                        ptent = pte_modify(ptent, newprot);
+
                        /*
                         * Avoid taking write faults for pages we know to be
                         * dirty.
                         */
                        if (dirty_accountable && pte_dirty(ptent))
                                ptent = pte_mkwrite(ptent);
-                       set_pte_at(mm, addr, pte, ptent);
-                       lazy_mmu_prot_update(ptent);
+
+                       ptep_modify_prot_commit(mm, addr, pte, ptent);
 #ifdef CONFIG_MIGRATION
                } else if (!pte_file(oldpte)) {
                        swp_entry_t entry = pte_to_swp_entry(oldpte);
@@ -70,6 +75,7 @@ static void change_pte_range(struct mm_struct *mm, pmd_t *pmd,
                }
 
        } while (pte++, addr += PAGE_SIZE, addr != end);
+       arch_leave_lazy_mmu_mode();
        pte_unmap_unlock(pte - 1, ptl);
 }
 
@@ -126,7 +132,7 @@ static void change_protection(struct vm_area_struct *vma,
        flush_tlb_range(vma, start, end);
 }
 
-static int
+int
 mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
        unsigned long start, unsigned long end, unsigned long newflags)
 {
@@ -191,11 +197,11 @@ success:
         * held in write mode.
         */
        vma->vm_flags = newflags;
-       vma->vm_page_prot = protection_map[newflags &
-               (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)];
+       vma->vm_page_prot = pgprot_modify(vma->vm_page_prot,
+                                         vm_get_page_prot(newflags));
+
        if (vma_wants_writenotify(vma)) {
-               vma->vm_page_prot = protection_map[newflags &
-                       (VM_READ|VM_WRITE|VM_EXEC)];
+               vma->vm_page_prot = vm_get_page_prot(newflags & ~VM_SHARED);
                dirty_accountable = 1;
        }
 
@@ -231,7 +237,7 @@ sys_mprotect(unsigned long start, size_t len, unsigned long prot)
        end = start + len;
        if (end <= start)
                return -ENOMEM;
-       if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM))
+       if (!arch_validate_prot(prot))
                return -EINVAL;
 
        reqprot = prot;