aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2005-12-16 13:21:23 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-12-16 13:21:23 -0500
commit4d7672b46244abffea1953e55688c0ea143dd617 (patch)
tree9f3bdf438bcb0d5f6e723665ced23308fffb8368
parent281ab031a8c9e5b593142eb4ec59a87faae8676a (diff)
Make sure we copy pages inserted with "vm_insert_page()" on fork
The logic that decides that a fork() might be able to avoid copying a VM area when it can be re-created by page faults didn't know about the new vm_insert_page() case. Also make some things a bit more anal wrt VM_PFNMAP. Pointed out by Hugh Dickins <hugh@veritas.com> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--include/linux/mm.h1
-rw-r--r--mm/memory.c3
-rw-r--r--mm/mmap.c2
-rw-r--r--mm/mremap.c2
4 files changed, 5 insertions, 3 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h
index e5677f456742..a06a84d347fb 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -163,6 +163,7 @@ extern unsigned int kobjsize(const void *objp);
163#define VM_HUGETLB 0x00400000 /* Huge TLB Page VM */ 163#define VM_HUGETLB 0x00400000 /* Huge TLB Page VM */
164#define VM_NONLINEAR 0x00800000 /* Is non-linear (remap_file_pages) */ 164#define VM_NONLINEAR 0x00800000 /* Is non-linear (remap_file_pages) */
165#define VM_MAPPED_COPY 0x01000000 /* T if mapped copy of data (nommu mmap) */ 165#define VM_MAPPED_COPY 0x01000000 /* T if mapped copy of data (nommu mmap) */
166#define VM_INSERTPAGE 0x02000000 /* The vma has had "vm_insert_page()" done on it */
166 167
167#ifndef VM_STACK_DEFAULT_FLAGS /* arch can override this */ 168#ifndef VM_STACK_DEFAULT_FLAGS /* arch can override this */
168#define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS 169#define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS
diff --git a/mm/memory.c b/mm/memory.c
index d22f78c8a381..d8dde07a3656 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -574,7 +574,7 @@ int copy_page_range(struct mm_struct *dst_mm, struct mm_struct *src_mm,
574 * readonly mappings. The tradeoff is that copy_page_range is more 574 * readonly mappings. The tradeoff is that copy_page_range is more
575 * efficient than faulting. 575 * efficient than faulting.
576 */ 576 */
577 if (!(vma->vm_flags & (VM_HUGETLB|VM_NONLINEAR|VM_PFNMAP))) { 577 if (!(vma->vm_flags & (VM_HUGETLB|VM_NONLINEAR|VM_PFNMAP|VM_INSERTPAGE))) {
578 if (!vma->anon_vma) 578 if (!vma->anon_vma)
579 return 0; 579 return 0;
580 } 580 }
@@ -1228,6 +1228,7 @@ int vm_insert_page(struct vm_area_struct *vma, unsigned long addr, struct page *
1228 return -EFAULT; 1228 return -EFAULT;
1229 if (!page_count(page)) 1229 if (!page_count(page))
1230 return -EINVAL; 1230 return -EINVAL;
1231 vma->vm_flags |= VM_INSERTPAGE;
1231 return insert_page(vma->vm_mm, addr, page, vma->vm_page_prot); 1232 return insert_page(vma->vm_mm, addr, page, vma->vm_page_prot);
1232} 1233}
1233EXPORT_SYMBOL(vm_insert_page); 1234EXPORT_SYMBOL(vm_insert_page);
diff --git a/mm/mmap.c b/mm/mmap.c
index 11ca5927d5ff..64ba4dbcb7de 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -611,7 +611,7 @@ again: remove_next = 1 + (end > next->vm_end);
611 * If the vma has a ->close operation then the driver probably needs to release 611 * If the vma has a ->close operation then the driver probably needs to release
612 * per-vma resources, so we don't attempt to merge those. 612 * per-vma resources, so we don't attempt to merge those.
613 */ 613 */
614#define VM_SPECIAL (VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED) 614#define VM_SPECIAL (VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED | VM_PFNMAP)
615 615
616static inline int is_mergeable_vma(struct vm_area_struct *vma, 616static inline int is_mergeable_vma(struct vm_area_struct *vma,
617 struct file *file, unsigned long vm_flags) 617 struct file *file, unsigned long vm_flags)
diff --git a/mm/mremap.c b/mm/mremap.c
index b535438c363c..ddaeee9a0b69 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -323,7 +323,7 @@ unsigned long do_mremap(unsigned long addr,
323 /* We can't remap across vm area boundaries */ 323 /* We can't remap across vm area boundaries */
324 if (old_len > vma->vm_end - addr) 324 if (old_len > vma->vm_end - addr)
325 goto out; 325 goto out;
326 if (vma->vm_flags & VM_DONTEXPAND) { 326 if (vma->vm_flags & (VM_DONTEXPAND | VM_PFNMAP)) {
327 if (new_len > old_len) 327 if (new_len > old_len)
328 goto out; 328 goto out;
329 } 329 }