Allow arbitrary read-only shared pfn-remapping too

The VM layer (for historical reasons) turns a read-only shared mmap into
a private-like mapping with the VM_MAYWRITE bit clear.  Thus checking
just VM_SHARED isn't actually sufficient.

So use a trivial helper function for the cases where we wanted to inquire
if a mapping was COW-like or not.

Moo!

Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Linus Torvalds 2005-12-11 20:38:17 -08:00
parent 913f2d792f
commit 67121172f9

View file

@ -349,6 +349,11 @@ void print_bad_pte(struct vm_area_struct *vma, pte_t pte, unsigned long vaddr)
dump_stack(); 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. * This function gets the "struct page" associated with a pte.
* *
@ -377,7 +382,7 @@ struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr, pte_
unsigned long off = (addr - vma->vm_start) >> PAGE_SHIFT; unsigned long off = (addr - vma->vm_start) >> PAGE_SHIFT;
if (pfn == vma->vm_pgoff + off) if (pfn == vma->vm_pgoff + off)
return NULL; return NULL;
if (vma->vm_flags & VM_SHARED) if (!is_cow_mapping(vma->vm_flags))
return NULL; return NULL;
} }
@ -439,7 +444,7 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
* If it's a COW mapping, write protect it both * If it's a COW mapping, write protect it both
* in the parent and the child * 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); ptep_set_wrprotect(src_mm, addr, src_pte);
pte = *src_pte; pte = *src_pte;
} }
@ -1319,7 +1324,7 @@ int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,
* behaviour that some programs depend on. We mark the "original" * behaviour that some programs depend on. We mark the "original"
* un-COW'ed pages by matching them up with "vma->vm_pgoff". * un-COW'ed pages by matching them up with "vma->vm_pgoff".
*/ */
if (!(vma->vm_flags & VM_SHARED)) { if (is_cow_mapping(vma->vm_flags)) {
if (addr != vma->vm_start || end != vma->vm_end) if (addr != vma->vm_start || end != vma->vm_end)
return -EINVAL; return -EINVAL;
vma->vm_pgoff = pfn; vma->vm_pgoff = pfn;