aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2005-12-11 23:38:17 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-12-11 23:38:17 -0500
commit67121172f9753f38689651b613a4850e0e75876f (patch)
treecfb6ea8365c44a43ee254385c7d246f0418cedd0
parent913f2d792ff584bf9ebf5968472b3e4ffe0fd9c8 (diff)
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>
-rw-r--r--mm/memory.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/mm/memory.c b/mm/memory.c
index 430a72ed08d5..47c533eaa072 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -349,6 +349,11 @@ void print_bad_pte(struct vm_area_struct *vma, pte_t pte, unsigned long vaddr)
349 dump_stack(); 349 dump_stack();
350} 350}
351 351
352static inline int is_cow_mapping(unsigned int flags)
353{
354 return (flags & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE;
355}
356
352/* 357/*
353 * This function gets the "struct page" associated with a pte. 358 * This function gets the "struct page" associated with a pte.
354 * 359 *
@@ -377,7 +382,7 @@ struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr, pte_
377 unsigned long off = (addr - vma->vm_start) >> PAGE_SHIFT; 382 unsigned long off = (addr - vma->vm_start) >> PAGE_SHIFT;
378 if (pfn == vma->vm_pgoff + off) 383 if (pfn == vma->vm_pgoff + off)
379 return NULL; 384 return NULL;
380 if (vma->vm_flags & VM_SHARED) 385 if (!is_cow_mapping(vma->vm_flags))
381 return NULL; 386 return NULL;
382 } 387 }
383 388
@@ -439,7 +444,7 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
439 * If it's a COW mapping, write protect it both 444 * If it's a COW mapping, write protect it both
440 * in the parent and the child 445 * in the parent and the child
441 */ 446 */
442 if ((vm_flags & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE) { 447 if (is_cow_mapping(vm_flags)) {
443 ptep_set_wrprotect(src_mm, addr, src_pte); 448 ptep_set_wrprotect(src_mm, addr, src_pte);
444 pte = *src_pte; 449 pte = *src_pte;
445 } 450 }
@@ -1319,7 +1324,7 @@ int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,
1319 * behaviour that some programs depend on. We mark the "original" 1324 * behaviour that some programs depend on. We mark the "original"
1320 * un-COW'ed pages by matching them up with "vma->vm_pgoff". 1325 * un-COW'ed pages by matching them up with "vma->vm_pgoff".
1321 */ 1326 */
1322 if (!(vma->vm_flags & VM_SHARED)) { 1327 if (is_cow_mapping(vma->vm_flags)) {
1323 if (addr != vma->vm_start || end != vma->vm_end) 1328 if (addr != vma->vm_start || end != vma->vm_end)
1324 return -EINVAL; 1329 return -EINVAL;
1325 vma->vm_pgoff = pfn; 1330 vma->vm_pgoff = pfn;