diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2005-12-11 22:46:02 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-12-11 22:46:02 -0500 |
commit | fb155c1619f056ae9765eed272cd6aba6e1a7399 (patch) | |
tree | 04a82b5fbf83bdb9dcf7fec9aeaaecf92532d88c | |
parent | e4f5c82a92c2a546a16af1614114eec19120e40a (diff) |
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 <torvalds@osdl.org>
-rw-r--r-- | mm/memory.c | 16 |
1 files changed, 12 insertions, 4 deletions
diff --git a/mm/memory.c b/mm/memory.c index aa8af0e20269..e65f8fc8ea67 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_ | |||
377 | unsigned long off = (addr - vma->vm_start) >> PAGE_SHIFT; | 377 | unsigned long off = (addr - vma->vm_start) >> PAGE_SHIFT; |
378 | if (pfn == vma->vm_pgoff + off) | 378 | if (pfn == vma->vm_pgoff + off) |
379 | return NULL; | 379 | return NULL; |
380 | if (vma->vm_flags & VM_SHARED) | ||
381 | return NULL; | ||
380 | } | 382 | } |
381 | 383 | ||
382 | /* | 384 | /* |
@@ -1343,9 +1345,6 @@ int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr, | |||
1343 | struct mm_struct *mm = vma->vm_mm; | 1345 | struct mm_struct *mm = vma->vm_mm; |
1344 | int err; | 1346 | int err; |
1345 | 1347 | ||
1346 | if (addr != vma->vm_start || end != vma->vm_end) | ||
1347 | return incomplete_pfn_remap(vma, addr, end, pfn, prot); | ||
1348 | |||
1349 | /* | 1348 | /* |
1350 | * Physically remapped pages are special. Tell the | 1349 | * Physically remapped pages are special. Tell the |
1351 | * rest of the world about it: | 1350 | * rest of the world about it: |
@@ -1359,9 +1358,18 @@ int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr, | |||
1359 | * VM_PFNMAP tells the core MM that the base pages are just | 1358 | * VM_PFNMAP tells the core MM that the base pages are just |
1360 | * raw PFN mappings, and do not have a "struct page" associated | 1359 | * raw PFN mappings, and do not have a "struct page" associated |
1361 | * with them. | 1360 | * with them. |
1361 | * | ||
1362 | * There's a horrible special case to handle copy-on-write | ||
1363 | * behaviour that some programs depend on. We mark the "original" | ||
1364 | * un-COW'ed pages by matching them up with "vma->vm_pgoff". | ||
1362 | */ | 1365 | */ |
1366 | if (!(vma->vm_flags & VM_SHARED)) { | ||
1367 | if (addr != vma->vm_start || end != vma->vm_end) | ||
1368 | return incomplete_pfn_remap(vma, addr, end, pfn, prot); | ||
1369 | vma->vm_pgoff = pfn; | ||
1370 | } | ||
1371 | |||
1363 | vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP; | 1372 | vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP; |
1364 | vma->vm_pgoff = pfn; | ||
1365 | 1373 | ||
1366 | BUG_ON(addr >= end); | 1374 | BUG_ON(addr >= end); |
1367 | pfn -= addr >> PAGE_SHIFT; | 1375 | pfn -= addr >> PAGE_SHIFT; |