diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2005-12-11 23:38:17 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-12-11 23:38:17 -0500 |
commit | 67121172f9753f38689651b613a4850e0e75876f (patch) | |
tree | cfb6ea8365c44a43ee254385c7d246f0418cedd0 | |
parent | 913f2d792ff584bf9ebf5968472b3e4ffe0fd9c8 (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.c | 11 |
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 | ||
352 | static 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; |