From: Linus Torvalds Date: Mon, 12 Dec 2005 03:46:02 +0000 (-0800) Subject: Allow arbitrary shared PFNMAP's X-Git-Tag: v2.6.15-rc6~148 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fb155c1619f056ae9765eed272cd6aba6e1a7399;p=linux-2.6 Allow arbitrary shared PFNMAP's A shared mapping doesn't cause COW-pages, so we don't need to worry about the whole vm_pgoff logic to decide if a PFN-remapped page has gone through COW or not. This makes it possible to entirely avoid the special "partial remapping" logic for the common case. Signed-off-by: Linus Torvalds --- diff --git a/mm/memory.c b/mm/memory.c index aa8af0e202..e65f8fc8ea 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -377,6 +377,8 @@ struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr, pte_ unsigned long off = (addr - vma->vm_start) >> PAGE_SHIFT; if (pfn == vma->vm_pgoff + off) return NULL; + if (vma->vm_flags & VM_SHARED) + return NULL; } /* @@ -1343,9 +1345,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: @@ -1359,9 +1358,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 (!(vma->vm_flags & VM_SHARED)) { + if (addr != vma->vm_start || end != vma->vm_end) + return incomplete_pfn_remap(vma, addr, end, pfn, prot); + 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;