fbdev: update after backlight argument change
[safe/jmp/linux-2.6] / mm / memory.c
index 745b348..156861f 100644 (file)
@@ -47,7 +47,9 @@
 #include <linux/pagemap.h>
 #include <linux/rmap.h>
 #include <linux/module.h>
+#include <linux/delayacct.h>
 #include <linux/init.h>
+#include <linux/writeback.h>
 
 #include <asm/pgalloc.h>
 #include <asm/uaccess.h>
@@ -82,6 +84,16 @@ EXPORT_SYMBOL(num_physpages);
 EXPORT_SYMBOL(high_memory);
 EXPORT_SYMBOL(vmalloc_earlyreserve);
 
+int randomize_va_space __read_mostly = 1;
+
+static int __init disable_randmaps(char *s)
+{
+       randomize_va_space = 0;
+       return 1;
+}
+__setup("norandmaps", disable_randmaps);
+
+
 /*
  * If a p?d_bad entry is found while walking page tables, report
  * the error, before resetting entry to p?d_none.  Usually (but
@@ -116,7 +128,7 @@ static void free_pte_range(struct mmu_gather *tlb, pmd_t *pmd)
        pmd_clear(pmd);
        pte_lock_deinit(page);
        pte_free_tlb(tlb, page);
-       dec_page_state(nr_page_table_pages);
+       dec_zone_page_state(page, NR_PAGETABLE);
        tlb->mm->nr_ptes--;
 }
 
@@ -267,7 +279,7 @@ void free_pgtables(struct mmu_gather **tlb, struct vm_area_struct *vma,
                anon_vma_unlink(vma);
                unlink_file_vma(vma);
 
-               if (is_hugepage_only_range(vma->vm_mm, addr, HPAGE_SIZE)) {
+               if (is_vm_hugetlb_page(vma)) {
                        hugetlb_free_pgd_range(tlb, addr, vma->vm_end,
                                floor, next? next->vm_start: ceiling);
                } else {
@@ -275,8 +287,7 @@ void free_pgtables(struct mmu_gather **tlb, struct vm_area_struct *vma,
                         * Optimization: gather nearby vmas into one call down
                         */
                        while (next && next->vm_start <= vma->vm_end + PMD_SIZE
-                         && !is_hugepage_only_range(vma->vm_mm, next->vm_start,
-                                                       HPAGE_SIZE)) {
+                              && !is_vm_hugetlb_page(next)) {
                                vma = next;
                                next = vma->vm_next;
                                anon_vma_unlink(vma);
@@ -302,7 +313,7 @@ int __pte_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long address)
                pte_free(new);
        } else {
                mm->nr_ptes++;
-               inc_page_state(nr_page_table_pages);
+               inc_zone_page_state(new, NR_PAGETABLE);
                pmd_populate(mm, pmd, new);
        }
        spin_unlock(&mm->page_table_lock);
@@ -349,6 +360,11 @@ void print_bad_pte(struct vm_area_struct *vma, pte_t pte, unsigned long vaddr)
        dump_stack();
 }
 
