]> err.no Git - linux-2.6/blobdiff - mm/mremap.c
Merge branch 'drm-fixes' of master.kernel.org:/pub/scm/linux/kernel/git/airlied/drm-2.6
[linux-2.6] / mm / mremap.c
index 0dd7ace94e519d13f96d601bc1ecc543bb8ac595..a32fed454bd7c60e15da0c720b1631b55a3f8835 100644 (file)
@@ -141,6 +141,10 @@ move_one_page(struct vm_area_struct *vma, unsigned long old_addr,
                        if (dst) {
                                pte_t pte;
                                pte = ptep_clear_flush(vma, old_addr, src);
+                               /* ZERO_PAGE can be dependant on virtual addr */
+                               if (pfn_valid(pte_pfn(pte)) &&
+                                       pte_page(pte) == ZERO_PAGE(old_addr))
+                                       pte = pte_wrprotect(mk_pte(ZERO_PAGE(new_addr), new_vma->vm_page_prot));
                                set_pte_at(mm, new_addr, dst, pte);
                        } else
                                error = -ENOMEM;
@@ -224,6 +228,13 @@ static unsigned long move_vma(struct vm_area_struct *vma,
                        split = 1;
        }
 
+       /*
+        * if we failed to move page tables we still do total_vm increment
+        * since do_munmap() will decrement it by old_len == new_len
+        */
+       mm->total_vm += new_len >> PAGE_SHIFT;
+       __vm_stat_account(mm, vma->vm_flags, vma->vm_file, new_len>>PAGE_SHIFT);
+
        if (do_munmap(mm, old_addr, old_len) < 0) {
                /* OOM: unable to split vma, just get accounts right */
                vm_unacct_memory(excess >> PAGE_SHIFT);
@@ -237,8 +248,6 @@ static unsigned long move_vma(struct vm_area_struct *vma,
                        vma->vm_next->vm_flags |= VM_ACCOUNT;
        }
 
-       mm->total_vm += new_len >> PAGE_SHIFT;
-       __vm_stat_account(mm, vma->vm_flags, vma->vm_file, new_len>>PAGE_SHIFT);
        if (vm_flags & VM_LOCKED) {
                mm->locked_vm += new_len >> PAGE_SHIFT;
                if (new_len > old_len)