From 3ee6dafc677a68e461a7ddafc94a580ebab80735 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Thu, 19 Jul 2007 01:47:24 -0700 Subject: only allow nonlinear vmas for ram backed filesystems page_mkclean() doesn't re-protect ptes for non-linear mappings, so a later re-dirty through such a mapping will not generate a fault, PG_dirty will not reflect the dirty state and the dirty count will be skewed. This implies that msync() is also currently broken for nonlinear mappings. The easiest solution is to emulate remap_file_pages on non-linear mappings with simple mmap() for non ram-backed filesystems. Applications continue to work (albeit slower), as long as the number of remappings remain below the maximum vma count. However all currently known real uses of non-linear mappings are for ram backed filesystems, which this patch doesn't affect. Signed-off-by: Miklos Szeredi Acked-by: Peter Zijlstra Cc: William Lee Irwin III Cc: Nick Piggin Cc: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/fremap.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'mm/fremap.c') diff --git a/mm/fremap.c b/mm/fremap.c index 5f50d736a03..c395b1abf08 100644 --- a/mm/fremap.c +++ b/mm/fremap.c @@ -181,6 +181,25 @@ asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size, goto retry; } mapping = vma->vm_file->f_mapping; + /* + * page_mkclean doesn't work on nonlinear vmas, so if + * dirty pages need to be accounted, emulate with linear + * vmas. + */ + if (mapping_cap_account_dirty(mapping)) { + unsigned long addr; + + flags &= MAP_NONBLOCK; + addr = mmap_region(vma->vm_file, start, size, + flags, vma->vm_flags, pgoff, 1); + if (IS_ERR_VALUE(addr)) { + err = addr; + } else { + BUG_ON(addr != start); + err = 0; + } + goto out; + } spin_lock(&mapping->i_mmap_lock); flush_dcache_mmap_lock(mapping); vma->vm_flags |= VM_NONLINEAR; -- cgit v1.2.3