+static inline int is_cow_mapping(unsigned int flags)
+{
+       return (flags & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE;
+}
+
 /*
  * This function gets the "struct page" associated with a pte.
  *
@@ -373,10 +389,12 @@ struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr, pte_
 {
        unsigned long pfn = pte_pfn(pte);
 
-       if (vma->vm_flags & VM_PFNMAP) {
+       if (unlikely(vma->vm_flags & VM_PFNMAP)) {
                unsigned long off = (addr - vma->vm_start) >> PAGE_SHIFT;
                if (pfn == vma->vm_pgoff + off)
                        return NULL;
+               if (!is_cow_mapping(vma->vm_flags))
+                       return NULL;
        }
 
        /*
@@ -384,8 +402,6 @@ struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr, pte_
         * we should just do "return pfn_to_page(pfn)", but
         * in the meantime we check that we get a valid pfn,
         * and that the resulting page looks ok.
-        *
-        * Remove this test eventually!
         */
        if (unlikely(!pfn_valid(pfn))) {
                print_bad_pte(vma, pte, addr);
@@ -420,7 +436,9 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
        /* pte contains position in swap or file, so copy. */
        if (unlikely(!pte_present(pte))) {
                if (!pte_file(pte)) {
-                       swap_duplicate(pte_to_swp_entry(pte));
+                       swp_entry_t entry = pte_to_swp_entry(pte);
+
+                       swap_duplicate(entry);
                        /* make sure dst_mm is on swapoff's mmlist. */
                        if (unlikely(list_empty(&dst_mm->mmlist))) {
                                spin_lock(&mmlist_lock);
@@ -429,6 +447,16 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
                                                 &src_mm->mmlist);
                                spin_unlock(&mmlist_lock);
                        }
+                       if (is_write_migration_entry(entry) &&
+                                       is_cow_mapping(vm_flags)) {
+                               /*
+                                * COW mappings require pages in both parent
+                                * and child to be set to read.
+                                */
+                               make_migration_entry_read(&entry);
+                               pte = swp_entry_to_pte(entry);
+                               set_pte_at(src_mm, addr, src_pte, pte);
+                       }
                }
                goto out_set_pte;
        }
@@ -437,9 +465,9 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
         * If it's a COW mapping, write protect it both
         * in the parent and the child
         */
-       if ((vm_flags & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE) {
+       if (is_cow_mapping(vm_flags)) {
                ptep_set_wrprotect(src_mm, addr, src_pte);
-               pte = *src_pte;
+               pte = pte_wrprotect(pte);
        }
 
        /*
@@ -477,7 +505,8 @@ again:
                return -ENOMEM;
        src_pte = pte_offset_map_nested(src_pmd, addr);
        src_ptl = pte_lockptr(src_mm, src_pmd);
-       spin_lock(src_ptl);
+       spin_lock_nested(src_ptl, SINGLE_DEPTH_NESTING);
+       arch_enter_lazy_mmu_mode();
 
        do {
                /*
@@ -499,6 +528,7 @@ again:
                progress += 8;
        } while (dst_pte++, src_pte++, addr += PAGE_SIZE, addr != end);
 
+       arch_leave_lazy_mmu_mode();
        spin_unlock(src_ptl);
        pte_unmap_nested(src_pte - 1);
        add_mm_rss(dst_mm, rss[0], rss[1]);
@@ -567,7 +597,7 @@ int copy_page_range(struct mm_struct *dst_mm, struct mm_struct *src_mm,
         * readonly mappings. The tradeoff is that copy_page_range is more
         * efficient than faulting.
         */
-       if (!(vma->vm_flags & (VM_HUGETLB|VM_NONLINEAR|VM_PFNMAP))) {
+       if (!(vma->vm_flags & (VM_HUGETLB|VM_NONLINEAR|VM_PFNMAP|VM_INSERTPAGE))) {
                if (!vma->anon_vma)
                        return 0;
        }
@@ -600,17 +630,19 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb,
        int anon_rss = 0;
 
        pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
+       arch_enter_lazy_mmu_mode();
        do {
                pte_t ptent = *pte;
                if (pte_none(ptent)) {
                        (*zap_work)--;
                        continue;
                }
+
+               (*zap_work) -= PAGE_SIZE;
+
                if (pte_present(ptent)) {
                        struct page *page;
 
-                       (*zap_work) -= PAGE_SIZE;
-
                        page = vm_normal_page(vma, addr, ptent);
                        if (unlikely(details) && page) {
                                /*
@@ -661,10 +693,11 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb,
                        continue;
                if (!pte_file(ptent))
                        free_swap_and_cache(pte_to_swp_entry(ptent));
-               pte_clear_full(mm, addr, pte, tlb->fullmm);
+               pte_clear_not_present_full(mm, addr, pte, tlb->fullmm);
        } while (pte++, addr += PAGE_SIZE, (addr != end && *zap_work > 0));
 
        add_mm_rss(mm, file_rss, anon_rss);
+       arch_leave_lazy_mmu_mode();
        pte_unmap_unlock(pte - 1, ptl);
 
        return addr;
@@ -1002,7 +1035,7 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
                        continue;
                }
 
-               if (!vma || (vma->vm_flags & VM_IO)
+               if (!vma || (vma->vm_flags & (VM_IO | VM_PFNMAP))
                                || !(vm_flags & vma->vm_flags))
                        return i ? : -EFAULT;
 
@@ -1053,9 +1086,12 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
                                default:
                                        BUG();
                                }
+                               cond_resched();
                        }
                        if (pages) {
                                pages[i] = page;
+
+                               flush_anon_page(page, start);
                                flush_dcache_page(page);
                        }
                        if (vmas)
@@ -1078,6 +1114,7 @@ static int zeromap_pte_range(struct mm_struct *mm, pmd_t *pmd,
        pte = pte_alloc_map_lock(mm, pmd, addr, &ptl);
        if (!pte)
                return -ENOMEM;
+       arch_enter_lazy_mmu_mode();
        do {
                struct page *page = ZERO_PAGE(addr);
                pte_t zero_pte = pte_wrprotect(mk_pte(page, prot));
@@ -1087,6 +1124,7 @@ static int zeromap_pte_range(struct mm_struct *mm, pmd_t *pmd,
                BUG_ON(!pte_none(*pte));
                set_pte_at(mm, addr, pte, zero_pte);
        } while (pte++, addr += PAGE_SIZE, addr != end);
+       arch_leave_lazy_mmu_mode();
        pte_unmap_unlock(pte - 1, ptl);
        return 0;
 }
@@ -1146,12 +1184,12 @@ int zeromap_page_range(struct vm_area_struct *vma,
        return err;
 }
 
-pte_t *get_locked_pte(struct mm_struct *mm, unsigned long addr, spinlock_t **ptl)
+pte_t * fastcall get_locked_pte(struct mm_struct *mm, unsigned long addr, spinlock_t **ptl)
 {
        pgd_t * pgd = pgd_offset(mm, addr);
        pud_t * pud = pud_alloc(mm, pgd, addr);
        if (pud) {
-               pmd_t * pmd = pmd_alloc(mm, pgd, addr);
+               pmd_t * pmd = pmd_alloc(mm, pud, addr);
                if (pmd)
                        return pte_alloc_map_lock(mm, pmd, addr, ptl);
        }
@@ -1172,7 +1210,7 @@ static int insert_page(struct mm_struct *mm, unsigned long addr, struct page *pa
        spinlock_t *ptl;  
 
        retval = -EINVAL;
-       if (PageAnon(page) || !PageReserved(page))
+       if (PageAnon(page))
                goto out;
        retval = -ENOMEM;
        flush_dcache_page(page);
@@ -1196,46 +1234,38 @@ out:
        return retval;
 }
 
-/*
- * Somebody does a pfn remapping that doesn't actually work as a vma.
+/**
+ * vm_insert_page - insert single page into user vma
+ * @vma: user vma to map to
+ * @addr: target user address of this page
+ * @page: source kernel page
+ *
+ * This allows drivers to insert individual pages they've allocated
+ * into a user vma.
+ *
+ * The page has to be a nice clean _individual_ kernel allocation.
+ * If you allocate a compound page, you need to have marked it as
+ * such (__GFP_COMP), or manually just split the page up yourself
+ * (see split_page()).
  *
- * Do it as individual pages instead, and warn about it. It's bad form,
- * and very inefficient.
+ * NOTE! Traditionally this was done with "remap_pfn_range()" which
+ * took an arbitrary page protection parameter. This doesn't allow
+ * that. Your vma protection will have to be set up correctly, which
+ * means that if you want a shared writable mapping, you'd better
+ * ask for a shared writable mapping!
+ *
+ * The page does not need to be reserved.
  */
-static int incomplete_pfn_remap(struct vm_area_struct *vma,
-               unsigned long start, unsigned long end,
-               unsigned long pfn, pgprot_t prot)
+int vm_insert_page(struct vm_area_struct *vma, unsigned long addr, struct page *page)
 {
-       static int warn = 10;
-       struct page *page;
-       int retval;
-
-       if (!(vma->vm_flags & VM_INCOMPLETE)) {
-               if (warn) {
-                       warn--;
-                       printk("%s does an incomplete pfn remapping", current->comm);
-                       dump_stack();
-               }
-       }
-       vma->vm_flags |= VM_INCOMPLETE | VM_IO | VM_RESERVED;
-
-       if (start < vma->vm_start || end > vma->vm_end)
+       if (addr < vma->vm_start || addr >= vma->vm_end)
+               return -EFAULT;
+       if (!page_count(page))
                return -EINVAL;
-
-       if (!pfn_valid(pfn))
-               return -EINVAL;
-
-       retval = 0;
-       page = pfn_to_page(pfn);
-       while (start < end) {
-               retval = insert_page(vma->vm_mm, start, page, prot);
-               if (retval < 0)
-                       break;
-               start += PAGE_SIZE;
-               page++;
-       }
-       return retval;
+       vma->vm_flags |= VM_INSERTPAGE;
+       return insert_page(vma->vm_mm, addr, page, vma->vm_page_prot);
 }
+EXPORT_SYMBOL(vm_insert_page);
 
 /*
  * maps a range of physical memory into the requested pages. the old
@@ -1252,11 +1282,13 @@ static int remap_pte_range(struct mm_struct *mm, pmd_t *pmd,
        pte = pte_alloc_map_lock(mm, pmd, addr, &ptl);
        if (!pte)
                return -ENOMEM;
+       arch_enter_lazy_mmu_mode();
        do {
                BUG_ON(!pte_none(*pte));
                set_pte_at(mm, addr, pte, pfn_pte(pfn, prot));
                pfn++;
        } while (pte++, addr += PAGE_SIZE, addr != end);
+       arch_leave_lazy_mmu_mode();
        pte_unmap_unlock(pte - 1, ptl);
        return 0;
 }
@@ -1301,7 +1333,16 @@ static inline int remap_pud_range(struct mm_struct *mm, pgd_t *pgd,
        return 0;
 }
 
-/*  Note: this is only safe if the mm semaphore is held when called. */
+/**
+ * remap_pfn_range - remap kernel memory to userspace
+ * @vma: user vma to map to
+ * @addr: target user address to start at
+ * @pfn: physical address of kernel memory
+ * @size: size of map area
+ * @prot: page protection flags for this mapping
+ *
+ *  Note: this is only safe if the mm semaphore is held when called.
+ */
 int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,
                    unsigned long pfn, unsigned long size, pgprot_t prot)
 {
@@ -1311,9 +1352,6 @@ int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,
        struct mm_struct *mm = vma->vm_mm;
        int err;
 
-       if (addr != vma->vm_start || end != vma->vm_end)
-               return incomplete_pfn_remap(vma, addr, end, pfn, prot);
-
        /*
         * Physically remapped pages are special. Tell the
         * rest of the world about it:
@@ -1327,9 +1365,18 @@ int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,
         *   VM_PFNMAP tells the core MM that the base pages are just
         *      raw PFN mappings, and do not have a "struct page" associated
         *      with them.
+        *
+        * There's a horrible special case to handle copy-on-write
+        * behaviour that some programs depend on. We mark the "original"
+        * un-COW'ed pages by matching them up with "vma->vm_pgoff".
         */
+       if (is_cow_mapping(vma->vm_flags)) {
+               if (addr != vma->vm_start || end != vma->vm_end)
+                       return -EINVAL;
+               vma->vm_pgoff = pfn;
+       }
+
        vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP;
-       vma->vm_pgoff = pfn;
 
        BUG_ON(addr >= end);
        pfn -= addr >> PAGE_SHIFT;
@@ -1405,6 +1452,7 @@ static inline void cow_user_page(struct page *dst, struct page *src, unsigned lo
                if (__copy_from_user_inatomic(kaddr, uaddr, PAGE_SIZE))
                        memset(kaddr, 0, PAGE_SIZE);
                kunmap_atomic(kaddr, KM_USER0);
+               flush_dcache_page(dst);
                return;
                
        }
@@ -1433,28 +1481,73 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
                unsigned long address, pte_t *page_table, pmd_t *pmd,
                spinlock_t *ptl, pte_t orig_pte)
 {
-       struct page *old_page, *src_page, *new_page;
+       struct page *old_page, *new_page;
        pte_t entry;
-       int ret = VM_FAULT_MINOR;
+       int reuse = 0, ret = VM_FAULT_MINOR;
+       struct page *dirty_page = NULL;
 
        old_page = vm_normal_page(vma, address, orig_pte);
-       src_page = old_page;
        if (!old_page)
                goto gotten;
 
-       if (PageAnon(old_page) && !TestSetPageLocked(old_page)) {
-               int reuse = can_share_swap_page(old_page);
-               unlock_page(old_page);
-               if (reuse) {
-                       flush_cache_page(vma, address, pte_pfn(orig_pte));
-                       entry = pte_mkyoung(orig_pte);
-                       entry = maybe_mkwrite(pte_mkdirty(entry), vma);
-                       ptep_set_access_flags(vma, address, page_table, entry, 1);
-                       update_mmu_cache(vma, address, entry);
-                       lazy_mmu_prot_update(entry);
-                       ret |= VM_FAULT_WRITE;
-                       goto unlock;
+       /*
+        * Take out anonymous pages first, anonymous shared vmas are
+        * not dirty accountable.
+        */
+       if (PageAnon(old_page)) {
+               if (!TestSetPageLocked(old_page)) {
+                       reuse = can_share_swap_page(old_page);
+                       unlock_page(old_page);
+               }
+       } else if (unlikely((vma->vm_flags & (VM_WRITE|VM_SHARED)) ==
+                                       (VM_WRITE|VM_SHARED))) {
+               /*
+                * Only catch write-faults on shared writable pages,
+                * read-only shared pages can get COWed by
+                * get_user_pages(.write=1, .force=1).
+                */
+               if (vma->vm_ops && vma->vm_ops->page_mkwrite) {
+                       /*
+                        * Notify the address space that the page is about to
+                        * become writable so that it can prohibit this or wait
+                        * for the page to get into an appropriate state.
+                        *
+                        * We do this without the lock held, so that it can
+                        * sleep if it needs to.
+                        */
+                       page_cache_get(old_page);
+                       pte_unmap_unlock(page_table, ptl);
+
+                       if (vma->vm_ops->page_mkwrite(vma, old_page) < 0)
+                               goto unwritable_page;
+
+                       page_cache_release(old_page);
+
+                       /*
+                        * Since we dropped the lock we need to revalidate
+                        * the PTE as someone else may have changed it.  If
+                        * they did, we just return, as we can count on the
+                        * MMU to tell us if they didn't also make it writable.
+                        */
+                       page_table = pte_offset_map_lock(mm, pmd, address,
+                                                        &ptl);
+                       if (!pte_same(*page_table, orig_pte))
+                               goto unlock;
                }
+               dirty_page = old_page;
+               get_page(dirty_page);
+               reuse = 1;
+       }
+
+       if (reuse) {
+               flush_cache_page(vma, address, pte_pfn(orig_pte));
+               entry = pte_mkyoung(orig_pte);
+               entry = maybe_mkwrite(pte_mkdirty(entry), vma);
+               ptep_set_access_flags(vma, address, page_table, entry, 1);
+               update_mmu_cache(vma, address, entry);
+               lazy_mmu_prot_update(entry);
+               ret |= VM_FAULT_WRITE;
+               goto unlock;
        }
 
        /*
@@ -1466,7 +1559,7 @@ gotten:
 
        if (unlikely(anon_vma_prepare(vma)))
                goto oom;
-       if (src_page == ZERO_PAGE(address)) {
+       if (old_page == ZERO_PAGE(address)) {
                new_page = alloc_zeroed_user_highpage(vma, address);
                if (!new_page)
                        goto oom;
@@ -1474,7 +1567,7 @@ gotten:
                new_page = alloc_page_vma(GFP_HIGHUSER, vma, address);
                if (!new_page)
                        goto oom;
-               cow_user_page(new_page, src_page, address);
+               cow_user_page(new_page, old_page, address);
        }
 
        /*
@@ -1493,11 +1586,18 @@ gotten:
                flush_cache_page(vma, address, pte_pfn(orig_pte));
                entry = mk_pte(new_page, vma->vm_page_prot);
                entry = maybe_mkwrite(pte_mkdirty(entry), vma);
-               ptep_establish(vma, address, page_table, entry);
-               update_mmu_cache(vma, address, entry);
                lazy_mmu_prot_update(entry);
+               /*
+                * Clear the pte entry and flush it first, before updating the
+                * pte with the new entry. This will avoid a race condition
+                * seen in the presence of one thread doing SMC and another
+                * thread doing COW.
+                */
+               ptep_clear_flush(vma, address, page_table);
+               set_pte_at(mm, address, page_table, entry);
+               update_mmu_cache(vma, address, entry);
                lru_cache_add_active(new_page);
-               page_add_anon_rmap(new_page, vma, address);
+               page_add_new_anon_rmap(new_page, vma, address);
 
                /* Free the old page.. */
                new_page = old_page;
@@ -1509,11 +1609,19 @@ gotten:
                page_cache_release(old_page);
 unlock:
        pte_unmap_unlock(page_table, ptl);
+       if (dirty_page) {
+               set_page_dirty_balance(dirty_page);
+               put_page(dirty_page);
+       }
        return ret;
 oom:
        if (old_page)
                page_cache_release(old_page);
        return VM_FAULT_OOM;
+
+unwritable_page:
+       page_cache_release(old_page);
+       return VM_FAULT_SIGBUS;
 }
 
 /*
@@ -1724,9 +1832,10 @@ void unmap_mapping_range(struct address_space *mapping,
 }
 EXPORT_SYMBOL(unmap_mapping_range);
 
-/*
- * Handle all mappings that got truncated by a "truncate()"
- * system call.
+/**
+ * vmtruncate - unmap mappings "freed" by truncate() syscall
+ * @inode: inode of the file used
+ * @offset: file offset to start truncating
  *
  * NOTE! We have to be ready to update the memory sharing
  * between the file and the memory map for a potential last
@@ -1769,14 +1878,42 @@ out_big:
 out_busy:
        return -ETXTBSY;
 }
-
 EXPORT_SYMBOL(vmtruncate);
 
-/* 
+int vmtruncate_range(struct inode *inode, loff_t offset, loff_t end)
+{
+       struct address_space *mapping = inode->i_mapping;
+
+       /*
+        * If the underlying filesystem is not going to provide
+        * a way to truncate a range of blocks (punch a hole) -
+        * we should return failure right now.
+        */
+       if (!inode->i_op || !inode->i_op->truncate_range)
+               return -ENOSYS;
+
+       mutex_lock(&inode->i_mutex);
+       down_write(&inode->i_alloc_sem);
+       unmap_mapping_range(mapping, offset, (end - offset), 1);
+       truncate_inode_pages_range(mapping, offset, end);
+       inode->i_op->truncate_range(inode, offset, end);
+       up_write(&inode->i_alloc_sem);
+       mutex_unlock(&inode->i_mutex);
+
+       return 0;
+}
+EXPORT_UNUSED_SYMBOL(vmtruncate_range);  /*  June 2006  */
+
+/**
+ * swapin_readahead - swap in pages in hope we need them soon
+ * @entry: swap entry of this memory
+ * @addr: address to start
+ * @vma: user vma this addresses belong to
+ *
  * Primitive swap readahead code. We simply read an aligned block of
  * (1 << page_cluster) entries in the swap area. This method is chosen
  * because it doesn't cost us any seek time.  We also make sure to queue
- * the 'original' request together with the readahead ones...  
+ * the 'original' request together with the readahead ones...
  *
  * This has been extended to use the NUMA policies from the mm triggering
  * the readahead.
@@ -1847,6 +1984,11 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,
                goto out;
 
        entry = pte_to_swp_entry(orig_pte);
+       if (is_migration_entry(entry)) {
+               migration_entry_wait(mm, pmd, address);
+               goto out;
+       }
+       delayacct_set_flag(DELAYACCT_PF_SWAPIN);
        page = lookup_swap_cache(entry);
        if (!page) {
                swapin_readahead(entry, address, vma);
@@ -1859,15 +2001,17 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,
                        page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
                        if (likely(pte_same(*page_table, orig_pte)))
                                ret = VM_FAULT_OOM;
+                       delayacct_clear_flag(DELAYACCT_PF_SWAPIN);
                        goto unlock;
                }
 
                /* Had to read the page from swap area: Major fault */
                ret = VM_FAULT_MAJOR;
-               inc_page_state(pgmajfault);
+               count_vm_event(PGMAJFAULT);
                grab_swap_token();
        }
 
+       delayacct_clear_flag(DELAYACCT_PF_SWAPIN);
        mark_page_accessed(page);
        lock_page(page);
 
@@ -1953,8 +2097,7 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
                        goto release;
                inc_mm_counter(mm, anon_rss);
                lru_cache_add_active(page);
-               SetPageReferenced(page);
-               page_add_anon_rmap(page, vma, address);
+               page_add_new_anon_rmap(page, vma, address);
        } else {
                /* Map the ZERO_PAGE - vm_page_prot is readonly */
                page = ZERO_PAGE(address);
@@ -2008,8 +2151,11 @@ static int do_no_page(struct mm_struct *mm, struct vm_area_struct *vma,
        unsigned int sequence = 0;
        int ret = VM_FAULT_MINOR;
        int anon = 0;
+       struct page *dirty_page = NULL;
 
        pte_unmap(page_table);
+       BUG_ON(vma->vm_flags & VM_PFNMAP);
+
        if (vma->vm_file) {
                mapping = vma->vm_file->f_mapping;
                sequence = mapping->truncate_count;
@@ -2025,27 +2171,42 @@ retry:
         * after the next truncate_count read.
         */
 
-       /* no page was available -- either SIGBUS or OOM */
-       if (new_page == NOPAGE_SIGBUS)
+       /* no page was available -- either SIGBUS, OOM or REFAULT */
+       if (unlikely(new_page == NOPAGE_SIGBUS))
                return VM_FAULT_SIGBUS;
-       if (new_page == NOPAGE_OOM)
+       else if (unlikely(new_page == NOPAGE_OOM))
                return VM_FAULT_OOM;
+       else if (unlikely(new_page == NOPAGE_REFAULT))
+               return VM_FAULT_MINOR;
 
        /*
         * Should we do an early C-O-W break?
         */
-       if (write_access && !(vma->vm_flags & VM_SHARED)) {
-               struct page *page;
+       if (write_access) {
+               if (!(vma->vm_flags & VM_SHARED)) {
+                       struct page *page;
 
-               if (unlikely(anon_vma_prepare(vma)))
-                       goto oom;
-               page = alloc_page_vma(GFP_HIGHUSER, vma, address);
-               if (!page)
-                       goto oom;
-               cow_user_page(page, new_page, address);
-               page_cache_release(new_page);
-               new_page = page;
-               anon = 1;
+                       if (unlikely(anon_vma_prepare(vma)))
+                               goto oom;
+                       page = alloc_page_vma(GFP_HIGHUSER, vma, address);
+                       if (!page)
+                               goto oom;
+                       copy_user_highpage(page, new_page, address);
+                       page_cache_release(new_page);
+                       new_page = page;
+                       anon = 1;
+
+               } else {
+                       /* if the page will be shareable, see if the backing
+                        * address space wants to know that the page is about
+                        * to become writable */
+                       if (vma->vm_ops->page_mkwrite &&
+                           vma->vm_ops->page_mkwrite(vma, new_page) < 0
+                           ) {
+                               page_cache_release(new_page);
+                               return VM_FAULT_SIGBUS;
+                       }
+               }
        }
 
        page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
@@ -2083,10 +2244,14 @@ retry:
                if (anon) {
                        inc_mm_counter(mm, anon_rss);
                        lru_cache_add_active(new_page);
-                       page_add_anon_rmap(new_page, vma, address);
+                       page_add_new_anon_rmap(new_page, vma, address);
                } else {
                        inc_mm_counter(mm, file_rss);
                        page_add_file_rmap(new_page);
+                       if (write_access) {
+                               dirty_page = new_page;
+                               get_page(dirty_page);
+                       }
                }
        } else {
                /* One of our sibling threads was faster, back out. */
@@ -2099,6 +2264,10 @@ retry:
        lazy_mmu_prot_update(entry);
 unlock:
        pte_unmap_unlock(page_table, ptl);
+       if (dirty_page) {
+               set_page_dirty_balance(dirty_page);
+               put_page(dirty_page);
+       }
        return ret;
 oom:
        page_cache_release(new_page);
@@ -2106,6 +2275,54 @@ oom:
 }
 
 /*
+ * do_no_pfn() tries to create a new page mapping for a page without
+ * a struct_page backing it
+ *
+ * As this is called only for pages that do not currently exist, we
+ * do not need to flush old virtual caches or the TLB.
+ *
+ * We enter with non-exclusive mmap_sem (to exclude vma changes,
+ * but allow concurrent faults), and pte mapped but not yet locked.
+ * We return with mmap_sem still held, but pte unmapped and unlocked.
+ *
+ * It is expected that the ->nopfn handler always returns the same pfn
+ * for a given virtual mapping.
+ *
+ * Mark this `noinline' to prevent it from bloating the main pagefault code.
+ */
+static noinline int do_no_pfn(struct mm_struct *mm, struct vm_area_struct *vma,
+                    unsigned long address, pte_t *page_table, pmd_t *pmd,
+                    int write_access)
+{
+       spinlock_t *ptl;
+       pte_t entry;
+       unsigned long pfn;
+       int ret = VM_FAULT_MINOR;
+
+       pte_unmap(page_table);
+       BUG_ON(!(vma->vm_flags & VM_PFNMAP));
+       BUG_ON(is_cow_mapping(vma->vm_flags));
+
+       pfn = vma->vm_ops->nopfn(vma, address & PAGE_MASK);
+       if (pfn == NOPFN_OOM)
+               return VM_FAULT_OOM;
+       if (pfn == NOPFN_SIGBUS)
+               return VM_FAULT_SIGBUS;
+
+       page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
+
+       /* Only go through if we didn't race with anybody else... */
+       if (pte_none(*page_table)) {
+               entry = pfn_pte(pfn, vma->vm_page_prot);
+               if (write_access)
+                       entry = maybe_mkwrite(pte_mkdirty(entry), vma);
+               set_pte_at(mm, address, page_table, entry);
+       }
+       pte_unmap_unlock(page_table, ptl);
+       return ret;
+}
+
+/*
  * Fault of a previously existing named mapping. Repopulate the pte
  * from the encoded file_pte if possible. This enables swappable
  * nonlinear vmas.
@@ -2167,11 +2384,17 @@ static inline int handle_pte_fault(struct mm_struct *mm,
        old_entry = entry = *pte;
        if (!pte_present(entry)) {
                if (pte_none(entry)) {
-                       if (!vma->vm_ops || !vma->vm_ops->nopage)
-                               return do_anonymous_page(mm, vma, address,
-                                       pte, pmd, write_access);
-                       return do_no_page(mm, vma, address,
-                                       pte, pmd, write_access);
+                       if (vma->vm_ops) {
+                               if (vma->vm_ops->nopage)
+                                       return do_no_page(mm, vma, address,
+                                                         pte, pmd,
+                                                         write_access);
+                               if (unlikely(vma->vm_ops->nopfn))
+                                       return do_no_pfn(mm, vma, address, pte,
+                                                        pmd, write_access);
+                       }
+                       return do_anonymous_page(mm, vma, address,
+                                                pte, pmd, write_access);
                }
                if (pte_file(entry))
                        return do_file_page(mm, vma, address,
@@ -2223,7 +2446,7 @@ int __handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma,
 
        __set_current_state(TASK_RUNNING);
 
-       inc_page_state(pgfault);
+       count_vm_event(PGFAULT);
 
        if (unlikely(is_vm_hugetlb_page(vma)))
                return hugetlb_fault(mm, vma, address, write_access);
@@ -2242,6 +2465,8 @@ int __handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma,
        return handle_pte_fault(mm, vma, address, pte, pmd, write_access);
 }
 
+EXPORT_SYMBOL_GPL(__handle_mm_fault);
+
 #ifndef __PAGETABLE_PUD_FOLDED
 /*
  * Allocate page upper directory.
@@ -2312,10 +2537,8 @@ int make_pages_present(unsigned long addr, unsigned long end)
        if (!vma)
                return -1;
        write = (vma->vm_flags & VM_WRITE) != 0;
-       if (addr >= end)
-               BUG();
-       if (end > vma->vm_end)
-               BUG();
+       BUG_ON(addr >= end);
+       BUG_ON(end > vma->vm_end);
        len = (end+PAGE_SIZE-1)/PAGE_SIZE-addr/PAGE_SIZE;
        ret = get_user_pages(current, current->mm, addr,
                        len, write, 0, NULL, NULL);
@@ -2400,3 +2623,56 @@ int in_gate_area_no_task(unsigned long addr)
 }
 
 #endif /* __HAVE_ARCH_GATE_AREA */
+
+/*
+ * Access another process' address space.
+ * Source/target buffer must be kernel space,
+ * Do not walk the page table directly, use get_user_pages
+ */
+int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write)
+{
+       struct mm_struct *mm;
+       struct vm_area_struct *vma;
+       struct page *page;
+       void *old_buf = buf;
+
+       mm = get_task_mm(tsk);
+       if (!mm)
+               return 0;
+
+       down_read(&mm->mmap_sem);
+       /* ignore errors, just check how much was sucessfully transfered */
+       while (len) {
+               int bytes, ret, offset;
+               void *maddr;
+
+               ret = get_user_pages(tsk, mm, addr, 1,
+                               write, 1, &page, &vma);
+               if (ret <= 0)
+                       break;
+
+               bytes = len;
+               offset = addr & (PAGE_SIZE-1);
+               if (bytes > PAGE_SIZE-offset)
+                       bytes = PAGE_SIZE-offset;
+
+               maddr = kmap(page);
+               if (write) {
+                       copy_to_user_page(vma, page, addr,
+                                         maddr + offset, buf, bytes);
+                       set_page_dirty_lock(page);
+               } else {
+                       copy_from_user_page(vma, page, addr,
+                                           buf, maddr + offset, bytes);
+               }
+               kunmap(page);
+               page_cache_release(page);
+               len -= bytes;
+               buf += bytes;
+               addr += bytes;
+       }
+       up_read(&mm->mmap_sem);
+       mmput(mm);
+
+       return buf - old_buf;
+}