]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - mm/memory.c
mm, x86, pat: rework linear pfn-mmap tracking
[karo-tx-linux.git] / mm / memory.c
index 57361708d1a57d7bc11c8f34d269a35c50317dbb..655e1429388a364014899b4a84ea59e97500a5ea 100644 (file)
@@ -1055,12 +1055,12 @@ int copy_page_range(struct mm_struct *dst_mm, struct mm_struct *src_mm,
        if (is_vm_hugetlb_page(vma))
                return copy_hugetlb_page_range(dst_mm, src_mm, vma);
 
-       if (unlikely(is_pfn_mapping(vma))) {
+       if (unlikely(vma->vm_flags & VM_PFNMAP)) {
                /*
                 * We do not free on error cases below as remove_vma
                 * gets called on error from higher level routine
                 */
-               ret = track_pfn_vma_copy(vma);
+               ret = track_pfn_copy(vma);
                if (ret)
                        return ret;
        }
@@ -1327,8 +1327,8 @@ static void unmap_single_vma(struct mmu_gather *tlb,
        if (vma->vm_file)
                uprobe_munmap(vma, start, end);
 
-       if (unlikely(is_pfn_mapping(vma)))
-               untrack_pfn_vma(vma, 0, 0);
+       if (unlikely(vma->vm_flags & VM_PFNMAP))
+               untrack_pfn(vma, 0, 0);
 
        if (start != end) {
                if (unlikely(is_vm_hugetlb_page(vma))) {
@@ -2162,14 +2162,11 @@ int vm_insert_pfn(struct vm_area_struct *vma, unsigned long addr,
 
        if (addr < vma->vm_start || addr >= vma->vm_end)
                return -EFAULT;
-       if (track_pfn_vma_new(vma, &pgprot, pfn, PAGE_SIZE))
+       if (track_pfn_insert(vma, &pgprot, pfn))
                return -EINVAL;
 
        ret = insert_pfn(vma, addr, pfn, pgprot);
 
-       if (ret)
-               untrack_pfn_vma(vma, pfn, PAGE_SIZE);
-
        return ret;
 }
 EXPORT_SYMBOL(vm_insert_pfn);
@@ -2302,26 +2299,20 @@ int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,
         * 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".
+        * See vm_normal_page() for details.
         */
-       if (addr == vma->vm_start && end == vma->vm_end) {
+       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_PFN_AT_MMAP;
-       } else if (is_cow_mapping(vma->vm_flags))
+       }
+
+       err = track_pfn_remap(vma, &prot, pfn, addr, PAGE_ALIGN(size));
+       if (err)
                return -EINVAL;
 
        vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP;
 
-       err = track_pfn_vma_new(vma, &prot, pfn, PAGE_ALIGN(size));
-       if (err) {
-               /*
-                * To indicate that track_pfn related cleanup is not
-                * needed from higher level routine calling unmap_vmas
-                */
-               vma->vm_flags &= ~(VM_IO | VM_RESERVED | VM_PFNMAP);
-               vma->vm_flags &= ~VM_PFN_AT_MMAP;
-               return -EINVAL;
-       }
-
        BUG_ON(addr >= end);
        pfn -= addr >> PAGE_SHIFT;
        pgd = pgd_offset(mm, addr);
@@ -2335,7 +2326,7 @@ int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,
        } while (pgd++, addr = next, addr != end);
 
        if (err)
-               untrack_pfn_vma(vma, pfn, PAGE_ALIGN(size));
+               untrack_pfn(vma, pfn, PAGE_ALIGN(size));
 
        return err;
 }