Commit 3ee6dafc677a68e461a7ddafc94a580ebab80735

Authored by Miklos Szeredi
Committed by Linus Torvalds
1 parent bb2d5ce164

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 <mszeredi@suse.cz>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: William Lee Irwin III <wli@holomorphy.com>
Cc: Nick Piggin <nickpiggin@yahoo.com.au>
Cc: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 1 changed file with 19 additions and 0 deletions Side-by-side Diff

... ... @@ -181,6 +181,25 @@
181 181 goto retry;
182 182 }
183 183 mapping = vma->vm_file->f_mapping;
  184 + /*
  185 + * page_mkclean doesn't work on nonlinear vmas, so if
  186 + * dirty pages need to be accounted, emulate with linear
  187 + * vmas.
  188 + */
  189 + if (mapping_cap_account_dirty(mapping)) {
  190 + unsigned long addr;
  191 +
  192 + flags &= MAP_NONBLOCK;
  193 + addr = mmap_region(vma->vm_file, start, size,
  194 + flags, vma->vm_flags, pgoff, 1);
  195 + if (IS_ERR_VALUE(addr)) {
  196 + err = addr;
  197 + } else {
  198 + BUG_ON(addr != start);
  199 + err = 0;
  200 + }
  201 + goto out;
  202 + }
184 203 spin_lock(&mapping->i_mmap_lock);
185 204 flush_dcache_mmap_lock(mapping);
186 205 vma->vm_flags |= VM_NONLINEAR;